00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "util/macro.h"
00021 #include "file/file.h"
00022 #include "util/bits.h"
00023 #include "mpls_parse.h"
00024
00025 #include <stdlib.h>
00026 #include <string.h>
00027
00028 #define MPLS_SIG1 ('M' << 24 | 'P' << 16 | 'L' << 8 | 'S')
00029 #define MPLS_SIG2A ('0' << 24 | '2' << 16 | '0' << 8 | '0')
00030 #define MPLS_SIG2B ('0' << 24 | '1' << 16 | '0' << 8 | '0')
00031
00032 static int mpls_verbose = 0;
00033
00034 static void
00035 _human_readable_sig(char *sig, uint32_t s1, uint32_t s2)
00036 {
00037 sig[0] = (s1 >> 24) & 0xFF;
00038 sig[1] = (s1 >> 16) & 0xFF;
00039 sig[2] = (s1 >> 8) & 0xFF;
00040 sig[3] = (s1 ) & 0xFF;
00041 sig[4] = (s2 >> 24) & 0xFF;
00042 sig[5] = (s2 >> 16) & 0xFF;
00043 sig[6] = (s2 >> 8) & 0xFF;
00044 sig[7] = (s2 ) & 0xFF;
00045 sig[8] = 0;
00046 }
00047
00048 int
00049 mpls_parse_uo(uint8_t *buf, BD_UO_MASK *uo)
00050 {
00051 BITBUFFER bb;
00052 bb_init(&bb, buf, 8);
00053
00054 uo->menu_call = bb_read(&bb, 1);
00055 uo->title_search = bb_read(&bb, 1);
00056 uo->chapter_search = bb_read(&bb, 1);
00057 uo->time_search = bb_read(&bb, 1);
00058 uo->skip_to_next_point = bb_read(&bb, 1);
00059 uo->skip_to_prev_point = bb_read(&bb, 1);
00060 uo->play_firstplay = bb_read(&bb, 1);
00061 uo->stop = bb_read(&bb, 1);
00062 uo->pause_on = bb_read(&bb, 1);
00063 uo->pause_off = bb_read(&bb, 1);
00064 uo->still = bb_read(&bb, 1);
00065 uo->forward = bb_read(&bb, 1);
00066 uo->backward = bb_read(&bb, 1);
00067 uo->resume = bb_read(&bb, 1);
00068 uo->move_up = bb_read(&bb, 1);
00069 uo->move_down = bb_read(&bb, 1);
00070 uo->move_left = bb_read(&bb, 1);
00071 uo->move_right = bb_read(&bb, 1);
00072 uo->select = bb_read(&bb, 1);
00073 uo->activate = bb_read(&bb, 1);
00074 uo->select_and_activate = bb_read(&bb, 1);
00075 uo->primary_audio_change = bb_read(&bb, 1);
00076 bb_skip(&bb, 1);
00077 uo->angle_change = bb_read(&bb, 1);
00078 uo->popup_on = bb_read(&bb, 1);
00079 uo->popup_off = bb_read(&bb, 1);
00080 uo->pg_enable_disable = bb_read(&bb, 1);
00081 uo->pg_change = bb_read(&bb, 1);
00082 uo->secondary_video_enable_disable = bb_read(&bb, 1);
00083 uo->secondary_video_change = bb_read(&bb, 1);
00084 uo->secondary_audio_enable_disable = bb_read(&bb, 1);
00085 uo->secondary_audio_change = bb_read(&bb, 1);
00086 bb_skip(&bb, 1);
00087 uo->pip_pg_change = bb_read(&bb, 1);
00088 bb_skip(&bb, 30);
00089 return 1;
00090 }
00091
00092 static int
00093 _parse_uo(BITSTREAM *bits, BD_UO_MASK *uo)
00094 {
00095 uint8_t buf[8];
00096 bs_read_bytes(bits, buf, 8);
00097 return mpls_parse_uo(buf, uo);
00098 }
00099
00100 static int
00101 _parse_appinfo(BITSTREAM *bits, MPLS_AI *ai)
00102 {
00103 int len;
00104 int pos;
00105
00106 if (!bs_is_align(bits, 0x07)) {
00107 fprintf(stderr, "_parse_appinfo: alignment error\n");
00108 }
00109 pos = bs_pos(bits) >> 3;
00110 len = bs_read(bits, 32);
00111
00112
00113 bs_skip(bits, 8);
00114 ai->playback_type = bs_read(bits, 8);
00115 if (ai->playback_type == 2 || ai->playback_type == 3) {
00116 ai->playback_count = bs_read(bits, 16);
00117 } else {
00118
00119 bs_skip(bits, 16);
00120 }
00121 _parse_uo(bits, &ai->uo_mask);
00122 ai->random_access_flag = bs_read(bits, 1);
00123 ai->audio_mix_flag = bs_read(bits, 1);
00124 ai->lossless_bypass_flag = bs_read(bits, 1);
00125
00126 bs_skip(bits, 13);
00127 bs_seek_byte(bits, pos + len);
00128 return 1;
00129 }
00130
00131 static int
00132 _parse_header(BITSTREAM *bits, MPLS_PL *pl)
00133 {
00134 pl->type_indicator = bs_read(bits, 32);
00135 pl->type_indicator2 = bs_read(bits, 32);
00136 if (pl->type_indicator != MPLS_SIG1 ||
00137 (pl->type_indicator2 != MPLS_SIG2A &&
00138 pl->type_indicator2 != MPLS_SIG2B)) {
00139
00140 char sig[9];
00141 char expect[9];
00142
00143 _human_readable_sig(sig, pl->type_indicator, pl->type_indicator2);
00144 _human_readable_sig(expect, MPLS_SIG1, MPLS_SIG2A);
00145 fprintf(stderr, "failed signature match, expected (%s) got (%s)\n",
00146 expect, sig);
00147 return 0;
00148 }
00149 pl->list_pos = bs_read(bits, 32);
00150 pl->mark_pos = bs_read(bits, 32);
00151 pl->ext_pos = bs_read(bits, 32);
00152
00153
00154 bs_skip(bits, 160);
00155
00156 _parse_appinfo(bits, &pl->app_info);
00157 return 1;
00158 }
00159
00160 static int
00161 _parse_stream(BITSTREAM *bits, MPLS_STREAM *s)
00162 {
00163 int len;
00164 int pos;
00165
00166 if (!bs_is_align(bits, 0x07)) {
00167 fprintf(stderr, "_parse_stream: Stream alignment error\n");
00168 }
00169 len = bs_read(bits, 8);
00170 pos = bs_pos(bits) >> 3;
00171
00172 s->stream_type = bs_read(bits, 8);
00173 switch (s->stream_type) {
00174 case 1:
00175 s->pid = bs_read(bits, 16);
00176 break;
00177
00178 case 2:
00179 case 4:
00180 s->subpath_id = bs_read(bits, 8);
00181 s->subclip_id = bs_read(bits, 8);
00182 s->pid = bs_read(bits, 16);
00183 break;
00184
00185 case 3:
00186 s->subpath_id = bs_read(bits, 8);
00187 s->pid = bs_read(bits, 16);
00188 break;
00189
00190 default:
00191 fprintf(stderr, "unrecognized stream type %02x\n", s->stream_type);
00192 break;
00193 };
00194
00195 bs_seek_byte(bits, pos + len);
00196
00197 len = bs_read(bits, 8);
00198 pos = bs_pos(bits) >> 3;
00199
00200 s->lang[0] = '\0';
00201 s->coding_type = bs_read(bits, 8);
00202 switch (s->coding_type) {
00203 case 0x01:
00204 case 0x02:
00205 case 0xea:
00206 case 0x1b:
00207 s->format = bs_read(bits, 4);
00208 s->rate = bs_read(bits, 4);
00209 break;
00210
00211 case 0x03:
00212 case 0x04:
00213 case 0x80:
00214 case 0x81:
00215 case 0x82:
00216 case 0x83:
00217 case 0x84:
00218 case 0x85:
00219 case 0x86:
00220 case 0xa1:
00221 case 0xa2:
00222 s->format = bs_read(bits, 4);
00223 s->rate = bs_read(bits, 4);
00224 bs_read_bytes(bits, s->lang, 3);
00225 break;
00226
00227 case 0x90:
00228 case 0x91:
00229 bs_read_bytes(bits, s->lang, 3);
00230 break;
00231
00232 case 0x92:
00233 s->char_code = bs_read(bits, 8);
00234 bs_read_bytes(bits, s->lang, 3);
00235 break;
00236
00237 default:
00238 fprintf(stderr, "unrecognized coding type %02x\n", s->coding_type);
00239 break;
00240 };
00241 s->lang[3] = '\0';
00242
00243 bs_seek_byte(bits, pos + len);
00244 return 1;
00245 }
00246
00247 static int
00248 _parse_stn(BITSTREAM *bits, MPLS_STN *stn)
00249 {
00250 int len;
00251 int pos;
00252 MPLS_STREAM *ss;
00253 int ii,jj;
00254
00255 if (!bs_is_align(bits, 0x07)) {
00256 fprintf(stderr, "_parse_stream: Stream alignment error\n");
00257 }
00258
00259 len = bs_read(bits, 16);
00260 pos = bs_pos(bits) >> 3;
00261
00262
00263 bs_skip(bits, 16);
00264
00265 stn->num_video = bs_read(bits, 8);
00266 stn->num_audio = bs_read(bits, 8);
00267 stn->num_pg = bs_read(bits, 8);
00268 stn->num_ig = bs_read(bits, 8);
00269 stn->num_secondary_audio = bs_read(bits, 8);
00270 stn->num_secondary_video = bs_read(bits, 8);
00271 stn->num_pip_pg = bs_read(bits, 8);
00272
00273
00274 bs_skip(bits, 5 * 8);
00275
00276
00277 ss = NULL;
00278 if (stn->num_video) {
00279 ss = calloc(stn->num_video, sizeof(MPLS_STREAM));
00280 for (ii = 0; ii < stn->num_video; ii++) {
00281 if (!_parse_stream(bits, &ss[ii])) {
00282 X_FREE(ss);
00283 fprintf(stderr, "error parsing video entry\n");
00284 return 0;
00285 }
00286 }
00287 }
00288 stn->video = ss;
00289
00290
00291 ss = NULL;
00292 if (stn->num_audio) {
00293 ss = calloc(stn->num_audio, sizeof(MPLS_STREAM));
00294 for (ii = 0; ii < stn->num_audio; ii++) {
00295
00296 if (!_parse_stream(bits, &ss[ii])) {
00297 X_FREE(ss);
00298 fprintf(stderr, "error parsing audio entry\n");
00299 return 0;
00300 }
00301 }
00302 }
00303 stn->audio = ss;
00304
00305
00306 ss = NULL;
00307 if (stn->num_pg || stn->num_pip_pg) {
00308 ss = calloc(stn->num_pg + stn->num_pip_pg, sizeof(MPLS_STREAM));
00309 for (ii = 0; ii < (stn->num_pg + stn->num_pip_pg); ii++) {
00310 if (!_parse_stream(bits, &ss[ii])) {
00311 X_FREE(ss);
00312 fprintf(stderr, "error parsing pg/pip-pg entry\n");
00313 return 0;
00314 }
00315 }
00316 }
00317 stn->pg = ss;
00318
00319
00320 ss = NULL;
00321 if (stn->num_ig) {
00322 ss = calloc(stn->num_ig, sizeof(MPLS_STREAM));
00323 for (ii = 0; ii < stn->num_ig; ii++) {
00324 if (!_parse_stream(bits, &ss[ii])) {
00325 X_FREE(ss);
00326 fprintf(stderr, "error parsing ig entry\n");
00327 return 0;
00328 }
00329 }
00330 }
00331 stn->ig = ss;
00332
00333
00334 ss = NULL;
00335 if (stn->num_secondary_audio) {
00336 ss = calloc(stn->num_secondary_audio, sizeof(MPLS_STREAM));
00337 for (ii = 0; ii < stn->num_secondary_audio; ii++) {
00338 if (!_parse_stream(bits, &ss[ii])) {
00339 X_FREE(ss);
00340 fprintf(stderr, "error parsing secondary audio entry\n");
00341 return 0;
00342 }
00343
00344 ss->sa_num_primary_audio_ref = bs_read(bits, 8);
00345 bs_skip(bits, 8);
00346 if (ss->sa_num_primary_audio_ref) {
00347 ss->sa_primary_audio_ref = calloc(ss->sa_num_primary_audio_ref, sizeof(uint8_t));
00348 for (jj = 0; jj < ss->sa_num_primary_audio_ref; jj++) {
00349 ss->sa_primary_audio_ref[jj] = bs_read(bits, 8);
00350 }
00351 if (ss->sa_num_primary_audio_ref % 2) {
00352 bs_skip(bits, 8);
00353 }
00354 }
00355 }
00356 }
00357 stn->secondary_audio = ss;
00358
00359
00360 ss = NULL;
00361 if (stn->num_secondary_video) {
00362 ss = calloc(stn->num_secondary_video, sizeof(MPLS_STREAM));
00363 for (ii = 0; ii < stn->num_secondary_video; ii++) {
00364 if (!_parse_stream(bits, &ss[ii])) {
00365 X_FREE(ss);
00366 fprintf(stderr, "error parsing secondary video entry\n");
00367 return 0;
00368 }
00369
00370 ss->sv_num_secondary_audio_ref = bs_read(bits, 8);
00371 bs_skip(bits, 8);
00372 if (ss->sv_num_secondary_audio_ref) {
00373 ss->sv_secondary_audio_ref = calloc(ss->sv_num_secondary_audio_ref, sizeof(uint8_t));
00374 for (jj = 0; jj < ss->sv_num_secondary_audio_ref; jj++) {
00375 ss->sv_secondary_audio_ref[jj] = bs_read(bits, 8);
00376 }
00377 if (ss->sv_num_secondary_audio_ref % 2) {
00378 bs_skip(bits, 8);
00379 }
00380 }
00381 ss->sv_num_pip_pg_ref = bs_read(bits, 8);
00382 bs_skip(bits, 8);
00383 if (ss->sv_num_pip_pg_ref) {
00384 ss->sv_pip_pg_ref = calloc(ss->sv_num_pip_pg_ref, sizeof(uint8_t));
00385 for (jj = 0; jj < ss->sv_num_pip_pg_ref; jj++) {
00386 ss->sv_pip_pg_ref[jj] = bs_read(bits, 8);
00387 }
00388 if (ss->sv_num_pip_pg_ref % 2) {
00389 bs_skip(bits, 8);
00390 }
00391 }
00392
00393 }
00394 }
00395 stn->secondary_video = ss;
00396
00397 bs_seek_byte(bits, pos + len);
00398 return 1;
00399 }
00400
00401 static void
00402 _clean_stn(MPLS_STN *stn)
00403 {
00404 X_FREE(stn->video);
00405 X_FREE(stn->audio);
00406 X_FREE(stn->pg);
00407 }
00408
00409 static int
00410 _parse_playitem(BITSTREAM *bits, MPLS_PI *pi)
00411 {
00412 int len, ii;
00413 int pos;
00414 char clip_id[6], codec_id[5];
00415 uint8_t stc_id;
00416
00417 if (!bs_is_align(bits, 0x07)) {
00418 fprintf(stderr, "_parse_playitem: Stream alignment error\n");
00419 }
00420
00421
00422 len = bs_read(bits, 16);
00423 pos = bs_pos(bits) >> 3;
00424
00425
00426 bs_read_bytes(bits, (uint8_t*)clip_id, 5);
00427 clip_id[5] = '\0';
00428
00429 bs_read_bytes(bits, (uint8_t*)codec_id, 4);
00430 codec_id[4] = '\0';
00431 if (memcmp(codec_id, "M2TS", 4) != 0) {
00432 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", codec_id);
00433 }
00434
00435
00436 bs_skip(bits, 11);
00437
00438 pi->is_multi_angle = bs_read(bits, 1);
00439
00440 pi->connection_condition = bs_read(bits, 4);
00441 if (pi->connection_condition != 0x01 &&
00442 pi->connection_condition != 0x05 &&
00443 pi->connection_condition != 0x06) {
00444
00445 fprintf(stderr, "Unexpected connection condition %02x\n",
00446 pi->connection_condition);
00447 }
00448
00449 stc_id = bs_read(bits, 8);
00450 pi->in_time = bs_read(bits, 32);
00451 pi->out_time = bs_read(bits, 32);
00452
00453 _parse_uo(bits, &pi->uo_mask);
00454 pi->random_access_flag = bs_read(bits, 1);
00455 bs_skip(bits, 7);
00456 pi->still_mode = bs_read(bits, 8);
00457 if (pi->still_mode == 0x01) {
00458 pi->still_time = bs_read(bits, 16);
00459 } else {
00460 bs_skip(bits, 16);
00461 }
00462
00463 pi->angle_count = 1;
00464 if (pi->is_multi_angle) {
00465 pi->angle_count = bs_read(bits, 8);
00466 if (pi->angle_count < 1) {
00467 pi->angle_count = 1;
00468 }
00469 bs_skip(bits, 6);
00470 pi->is_different_audio = bs_read(bits, 1);
00471 pi->is_seamless_angle = bs_read(bits, 1);
00472 }
00473 pi->clip = calloc(pi->angle_count, sizeof(MPLS_CLIP));
00474 strcpy(pi->clip[0].clip_id, clip_id);
00475 strcpy(pi->clip[0].codec_id, codec_id);
00476 pi->clip[0].stc_id = stc_id;
00477 for (ii = 1; ii < pi->angle_count; ii++) {
00478 bs_read_bytes(bits, (uint8_t*)pi->clip[ii].clip_id, 5);
00479 pi->clip[ii].clip_id[5] = '\0';
00480
00481 bs_read_bytes(bits, (uint8_t*)pi->clip[ii].codec_id, 4);
00482 pi->clip[ii].codec_id[4] = '\0';
00483 if (memcmp(pi->clip[ii].codec_id, "M2TS", 4) != 0) {
00484 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", pi->clip[ii].codec_id);
00485 }
00486 pi->clip[ii].stc_id = bs_read(bits, 8);
00487 }
00488 if (!_parse_stn(bits, &pi->stn)) {
00489 return 0;
00490 }
00491
00492 bs_seek_byte(bits, pos + len);
00493 return 1;
00494 }
00495
00496 static void
00497 _clean_playitem(MPLS_PI *pi)
00498 {
00499 X_FREE(pi->clip);
00500 _clean_stn(&pi->stn);
00501 }
00502
00503 static int
00504 _parse_subplayitem(BITSTREAM *bits, MPLS_SUB_PI *spi)
00505 {
00506 int len, ii;
00507 int pos;
00508 char clip_id[6], codec_id[5];
00509 uint8_t stc_id;
00510
00511 if (!bs_is_align(bits, 0x07)) {
00512 fprintf(stderr, "_parse_subplayitem: alignment error\n");
00513 }
00514
00515
00516 len = bs_read(bits, 16);
00517 pos = bs_pos(bits) >> 3;
00518
00519
00520 bs_read_bytes(bits, (uint8_t*)clip_id, 5);
00521 clip_id[5] = '\0';
00522
00523 bs_read_bytes(bits, (uint8_t*)codec_id, 4);
00524 codec_id[4] = '\0';
00525 if (memcmp(codec_id, "M2TS", 4) != 0) {
00526 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", codec_id);
00527 }
00528
00529 bs_skip(bits, 27);
00530
00531 spi->connection_condition = bs_read(bits, 4);
00532
00533 if (spi->connection_condition != 0x01 &&
00534 spi->connection_condition != 0x05 &&
00535 spi->connection_condition != 0x06) {
00536
00537 fprintf(stderr, "Unexpected connection condition %02x\n",
00538 spi->connection_condition);
00539 }
00540 spi->is_multi_clip = bs_read(bits, 1);
00541 stc_id = bs_read(bits, 8);
00542 spi->in_time = bs_read(bits, 32);
00543 spi->out_time = bs_read(bits, 32);
00544 spi->sync_play_item_id = bs_read(bits, 16);
00545 spi->sync_pts = bs_read(bits, 32);
00546 spi->clip_count = 1;
00547 if (spi->is_multi_clip) {
00548 spi->clip_count = bs_read(bits, 8);
00549 if (spi->clip_count < 1) {
00550 spi->clip_count = 1;
00551 }
00552 }
00553 spi->clip = calloc(spi->clip_count, sizeof(MPLS_CLIP));
00554 strcpy(spi->clip[0].clip_id, clip_id);
00555 strcpy(spi->clip[0].codec_id, codec_id);
00556 spi->clip[0].stc_id = stc_id;
00557 for (ii = 1; ii < spi->clip_count; ii++) {
00558
00559 bs_read_bytes(bits, (uint8_t*)spi->clip[ii].clip_id, 5);
00560 spi->clip[ii].clip_id[5] = '\0';
00561
00562 bs_read_bytes(bits, (uint8_t*)spi->clip[ii].codec_id, 4);
00563 spi->clip[ii].codec_id[4] = '\0';
00564 if (memcmp(spi->clip[ii].codec_id, "M2TS", 4) != 0) {
00565 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", spi->clip[ii].codec_id);
00566 }
00567 spi->clip[ii].stc_id = bs_read(bits, 8);
00568 }
00569
00570
00571
00572 bs_seek_byte(bits, pos + len);
00573 return 1;
00574 }
00575
00576 static void
00577 _clean_subplayitem(MPLS_SUB_PI *spi)
00578 {
00579 X_FREE(spi->clip);
00580 }
00581
00582 static int
00583 _parse_subpath(BITSTREAM *bits, MPLS_SUB *sp)
00584 {
00585 int len, ii;
00586 int pos;
00587 MPLS_SUB_PI *spi = NULL;
00588
00589 if (!bs_is_align(bits, 0x07)) {
00590 fprintf(stderr, "_parse_subpath: alignment error\n");
00591 }
00592
00593
00594 len = bs_read(bits, 32);
00595 pos = bs_pos(bits) >> 3;
00596
00597 bs_skip(bits, 8);
00598 sp->type = bs_read(bits, 8);
00599 bs_skip(bits, 15);
00600 sp->is_repeat = bs_read(bits, 1);
00601 bs_skip(bits, 8);
00602 sp->sub_playitem_count = bs_read(bits, 8);
00603
00604 spi = calloc(sp->sub_playitem_count, sizeof(MPLS_SUB_PI));
00605 for (ii = 0; ii < sp->sub_playitem_count; ii++) {
00606 if (!_parse_subplayitem(bits, &spi[ii])) {
00607 X_FREE(spi);
00608 fprintf(stderr, "error parsing sub play item\n");
00609 return 0;
00610 }
00611 }
00612 sp->sub_play_item = spi;
00613
00614
00615 bs_seek_byte(bits, pos + len);
00616 return 1;
00617 }
00618
00619 static void
00620 _clean_subpath(MPLS_SUB *sp)
00621 {
00622 int ii;
00623
00624 for (ii = 0; ii < sp->sub_playitem_count; ii++) {
00625 _clean_subplayitem(&sp->sub_play_item[ii]);
00626 }
00627 X_FREE(sp->sub_play_item);
00628 }
00629
00630 static int
00631 _parse_playlistmark(BITSTREAM *bits, MPLS_PL *pl)
00632 {
00633 int ii;
00634 MPLS_PLM *plm = NULL;
00635
00636 bs_seek_byte(bits, pl->mark_pos);
00637
00638 bs_skip(bits, 32);
00639
00640 pl->mark_count = bs_read(bits, 16);
00641
00642 plm = calloc(pl->mark_count, sizeof(MPLS_PLM));
00643 for (ii = 0; ii < pl->mark_count; ii++) {
00644 plm[ii].mark_id = bs_read(bits, 8);
00645 plm[ii].mark_type = bs_read(bits, 8);
00646 plm[ii].play_item_ref = bs_read(bits, 16);
00647 plm[ii].time = bs_read(bits, 32);
00648 plm[ii].entry_es_pid = bs_read(bits, 16);
00649 plm[ii].duration = bs_read(bits, 32);
00650 }
00651 pl->play_mark = plm;
00652 return 1;
00653 }
00654
00655 static int
00656 _parse_playlist(BITSTREAM *bits, MPLS_PL *pl)
00657 {
00658 int ii;
00659 MPLS_PI *pi = NULL;
00660 MPLS_SUB *sub_path = NULL;
00661
00662 bs_seek_byte(bits, pl->list_pos);
00663
00664 bs_skip(bits, 32);
00665
00666 bs_skip(bits, 16);
00667
00668 pl->list_count = bs_read(bits, 16);
00669 pl->sub_count = bs_read(bits, 16);
00670
00671 pi = calloc(pl->list_count, sizeof(MPLS_PI));
00672 for (ii = 0; ii < pl->list_count; ii++) {
00673 if (!_parse_playitem(bits, &pi[ii])) {
00674 X_FREE(pi);
00675 fprintf(stderr, "error parsing play list item\n");
00676 return 0;
00677 }
00678 }
00679 pl->play_item = pi;
00680
00681 sub_path = calloc(pl->sub_count, sizeof(MPLS_SUB));
00682 for (ii = 0; ii < pl->sub_count; ii++)
00683 {
00684 if (!_parse_subpath(bits, &sub_path[ii]))
00685 {
00686 X_FREE(sub_path);
00687 fprintf(stderr, "error parsing subpath\n");
00688 return 0;
00689 }
00690 }
00691 pl->sub_path = sub_path;
00692
00693 return 1;
00694 }
00695
00696 static void
00697 _clean_playlist(MPLS_PL *pl)
00698 {
00699 int ii;
00700
00701 if (pl == NULL) {
00702 return;
00703 }
00704 if (pl->play_item != NULL) {
00705 for (ii = 0; ii < pl->list_count; ii++) {
00706 _clean_playitem(&pl->play_item[ii]);
00707 }
00708 X_FREE(pl->play_item);
00709 }
00710 if (pl->sub_path != NULL) {
00711 for (ii = 0; ii < pl->sub_count; ii++) {
00712 _clean_subpath(&pl->sub_path[ii]);
00713 }
00714 X_FREE(pl->sub_path);
00715 }
00716 X_FREE(pl->play_mark);
00717 X_FREE(pl);
00718 }
00719
00720 void
00721 mpls_free(MPLS_PL *pl)
00722 {
00723 _clean_playlist(pl);
00724 }
00725
00726 MPLS_PL*
00727 mpls_parse(char *path, int verbose)
00728 {
00729 BITSTREAM bits;
00730 BD_FILE_H *fp;
00731 MPLS_PL *pl = NULL;
00732
00733 mpls_verbose = verbose;
00734
00735 pl = calloc(1, sizeof(MPLS_PL));
00736 if (pl == NULL) {
00737 return NULL;
00738 }
00739
00740 fp = file_open(path, "rb");
00741 if (fp == NULL) {
00742 fprintf(stderr, "Failed to open %s\n", path);
00743 X_FREE(pl);
00744 return NULL;
00745 }
00746
00747 bs_init(&bits, fp);
00748 if (!_parse_header(&bits, pl)) {
00749 file_close(fp);
00750 _clean_playlist(pl);
00751 return NULL;
00752 }
00753 if (!_parse_playlist(&bits, pl)) {
00754 file_close(fp);
00755 _clean_playlist(pl);
00756 return NULL;
00757 }
00758 if (!_parse_playlistmark(&bits, pl)) {
00759 file_close(fp);
00760 _clean_playlist(pl);
00761 return NULL;
00762 }
00763 file_close(fp);
00764 return pl;
00765 }
00766