History

libavutil/hwcontext_qsv: Align width and heigh when download qsv frame

The width and height for qsv frame to download need to be aligned with 16. Add the alignment operation. Now the following command works: ffmpeg -hwaccel qsv -f rawvideo -s 1920x1080 -pix_fmt yuv420p -i \ input.yuv -vf "hwupload=extra_hw_frames=16,format=qsv,hwdownload, \ format=nv12" -f null -

Wenbin Chen committed 4 years ago

Commit 7e7b3a41 parent 7427b871 file · +42 −5Browse files

Unified · Split

libavutil/hwcontext_qsv.c+42−5
@@ -91,7 +91,8 @@ typedef struct QSVFramesContext { · 90 unmodified lines
9191
9292 mfxExtOpaqueSurfaceAlloc opaque_alloc;
9393 mfxExtBuffer *ext_buffers[1];
94− AVFrame realigned_tmp_frame;
94+ AVFrame realigned_upload_frame;
95+ AVFrame realigned_download_frame;
9596 } QSVFramesContext;
9697
9798 static const struct {
@@ -303,7 +304,8 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) · 205 unmodified lines
303304 av_freep(&s->surface_ptrs);
304305 av_freep(&s->surfaces_internal);
305306 av_freep(&s->handle_pairs_internal);
306− av_frame_unref(&s->realigned_tmp_frame);
307+ av_frame_unref(&s->realigned_upload_frame);
308+ av_frame_unref(&s->realigned_download_frame);
307309 av_buffer_unref(&s->child_frames_ref);
308310 }
309311
@@ -1058,21 +1060,46 @@ static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, · 748 unmodified lines
10581060 mfxSyncPoint sync = NULL;
10591061 mfxStatus err;
10601062 int ret = 0;
1063+ /* download to temp frame if the output is not padded as libmfx requires */
1064+ AVFrame *tmp_frame = &s->realigned_download_frame;
1065+ AVFrame *dst_frame;
1066+ int realigned = 0;
10611067
10621068 ret = qsv_internal_session_check_init(ctx, 0);
10631069 if (ret < 0)
10641070 return ret;
10651071
1072+ /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16.
1073+ * Height must be a multiple of 16 for progressive frame sequence and a
1074+ * multiple of 32 otherwise.", so allign all frames to 16 before downloading. */
1075+ if (dst->height & 15 || dst->linesize[0] & 15) {
1076+ realigned = 1;
1077+ if (tmp_frame->format != dst->format ||
1078+ tmp_frame->width != FFALIGN(dst->linesize[0], 16) ||
1079+ tmp_frame->height != FFALIGN(dst->height, 16)) {
1080+ av_frame_unref(tmp_frame);
1081+
1082+ tmp_frame->format = dst->format;
1083+ tmp_frame->width = FFALIGN(dst->linesize[0], 16);
1084+ tmp_frame->height = FFALIGN(dst->height, 16);
1085+ ret = av_frame_get_buffer(tmp_frame, 0);
1086+ if (ret < 0)
1087+ return ret;
1088+ }
1089+ }
1090+
1091+ dst_frame = realigned ? tmp_frame : dst;
1092+
10661093 if (!s->session_download) {
10671094 if (s->child_frames_ref)
1068− return qsv_transfer_data_child(ctx, dst, src);
1095+ return qsv_transfer_data_child(ctx, dst_frame, src);
10691096
10701097 av_log(ctx, AV_LOG_ERROR, "Surface download not possible\n");
10711098 return AVERROR(ENOSYS);
10721099 }
10731100
10741101 out.Info = in->Info;
1075− map_frame_to_surface(dst, &out);
1102+ map_frame_to_surface(dst_frame, &out);
10761103
10771104 do {
10781105 err = MFXVideoVPP_RunFrameVPPAsync(s->session_download, in, &out, NULL, &sync);
@@ -1093,6 +1120,16 @@ static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, · 14 unmodified lines
10931120 return AVERROR_UNKNOWN;
10941121 }
10951122
1123+ if (realigned) {
1124+ tmp_frame->width = dst->width;
1125+ tmp_frame->height = dst->height;
1126+ ret = av_frame_copy(dst, tmp_frame);
1127+ tmp_frame->width = FFALIGN(dst->linesize[0], 16);
1128+ tmp_frame->height = FFALIGN(dst->height, 16);
1129+ if (ret < 0)
1130+ return ret;
1131+ }
1132+
10961133 return 0;
10971134 }
10981135
@@ -1108,7 +1145,7 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, · 9 unmodified lines
11081145 mfxStatus err;
11091146 int ret = 0;
11101147 /* make a copy if the input is not padded as libmfx requires */
1111− AVFrame *tmp_frame = &s->realigned_tmp_frame;
1148+ AVFrame *tmp_frame = &s->realigned_upload_frame;
11121149 const AVFrame *src_frame;
11131150 int realigned = 0;
11141151

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t