blob: e137a38e3c6a4d84742b739632d86b9c27675248 [file] [log] [blame]
Anton Khirnov4e08c822015-02-10 09:40:591/*
2 * Intel MediaSDK QSV codec-independent code
3 *
4 * copyright (c) 2013 Luca Barbato
5 * copyright (c) 2015 Anton Khirnov <[email protected]>
6 *
Michael Niedermayer841e9f42015-02-19 19:52:297 * This file is part of FFmpeg.
Anton Khirnov4e08c822015-02-10 09:40:598 *
Michael Niedermayer841e9f42015-02-19 19:52:299 * FFmpeg is free software; you can redistribute it and/or
Anton Khirnov4e08c822015-02-10 09:40:5910 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
Michael Niedermayer841e9f42015-02-19 19:52:2914 * FFmpeg is distributed in the hope that it will be useful,
Anton Khirnov4e08c822015-02-10 09:40:5915 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
Michael Niedermayer841e9f42015-02-19 19:52:2920 * License along with FFmpeg; if not, write to the Free Software
Anton Khirnov4e08c822015-02-10 09:40:5921 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
Martin Storsjöa78f1362022-02-23 12:56:4924#include "config_components.h"
25
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4126#include <stdint.h>
Anton Khirnov4e08c822015-02-10 09:40:5927#include <string.h>
28#include <sys/types.h>
29
Haihao Xiang3e61b7d2020-09-08 03:17:2730#include <mfxvideo.h>
Anton Khirnov4e08c822015-02-10 09:40:5931
32#include "libavutil/common.h"
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4133#include "libavutil/fifo.h"
34#include "libavutil/frame.h"
Mark Thompson1f26a232016-10-21 17:57:1235#include "libavutil/hwcontext.h"
36#include "libavutil/hwcontext_qsv.h"
Anton Khirnov4e08c822015-02-10 09:40:5937#include "libavutil/mem.h"
38#include "libavutil/log.h"
Xu Guangxin399c1f92021-01-05 02:43:4039#include "libavutil/opt.h"
Anton Khirnov4e08c822015-02-10 09:40:5940#include "libavutil/pixfmt.h"
41#include "libavutil/time.h"
Linjie Fu53459652019-10-08 13:41:0242#include "libavutil/imgutils.h"
Haihao Xiang8ca06a82022-01-24 08:24:5543#include "libavutil/film_grain_params.h"
Haihao Xiang71cded62022-11-21 02:31:2444#include "libavutil/mastering_display_metadata.h"
Anton Khirnov4e08c822015-02-10 09:40:5945
46#include "avcodec.h"
Andreas Rheinhardt20f97272022-03-16 20:09:5447#include "codec_internal.h"
Anton Khirnov4e08c822015-02-10 09:40:5948#include "internal.h"
Linjie Fu53459652019-10-08 13:41:0249#include "decode.h"
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4150#include "hwconfig.h"
Ivan Uskov6e127992015-07-14 11:07:0451#include "qsv.h"
Anton Khirnovd0a63d82015-03-13 07:13:0052#include "qsv_internal.h"
Anton Khirnov4e08c822015-02-10 09:40:5953
Haihao Xiang6900fee2021-01-04 02:46:1454#if QSV_ONEVPL
55#include <mfxdispatcher.h>
56#else
57#define MFXUnload(a) do { } while(0)
58#endif
59
Haihao Xiang971b4ac2021-06-11 02:19:4560static const AVRational mfx_tb = { 1, 90000 };
61
62#define PTS_TO_MFX_PTS(pts, pts_tb) ((pts) == AV_NOPTS_VALUE ? \
63 MFX_TIMESTAMP_UNKNOWN : pts_tb.num ? \
64 av_rescale_q(pts, pts_tb, mfx_tb) : pts)
65
66#define MFX_PTS_TO_PTS(mfx_pts, pts_tb) ((mfx_pts) == MFX_TIMESTAMP_UNKNOWN ? \
67 AV_NOPTS_VALUE : pts_tb.num ? \
68 av_rescale_q(mfx_pts, mfx_tb, pts_tb) : mfx_pts)
69
Anton Khirnov08181622022-01-06 16:16:4770typedef struct QSVAsyncFrame {
71 mfxSyncPoint *sync;
72 QSVFrame *frame;
73} QSVAsyncFrame;
74
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4175typedef struct QSVContext {
76 // the session used for decoding
77 mfxSession session;
Haihao Xiang7c24a762022-01-24 08:24:5478 mfxVersion ver;
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4179
80 // the session we allocated internally, in case the caller did not provide
81 // one
82 QSVSession internal_qs;
83
84 QSVFramesContext frames_ctx;
85
86 /**
87 * a linked list of frames currently being used by QSV
88 */
89 QSVFrame *work_frames;
90
Anton Khirnov08181622022-01-06 16:16:4791 AVFifo *async_fifo;
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4192 int zero_consume_run;
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4193 int reinit_flag;
94
95 enum AVPixelFormat orig_pix_fmt;
96 uint32_t fourcc;
97 mfxFrameInfo frame_info;
98 AVBufferPool *pool;
Wenbin Chen0a0847d2022-03-18 06:25:1199 int suggest_pool_size;
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41100 int initialized;
101
102 // options set by the caller
103 int async_depth;
104 int iopattern;
105 int gpu_copy;
106
107 char *load_plugins;
108
109 mfxExtBuffer **ext_buffers;
110 int nb_ext_buffers;
111} QSVContext;
112
113static const AVCodecHWConfigInternal *const qsv_hw_configs[] = {
Mark Thompson758fbc52017-10-25 23:18:40114 &(const AVCodecHWConfigInternal) {
115 .public = {
116 .pix_fmt = AV_PIX_FMT_QSV,
117 .methods = AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX |
Haihao Xiangecee3b02021-08-11 06:01:54118 AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX,
Mark Thompson758fbc52017-10-25 23:18:40119 .device_type = AV_HWDEVICE_TYPE_QSV,
120 },
121 .hwaccel = NULL,
122 },
123 NULL
124};
125
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41126static int qsv_get_continuous_buffer(AVCodecContext *avctx, AVFrame *frame,
127 AVBufferPool *pool)
Linjie Fu53459652019-10-08 13:41:02128{
129 int ret = 0;
130
Anton Khirnov5bf8f292023-01-05 08:50:57131 ret = ff_decode_frame_props(avctx, frame);
132 if (ret < 0)
133 return ret;
Linjie Fu53459652019-10-08 13:41:02134
135 frame->width = avctx->width;
136 frame->height = avctx->height;
137
138 switch (avctx->pix_fmt) {
139 case AV_PIX_FMT_NV12:
140 frame->linesize[0] = FFALIGN(avctx->width, 128);
141 break;
142 case AV_PIX_FMT_P010:
Fei Wang56a52af2022-10-06 07:35:38143 case AV_PIX_FMT_P012:
Wenbin Chene0ae8102022-04-06 08:48:03144 case AV_PIX_FMT_YUYV422:
Linjie Fu53459652019-10-08 13:41:02145 frame->linesize[0] = 2 * FFALIGN(avctx->width, 128);
146 break;
Wenbin Chene0ae8102022-04-06 08:48:03147 case AV_PIX_FMT_Y210:
Haihao Xiangdb85e012022-09-06 04:53:38148 case AV_PIX_FMT_VUYX:
Haihao Xiang1898dbd2022-10-06 07:35:36149 case AV_PIX_FMT_XV30:
Fei Wang56a52af2022-10-06 07:35:38150 case AV_PIX_FMT_Y212:
Wenbin Chene0ae8102022-04-06 08:48:03151 frame->linesize[0] = 4 * FFALIGN(avctx->width, 128);
152 break;
Fei Wang56a52af2022-10-06 07:35:38153 case AV_PIX_FMT_XV36:
154 frame->linesize[0] = 8 * FFALIGN(avctx->width, 128);
155 break;
Linjie Fu53459652019-10-08 13:41:02156 default:
157 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n");
Zhong Li9fff5c42019-12-28 14:22:07158 return AVERROR(EINVAL);
Linjie Fu53459652019-10-08 13:41:02159 }
160
Linjie Fu53459652019-10-08 13:41:02161 frame->buf[0] = av_buffer_pool_get(pool);
162 if (!frame->buf[0])
163 return AVERROR(ENOMEM);
164
165 frame->data[0] = frame->buf[0]->data;
Wenbin Chene0ae8102022-04-06 08:48:03166 if (avctx->pix_fmt == AV_PIX_FMT_NV12 ||
Fei Wang56a52af2022-10-06 07:35:38167 avctx->pix_fmt == AV_PIX_FMT_P010 ||
168 avctx->pix_fmt == AV_PIX_FMT_P012) {
Wenbin Chene0ae8102022-04-06 08:48:03169 frame->linesize[1] = frame->linesize[0];
170 frame->data[1] = frame->data[0] +
171 frame->linesize[0] * FFALIGN(avctx->height, 64);
172 }
Linjie Fu53459652019-10-08 13:41:02173
174 ret = ff_attach_decode_data(frame);
175 if (ret < 0)
176 return ret;
177
178 return 0;
179}
180
Mark Thompson1f26a232016-10-21 17:57:12181static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session,
Mark Thompson8aa3c2d2017-03-04 23:57:36182 AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref)
Anton Khirnov4e08c822015-02-10 09:40:59183{
Mark Thompson1f26a232016-10-21 17:57:12184 int ret;
185
Linjie Fu53459652019-10-08 13:41:02186 if (q->gpu_copy == MFX_GPUCOPY_ON &&
Zhong Li779951f2019-12-28 14:28:45187 !(q->iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) {
Linjie Fu53459652019-10-08 13:41:02188 av_log(avctx, AV_LOG_WARNING, "GPU-accelerated memory copy "
Zhong Li779951f2019-12-28 14:28:45189 "only works in system memory mode.\n");
190 q->gpu_copy = MFX_GPUCOPY_OFF;
191 }
Mark Thompson1f26a232016-10-21 17:57:12192 if (session) {
193 q->session = session;
194 } else if (hw_frames_ref) {
Zhong Li74007dd2019-09-19 20:45:26195 if (q->internal_qs.session) {
196 MFXClose(q->internal_qs.session);
197 q->internal_qs.session = NULL;
Mark Thompson1f26a232016-10-21 17:57:12198 }
199 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
200
201 q->frames_ctx.hw_frames_ctx = av_buffer_ref(hw_frames_ref);
202 if (!q->frames_ctx.hw_frames_ctx)
203 return AVERROR(ENOMEM);
204
Zhong Li74007dd2019-09-19 20:45:26205 ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
Mark Thompson91c3b502017-03-04 23:57:35206 &q->frames_ctx, q->load_plugins,
Haihao Xiangc77149b2020-08-19 01:43:12207#if QSV_HAVE_OPAQUE
Linjie Fu53459652019-10-08 13:41:02208 q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
Haihao Xiangc77149b2020-08-19 01:43:12209#else
210 0,
211#endif
Linjie Fu53459652019-10-08 13:41:02212 q->gpu_copy);
Mark Thompson1f26a232016-10-21 17:57:12213 if (ret < 0) {
214 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
215 return ret;
216 }
217
Zhong Li74007dd2019-09-19 20:45:26218 q->session = q->internal_qs.session;
Mark Thompson8aa3c2d2017-03-04 23:57:36219 } else if (hw_device_ref) {
Zhong Li74007dd2019-09-19 20:45:26220 if (q->internal_qs.session) {
221 MFXClose(q->internal_qs.session);
222 q->internal_qs.session = NULL;
Mark Thompson8aa3c2d2017-03-04 23:57:36223 }
224
Zhong Li74007dd2019-09-19 20:45:26225 ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session,
Linjie Fu53459652019-10-08 13:41:02226 hw_device_ref, q->load_plugins, q->gpu_copy);
Mark Thompson8aa3c2d2017-03-04 23:57:36227 if (ret < 0)
228 return ret;
229
Zhong Li74007dd2019-09-19 20:45:26230 q->session = q->internal_qs.session;
Mark Thompson1f26a232016-10-21 17:57:12231 } else {
Zhong Li74007dd2019-09-19 20:45:26232 if (!q->internal_qs.session) {
233 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
Linjie Fu53459652019-10-08 13:41:02234 q->load_plugins, q->gpu_copy);
Anton Khirnovd0a63d82015-03-13 07:13:00235 if (ret < 0)
236 return ret;
Anton Khirnov4e08c822015-02-10 09:40:59237 }
238
Zhong Li74007dd2019-09-19 20:45:26239 q->session = q->internal_qs.session;
Anton Khirnov4e08c822015-02-10 09:40:59240 }
241
Haihao Xiang7c24a762022-01-24 08:24:54242 if (MFXQueryVersion(q->session, &q->ver) != MFX_ERR_NONE) {
243 av_log(avctx, AV_LOG_ERROR, "Error querying the session version. \n");
244 q->session = NULL;
245
246 if (q->internal_qs.session) {
247 MFXClose(q->internal_qs.session);
248 q->internal_qs.session = NULL;
249 }
250
Haihao Xiang6900fee2021-01-04 02:46:14251 if (q->internal_qs.loader) {
252 MFXUnload(q->internal_qs.loader);
253 q->internal_qs.loader = NULL;
254 }
255
Haihao Xiang7c24a762022-01-24 08:24:54256 return AVERROR_EXTERNAL;
257 }
258
Mark Thompson1f26a232016-10-21 17:57:12259 /* make sure the decoder is uninitialized */
260 MFXVideoDECODE_Close(q->session);
261
262 return 0;
Anton Khirnov4e08c822015-02-10 09:40:59263}
264
Zhong Li00d0a4a2019-08-13 06:11:09265static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixelFormat pix_fmt, mfxVideoParam *param)
Anton Khirnov4e08c822015-02-10 09:40:59266{
Anton Khirnov6f19bbc2016-05-21 16:26:40267 mfxSession session = NULL;
Mark Thompson1f26a232016-10-21 17:57:12268 int iopattern = 0;
Anton Khirnov4e08c822015-02-10 09:40:59269 int ret;
Zhong Li00d0a4a2019-08-13 06:11:09270 enum AVPixelFormat pix_fmts[3] = {
271 AV_PIX_FMT_QSV, /* opaque format in case of video memory output */
272 pix_fmt, /* system memory format obtained from bitstream parser */
273 AV_PIX_FMT_NONE };
Anton Khirnov4e08c822015-02-10 09:40:59274
Zhong Li00d0a4a2019-08-13 06:11:09275 ret = ff_get_format(avctx, pix_fmts);
276 if (ret < 0) {
277 q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE;
278 return ret;
279 }
Anton Khirnov92736c72016-06-22 09:53:00280
Mark Thompson1f26a232016-10-21 17:57:12281 if (!q->async_fifo) {
Anton Khirnov08181622022-01-06 16:16:47282 q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVAsyncFrame), 0);
Mark Thompson1f26a232016-10-21 17:57:12283 if (!q->async_fifo)
284 return AVERROR(ENOMEM);
Hendrik Leppkesb54d6452015-10-22 15:00:49285 }
Hendrik Leppkesb54d6452015-10-22 15:00:49286
Anton Khirnove3281782016-07-30 14:38:51287 if (avctx->pix_fmt == AV_PIX_FMT_QSV && avctx->hwaccel_context) {
Mark Thompson1f26a232016-10-21 17:57:12288 AVQSVContext *user_ctx = avctx->hwaccel_context;
289 session = user_ctx->session;
290 iopattern = user_ctx->iopattern;
291 q->ext_buffers = user_ctx->ext_buffers;
292 q->nb_ext_buffers = user_ctx->nb_ext_buffers;
293 }
294
Haihao Xiangecee3b02021-08-11 06:01:54295 if (avctx->hw_device_ctx && !avctx->hw_frames_ctx && ret == AV_PIX_FMT_QSV) {
296 AVHWFramesContext *hwframes_ctx;
297 AVQSVFramesContext *frames_hwctx;
298
299 avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
300
301 if (!avctx->hw_frames_ctx) {
302 av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n");
303 return AVERROR(ENOMEM);
304 }
305
306 hwframes_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
307 frames_hwctx = hwframes_ctx->hwctx;
308 hwframes_ctx->width = FFALIGN(avctx->coded_width, 32);
309 hwframes_ctx->height = FFALIGN(avctx->coded_height, 32);
310 hwframes_ctx->format = AV_PIX_FMT_QSV;
311 hwframes_ctx->sw_format = avctx->sw_pix_fmt;
Wenbin Chen0a0847d2022-03-18 06:25:11312 hwframes_ctx->initial_pool_size = q->suggest_pool_size + 16 + avctx->extra_hw_frames;
Haihao Xiangecee3b02021-08-11 06:01:54313 frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
314
315 ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
316
317 if (ret < 0) {
318 av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame pool\n");
319 av_buffer_unref(&avctx->hw_frames_ctx);
320 return ret;
321 }
322 }
323
Mark Thompson1f26a232016-10-21 17:57:12324 if (avctx->hw_frames_ctx) {
325 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
326 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
327
328 if (!iopattern) {
Haihao Xiangc77149b2020-08-19 01:43:12329#if QSV_HAVE_OPAQUE
Mark Thompson1f26a232016-10-21 17:57:12330 if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
331 iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
332 else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
333 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
Haihao Xiangc77149b2020-08-19 01:43:12334#else
335 if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
336 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
337#endif
Mark Thompson1f26a232016-10-21 17:57:12338 }
339 }
340
341 if (!iopattern)
342 iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
343 q->iopattern = iopattern;
344
Zhong Li525de952019-09-19 20:45:27345 ff_qsv_print_iopattern(avctx, q->iopattern, "Decoder");
346
Mark Thompson8aa3c2d2017-03-04 23:57:36347 ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx);
Anton Khirnov4e08c822015-02-10 09:40:59348 if (ret < 0) {
349 av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
350 return ret;
Ivan Uskov6e127992015-07-14 11:07:04351 }
Anton Khirnov4e08c822015-02-10 09:40:59352
Zhong Li00d0a4a2019-08-13 06:11:09353 param->IOPattern = q->iopattern;
354 param->AsyncDepth = q->async_depth;
355 param->ExtParam = q->ext_buffers;
356 param->NumExtParam = q->nb_ext_buffers;
Mark Thompson1f26a232016-10-21 17:57:12357
Zhong Li00d0a4a2019-08-13 06:11:09358 return 0;
359 }
Mark Thompson1f26a232016-10-21 17:57:12360
Xu Guangxin399c1f92021-01-05 02:43:40361static int qsv_decode_init_context(AVCodecContext *avctx, QSVContext *q, mfxVideoParam *param)
Zhong Li00d0a4a2019-08-13 06:11:09362{
363 int ret;
Mark Thompson1f26a232016-10-21 17:57:12364
Zhong Li00d0a4a2019-08-13 06:11:09365 avctx->width = param->mfx.FrameInfo.CropW;
366 avctx->height = param->mfx.FrameInfo.CropH;
367 avctx->coded_width = param->mfx.FrameInfo.Width;
368 avctx->coded_height = param->mfx.FrameInfo.Height;
369 avctx->level = param->mfx.CodecLevel;
370 avctx->profile = param->mfx.CodecProfile;
371 avctx->field_order = ff_qsv_map_picstruct(param->mfx.FrameInfo.PicStruct);
372 avctx->pix_fmt = ff_qsv_map_fourcc(param->mfx.FrameInfo.FourCC);
Anton Khirnov4e08c822015-02-10 09:40:59373
Zhong Li00d0a4a2019-08-13 06:11:09374 ret = MFXVideoDECODE_Init(q->session, param);
Anton Khirnov95414eb2016-06-25 19:38:10375 if (ret < 0)
376 return ff_qsv_print_error(avctx, ret,
377 "Error initializing the MFX video decoder");
Anton Khirnov4e08c822015-02-10 09:40:59378
Zhong Li00d0a4a2019-08-13 06:11:09379 q->frame_info = param->mfx.FrameInfo;
380
Linjie Fu53459652019-10-08 13:41:02381 if (!avctx->hw_frames_ctx)
382 q->pool = av_buffer_pool_init(av_image_get_buffer_size(avctx->pix_fmt,
383 FFALIGN(avctx->width, 128), FFALIGN(avctx->height, 64), 1), av_buffer_allocz);
Zhong Li00d0a4a2019-08-13 06:11:09384 return 0;
385}
386
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41387static int qsv_decode_header(AVCodecContext *avctx, QSVContext *q,
388 const AVPacket *avpkt, enum AVPixelFormat pix_fmt,
389 mfxVideoParam *param)
Zhong Li00d0a4a2019-08-13 06:11:09390{
391 int ret;
Haihao Xiangc8cfe672021-07-28 08:15:46392 mfxExtVideoSignalInfo video_signal_info = { 0 };
393 mfxExtBuffer *header_ext_params[1] = { (mfxExtBuffer *)&video_signal_info };
Zhong Li00d0a4a2019-08-13 06:11:09394 mfxBitstream bs = { 0 };
395
396 if (avpkt->size) {
397 bs.Data = avpkt->data;
398 bs.DataLength = avpkt->size;
399 bs.MaxLength = bs.DataLength;
Haihao Xiang971b4ac2021-06-11 02:19:45400 bs.TimeStamp = PTS_TO_MFX_PTS(avpkt->pts, avctx->pkt_timebase);
Zhong Li00d0a4a2019-08-13 06:11:09401 if (avctx->field_order == AV_FIELD_PROGRESSIVE)
402 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
403 } else
404 return AVERROR_INVALIDDATA;
405
406
407 if(!q->session) {
408 ret = qsv_decode_preinit(avctx, q, pix_fmt, param);
409 if (ret < 0)
410 return ret;
411 }
412
413 ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
414 if (ret < 0)
415 return ret;
416
417 param->mfx.CodecId = ret;
Haihao Xiangc8cfe672021-07-28 08:15:46418 video_signal_info.Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO;
419 video_signal_info.Header.BufferSz = sizeof(video_signal_info);
420 // The SDK doesn't support other ext buffers when calling MFXVideoDECODE_DecodeHeader,
421 // so do not append this buffer to the existent buffer array
422 param->ExtParam = header_ext_params;
423 param->NumExtParam = 1;
Zhong Li00d0a4a2019-08-13 06:11:09424 ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, param);
425 if (MFX_ERR_MORE_DATA == ret) {
426 return AVERROR(EAGAIN);
427 }
428 if (ret < 0)
429 return ff_qsv_print_error(avctx, ret,
430 "Error decoding stream header");
Anton Khirnovce320cf2016-06-22 09:44:09431
Haihao Xiangc8cfe672021-07-28 08:15:46432 avctx->color_range = video_signal_info.VideoFullRange ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
433
434 if (video_signal_info.ColourDescriptionPresent) {
435 avctx->color_primaries = video_signal_info.ColourPrimaries;
436 avctx->color_trc = video_signal_info.TransferCharacteristics;
437 avctx->colorspace = video_signal_info.MatrixCoefficients;
438 }
439
440 param->ExtParam = q->ext_buffers;
441 param->NumExtParam = q->nb_ext_buffers;
442
Haihao Xiang8ca06a82022-01-24 08:24:55443#if QSV_VERSION_ATLEAST(1, 34)
444 if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && avctx->codec_id == AV_CODEC_ID_AV1)
445 param->mfx.FilmGrain = (avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) ? 0 : param->mfx.FilmGrain;
446#endif
447
Anton Khirnov4e08c822015-02-10 09:40:59448 return 0;
449}
450
Anton Khirnovce320cf2016-06-22 09:44:09451static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame)
Anton Khirnov4e08c822015-02-10 09:40:59452{
453 int ret;
454
Linjie Fu53459652019-10-08 13:41:02455 if (q->pool)
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41456 ret = qsv_get_continuous_buffer(avctx, frame->frame, q->pool);
Linjie Fu53459652019-10-08 13:41:02457 else
458 ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
459
Anton Khirnov4e08c822015-02-10 09:40:59460 if (ret < 0)
461 return ret;
462
463 if (frame->frame->format == AV_PIX_FMT_QSV) {
Anton Khirnov404e5142016-08-09 10:05:49464 frame->surface = *(mfxFrameSurface1*)frame->frame->data[3];
Anton Khirnov4e08c822015-02-10 09:40:59465 } else {
Wenbin Chene0ae8102022-04-06 08:48:03466 ret = ff_qsv_map_frame_to_surface(frame->frame, &frame->surface);
467 if (ret < 0) {
468 av_log(avctx, AV_LOG_ERROR, "map frame to surface failed.\n");
469 return ret;
470 }
Anton Khirnov4e08c822015-02-10 09:40:59471 }
472
Wenbin Chenb1c26ce2022-02-11 02:37:36473 frame->surface.Info = q->frame_info;
474
Anton Khirnov00aeedd2016-08-10 06:29:23475 if (q->frames_ctx.mids) {
476 ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame);
477 if (ret < 0)
478 return ret;
479
480 frame->surface.Data.MemId = &q->frames_ctx.mids[ret];
481 }
Haihao Xiang8dd507b2022-01-24 08:24:53482
483 frame->surface.Data.ExtParam = frame->ext_param;
484 frame->surface.Data.NumExtParam = 0;
485 frame->num_ext_params = 0;
Zhong Li52ed83f2018-04-04 09:51:29486 frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO;
487 frame->dec_info.Header.BufferSz = sizeof(frame->dec_info);
Haihao Xiang8dd507b2022-01-24 08:24:53488 ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->dec_info);
Haihao Xiang8ca06a82022-01-24 08:24:55489#if QSV_VERSION_ATLEAST(1, 34)
490 if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && avctx->codec_id == AV_CODEC_ID_AV1) {
491 frame->av1_film_grain_param.Header.BufferId = MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM;
492 frame->av1_film_grain_param.Header.BufferSz = sizeof(frame->av1_film_grain_param);
493 frame->av1_film_grain_param.FilmGrainFlags = 0;
494 ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->av1_film_grain_param);
495 }
496#endif
Anton Khirnov00aeedd2016-08-10 06:29:23497
Haihao Xiang71cded62022-11-21 02:31:24498#if QSV_VERSION_ATLEAST(1, 35)
499 if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 35) && avctx->codec_id == AV_CODEC_ID_HEVC) {
500 frame->mdcv.Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME;
501 frame->mdcv.Header.BufferSz = sizeof(frame->mdcv);
502 // The data in mdcv is valid when this flag is 1
503 frame->mdcv.InsertPayloadToggle = 0;
504 ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->mdcv);
505
506 frame->clli.Header.BufferId = MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO;
507 frame->clli.Header.BufferSz = sizeof(frame->clli);
508 // The data in clli is valid when this flag is 1
509 frame->clli.InsertPayloadToggle = 0;
510 ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->clli);
511 }
512#endif
513
Anton Khirnov404e5142016-08-09 10:05:49514 frame->used = 1;
515
Anton Khirnov4e08c822015-02-10 09:40:59516 return 0;
517}
518
519static void qsv_clear_unused_frames(QSVContext *q)
520{
521 QSVFrame *cur = q->work_frames;
522 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49523 if (cur->used && !cur->surface.Data.Locked && !cur->queued) {
524 cur->used = 0;
Anton Khirnov4e08c822015-02-10 09:40:59525 av_frame_unref(cur->frame);
526 }
527 cur = cur->next;
528 }
529}
530
531static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
532{
533 QSVFrame *frame, **last;
534 int ret;
535
536 qsv_clear_unused_frames(q);
537
538 frame = q->work_frames;
539 last = &q->work_frames;
540 while (frame) {
Anton Khirnov404e5142016-08-09 10:05:49541 if (!frame->used) {
Anton Khirnovce320cf2016-06-22 09:44:09542 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59543 if (ret < 0)
544 return ret;
Anton Khirnov404e5142016-08-09 10:05:49545 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59546 return 0;
547 }
548
549 last = &frame->next;
550 frame = frame->next;
551 }
552
553 frame = av_mallocz(sizeof(*frame));
554 if (!frame)
555 return AVERROR(ENOMEM);
556 frame->frame = av_frame_alloc();
557 if (!frame->frame) {
558 av_freep(&frame);
559 return AVERROR(ENOMEM);
560 }
561 *last = frame;
562
Anton Khirnovce320cf2016-06-22 09:44:09563 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59564 if (ret < 0)
565 return ret;
566
Anton Khirnov404e5142016-08-09 10:05:49567 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59568
569 return 0;
570}
571
Anton Khirnovf5c4d382015-07-14 16:16:26572static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
Anton Khirnov4e08c822015-02-10 09:40:59573{
574 QSVFrame *cur = q->work_frames;
575 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49576 if (surf == &cur->surface)
Anton Khirnovf5c4d382015-07-14 16:16:26577 return cur;
Anton Khirnov4e08c822015-02-10 09:40:59578 cur = cur->next;
579 }
580 return NULL;
581}
582
Haihao Xiang8ca06a82022-01-24 08:24:55583#if QSV_VERSION_ATLEAST(1, 34)
584static int qsv_export_film_grain(AVCodecContext *avctx, mfxExtAV1FilmGrainParam *ext_param, AVFrame *frame)
585{
586 AVFilmGrainParams *fgp;
587 AVFilmGrainAOMParams *aom;
588 int i;
589
590 if (!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_APPLY))
591 return 0;
592
593 fgp = av_film_grain_params_create_side_data(frame);
594
595 if (!fgp)
596 return AVERROR(ENOMEM);
597
598 fgp->type = AV_FILM_GRAIN_PARAMS_AV1;
599 fgp->seed = ext_param->GrainSeed;
600 aom = &fgp->codec.aom;
601
602 aom->chroma_scaling_from_luma = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_CHROMA_SCALING_FROM_LUMA);
603 aom->scaling_shift = ext_param->GrainScalingMinus8 + 8;
604 aom->ar_coeff_lag = ext_param->ArCoeffLag;
605 aom->ar_coeff_shift = ext_param->ArCoeffShiftMinus6 + 6;
606 aom->grain_scale_shift = ext_param->GrainScaleShift;
607 aom->overlap_flag = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_OVERLAP);
608 aom->limit_output_range = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_CLIP_TO_RESTRICTED_RANGE);
609
610 aom->num_y_points = ext_param->NumYPoints;
611
612 for (i = 0; i < aom->num_y_points; i++) {
613 aom->y_points[i][0] = ext_param->PointY[i].Value;
614 aom->y_points[i][1] = ext_param->PointY[i].Scaling;
615 }
616
617 aom->num_uv_points[0] = ext_param->NumCbPoints;
618
619 for (i = 0; i < aom->num_uv_points[0]; i++) {
620 aom->uv_points[0][i][0] = ext_param->PointCb[i].Value;
621 aom->uv_points[0][i][1] = ext_param->PointCb[i].Scaling;
622 }
623
624 aom->num_uv_points[1] = ext_param->NumCrPoints;
625
626 for (i = 0; i < aom->num_uv_points[1]; i++) {
627 aom->uv_points[1][i][0] = ext_param->PointCr[i].Value;
628 aom->uv_points[1][i][1] = ext_param->PointCr[i].Scaling;
629 }
630
631 for (i = 0; i < 24; i++)
632 aom->ar_coeffs_y[i] = ext_param->ArCoeffsYPlus128[i] - 128;
633
634 for (i = 0; i < 25; i++) {
635 aom->ar_coeffs_uv[0][i] = ext_param->ArCoeffsCbPlus128[i] - 128;
636 aom->ar_coeffs_uv[1][i] = ext_param->ArCoeffsCrPlus128[i] - 128;
637 }
638
639 aom->uv_mult[0] = ext_param->CbMult;
640 aom->uv_mult[1] = ext_param->CrMult;
641 aom->uv_mult_luma[0] = ext_param->CbLumaMult;
642 aom->uv_mult_luma[1] = ext_param->CrLumaMult;
643 aom->uv_offset[0] = ext_param->CbOffset;
644 aom->uv_offset[1] = ext_param->CrOffset;
645
646 return 0;
647}
648#endif
649
Haihao Xiang71cded62022-11-21 02:31:24650#if QSV_VERSION_ATLEAST(1, 35)
651static int qsv_export_hdr_side_data(AVCodecContext *avctx, mfxExtMasteringDisplayColourVolume *mdcv,
652 mfxExtContentLightLevelInfo *clli, AVFrame *frame)
653{
654 // The SDK re-uses this flag for HDR SEI parsing
655 if (mdcv->InsertPayloadToggle) {
656 AVMasteringDisplayMetadata *mastering = av_mastering_display_metadata_create_side_data(frame);
657 const int mapping[3] = {2, 0, 1};
658 const int chroma_den = 50000;
659 const int luma_den = 10000;
660 int i;
661
662 if (!mastering)
663 return AVERROR(ENOMEM);
664
665 for (i = 0; i < 3; i++) {
666 const int j = mapping[i];
667 mastering->display_primaries[i][0] = av_make_q(mdcv->DisplayPrimariesX[j], chroma_den);
668 mastering->display_primaries[i][1] = av_make_q(mdcv->DisplayPrimariesY[j], chroma_den);
669 }
670
671 mastering->white_point[0] = av_make_q(mdcv->WhitePointX, chroma_den);
672 mastering->white_point[1] = av_make_q(mdcv->WhitePointY, chroma_den);
673
674 mastering->max_luminance = av_make_q(mdcv->MaxDisplayMasteringLuminance, luma_den);
675 mastering->min_luminance = av_make_q(mdcv->MinDisplayMasteringLuminance, luma_den);
676
677 mastering->has_luminance = 1;
678 mastering->has_primaries = 1;
679 }
680
681 // The SDK re-uses this flag for HDR SEI parsing
682 if (clli->InsertPayloadToggle) {
683 AVContentLightMetadata *light = av_content_light_metadata_create_side_data(frame);
684
685 if (!light)
686 return AVERROR(ENOMEM);
687
688 light->MaxCLL = clli->MaxContentLightLevel;
689 light->MaxFALL = clli->MaxPicAverageLightLevel;
690 }
691
692 return 0;
693}
694
695#endif
696
Mark Thompson1f26a232016-10-21 17:57:12697static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
698 AVFrame *frame, int *got_frame,
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41699 const AVPacket *avpkt)
Anton Khirnov4e08c822015-02-10 09:40:59700{
701 mfxFrameSurface1 *insurf;
702 mfxFrameSurface1 *outsurf;
Mark Thompson1f26a232016-10-21 17:57:12703 mfxSyncPoint *sync;
Anton Khirnov4e08c822015-02-10 09:40:59704 mfxBitstream bs = { { { 0 } } };
705 int ret;
706
Mark Thompson1f26a232016-10-21 17:57:12707 if (avpkt->size) {
708 bs.Data = avpkt->data;
709 bs.DataLength = avpkt->size;
Anton Khirnov4e08c822015-02-10 09:40:59710 bs.MaxLength = bs.DataLength;
Haihao Xiang971b4ac2021-06-11 02:19:45711 bs.TimeStamp = PTS_TO_MFX_PTS(avpkt->pts, avctx->pkt_timebase);
Zhong Li54307b32018-04-07 17:38:55712 if (avctx->field_order == AV_FIELD_PROGRESSIVE)
713 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
Anton Khirnov4e08c822015-02-10 09:40:59714 }
715
Mark Thompson1f26a232016-10-21 17:57:12716 sync = av_mallocz(sizeof(*sync));
717 if (!sync) {
718 av_freep(&sync);
719 return AVERROR(ENOMEM);
720 }
721
722 do {
Anton Khirnov4e08c822015-02-10 09:40:59723 ret = get_surface(avctx, q, &insurf);
Timothy Gub6f80b12016-12-05 18:20:26724 if (ret < 0) {
725 av_freep(&sync);
Anton Khirnov4e08c822015-02-10 09:40:59726 return ret;
Timothy Gub6f80b12016-12-05 18:20:26727 }
Mark Thompson1f26a232016-10-21 17:57:12728
729 ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
730 insurf, &outsurf, sync);
731 if (ret == MFX_WRN_DEVICE_BUSY)
Ivan Uskov9f543e02015-07-24 11:45:38732 av_usleep(500);
Anton Khirnov4e08c822015-02-10 09:40:59733
Mark Thompson1f26a232016-10-21 17:57:12734 } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
Anton Khirnov4e08c822015-02-10 09:40:59735
Wenbin Chen40f38652022-03-18 06:25:09736 if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) {
737 q->reinit_flag = 1;
738 av_log(avctx, AV_LOG_DEBUG, "Video parameter change\n");
739 av_freep(&sync);
740 return 0;
741 }
742
Mark Thompson1f26a232016-10-21 17:57:12743 if (ret != MFX_ERR_NONE &&
744 ret != MFX_ERR_MORE_DATA &&
745 ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
746 ret != MFX_ERR_MORE_SURFACE) {
Mark Thompson1f26a232016-10-21 17:57:12747 av_freep(&sync);
Anton Khirnov95414eb2016-06-25 19:38:10748 return ff_qsv_print_error(avctx, ret,
749 "Error during QSV decoding.");
Anton Khirnovf5c4d382015-07-14 16:16:26750 }
751
Anton Khirnovaa9d15d2015-07-09 18:08:13752 /* make sure we do not enter an infinite loop if the SDK
753 * did not consume any data and did not return anything */
Mark Thompson1f26a232016-10-21 17:57:12754 if (!*sync && !bs.DataOffset) {
Anton Khirnovaa9d15d2015-07-09 18:08:13755 bs.DataOffset = avpkt->size;
Mark Thompson0940b742016-10-30 16:58:23756 ++q->zero_consume_run;
757 if (q->zero_consume_run > 1)
758 ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data");
759 } else {
760 q->zero_consume_run = 0;
Anton Khirnovaa9d15d2015-07-09 18:08:13761 }
762
Mark Thompson1f26a232016-10-21 17:57:12763 if (*sync) {
Anton Khirnov08181622022-01-06 16:16:47764 QSVAsyncFrame aframe;
Mark Thompson1f26a232016-10-21 17:57:12765 QSVFrame *out_frame = find_frame(q, outsurf);
766
767 if (!out_frame) {
768 av_log(avctx, AV_LOG_ERROR,
769 "The returned surface does not correspond to any frame\n");
770 av_freep(&sync);
771 return AVERROR_BUG;
772 }
773
Chen,Wenbine6b990e2021-03-12 02:44:06774 out_frame->queued += 1;
Anton Khirnov08181622022-01-06 16:16:47775
776 aframe = (QSVAsyncFrame){ sync, out_frame };
777 av_fifo_write(q->async_fifo, &aframe, 1);
Mark Thompson1f26a232016-10-21 17:57:12778 } else {
779 av_freep(&sync);
Ivan Uskovc90dbc62015-07-24 10:26:14780 }
781
Anton Khirnov08181622022-01-06 16:16:47782 if ((av_fifo_can_read(q->async_fifo) >= q->async_depth) ||
783 (!avpkt->size && av_fifo_can_read(q->async_fifo))) {
784 QSVAsyncFrame aframe;
Anton Khirnovf5c4d382015-07-14 16:16:26785 AVFrame *src_frame;
786
Anton Khirnov08181622022-01-06 16:16:47787 av_fifo_read(q->async_fifo, &aframe, 1);
788 aframe.frame->queued -= 1;
Anton Khirnovf5c4d382015-07-14 16:16:26789
Anton Khirnovb68e3532017-01-07 20:06:16790 if (avctx->pix_fmt != AV_PIX_FMT_QSV) {
791 do {
Anton Khirnov08181622022-01-06 16:16:47792 ret = MFXVideoCORE_SyncOperation(q->session, *aframe.sync, 1000);
Anton Khirnovb68e3532017-01-07 20:06:16793 } while (ret == MFX_WRN_IN_EXECUTION);
794 }
Anton Khirnovf5c4d382015-07-14 16:16:26795
Anton Khirnov08181622022-01-06 16:16:47796 av_freep(&aframe.sync);
Mark Thompson1f26a232016-10-21 17:57:12797
Anton Khirnov08181622022-01-06 16:16:47798 src_frame = aframe.frame->frame;
Anton Khirnovf5c4d382015-07-14 16:16:26799
Anton Khirnov4e08c822015-02-10 09:40:59800 ret = av_frame_ref(frame, src_frame);
801 if (ret < 0)
802 return ret;
803
Anton Khirnov08181622022-01-06 16:16:47804 outsurf = &aframe.frame->surface;
Anton Khirnovf5c4d382015-07-14 16:16:26805
Haihao Xiang971b4ac2021-06-11 02:19:45806 frame->pts = MFX_PTS_TO_PTS(outsurf->Data.TimeStamp, avctx->pkt_timebase);
Haihao Xiang8ca06a82022-01-24 08:24:55807#if QSV_VERSION_ATLEAST(1, 34)
808 if ((avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) &&
809 QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) &&
810 avctx->codec_id == AV_CODEC_ID_AV1) {
Anton Khirnov08181622022-01-06 16:16:47811 ret = qsv_export_film_grain(avctx, &aframe.frame->av1_film_grain_param, frame);
Haihao Xiang8ca06a82022-01-24 08:24:55812
813 if (ret < 0)
814 return ret;
815 }
816#endif
Anton Khirnov4e08c822015-02-10 09:40:59817
Haihao Xiang71cded62022-11-21 02:31:24818#if QSV_VERSION_ATLEAST(1, 35)
819 if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 35) && avctx->codec_id == AV_CODEC_ID_HEVC) {
820 ret = qsv_export_hdr_side_data(avctx, &aframe.frame->mdcv, &aframe.frame->clli, frame);
821
822 if (ret < 0)
823 return ret;
824 }
825#endif
826
Anton Khirnov4e08c822015-02-10 09:40:59827 frame->repeat_pict =
828 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
829 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
830 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
James Almer2f561ba2023-04-11 18:02:14831 frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST *
832 !!(outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF);
833 frame->flags |= AV_FRAME_FLAG_INTERLACED *
Anton Khirnov4e08c822015-02-10 09:40:59834 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
Anton Khirnov08181622022-01-06 16:16:47835 frame->pict_type = ff_qsv_map_pictype(aframe.frame->dec_info.FrameType);
Zhong Li52ed83f2018-04-04 09:51:29836 //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames.
837 if (avctx->codec_id == AV_CODEC_ID_H264)
Anton Khirnov08181622022-01-06 16:16:47838 frame->key_frame = !!(aframe.frame->dec_info.FrameType & MFX_FRAMETYPE_IDR);
Anton Khirnov4e08c822015-02-10 09:40:59839
Anton Khirnov404e5142016-08-09 10:05:49840 /* update the surface properties */
841 if (avctx->pix_fmt == AV_PIX_FMT_QSV)
842 ((mfxFrameSurface1*)frame->data[3])->Info = outsurf->Info;
843
Anton Khirnov4e08c822015-02-10 09:40:59844 *got_frame = 1;
845 }
846
Mark Thompson1f26a232016-10-21 17:57:12847 return bs.DataOffset;
Ivan Uskov3f8e2e92015-08-06 16:10:24848}
Anton Khirnov4e08c822015-02-10 09:40:59849
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41850static void qsv_decode_close_qsvcontext(QSVContext *q)
Anton Khirnov4e08c822015-02-10 09:40:59851{
Mark Thompson1f26a232016-10-21 17:57:12852 QSVFrame *cur = q->work_frames;
Anton Khirnov4e08c822015-02-10 09:40:59853
Mark Thompson1f26a232016-10-21 17:57:12854 if (q->session)
855 MFXVideoDECODE_Close(q->session);
Ivan Uskovcc167f72015-08-04 10:40:06856
Anton Khirnov08181622022-01-06 16:16:47857 if (q->async_fifo) {
858 QSVAsyncFrame aframe;
859 while (av_fifo_read(q->async_fifo, &aframe, 1) >= 0)
860 av_freep(&aframe.sync);
861 av_fifo_freep2(&q->async_fifo);
Mark Thompson1f26a232016-10-21 17:57:12862 }
863
864 while (cur) {
865 q->work_frames = cur->next;
866 av_frame_free(&cur->frame);
867 av_freep(&cur);
868 cur = q->work_frames;
869 }
Anton Khirnov4e08c822015-02-10 09:40:59870
Zhong Li74007dd2019-09-19 20:45:26871 ff_qsv_close_internal_session(&q->internal_qs);
Mark Thompson1f26a232016-10-21 17:57:12872
873 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
Anton Khirnov4ab61cd2016-08-10 07:38:21874 av_buffer_unref(&q->frames_ctx.mids_buf);
Linjie Fu53459652019-10-08 13:41:02875 av_buffer_pool_uninit(&q->pool);
Anton Khirnov4e08c822015-02-10 09:40:59876}
Mark Thompson1f26a232016-10-21 17:57:12877
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41878static int qsv_process_data(AVCodecContext *avctx, QSVContext *q,
879 AVFrame *frame, int *got_frame, const AVPacket *pkt)
Mark Thompson1f26a232016-10-21 17:57:12880{
Mark Thompson1f26a232016-10-21 17:57:12881 int ret;
Zhong Li00d0a4a2019-08-13 06:11:09882 mfxVideoParam param = { 0 };
883 enum AVPixelFormat pix_fmt = AV_PIX_FMT_NV12;
Mark Thompson1f26a232016-10-21 17:57:12884
Mark Thompson1f26a232016-10-21 17:57:12885 if (!pkt->size)
886 return qsv_decode(avctx, q, frame, got_frame, pkt);
887
Mark Thompson1f26a232016-10-21 17:57:12888 /* TODO: flush delayed frames on reinit */
Zhong Li00d0a4a2019-08-13 06:11:09889
890 // sw_pix_fmt, coded_width/height should be set for ff_get_format(),
891 // assume sw_pix_fmt is NV12 and coded_width/height to be 1280x720,
892 // the assumption may be not corret but will be updated after header decoded if not true.
893 if (q->orig_pix_fmt != AV_PIX_FMT_NONE)
894 pix_fmt = q->orig_pix_fmt;
895 if (!avctx->coded_width)
896 avctx->coded_width = 1280;
897 if (!avctx->coded_height)
898 avctx->coded_height = 720;
899
Wenbin Chen4a633eb2022-03-18 06:25:10900 /* decode zero-size pkt to flush the buffered pkt before reinit */
901 if (q->reinit_flag) {
Linjie Fu87368882018-10-16 01:36:13902 AVPacket zero_pkt = {0};
Wenbin Chen4a633eb2022-03-18 06:25:10903 ret = qsv_decode(avctx, q, frame, got_frame, &zero_pkt);
904 if (ret < 0 || *got_frame)
905 return ret;
906 }
Linjie Fu87368882018-10-16 01:36:13907
Wenbin Chen4a633eb2022-03-18 06:25:10908 if (q->reinit_flag || !q->session || !q->initialized) {
Wenbin Chen0a0847d2022-03-18 06:25:11909 mfxFrameAllocRequest request;
910 memset(&request, 0, sizeof(request));
911
Linjie Fu87368882018-10-16 01:36:13912 q->reinit_flag = 0;
Wenbin Chen4a633eb2022-03-18 06:25:10913 ret = qsv_decode_header(avctx, q, pkt, pix_fmt, &param);
914 if (ret < 0) {
915 if (ret == AVERROR(EAGAIN))
916 av_log(avctx, AV_LOG_INFO, "More data is required to decode header\n");
917 else
918 av_log(avctx, AV_LOG_ERROR, "Error decoding header\n");
919 goto reinit_fail;
920 }
Wenbin Chen0a0847d2022-03-18 06:25:11921 param.IOPattern = q->iopattern;
Mark Thompson1f26a232016-10-21 17:57:12922
Zhong Li00d0a4a2019-08-13 06:11:09923 q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC);
Mark Thompson1f26a232016-10-21 17:57:12924
Zhong Li00d0a4a2019-08-13 06:11:09925 avctx->coded_width = param.mfx.FrameInfo.Width;
926 avctx->coded_height = param.mfx.FrameInfo.Height;
Mark Thompson1f26a232016-10-21 17:57:12927
Wenbin Chen0a0847d2022-03-18 06:25:11928 ret = MFXVideoDECODE_QueryIOSurf(q->session, &param, &request);
929 if (ret < 0)
930 return ff_qsv_print_error(avctx, ret, "Error querying IO surface");
931
932 q->suggest_pool_size = request.NumFrameSuggested;
933
Zhong Li00d0a4a2019-08-13 06:11:09934 ret = qsv_decode_preinit(avctx, q, pix_fmt, &param);
Mark Thompson1f26a232016-10-21 17:57:12935 if (ret < 0)
936 goto reinit_fail;
Zhong Li00d0a4a2019-08-13 06:11:09937 q->initialized = 0;
938 }
Mark Thompson1f26a232016-10-21 17:57:12939
Zhong Li00d0a4a2019-08-13 06:11:09940 if (!q->initialized) {
Xu Guangxin399c1f92021-01-05 02:43:40941 ret = qsv_decode_init_context(avctx, q, &param);
Mark Thompson1f26a232016-10-21 17:57:12942 if (ret < 0)
943 goto reinit_fail;
Zhong Li00d0a4a2019-08-13 06:11:09944 q->initialized = 1;
Mark Thompson1f26a232016-10-21 17:57:12945 }
946
947 return qsv_decode(avctx, q, frame, got_frame, pkt);
948
949reinit_fail:
Zhong Li0dfcfc52019-08-13 06:11:10950 q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE;
Mark Thompson1f26a232016-10-21 17:57:12951 return ret;
952}
953
Xu Guangxin399c1f92021-01-05 02:43:40954enum LoadPlugin {
955 LOAD_PLUGIN_NONE,
956 LOAD_PLUGIN_HEVC_SW,
957 LOAD_PLUGIN_HEVC_HW,
958};
959
960typedef struct QSVDecContext {
961 AVClass *class;
962 QSVContext qsv;
963
964 int load_plugin;
965
Anton Khirnov08181622022-01-06 16:16:47966 AVFifo *packet_fifo;
Xu Guangxin399c1f92021-01-05 02:43:40967
968 AVPacket buffer_pkt;
969} QSVDecContext;
970
971static void qsv_clear_buffers(QSVDecContext *s)
972{
973 AVPacket pkt;
Anton Khirnov08181622022-01-06 16:16:47974 while (av_fifo_read(s->packet_fifo, &pkt, 1) >= 0)
Xu Guangxin399c1f92021-01-05 02:43:40975 av_packet_unref(&pkt);
Xu Guangxin399c1f92021-01-05 02:43:40976
977 av_packet_unref(&s->buffer_pkt);
978}
979
980static av_cold int qsv_decode_close(AVCodecContext *avctx)
981{
982 QSVDecContext *s = avctx->priv_data;
983
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41984 qsv_decode_close_qsvcontext(&s->qsv);
Xu Guangxin399c1f92021-01-05 02:43:40985
986 qsv_clear_buffers(s);
987
Anton Khirnov08181622022-01-06 16:16:47988 av_fifo_freep2(&s->packet_fifo);
Xu Guangxin399c1f92021-01-05 02:43:40989
990 return 0;
991}
992
993static av_cold int qsv_decode_init(AVCodecContext *avctx)
994{
995 QSVDecContext *s = avctx->priv_data;
996 int ret;
Xu Guangxin7a5a5e62021-01-05 02:43:42997 const char *uid = NULL;
Xu Guangxin399c1f92021-01-05 02:43:40998
Xu Guangxind78ecf12021-01-05 02:43:41999 if (avctx->codec_id == AV_CODEC_ID_VP8) {
Xu Guangxin7a5a5e62021-01-05 02:43:421000 uid = "f622394d8d87452f878c51f2fc9b4131";
Xu Guangxind78ecf12021-01-05 02:43:411001 } else if (avctx->codec_id == AV_CODEC_ID_VP9) {
Xu Guangxin7a5a5e62021-01-05 02:43:421002 uid = "a922394d8d87452f878c51f2fc9b4131";
Xu Guangxind78ecf12021-01-05 02:43:411003 }
1004 else if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) {
Xu Guangxin399c1f92021-01-05 02:43:401005 static const char * const uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6";
1006 static const char * const uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e";
1007
1008 if (s->qsv.load_plugins[0]) {
1009 av_log(avctx, AV_LOG_WARNING,
1010 "load_plugins is not empty, but load_plugin is not set to 'none'."
1011 "The load_plugin value will be ignored.\n");
1012 } else {
Xu Guangxin399c1f92021-01-05 02:43:401013 if (s->load_plugin == LOAD_PLUGIN_HEVC_SW)
Xu Guangxin7a5a5e62021-01-05 02:43:421014 uid = uid_hevcdec_sw;
Xu Guangxin399c1f92021-01-05 02:43:401015 else
Xu Guangxin7a5a5e62021-01-05 02:43:421016 uid = uid_hevcdec_hw;
Xu Guangxin399c1f92021-01-05 02:43:401017 }
1018 }
Xu Guangxin7a5a5e62021-01-05 02:43:421019 if (uid) {
1020 av_freep(&s->qsv.load_plugins);
1021 s->qsv.load_plugins = av_strdup(uid);
1022 if (!s->qsv.load_plugins)
1023 return AVERROR(ENOMEM);
1024 }
Xu Guangxin399c1f92021-01-05 02:43:401025
1026 s->qsv.orig_pix_fmt = AV_PIX_FMT_NV12;
Anton Khirnov08181622022-01-06 16:16:471027 s->packet_fifo = av_fifo_alloc2(1, sizeof(AVPacket),
1028 AV_FIFO_FLAG_AUTO_GROW);
Xu Guangxin399c1f92021-01-05 02:43:401029 if (!s->packet_fifo) {
1030 ret = AVERROR(ENOMEM);
1031 goto fail;
1032 }
1033
Haihao Xiang971b4ac2021-06-11 02:19:451034 if (!avctx->pkt_timebase.num)
1035 av_log(avctx, AV_LOG_WARNING, "Invalid pkt_timebase, passing timestamps as-is.\n");
1036
Xu Guangxin399c1f92021-01-05 02:43:401037 return 0;
1038fail:
1039 qsv_decode_close(avctx);
1040 return ret;
1041}
1042
Andreas Rheinhardtce7dbd02022-03-30 19:33:241043static int qsv_decode_frame(AVCodecContext *avctx, AVFrame *frame,
Xu Guangxin399c1f92021-01-05 02:43:401044 int *got_frame, AVPacket *avpkt)
1045{
1046 QSVDecContext *s = avctx->priv_data;
Xu Guangxin399c1f92021-01-05 02:43:401047 int ret;
1048
1049 /* buffer the input packet */
1050 if (avpkt->size) {
1051 AVPacket input_ref;
1052
Xu Guangxin399c1f92021-01-05 02:43:401053 ret = av_packet_ref(&input_ref, avpkt);
1054 if (ret < 0)
1055 return ret;
Anton Khirnov08181622022-01-06 16:16:471056 av_fifo_write(s->packet_fifo, &input_ref, 1);
Xu Guangxin399c1f92021-01-05 02:43:401057 }
1058
1059 /* process buffered data */
1060 while (!*got_frame) {
1061 /* prepare the input data */
1062 if (s->buffer_pkt.size <= 0) {
1063 /* no more data */
Anton Khirnov08181622022-01-06 16:16:471064 if (!av_fifo_can_read(s->packet_fifo))
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:411065 return avpkt->size ? avpkt->size : qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt);
Xu Guangxin399c1f92021-01-05 02:43:401066 /* in progress of reinit, no read from fifo and keep the buffer_pkt */
1067 if (!s->qsv.reinit_flag) {
1068 av_packet_unref(&s->buffer_pkt);
Anton Khirnov08181622022-01-06 16:16:471069 av_fifo_read(s->packet_fifo, &s->buffer_pkt, 1);
Xu Guangxin399c1f92021-01-05 02:43:401070 }
1071 }
1072
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:411073 ret = qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt);
Xu Guangxin399c1f92021-01-05 02:43:401074 if (ret < 0){
1075 /* Drop buffer_pkt when failed to decode the packet. Otherwise,
1076 the decoder will keep decoding the failure packet. */
1077 av_packet_unref(&s->buffer_pkt);
1078 return ret;
1079 }
1080 if (s->qsv.reinit_flag)
1081 continue;
1082
1083 s->buffer_pkt.size -= ret;
1084 s->buffer_pkt.data += ret;
1085 }
1086
1087 return avpkt->size;
1088}
1089
1090static void qsv_decode_flush(AVCodecContext *avctx)
1091{
1092 QSVDecContext *s = avctx->priv_data;
1093
1094 qsv_clear_buffers(s);
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:411095
1096 s->qsv.orig_pix_fmt = AV_PIX_FMT_NONE;
1097 s->qsv.initialized = 0;
Xu Guangxin399c1f92021-01-05 02:43:401098}
1099
1100#define OFFSET(x) offsetof(QSVDecContext, x)
1101#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
1102
1103#define DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, opt) \
1104static const AVClass x##_qsv_class = { \
1105 .class_name = #x "_qsv", \
1106 .item_name = av_default_item_name, \
1107 .option = opt, \
1108 .version = LIBAVUTIL_VERSION_INT, \
1109}; \
Andreas Rheinhardt20f97272022-03-16 20:09:541110const FFCodec ff_##x##_qsv_decoder = { \
1111 .p.name = #x "_qsv", \
Andreas Rheinhardt48286d42022-08-29 11:38:021112 CODEC_LONG_NAME(#X " video (Intel Quick Sync Video acceleration)"), \
Xu Guangxin399c1f92021-01-05 02:43:401113 .priv_data_size = sizeof(QSVDecContext), \
Andreas Rheinhardt20f97272022-03-16 20:09:541114 .p.type = AVMEDIA_TYPE_VIDEO, \
1115 .p.id = AV_CODEC_ID_##X, \
Xu Guangxin399c1f92021-01-05 02:43:401116 .init = qsv_decode_init, \
Andreas Rheinhardt4243da42022-03-30 21:28:241117 FF_CODEC_DECODE_CB(qsv_decode_frame), \
Xu Guangxin399c1f92021-01-05 02:43:401118 .flush = qsv_decode_flush, \
1119 .close = qsv_decode_close, \
1120 .bsfs = bsf_name, \
Andreas Rheinhardt20f97272022-03-16 20:09:541121 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \
1122 .p.priv_class = &x##_qsv_class, \
1123 .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \
Xu Guangxin399c1f92021-01-05 02:43:401124 AV_PIX_FMT_P010, \
Fei Wang56a52af2022-10-06 07:35:381125 AV_PIX_FMT_P012, \
Wenbin Chene0ae8102022-04-06 08:48:031126 AV_PIX_FMT_YUYV422, \
1127 AV_PIX_FMT_Y210, \
Fei Wang56a52af2022-10-06 07:35:381128 AV_PIX_FMT_Y212, \
Haihao Xiangdb85e012022-09-06 04:53:381129 AV_PIX_FMT_VUYX, \
Haihao Xiang1898dbd2022-10-06 07:35:361130 AV_PIX_FMT_XV30, \
Fei Wang56a52af2022-10-06 07:35:381131 AV_PIX_FMT_XV36, \
Xu Guangxin399c1f92021-01-05 02:43:401132 AV_PIX_FMT_QSV, \
1133 AV_PIX_FMT_NONE }, \
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:411134 .hw_configs = qsv_hw_configs, \
Andreas Rheinhardt20f97272022-03-16 20:09:541135 .p.wrapper_name = "qsv", \
Andreas Rheinhardt6aad1202022-07-09 20:25:411136 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, \
Xu Guangxin399c1f92021-01-05 02:43:401137}; \
1138
1139#define DEFINE_QSV_DECODER(x, X, bsf_name) DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, options)
1140
1141#if CONFIG_HEVC_QSV_DECODER
1142static const AVOption hevc_options[] = {
1143 { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
1144
1145 { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_HW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" },
1146 { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" },
1147 { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" },
1148 { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" },
1149
1150 { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
1151 OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD },
1152
1153 { "gpu_copy", "A GPU-accelerated copy between video and system memory", OFFSET(qsv.gpu_copy), AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF, VD, "gpu_copy"},
1154 { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"},
1155 { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"},
1156 { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"},
1157 { NULL },
1158};
1159DEFINE_QSV_DECODER_WITH_OPTION(hevc, HEVC, "hevc_mp4toannexb", hevc_options)
1160#endif
1161
1162static const AVOption options[] = {
1163 { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
1164
1165 { "gpu_copy", "A GPU-accelerated copy between video and system memory", OFFSET(qsv.gpu_copy), AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF, VD, "gpu_copy"},
1166 { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"},
1167 { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"},
1168 { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"},
1169 { NULL },
1170};
1171
1172#if CONFIG_H264_QSV_DECODER
1173DEFINE_QSV_DECODER(h264, H264, "h264_mp4toannexb")
1174#endif
Xu Guangxind78ecf12021-01-05 02:43:411175
1176#if CONFIG_MPEG2_QSV_DECODER
1177DEFINE_QSV_DECODER(mpeg2, MPEG2VIDEO, NULL)
1178#endif
1179
1180#if CONFIG_VC1_QSV_DECODER
1181DEFINE_QSV_DECODER(vc1, VC1, NULL)
1182#endif
1183
1184#if CONFIG_MJPEG_QSV_DECODER
1185DEFINE_QSV_DECODER(mjpeg, MJPEG, NULL)
1186#endif
1187
1188#if CONFIG_VP8_QSV_DECODER
1189DEFINE_QSV_DECODER(vp8, VP8, NULL)
1190#endif
1191
1192#if CONFIG_VP9_QSV_DECODER
1193DEFINE_QSV_DECODER(vp9, VP9, NULL)
1194#endif
1195
1196#if CONFIG_AV1_QSV_DECODER
1197DEFINE_QSV_DECODER(av1, AV1, NULL)
1198#endif