Changeset 1488bab


Ignore:
Timestamp:
07/10/11 21:45:25 (5 years ago)
Author:
jstebbins <jstebbins.hb@…>
Branches:
master
Children:
bbc5fc7
Parents:
71f634b
Message:

libhb: improve dvdnav main feature detection
Add detection of fake menus. Some menus have very short duration and/or
are hidden from the user by making the hightlight transparent. These
menus can lead to invalid titles if traversed, so ignore them.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4096 b64f7644-9d1e-0410-96f1-a4d463321fa5

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libhb/dvdnav.c

    r71f634b r1488bab  
    834834}
    835835
    836 static void skip_some( dvdnav_t * dvdnav, int blocks )
     836static int skip_to_menu( dvdnav_t * dvdnav, int blocks )
    837837{
    838838    int ii;
     
    846846        {
    847847            hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(dvdnav));
    848             return;
     848            return 0;
    849849        }
    850850        switch ( event )
     
    858858
    859859        case DVDNAV_STILL_FRAME:
     860        {
     861            dvdnav_still_event_t *event;
     862            event = (dvdnav_still_event_t*)buf;
    860863            dvdnav_still_skip( dvdnav );
    861             break;
     864            if ( event->length == 255 )
     865            {
     866                // Infinite still. Can't be the main feature unless
     867                // you like watching paint dry.
     868                return 0;
     869            }
     870        } break;
    862871
    863872        case DVDNAV_WAIT:
     
    866875
    867876        case DVDNAV_STOP:
    868             return;
     877            return 0;
    869878
    870879        case DVDNAV_HOP_CHANNEL:
     
    872881
    873882        case DVDNAV_NAV_PACKET:
    874             break;
     883        {
     884            pci_t *pci = dvdnav_get_current_nav_pci( dvdnav );
     885            if ( pci == NULL ) break;
     886
     887            int buttons = pci->hli.hl_gi.btn_ns;
     888
     889            int title, part;
     890            result = dvdnav_current_title_info( dvdnav, &title, &part );
     891            if (result != DVDNAV_STATUS_OK)
     892            {
     893                hb_log("dvdnav title info: %s", dvdnav_err_to_string(dvdnav));
     894            }
     895            else if ( title == 0 && buttons > 0 )
     896            {
     897                // Check button activation duration to see if this
     898                // isn't another fake menu.
     899                if ( pci->hli.hl_gi.btn_se_e_ptm - pci->hli.hl_gi.hli_s_ptm >
     900                     15 * 90000 )
     901                {
     902                    // Found what appears to be a good menu.
     903                    return 1;
     904                }
     905            }
     906        } break;
    875907
    876908        case DVDNAV_VTS_CHANGE:
     
    904936        }
    905937    }
    906 }
    907 
    908 static int try_button( dvdnav_t * dvdnav, int menu_id, int button, hb_list_t * list_title )
     938    return 0;
     939}
     940
     941static int try_button( dvdnav_t * dvdnav, int button, hb_list_t * list_title )
    909942{
    910943    int result, event, len;
    911944    uint8_t buf[HB_DVD_READ_BUFFER_SIZE];
    912945    int ii, jj;
    913     int32_t cur_title = 0, title, pgcn, pgn;
     946    int32_t cur_title = 0, title, part;
    914947    uint64_t longest_duration = 0;
    915948    int longest = -1;
     
    923956    }
    924957
    925     result = dvdnav_current_title_program( dvdnav, &title, &pgcn, &pgn );
     958    result = dvdnav_current_title_info( dvdnav, &title, &part );
    926959    if (result != DVDNAV_STATUS_OK)
    927         hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(dvdnav));
    928 
    929     if ( title > 0 )
    930     {
    931         hb_title_t * hbtitle;
    932         int index;
    933         index = find_title( list_title, title );
    934         hbtitle = hb_list_item( list_title, index );
    935         if ( hbtitle != NULL )
    936         {
    937             if ( hbtitle->duration > longest_duration )
    938             {
    939                 longest_duration = hbtitle->duration;
    940                 longest = title;
    941             }
    942         }
    943         cur_title = title;
    944     }
     960        hb_log("dvdnav cur title info: %s", dvdnav_err_to_string(dvdnav));
     961
     962    cur_title = title;
    945963
    946964    for (jj = 0; jj < 5; jj++)
     
    952970            {
    953971                hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(dvdnav));
    954                 return -1;
     972                goto done;
    955973            }
    956974            switch ( event )
     
    961979            case DVDNAV_CELL_CHANGE:
    962980            {
    963                 result = dvdnav_current_title_program( dvdnav, &title, &pgcn, &pgn );
     981                result = dvdnav_current_title_info( dvdnav, &title, &part );
    964982                if (result != DVDNAV_STATUS_OK)
    965                     hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(dvdnav));
    966 
    967                 if ( title != cur_title && title > 0 )
    968                 {
    969                     hb_title_t * hbtitle;
    970                     int index;
    971                     index = find_title( list_title, title );
    972                     hbtitle = hb_list_item( list_title, index );
    973                     if ( hbtitle != NULL )
    974                     {
    975                         if ( hbtitle->duration > longest_duration )
    976                         {
    977                             longest_duration = hbtitle->duration;
    978                             longest = title;
    979                         }
    980                     }
    981                     cur_title = title;
    982                 }
     983                    hb_log("dvdnav title info: %s", dvdnav_err_to_string(dvdnav));
     984
     985                cur_title = title;
    983986                // Note, some "fake" titles have long advertised durations
    984987                // but then jump to the real title early in playback.
     
    988991
    989992            case DVDNAV_STILL_FRAME:
     993            {
     994                dvdnav_still_event_t *event;
     995                event = (dvdnav_still_event_t*)buf;
    990996                dvdnav_still_skip( dvdnav );
    991                 break;
     997                if ( event->length == 255 )
     998                {
     999                    // Infinite still. Can't be the main feature unless
     1000                    // you like watching paint dry.
     1001                    goto done;
     1002                }
     1003            } break;
    9921004
    9931005            case DVDNAV_WAIT:
     
    9961008
    9971009            case DVDNAV_STOP:
    998                 return -1;
     1010                goto done;
    9991011
    10001012            case DVDNAV_HOP_CHANNEL:
     
    10071019            case DVDNAV_VTS_CHANGE:
    10081020            {
    1009                 result = dvdnav_current_title_program( dvdnav, &title, &pgcn, &pgn );
     1021                result = dvdnav_current_title_info( dvdnav, &title, &part );
    10101022                if (result != DVDNAV_STATUS_OK)
    1011                     hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(dvdnav));
    1012 
    1013                 if ( title != cur_title && title > 0 )
    1014                 {
    1015                     hb_title_t * hbtitle;
    1016                     int index;
    1017                     index = find_title( list_title, title );
    1018                     hbtitle = hb_list_item( list_title, index );
    1019                     if ( hbtitle != NULL )
    1020                     {
    1021                         if ( hbtitle->duration > longest_duration )
    1022                         {
    1023                             longest_duration = hbtitle->duration;
    1024                             longest = title;
    1025                         }
    1026                     }
    1027                     cur_title = title;
    1028                 }
     1023                    hb_log("dvdnav title info: %s", dvdnav_err_to_string(dvdnav));
     1024
     1025                cur_title = title;
    10291026                // Note, some "fake" titles have long advertised durations
    10301027                // but then jump to the real title early in playback.
     
    10691066                    return cur_title;
    10701067                }
     1068                if ( hbtitle->duration > longest_duration )
     1069                {
     1070                    longest_duration = hbtitle->duration;
     1071                    longest = title;
     1072                }
    10711073            }
    1072         }
    1073         if (cur_title > 0)
    1074         {
    10751074            // Some titles have long lead-ins. Try skipping it.
    10761075            dvdnav_next_pg_search( dvdnav );
    10771076        }
    10781077    }
     1078
     1079done:
    10791080    if ( longest != -1 )
    10801081    {
     
    11021103    uint8_t buf[HB_DVD_READ_BUFFER_SIZE];
    11031104    int ii, jj;
    1104     int32_t cur_title, title, pgcn, pgn;
     1105    int32_t cur_title, title, part;
    11051106    uint64_t longest_duration = 0;
    11061107    int longest = -1;
    11071108
    1108 
    1109     result = dvdnav_menu_call( d->dvdnav, menu );
    1110     if ( result != DVDNAV_STATUS_OK )
    1111     {
    1112         // Sometimes the "first play" item doesn't initialize the
    1113         // initial VTS. So do it here.
    1114         result = dvdnav_title_play( d->dvdnav, 1 );
     1109    // A bit of a hack here.  Abusing Escape menu to mean use whatever
     1110    // current menu is already set.
     1111    if ( menu != DVD_MENU_Escape )
     1112    {
    11151113        result = dvdnav_menu_call( d->dvdnav, menu );
    11161114        if ( result != DVDNAV_STATUS_OK )
    11171115        {
    1118             hb_error("dvdnav: Can not set dvd menu, %s", dvdnav_err_to_string(d->dvdnav));
    1119             goto done;
    1120         }
    1121     }
    1122 
    1123     result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn );
     1116            // Sometimes the "first play" item doesn't initialize the
     1117            // initial VTS. So do it here.
     1118            result = dvdnav_title_play( d->dvdnav, 1 );
     1119            result = dvdnav_menu_call( d->dvdnav, menu );
     1120            if ( result != DVDNAV_STATUS_OK )
     1121            {
     1122                hb_error("dvdnav: Can not set dvd menu, %s", dvdnav_err_to_string(d->dvdnav));
     1123                goto done;
     1124            }
     1125        }
     1126    }
     1127
     1128    result = dvdnav_current_title_info( d->dvdnav, &title, &part );
    11241129    if (result != DVDNAV_STATUS_OK)
    1125         hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav));
     1130        hb_log("dvdnav title info: %s", dvdnav_err_to_string(d->dvdnav));
    11261131
    11271132    cur_title = title;
     
    11441149            case DVDNAV_CELL_CHANGE:
    11451150            {
    1146                 result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn );
     1151                result = dvdnav_current_title_info( d->dvdnav, &title, &part );
    11471152                if (result != DVDNAV_STATUS_OK)
    1148                     hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav));
     1153                    hb_log("dvdnav title info: %s", dvdnav_err_to_string(d->dvdnav));
    11491154                cur_title = title;
    11501155            } break;
    11511156
    11521157            case DVDNAV_STILL_FRAME:
     1158            {
     1159                dvdnav_still_event_t *event;
     1160                event = (dvdnav_still_event_t*)buf;
    11531161                dvdnav_still_skip( d->dvdnav );
    1154                 break;
     1162                if ( event->length == 255 )
     1163                {
     1164                    // Infinite still.  There won't be any menus after this.
     1165                    goto done;
     1166                }
     1167            } break;
    11551168
    11561169            case DVDNAV_WAIT:
     
    11721185
    11731186                buttons = pci->hli.hl_gi.btn_ns;
    1174                 if ( cur_title == 0 && buttons > 1 )
     1187
     1188                // If we are on a menu that has buttons and
     1189                // the button activation duration is long enough
     1190                // that this isn't another fake menu.
     1191                if ( cur_title == 0 && buttons > 0 &&
     1192                     pci->hli.hl_gi.btn_se_e_ptm - pci->hli.hl_gi.hli_s_ptm >
     1193                     15 * 90000 )
    11751194                {
    1176                     int menu_title, menu_id;
    1177                     result = dvdnav_current_title_info( d->dvdnav, &menu_title, &menu_id );
    1178                     if (result != DVDNAV_STATUS_OK)
    1179                         hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav));
    11801195                    for (kk = 0; kk < buttons; kk++)
    11811196                    {
     
    11881203                            goto done;
    11891204                        }
    1190                         title = try_button( dvdnav_copy, menu_id, kk, list_title );
     1205                        title = try_button( dvdnav_copy, kk, list_title );
    11911206                        dvdnav_free_dup( dvdnav_copy );
    11921207
     
    12111226                    goto done;
    12121227                }
    1213                 if ( cur_title == 0 && buttons == 1 )
    1214                 {
    1215                     dvdnav_button_select_and_activate( d->dvdnav, pci, 1 );
    1216                 }
    12171228            } break;
    12181229
    12191230            case DVDNAV_VTS_CHANGE:
    12201231            {
    1221                 result = dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn );
     1232                result = dvdnav_current_title_info( d->dvdnav, &title, &part );
    12221233                if (result != DVDNAV_STATUS_OK)
    1223                     hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav));
     1234                    hb_log("dvdnav title info: %s", dvdnav_err_to_string(d->dvdnav));
    12241235                cur_title = title;
    12251236            } break;
     
    12491260        // try hitting the menu again.
    12501261        if ( !(jj & 1) )
     1262        {
    12511263            dvdnav_next_pg_search( d->dvdnav );
     1264        }
    12521265        else
     1266        {
    12531267            result = dvdnav_menu_call( d->dvdnav, menu );
     1268        }
    12541269    }
    12551270
     
    12611276{
    12621277    hb_dvdnav_t * d = &(e->dvdnav);
    1263     int longest_root;
    1264     int longest_title = 0;
     1278    int longest_root = -1;
     1279    int longest_title = -1;
    12651280    int longest_fallback = 0;
    12661281    int ii;
     
    12911306
    12921307    dvdnav_reset( d->dvdnav );
    1293 
    1294     longest_root = try_menu( d, list_title, DVD_MENU_Root, longest_duration_fallback );
    1295     if ( longest_root >= 0 )
    1296     {
    1297         index = find_title( list_title, longest_root );
    1298         title = hb_list_item( list_title, index );
    1299         if ( title )
    1300         {
    1301             longest_duration_root = title->duration;
    1302             hb_deep_log( 2, "dvdnav: Found root title %d duration %02d:%02d:%02d",
    1303                         longest_root, title->hours, title->minutes, title->seconds );
    1304         }
    1305     }
    1306     else
    1307     {
    1308         hb_deep_log( 2, "dvdnav: No root menu title found" );
    1309     }
     1308    if ( skip_to_menu( d->dvdnav, 2000 ) )
     1309    {
     1310        longest_root = try_menu( d, list_title, DVD_MENU_Escape, longest_duration_fallback );
     1311        if ( longest_root >= 0 )
     1312        {
     1313            index = find_title( list_title, longest_root );
     1314            title = hb_list_item( list_title, index );
     1315            if ( title )
     1316            {
     1317                longest_duration_root = title->duration;
     1318                hb_deep_log( 2, "dvdnav: Found first-play title %d duration %02d:%02d:%02d",
     1319                            longest_root, title->hours, title->minutes, title->seconds );
     1320            }
     1321        }
     1322        else
     1323        {
     1324            hb_deep_log( 2, "dvdnav: No first-play menu title found" );
     1325        }
     1326    }
     1327
     1328    if ( longest_root < 0 ||
     1329         (float)longest_duration_fallback * 0.7 > longest_duration_root)
     1330    {
     1331        longest_root = try_menu( d, list_title, DVD_MENU_Root, longest_duration_fallback );
     1332        if ( longest_root >= 0 )
     1333        {
     1334            index = find_title( list_title, longest_root );
     1335            title = hb_list_item( list_title, index );
     1336            if ( title )
     1337            {
     1338                longest_duration_root = title->duration;
     1339                hb_deep_log( 2, "dvdnav: Found root title %d duration %02d:%02d:%02d",
     1340                            longest_root, title->hours, title->minutes, title->seconds );
     1341            }
     1342        }
     1343        else
     1344        {
     1345            hb_deep_log( 2, "dvdnav: No root menu title found" );
     1346        }
     1347    }
     1348
    13101349    if ( longest_root < 0 ||
    13111350         (float)longest_duration_fallback * 0.7 > longest_duration_root)
Note: See TracChangeset for help on using the changeset viewer.