[FFmpeg-devel] [PATCH] lavc/qsv: fix transcode with interlaced clip
Fei Wang
fei.w.wang at intel.com
Thu Aug 20 11:21:21 EEST 2020
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 at intel.com>
---
libavcodec/qsvdec.c | 2 +-
libavfilter/qsvvpp.c | 32 ++++++++++++++++++++++++++++++--
2 files changed, 31 insertions(+), 3 deletions(-)
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);
--
2.17.1
More information about the ffmpeg-devel
mailing list