[FFmpeg-devel] cuviddec: improved way of finding out if a frame is interlaced or progressive

Submitted by Sergey Svechnikov on April 22, 2019, 5:26 p.m.

Details

Message ID 1555953984-25841-1-git-send-email-svechnikov66@gmail.com
State New
Headers show

Commit Message

Sergey Svechnikov April 22, 2019, 5:26 p.m.
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).

More info, samples and reproduction steps are here https://github.com/Svechnikov/ffmpeg-cuda-deinterlace-problems
---
 libavcodec/cuviddec.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Timo Rothenpieler April 23, 2019, 11:05 a.m.
applied, thanks.

Patch hide | download patch | download mbox

diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c
index 2aecb45..671fc8c 100644
--- a/libavcodec/cuviddec.c
+++ b/libavcodec/cuviddec.c
@@ -77,6 +77,7 @@  typedef struct CuvidContext
     int deint_mode;
     int deint_mode_current;
     int64_t prev_pts;
+    unsigned char progressive_sequence;
 
     int internal_error;
     int decoder_flushing;
@@ -216,6 +217,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
@@ -509,6 +512,8 @@  static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame)
 
         av_fifo_generic_read(ctx->frame_queue, &parsed_frame, sizeof(CuvidParsedFrame), NULL);
 
+        parsed_frame.dispinfo.progressive_frame = ctx->progressive_sequence;
+
         memset(&params, 0, sizeof(params));
         params.progressive_frame = parsed_frame.dispinfo.progressive_frame;
         params.second_field = parsed_frame.second_field;