From da3899b24ad89b4788a3b8191d53b26f5eec328e Mon Sep 17 00:00:00 2001 From: Aaron Levinson <alevi...@aracnet.com> Date: Thu, 13 Apr 2017 23:12:30 -0700 Subject: [PATCH] Fixed problems with QuickSync (QSV) interlaced video encoding
Purpose: Fixed problems with QuickSync (QSV) interlaced video encoding that were introduced in revision 1f26a23 on Oct. 31, 2016 (qsv: Merge libav implementation, at https://github.com/FFmpeg/FFmpeg/commit/1f26a231bb065276cd80ce02957c759f3197edfa#diff-7d84a34d58597bb7aa4b8239dca1f9f8). As a result of the qsv libav merge, when attempting to encode interlaced video, it doesn't work and instead results in a bunch of incompatible video parameter errors. Comments: -- qsvenc.c / .h: a) Added code back in to set PicStruct appropriately based on whether or not interlaced or progressive video is being encoded. Also reintroduced the related code to set the height alignment. The height alignment code was also enhanced slightly (compared to the version in 3.2.4) to properly handle progressive video when the HEVC encoder is used. The elimination of this code is the main reason why interlaced video encoding stopped working. b) Reintroduced code to call MFXVideoENCODE_Query() after calling init_video_param(). This isn't strictly required to fix the interlaced video encoding issue, but it represents a generally good practice to make sure that one is working with the right parameter values. --- libavcodec/qsvenc.c | 33 +++++++++++++++++++++++++++++---- libavcodec/qsvenc.h | 1 + 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 9c385a7..24ac390 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -358,6 +358,9 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) return AVERROR_BUG; q->param.mfx.CodecId = ret; + // TODO: detect version of MFX--if the minor version is greater than + // or equal to 19, then can use the same alignment settings as H.264 + // for HEVC q->width_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16; if (avctx->level > 0) @@ -381,20 +384,34 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); - q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align); - q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, 32); q->param.mfx.FrameInfo.CropX = 0; q->param.mfx.FrameInfo.CropY = 0; q->param.mfx.FrameInfo.CropW = avctx->width; q->param.mfx.FrameInfo.CropH = avctx->height; q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; - q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; + q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align); + if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + // it is important that PicStruct be setup correctly from the + // start--otherwise, encoding doesn't work and results in a bunch + // of incompatible video parameter errors + q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF; + // height alignment always must be 32 for interlaced video + q->height_align = 32; + } else { + q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + // for progressive video, the height should be aligned to 16 for + // H.264. For HEVC, depending on the version of MFX, it should be + // either 32 or 16. The lower number is better if possible. + q->height_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16; + } + q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, q->height_align); + if (avctx->hw_frames_ctx) { AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; @@ -740,10 +757,18 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) if (ret < 0) return ret; + ret = MFXVideoENCODE_Query(q->session, &q->param, &q->param); + if (ret == MFX_WRN_PARTIAL_ACCELERATION) { + av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n"); + } else if (ret < 0) { + return ff_qsv_print_error(avctx, ret, + "Error querying encoder params"); + } + ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req); if (ret < 0) return ff_qsv_print_error(avctx, ret, - "Error querying the encoding parameters"); + "Error querying (IOSurf) the encoding parameters"); if (opaque_alloc) { ret = qsv_init_opaque_alloc(avctx, q); diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 361d933..12e3444 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -84,6 +84,7 @@ typedef struct QSVEncContext { int packet_size; int width_align; + int height_align; mfxVideoParam param; mfxFrameAllocRequest req; -- 2.10.1.windows.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel