avcodec/cuviddec: improve progressive frame detection release/4.0
authorSergey Svechnikov <svechnikov66@gmail.com>
Mon, 22 Apr 2019 17:26:24 +0000 (22:26 +0500)
committerTimo Rothenpieler <timo@rothenpieler.org>
Tue, 23 Apr 2019 10:59:44 +0000 (12:59 +0200)
There are 2 types of problems when using adaptive deinterlace with cuvid:

1. Sometimes, in the middle of transcoding, cuvid outputs frames with visible horizontal lines (as though weave deinterlace method was chosen);
2. Occasionally, on scene changes, cuvid outputs a wrong frame, which should have been shown several seconds before (as if the frame was assigned some wrong PTS value).

The reason is that sometimes CUVIDPARSERDISPINFO has property progressive_frame equal to 1 with interlaced videos.
In order to fix the problem we should check if the video is interlaced or progressive in the beginning of a video sequence (cuvid_handle_video_sequence).
And then we just use this information instead of the property progressive_frame in CUVIDPARSERDISPINFO (which is unreliable).

Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
libavcodec/cuviddec.c

index 3862380..e922404 100644 (file)
@@ -70,6 +70,7 @@ typedef struct CuvidContext
     int deint_mode;
     int deint_mode_current;
     int64_t prev_pts;
+    int progressive_sequence;
 
     int internal_error;
     int decoder_flushing;
@@ -228,6 +229,8 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form
                               ? cudaVideoDeinterlaceMode_Weave
                               : ctx->deint_mode;
 
+    ctx->progressive_sequence = format->progressive_sequence;
+
     if (!format->progressive_sequence && ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave)
         avctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT;
     else
@@ -360,6 +363,9 @@ static int CUDAAPI cuvid_handle_picture_display(void *opaque, CUVIDPARSERDISPINF
     parsed_frame.dispinfo = *dispinfo;
     ctx->internal_error = 0;
 
+    // For some reason, dispinfo->progressive_frame is sometimes wrong.
+    parsed_frame.dispinfo.progressive_frame = ctx->progressive_sequence;
+
     if (ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave) {
         av_fifo_generic_write(ctx->frame_queue, &parsed_frame, sizeof(CuvidParsedFrame), NULL);
     } else {