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