diff mbox series

[FFmpeg-devel] lavc/qsv: fix transcode with interlaced clip

Message ID 20200820082121.7807-1-fei.w.wang@intel.com
State New
Headers show
Series [FFmpeg-devel] lavc/qsv: fix transcode with interlaced clip | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Fei Wang Aug. 20, 2020, 8:21 a.m. UTC
1. qsvdec: set output surface info correctly.
2. qsvvpp: set output surface/frame's picture struct according to
input if deinterlace option is not enabled.

This fix will make interlace transcode works:
ffmpeg -init_hw_device qsv=hw:/dev/dri/renderD128 -filter_hw_device  \
hw -hwaccel_output_format qsv -hwaccel qsv -v debug -c:v h264_qsv -i \
1920x1080_interlace.mp4 -vf "vpp_qsv=w=1280:h=720" -c:v h264_qsv     \
-flags +ildct+ilme -preset medium -b:v 10M -y 1280x720_interlace.mp4

Signed-off-by: Fei Wang <fei.w.wang@intel.com>
---
 libavcodec/qsvdec.c  |  2 +-
 libavfilter/qsvvpp.c | 32 ++++++++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index fc25dc73e5..4dadc3de07 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -521,7 +521,7 @@  FF_ENABLE_DEPRECATION_WARNINGS
             frame->key_frame = !!(out_frame->dec_info.FrameType & MFX_FRAMETYPE_IDR);
 
         /* update the surface properties */
-        if (avctx->pix_fmt == AV_PIX_FMT_QSV)
+        if (frame->format == AV_PIX_FMT_QSV)
             ((mfxFrameSurface1*)frame->data[3])->Info = outsurf->Info;
 
         *got_frame = 1;
diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index 8d5ff2eb65..3de98ca475 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -61,6 +61,7 @@  struct QSVVPPContext {
     int                 nb_surface_ptrs_out;
     mfxFrameSurface1  **surface_ptrs_in;
     mfxFrameSurface1  **surface_ptrs_out;
+    int                 out_frame_deinterlaced;
 
     /* MFXVPP extern parameters */
     mfxExtOpaqueSurfaceAlloc opaque_alloc;
@@ -347,7 +348,7 @@  static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *p
 }
 
 /* get the output surface */
-static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink)
+static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, AVFrame *picref)
 {
     AVFilterContext *ctx = outlink->src;
     QSVFrame        *out_frame;
@@ -395,6 +396,27 @@  static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink)
 
     out_frame->surface->Info = s->vpp_param.vpp.Out;
 
+    if (!s->out_frame_deinterlaced) {
+        /* copy picture info from input to out_frame */
+        out_frame->frame->repeat_pict = picref->repeat_pict;
+        out_frame->frame->top_field_first = picref->top_field_first;
+        out_frame->frame->interlaced_frame = picref->interlaced_frame;
+        out_frame->frame->pict_type = picref->pict_type;
+
+        /* surfaces in pool is inited with MFX_PICSTRUCT_PROGRESSIVE, update
+         * it base on input frame info. */
+        out_frame->surface->Info.PicStruct =
+            !picref->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
+            (picref->top_field_first ? MFX_PICSTRUCT_FIELD_TFF :
+                                       MFX_PICSTRUCT_FIELD_BFF);
+        if (picref->repeat_pict == 1)
+            out_frame->surface->Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
+        else if (picref->repeat_pict == 2)
+            out_frame->surface->Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
+        else if (picref->repeat_pict == 4)
+            out_frame->surface->Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
+    }
+
     return out_frame;
 }
 
@@ -612,6 +634,12 @@  int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p
         goto failed;
     }
 
+    /* Update output's interlace state according to params */
+    for (i = 0; i < param->num_ext_buf; i++) {
+        if (param->ext_buf[i]->BufferId == MFX_EXTBUFF_VPP_DEINTERLACING)
+            s->out_frame_deinterlaced = 1;
+    }
+
     if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
         s->nb_ext_buffers = param->num_ext_buf + 1;
         s->ext_buffers = av_mallocz_array(s->nb_ext_buffers, sizeof(*s->ext_buffers));
@@ -701,7 +729,7 @@  int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr
     }
 
     do {
-        out_frame = query_frame(s, outlink);
+        out_frame = query_frame(s, outlink, picref);
         if (!out_frame) {
             av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n");
             return AVERROR(ENOMEM);