static MPLS_PL* _process_file(char *name, MPLS_PL *pl_list[], int pl_count) { MPLS_PL *pl; pl = bd_read_mpls(name); if (pl == NULL) { fprintf(stderr, "Parse failed: %s\n", name); return NULL; } if (seconds) { if (!_filter_short(pl, seconds)) { bd_free_mpls(pl); return NULL; } } if (repeats) { if (!_filter_repeats(pl, repeats)) { bd_free_mpls(pl); return NULL; } } if (dups) { if (!_filter_dup(pl_list, pl_count, pl)) { bd_free_mpls(pl); return NULL; } } if (verbose) { indent_printf(0, "%s -- Num Clips: %3d , Duration: minutes %4u:%02u", basename(name), pl->list_count, _pl_duration(pl) / (45000 * 60), (_pl_duration(pl) / 45000) % 60); _show_ai(pl, 1); } else { indent_printf(0, "%s -- Duration: minutes %4u:%02u", basename(name), _pl_duration(pl) / (45000 * 60), (_pl_duration(pl) / 45000) % 60); } if (playlist_info) { _show_details(pl, 1); } if (chapter_marks) { _show_marks(pl, 1); } if (pip_metadata) { _show_pip_metadata(pl, 1); } if (clip_list) { _show_clip_list(pl, 1); } if (sub_paths) { _show_sub_paths(pl, 1); _show_sub_paths_ss(pl, 1); } return pl; }
static int _filter_dup(MPLS_PL *pl_list[], int count, MPLS_PL *pl) { int ii, jj; for (ii = 0; ii < count; ii++) { if (pl->list_count != pl_list[ii]->list_count || _pl_duration(pl) != _pl_duration(pl_list[ii])) { continue; } for (jj = 0; jj < pl->list_count; jj++) { MPLS_PI *pi1, *pi2; pi1 = &pl->play_item[jj]; pi2 = &pl_list[ii]->play_item[jj]; if (memcmp(pi1->clip[0].clip_id, pi2->clip[0].clip_id, 5) != 0 || pi1->in_time != pi2->in_time || pi1->out_time != pi2->out_time) { break; } } if (jj != pl->list_count) { continue; } return 0; } return 1; }
static int _filter_short(MPLS_PL *pl, unsigned int seconds) { // Ignore short playlists if (_pl_duration(pl) / 45000 <= seconds) { return 0; } return 1; }
static int _pl_guess_main_title(MPLS_PL *p1, MPLS_PL *p2) { uint32_t d1 = _pl_duration(p1); uint32_t d2 = _pl_duration(p2); /* if both longer than 30 min */ if (d1 > 30*60*45000 && d2 > 30*60*45000) { /* prefer many chapters over no chapters */ int chap1 = _pl_chapter_count(p1); int chap2 = _pl_chapter_count(p2); int chap_diff = chap2 - chap1; if ((chap1 < 2 || chap2 < 2) && (chap_diff < -5 || chap_diff > 5)) { /* chapter count differs by more than 5 */ BD_DEBUG(DBG_MAIN_PL, "main title: chapter count difference %d\n", chap_diff); return chap_diff; } /* Check video: prefer HD over SD, H.264/VC1 over MPEG1/2 */ int vid_diff = _cmp_video_props(p1, p2); if (vid_diff) { BD_DEBUG(DBG_MAIN_PL, "main title: video properties difference %d\n", vid_diff); return vid_diff; } /* compare audio: prefer HD audio */ int aud_diff = _cmp_audio_props(p1, p2); if (aud_diff) { BD_DEBUG(DBG_MAIN_PL, "main title: audio properties difference %d\n", aud_diff); return aud_diff; } } /* compare playlist duration, select longer playlist */ if (d1 < d2) { return 1; } if (d1 > d2) { return -1; } return 0; }
char* nav_find_main_title(const char *root) { BD_DIR_H *dir; BD_DIRENT ent; char *path = NULL; MPLS_PL **pl_list = NULL; MPLS_PL **tmp = NULL; MPLS_PL *pl = NULL; unsigned count, ii, jj, pl_list_size = 0; int res; char longest[11]; BD_DEBUG(DBG_NAV, "Root: %s:\n", root); path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST", root); dir = dir_open(path); if (dir == NULL) { fprintf(stderr, "Failed to open dir: %s\n", path); X_FREE(path); return NULL; } X_FREE(path); ii = jj = 0; for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) { if (ent.d_name[0] == '.') { continue; } path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST" DIR_SEP "%s", root, ent.d_name); if (ii >= pl_list_size) { pl_list_size += 100; tmp = realloc(pl_list, pl_list_size * sizeof(MPLS_PL*)); if (tmp == NULL) { X_FREE(path); break; } pl_list = tmp; } pl = mpls_parse(path, 0); X_FREE(path); if (pl != NULL) { if (_filter_dup(pl_list, ii, pl) && _filter_repeats(pl, 2)) { pl_list[ii] = pl; if (_pl_duration(pl_list[ii]) >= _pl_duration(pl_list[jj])) { strncpy(longest, ent.d_name, 11); longest[10] = '\0'; jj = ii; } ii++; } else { mpls_free(pl); } } } dir_close(dir); count = ii; for (ii = 0; ii < count; ii++) { mpls_free(pl_list[ii]); } if (count > 0) { char *str = (char*)malloc(strlen(longest) + 1); strcpy(str, longest); return str; } else { return NULL; } }
NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags) { BD_DIR_H *dir; BD_DIRENT ent; char *path = NULL; MPLS_PL **pl_list = NULL; MPLS_PL *pl = NULL; unsigned int ii, pl_list_size = 0; int res; NAV_TITLE_LIST *title_list; unsigned int title_info_alloc = 100; title_list = calloc(1, sizeof(NAV_TITLE_LIST)); title_list->title_info = calloc(title_info_alloc, sizeof(NAV_TITLE_INFO)); BD_DEBUG(DBG_NAV, "Root: %s:\n", root); path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST", root); dir = dir_open(path); if (dir == NULL) { BD_DEBUG(DBG_NAV, "Failed to open dir: %s\n", path); X_FREE(path); X_FREE(title_list); return NULL; } X_FREE(path); ii = 0; for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) { if (ent.d_name[0] == '.') { continue; } path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST" DIR_SEP "%s", root, ent.d_name); if (ii >= pl_list_size) { MPLS_PL **tmp = NULL; pl_list_size += 100; tmp = realloc(pl_list, pl_list_size * sizeof(MPLS_PL*)); if (tmp == NULL) { X_FREE(path); break; } pl_list = tmp; } pl = mpls_parse(path, 0); X_FREE(path); if (pl != NULL) { if ((flags & TITLES_FILTER_DUP_TITLE) && !_filter_dup(pl_list, ii, pl)) { mpls_free(pl); continue; } if ((flags & TITLES_FILTER_DUP_CLIP) && !_filter_repeats(pl, 2)) { mpls_free(pl); continue; } if (ii >= title_info_alloc) { NAV_TITLE_INFO *tmp = NULL; title_info_alloc += 100; tmp = realloc(title_list->title_info, title_info_alloc * sizeof(NAV_TITLE_INFO)); if (tmp == NULL) { break; } title_list->title_info = tmp; } pl_list[ii] = pl; strncpy(title_list->title_info[ii].name, ent.d_name, 11); title_list->title_info[ii].name[10] = '\0'; title_list->title_info[ii].ref = ii; title_list->title_info[ii].mpls_id = atoi(ent.d_name); title_list->title_info[ii].duration = _pl_duration(pl_list[ii]); ii++; } } dir_close(dir); title_list->count = ii; for (ii = 0; ii < title_list->count; ii++) { mpls_free(pl_list[ii]); } return title_list; }
NAV_TITLE_LIST* nav_get_title_list(BD_DISC *disc, uint32_t flags, uint32_t min_title_length) { BD_DIR_H *dir; BD_DIRENT ent; MPLS_PL **pl_list = NULL; MPLS_PL *pl = NULL; unsigned int ii, pl_list_size = 0; int res; NAV_TITLE_LIST *title_list; unsigned int title_info_alloc = 100; dir = disc_open_dir(disc, "BDMV" DIR_SEP "PLAYLIST"); if (dir == NULL) { return NULL; } title_list = calloc(1, sizeof(NAV_TITLE_LIST)); title_list->title_info = calloc(title_info_alloc, sizeof(NAV_TITLE_INFO)); ii = 0; for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) { if (ent.d_name[0] == '.') { continue; } if (ii >= pl_list_size) { MPLS_PL **tmp = NULL; pl_list_size += 100; tmp = realloc(pl_list, pl_list_size * sizeof(MPLS_PL*)); if (tmp == NULL) { break; } pl_list = tmp; } pl = mpls_get(disc, ent.d_name); if (pl != NULL) { if ((flags & TITLES_FILTER_DUP_TITLE) && !_filter_dup(pl_list, ii, pl)) { mpls_free(pl); continue; } if ((flags & TITLES_FILTER_DUP_CLIP) && !_filter_repeats(pl, 2)) { mpls_free(pl); continue; } if (min_title_length > 0 && _pl_duration(pl) < min_title_length*45000) { mpls_free(pl); continue; } if (ii >= title_info_alloc) { NAV_TITLE_INFO *tmp = NULL; title_info_alloc += 100; tmp = realloc(title_list->title_info, title_info_alloc * sizeof(NAV_TITLE_INFO)); if (tmp == NULL) { break; } title_list->title_info = tmp; } pl_list[ii] = pl; /* main title guessing */ if (_filter_dup(pl_list, ii, pl) && _filter_repeats(pl, 2)) { if (_pl_guess_main_title(pl_list[ii], pl_list[title_list->main_title_idx]) <= 0) { title_list->main_title_idx = ii; } } strncpy(title_list->title_info[ii].name, ent.d_name, 11); title_list->title_info[ii].name[10] = '\0'; title_list->title_info[ii].ref = ii; title_list->title_info[ii].mpls_id = atoi(ent.d_name); title_list->title_info[ii].duration = _pl_duration(pl_list[ii]); ii++; } } dir_close(dir); title_list->count = ii; for (ii = 0; ii < title_list->count; ii++) { mpls_free(pl_list[ii]); } X_FREE(pl_list); return title_list; }
int BD_Parser(FILE *fp, FileInfo *finfo, int is_dir) { int nRet = 0; int ii; int title_guess, title_count; uint64_t max_duration = 0; uint64_t max_duration2 = 0; MPLS_PL * pl = NULL, * pl2 = NULL, * def_pl; BLURAY *bd = NULL; parse_priv * par_priv = NULL; BLURAY_TITLE_MAX_DUR *title_max = NULL; int title_id[2] = {-1}; int mpls_id[2] = {-1}; mp_msg("BD_Parser\n"); if (finfo->priv != NULL) { par_priv = (parse_priv *)finfo->priv; bd = par_priv->bd; title_count = par_priv->title_num; free(par_priv); finfo->priv = NULL; } else { bd = bd_open(finfo->filepath, NULL); if (bd) title_count = bd_get_titles(bd, TITLES_RELEVANT); } //goto error_end; if (bd) { title_max = bd_get_title_max2_dur(bd); if (title_max != NULL) { pl = bd_title_filter(bd, title_max->dur_first_count, title_max->dur_first, is_dir, finfo->filepath, &title_id[0], &mpls_id[0]); if (title_max->dur_second_count > 0) { pl2 = bd_title_filter(bd, title_max->dur_second_count, title_max->dur_second, is_dir, finfo->filepath, &title_id[1], &mpls_id[1]); } mp_msg("title_id: %d %d, mpls_id: %d %d\n", title_id[0], title_id[1], mpls_id[0], mpls_id[1]); title_guess = title_id[0]; bd_free_title_max2_dur(title_max); } def_pl = pl; //if (pl2 != NULL) if (pl2 != NULL && pl != NULL) { MPLS_PI *pi, *pi2; pi = &pl->play_item[0]; pi2 = &pl2->play_item[0]; mp_msg("playlist 1: c: %d, v: %d, a: %d, s: %d, d: %d\n", bd_get_chapters(pl), pi->stn.num_video, pi->stn.num_audio, pi->stn.num_pg, _pl_duration(pl)/45000); mp_msg("playlist 2: c: %d, v: %d, a: %d, s: %d, d: %d\n", bd_get_chapters(pl2), pi2->stn.num_video, pi2->stn.num_audio, pi2->stn.num_pg, _pl_duration(pl2)/45000); if ((bd_get_chapters(pl) < bd_get_chapters(pl2)) && (pi->stn.num_audio <= pi2->stn.num_audio) ) { // playlist 2 have more chapters and audio use it. def_pl = pl2; title_guess = title_id[1]; } else { if ((pl->list_count > 0) && (pl2->list_count > 0)) { if ( (pi2->stn.num_audio >= pi->stn.num_audio) && (pi2->stn.num_pg > pi->stn.num_pg) && (bd_get_chapters(pl2) >= bd_get_chapters(pl)) ) //Barry 2011-07-29 fix mantis: 5605 { def_pl = pl2; title_guess = title_id[1]; } #if 1 //Barry 2011-07-13 fix mantis: 5192 if ((_pl_duration(pl)/45000) > 60000) { def_pl = pl2; title_guess = title_id[1]; } #endif } } } else if (pl2 != NULL && pl == NULL) { // playlist 2 have more chapters and audio use it. def_pl = pl2; title_guess = title_id[1]; //printf("*********** Switch to playlist 2 **********\n"); } nRet = set_mpls_info(def_pl, finfo); if (nRet == 1) { MPLS_PI *pi; int chapters = bd_get_chapters(def_pl); ((bd_priv_t *)finfo->priv)->chapter_num = chapters; ((bd_priv_t *)finfo->priv)->title = title_guess; pi = &def_pl->play_item[0]; if (pi != NULL) ((bd_priv_t *)finfo->priv)->file_id = atoi(pi->clip[0].clip_id); } error_end: if (pl != NULL) mpls_free(pl); if (pl2 != NULL) mpls_free(pl2); if (bd != NULL) bd_close(bd); } return nRet; }
static MPLS_PL * bd_title_filter(BLURAY *bd, uint32_t count, BLURAY_TITLE_MPLS_ID *title, int is_dir, char *filepath, int *title_id, int *mpls_id) { MPLS_PL *pl = NULL, *pl_tmp = NULL; MPLS_PI *pi = NULL, *pi_tmp = NULL; int chapter_count, chapter_count_tmp; char *path = NULL; int ii; for (ii = 0; ii < count; ii++) { if (is_dir == 1) { path = str_printf("%s/BDMV/PLAYLIST/%05d.mpls", filepath, title[ii].mpls_id); } else { path = str_printf("/BDMV/PLAYLIST/%05d.mpls", title[ii].mpls_id); } if (pl == NULL) { pl = mpls_parse(path, 0, bd_get_udfdata(bd)); if (pl != NULL) { pi = &pl->play_item[0]; *title_id = (int)title[ii].title_id; *mpls_id = (int)title[ii].mpls_id; chapter_count = bd_get_chapters(pl); } } else { pl_tmp = mpls_parse(path, 0, bd_get_udfdata(bd)); if (pl_tmp != NULL) { pi_tmp = &pl_tmp->play_item[0]; chapter_count_tmp = bd_get_chapters(pl_tmp); mp_msg("filter playlist 1: c: %d, v: %d, a: %d, s: %d, d: %d\n", chapter_count, pi->stn.num_video, pi->stn.num_audio, pi->stn.num_pg, _pl_duration(pl)/45000); mp_msg("filter playlist 2: c: %d, v: %d, a: %d, s: %d, d: %d\n", chapter_count_tmp, pi_tmp->stn.num_video, pi_tmp->stn.num_audio, pi_tmp->stn.num_pg, _pl_duration(pl_tmp)/45000); if ( ((pi_tmp->stn.num_pg > 0) && (pi->stn.num_pg > pi_tmp->stn.num_pg)) && \ ((pi_tmp->stn.num_audio > 0) && (pi_tmp->stn.num_audio >= pi->stn.num_audio - 1)) && \ (chapter_count_tmp >= chapter_count) ) { mpls_free(pl); pl = pl_tmp; pi = &pl->play_item[0]; chapter_count = chapter_count_tmp; *title_id = (int)title[ii].title_id; *mpls_id = (int)title[ii].mpls_id; } else { #if 1 //Barry 2011-07-13 fix mantis: 5192 if ((_pl_duration(pl)/45000) > 60000) { mpls_free(pl); pl = pl_tmp; pi = &pl->play_item[0]; chapter_count = chapter_count_tmp; *title_id = (int)title[ii].title_id; *mpls_id = (int)title[ii].mpls_id; } else #endif mpls_free(pl_tmp); } } } if (path != NULL) free(path); } return pl; }
static int set_mpls_info(MPLS_PL *pl, FileInfo *finfo) { int nRet = 0; int ii, jj; MPLS_PI *pi = NULL; MPLS_STREAM *ss; bd_priv_t *bd_priv; finfo->priv = calloc(1, sizeof(bd_priv_t)); if (finfo->priv == NULL) { mp_msg("malloc priv data error!!!"); return nRet; } bd_priv = (bd_priv_t *)finfo->priv; #if 1 //for (ii = 0; ii < pl->list_count; ii++) { for (ii = 0; ii < 1; ii++) { pi = &pl->play_item[ii]; // video bd_priv->video_num = pi->stn.num_video; bd_priv->video_list = (list_priv_t *)calloc(1, sizeof(list_priv_t) * bd_priv->video_num); for (jj = 0; jj < pi->stn.num_video; jj++) { mp_msg("Video Stream %d:\n", jj); //_show_stream(&pi->stn.video[jj]); bd_priv->video_list[jj].sid = pi->stn.video[jj].pid; bd_priv->video_list[jj].type = pi->stn.video[jj].coding_type; } // audio bd_priv->audio_num = pi->stn.num_audio; bd_priv->audio_list = (list_priv_t *)calloc(1, sizeof(list_priv_t) * bd_priv->audio_num); for (jj = 0; jj < pi->stn.num_audio; jj++) { mp_msg("Audio Stream %d:\n", jj); //_show_stream(&pi->stn.audio[jj]); bd_priv->audio_list[jj].sid = pi->stn.audio[jj].pid; bd_priv->audio_list[jj].type = pi->stn.audio[jj].coding_type; bd_priv->audio_list[jj].format = pi->stn.audio[jj].format; memcpy(bd_priv->audio_list[jj].lang ,pi->stn.audio[jj].lang, 4); } // subtitle //bd_priv->sub_num = pi->stn.num_pg + pi->stn.num_pip_pg; bd_priv->sub_num = pi->stn.num_pg; bd_priv->sub_list = (list_priv_t *)calloc(1, sizeof(list_priv_t) * bd_priv->sub_num); for (jj = 0; jj < bd_priv->sub_num; jj++) { if (jj < pi->stn.num_pg) { mp_msg("Presentation Graphics Stream %d:\n", jj); } else { mp_msg("PIP Presentation Graphics Stream %d:\n", jj); } //_show_stream(&pi->stn.pg[jj]); bd_priv->sub_list[jj].sid = pi->stn.pg[jj].pid; bd_priv->sub_list[jj].type = pi->stn.pg[jj].coding_type; memcpy(bd_priv->sub_list[jj].lang ,pi->stn.pg[jj].lang, 4); } } #endif if (pl->list_count > 0) pi = &pl->play_item[0]; if (pi != NULL) { if (pi->stn.num_video > 0) { ss = &pi->stn.video[0]; //_show_stream(ss); if (_set_video_stream(finfo, ss)) { finfo->bVideo = 1; } } for (ii = 0; ii < pi->stn.num_audio; ii++) { ss = &pi->stn.audio[ii]; //_show_stream(ss); if (_set_audio_stream(finfo, ss)) { if (check_audio_type(finfo->AudioType, finfo->wf.nChannels, finfo->hw_a_flag) != 0) { finfo->bAudio = 1; break; } } } if (finfo->bVideo || finfo->bAudio) nRet = 1; } if (nRet == 0) { if (finfo->priv != NULL) free(finfo->priv); } finfo->FileDuration = _pl_duration(pl) / 45000; return nRet; }