|
MythTV
0.26-pre
|
00001 /* 00002 * This file is part of libbluray 00003 * Copyright (C) 2009-2010 John Stebbins 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library. If not, see 00017 * <http://www.gnu.org/licenses/>. 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 // Reserved 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 // Reserved 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 // Reserved 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 // Skip 160 reserved bits 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 // Skip STN len 00259 len = bs_read(bits, 16); 00260 pos = bs_pos(bits) >> 3; 00261 00262 // Skip 2 reserved bytes 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 // 5 reserve bytes 00274 bs_skip(bits, 5 * 8); 00275 00276 // Primary Video Streams 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 // Primary Audio Streams 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 // Presentation Graphic Streams 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 // Interactive Graphic Streams 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 // Secondary Audio Streams 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 // Read Secondary Audio Extra Attributes 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 // Secondary Video Streams 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 // Read Secondary Video Extra Attributes 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 // PlayItem Length 00425 len = bs_read(bits, 16); 00426 pos = bs_pos(bits) >> 3; 00427 00428 // Primary Clip identifer 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 // Skip reserved 11 bits 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 // Seek past any unused items 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 // PlayItem Length 00519 len = bs_read(bits, 16); 00520 pos = bs_pos(bits) >> 3; 00521 00522 // Primary Clip identifer 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 // Primary Clip identifer 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 // Seek to end of subpath 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 // PlayItem Length 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 // Seek to end of subpath 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 // Skip the length field, I don't use it 00641 bs_skip(bits, 32); 00642 // Then get the number of marks 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 // Skip playlist length 00667 bs_skip(bits, 32); 00668 // Skip reserved bytes 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
1.7.6.1