00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #if HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include "util/macro.h"
00025 #include "util/logging.h"
00026 #include "util/strutl.h"
00027 #include "file/file.h"
00028 #include "../bluray.h"
00029 #include "mpls_parse.h"
00030 #include "navigation.h"
00031
00032 #include <stdlib.h>
00033 #include <string.h>
00034
00035 static int _filter_dup(MPLS_PL *pl_list[], unsigned count, MPLS_PL *pl)
00036 {
00037 unsigned ii, jj;
00038
00039 for (ii = 0; ii < count; ii++) {
00040 if (pl->list_count != pl_list[ii]->list_count) {
00041 continue;
00042 }
00043 for (jj = 0; jj < pl->list_count; jj++) {
00044 MPLS_PI *pi1, *pi2;
00045
00046 pi1 = &pl->play_item[jj];
00047 pi2 = &pl_list[ii]->play_item[jj];
00048
00049 if (memcmp(pi1->clip[0].clip_id, pi2->clip[0].clip_id, 5) != 0 ||
00050 pi1->in_time != pi2->in_time ||
00051 pi1->out_time != pi2->out_time) {
00052 break;
00053 }
00054 }
00055 if (jj != pl->list_count) {
00056 continue;
00057 }
00058 return 0;
00059 }
00060 return 1;
00061 }
00062
00063 static unsigned int
00064 _find_repeats(MPLS_PL *pl, const char *m2ts)
00065 {
00066 unsigned ii, count = 0;
00067
00068 for (ii = 0; ii < pl->list_count; ii++) {
00069 MPLS_PI *pi;
00070
00071 pi = &pl->play_item[ii];
00072
00073 if (strcmp(pi->clip[0].clip_id, m2ts) == 0) {
00074 count++;
00075 }
00076 }
00077 return count;
00078 }
00079
00080 static int
00081 _filter_repeats(MPLS_PL *pl, unsigned repeats)
00082 {
00083 unsigned ii;
00084
00085 for (ii = 0; ii < pl->list_count; ii++) {
00086 MPLS_PI *pi;
00087
00088 pi = &pl->play_item[ii];
00089
00090 if (_find_repeats(pl, pi->clip[0].clip_id) > repeats) {
00091 return 0;
00092 }
00093 }
00094 return 1;
00095 }
00096
00097 static uint32_t
00098 _pl_duration(MPLS_PL *pl)
00099 {
00100 unsigned ii;
00101 uint32_t duration = 0;
00102 MPLS_PI *pi;
00103
00104 for (ii = 0; ii < pl->list_count; ii++) {
00105 pi = &pl->play_item[ii];
00106 duration += pi->out_time - pi->in_time;
00107 }
00108 return duration;
00109 }
00110
00111 NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags)
00112 {
00113 BD_DIR_H *dir;
00114 BD_DIRENT ent;
00115 char *path = NULL;
00116 MPLS_PL **pl_list = NULL;
00117 MPLS_PL *pl = NULL;
00118 unsigned int ii, pl_list_size = 0;
00119 int res;
00120 NAV_TITLE_LIST *title_list;
00121 unsigned int title_info_alloc = 100;
00122
00123 title_list = calloc(1, sizeof(NAV_TITLE_LIST));
00124 title_list->title_info = calloc(title_info_alloc, sizeof(NAV_TITLE_INFO));
00125
00126 DEBUG(DBG_NAV, "Root: %s:\n", root);
00127 path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST", root);
00128
00129 dir = dir_open(path);
00130 if (dir == NULL) {
00131 DEBUG(DBG_NAV, "Failed to open dir: %s\n", path);
00132 X_FREE(path);
00133 X_FREE(title_list);
00134 return NULL;
00135 }
00136 X_FREE(path);
00137
00138 ii = 0;
00139 for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) {
00140
00141 if (ent.d_name[0] == '.') {
00142 continue;
00143 }
00144 path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST" DIR_SEP "%s",
00145 root, ent.d_name);
00146
00147 if (ii >= pl_list_size) {
00148 MPLS_PL **tmp = NULL;
00149
00150 pl_list_size += 100;
00151 tmp = realloc(pl_list, pl_list_size * sizeof(MPLS_PL*));
00152 if (tmp == NULL) {
00153 X_FREE(path);
00154 break;
00155 }
00156 pl_list = tmp;
00157 }
00158 pl = mpls_parse(path, 0);
00159 X_FREE(path);
00160 if (pl != NULL) {
00161 if ((flags & TITLES_FILTER_DUP_TITLE) &&
00162 !_filter_dup(pl_list, ii, pl)) {
00163 mpls_free(pl);
00164 continue;
00165 }
00166 if ((flags & TITLES_FILTER_DUP_CLIP) && !_filter_repeats(pl, 2)) {
00167 mpls_free(pl);
00168 continue;
00169 }
00170 if (ii >= title_info_alloc) {
00171 NAV_TITLE_INFO *tmp = NULL;
00172 title_info_alloc += 100;
00173
00174 tmp = realloc(title_list->title_info,
00175 title_info_alloc * sizeof(NAV_TITLE_INFO));
00176 if (tmp == NULL) {
00177 break;
00178 }
00179 title_list->title_info = tmp;
00180 }
00181 pl_list[ii] = pl;
00182 strncpy(title_list->title_info[ii].name, ent.d_name, 11);
00183 title_list->title_info[ii].name[10] = '\0';
00184 title_list->title_info[ii].ref = ii;
00185 title_list->title_info[ii].mpls_id = atoi(ent.d_name);
00186 title_list->title_info[ii].duration = _pl_duration(pl_list[ii]);
00187 ii++;
00188 }
00189 }
00190 dir_close(dir);
00191
00192 title_list->count = ii;
00193 for (ii = 0; ii < title_list->count; ii++) {
00194 mpls_free(pl_list[ii]);
00195 }
00196 return title_list;
00197 }
00198
00199 void nav_free_title_list(NAV_TITLE_LIST *title_list)
00200 {
00201 X_FREE(title_list->title_info);
00202 X_FREE(title_list);
00203 }
00204
00205 char* nav_find_main_title(const char *root)
00206 {
00207 BD_DIR_H *dir;
00208 BD_DIRENT ent;
00209 char *path = NULL;
00210 MPLS_PL **pl_list = NULL;
00211 MPLS_PL **tmp = NULL;
00212 MPLS_PL *pl = NULL;
00213 unsigned count, ii, jj, pl_list_size = 0;
00214 int res;
00215 char longest[11];
00216
00217 DEBUG(DBG_NAV, "Root: %s:\n", root);
00218 path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST", root);
00219
00220 dir = dir_open(path);
00221 if (dir == NULL) {
00222 fprintf(stderr, "Failed to open dir: %s\n", path);
00223 X_FREE(path);
00224 return NULL;
00225 }
00226 X_FREE(path);
00227
00228 ii = jj = 0;
00229 for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) {
00230
00231 if (ent.d_name[0] == '.') {
00232 continue;
00233 }
00234 path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST" DIR_SEP "%s",
00235 root, ent.d_name);
00236
00237 if (ii >= pl_list_size) {
00238 pl_list_size += 100;
00239 tmp = realloc(pl_list, pl_list_size * sizeof(MPLS_PL*));
00240 if (tmp == NULL) {
00241 X_FREE(path);
00242 break;
00243 }
00244 pl_list = tmp;
00245 }
00246 pl = mpls_parse(path, 0);
00247 X_FREE(path);
00248 if (pl != NULL) {
00249 if (_filter_dup(pl_list, ii, pl) &&
00250 _filter_repeats(pl, 2)) {
00251 pl_list[ii] = pl;
00252 if (_pl_duration(pl_list[ii]) >= _pl_duration(pl_list[jj])) {
00253 strncpy(longest, ent.d_name, 11);
00254 longest[10] = '\0';
00255 jj = ii;
00256 }
00257 ii++;
00258 } else {
00259 mpls_free(pl);
00260 }
00261 }
00262 }
00263 dir_close(dir);
00264
00265 count = ii;
00266 for (ii = 0; ii < count; ii++) {
00267 mpls_free(pl_list[ii]);
00268 }
00269 if (count > 0) {
00270 char *str = (char*)malloc(strlen(longest) + 1);
00271 strcpy(str, longest);
00272 return str;
00273 } else {
00274 return NULL;
00275 }
00276 }
00277
00278 uint8_t nav_lookup_aspect(NAV_CLIP *clip, int pid)
00279 {
00280 CLPI_PROG *progs;
00281 int ii, jj;
00282
00283 progs = clip->cl->program.progs;
00284 for (ii = 0; ii < clip->cl->program.num_prog; ii++) {
00285 CLPI_PROG_STREAM *ps = progs[ii].streams;
00286 for (jj = 0; jj < progs[ii].num_streams; jj++) {
00287 if (ps[jj].pid == pid)
00288 {
00289 return ps[jj].aspect;
00290 }
00291 }
00292 }
00293 return 0;
00294 }
00295
00296 static void
00297 _fill_mark(NAV_TITLE *title, NAV_MARK *mark, int entry)
00298 {
00299 MPLS_PL *pl = title->pl;
00300 MPLS_PLM *plm;
00301 MPLS_PI *pi;
00302 NAV_CLIP *clip;
00303
00304 plm = &pl->play_mark[entry];
00305
00306 mark->plm = plm;
00307 mark->mark_type = plm->mark_type;
00308 mark->clip_ref = plm->play_item_ref;
00309 clip = &title->clip_list.clip[mark->clip_ref];
00310 mark->clip_pkt = clpi_lookup_spn(clip->cl, plm->time, 1,
00311 title->pl->play_item[mark->clip_ref].clip[title->angle].stc_id);
00312 mark->title_pkt = clip->title_pkt + mark->clip_pkt;
00313 mark->clip_time = plm->time;
00314
00315
00316 if (plm->play_item_ref < title->clip_list.count) {
00317 clip = &title->clip_list.clip[plm->play_item_ref];
00318 pi = &pl->play_item[plm->play_item_ref];
00319 mark->title_time = clip->title_time + plm->time - pi->in_time;
00320 }
00321 }
00322
00323 static void
00324 _extrapolate_title(NAV_TITLE *title)
00325 {
00326 uint64_t duration = 0;
00327 uint64_t pkt = 0;
00328 unsigned ii, jj;
00329 MPLS_PL *pl = title->pl;
00330 MPLS_PI *pi;
00331 MPLS_PLM *plm;
00332 NAV_MARK *mark, *prev = NULL;
00333 NAV_CLIP *clip;
00334
00335 for (ii = 0; ii < title->clip_list.count; ii++) {
00336 clip = &title->clip_list.clip[ii];
00337 pi = &pl->play_item[ii];
00338 if (pi->angle_count > title->angle_count) {
00339 title->angle_count = pi->angle_count;
00340 }
00341
00342 clip->title_time = duration;
00343 clip->duration = pi->out_time - pi->in_time;
00344 clip->title_pkt = pkt;
00345 duration += clip->duration;
00346 pkt += clip->end_pkt - clip->start_pkt;
00347 }
00348 title->duration = duration;
00349 title->packets = pkt;
00350
00351 for (ii = 0, jj = 0; ii < pl->mark_count; ii++) {
00352 plm = &pl->play_mark[ii];
00353 if (plm->mark_type == BD_MARK_ENTRY) {
00354
00355 mark = &title->chap_list.mark[jj];
00356 _fill_mark(title, mark, ii);
00357 mark->number = jj;
00358
00359
00360 if (plm->duration != 0) {
00361 mark->duration = plm->duration;
00362 } else if (prev != NULL) {
00363 if (prev->duration == 0) {
00364 prev->duration = mark->title_time - prev->title_time;
00365 }
00366 }
00367 prev = mark;
00368 jj++;
00369 }
00370 mark = &title->mark_list.mark[ii];
00371 _fill_mark(title, mark, ii);
00372 mark->number = ii;
00373 }
00374 title->chap_list.count = jj;
00375 if (prev->duration == 0) {
00376 prev->duration = title->duration - prev->title_time;
00377 }
00378 }
00379
00380 static void _fill_clip(NAV_TITLE *title,
00381 MPLS_CLIP *mpls_clip,
00382 uint8_t connection_condition, uint32_t in_time, uint32_t out_time,
00383 NAV_CLIP *clip,
00384 unsigned ref, uint32_t *pos, uint32_t *time)
00385
00386 {
00387 char *path;
00388
00389 clip->title = title;
00390 clip->ref = ref;
00391 clip->angle = 0;
00392 strncpy(clip->name, mpls_clip[clip->angle].clip_id, 5);
00393 strncpy(&clip->name[5], ".m2ts", 6);
00394 clip->clip_id = atoi(mpls_clip[clip->angle].clip_id);
00395
00396 path = str_printf("%s"DIR_SEP"BDMV"DIR_SEP"CLIPINF"DIR_SEP"%s.clpi",
00397 title->root, mpls_clip[clip->angle].clip_id);
00398 clip->cl = clpi_parse(path, 0);
00399 X_FREE(path);
00400 if (clip->cl == NULL) {
00401 clip->start_pkt = 0;
00402 clip->end_pkt = 0;
00403 return;
00404 }
00405 switch (connection_condition) {
00406 case 5:
00407 case 6:
00408 clip->start_pkt = 0;
00409 clip->connection = CONNECT_SEAMLESS;
00410 break;
00411 default:
00412 clip->start_pkt = clpi_lookup_spn(clip->cl, in_time, 1,
00413 mpls_clip[clip->angle].stc_id);
00414 clip->connection = CONNECT_NON_SEAMLESS;
00415 break;
00416 }
00417 clip->end_pkt = clpi_lookup_spn(clip->cl, out_time, 0,
00418 mpls_clip[clip->angle].stc_id);
00419 clip->in_time = in_time;
00420 clip->out_time = out_time;
00421 clip->pos = *pos;
00422 *pos += clip->end_pkt - clip->start_pkt;
00423 clip->start_time = *time;
00424 *time += clip->out_time - clip->in_time;
00425 }
00426
00427 NAV_TITLE* nav_title_open(const char *root, const char *playlist)
00428 {
00429 NAV_TITLE *title = NULL;
00430 char *path;
00431 unsigned ii, ss, chapters = 0;
00432 uint32_t pos = 0;
00433 uint32_t time = 0;
00434
00435 title = calloc(1, sizeof(NAV_TITLE));
00436 if (title == NULL) {
00437 return NULL;
00438 }
00439 title->root = (char*)malloc(strlen(root) + 1);
00440 strcpy(title->root, root);
00441 strncpy(title->name, playlist, 11);
00442 title->name[10] = '\0';
00443 path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST" DIR_SEP "%s",
00444 root, playlist);
00445 title->angle_count = 0;
00446 title->angle = 0;
00447 title->pl = mpls_parse(path, 0);
00448 if (title->pl == NULL) {
00449 DEBUG(DBG_NAV, "Fail: Playlist parse %s\n", path);
00450 X_FREE(title);
00451 X_FREE(path);
00452 return NULL;
00453 }
00454 X_FREE(path);
00455
00456 title->clip_list.count = title->pl->list_count;
00457 title->clip_list.clip = calloc(title->pl->list_count, sizeof(NAV_CLIP));
00458 title->packets = 0;
00459 for (ii = 0; ii < title->pl->list_count; ii++) {
00460 MPLS_PI *pi;
00461 NAV_CLIP *clip;
00462
00463 pi = &title->pl->play_item[ii];
00464
00465 clip = &title->clip_list.clip[ii];
00466
00467 _fill_clip(title, pi->clip, pi->connection_condition, pi->in_time, pi->out_time, clip, ii, &pos, &time);
00468 }
00469
00470
00471
00472 if (title->pl->sub_count > 0) {
00473 title->sub_path_count = title->pl->sub_count;
00474 title->sub_path = calloc(title->sub_path_count, sizeof(NAV_SUB_PATH));
00475
00476 for (ss = 0; ss < title->sub_path_count; ss++) {
00477 NAV_SUB_PATH *sub_path = &title->sub_path[ss];
00478
00479 sub_path->type = title->pl->sub_path[ss].type;
00480 sub_path->clip_list.count = title->pl->sub_path[ss].sub_playitem_count;
00481 sub_path->clip_list.clip = calloc(sub_path->clip_list.count, sizeof(NAV_CLIP));
00482
00483 pos = time = 0;
00484 for (ii = 0; ii < sub_path->clip_list.count; ii++) {
00485 MPLS_SUB_PI *pi = &title->pl->sub_path[ss].sub_play_item[ii];
00486 NAV_CLIP *clip = &sub_path->clip_list.clip[ii];
00487
00488 _fill_clip(title, pi->clip, pi->connection_condition, pi->in_time, pi->out_time, clip, ii, &pos, &time);
00489 }
00490 }
00491 }
00492
00493
00494
00495 for (ii = 0; ii < title->pl->mark_count; ii++) {
00496 if (title->pl->play_mark[ii].mark_type == BD_MARK_ENTRY) {
00497 chapters++;
00498 }
00499 }
00500 title->chap_list.count = chapters;
00501 title->chap_list.mark = calloc(chapters, sizeof(NAV_MARK));
00502 title->mark_list.count = title->pl->mark_count;
00503 title->mark_list.mark = calloc(title->pl->mark_count, sizeof(NAV_MARK));
00504
00505 _extrapolate_title(title);
00506 return title;
00507 }
00508
00509 void nav_title_close(NAV_TITLE *title)
00510 {
00511 unsigned ii, ss;
00512
00513 for (ss = 0; ss < title->sub_path_count; ss++) {
00514 for (ii = 0; ii < title->sub_path[ss].clip_list.count; ii++) {
00515 clpi_free(title->sub_path[ss].clip_list.clip[ii].cl);
00516 }
00517 X_FREE(title->sub_path[ss].clip_list.clip);
00518 }
00519 X_FREE(title->sub_path);
00520
00521 for (ii = 0; ii < title->pl->list_count; ii++) {
00522 clpi_free(title->clip_list.clip[ii].cl);
00523 }
00524 mpls_free(title->pl);
00525 X_FREE(title->clip_list.clip);
00526 X_FREE(title->root);
00527 X_FREE(title->chap_list.mark);
00528 X_FREE(title->mark_list.mark);
00529 X_FREE(title);
00530 }
00531
00532
00533
00534 NAV_CLIP* nav_chapter_search(NAV_TITLE *title, unsigned chapter, uint32_t *clip_pkt, uint32_t *out_pkt)
00535 {
00536 NAV_CLIP *clip;
00537
00538 if (chapter > title->chap_list.count) {
00539 clip = &title->clip_list.clip[0];
00540 *clip_pkt = clip->start_pkt;
00541 *out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
00542 return clip;
00543 }
00544 clip = &title->clip_list.clip[title->chap_list.mark[chapter].clip_ref];
00545 *clip_pkt = title->chap_list.mark[chapter].clip_pkt;
00546 *out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
00547 return clip;
00548 }
00549
00550 uint32_t nav_chapter_get_current(NAV_CLIP *clip, uint32_t pkt)
00551 {
00552 NAV_MARK * mark;
00553 NAV_TITLE *title;
00554 uint32_t ii;
00555
00556
00557 if (clip == NULL) {
00558 return 0;
00559 }
00560 title = clip->title;
00561 for (ii = 0; ii < title->chap_list.count; ii++) {
00562 mark = &title->chap_list.mark[ii];
00563 if (mark->clip_ref > clip->ref)
00564 {
00565 if (ii)
00566 return ii-1;
00567 else
00568 return 0;
00569 }
00570 if (mark->clip_ref == clip->ref && mark->clip_pkt <= pkt) {
00571 if ( ii == title->chap_list.count - 1 ) {
00572 return ii;
00573 }
00574 mark = &title->chap_list.mark[ii+1];
00575 if (mark->clip_ref != clip->ref || mark->clip_pkt > pkt) {
00576 return ii;
00577 }
00578 }
00579 }
00580 return 0;
00581 }
00582
00583
00584
00585 NAV_CLIP* nav_mark_search(NAV_TITLE *title, unsigned mark, uint32_t *clip_pkt, uint32_t *out_pkt)
00586 {
00587 NAV_CLIP *clip;
00588
00589 if (mark > title->mark_list.count) {
00590 clip = &title->clip_list.clip[0];
00591 *clip_pkt = clip->start_pkt;
00592 *out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
00593 return clip;
00594 }
00595 clip = &title->clip_list.clip[title->mark_list.mark[mark].clip_ref];
00596 *clip_pkt = title->mark_list.mark[mark].clip_pkt;
00597 *out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
00598 return clip;
00599 }
00600
00601
00602
00603
00604
00605 NAV_CLIP* nav_packet_search(NAV_TITLE *title, uint32_t pkt, uint32_t *clip_pkt, uint32_t *out_pkt, uint32_t *out_time)
00606 {
00607 uint32_t pos, len;
00608 NAV_CLIP *clip;
00609 unsigned ii;
00610
00611 pos = 0;
00612 for (ii = 0; ii < title->pl->list_count; ii++) {
00613 clip = &title->clip_list.clip[ii];
00614 len = clip->end_pkt - clip->start_pkt;
00615 if (pkt < pos + len)
00616 break;
00617 pos += len;
00618 }
00619 if (ii == title->pl->list_count) {
00620 clip = &title->clip_list.clip[ii-1];
00621 *out_time = clip->duration + clip->in_time;
00622 *clip_pkt = clip->end_pkt;
00623 } else {
00624 clip = &title->clip_list.clip[ii];
00625 *clip_pkt = clpi_access_point(clip->cl, pkt - pos + clip->start_pkt, 0, 0, out_time);
00626 }
00627 if(*out_time < clip->in_time)
00628 *out_time = 0;
00629 else
00630 *out_time -= clip->in_time;
00631 *out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
00632 return clip;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 uint32_t nav_angle_change_search(NAV_CLIP *clip, uint32_t pkt, uint32_t *time)
00657 {
00658 return clpi_access_point(clip->cl, pkt, 1, 1, time);
00659 }
00660
00661
00662
00663 NAV_CLIP* nav_time_search(NAV_TITLE *title, uint32_t tick, uint32_t *clip_pkt, uint32_t *out_pkt)
00664 {
00665 uint32_t pos, len;
00666 MPLS_PI *pi;
00667 NAV_CLIP *clip;
00668 unsigned ii;
00669
00670 pos = 0;
00671 for (ii = 0; ii < title->pl->list_count; ii++) {
00672 pi = &title->pl->play_item[ii];
00673 len = pi->out_time - pi->in_time;
00674 if (tick < pos + len)
00675 break;
00676 pos += len;
00677 }
00678 if (ii == title->pl->list_count) {
00679 clip = &title->clip_list.clip[ii-1];
00680 *clip_pkt = clip->end_pkt;
00681 } else {
00682 clip = &title->clip_list.clip[ii];
00683 *clip_pkt = clpi_lookup_spn(clip->cl, tick - pos + pi->in_time, 1,
00684 title->pl->play_item[clip->ref].clip[clip->angle].stc_id);
00685 }
00686 *out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
00687 return clip;
00688 }
00689
00690
00691
00692 void nav_clip_time_search(NAV_CLIP *clip, uint32_t tick, uint32_t *clip_pkt, uint32_t *out_pkt)
00693 {
00694 if (tick >= clip->out_time) {
00695 *clip_pkt = clip->end_pkt;
00696 } else {
00697 *clip_pkt = clpi_lookup_spn(clip->cl, tick, 1,
00698 clip->title->pl->play_item[clip->ref].clip[clip->angle].stc_id);
00699 }
00700 *out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 NAV_CLIP* nav_next_clip(NAV_TITLE *title, NAV_CLIP *clip)
00712 {
00713 if (clip == NULL) {
00714 return &title->clip_list.clip[0];
00715 }
00716 if (clip->ref >= title->clip_list.count - 1) {
00717 return NULL;
00718 }
00719 return &title->clip_list.clip[clip->ref + 1];
00720 }
00721
00722 NAV_CLIP* nav_set_angle(NAV_TITLE *title, NAV_CLIP *clip, unsigned angle)
00723 {
00724 char *path;
00725 int ii;
00726 uint32_t pos = 0;
00727 uint32_t time = 0;
00728
00729 if (title == NULL) {
00730 return clip;
00731 }
00732 if (angle > 8) {
00733
00734 return clip;
00735 }
00736 if (angle == title->angle) {
00737
00738 return clip;
00739 }
00740
00741 title->angle = angle;
00742
00743 title->packets = 0;
00744 for (ii = 0; ii < title->pl->list_count; ii++) {
00745 MPLS_PI *pi;
00746 NAV_CLIP *clip;
00747
00748 pi = &title->pl->play_item[ii];
00749 clip = &title->clip_list.clip[ii];
00750 if (title->angle >= pi->angle_count) {
00751 clip->angle = 0;
00752 } else {
00753 clip->angle = title->angle;
00754 }
00755
00756 clpi_free(clip->cl);
00757
00758 clip->ref = ii;
00759 strncpy(clip->name, pi->clip[clip->angle].clip_id, 5);
00760 strncpy(&clip->name[5], ".m2ts", 6);
00761 clip->clip_id = atoi(pi->clip[clip->angle].clip_id);
00762
00763 path = str_printf("%s"DIR_SEP"BDMV"DIR_SEP"CLIPINF"DIR_SEP"%s.clpi",
00764 title->root, pi->clip[clip->angle].clip_id);
00765 clip->cl = clpi_parse(path, 0);
00766 X_FREE(path);
00767 if (clip->cl == NULL) {
00768 clip->start_pkt = 0;
00769 clip->end_pkt = 0;
00770 continue;
00771 }
00772 switch (pi->connection_condition) {
00773 case 5:
00774 case 6:
00775 clip->start_pkt = 0;
00776 clip->connection = CONNECT_SEAMLESS;
00777 break;
00778 default:
00779 clip->start_pkt = clpi_lookup_spn(clip->cl, pi->in_time, 1,
00780 pi->clip[clip->angle].stc_id);
00781 clip->connection = CONNECT_NON_SEAMLESS;
00782 break;
00783 }
00784 clip->end_pkt = clpi_lookup_spn(clip->cl, pi->out_time, 0,
00785 pi->clip[clip->angle].stc_id);
00786 clip->in_time = pi->in_time;
00787 clip->out_time = pi->out_time;
00788 clip->pos = pos;
00789 pos += clip->end_pkt - clip->start_pkt;
00790 clip->start_time = time;
00791 time += clip->out_time - clip->in_time;
00792 }
00793 _extrapolate_title(title);
00794 return clip;
00795 }
00796