From 2c9dc98a904306ff2f479edacfe71edbba14e934 Mon Sep 17 00:00:00 2001
From: Aaron Levinson <[email protected]>
Date: Sun, 16 Apr 2017 17:48:22 -0700
Subject: [PATCH 1/2] Fixed problems with QuickSync (QSV) interlaced video
 encoding, improved alignment

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.  In the case of the libav code,
it looks like interlaced video encoding has always been an issue based
on the history of qsvenc.c.

Notes: Tested changes with both progressive (720p59.94) and interlaced
(1080i59.94) video (with ffmpeg).

Comments:

-- qsvenc.c / .h: Added code 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 ffmpeg 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.  Please
   note that much of this log message pertains to the ffmpeg code
   base.  Interlaced video has almost certainly never worked with the
   libav code base.  Plus, the height alignment in libav has always
   been 32-byte alignment, and 16-byte alignment is sufficient in some
   cases.
---
 libavcodec/qsvenc.c | 29 +++++++++++++++++++++++------
 libavcodec/qsvenc.h |  1 +
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index bd8c243..ccb1216 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -366,8 +366,6 @@ static int init_video_param(AVCodecContext *avctx, 
QSVEncContext *q)
         return AVERROR_BUG;
     q->param.mfx.CodecId = ret;
 
-    q->width_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16;
-
     if (avctx->level > 0)
         q->param.mfx.CodecLevel = avctx->level;
 
@@ -389,20 +387,39 @@ 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;
 
+    // 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;
+    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;
@@ -890,7 +907,7 @@ static int submit_frame(QSVEncContext *q, const AVFrame 
*frame,
     } else {
         /* make a copy if the input is not padded as libmfx requires */
         if (frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) {
-            qf->frame->height = FFALIGN(frame->height, 32);
+            qf->frame->height = FFALIGN(frame->height, q->height_align);
             qf->frame->width  = FFALIGN(frame->width, q->width_align);
 
             ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF);
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 13e4c47..a639904 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -79,6 +79,7 @@ typedef struct QSVEncContext {
 
     int packet_size;
     int width_align;
+    int height_align;
 
     mfxVideoParam param;
     mfxFrameAllocRequest req;
-- 
2.10.1.windows.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to