mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-01-27 09:43:34 +00:00
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@intel.com>
This commit is contained in:
parent
a5e1cb9e96
commit
681aa7d14f
@ -862,6 +862,10 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
|
|||||||
mfxSyncPoint sync = NULL;
|
mfxSyncPoint sync = NULL;
|
||||||
mfxStatus err;
|
mfxStatus err;
|
||||||
int ret = 0;
|
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) {
|
while (!s->session_upload_init && !s->session_upload && !ret) {
|
||||||
#if HAVE_PTHREADS
|
#if HAVE_PTHREADS
|
||||||
@ -887,16 +891,36 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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->session_upload) {
|
||||||
if (s->child_frames_ref)
|
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");
|
av_log(ctx, AV_LOG_ERROR, "Surface upload not possible\n");
|
||||||
return AVERROR(ENOSYS);
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
in.Info = out->Info;
|
in.Info = out->Info;
|
||||||
map_frame_to_surface(src, &in);
|
map_frame_to_surface(src_frame, &in);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
err = MFXVideoVPP_RunFrameVPPAsync(s->session_upload, &in, out, NULL, &sync);
|
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;
|
return AVERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (realigned)
|
||||||
|
av_frame_unref(&tmp_frame);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user