libhb: detect read errors and propagate
authorjstebbins <jstebbins.hb@gmail.com>
Mon, 29 Jun 2015 16:05:38 +0000 (16:05 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Mon, 29 Jun 2015 16:05:38 +0000 (16:05 +0000)
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@7332 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/bd.c
libhb/common.h
libhb/dvd.c
libhb/dvd.h
libhb/dvdnav.c
libhb/hb.c
libhb/internal.h
libhb/reader.c
libhb/scan.c
libhb/stream.c

index 44b8a2e265a8629d61c4ffedf2cf36f5914bdca5..7da108c5019ac6be096326ad13ba6d3360c1b4d2 100644 (file)
@@ -719,13 +719,14 @@ hb_buffer_t * hb_bd_read( hb_bd_t * d )
             if (error_count > 10)
             {
                 hb_error("bd: Error, too many consecutive read errors");
-                return 0;
+                hb_set_work_error(d->h, HB_ERROR_READ);
+                return NULL;
             }
             continue;
         }
         else if ( result == 0 )
         {
-            return 0;
+            return NULL;
         }
 
         error_count = 0;
@@ -827,7 +828,8 @@ static int have_ts_sync(const uint8_t *buf, int psize)
 
 static uint64_t align_to_next_packet(BLURAY *bd, uint8_t *pkt)
 {
-    uint8_t buf[MAX_HOLE];
+    int      result;
+    uint8_t  buf[MAX_HOLE];
     uint64_t pos = 0;
     uint64_t start = bd_tell(bd);
     uint64_t orig;
@@ -841,7 +843,8 @@ static uint64_t align_to_next_packet(BLURAY *bd, uint8_t *pkt)
 
     while (1)
     {
-        if (bd_read(bd, buf+off, sizeof(buf)-off) == sizeof(buf)-off)
+        result = bd_read(bd, buf + off, sizeof(buf) - off);
+        if (result == sizeof(buf) - off)
         {
             const uint8_t *bp = buf;
             int i;
@@ -862,6 +865,10 @@ static uint64_t align_to_next_packet(BLURAY *bd, uint8_t *pkt)
             memcpy(buf, buf + sizeof(buf) - off, off);
             start += sizeof(buf) - off;
         }
+        else if (result < 0)
+        {
+            return -1;
+        }
         else
         {
             return 0;
@@ -874,9 +881,14 @@ static uint64_t align_to_next_packet(BLURAY *bd, uint8_t *pkt)
     bd_seek(bd, off);
     while (off > bd_tell(bd))
     {
-        if (bd_read(bd, buf, 192) != 192)
+        result = bd_read(bd, buf, 192);
+        if (result < 0)
         {
-            break;
+            return -1;
+        }
+        else if (result != 192)
+        {
+            return 0;
         }
     }
     return start - orig + pos;
@@ -905,12 +917,16 @@ static int next_packet( BLURAY *bd, uint8_t *pkt )
         // lost sync - back up to where we started then try to re-establish.
         uint64_t pos = bd_tell(bd);
         uint64_t pos2 = align_to_next_packet(bd, pkt);
-        if ( pos2 == 0 )
+        if (pos2 < 0)
+        {
+            return -1;
+        }
+        else if (pos2 == 0)
         {
-            hb_log( "next_packet: eof while re-establishing sync @ %"PRIu64"", pos );
+            hb_log("next_packet: eof while re-establishing sync @ %"PRIu64"", pos );
             return 0;
         }
-        hb_log( "next_packet: sync lost @ %"PRIu64", regained after %"PRIu64" bytes",
+        hb_log("next_packet: sync lost @ %"PRIu64", regained after %"PRIu64" bytes",
                  pos, pos2 );
     }
 }
index d088ad8fd017ccf4eb84aa54079b42fce0d6d812..d1fe733352099844b4ab0e0a7a3a28f8b7e47393 100644 (file)
@@ -108,11 +108,12 @@ typedef struct hb_fifo_s hb_fifo_t;
 typedef struct hb_lock_s hb_lock_t;
 typedef enum
 {
-     HB_ERROR_NONE    = 0,
-     HB_ERROR_CANCELED   ,
-     HB_ERROR_WRONG_INPUT,
-     HB_ERROR_INIT       ,
-     HB_ERROR_UNKNOWN
+     HB_ERROR_NONE         = 0,
+     HB_ERROR_CANCELED     = 1,
+     HB_ERROR_WRONG_INPUT  = 2,
+     HB_ERROR_INIT         = 3,
+     HB_ERROR_UNKNOWN      = 4,
+     HB_ERROR_READ         = 5
 } hb_error_code;
 
 #include "ports.h"
index 99e8a142e7a2e0f4b04d76150f29106bb738de5e..082057bade3ef540571086621c9ace527f9b151a 100644 (file)
@@ -15,7 +15,7 @@
 #include "dvdread/ifo_print.h"
 #include "dvdread/nav_read.h"
 
-static hb_dvd_t    * hb_dvdread_init( char * path );
+static hb_dvd_t    * hb_dvdread_init( hb_handle_t * h, char * path );
 static void          hb_dvdread_close( hb_dvd_t ** _d );
 static char        * hb_dvdread_name( char * path );
 static int           hb_dvdread_title_count( hb_dvd_t * d );
@@ -106,7 +106,7 @@ static char * hb_dvdread_name( char * path )
  ***********************************************************************
  *
  **********************************************************************/
-hb_dvd_t * hb_dvdread_init( char * path )
+hb_dvd_t * hb_dvdread_init( hb_handle_t * h, char * path )
 {
     hb_dvd_t * e;
     hb_dvdread_t * d;
@@ -115,6 +115,7 @@ hb_dvd_t * hb_dvdread_init( char * path )
 
     e = calloc( sizeof( hb_dvd_t ), 1 );
     d = &(e->dvdread);
+    d->h = h;
 
     /*
      * Convert UTF-8 path to current code page on Windows
@@ -890,6 +891,7 @@ static hb_buffer_t * hb_dvdread_read( hb_dvd_t * e )
                 if ( d->cell_cur > d->cell_end )
                 {
                     hb_buffer_close( &b );
+                    hb_set_work_error(d->h, HB_ERROR_READ);
                     return NULL;
                 }
                 d->in_cell = 0;
@@ -988,8 +990,9 @@ static hb_buffer_t * hb_dvdread_read( hb_dvd_t * e )
             /* Wasn't a valid VOBU, try next block */
             if( ++error > 1024 )
             {
-                hb_log( "dvd: couldn't find a VOBU after 1024 blocks" );
+                hb_error( "dvd: couldn't find a VOBU after 1024 blocks" );
                 hb_buffer_close( &b );
+                hb_set_work_error(d->h, HB_ERROR_READ);
                 return NULL;
             }
 
@@ -1269,9 +1272,9 @@ char * hb_dvd_name( char * path )
     return dvd_methods->name(path);
 }
 
-hb_dvd_t * hb_dvd_init( char * path )
+hb_dvd_t * hb_dvd_init( hb_handle_t * h, char * path )
 {
-    return dvd_methods->init(path);
+    return dvd_methods->init(h, path);
 }
 
 int hb_dvd_title_count( hb_dvd_t * d )
index 24f4f1e308e2d3c3881ebdddfe2722e58231533e..55153381f0aeecf1ce8eee54da89b816b0eb58c0 100644 (file)
@@ -42,6 +42,7 @@ struct hb_dvdread_s
     int            in_sync;
     uint16_t       cur_vob_id;
     uint8_t        cur_cell_id;
+    hb_handle_t  * h;
 };
 
 struct hb_dvdnav_s
@@ -57,6 +58,7 @@ struct hb_dvdnav_s
     int            cell;
     hb_list_t    * list_chapter;
     int            stopped;
+    hb_handle_t  * h;
 };
 
 typedef struct hb_dvdnav_s hb_dvdnav_t;
@@ -71,7 +73,7 @@ union hb_dvd_s
 
 struct hb_dvd_func_s
 {
-    hb_dvd_t *    (* init)        ( char * );
+    hb_dvd_t *    (* init)        ( hb_handle_t *, char * );
     void          (* close)       ( hb_dvd_t ** );
     char        * (* name)        ( char * );
     int           (* title_count) ( hb_dvd_t * );
index 1999f6f9d408420b168292083196e06fe740e908..09dc411f8a9b9d0e9a04837b680fdc636e4ccd0a 100644 (file)
@@ -19,7 +19,7 @@
 #define DVD_READ_CACHE 1
 
 static char        * hb_dvdnav_name( char * path );
-static hb_dvd_t    * hb_dvdnav_init( char * path );
+static hb_dvd_t    * hb_dvdnav_init( hb_handle_t * h, 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, uint64_t min_duration );
 static int           hb_dvdnav_start( hb_dvd_t * d, hb_title_t *title, int chapter );
@@ -148,7 +148,7 @@ fail:
  ***********************************************************************
  *
  **********************************************************************/
-static hb_dvd_t * hb_dvdnav_init( char * path )
+static hb_dvd_t * hb_dvdnav_init( hb_handle_t * h, char * path )
 {
     hb_dvd_t * e;
     hb_dvdnav_t * d;
@@ -157,6 +157,7 @@ static hb_dvd_t * hb_dvdnav_init( char * path )
 
     e = calloc( sizeof( hb_dvd_t ), 1 );
     d = &(e->dvdnav);
+    d->h = h;
 
     /*
      * Convert UTF-8 path to current code page on Windows
@@ -1627,6 +1628,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
                 hb_error( "dvd: dvdnav_sector_search failed - %s",
                         dvdnav_err_to_string(d->dvdnav) );
                 hb_buffer_close( &b );
+                hb_set_work_error(d->h, HB_ERROR_READ);
                 return NULL;
             }
             error_count++;
@@ -1634,6 +1636,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
             {
                 hb_error("dvdnav: Error, too many consecutive read errors");
                 hb_buffer_close( &b );
+                hb_set_work_error(d->h, HB_ERROR_READ);
                 return NULL;
             }
             continue;
@@ -1726,6 +1729,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
                 {
                     // Transition to another title signals that we are done.
                     hb_buffer_close( &b );
+                    hb_deep_log(2, "dvdnav: vts change, found next title");
                     return NULL;
                 }
             }
@@ -1749,6 +1753,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
                 {
                     // Transition to another title signals that we are done.
                     hb_buffer_close( &b );
+                    hb_deep_log(2, "dvdnav: cell change, found next title");
                     return NULL;
                 }
                 c = FindChapterIndex(d->list_chapter, pgcn, pgn);
@@ -1759,6 +1764,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
                         // Some titles end with a 'link' back to the beginning so
                         // a transition to an earlier chapter means we're done.
                         hb_buffer_close( &b );
+                        hb_deep_log(2, "dvdnav: cell change, previous chapter");
                         return NULL;
                     }
                     chapter = d->chapter = c;
@@ -1766,6 +1772,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
                 else if ( cell_event->cellN <= d->cell )
                 {
                     hb_buffer_close( &b );
+                    hb_deep_log(2, "dvdnav: cell change, previous cell");
                     return NULL;
                 }
                 d->cell = cell_event->cellN;
@@ -1808,6 +1815,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
             */
             d->stopped = 1;
             hb_buffer_close( &b );
+            hb_deep_log(2, "dvdnav: stop");
             return NULL;
 
         default:
index 513c27e622a20e848e37640387869365443a841b..a3e373b0fe835685638b982932982b9751877d0e 100644 (file)
@@ -1819,6 +1819,11 @@ void hb_set_state( hb_handle_t * h, hb_state_t * s )
     hb_unlock( h->pause_lock );
 }
 
+void hb_set_work_error( hb_handle_t * h, hb_error_code err )
+{
+    h->work_error = err;
+}
+
 void hb_system_sleep_allow(hb_handle_t *h)
 {
     hb_system_sleep_private_enable(h->system_sleep_opaque);
index 30d8c24c892fc662e66d8aa2bea878c266534f95..4be0dffc333d6ba09b7c478fdf39541a12f9b209 100644 (file)
@@ -48,6 +48,7 @@ void         hb_title_close( hb_title_t ** );
  **********************************************************************/
 int  hb_get_pid( hb_handle_t * );
 void hb_set_state( hb_handle_t *, hb_state_t * );
+void hb_set_work_error( hb_handle_t * h, hb_error_code err );
 void hb_job_setup_passes(hb_handle_t *h, hb_job_t *job, hb_list_t *list_pass);
 
 /***********************************************************************
@@ -327,7 +328,7 @@ typedef struct hb_bd_s hb_bd_t;
 typedef union  hb_dvd_s hb_dvd_t;
 typedef struct hb_stream_s hb_stream_t;
 
-hb_dvd_t *   hb_dvd_init( char * path );
+hb_dvd_t *   hb_dvd_init( hb_handle_t * h, char * path );
 int          hb_dvd_title_count( hb_dvd_t * );
 hb_title_t * hb_dvd_title_scan( hb_dvd_t *, int title, uint64_t min_duration );
 int          hb_dvd_start( hb_dvd_t *, hb_title_t *title, int chapter );
index d730c1f09d1954dec34adf6ad2c8bdf1a4fc6ae3..9c742e6fd05f2ccf65b7c7c8ae4bee1114fbc1f5 100644 (file)
@@ -81,7 +81,7 @@ static int hb_reader_open( hb_work_private_t * r )
     }
     else if ( r->title->type == HB_DVD_TYPE )
     {
-        if ( !( r->dvd = hb_dvd_init( r->title->path ) ) )
+        if ( !( r->dvd = hb_dvd_init( r->h, r->title->path ) ) )
             return 1;
     }
     else if ( r->title->type == HB_STREAM_TYPE ||
index a446344cd20bde44943d8015f5d59497be833feb..56a256f8b3f5d1f88d1eaf58851a907d611a35fe 100644 (file)
@@ -126,7 +126,7 @@ static void ScanFunc( void * _data )
                                           data->title_set->list_title );
         }
     }
-    else if( ( data->dvd = hb_dvd_init( data->path ) ) )
+    else if( ( data->dvd = hb_dvd_init( data->h, data->path ) ) )
     {
         hb_log( "scan: DVD has %d title(s)",
                 hb_dvd_title_count( data->dvd ) );
index cb669e52f42ab5998435c52166020655ca5a4404..e404513e0f15d53ff71323d56de6b8f7b0147244 100644 (file)
@@ -1125,6 +1125,12 @@ static const uint8_t *next_packet( hb_stream_t *stream )
         if ( fread(stream->ts.packet, 1, stream->packetsize, stream->file_handle) !=
              stream->packetsize )
         {
+            int err;
+            if ((err = ferror(stream->file_handle)) != 0)
+            {
+                hb_error("next_packet: error (%d)", err);
+                hb_set_work_error(stream->h, HB_ERROR_READ);
+            }
             return NULL;
         }
         if (buf[0] == 0x47)
@@ -2408,6 +2414,12 @@ static off_t align_to_next_packet(hb_stream_t *stream)
         }
         else
         {
+            int err;
+            if ((err = ferror(stream->file_handle)) != 0)
+            {
+                hb_error("align_to_next_packet: error (%d)", err);
+                hb_set_work_error(stream->h, HB_ERROR_READ);
+            }
             return 0;
         }
     }
@@ -3352,9 +3364,18 @@ static int hb_ps_read_packet( hb_stream_t * stream, hb_buffer_t *b )
         pos -= 4;
         fseeko( stream->file_handle, -4, SEEK_CUR );
     }
+
 done:
     // Parse packet for information we might need
     funlockfile( stream->file_handle );
+
+    int err;
+    if ((err = ferror(stream->file_handle)) != 0)
+    {
+        hb_error("hb_ps_read_packet: error (%d)", err);
+        hb_set_work_error(stream->h, HB_ERROR_READ);
+    }
+
     int len = pos - b->size;
     b->size = pos;
 #undef cp
@@ -5657,8 +5678,17 @@ hb_buffer_t * hb_ffmpeg_read( hb_stream_t *stream )
         // use M$ 'packed b-frames' and occasionally have negative
         // sizes for the null frames these require.
         if ( err != AVERROR(ENOMEM) || stream->ffmpeg_pkt->size >= 0 )
-            // eof
+        {
+            // error or eof
+            if (err != AVERROR_EOF)
+            {
+                char errstr[80];
+                av_strerror(err, errstr, 80);
+                hb_error("av_read_frame error (%d): %s", err, errstr);
+                hb_set_work_error(stream->h, HB_ERROR_READ);
+            }
             return NULL;
+        }
     }
     if ( stream->ffmpeg_pkt->stream_index == stream->ffmpeg_video_id )
     {