libhb: improve preview generateion when there are no IDRs
authorjstebbins <jstebbins.hb@gmail.com>
Thu, 2 Oct 2014 21:05:08 +0000 (21:05 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Thu, 2 Oct 2014 21:05:08 +0000 (21:05 +0000)
Puts the decoder into a mode that returns *all* frames.  I.e.
it won't just scan to the end of the file looking for an IDR.  Then
we decode multiple frames (up to 100) searching for an I frame. This way,
the reconstructed frame we use for a preview is more likely to be complete.

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

libhb/bd.c
libhb/decavcodec.c
libhb/scan.c
libhb/stream.c

index 6cef95609d1e5027b1b1a32eb8366a505bcb5cf9..06d4feaef6fd80e677877037253b4fd802bc42a4 100644 (file)
@@ -350,7 +350,6 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
         case BLURAY_STREAM_TYPE_VIDEO_H264:
             title->video_codec = WORK_DECAVCODECV;
             title->video_codec_param = AV_CODEC_ID_H264;
-            title->flags |= HBTF_NO_IDR;
             break;
 
         default:
index e235111d8ce070c632f6493acf5ede87bb79074a..4eb9f6947be9f93bed29a150532102c6d7fbe99d 100644 (file)
@@ -1149,6 +1149,20 @@ static hb_buffer_t * cc_fill_buffer(hb_work_private_t *pv, uint8_t *cc, int size
     return buf;
 }
 
+static int get_frame_type(int type)
+{
+    switch(type)
+    {
+        case AV_PICTURE_TYPE_I:
+            return HB_FRAME_I;
+        case AV_PICTURE_TYPE_B:
+            return HB_FRAME_B;
+        case AV_PICTURE_TYPE_P:
+            return HB_FRAME_P;
+    }
+    return 0;
+}
+
 /*
  * Decodes a video frame from the specified raw packet data
  *      ('data', 'size', 'sequence').
@@ -1315,6 +1329,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
         {
             flags |= PIC_FLAG_REPEAT_FRAME;
         }
+        int frametype = get_frame_type(pv->frame->pict_type);
 
         // Check for CC data
         AVFrameSideData *sd;
@@ -1385,6 +1400,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
             buf->sequence = sequence;
 
             buf->s.flags = flags;
+            buf->s.frametype = frametype;
 
             if ( pv->new_chap && buf->s.start >= pv->chap_time )
             {
@@ -1451,6 +1467,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
         buf->sequence = sequence;
         /* Store picture flags for later use by filters */
         buf->s.flags = flags;
+        buf->s.frametype = frametype;
         pv->delayq[slot] = buf;
         heap_push( &pv->pts_heap, pts );
 
@@ -1654,6 +1671,10 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
         // Set encoder opts...
         AVDictionary * av_opts = NULL;
         av_dict_set( &av_opts, "refcounted_frames", "1", 0 );
+        if (pv->title->flags & HBTF_NO_IDR)
+        {
+            av_dict_set( &av_opts, "flags", "output_corrupt", 0 );
+        }
 
         if ( hb_avcodec_open( pv->context, codec, &av_opts, pv->threads ) )
         {
@@ -1818,6 +1839,10 @@ static int decavcodecvWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
 
         AVDictionary * av_opts = NULL;
         av_dict_set( &av_opts, "refcounted_frames", "1", 0 );
+        if (pv->title->flags & HBTF_NO_IDR)
+        {
+            av_dict_set( &av_opts, "flags", "output_corrupt", 0 );
+        }
 
         // disable threaded decoding for scan, can cause crashes
         if ( hb_avcodec_open( pv->context, codec, &av_opts, pv->threads ) )
index 5726e8a5d6dac22349c08336e47f6b4cca337095..08b8e9e249bf54d930d1eb96b02f59a7e7a11c42 100644 (file)
@@ -493,6 +493,7 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush )
     int pulldown_count = 0;
     int doubled_frame_count = 0;
     int interlaced_preview_count = 0;
+    int frame_wait = 0;
     hb_stream_t  * stream = NULL;
     info_list_t * info_list = calloc( data->preview_count+1, sizeof(*info_list) );
     crop_record_t *crops = crop_record_init( data->preview_count );
@@ -590,6 +591,10 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush )
 
         if (flush && vid_decoder->flush)
             vid_decoder->flush( vid_decoder );
+        if (title->flags & HBTF_NO_IDR)
+        {
+            frame_wait = 100;
+        }
 
         hb_buffer_t * vid_buf = NULL;
 
@@ -660,6 +665,18 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush )
                 if( buf_es->s.id == title->video_id && vid_buf == NULL )
                 {
                     vid_decoder->work( vid_decoder, &buf_es, &vid_buf );
+                    if (vid_buf != NULL && frame_wait)
+                    {
+                        if (vid_buf->s.frametype != HB_FRAME_I)
+                        {
+                            hb_buffer_close(&vid_buf);
+                            frame_wait--;
+                        }
+                        else
+                        {
+                            frame_wait = 0;
+                        }
+                    }
                 }
                 else if( ! AllAudioOK( title ) ) 
                 {
index 5b59c44db1ffa6744841e116c0a7b51265ff5fdb..0d1bec2265c4287cce077845449ab4ed0f58c814 100644 (file)
@@ -1098,7 +1098,6 @@ hb_title_t * hb_stream_title_scan(hb_stream_t *stream, hb_title_t * title)
     chapter->seconds = title->seconds;
     hb_list_add( title->list_chapter, chapter );
 
-
     if ( stream->has_IDRs < 1 )
     {
         hb_log( "stream doesn't seem to have video IDR frames" );
@@ -5440,9 +5439,6 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title )
                 title->pixel_aspect_height = ic->streams[i]->sample_aspect_ratio.den;
             }
 
-            if ( context->codec_id == AV_CODEC_ID_H264 )
-                title->flags |= HBTF_NO_IDR;
-
             title->video_codec = WORK_DECAVCODECV;
             title->video_codec_param = context->codec_id;
         }