[FFmpeg-devel] [PATCH] Fixed problems with QuickSync (QSV) interlaced video encoding

Aaron Levinson alevinsn at aracnet.com
Fri Apr 14 09:36:21 EEST 2017


>From da3899b24ad89b4788a3b8191d53b26f5eec328e Mon Sep 17 00:00:00 2001
From: Aaron Levinson <alevinsn at 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



More information about the ffmpeg-devel mailing list