[FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: Fix bug that the QSV encoded frames'width and height are 32-aligned

Mark Thompson sw at jkqxz.net
Tue Jan 3 14:40:55 EET 2017


On 03/01/17 06:35, Huang, Zhengxu wrote:
> From 8b1bcc0634f6ce36acfbd2bfdd26690a6323d09c Mon Sep 17 00:00:00 2001
> From: Zhengxu <zhengxu.maxwell at gmail.com>
> Date: Fri, 16 Dec 2016 11:10:34 +0800
> Subject: [PATCH] libavutil/hwcontext_qsv: Fix bug that the QSV encoded frames'
>  width and height are 32-aligned.
> 
> Description:
> If an input is of 1280x720, the encoded stream created by command below is of 1280x736:
> ffmpeg -hwaccel qsv -c:v h264_qsv -i test.h264 -c:v h264_qsv out.h264
> 
> Reason:
> When creating a AVQSVFramesContext, width and height shouldn't be aligned, or the mfxSurfaces'
>  cropW and cropH will be wrong.
> 
> Fix:
> User should configure AVQSVFramesContext with origin width and height and AVFramesContext will
>  align the width and height when being initiallized.
> 
> Signed-off-by: ChaoX A Liu <chaox.a.liu at gmail.com>
> Signed-off-by: Huang, Zhengxu <zhengxu.maxwell at gmail.com>
> Signed-off-by: Andrew, Zhang <huazh407 at gmail.com>
> ---
>  ffmpeg_qsv.c              | 8 ++++----
>  libavutil/hwcontext_qsv.c | 8 ++++++--
>  2 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/ffmpeg_qsv.c b/ffmpeg_qsv.c
> index 68ff5bd..aab7375 100644
> --- a/ffmpeg_qsv.c
> +++ b/ffmpeg_qsv.c
> @@ -76,8 +76,8 @@ int qsv_init(AVCodecContext *s)
>      frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
>      frames_hwctx = frames_ctx->hwctx;
>  
> -    frames_ctx->width             = FFALIGN(s->coded_width,  32);
> -    frames_ctx->height            = FFALIGN(s->coded_height, 32);
> +    frames_ctx->width             = s->coded_width;
> +    frames_ctx->height            = s->coded_height;
>      frames_ctx->format            = AV_PIX_FMT_QSV;
>      frames_ctx->sw_format         = s->sw_pix_fmt;
>      frames_ctx->initial_pool_size = 64;
> @@ -152,8 +152,8 @@ int qsv_transcode_init(OutputStream *ost)
>      encode_frames = (AVHWFramesContext*)encode_frames_ref->data;
>      qsv_frames = encode_frames->hwctx;
>  
> -    encode_frames->width     = FFALIGN(ist->resample_width,  32);
> -    encode_frames->height    = FFALIGN(ist->resample_height, 32);
> +    encode_frames->width     = ist->resample_width;
> +    encode_frames->height    = ist->resample_height;
>      encode_frames->format    = AV_PIX_FMT_QSV;
>      encode_frames->sw_format = AV_PIX_FMT_NV12;
>      encode_frames->initial_pool_size = 1;
> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
> index 03244a6..2dc9aca 100644
> --- a/libavutil/hwcontext_qsv.c
> +++ b/libavutil/hwcontext_qsv.c
> @@ -308,9 +308,13 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
>              surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV444;
>  
>          surf->Info.FourCC         = fourcc;
> -        surf->Info.Width          = ctx->width;
> +        /*
> +         * WxH being aligned with 32x32 is needed by MSDK.
> +         * CropW and CropH are the real size of the frame.
> +         */
> +        surf->Info.Width          = FFALIGN(ctx->width, 32);
>          surf->Info.CropW          = ctx->width;
> -        surf->Info.Height         = ctx->height;
> +        surf->Info.Height         = FFALIGN(ctx->height, 32);
>          surf->Info.CropH          = ctx->height;
>          surf->Info.FrameRateExtN  = 25;
>          surf->Info.FrameRateExtD  = 1;
> -- 
> 1.8.3.1
> 

This seems wrong to me - the hwcontext code is only dealing in surfaces, and should not be interested in the actual dimensions of the frame on each surface (that is a per-frame property anyway, since it need not be the same for all frames in a context).

Is it possible to instead fix this case by adjusting the cropping parameters after copying the FrameInfo at libavcodec/qsvenc.c:378?  Maybe this (not tested at all):

diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index ac443c1a26..32e2a4ed13 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -376,6 +376,8 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
         AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
         AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
         q->param.mfx.FrameInfo = frames_hwctx->surfaces[0].Info;
+        q->param.mfx.FrameInfo.CropW = avctx->width;
+        q->param.mfx.FrameInfo.CropH = avctx->height;
     } else {
         q->param.mfx.FrameInfo.FourCC         = MFX_FOURCC_NV12;
         q->param.mfx.FrameInfo.Width          = FFALIGN(avctx->width, q->width_align);

Thanks,

- Mark



More information about the ffmpeg-devel mailing list