X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fdvdnav.c;h=5f30dedf06d1f83d2504b81560b090cc7c908d28;hb=4b72a63eb61a01275493c4bfb51ba02152d1c5e1;hp=a1a8da472777769cd9b8b84aa2d2c67240ad1dff;hpb=2d0e6c375b8dfd89d66b05128be8b2c236834b57;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/dvdnav.c b/libhb/dvdnav.c index a1a8da47..5f30dedf 100644 --- a/libhb/dvdnav.c +++ b/libhb/dvdnav.c @@ -18,7 +18,7 @@ static char * hb_dvdnav_name( char * path ); static hb_dvd_t * hb_dvdnav_init( char * path ); static int hb_dvdnav_title_count( hb_dvd_t * d ); -static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * d, int t ); +static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * d, int t, uint64_t min_duration ); static int hb_dvdnav_start( hb_dvd_t * d, hb_title_t *title, int chapter ); static void hb_dvdnav_stop( hb_dvd_t * d ); static int hb_dvdnav_seek( hb_dvd_t * d, float f ); @@ -289,7 +289,7 @@ PttDuration(ifo_handle_t *ifo, int ttn, int pttn, int *blocks, int *last_pgcn) /*********************************************************************** * hb_dvdnav_title_scan **********************************************************************/ -static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t ) +static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_duration ) { hb_dvdnav_t * d = &(e->dvdnav); @@ -418,7 +418,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t ) /* ignore titles under 10 seconds because they're often stills or * clips with no audio & our preview code doesn't currently handle * either of these. */ - if( longest < 900000LL ) + if( longest < min_duration ) { hb_log( "scan: ignoring title (too short)" ); goto fail; @@ -456,8 +456,8 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t ) title->cell_end = pgc->nr_of_cells - 1; title->block_end = pgc->cell_playback[title->cell_end].last_sector; - hb_log( "scan: vts=%d, ttn=%d, cells=%d->%d, blocks=%d->%d, " - "%d blocks", title->vts, title->ttn, title->cell_start, + hb_log( "scan: vts=%d, ttn=%d, cells=%d->%d, blocks=%"PRIu64"->%"PRIu64", " + "%"PRIu64" blocks", title->vts, title->ttn, title->cell_start, title->cell_end, title->block_start, title->block_end, title->block_count ); @@ -591,10 +591,6 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t ) hb_list_add( title->list_audio, audio ); } - memcpy( title->palette, - ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette, - 16 * sizeof( uint32_t ) ); - /* Check for subtitles */ for( i = 0; i < ifo->vtsi_mat->nr_of_vts_subp_streams; i++ ) { @@ -650,6 +646,10 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t ) subtitle->config.dest = RENDERSUB; // By default render (burn-in) the VOBSUB. subtitle->type = lang_extension; + + memcpy( subtitle->palette, + ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette, + 16 * sizeof( uint32_t ) ); switch( lang_extension ) { @@ -782,7 +782,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t ) chapter->minutes = ( seconds % 3600 ) / 60; chapter->seconds = seconds % 60; - hb_log( "scan: chap %d c=%d->%d, b=%d->%d (%d), %"PRId64" ms", + hb_log( "scan: chap %d c=%d->%d, b=%"PRIu64"->%"PRIu64" (%"PRIu64"), %"PRId64" ms", chapter->index, chapter->cell_start, chapter->cell_end, chapter->block_start, chapter->block_end, chapter->block_count, chapter->duration / 90 ); @@ -835,11 +835,83 @@ static int find_title( hb_list_t * list_title, int title ) return -1; } +static void skip_some( dvdnav_t * dvdnav, int blocks ) +{ + int ii; + int result, event, len; + uint8_t buf[HB_DVD_READ_BUFFER_SIZE]; + + for ( ii = 0; ii < blocks; ii++ ) + { + result = dvdnav_get_next_block( dvdnav, buf, &event, &len ); + if ( result == DVDNAV_STATUS_ERR ) + { + hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(dvdnav)); + return; + } + switch ( event ) + { + case DVDNAV_BLOCK_OK: + break; + + case DVDNAV_CELL_CHANGE: + { + } break; + + case DVDNAV_STILL_FRAME: + dvdnav_still_skip( dvdnav ); + break; + + case DVDNAV_WAIT: + dvdnav_wait_skip( dvdnav ); + break; + + case DVDNAV_STOP: + return; + + case DVDNAV_HOP_CHANNEL: + break; + + case DVDNAV_NAV_PACKET: + break; + + case DVDNAV_VTS_CHANGE: + { + dvdnav_vts_change_event_t *event; + event = (dvdnav_vts_change_event_t*)buf; + // Some discs initialize the vts with the "first play" item + // and some don't seem to. So if we see it is uninitialized, + // set it. + if ( event->new_vtsN <= 0 ) + result = dvdnav_title_play( dvdnav, 1 ); + } break; + + case DVDNAV_HIGHLIGHT: + break; + + case DVDNAV_AUDIO_STREAM_CHANGE: + break; + + case DVDNAV_SPU_STREAM_CHANGE: + break; + + case DVDNAV_SPU_CLUT_CHANGE: + break; + + case DVDNAV_NOP: + break; + + default: + break; + } + } +} + static int try_button( dvdnav_t * dvdnav, int menu_id, int button, hb_list_t * list_title ) { int result, event, len; uint8_t buf[HB_DVD_READ_BUFFER_SIZE]; - int ii; + int ii, jj; int32_t cur_title, title, pgcn, pgn; uint64_t longest_duration = 0; int longest = -1; @@ -878,292 +950,292 @@ static int try_button( dvdnav_t * dvdnav, int menu_id, int button, hb_list_t * l } cur_title = title; - for (ii = 0; ii < 8000; ii++) + for (jj = 0; jj < 5; jj++) { - result = dvdnav_get_next_block( dvdnav, buf, &event, &len ); - if ( result == DVDNAV_STATUS_ERR ) - { - hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(dvdnav)); - return 0; - } - switch ( event ) + for (ii = 0; ii < 2000; ii++) { - case DVDNAV_BLOCK_OK: - break; + result = dvdnav_get_next_block( dvdnav, buf, &event, &len ); + if ( result == DVDNAV_STATUS_ERR ) + { + hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(dvdnav)); + return 0; + } + switch ( event ) + { + case DVDNAV_BLOCK_OK: + break; - case DVDNAV_CELL_CHANGE: - { - result = dvdnav_current_title_program( dvdnav, &title, &pgcn, &pgn ); - if (result != DVDNAV_STATUS_OK) - hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(dvdnav)); - if ( title != cur_title && title > 0 ) + case DVDNAV_CELL_CHANGE: { - hb_title_t * hbtitle; - int index; - index = find_title( list_title, title ); - hbtitle = hb_list_item( list_title, index ); - if ( hbtitle != NULL ) + result = dvdnav_current_title_program( dvdnav, &title, &pgcn, &pgn ); + if (result != DVDNAV_STATUS_OK) + hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(dvdnav)); + + if ( title != cur_title && title > 0 ) { - if ( hbtitle->duration > longest_duration ) + hb_title_t * hbtitle; + int index; + index = find_title( list_title, title ); + hbtitle = hb_list_item( list_title, index ); + if ( hbtitle != NULL ) { - longest_duration = hbtitle->duration; - longest = title; + if ( hbtitle->duration > longest_duration ) + { + longest_duration = hbtitle->duration; + longest = title; + } + } + // If the duration is longer than 10min, assume + // this isn't garbage leading to something bigger. + if ( longest_duration / 90000 > 10 * 60 ) + { + return longest; } - } - // If the duration is longer than 10min, assume - // this isn't garbage leading to something bigger. - if ( longest_duration / 90000 > 10 * 60 ) - { - return longest; } cur_title = title; - } - if (title > 0) - { - result = dvdnav_next_pg_search( dvdnav ); - if ( result != DVDNAV_STATUS_OK ) - { - return longest; - } - int next_title, next_pgcn, next_pgn; - dvdnav_current_title_program( dvdnav, &next_title, &next_pgcn, &next_pgn ); - if (title == next_title && pgcn == next_pgcn && pgn == next_pgn) + if (title > 0) { - return longest; + result = dvdnav_next_pg_search( dvdnav ); + if ( result != DVDNAV_STATUS_OK ) + { + return longest; + } } - } - } break; + } break; - case DVDNAV_STILL_FRAME: - dvdnav_still_skip( dvdnav ); - break; + case DVDNAV_STILL_FRAME: + dvdnav_still_skip( dvdnav ); + break; - case DVDNAV_WAIT: - dvdnav_wait_skip( dvdnav ); - break; + case DVDNAV_WAIT: + dvdnav_wait_skip( dvdnav ); + break; - case DVDNAV_STOP: - hb_log("dvdnav: stop encountered during seek"); - return 0; + case DVDNAV_STOP: + return 0; - case DVDNAV_HOP_CHANNEL: - break; + case DVDNAV_HOP_CHANNEL: + break; - case DVDNAV_NAV_PACKET: - { - } break; + case DVDNAV_NAV_PACKET: + { + } break; - case DVDNAV_VTS_CHANGE: - { - result = dvdnav_current_title_program( dvdnav, &title, &pgcn, &pgn ); - if (result != DVDNAV_STATUS_OK) - hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(dvdnav)); - if ( title != cur_title && title > 0 ) + case DVDNAV_VTS_CHANGE: { - hb_title_t * hbtitle; - int index; - index = find_title( list_title, title ); - hbtitle = hb_list_item( list_title, index ); - if ( hbtitle != NULL ) + result = dvdnav_current_title_program( dvdnav, &title, &pgcn, &pgn ); + if (result != DVDNAV_STATUS_OK) + hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(dvdnav)); + + if ( title != cur_title && title > 0 ) { - if ( hbtitle->duration > longest_duration ) + hb_title_t * hbtitle; + int index; + index = find_title( list_title, title ); + hbtitle = hb_list_item( list_title, index ); + if ( hbtitle != NULL ) { - longest_duration = hbtitle->duration; - longest = title; + if ( hbtitle->duration > longest_duration ) + { + longest_duration = hbtitle->duration; + longest = title; + } + } + if ( longest_duration / 90000 > 10 * 60 ) + { + return longest; } } cur_title = title; - if ( longest_duration / 90000 > 10 * 60 ) - { - return longest; - } - } - if ( title > 0 ) - { - dvdnav_next_pg_search( dvdnav ); - } - } break; + } break; - case DVDNAV_HIGHLIGHT: - break; + case DVDNAV_HIGHLIGHT: + break; - case DVDNAV_AUDIO_STREAM_CHANGE: - break; + case DVDNAV_AUDIO_STREAM_CHANGE: + break; - case DVDNAV_SPU_STREAM_CHANGE: - break; + case DVDNAV_SPU_STREAM_CHANGE: + break; - case DVDNAV_SPU_CLUT_CHANGE: - break; + case DVDNAV_SPU_CLUT_CHANGE: + break; - case DVDNAV_NOP: - break; + case DVDNAV_NOP: + break; - default: - break; + default: + break; + } + } + if (cur_title > 0) + { + // Some titles have long lead-ins. Try skipping it. + dvdnav_next_pg_search( dvdnav ); } } return longest; } -static int try_menu( hb_dvdnav_t * d, hb_list_t * list_title, DVDMenuID_t menu ) +static int try_menu( + hb_dvdnav_t * d, + hb_list_t * list_title, + DVDMenuID_t menu, + uint64_t fallback_duration ) { int result, event, len; uint8_t buf[HB_DVD_READ_BUFFER_SIZE]; - int ii; + int ii, jj; int32_t cur_title, title, pgcn, pgn; uint64_t longest_duration = 0; int longest = -1; - dvdnav_reset( d->dvdnav ); - result = dvdnav_title_play( d->dvdnav, 1 ); - if ( result == DVDNAV_STATUS_ERR ) - { - hb_error("dvdnav: Can not set title, %s", dvdnav_err_to_string(d->dvdnav)); - goto done; - } + result = dvdnav_menu_call( d->dvdnav, menu ); if ( result != DVDNAV_STATUS_OK ) { - hb_error("dvdnav: Can not set dvd menu, %s", dvdnav_err_to_string(d->dvdnav)); - goto done; + // Sometimes the "first play" item doesn't initialize the + // initial VTS. So do it here. + result = dvdnav_title_play( d->dvdnav, 1 ); + result = dvdnav_menu_call( d->dvdnav, menu ); + if ( result != DVDNAV_STATUS_OK ) + { + hb_error("dvdnav: Can not set dvd menu, %s", dvdnav_err_to_string(d->dvdnav)); + goto done; + } } - result = dvdnav_current_title_program( d->dvdnav, &cur_title, &pgcn, &pgn ); + result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn ); if (result != DVDNAV_STATUS_OK) hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav)); - // Hit the root menu again to see if we can force - // our way to the main menu. - dvdnav_next_pg_search( d->dvdnav ); - result = dvdnav_menu_call( d->dvdnav, menu ); - - dvdnav_next_pg_search( d->dvdnav ); - result = dvdnav_menu_call( d->dvdnav, menu ); - - if ( cur_title > 0 ) - { - dvdnav_next_pg_search( d->dvdnav ); - } + cur_title = title; - for (ii = 0; ii < 5000; ii++) + for (jj = 0; jj < 4; jj++) { - result = dvdnav_get_next_block( d->dvdnav, buf, &event, &len ); - if ( result == DVDNAV_STATUS_ERR ) + for (ii = 0; ii < 4000; ii++) { - hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav)); - goto done; - } - switch ( event ) - { - case DVDNAV_BLOCK_OK: - break; - - case DVDNAV_CELL_CHANGE: - { - result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn ); - if (result != DVDNAV_STATUS_OK) - hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav)); - cur_title = title; - if ( title > 0 ) + result = dvdnav_get_next_block( d->dvdnav, buf, &event, &len ); + if ( result == DVDNAV_STATUS_ERR ) { - dvdnav_next_pg_search( d->dvdnav ); + hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav)); + goto done; } - } break; + switch ( event ) + { + case DVDNAV_BLOCK_OK: + break; - case DVDNAV_STILL_FRAME: - dvdnav_still_skip( d->dvdnav ); - break; + case DVDNAV_CELL_CHANGE: + { + result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn ); + if (result != DVDNAV_STATUS_OK) + hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav)); + cur_title = title; + } break; - case DVDNAV_WAIT: - dvdnav_wait_skip( d->dvdnav ); - break; + case DVDNAV_STILL_FRAME: + dvdnav_still_skip( d->dvdnav ); + break; - case DVDNAV_STOP: - hb_log("dvdnav: stop encountered during seek"); - d->stopped = 1; - goto done; + case DVDNAV_WAIT: + dvdnav_wait_skip( d->dvdnav ); + break; - case DVDNAV_HOP_CHANNEL: - break; + case DVDNAV_STOP: + goto done; - case DVDNAV_NAV_PACKET: - { - pci_t *pci = dvdnav_get_current_nav_pci( d->dvdnav ); - int kk; - int buttons; - if ( pci == NULL ) break; + case DVDNAV_HOP_CHANNEL: + break; - buttons = pci->hli.hl_gi.btn_ns; - if ( cur_title == 0 && buttons > 0 ) + case DVDNAV_NAV_PACKET: { - int menu_title, menu_id; - result = dvdnav_current_title_info( d->dvdnav, &menu_title, &menu_id ); - if (result != DVDNAV_STATUS_OK) - hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav)); - for (kk = 0; kk < buttons; kk++) - { - dvdnav_t *dvdnav_copy; + pci_t *pci = dvdnav_get_current_nav_pci( d->dvdnav ); + int kk; + int buttons; + if ( pci == NULL ) break; - result = dvdnav_dup( &dvdnav_copy, d->dvdnav ); + buttons = pci->hli.hl_gi.btn_ns; + if ( cur_title == 0 && buttons > 1 ) + { + int menu_title, menu_id; + result = dvdnav_current_title_info( d->dvdnav, &menu_title, &menu_id ); if (result != DVDNAV_STATUS_OK) + hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav)); + for (kk = 0; kk < buttons; kk++) { - hb_log("dvdnav dup failed: %s", dvdnav_err_to_string(d->dvdnav)); - goto done; - } - title = try_button( dvdnav_copy, menu_id, kk, list_title ); - dvdnav_free_dup( dvdnav_copy ); + dvdnav_t *dvdnav_copy; - if ( title >= 0 ) - { - hb_title_t * hbtitle; - int index; - index = find_title( list_title, title ); - hbtitle = hb_list_item( list_title, index ); - if ( hbtitle != NULL ) + result = dvdnav_dup( &dvdnav_copy, d->dvdnav ); + if (result != DVDNAV_STATUS_OK) { - if ( hbtitle->duration > longest_duration ) + hb_log("dvdnav dup failed: %s", dvdnav_err_to_string(d->dvdnav)); + goto done; + } + title = try_button( dvdnav_copy, menu_id, kk, list_title ); + dvdnav_free_dup( dvdnav_copy ); + + if ( title >= 0 ) + { + hb_title_t * hbtitle; + int index; + index = find_title( list_title, title ); + hbtitle = hb_list_item( list_title, index ); + if ( hbtitle != NULL ) { - longest_duration = hbtitle->duration; - longest = title; + if ( hbtitle->duration > longest_duration ) + { + longest_duration = hbtitle->duration; + longest = title; + if ((float)fallback_duration * 0.75 < longest_duration) + goto done; + } } } } + goto done; } - goto done; - } - } break; + if ( cur_title == 0 && buttons == 1 ) + { + dvdnav_button_select_and_activate( d->dvdnav, pci, 1 ); + } + } break; - case DVDNAV_VTS_CHANGE: - { - result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn ); - if (result != DVDNAV_STATUS_OK) - hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav)); - cur_title = title; - if ( title > 0 ) + case DVDNAV_VTS_CHANGE: { - dvdnav_next_pg_search( d->dvdnav ); - } - } break; + result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn ); + if (result != DVDNAV_STATUS_OK) + hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav)); + cur_title = title; + } break; - case DVDNAV_HIGHLIGHT: - break; + case DVDNAV_HIGHLIGHT: + break; - case DVDNAV_AUDIO_STREAM_CHANGE: - break; + case DVDNAV_AUDIO_STREAM_CHANGE: + break; - case DVDNAV_SPU_STREAM_CHANGE: - break; + case DVDNAV_SPU_STREAM_CHANGE: + break; - case DVDNAV_SPU_CLUT_CHANGE: - break; + case DVDNAV_SPU_CLUT_CHANGE: + break; - case DVDNAV_NOP: - break; + case DVDNAV_NOP: + break; - default: - break; + default: + break; + } } + // Sometimes the menu is preceeded by a intro that just + // gets restarted when hitting the menu button. So + // try skipping with the skip forward button. Then + // try hitting the menu again. + if ( !(jj & 1) ) + dvdnav_next_pg_search( d->dvdnav ); + else + result = dvdnav_menu_call( d->dvdnav, menu ); } done: @@ -1174,8 +1246,8 @@ static int hb_dvdnav_main_feature( hb_dvd_t * e, hb_list_t * list_title ) { hb_dvdnav_t * d = &(e->dvdnav); int longest_root; - int longest_title; - int longest_fallback; + int longest_title = 0; + int longest_fallback = 0; int ii; uint64_t longest_duration_root = 0; uint64_t longest_duration_title = 0; @@ -1191,7 +1263,10 @@ static int hb_dvdnav_main_feature( hb_dvd_t * e, hb_list_t * list_title ) } } - longest_root = try_menu( d, list_title, DVD_MENU_Root ); + dvdnav_reset( d->dvdnav ); + skip_some( d->dvdnav, 500 ); + + longest_root = try_menu( d, list_title, DVD_MENU_Root, longest_duration_fallback ); if ( longest_root >= 0 ) { hb_title_t * hbtitle; @@ -1204,7 +1279,7 @@ static int hb_dvdnav_main_feature( hb_dvd_t * e, hb_list_t * list_title ) if ( longest_root < 0 || (float)longest_duration_fallback * 0.7 > longest_duration_root) { - longest_title = try_menu( d, list_title, DVD_MENU_Title ); + longest_title = try_menu( d, list_title, DVD_MENU_Title, longest_duration_fallback ); if ( longest_title >= 0 ) { hb_title_t * hbtitle;