@@ -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;
@@ -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);
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(-)