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 X_FREE(stn->ig);
00408 X_FREE(stn->secondary_audio);
00409 X_FREE(stn->secondary_video);
00410 }
00411
00412 static int
00413 _parse_playitem(BITSTREAM *bits, MPLS_PI *pi)
00414 {
00415 int len, ii;
00416 int pos;
00417 char clip_id[6], codec_id[5];
00418 uint8_t stc_id;
00419
00420 if (!bs_is_align(bits, 0x07)) {
00421 fprintf(stderr, "_parse_playitem: Stream alignment error\n");
00422 }
00423
00424
00425 len = bs_read(bits, 16);
00426 pos = bs_pos(bits) >> 3;
00427
00428
00429 bs_read_bytes(bits, (uint8_t*)clip_id, 5);
00430 clip_id[5] = '\0';
00431
00432 bs_read_bytes(bits, (uint8_t*)codec_id, 4);
00433 codec_id[4] = '\0';
00434 if (memcmp(codec_id, "M2TS", 4) != 0) {
00435 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", codec_id);
00436 }
00437
00438
00439 bs_skip(bits, 11);
00440
00441 pi->is_multi_angle = bs_read(bits, 1);
00442
00443 pi->connection_condition = bs_read(bits, 4);
00444 if (pi->connection_condition != 0x01 &&
00445 pi->connection_condition != 0x05 &&
00446 pi->connection_condition != 0x06) {
00447
00448 fprintf(stderr, "Unexpected connection condition %02x\n",
00449 pi->connection_condition);
00450 }
00451
00452 stc_id = bs_read(bits, 8);
00453 pi->in_time = bs_read(bits, 32);
00454 pi->out_time = bs_read(bits, 32);
00455
00456 _parse_uo(bits, &pi->uo_mask);
00457 pi->random_access_flag = bs_read(bits, 1);
00458 bs_skip(bits, 7);
00459 pi->still_mode = bs_read(bits, 8);
00460 if (pi->still_mode == 0x01) {
00461 pi->still_time = bs_read(bits, 16);
00462 } else {
00463 bs_skip(bits, 16);
00464 }
00465
00466 pi->angle_count = 1;
00467 if (pi->is_multi_angle) {
00468 pi->angle_count = bs_read(bits, 8);
00469 if (pi->angle_count < 1) {
00470 pi->angle_count = 1;
00471 }
00472 bs_skip(bits, 6);
00473 pi->is_different_audio = bs_read(bits, 1);
00474 pi->is_seamless_angle = bs_read(bits, 1);
00475 }
00476 pi->clip = calloc(pi->angle_count, sizeof(MPLS_CLIP));
00477 strcpy(pi->clip[0].clip_id, clip_id);
00478 strcpy(pi->clip[0].codec_id, codec_id);
00479 pi->clip[0].stc_id = stc_id;
00480 for (ii = 1; ii < pi->angle_count; ii++) {
00481 bs_read_bytes(bits, (uint8_t*)pi->clip[ii].clip_id, 5);
00482 pi->clip[ii].clip_id[5] = '\0';
00483
00484 bs_read_bytes(bits, (uint8_t*)pi->clip[ii].codec_id, 4);
00485 pi->clip[ii].codec_id[4] = '\0';
00486 if (memcmp(pi->clip[ii].codec_id, "M2TS", 4) != 0) {
00487 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", pi->clip[ii].codec_id);
00488 }
00489 pi->clip[ii].stc_id = bs_read(bits, 8);
00490 }
00491 if (!_parse_stn(bits, &pi->stn)) {
00492 return 0;
00493 }
00494
00495 bs_seek_byte(bits, pos + len);
00496 return 1;
00497 }
00498
00499 static void
00500 _clean_playitem(MPLS_PI *pi)
00501 {
00502 X_FREE(pi->clip);
00503 _clean_stn(&pi->stn);
00504 }
00505
00506 static int
00507 _parse_subplayitem(BITSTREAM *bits, MPLS_SUB_PI *spi)
00508 {
00509 int len, ii;
00510 int pos;
00511 char clip_id[6], codec_id[5];
00512 uint8_t stc_id;
00513
00514 if (!bs_is_align(bits, 0x07)) {
00515 fprintf(stderr, "_parse_subplayitem: alignment error\n");
00516 }
00517
00518
00519 len = bs_read(bits, 16);
00520 pos = bs_pos(bits) >> 3;
00521
00522
00523 bs_read_bytes(bits, (uint8_t*)clip_id, 5);
00524 clip_id[5] = '\0';
00525
00526 bs_read_bytes(bits, (uint8_t*)codec_id, 4);
00527 codec_id[4] = '\0';
00528 if (memcmp(codec_id, "M2TS", 4) != 0) {
00529 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", codec_id);
00530 }
00531
00532 bs_skip(bits, 27);
00533
00534 spi->connection_condition = bs_read(bits, 4);
00535
00536 if (spi->connection_condition != 0x01 &&
00537 spi->connection_condition != 0x05 &&
00538 spi->connection_condition != 0x06) {
00539
00540 fprintf(stderr, "Unexpected connection condition %02x\n",
00541 spi->connection_condition);
00542 }
00543 spi->is_multi_clip = bs_read(bits, 1);
00544 stc_id = bs_read(bits, 8);
00545 spi->in_time = bs_read(bits, 32);
00546 spi->out_time = bs_read(bits, 32);
00547 spi->sync_play_item_id = bs_read(bits, 16);
00548 spi->sync_pts = bs_read(bits, 32);
00549 spi->clip_count = 1;
00550 if (spi->is_multi_clip) {
00551 spi->clip_count = bs_read(bits, 8);
00552 if (spi->clip_count < 1) {
00553 spi->clip_count = 1;
00554 }
00555 }
00556 spi->clip = calloc(spi->clip_count, sizeof(MPLS_CLIP));
00557 strcpy(spi->clip[0].clip_id, clip_id);
00558 strcpy(spi->clip[0].codec_id, codec_id);
00559 spi->clip[0].stc_id = stc_id;
00560 for (ii = 1; ii < spi->clip_count; ii++) {
00561
00562 bs_read_bytes(bits, (uint8_t*)spi->clip[ii].clip_id, 5);
00563 spi->clip[ii].clip_id[5] = '\0';
00564
00565 bs_read_bytes(bits, (uint8_t*)spi->clip[ii].codec_id, 4);
00566 spi->clip[ii].codec_id[4] = '\0';
00567 if (memcmp(spi->clip[ii].codec_id, "M2TS", 4) != 0) {
00568 fprintf(stderr, "Incorrect CodecIdentifier (%s)\n", spi->clip[ii].codec_id);
00569 }
00570 spi->clip[ii].stc_id = bs_read(bits, 8);
00571 }
00572
00573
00574
00575 bs_seek_byte(bits, pos + len);
00576 return 1;
00577 }
00578
00579 static void
00580 _clean_subplayitem(MPLS_SUB_PI *spi)
00581 {
00582 X_FREE(spi->clip);
00583 }
00584
00585 static int
00586 _parse_subpath(BITSTREAM *bits, MPLS_SUB *sp)
00587 {
00588 int len, ii;
00589 int pos;
00590 MPLS_SUB_PI *spi = NULL;
00591
00592 if (!bs_is_align(bits, 0x07)) {
00593 fprintf(stderr, "_parse_subpath: alignment error\n");
00594 }
00595
00596
00597 len = bs_read(bits, 32);
00598 pos = bs_pos(bits) >> 3;
00599
00600 bs_skip(bits, 8);
00601 sp->type = bs_read(bits, 8);
00602 bs_skip(bits, 15);
00603 sp->is_repeat = bs_read(bits, 1);
00604 bs_skip(bits, 8);
00605 sp->sub_playitem_count = bs_read(bits, 8);
00606
00607 spi = calloc(sp->sub_playitem_count, sizeof(MPLS_SUB_PI));
00608 for (ii = 0; ii < sp->sub_playitem_count; ii++) {
00609 if (!_parse_subplayitem(bits, &spi[ii])) {
00610 X_FREE(spi);
00611 fprintf(stderr, "error parsing sub play item\n");
00612 return 0;
00613 }
00614 }
00615 sp->sub_play_item = spi;
00616
00617
00618 bs_seek_byte(bits, pos + len);
00619 return 1;
00620 }
00621
00622 static void
00623 _clean_subpath(MPLS_SUB *sp)
00624 {
00625 int ii;
00626
00627 for (ii = 0; ii < sp->sub_playitem_count; ii++) {
00628 _clean_subplayitem(&sp->sub_play_item[ii]);
00629 }
00630 X_FREE(sp->sub_play_item);
00631 }
00632
00633 static int
00634 _parse_playlistmark(BITSTREAM *bits, MPLS_PL *pl)
00635 {
00636 int ii;
00637 MPLS_PLM *plm = NULL;
00638
00639 bs_seek_byte(bits, pl->mark_pos);
00640
00641 bs_skip(bits, 32);
00642
00643 pl->mark_count = bs_read(bits, 16);
00644
00645 plm = calloc(pl->mark_count, sizeof(MPLS_PLM));
00646 for (ii = 0; ii < pl->mark_count; ii++) {
00647 plm[ii].mark_id = bs_read(bits, 8);
00648 plm[ii].mark_type = bs_read(bits, 8);
00649 plm[ii].play_item_ref = bs_read(bits, 16);
00650 plm[ii].time = bs_read(bits, 32);
00651 plm[ii].entry_es_pid = bs_read(bits, 16);
00652 plm[ii].duration = bs_read(bits, 32);
00653 }
00654 pl->play_mark = plm;
00655 return 1;
00656 }
00657
00658 static int
00659 _parse_playlist(BITSTREAM *bits, MPLS_PL *pl)
00660 {
00661 int ii;
00662 MPLS_PI *pi = NULL;
00663 MPLS_SUB *sub_path = NULL;
00664
00665 bs_seek_byte(bits, pl->list_pos);
00666
00667 bs_skip(bits, 32);
00668
00669 bs_skip(bits, 16);
00670
00671 pl->list_count = bs_read(bits, 16);
00672 pl->sub_count = bs_read(bits, 16);
00673
00674 pi = calloc(pl->list_count, sizeof(MPLS_PI));
00675 for (ii = 0; ii < pl->list_count; ii++) {
00676 if (!_parse_playitem(bits, &pi[ii])) {
00677 X_FREE(pi);
00678 fprintf(stderr, "error parsing play list item\n");
00679 return 0;
00680 }
00681 }
00682 pl->play_item = pi;
00683
00684 sub_path = calloc(pl->sub_count, sizeof(MPLS_SUB));
00685 for (ii = 0; ii < pl->sub_count; ii++)
00686 {
00687 if (!_parse_subpath(bits, &sub_path[ii]))
00688 {
00689 X_FREE(sub_path);
00690 fprintf(stderr, "error parsing subpath\n");
00691 return 0;
00692 }
00693 }
00694 pl->sub_path = sub_path;
00695
00696 return 1;
00697 }
00698
00699 static void
00700 _clean_playlist(MPLS_PL *pl)
00701 {
00702 int ii;
00703
00704 if (pl == NULL) {
00705 return;
00706 }
00707 if (pl->play_item != NULL) {
00708 for (ii = 0; ii < pl->list_count; ii++) {
00709 _clean_playitem(&pl->play_item[ii]);
00710 }
00711 X_FREE(pl->play_item);
00712 }
00713 if (pl->sub_path != NULL) {
00714 for (ii = 0; ii < pl->sub_count; ii++) {
00715 _clean_subpath(&pl->sub_path[ii]);
00716 }
00717 X_FREE(pl->sub_path);
00718 }
00719 X_FREE(pl->play_mark);
00720 X_FREE(pl);
00721 }
00722
00723 void
00724 mpls_free(MPLS_PL *pl)
00725 {
00726 _clean_playlist(pl);
00727 }
00728
00729 MPLS_PL*
00730 mpls_parse(char *path, int verbose)
00731 {
00732 BITSTREAM bits;
00733 BD_FILE_H *fp;
00734 MPLS_PL *pl = NULL;
00735
00736 mpls_verbose = verbose;
00737
00738 pl = calloc(1, sizeof(MPLS_PL));
00739 if (pl == NULL) {
00740 return NULL;
00741 }
00742
00743 fp = file_open(path, "rb");
00744 if (fp == NULL) {
00745 fprintf(stderr, "Failed to open %s\n", path);
00746 X_FREE(pl);
00747 return NULL;
00748 }
00749
00750 bs_init(&bits, fp);
00751 if (!_parse_header(&bits, pl)) {
00752 file_close(fp);
00753 _clean_playlist(pl);
00754 return NULL;
00755 }
00756 if (!_parse_playlist(&bits, pl)) {
00757 file_close(fp);
00758 _clean_playlist(pl);
00759 return NULL;
00760 }
00761 if (!_parse_playlistmark(&bits, pl)) {
00762 file_close(fp);
00763 _clean_playlist(pl);
00764 return NULL;
00765 }
00766 file_close(fp);
00767 return pl;
00768 }
00769