OSDN Git Service

Rate limit hb_error() messages to at most 1 message per second of the same message...
[handbrake-jp/handbrake-jp-git.git] / libhb / dvdnav.c
index 515de1e..2f1ac93 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "dvdnav/dvdnav.h"
 #include "dvdread/ifo_read.h"
+#include "dvdread/ifo_print.h"
 #include "dvdread/nav_read.h"
 
 #define DVD_READ_CACHE 1
@@ -141,10 +142,21 @@ static hb_dvd_t * hb_dvdnav_init( char * path )
 {
     hb_dvd_t * e;
     hb_dvdnav_t * d;
+    int region_mask;
 
     e = calloc( sizeof( hb_dvd_t ), 1 );
     d = &(e->dvdnav);
 
+       /* Log DVD drive region code */
+    if ( hb_dvd_region( path, &region_mask ) == 0 )
+    {
+        hb_log( "dvd: Region mask 0x%02x", region_mask );
+        if ( region_mask == 0xFF )
+        {
+            hb_log( "dvd: Warning, DVD device has no region set" );
+        }
+    }
+
     /* Open device */
     if( dvdnav_open(&d->dvdnav, path) != DVDNAV_STATUS_OK )
     {
@@ -251,6 +263,12 @@ PttDuration(ifo_handle_t *ifo, int ttn, int pttn, int *blocks, int *last_pgcn)
             hb_error( "scan: pgc not valid, skipping" );
             break;
         }
+        if (pgn > pgc->nr_of_programs)
+        {
+            pgn = 1;
+            continue;
+        }
+
         duration += 90LL * dvdtime2msec( &pgc->playback_time );
 
         cell_start = pgc->program_map[pgn-1] - 1;
@@ -418,7 +436,12 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t )
 
     pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
 
-    hb_log("pgc_id: %d, pgn: %d: pgc: 0x%x", pgcn, pgn, pgc);
+    hb_log("pgc_id: %d, pgn: %d: pgc: %p", pgcn, pgn, pgc);
+    if (pgn > pgc->nr_of_programs)
+    {
+        hb_error( "invalid PGN %d for title %d, skipping", pgn, t );
+        goto fail;
+    }
 
     /* Title start */
     title->cell_start = pgc->program_map[pgn-1] - 1;
@@ -440,7 +463,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t )
     title->hours    = title->duration / 90000 / 3600;
     title->minutes  = ( ( title->duration / 90000 ) % 3600 ) / 60;
     title->seconds  = ( title->duration / 90000 ) % 60;
-    hb_log( "scan: duration is %02d:%02d:%02d (%lld ms)",
+    hb_log( "scan: duration is %02d:%02d:%02d (%"PRId64" ms)",
             title->hours, title->minutes, title->seconds,
             title->duration / 90 );
 
@@ -565,12 +588,6 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t )
         hb_list_add( title->list_audio, audio );
     }
 
-    if( !hb_list_count( title->list_audio ) )
-    {
-        hb_log( "scan: ignoring title (no audio track)" );
-        goto fail;
-    }
-
     memcpy( title->palette,
             ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette,
             16 * sizeof( uint32_t ) );
@@ -627,7 +644,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t )
                   lang->iso639_2);
         subtitle->format = PICTURESUB;
         subtitle->source = VOBSUB;
-        subtitle->dest   = RENDERSUB;  // By default render (burn-in) the VOBSUB.
+        subtitle->config.dest   = RENDERSUB;  // By default render (burn-in) the VOBSUB.
 
         subtitle->type = lang_extension;
 
@@ -762,7 +779,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), %lld ms",
+        hb_log( "scan: chap %d c=%d->%d, b=%d->%d (%d), %"PRId64" ms",
                 chapter->index, chapter->cell_start, chapter->cell_end,
                 chapter->block_start, chapter->block_end,
                 chapter->block_count, chapter->duration / 90 );
@@ -831,6 +848,7 @@ static int hb_dvdnav_start( hb_dvd_t * e, hb_title_t *title, int c )
     }
     d->title = t;
     d->stopped = 0;
+    d->chapter = 0;
     return 1;
 }
 
@@ -903,7 +921,7 @@ static int hb_dvdnav_seek( hb_dvd_t * e, float f )
         result = dvdnav_get_next_block( d->dvdnav, buf, &event, &len );
         if ( result == DVDNAV_STATUS_ERR )
         {
-            hb_log("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav));
+            hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav));
             return 0;
         }
         switch ( event )
@@ -958,6 +976,7 @@ static int hb_dvdnav_read( hb_dvd_t * e, hb_buffer_t * b )
     hb_dvdnav_t * d = &(e->dvdnav);
     int result, event, len;
     int chapter = 0;
+    int error_count = 0;
 
     while ( 1 )
     {
@@ -968,9 +987,22 @@ static int hb_dvdnav_read( hb_dvd_t * e, hb_buffer_t * b )
         result = dvdnav_get_next_block( d->dvdnav, b->data, &event, &len );
         if ( result == DVDNAV_STATUS_ERR )
         {
-            hb_log("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav));
-            return 0;
+            hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav));
+            if (dvdnav_sector_search(d->dvdnav, 1, SEEK_CUR) != DVDNAV_STATUS_OK)
+            {
+                hb_error( "dvd: dvdnav_sector_search failed - %s",
+                        dvdnav_err_to_string(d->dvdnav) );
+                return 0;
+            }
+            error_count++;
+            if (error_count > 10)
+            {
+                hb_error("dvdnav: Error, too many consecutive read errors");
+                return 0;
+            }
+            continue;
         }
+        error_count = 0;
         switch ( event )
         {
         case DVDNAV_BLOCK_OK:
@@ -1069,8 +1101,16 @@ static int hb_dvdnav_read( hb_dvd_t * e, hb_buffer_t * b )
                     return 0;
                 }
                 c = FindChapterIndex(d->list_chapter, pgcn, pgn);
-                if (c > d->chapter)
+                if (c != d->chapter)
+                {
+                    if (c < d->chapter)
+                    {
+                        // Some titles end with a 'link' back to the beginning so
+                        // a transition to an earlier chapter means we're done.
+                        return 0;
+                    }
                     chapter = d->chapter = c;
+                }
             }
             break;