blob: 8b83d5695fcdef511c93e430af52dd614bfdb865 [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
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4124#include <stdint.h>
Anton Khirnov4e08c822015-02-10 09:40:5925#include <string.h>
26#include <sys/types.h>
27
28#include <mfx/mfxvideo.h>
29
30#include "libavutil/common.h"
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4131#include "libavutil/fifo.h"
32#include "libavutil/frame.h"
Mark Thompson1f26a232016-10-21 17:57:1233#include "libavutil/hwcontext.h"
34#include "libavutil/hwcontext_qsv.h"
Anton Khirnov4e08c822015-02-10 09:40:5935#include "libavutil/mem.h"
36#include "libavutil/log.h"
Xu Guangxin399c1f92021-01-05 02:43:4037#include "libavutil/opt.h"
Anton Khirnov4e08c822015-02-10 09:40:5938#include "libavutil/pixfmt.h"
39#include "libavutil/time.h"
Linjie Fu53459652019-10-08 13:41:0240#include "libavutil/imgutils.h"
Anton Khirnov4e08c822015-02-10 09:40:5941
42#include "avcodec.h"
43#include "internal.h"
Linjie Fu53459652019-10-08 13:41:0244#include "decode.h"
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4145#include "hwconfig.h"
Ivan Uskov6e127992015-07-14 11:07:0446#include "qsv.h"
Anton Khirnovd0a63d82015-03-13 07:13:0047#include "qsv_internal.h"
Anton Khirnov4e08c822015-02-10 09:40:5948
Haihao Xiang971b4ac2021-06-11 02:19:4549static const AVRational mfx_tb = { 1, 90000 };
50
51#define PTS_TO_MFX_PTS(pts, pts_tb) ((pts) == AV_NOPTS_VALUE ? \
52 MFX_TIMESTAMP_UNKNOWN : pts_tb.num ? \
53 av_rescale_q(pts, pts_tb, mfx_tb) : pts)
54
55#define MFX_PTS_TO_PTS(mfx_pts, pts_tb) ((mfx_pts) == MFX_TIMESTAMP_UNKNOWN ? \
56 AV_NOPTS_VALUE : pts_tb.num ? \
57 av_rescale_q(mfx_pts, mfx_tb, pts_tb) : mfx_pts)
58
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4159typedef struct QSVContext {
60 // the session used for decoding
61 mfxSession session;
Haihao Xiang7c24a762022-01-24 08:24:5462 mfxVersion ver;
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:4163
64 // the session we allocated internally, in case the caller did not provide
65 // one
66 QSVSession internal_qs;
67
68 QSVFramesContext frames_ctx;
69
70 /**
71 * a linked list of frames currently being used by QSV
72 */
73 QSVFrame *work_frames;
74
75 AVFifoBuffer *async_fifo;
76 int zero_consume_run;
77 int buffered_count;
78 int reinit_flag;
79
80 enum AVPixelFormat orig_pix_fmt;
81 uint32_t fourcc;
82 mfxFrameInfo frame_info;
83 AVBufferPool *pool;
84
85 int initialized;
86
87 // options set by the caller
88 int async_depth;
89 int iopattern;
90 int gpu_copy;
91
92 char *load_plugins;
93
94 mfxExtBuffer **ext_buffers;
95 int nb_ext_buffers;
96} QSVContext;
97
98static const AVCodecHWConfigInternal *const qsv_hw_configs[] = {
Mark Thompson758fbc52017-10-25 23:18:4099 &(const AVCodecHWConfigInternal) {
100 .public = {
101 .pix_fmt = AV_PIX_FMT_QSV,
102 .methods = AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX |
Haihao Xiangecee3b02021-08-11 06:01:54103 AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX,
Mark Thompson758fbc52017-10-25 23:18:40104 .device_type = AV_HWDEVICE_TYPE_QSV,
105 },
106 .hwaccel = NULL,
107 },
108 NULL
109};
110
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41111static int qsv_get_continuous_buffer(AVCodecContext *avctx, AVFrame *frame,
112 AVBufferPool *pool)
Linjie Fu53459652019-10-08 13:41:02113{
114 int ret = 0;
115
116 ff_decode_frame_props(avctx, frame);
117
118 frame->width = avctx->width;
119 frame->height = avctx->height;
120
121 switch (avctx->pix_fmt) {
122 case AV_PIX_FMT_NV12:
123 frame->linesize[0] = FFALIGN(avctx->width, 128);
124 break;
125 case AV_PIX_FMT_P010:
126 frame->linesize[0] = 2 * FFALIGN(avctx->width, 128);
127 break;
128 default:
129 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n");
Zhong Li9fff5c42019-12-28 14:22:07130 return AVERROR(EINVAL);
Linjie Fu53459652019-10-08 13:41:02131 }
132
133 frame->linesize[1] = frame->linesize[0];
134 frame->buf[0] = av_buffer_pool_get(pool);
135 if (!frame->buf[0])
136 return AVERROR(ENOMEM);
137
138 frame->data[0] = frame->buf[0]->data;
139 frame->data[1] = frame->data[0] +
140 frame->linesize[0] * FFALIGN(avctx->height, 64);
141
142 ret = ff_attach_decode_data(frame);
143 if (ret < 0)
144 return ret;
145
146 return 0;
147}
148
Mark Thompson1f26a232016-10-21 17:57:12149static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session,
Mark Thompson8aa3c2d2017-03-04 23:57:36150 AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref)
Anton Khirnov4e08c822015-02-10 09:40:59151{
Mark Thompson1f26a232016-10-21 17:57:12152 int ret;
153
Linjie Fu53459652019-10-08 13:41:02154 if (q->gpu_copy == MFX_GPUCOPY_ON &&
Zhong Li779951f2019-12-28 14:28:45155 !(q->iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) {
Linjie Fu53459652019-10-08 13:41:02156 av_log(avctx, AV_LOG_WARNING, "GPU-accelerated memory copy "
Zhong Li779951f2019-12-28 14:28:45157 "only works in system memory mode.\n");
158 q->gpu_copy = MFX_GPUCOPY_OFF;
159 }
Mark Thompson1f26a232016-10-21 17:57:12160 if (session) {
161 q->session = session;
162 } else if (hw_frames_ref) {
Zhong Li74007dd2019-09-19 20:45:26163 if (q->internal_qs.session) {
164 MFXClose(q->internal_qs.session);
165 q->internal_qs.session = NULL;
Mark Thompson1f26a232016-10-21 17:57:12166 }
167 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
168
169 q->frames_ctx.hw_frames_ctx = av_buffer_ref(hw_frames_ref);
170 if (!q->frames_ctx.hw_frames_ctx)
171 return AVERROR(ENOMEM);
172
Zhong Li74007dd2019-09-19 20:45:26173 ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
Mark Thompson91c3b502017-03-04 23:57:35174 &q->frames_ctx, q->load_plugins,
Linjie Fu53459652019-10-08 13:41:02175 q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
176 q->gpu_copy);
Mark Thompson1f26a232016-10-21 17:57:12177 if (ret < 0) {
178 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
179 return ret;
180 }
181
Zhong Li74007dd2019-09-19 20:45:26182 q->session = q->internal_qs.session;
Mark Thompson8aa3c2d2017-03-04 23:57:36183 } else if (hw_device_ref) {
Zhong Li74007dd2019-09-19 20:45:26184 if (q->internal_qs.session) {
185 MFXClose(q->internal_qs.session);
186 q->internal_qs.session = NULL;
Mark Thompson8aa3c2d2017-03-04 23:57:36187 }
188
Zhong Li74007dd2019-09-19 20:45:26189 ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session,
Linjie Fu53459652019-10-08 13:41:02190 hw_device_ref, q->load_plugins, q->gpu_copy);
Mark Thompson8aa3c2d2017-03-04 23:57:36191 if (ret < 0)
192 return ret;
193
Zhong Li74007dd2019-09-19 20:45:26194 q->session = q->internal_qs.session;
Mark Thompson1f26a232016-10-21 17:57:12195 } else {
Zhong Li74007dd2019-09-19 20:45:26196 if (!q->internal_qs.session) {
197 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
Linjie Fu53459652019-10-08 13:41:02198 q->load_plugins, q->gpu_copy);
Anton Khirnovd0a63d82015-03-13 07:13:00199 if (ret < 0)
200 return ret;
Anton Khirnov4e08c822015-02-10 09:40:59201 }
202
Zhong Li74007dd2019-09-19 20:45:26203 q->session = q->internal_qs.session;
Anton Khirnov4e08c822015-02-10 09:40:59204 }
205
Haihao Xiang7c24a762022-01-24 08:24:54206 if (MFXQueryVersion(q->session, &q->ver) != MFX_ERR_NONE) {
207 av_log(avctx, AV_LOG_ERROR, "Error querying the session version. \n");
208 q->session = NULL;
209
210 if (q->internal_qs.session) {
211 MFXClose(q->internal_qs.session);
212 q->internal_qs.session = NULL;
213 }
214
215 return AVERROR_EXTERNAL;
216 }
217
Mark Thompson1f26a232016-10-21 17:57:12218 /* make sure the decoder is uninitialized */
219 MFXVideoDECODE_Close(q->session);
220
221 return 0;
Anton Khirnov4e08c822015-02-10 09:40:59222}
223
Dmitry Rogozhkinc1bcd322018-07-24 17:36:19224static inline unsigned int qsv_fifo_item_size(void)
225{
226 return sizeof(mfxSyncPoint*) + sizeof(QSVFrame*);
227}
228
229static inline unsigned int qsv_fifo_size(const AVFifoBuffer* fifo)
230{
231 return av_fifo_size(fifo) / qsv_fifo_item_size();
232}
233
Zhong Li00d0a4a2019-08-13 06:11:09234static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixelFormat pix_fmt, mfxVideoParam *param)
Anton Khirnov4e08c822015-02-10 09:40:59235{
Anton Khirnov6f19bbc2016-05-21 16:26:40236 mfxSession session = NULL;
Mark Thompson1f26a232016-10-21 17:57:12237 int iopattern = 0;
Anton Khirnov4e08c822015-02-10 09:40:59238 int ret;
Zhong Li00d0a4a2019-08-13 06:11:09239 enum AVPixelFormat pix_fmts[3] = {
240 AV_PIX_FMT_QSV, /* opaque format in case of video memory output */
241 pix_fmt, /* system memory format obtained from bitstream parser */
242 AV_PIX_FMT_NONE };
Anton Khirnov4e08c822015-02-10 09:40:59243
Zhong Li00d0a4a2019-08-13 06:11:09244 ret = ff_get_format(avctx, pix_fmts);
245 if (ret < 0) {
246 q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE;
247 return ret;
248 }
Anton Khirnov92736c72016-06-22 09:53:00249
Mark Thompson1f26a232016-10-21 17:57:12250 if (!q->async_fifo) {
Dmitry Rogozhkinc1bcd322018-07-24 17:36:19251 q->async_fifo = av_fifo_alloc(q->async_depth * qsv_fifo_item_size());
Mark Thompson1f26a232016-10-21 17:57:12252 if (!q->async_fifo)
253 return AVERROR(ENOMEM);
Hendrik Leppkesb54d6452015-10-22 15:00:49254 }
Hendrik Leppkesb54d6452015-10-22 15:00:49255
Anton Khirnove3281782016-07-30 14:38:51256 if (avctx->pix_fmt == AV_PIX_FMT_QSV && avctx->hwaccel_context) {
Mark Thompson1f26a232016-10-21 17:57:12257 AVQSVContext *user_ctx = avctx->hwaccel_context;
258 session = user_ctx->session;
259 iopattern = user_ctx->iopattern;
260 q->ext_buffers = user_ctx->ext_buffers;
261 q->nb_ext_buffers = user_ctx->nb_ext_buffers;
262 }
263
Haihao Xiangecee3b02021-08-11 06:01:54264 if (avctx->hw_device_ctx && !avctx->hw_frames_ctx && ret == AV_PIX_FMT_QSV) {
265 AVHWFramesContext *hwframes_ctx;
266 AVQSVFramesContext *frames_hwctx;
267
268 avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
269
270 if (!avctx->hw_frames_ctx) {
271 av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n");
272 return AVERROR(ENOMEM);
273 }
274
275 hwframes_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
276 frames_hwctx = hwframes_ctx->hwctx;
277 hwframes_ctx->width = FFALIGN(avctx->coded_width, 32);
278 hwframes_ctx->height = FFALIGN(avctx->coded_height, 32);
279 hwframes_ctx->format = AV_PIX_FMT_QSV;
280 hwframes_ctx->sw_format = avctx->sw_pix_fmt;
281 hwframes_ctx->initial_pool_size = 64 + avctx->extra_hw_frames;
282 frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
283
284 ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
285
286 if (ret < 0) {
287 av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame pool\n");
288 av_buffer_unref(&avctx->hw_frames_ctx);
289 return ret;
290 }
291 }
292
Mark Thompson1f26a232016-10-21 17:57:12293 if (avctx->hw_frames_ctx) {
294 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
295 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
296
297 if (!iopattern) {
298 if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
299 iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
300 else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
301 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
302 }
Mark Thompson1f26a232016-10-21 17:57:12303 }
304
305 if (!iopattern)
306 iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
307 q->iopattern = iopattern;
308
Zhong Li525de952019-09-19 20:45:27309 ff_qsv_print_iopattern(avctx, q->iopattern, "Decoder");
310
Mark Thompson8aa3c2d2017-03-04 23:57:36311 ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx);
Anton Khirnov4e08c822015-02-10 09:40:59312 if (ret < 0) {
313 av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
314 return ret;
Ivan Uskov6e127992015-07-14 11:07:04315 }
Anton Khirnov4e08c822015-02-10 09:40:59316
Zhong Li00d0a4a2019-08-13 06:11:09317 param->IOPattern = q->iopattern;
318 param->AsyncDepth = q->async_depth;
319 param->ExtParam = q->ext_buffers;
320 param->NumExtParam = q->nb_ext_buffers;
Mark Thompson1f26a232016-10-21 17:57:12321
Zhong Li00d0a4a2019-08-13 06:11:09322 return 0;
323 }
Mark Thompson1f26a232016-10-21 17:57:12324
Xu Guangxin399c1f92021-01-05 02:43:40325static int qsv_decode_init_context(AVCodecContext *avctx, QSVContext *q, mfxVideoParam *param)
Zhong Li00d0a4a2019-08-13 06:11:09326{
327 int ret;
Mark Thompson1f26a232016-10-21 17:57:12328
Zhong Li00d0a4a2019-08-13 06:11:09329 avctx->width = param->mfx.FrameInfo.CropW;
330 avctx->height = param->mfx.FrameInfo.CropH;
331 avctx->coded_width = param->mfx.FrameInfo.Width;
332 avctx->coded_height = param->mfx.FrameInfo.Height;
333 avctx->level = param->mfx.CodecLevel;
334 avctx->profile = param->mfx.CodecProfile;
335 avctx->field_order = ff_qsv_map_picstruct(param->mfx.FrameInfo.PicStruct);
336 avctx->pix_fmt = ff_qsv_map_fourcc(param->mfx.FrameInfo.FourCC);
Anton Khirnov4e08c822015-02-10 09:40:59337
Zhong Li00d0a4a2019-08-13 06:11:09338 ret = MFXVideoDECODE_Init(q->session, param);
Anton Khirnov95414eb2016-06-25 19:38:10339 if (ret < 0)
340 return ff_qsv_print_error(avctx, ret,
341 "Error initializing the MFX video decoder");
Anton Khirnov4e08c822015-02-10 09:40:59342
Zhong Li00d0a4a2019-08-13 06:11:09343 q->frame_info = param->mfx.FrameInfo;
344
Linjie Fu53459652019-10-08 13:41:02345 if (!avctx->hw_frames_ctx)
346 q->pool = av_buffer_pool_init(av_image_get_buffer_size(avctx->pix_fmt,
347 FFALIGN(avctx->width, 128), FFALIGN(avctx->height, 64), 1), av_buffer_allocz);
Zhong Li00d0a4a2019-08-13 06:11:09348 return 0;
349}
350
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41351static int qsv_decode_header(AVCodecContext *avctx, QSVContext *q,
352 const AVPacket *avpkt, enum AVPixelFormat pix_fmt,
353 mfxVideoParam *param)
Zhong Li00d0a4a2019-08-13 06:11:09354{
355 int ret;
Haihao Xiangc8cfe672021-07-28 08:15:46356 mfxExtVideoSignalInfo video_signal_info = { 0 };
357 mfxExtBuffer *header_ext_params[1] = { (mfxExtBuffer *)&video_signal_info };
Zhong Li00d0a4a2019-08-13 06:11:09358 mfxBitstream bs = { 0 };
359
360 if (avpkt->size) {
361 bs.Data = avpkt->data;
362 bs.DataLength = avpkt->size;
363 bs.MaxLength = bs.DataLength;
Haihao Xiang971b4ac2021-06-11 02:19:45364 bs.TimeStamp = PTS_TO_MFX_PTS(avpkt->pts, avctx->pkt_timebase);
Zhong Li00d0a4a2019-08-13 06:11:09365 if (avctx->field_order == AV_FIELD_PROGRESSIVE)
366 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
367 } else
368 return AVERROR_INVALIDDATA;
369
370
371 if(!q->session) {
372 ret = qsv_decode_preinit(avctx, q, pix_fmt, param);
373 if (ret < 0)
374 return ret;
375 }
376
377 ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
378 if (ret < 0)
379 return ret;
380
381 param->mfx.CodecId = ret;
Haihao Xiangc8cfe672021-07-28 08:15:46382 video_signal_info.Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO;
383 video_signal_info.Header.BufferSz = sizeof(video_signal_info);
384 // The SDK doesn't support other ext buffers when calling MFXVideoDECODE_DecodeHeader,
385 // so do not append this buffer to the existent buffer array
386 param->ExtParam = header_ext_params;
387 param->NumExtParam = 1;
Zhong Li00d0a4a2019-08-13 06:11:09388 ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, param);
389 if (MFX_ERR_MORE_DATA == ret) {
390 return AVERROR(EAGAIN);
391 }
392 if (ret < 0)
393 return ff_qsv_print_error(avctx, ret,
394 "Error decoding stream header");
Anton Khirnovce320cf2016-06-22 09:44:09395
Haihao Xiangc8cfe672021-07-28 08:15:46396 avctx->color_range = video_signal_info.VideoFullRange ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
397
398 if (video_signal_info.ColourDescriptionPresent) {
399 avctx->color_primaries = video_signal_info.ColourPrimaries;
400 avctx->color_trc = video_signal_info.TransferCharacteristics;
401 avctx->colorspace = video_signal_info.MatrixCoefficients;
402 }
403
404 param->ExtParam = q->ext_buffers;
405 param->NumExtParam = q->nb_ext_buffers;
406
Anton Khirnov4e08c822015-02-10 09:40:59407 return 0;
408}
409
Anton Khirnovce320cf2016-06-22 09:44:09410static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame)
Anton Khirnov4e08c822015-02-10 09:40:59411{
412 int ret;
413
Linjie Fu53459652019-10-08 13:41:02414 if (q->pool)
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41415 ret = qsv_get_continuous_buffer(avctx, frame->frame, q->pool);
Linjie Fu53459652019-10-08 13:41:02416 else
417 ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
418
Anton Khirnov4e08c822015-02-10 09:40:59419 if (ret < 0)
420 return ret;
421
422 if (frame->frame->format == AV_PIX_FMT_QSV) {
Anton Khirnov404e5142016-08-09 10:05:49423 frame->surface = *(mfxFrameSurface1*)frame->frame->data[3];
Anton Khirnov4e08c822015-02-10 09:40:59424 } else {
Anton Khirnov404e5142016-08-09 10:05:49425 frame->surface.Info = q->frame_info;
Anton Khirnov4e08c822015-02-10 09:40:59426
Anton Khirnov404e5142016-08-09 10:05:49427 frame->surface.Data.PitchLow = frame->frame->linesize[0];
428 frame->surface.Data.Y = frame->frame->data[0];
429 frame->surface.Data.UV = frame->frame->data[1];
Anton Khirnov4e08c822015-02-10 09:40:59430 }
431
Anton Khirnov00aeedd2016-08-10 06:29:23432 if (q->frames_ctx.mids) {
433 ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame);
434 if (ret < 0)
435 return ret;
436
437 frame->surface.Data.MemId = &q->frames_ctx.mids[ret];
438 }
Haihao Xiang8dd507b2022-01-24 08:24:53439
440 frame->surface.Data.ExtParam = frame->ext_param;
441 frame->surface.Data.NumExtParam = 0;
442 frame->num_ext_params = 0;
Zhong Li52ed83f2018-04-04 09:51:29443 frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO;
444 frame->dec_info.Header.BufferSz = sizeof(frame->dec_info);
Haihao Xiang8dd507b2022-01-24 08:24:53445 ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->dec_info);
Anton Khirnov00aeedd2016-08-10 06:29:23446
Anton Khirnov404e5142016-08-09 10:05:49447 frame->used = 1;
448
Anton Khirnov4e08c822015-02-10 09:40:59449 return 0;
450}
451
452static void qsv_clear_unused_frames(QSVContext *q)
453{
454 QSVFrame *cur = q->work_frames;
455 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49456 if (cur->used && !cur->surface.Data.Locked && !cur->queued) {
457 cur->used = 0;
Anton Khirnov4e08c822015-02-10 09:40:59458 av_frame_unref(cur->frame);
459 }
460 cur = cur->next;
461 }
462}
463
464static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
465{
466 QSVFrame *frame, **last;
467 int ret;
468
469 qsv_clear_unused_frames(q);
470
471 frame = q->work_frames;
472 last = &q->work_frames;
473 while (frame) {
Anton Khirnov404e5142016-08-09 10:05:49474 if (!frame->used) {
Anton Khirnovce320cf2016-06-22 09:44:09475 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59476 if (ret < 0)
477 return ret;
Anton Khirnov404e5142016-08-09 10:05:49478 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59479 return 0;
480 }
481
482 last = &frame->next;
483 frame = frame->next;
484 }
485
486 frame = av_mallocz(sizeof(*frame));
487 if (!frame)
488 return AVERROR(ENOMEM);
489 frame->frame = av_frame_alloc();
490 if (!frame->frame) {
491 av_freep(&frame);
492 return AVERROR(ENOMEM);
493 }
494 *last = frame;
495
Anton Khirnovce320cf2016-06-22 09:44:09496 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59497 if (ret < 0)
498 return ret;
499
Anton Khirnov404e5142016-08-09 10:05:49500 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59501
502 return 0;
503}
504
Anton Khirnovf5c4d382015-07-14 16:16:26505static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
Anton Khirnov4e08c822015-02-10 09:40:59506{
507 QSVFrame *cur = q->work_frames;
508 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49509 if (surf == &cur->surface)
Anton Khirnovf5c4d382015-07-14 16:16:26510 return cur;
Anton Khirnov4e08c822015-02-10 09:40:59511 cur = cur->next;
512 }
513 return NULL;
514}
515
Mark Thompson1f26a232016-10-21 17:57:12516static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
517 AVFrame *frame, int *got_frame,
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41518 const AVPacket *avpkt)
Anton Khirnov4e08c822015-02-10 09:40:59519{
Anton Khirnovf5c4d382015-07-14 16:16:26520 QSVFrame *out_frame;
Anton Khirnov4e08c822015-02-10 09:40:59521 mfxFrameSurface1 *insurf;
522 mfxFrameSurface1 *outsurf;
Mark Thompson1f26a232016-10-21 17:57:12523 mfxSyncPoint *sync;
Anton Khirnov4e08c822015-02-10 09:40:59524 mfxBitstream bs = { { { 0 } } };
525 int ret;
526
Mark Thompson1f26a232016-10-21 17:57:12527 if (avpkt->size) {
528 bs.Data = avpkt->data;
529 bs.DataLength = avpkt->size;
Anton Khirnov4e08c822015-02-10 09:40:59530 bs.MaxLength = bs.DataLength;
Haihao Xiang971b4ac2021-06-11 02:19:45531 bs.TimeStamp = PTS_TO_MFX_PTS(avpkt->pts, avctx->pkt_timebase);
Zhong Li54307b32018-04-07 17:38:55532 if (avctx->field_order == AV_FIELD_PROGRESSIVE)
533 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
Anton Khirnov4e08c822015-02-10 09:40:59534 }
535
Mark Thompson1f26a232016-10-21 17:57:12536 sync = av_mallocz(sizeof(*sync));
537 if (!sync) {
538 av_freep(&sync);
539 return AVERROR(ENOMEM);
540 }
541
542 do {
Anton Khirnov4e08c822015-02-10 09:40:59543 ret = get_surface(avctx, q, &insurf);
Timothy Gub6f80b12016-12-05 18:20:26544 if (ret < 0) {
545 av_freep(&sync);
Anton Khirnov4e08c822015-02-10 09:40:59546 return ret;
Timothy Gub6f80b12016-12-05 18:20:26547 }
Mark Thompson1f26a232016-10-21 17:57:12548
549 ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
550 insurf, &outsurf, sync);
551 if (ret == MFX_WRN_DEVICE_BUSY)
Ivan Uskov9f543e02015-07-24 11:45:38552 av_usleep(500);
Anton Khirnov4e08c822015-02-10 09:40:59553
Mark Thompson1f26a232016-10-21 17:57:12554 } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
Anton Khirnov4e08c822015-02-10 09:40:59555
Mark Thompson1f26a232016-10-21 17:57:12556 if (ret != MFX_ERR_NONE &&
557 ret != MFX_ERR_MORE_DATA &&
558 ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
559 ret != MFX_ERR_MORE_SURFACE) {
Mark Thompson1f26a232016-10-21 17:57:12560 av_freep(&sync);
Anton Khirnov95414eb2016-06-25 19:38:10561 return ff_qsv_print_error(avctx, ret,
562 "Error during QSV decoding.");
Anton Khirnovf5c4d382015-07-14 16:16:26563 }
564
Anton Khirnovaa9d15d2015-07-09 18:08:13565 /* make sure we do not enter an infinite loop if the SDK
566 * did not consume any data and did not return anything */
Mark Thompson1f26a232016-10-21 17:57:12567 if (!*sync && !bs.DataOffset) {
Anton Khirnovaa9d15d2015-07-09 18:08:13568 bs.DataOffset = avpkt->size;
Mark Thompson0940b742016-10-30 16:58:23569 ++q->zero_consume_run;
570 if (q->zero_consume_run > 1)
571 ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data");
Linjie Fu87368882018-10-16 01:36:13572 } else if (!*sync && bs.DataOffset) {
573 ++q->buffered_count;
Mark Thompson0940b742016-10-30 16:58:23574 } else {
575 q->zero_consume_run = 0;
Anton Khirnovaa9d15d2015-07-09 18:08:13576 }
577
Mark Thompson1f26a232016-10-21 17:57:12578 if (*sync) {
579 QSVFrame *out_frame = find_frame(q, outsurf);
580
581 if (!out_frame) {
582 av_log(avctx, AV_LOG_ERROR,
583 "The returned surface does not correspond to any frame\n");
584 av_freep(&sync);
585 return AVERROR_BUG;
586 }
587
Chen,Wenbine6b990e2021-03-12 02:44:06588 out_frame->queued += 1;
Mark Thompson1f26a232016-10-21 17:57:12589 av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
590 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
591 } else {
592 av_freep(&sync);
Ivan Uskovc90dbc62015-07-24 10:26:14593 }
594
Dmitry Rogozhkinc1bcd322018-07-24 17:36:19595 if ((qsv_fifo_size(q->async_fifo) >= q->async_depth) ||
Mark Thompson1f26a232016-10-21 17:57:12596 (!avpkt->size && av_fifo_size(q->async_fifo))) {
Anton Khirnovf5c4d382015-07-14 16:16:26597 AVFrame *src_frame;
598
599 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
600 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
Chen,Wenbine6b990e2021-03-12 02:44:06601 out_frame->queued -= 1;
Anton Khirnovf5c4d382015-07-14 16:16:26602
Anton Khirnovb68e3532017-01-07 20:06:16603 if (avctx->pix_fmt != AV_PIX_FMT_QSV) {
604 do {
605 ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
606 } while (ret == MFX_WRN_IN_EXECUTION);
607 }
Anton Khirnovf5c4d382015-07-14 16:16:26608
Mark Thompson1f26a232016-10-21 17:57:12609 av_freep(&sync);
610
Anton Khirnovf5c4d382015-07-14 16:16:26611 src_frame = out_frame->frame;
612
Anton Khirnov4e08c822015-02-10 09:40:59613 ret = av_frame_ref(frame, src_frame);
614 if (ret < 0)
615 return ret;
616
Anton Khirnov404e5142016-08-09 10:05:49617 outsurf = &out_frame->surface;
Anton Khirnovf5c4d382015-07-14 16:16:26618
Haihao Xiang971b4ac2021-06-11 02:19:45619 frame->pts = MFX_PTS_TO_PTS(outsurf->Data.TimeStamp, avctx->pkt_timebase);
Anton Khirnov4e08c822015-02-10 09:40:59620
621 frame->repeat_pict =
622 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
623 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
624 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
625 frame->top_field_first =
626 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
627 frame->interlaced_frame =
628 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
Zhong Li52ed83f2018-04-04 09:51:29629 frame->pict_type = ff_qsv_map_pictype(out_frame->dec_info.FrameType);
630 //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames.
631 if (avctx->codec_id == AV_CODEC_ID_H264)
632 frame->key_frame = !!(out_frame->dec_info.FrameType & MFX_FRAMETYPE_IDR);
Anton Khirnov4e08c822015-02-10 09:40:59633
Anton Khirnov404e5142016-08-09 10:05:49634 /* update the surface properties */
635 if (avctx->pix_fmt == AV_PIX_FMT_QSV)
636 ((mfxFrameSurface1*)frame->data[3])->Info = outsurf->Info;
637
Anton Khirnov4e08c822015-02-10 09:40:59638 *got_frame = 1;
639 }
640
Mark Thompson1f26a232016-10-21 17:57:12641 return bs.DataOffset;
Ivan Uskov3f8e2e92015-08-06 16:10:24642}
Anton Khirnov4e08c822015-02-10 09:40:59643
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41644static void qsv_decode_close_qsvcontext(QSVContext *q)
Anton Khirnov4e08c822015-02-10 09:40:59645{
Mark Thompson1f26a232016-10-21 17:57:12646 QSVFrame *cur = q->work_frames;
Anton Khirnov4e08c822015-02-10 09:40:59647
Mark Thompson1f26a232016-10-21 17:57:12648 if (q->session)
649 MFXVideoDECODE_Close(q->session);
Ivan Uskovcc167f72015-08-04 10:40:06650
Mark Thompson1f26a232016-10-21 17:57:12651 while (q->async_fifo && av_fifo_size(q->async_fifo)) {
652 QSVFrame *out_frame;
653 mfxSyncPoint *sync;
654
655 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
656 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
657
658 av_freep(&sync);
659 }
660
661 while (cur) {
662 q->work_frames = cur->next;
663 av_frame_free(&cur->frame);
664 av_freep(&cur);
665 cur = q->work_frames;
666 }
Anton Khirnov4e08c822015-02-10 09:40:59667
Anton Khirnovf5c4d382015-07-14 16:16:26668 av_fifo_free(q->async_fifo);
669 q->async_fifo = NULL;
670
Zhong Li74007dd2019-09-19 20:45:26671 ff_qsv_close_internal_session(&q->internal_qs);
Mark Thompson1f26a232016-10-21 17:57:12672
673 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
Anton Khirnov4ab61cd2016-08-10 07:38:21674 av_buffer_unref(&q->frames_ctx.mids_buf);
Linjie Fu53459652019-10-08 13:41:02675 av_buffer_pool_uninit(&q->pool);
Anton Khirnov4e08c822015-02-10 09:40:59676}
Mark Thompson1f26a232016-10-21 17:57:12677
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41678static int qsv_process_data(AVCodecContext *avctx, QSVContext *q,
679 AVFrame *frame, int *got_frame, const AVPacket *pkt)
Mark Thompson1f26a232016-10-21 17:57:12680{
Mark Thompson1f26a232016-10-21 17:57:12681 int ret;
Zhong Li00d0a4a2019-08-13 06:11:09682 mfxVideoParam param = { 0 };
683 enum AVPixelFormat pix_fmt = AV_PIX_FMT_NV12;
Mark Thompson1f26a232016-10-21 17:57:12684
Mark Thompson1f26a232016-10-21 17:57:12685 if (!pkt->size)
686 return qsv_decode(avctx, q, frame, got_frame, pkt);
687
Mark Thompson1f26a232016-10-21 17:57:12688 /* TODO: flush delayed frames on reinit */
Zhong Li00d0a4a2019-08-13 06:11:09689
690 // sw_pix_fmt, coded_width/height should be set for ff_get_format(),
691 // assume sw_pix_fmt is NV12 and coded_width/height to be 1280x720,
692 // the assumption may be not corret but will be updated after header decoded if not true.
693 if (q->orig_pix_fmt != AV_PIX_FMT_NONE)
694 pix_fmt = q->orig_pix_fmt;
695 if (!avctx->coded_width)
696 avctx->coded_width = 1280;
697 if (!avctx->coded_height)
698 avctx->coded_height = 720;
699
700 ret = qsv_decode_header(avctx, q, pkt, pix_fmt, &param);
701
702 if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) ||
703 avctx->coded_width != param.mfx.FrameInfo.Width ||
704 avctx->coded_height != param.mfx.FrameInfo.Height)) {
Linjie Fu87368882018-10-16 01:36:13705 AVPacket zero_pkt = {0};
706
707 if (q->buffered_count) {
708 q->reinit_flag = 1;
709 /* decode zero-size pkt to flush the buffered pkt before reinit */
710 q->buffered_count--;
711 return qsv_decode(avctx, q, frame, got_frame, &zero_pkt);
712 }
Linjie Fu87368882018-10-16 01:36:13713 q->reinit_flag = 0;
Mark Thompson1f26a232016-10-21 17:57:12714
Zhong Li00d0a4a2019-08-13 06:11:09715 q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC);
Mark Thompson1f26a232016-10-21 17:57:12716
Zhong Li00d0a4a2019-08-13 06:11:09717 avctx->coded_width = param.mfx.FrameInfo.Width;
718 avctx->coded_height = param.mfx.FrameInfo.Height;
Mark Thompson1f26a232016-10-21 17:57:12719
Zhong Li00d0a4a2019-08-13 06:11:09720 ret = qsv_decode_preinit(avctx, q, pix_fmt, &param);
Mark Thompson1f26a232016-10-21 17:57:12721 if (ret < 0)
722 goto reinit_fail;
Zhong Li00d0a4a2019-08-13 06:11:09723 q->initialized = 0;
724 }
Mark Thompson1f26a232016-10-21 17:57:12725
Zhong Li00d0a4a2019-08-13 06:11:09726 if (!q->initialized) {
Xu Guangxin399c1f92021-01-05 02:43:40727 ret = qsv_decode_init_context(avctx, q, &param);
Mark Thompson1f26a232016-10-21 17:57:12728 if (ret < 0)
729 goto reinit_fail;
Zhong Li00d0a4a2019-08-13 06:11:09730 q->initialized = 1;
Mark Thompson1f26a232016-10-21 17:57:12731 }
732
733 return qsv_decode(avctx, q, frame, got_frame, pkt);
734
735reinit_fail:
Zhong Li0dfcfc52019-08-13 06:11:10736 q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE;
Mark Thompson1f26a232016-10-21 17:57:12737 return ret;
738}
739
Xu Guangxin399c1f92021-01-05 02:43:40740enum LoadPlugin {
741 LOAD_PLUGIN_NONE,
742 LOAD_PLUGIN_HEVC_SW,
743 LOAD_PLUGIN_HEVC_HW,
744};
745
746typedef struct QSVDecContext {
747 AVClass *class;
748 QSVContext qsv;
749
750 int load_plugin;
751
752 AVFifoBuffer *packet_fifo;
753
754 AVPacket buffer_pkt;
755} QSVDecContext;
756
757static void qsv_clear_buffers(QSVDecContext *s)
758{
759 AVPacket pkt;
760 while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) {
761 av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL);
762 av_packet_unref(&pkt);
763 }
764
765 av_packet_unref(&s->buffer_pkt);
766}
767
768static av_cold int qsv_decode_close(AVCodecContext *avctx)
769{
770 QSVDecContext *s = avctx->priv_data;
771
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41772 qsv_decode_close_qsvcontext(&s->qsv);
Xu Guangxin399c1f92021-01-05 02:43:40773
774 qsv_clear_buffers(s);
775
776 av_fifo_free(s->packet_fifo);
777
778 return 0;
779}
780
781static av_cold int qsv_decode_init(AVCodecContext *avctx)
782{
783 QSVDecContext *s = avctx->priv_data;
784 int ret;
Xu Guangxin7a5a5e62021-01-05 02:43:42785 const char *uid = NULL;
Xu Guangxin399c1f92021-01-05 02:43:40786
Xu Guangxind78ecf12021-01-05 02:43:41787 if (avctx->codec_id == AV_CODEC_ID_VP8) {
Xu Guangxin7a5a5e62021-01-05 02:43:42788 uid = "f622394d8d87452f878c51f2fc9b4131";
Xu Guangxind78ecf12021-01-05 02:43:41789 } else if (avctx->codec_id == AV_CODEC_ID_VP9) {
Xu Guangxin7a5a5e62021-01-05 02:43:42790 uid = "a922394d8d87452f878c51f2fc9b4131";
Xu Guangxind78ecf12021-01-05 02:43:41791 }
792 else if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) {
Xu Guangxin399c1f92021-01-05 02:43:40793 static const char * const uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6";
794 static const char * const uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e";
795
796 if (s->qsv.load_plugins[0]) {
797 av_log(avctx, AV_LOG_WARNING,
798 "load_plugins is not empty, but load_plugin is not set to 'none'."
799 "The load_plugin value will be ignored.\n");
800 } else {
Xu Guangxin399c1f92021-01-05 02:43:40801 if (s->load_plugin == LOAD_PLUGIN_HEVC_SW)
Xu Guangxin7a5a5e62021-01-05 02:43:42802 uid = uid_hevcdec_sw;
Xu Guangxin399c1f92021-01-05 02:43:40803 else
Xu Guangxin7a5a5e62021-01-05 02:43:42804 uid = uid_hevcdec_hw;
Xu Guangxin399c1f92021-01-05 02:43:40805 }
806 }
Xu Guangxin7a5a5e62021-01-05 02:43:42807 if (uid) {
808 av_freep(&s->qsv.load_plugins);
809 s->qsv.load_plugins = av_strdup(uid);
810 if (!s->qsv.load_plugins)
811 return AVERROR(ENOMEM);
812 }
Xu Guangxin399c1f92021-01-05 02:43:40813
814 s->qsv.orig_pix_fmt = AV_PIX_FMT_NV12;
815 s->packet_fifo = av_fifo_alloc(sizeof(AVPacket));
816 if (!s->packet_fifo) {
817 ret = AVERROR(ENOMEM);
818 goto fail;
819 }
820
Haihao Xiang971b4ac2021-06-11 02:19:45821 if (!avctx->pkt_timebase.num)
822 av_log(avctx, AV_LOG_WARNING, "Invalid pkt_timebase, passing timestamps as-is.\n");
823
Xu Guangxin399c1f92021-01-05 02:43:40824 return 0;
825fail:
826 qsv_decode_close(avctx);
827 return ret;
828}
829
830static int qsv_decode_frame(AVCodecContext *avctx, void *data,
831 int *got_frame, AVPacket *avpkt)
832{
833 QSVDecContext *s = avctx->priv_data;
834 AVFrame *frame = data;
835 int ret;
836
837 /* buffer the input packet */
838 if (avpkt->size) {
839 AVPacket input_ref;
840
841 if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) {
842 ret = av_fifo_realloc2(s->packet_fifo,
843 av_fifo_size(s->packet_fifo) + sizeof(input_ref));
844 if (ret < 0)
845 return ret;
846 }
847
848 ret = av_packet_ref(&input_ref, avpkt);
849 if (ret < 0)
850 return ret;
851 av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
852 }
853
854 /* process buffered data */
855 while (!*got_frame) {
856 /* prepare the input data */
857 if (s->buffer_pkt.size <= 0) {
858 /* no more data */
859 if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket))
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41860 return avpkt->size ? avpkt->size : qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt);
Xu Guangxin399c1f92021-01-05 02:43:40861 /* in progress of reinit, no read from fifo and keep the buffer_pkt */
862 if (!s->qsv.reinit_flag) {
863 av_packet_unref(&s->buffer_pkt);
864 av_fifo_generic_read(s->packet_fifo, &s->buffer_pkt, sizeof(s->buffer_pkt), NULL);
865 }
866 }
867
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41868 ret = qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt);
Xu Guangxin399c1f92021-01-05 02:43:40869 if (ret < 0){
870 /* Drop buffer_pkt when failed to decode the packet. Otherwise,
871 the decoder will keep decoding the failure packet. */
872 av_packet_unref(&s->buffer_pkt);
873 return ret;
874 }
875 if (s->qsv.reinit_flag)
876 continue;
877
878 s->buffer_pkt.size -= ret;
879 s->buffer_pkt.data += ret;
880 }
881
882 return avpkt->size;
883}
884
885static void qsv_decode_flush(AVCodecContext *avctx)
886{
887 QSVDecContext *s = avctx->priv_data;
888
889 qsv_clear_buffers(s);
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41890
891 s->qsv.orig_pix_fmt = AV_PIX_FMT_NONE;
892 s->qsv.initialized = 0;
Xu Guangxin399c1f92021-01-05 02:43:40893}
894
895#define OFFSET(x) offsetof(QSVDecContext, x)
896#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
897
898#define DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, opt) \
899static const AVClass x##_qsv_class = { \
900 .class_name = #x "_qsv", \
901 .item_name = av_default_item_name, \
902 .option = opt, \
903 .version = LIBAVUTIL_VERSION_INT, \
904}; \
Andreas Rheinhardta247ac62021-02-25 09:50:26905const AVCodec ff_##x##_qsv_decoder = { \
Xu Guangxin399c1f92021-01-05 02:43:40906 .name = #x "_qsv", \
907 .long_name = NULL_IF_CONFIG_SMALL(#X " video (Intel Quick Sync Video acceleration)"), \
908 .priv_data_size = sizeof(QSVDecContext), \
909 .type = AVMEDIA_TYPE_VIDEO, \
910 .id = AV_CODEC_ID_##X, \
911 .init = qsv_decode_init, \
912 .decode = qsv_decode_frame, \
913 .flush = qsv_decode_flush, \
914 .close = qsv_decode_close, \
915 .bsfs = bsf_name, \
916 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \
917 .priv_class = &x##_qsv_class, \
918 .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \
919 AV_PIX_FMT_P010, \
920 AV_PIX_FMT_QSV, \
921 AV_PIX_FMT_NONE }, \
Andreas Rheinhardtf0dc8fa2021-03-04 15:08:41922 .hw_configs = qsv_hw_configs, \
Xu Guangxin399c1f92021-01-05 02:43:40923 .wrapper_name = "qsv", \
924}; \
925
926#define DEFINE_QSV_DECODER(x, X, bsf_name) DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, options)
927
928#if CONFIG_HEVC_QSV_DECODER
929static const AVOption hevc_options[] = {
930 { "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 },
931
932 { "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" },
933 { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" },
934 { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" },
935 { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" },
936
937 { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
938 OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD },
939
940 { "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"},
941 { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"},
942 { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"},
943 { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"},
944 { NULL },
945};
946DEFINE_QSV_DECODER_WITH_OPTION(hevc, HEVC, "hevc_mp4toannexb", hevc_options)
947#endif
948
949static const AVOption options[] = {
950 { "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 },
951
952 { "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"},
953 { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"},
954 { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"},
955 { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"},
956 { NULL },
957};
958
959#if CONFIG_H264_QSV_DECODER
960DEFINE_QSV_DECODER(h264, H264, "h264_mp4toannexb")
961#endif
Xu Guangxind78ecf12021-01-05 02:43:41962
963#if CONFIG_MPEG2_QSV_DECODER
964DEFINE_QSV_DECODER(mpeg2, MPEG2VIDEO, NULL)
965#endif
966
967#if CONFIG_VC1_QSV_DECODER
968DEFINE_QSV_DECODER(vc1, VC1, NULL)
969#endif
970
971#if CONFIG_MJPEG_QSV_DECODER
972DEFINE_QSV_DECODER(mjpeg, MJPEG, NULL)
973#endif
974
975#if CONFIG_VP8_QSV_DECODER
976DEFINE_QSV_DECODER(vp8, VP8, NULL)
977#endif
978
979#if CONFIG_VP9_QSV_DECODER
980DEFINE_QSV_DECODER(vp9, VP9, NULL)
981#endif
982
983#if CONFIG_AV1_QSV_DECODER
984DEFINE_QSV_DECODER(av1, AV1, NULL)
985#endif