[FFmpeg-cvslog] lavu/qsv: make a copy as libmfx alignment requirement for uploading
Zhong Li
git at videolan.org
Thu Oct 11 08:38:22 EEST 2018
ffmpeg | branch: master | Zhong Li <zhong.li at intel.com> | Mon Sep 17 19:16:44 2018 +0800| [681aa7d14f97fd98181ca6d61e11be48fe65692d] | committer: Zhong Li
lavu/qsv: make a copy as libmfx alignment requirement for uploading
Libmfx requires 16 bytes aligned input/output for uploading.
Currently only output is 16 byte aligned and assigning same width/height to
input with smaller buffer size actually, thus definitely will cause segment fault.
Can reproduce with any 1080p nv12 rawvideo input:
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -f rawvideo -pix_fmt nv12 -s:v 1920x1080
-i 1080p_nv12.yuv -vf 'format=nv12,hwupload=extra_hw_frames=16,hwdownload,format=nv12' -an -y out_nv12.yuv
It can fix #7418
Signed-off-by: Zhong Li <zhong.li at intel.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=681aa7d14f97fd98181ca6d61e11be48fe65692d
---
libavutil/hwcontext_qsv.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 33e121b416..814ce215ce 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -862,6 +862,10 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
mfxSyncPoint sync = NULL;
mfxStatus err;
int ret = 0;
+ /* make a copy if the input is not padded as libmfx requires */
+ AVFrame tmp_frame, *src_frame;
+ int realigned = 0;
+
while (!s->session_upload_init && !s->session_upload && !ret) {
#if HAVE_PTHREADS
@@ -887,16 +891,36 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
if (ret < 0)
return ret;
+
+ if (src->height & 16 || src->linesize[0] & 16) {
+ realigned = 1;
+ memset(&tmp_frame, 0, sizeof(tmp_frame));
+ tmp_frame.format = src->format;
+ tmp_frame.width = FFALIGN(src->width, 16);
+ tmp_frame.height = FFALIGN(src->height, 16);
+ ret = av_frame_get_buffer(&tmp_frame, 32);
+ if (ret < 0)
+ return ret;
+
+ ret = av_frame_copy(&tmp_frame, src);
+ if (ret < 0) {
+ av_frame_unref(&tmp_frame);
+ return ret;
+ }
+ }
+
+ src_frame = realigned ? &tmp_frame : src;
+
if (!s->session_upload) {
if (s->child_frames_ref)
- return qsv_transfer_data_child(ctx, dst, src);
+ return qsv_transfer_data_child(ctx, dst, src_frame);
av_log(ctx, AV_LOG_ERROR, "Surface upload not possible\n");
return AVERROR(ENOSYS);
}
in.Info = out->Info;
- map_frame_to_surface(src, &in);
+ map_frame_to_surface(src_frame, &in);
do {
err = MFXVideoVPP_RunFrameVPPAsync(s->session_upload, &in, out, NULL, &sync);
@@ -917,6 +941,9 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
return AVERROR_UNKNOWN;
}
+ if (realigned)
+ av_frame_unref(&tmp_frame);
+
return 0;
}
More information about the ffmpeg-cvslog
mailing list