blob: baaf1f205f724f0d3a8cd21d78b4d494ff20861e [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
24#include <string.h>
25#include <sys/types.h>
26
27#include <mfx/mfxvideo.h>
28
29#include "libavutil/common.h"
Mark Thompson1f26a232016-10-21 17:57:1230#include "libavutil/hwcontext.h"
31#include "libavutil/hwcontext_qsv.h"
Anton Khirnov4e08c822015-02-10 09:40:5932#include "libavutil/mem.h"
33#include "libavutil/log.h"
Anton Khirnov92736c72016-06-22 09:53:0034#include "libavutil/pixdesc.h"
Anton Khirnov4e08c822015-02-10 09:40:5935#include "libavutil/pixfmt.h"
36#include "libavutil/time.h"
Linjie Fu53459652019-10-08 13:41:0237#include "libavutil/imgutils.h"
Anton Khirnov4e08c822015-02-10 09:40:5938
39#include "avcodec.h"
40#include "internal.h"
Linjie Fu53459652019-10-08 13:41:0241#include "decode.h"
Ivan Uskov6e127992015-07-14 11:07:0442#include "qsv.h"
Anton Khirnovd0a63d82015-03-13 07:13:0043#include "qsv_internal.h"
Anton Khirnovb04d0092015-03-13 06:55:5344#include "qsvdec.h"
Anton Khirnov4e08c822015-02-10 09:40:5945
Mark Thompson758fbc52017-10-25 23:18:4046const AVCodecHWConfigInternal *ff_qsv_hw_configs[] = {
47 &(const AVCodecHWConfigInternal) {
48 .public = {
49 .pix_fmt = AV_PIX_FMT_QSV,
50 .methods = AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX |
51 AV_CODEC_HW_CONFIG_METHOD_AD_HOC,
52 .device_type = AV_HWDEVICE_TYPE_QSV,
53 },
54 .hwaccel = NULL,
55 },
56 NULL
57};
58
Linjie Fu53459652019-10-08 13:41:0259static int ff_qsv_get_continuous_buffer(AVCodecContext *avctx, AVFrame *frame, AVBufferPool *pool)
60{
61 int ret = 0;
62
63 ff_decode_frame_props(avctx, frame);
64
65 frame->width = avctx->width;
66 frame->height = avctx->height;
67
68 switch (avctx->pix_fmt) {
69 case AV_PIX_FMT_NV12:
70 frame->linesize[0] = FFALIGN(avctx->width, 128);
71 break;
72 case AV_PIX_FMT_P010:
73 frame->linesize[0] = 2 * FFALIGN(avctx->width, 128);
74 break;
75 default:
76 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n");
Zhong Li9fff5c42019-12-28 14:22:0777 return AVERROR(EINVAL);
Linjie Fu53459652019-10-08 13:41:0278 }
79
80 frame->linesize[1] = frame->linesize[0];
81 frame->buf[0] = av_buffer_pool_get(pool);
82 if (!frame->buf[0])
83 return AVERROR(ENOMEM);
84
85 frame->data[0] = frame->buf[0]->data;
86 frame->data[1] = frame->data[0] +
87 frame->linesize[0] * FFALIGN(avctx->height, 64);
88
89 ret = ff_attach_decode_data(frame);
90 if (ret < 0)
91 return ret;
92
93 return 0;
94}
95
Mark Thompson1f26a232016-10-21 17:57:1296static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session,
Mark Thompson8aa3c2d2017-03-04 23:57:3697 AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref)
Anton Khirnov4e08c822015-02-10 09:40:5998{
Mark Thompson1f26a232016-10-21 17:57:1299 int ret;
100
Linjie Fu53459652019-10-08 13:41:02101 if (q->gpu_copy == MFX_GPUCOPY_ON &&
102 !(q->iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY))
103 av_log(avctx, AV_LOG_WARNING, "GPU-accelerated memory copy "
104 "only works in MFX_IOPATTERN_OUT_SYSTEM_MEMORY.\n");
Mark Thompson1f26a232016-10-21 17:57:12105 if (session) {
106 q->session = session;
107 } else if (hw_frames_ref) {
Zhong Li74007dd2019-09-19 20:45:26108 if (q->internal_qs.session) {
109 MFXClose(q->internal_qs.session);
110 q->internal_qs.session = NULL;
Mark Thompson1f26a232016-10-21 17:57:12111 }
112 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
113
114 q->frames_ctx.hw_frames_ctx = av_buffer_ref(hw_frames_ref);
115 if (!q->frames_ctx.hw_frames_ctx)
116 return AVERROR(ENOMEM);
117
Zhong Li74007dd2019-09-19 20:45:26118 ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
Mark Thompson91c3b502017-03-04 23:57:35119 &q->frames_ctx, q->load_plugins,
Linjie Fu53459652019-10-08 13:41:02120 q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
121 q->gpu_copy);
Mark Thompson1f26a232016-10-21 17:57:12122 if (ret < 0) {
123 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
124 return ret;
125 }
126
Zhong Li74007dd2019-09-19 20:45:26127 q->session = q->internal_qs.session;
Mark Thompson8aa3c2d2017-03-04 23:57:36128 } else if (hw_device_ref) {
Zhong Li74007dd2019-09-19 20:45:26129 if (q->internal_qs.session) {
130 MFXClose(q->internal_qs.session);
131 q->internal_qs.session = NULL;
Mark Thompson8aa3c2d2017-03-04 23:57:36132 }
133
Zhong Li74007dd2019-09-19 20:45:26134 ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session,
Linjie Fu53459652019-10-08 13:41:02135 hw_device_ref, q->load_plugins, q->gpu_copy);
Mark Thompson8aa3c2d2017-03-04 23:57:36136 if (ret < 0)
137 return ret;
138
Zhong Li74007dd2019-09-19 20:45:26139 q->session = q->internal_qs.session;
Mark Thompson1f26a232016-10-21 17:57:12140 } else {
Zhong Li74007dd2019-09-19 20:45:26141 if (!q->internal_qs.session) {
142 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
Linjie Fu53459652019-10-08 13:41:02143 q->load_plugins, q->gpu_copy);
Anton Khirnovd0a63d82015-03-13 07:13:00144 if (ret < 0)
145 return ret;
Anton Khirnov4e08c822015-02-10 09:40:59146 }
147
Zhong Li74007dd2019-09-19 20:45:26148 q->session = q->internal_qs.session;
Anton Khirnov4e08c822015-02-10 09:40:59149 }
150
Mark Thompson1f26a232016-10-21 17:57:12151 /* make sure the decoder is uninitialized */
152 MFXVideoDECODE_Close(q->session);
153
154 return 0;
Anton Khirnov4e08c822015-02-10 09:40:59155}
156
Dmitry Rogozhkinc1bcd322018-07-24 17:36:19157static inline unsigned int qsv_fifo_item_size(void)
158{
159 return sizeof(mfxSyncPoint*) + sizeof(QSVFrame*);
160}
161
162static inline unsigned int qsv_fifo_size(const AVFifoBuffer* fifo)
163{
164 return av_fifo_size(fifo) / qsv_fifo_item_size();
165}
166
Zhong Li00d0a4a2019-08-13 06:11:09167static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixelFormat pix_fmt, mfxVideoParam *param)
Anton Khirnov4e08c822015-02-10 09:40:59168{
Anton Khirnov6f19bbc2016-05-21 16:26:40169 mfxSession session = NULL;
Mark Thompson1f26a232016-10-21 17:57:12170 int iopattern = 0;
Anton Khirnov4e08c822015-02-10 09:40:59171 int ret;
Zhong Li00d0a4a2019-08-13 06:11:09172 enum AVPixelFormat pix_fmts[3] = {
173 AV_PIX_FMT_QSV, /* opaque format in case of video memory output */
174 pix_fmt, /* system memory format obtained from bitstream parser */
175 AV_PIX_FMT_NONE };
Anton Khirnov4e08c822015-02-10 09:40:59176
Zhong Li00d0a4a2019-08-13 06:11:09177 ret = ff_get_format(avctx, pix_fmts);
178 if (ret < 0) {
179 q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE;
180 return ret;
181 }
Anton Khirnov92736c72016-06-22 09:53:00182
Mark Thompson1f26a232016-10-21 17:57:12183 if (!q->async_fifo) {
Dmitry Rogozhkinc1bcd322018-07-24 17:36:19184 q->async_fifo = av_fifo_alloc(q->async_depth * qsv_fifo_item_size());
Mark Thompson1f26a232016-10-21 17:57:12185 if (!q->async_fifo)
186 return AVERROR(ENOMEM);
Hendrik Leppkesb54d6452015-10-22 15:00:49187 }
Hendrik Leppkesb54d6452015-10-22 15:00:49188
Anton Khirnove3281782016-07-30 14:38:51189 if (avctx->pix_fmt == AV_PIX_FMT_QSV && avctx->hwaccel_context) {
Mark Thompson1f26a232016-10-21 17:57:12190 AVQSVContext *user_ctx = avctx->hwaccel_context;
191 session = user_ctx->session;
192 iopattern = user_ctx->iopattern;
193 q->ext_buffers = user_ctx->ext_buffers;
194 q->nb_ext_buffers = user_ctx->nb_ext_buffers;
195 }
196
197 if (avctx->hw_frames_ctx) {
198 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
199 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
200
201 if (!iopattern) {
202 if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
203 iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
204 else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
205 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
206 }
Mark Thompson1f26a232016-10-21 17:57:12207 }
208
209 if (!iopattern)
210 iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
211 q->iopattern = iopattern;
212
Zhong Li525de952019-09-19 20:45:27213 ff_qsv_print_iopattern(avctx, q->iopattern, "Decoder");
214
Mark Thompson8aa3c2d2017-03-04 23:57:36215 ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx);
Anton Khirnov4e08c822015-02-10 09:40:59216 if (ret < 0) {
217 av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
218 return ret;
Ivan Uskov6e127992015-07-14 11:07:04219 }
Anton Khirnov4e08c822015-02-10 09:40:59220
Zhong Li00d0a4a2019-08-13 06:11:09221 param->IOPattern = q->iopattern;
222 param->AsyncDepth = q->async_depth;
223 param->ExtParam = q->ext_buffers;
224 param->NumExtParam = q->nb_ext_buffers;
Mark Thompson1f26a232016-10-21 17:57:12225
Zhong Li00d0a4a2019-08-13 06:11:09226 return 0;
227 }
Mark Thompson1f26a232016-10-21 17:57:12228
Zhong Li00d0a4a2019-08-13 06:11:09229static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, mfxVideoParam *param)
230{
231 int ret;
Mark Thompson1f26a232016-10-21 17:57:12232
Zhong Li00d0a4a2019-08-13 06:11:09233 avctx->width = param->mfx.FrameInfo.CropW;
234 avctx->height = param->mfx.FrameInfo.CropH;
235 avctx->coded_width = param->mfx.FrameInfo.Width;
236 avctx->coded_height = param->mfx.FrameInfo.Height;
237 avctx->level = param->mfx.CodecLevel;
238 avctx->profile = param->mfx.CodecProfile;
239 avctx->field_order = ff_qsv_map_picstruct(param->mfx.FrameInfo.PicStruct);
240 avctx->pix_fmt = ff_qsv_map_fourcc(param->mfx.FrameInfo.FourCC);
Anton Khirnov4e08c822015-02-10 09:40:59241
Zhong Li00d0a4a2019-08-13 06:11:09242 ret = MFXVideoDECODE_Init(q->session, param);
Anton Khirnov95414eb2016-06-25 19:38:10243 if (ret < 0)
244 return ff_qsv_print_error(avctx, ret,
245 "Error initializing the MFX video decoder");
Anton Khirnov4e08c822015-02-10 09:40:59246
Zhong Li00d0a4a2019-08-13 06:11:09247 q->frame_info = param->mfx.FrameInfo;
248
Linjie Fu53459652019-10-08 13:41:02249 if (!avctx->hw_frames_ctx)
250 q->pool = av_buffer_pool_init(av_image_get_buffer_size(avctx->pix_fmt,
251 FFALIGN(avctx->width, 128), FFALIGN(avctx->height, 64), 1), av_buffer_allocz);
Zhong Li00d0a4a2019-08-13 06:11:09252 return 0;
253}
254
255static int qsv_decode_header(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt, enum AVPixelFormat pix_fmt, mfxVideoParam *param)
256{
257 int ret;
258
259 mfxBitstream bs = { 0 };
260
261 if (avpkt->size) {
262 bs.Data = avpkt->data;
263 bs.DataLength = avpkt->size;
264 bs.MaxLength = bs.DataLength;
265 bs.TimeStamp = avpkt->pts;
266 if (avctx->field_order == AV_FIELD_PROGRESSIVE)
267 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
268 } else
269 return AVERROR_INVALIDDATA;
270
271
272 if(!q->session) {
273 ret = qsv_decode_preinit(avctx, q, pix_fmt, param);
274 if (ret < 0)
275 return ret;
276 }
277
278 ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
279 if (ret < 0)
280 return ret;
281
282 param->mfx.CodecId = ret;
283 ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, param);
284 if (MFX_ERR_MORE_DATA == ret) {
285 return AVERROR(EAGAIN);
286 }
287 if (ret < 0)
288 return ff_qsv_print_error(avctx, ret,
289 "Error decoding stream header");
Anton Khirnovce320cf2016-06-22 09:44:09290
Anton Khirnov4e08c822015-02-10 09:40:59291 return 0;
292}
293
Anton Khirnovce320cf2016-06-22 09:44:09294static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame)
Anton Khirnov4e08c822015-02-10 09:40:59295{
296 int ret;
297
Linjie Fu53459652019-10-08 13:41:02298 if (q->pool)
299 ret = ff_qsv_get_continuous_buffer(avctx, frame->frame, q->pool);
300 else
301 ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
302
Anton Khirnov4e08c822015-02-10 09:40:59303 if (ret < 0)
304 return ret;
305
306 if (frame->frame->format == AV_PIX_FMT_QSV) {
Anton Khirnov404e5142016-08-09 10:05:49307 frame->surface = *(mfxFrameSurface1*)frame->frame->data[3];
Anton Khirnov4e08c822015-02-10 09:40:59308 } else {
Anton Khirnov404e5142016-08-09 10:05:49309 frame->surface.Info = q->frame_info;
Anton Khirnov4e08c822015-02-10 09:40:59310
Anton Khirnov404e5142016-08-09 10:05:49311 frame->surface.Data.PitchLow = frame->frame->linesize[0];
312 frame->surface.Data.Y = frame->frame->data[0];
313 frame->surface.Data.UV = frame->frame->data[1];
Anton Khirnov4e08c822015-02-10 09:40:59314 }
315
Anton Khirnov00aeedd2016-08-10 06:29:23316 if (q->frames_ctx.mids) {
317 ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame);
318 if (ret < 0)
319 return ret;
320
321 frame->surface.Data.MemId = &q->frames_ctx.mids[ret];
322 }
Zhong Li52ed83f2018-04-04 09:51:29323 frame->surface.Data.ExtParam = &frame->ext_param;
324 frame->surface.Data.NumExtParam = 1;
325 frame->ext_param = (mfxExtBuffer*)&frame->dec_info;
326 frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO;
327 frame->dec_info.Header.BufferSz = sizeof(frame->dec_info);
Anton Khirnov00aeedd2016-08-10 06:29:23328
Anton Khirnov404e5142016-08-09 10:05:49329 frame->used = 1;
330
Anton Khirnov4e08c822015-02-10 09:40:59331 return 0;
332}
333
334static void qsv_clear_unused_frames(QSVContext *q)
335{
336 QSVFrame *cur = q->work_frames;
337 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49338 if (cur->used && !cur->surface.Data.Locked && !cur->queued) {
339 cur->used = 0;
Anton Khirnov4e08c822015-02-10 09:40:59340 av_frame_unref(cur->frame);
341 }
342 cur = cur->next;
343 }
344}
345
346static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
347{
348 QSVFrame *frame, **last;
349 int ret;
350
351 qsv_clear_unused_frames(q);
352
353 frame = q->work_frames;
354 last = &q->work_frames;
355 while (frame) {
Anton Khirnov404e5142016-08-09 10:05:49356 if (!frame->used) {
Anton Khirnovce320cf2016-06-22 09:44:09357 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59358 if (ret < 0)
359 return ret;
Anton Khirnov404e5142016-08-09 10:05:49360 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59361 return 0;
362 }
363
364 last = &frame->next;
365 frame = frame->next;
366 }
367
368 frame = av_mallocz(sizeof(*frame));
369 if (!frame)
370 return AVERROR(ENOMEM);
371 frame->frame = av_frame_alloc();
372 if (!frame->frame) {
373 av_freep(&frame);
374 return AVERROR(ENOMEM);
375 }
376 *last = frame;
377
Anton Khirnovce320cf2016-06-22 09:44:09378 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59379 if (ret < 0)
380 return ret;
381
Anton Khirnov404e5142016-08-09 10:05:49382 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59383
384 return 0;
385}
386
Anton Khirnovf5c4d382015-07-14 16:16:26387static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
Anton Khirnov4e08c822015-02-10 09:40:59388{
389 QSVFrame *cur = q->work_frames;
390 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49391 if (surf == &cur->surface)
Anton Khirnovf5c4d382015-07-14 16:16:26392 return cur;
Anton Khirnov4e08c822015-02-10 09:40:59393 cur = cur->next;
394 }
395 return NULL;
396}
397
Mark Thompson1f26a232016-10-21 17:57:12398static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
399 AVFrame *frame, int *got_frame,
400 AVPacket *avpkt)
Anton Khirnov4e08c822015-02-10 09:40:59401{
Anton Khirnovf5c4d382015-07-14 16:16:26402 QSVFrame *out_frame;
Anton Khirnov4e08c822015-02-10 09:40:59403 mfxFrameSurface1 *insurf;
404 mfxFrameSurface1 *outsurf;
Mark Thompson1f26a232016-10-21 17:57:12405 mfxSyncPoint *sync;
Anton Khirnov4e08c822015-02-10 09:40:59406 mfxBitstream bs = { { { 0 } } };
407 int ret;
408
Mark Thompson1f26a232016-10-21 17:57:12409 if (avpkt->size) {
410 bs.Data = avpkt->data;
411 bs.DataLength = avpkt->size;
Anton Khirnov4e08c822015-02-10 09:40:59412 bs.MaxLength = bs.DataLength;
413 bs.TimeStamp = avpkt->pts;
Zhong Li54307b32018-04-07 17:38:55414 if (avctx->field_order == AV_FIELD_PROGRESSIVE)
415 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
Anton Khirnov4e08c822015-02-10 09:40:59416 }
417
Mark Thompson1f26a232016-10-21 17:57:12418 sync = av_mallocz(sizeof(*sync));
419 if (!sync) {
420 av_freep(&sync);
421 return AVERROR(ENOMEM);
422 }
423
424 do {
Anton Khirnov4e08c822015-02-10 09:40:59425 ret = get_surface(avctx, q, &insurf);
Timothy Gub6f80b12016-12-05 18:20:26426 if (ret < 0) {
427 av_freep(&sync);
Anton Khirnov4e08c822015-02-10 09:40:59428 return ret;
Timothy Gub6f80b12016-12-05 18:20:26429 }
Mark Thompson1f26a232016-10-21 17:57:12430
431 ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
432 insurf, &outsurf, sync);
433 if (ret == MFX_WRN_DEVICE_BUSY)
Ivan Uskov9f543e02015-07-24 11:45:38434 av_usleep(500);
Anton Khirnov4e08c822015-02-10 09:40:59435
Mark Thompson1f26a232016-10-21 17:57:12436 } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
Anton Khirnov4e08c822015-02-10 09:40:59437
Mark Thompson1f26a232016-10-21 17:57:12438 if (ret != MFX_ERR_NONE &&
439 ret != MFX_ERR_MORE_DATA &&
440 ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
441 ret != MFX_ERR_MORE_SURFACE) {
Mark Thompson1f26a232016-10-21 17:57:12442 av_freep(&sync);
Anton Khirnov95414eb2016-06-25 19:38:10443 return ff_qsv_print_error(avctx, ret,
444 "Error during QSV decoding.");
Anton Khirnovf5c4d382015-07-14 16:16:26445 }
446
Anton Khirnovaa9d15d2015-07-09 18:08:13447 /* make sure we do not enter an infinite loop if the SDK
448 * did not consume any data and did not return anything */
Mark Thompson1f26a232016-10-21 17:57:12449 if (!*sync && !bs.DataOffset) {
Anton Khirnovaa9d15d2015-07-09 18:08:13450 bs.DataOffset = avpkt->size;
Mark Thompson0940b742016-10-30 16:58:23451 ++q->zero_consume_run;
452 if (q->zero_consume_run > 1)
453 ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data");
Linjie Fu87368882018-10-16 01:36:13454 } else if (!*sync && bs.DataOffset) {
455 ++q->buffered_count;
Mark Thompson0940b742016-10-30 16:58:23456 } else {
457 q->zero_consume_run = 0;
Anton Khirnovaa9d15d2015-07-09 18:08:13458 }
459
Mark Thompson1f26a232016-10-21 17:57:12460 if (*sync) {
461 QSVFrame *out_frame = find_frame(q, outsurf);
462
463 if (!out_frame) {
464 av_log(avctx, AV_LOG_ERROR,
465 "The returned surface does not correspond to any frame\n");
466 av_freep(&sync);
467 return AVERROR_BUG;
468 }
469
470 out_frame->queued = 1;
471 av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
472 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
473 } else {
474 av_freep(&sync);
Ivan Uskovc90dbc62015-07-24 10:26:14475 }
476
Dmitry Rogozhkinc1bcd322018-07-24 17:36:19477 if ((qsv_fifo_size(q->async_fifo) >= q->async_depth) ||
Mark Thompson1f26a232016-10-21 17:57:12478 (!avpkt->size && av_fifo_size(q->async_fifo))) {
Anton Khirnovf5c4d382015-07-14 16:16:26479 AVFrame *src_frame;
480
481 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
482 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
483 out_frame->queued = 0;
484
Anton Khirnovb68e3532017-01-07 20:06:16485 if (avctx->pix_fmt != AV_PIX_FMT_QSV) {
486 do {
487 ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
488 } while (ret == MFX_WRN_IN_EXECUTION);
489 }
Anton Khirnovf5c4d382015-07-14 16:16:26490
Mark Thompson1f26a232016-10-21 17:57:12491 av_freep(&sync);
492
Anton Khirnovf5c4d382015-07-14 16:16:26493 src_frame = out_frame->frame;
494
Anton Khirnov4e08c822015-02-10 09:40:59495 ret = av_frame_ref(frame, src_frame);
496 if (ret < 0)
497 return ret;
498
Anton Khirnov404e5142016-08-09 10:05:49499 outsurf = &out_frame->surface;
Anton Khirnovf5c4d382015-07-14 16:16:26500
Anton Khirnov32c83592016-03-19 20:45:24501#if FF_API_PKT_PTS
502FF_DISABLE_DEPRECATION_WARNINGS
503 frame->pkt_pts = outsurf->Data.TimeStamp;
504FF_ENABLE_DEPRECATION_WARNINGS
505#endif
506 frame->pts = outsurf->Data.TimeStamp;
Anton Khirnov4e08c822015-02-10 09:40:59507
508 frame->repeat_pict =
509 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
510 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
511 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
512 frame->top_field_first =
513 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
514 frame->interlaced_frame =
515 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
Zhong Li52ed83f2018-04-04 09:51:29516 frame->pict_type = ff_qsv_map_pictype(out_frame->dec_info.FrameType);
517 //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames.
518 if (avctx->codec_id == AV_CODEC_ID_H264)
519 frame->key_frame = !!(out_frame->dec_info.FrameType & MFX_FRAMETYPE_IDR);
Anton Khirnov4e08c822015-02-10 09:40:59520
Anton Khirnov404e5142016-08-09 10:05:49521 /* update the surface properties */
522 if (avctx->pix_fmt == AV_PIX_FMT_QSV)
523 ((mfxFrameSurface1*)frame->data[3])->Info = outsurf->Info;
524
Anton Khirnov4e08c822015-02-10 09:40:59525 *got_frame = 1;
526 }
527
Mark Thompson1f26a232016-10-21 17:57:12528 return bs.DataOffset;
Ivan Uskov3f8e2e92015-08-06 16:10:24529}
Anton Khirnov4e08c822015-02-10 09:40:59530
Anton Khirnov9ba27c22015-03-13 07:21:38531int ff_qsv_decode_close(QSVContext *q)
Anton Khirnov4e08c822015-02-10 09:40:59532{
Mark Thompson1f26a232016-10-21 17:57:12533 QSVFrame *cur = q->work_frames;
Anton Khirnov4e08c822015-02-10 09:40:59534
Mark Thompson1f26a232016-10-21 17:57:12535 if (q->session)
536 MFXVideoDECODE_Close(q->session);
Ivan Uskovcc167f72015-08-04 10:40:06537
Mark Thompson1f26a232016-10-21 17:57:12538 while (q->async_fifo && av_fifo_size(q->async_fifo)) {
539 QSVFrame *out_frame;
540 mfxSyncPoint *sync;
541
542 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
543 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
544
545 av_freep(&sync);
546 }
547
548 while (cur) {
549 q->work_frames = cur->next;
550 av_frame_free(&cur->frame);
551 av_freep(&cur);
552 cur = q->work_frames;
553 }
Anton Khirnov4e08c822015-02-10 09:40:59554
Anton Khirnovf5c4d382015-07-14 16:16:26555 av_fifo_free(q->async_fifo);
556 q->async_fifo = NULL;
557
Zhong Li74007dd2019-09-19 20:45:26558 ff_qsv_close_internal_session(&q->internal_qs);
Mark Thompson1f26a232016-10-21 17:57:12559
560 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
Anton Khirnov4ab61cd2016-08-10 07:38:21561 av_buffer_unref(&q->frames_ctx.mids_buf);
Linjie Fu53459652019-10-08 13:41:02562 av_buffer_pool_uninit(&q->pool);
Ivan Uskovd50ab822015-07-23 09:14:41563
Anton Khirnov4e08c822015-02-10 09:40:59564 return 0;
565}
Mark Thompson1f26a232016-10-21 17:57:12566
567int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q,
568 AVFrame *frame, int *got_frame, AVPacket *pkt)
569{
Mark Thompson1f26a232016-10-21 17:57:12570 int ret;
Zhong Li00d0a4a2019-08-13 06:11:09571 mfxVideoParam param = { 0 };
572 enum AVPixelFormat pix_fmt = AV_PIX_FMT_NV12;
Mark Thompson1f26a232016-10-21 17:57:12573
Mark Thompson1f26a232016-10-21 17:57:12574 if (!pkt->size)
575 return qsv_decode(avctx, q, frame, got_frame, pkt);
576
Mark Thompson1f26a232016-10-21 17:57:12577 /* TODO: flush delayed frames on reinit */
Zhong Li00d0a4a2019-08-13 06:11:09578
579 // sw_pix_fmt, coded_width/height should be set for ff_get_format(),
580 // assume sw_pix_fmt is NV12 and coded_width/height to be 1280x720,
581 // the assumption may be not corret but will be updated after header decoded if not true.
582 if (q->orig_pix_fmt != AV_PIX_FMT_NONE)
583 pix_fmt = q->orig_pix_fmt;
584 if (!avctx->coded_width)
585 avctx->coded_width = 1280;
586 if (!avctx->coded_height)
587 avctx->coded_height = 720;
588
589 ret = qsv_decode_header(avctx, q, pkt, pix_fmt, &param);
590
591 if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) ||
592 avctx->coded_width != param.mfx.FrameInfo.Width ||
593 avctx->coded_height != param.mfx.FrameInfo.Height)) {
Linjie Fu87368882018-10-16 01:36:13594 AVPacket zero_pkt = {0};
595
596 if (q->buffered_count) {
597 q->reinit_flag = 1;
598 /* decode zero-size pkt to flush the buffered pkt before reinit */
599 q->buffered_count--;
600 return qsv_decode(avctx, q, frame, got_frame, &zero_pkt);
601 }
Linjie Fu87368882018-10-16 01:36:13602 q->reinit_flag = 0;
Mark Thompson1f26a232016-10-21 17:57:12603
Zhong Li00d0a4a2019-08-13 06:11:09604 q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC);
Mark Thompson1f26a232016-10-21 17:57:12605
Zhong Li00d0a4a2019-08-13 06:11:09606 avctx->coded_width = param.mfx.FrameInfo.Width;
607 avctx->coded_height = param.mfx.FrameInfo.Height;
Mark Thompson1f26a232016-10-21 17:57:12608
Zhong Li00d0a4a2019-08-13 06:11:09609 ret = qsv_decode_preinit(avctx, q, pix_fmt, &param);
Mark Thompson1f26a232016-10-21 17:57:12610 if (ret < 0)
611 goto reinit_fail;
Zhong Li00d0a4a2019-08-13 06:11:09612 q->initialized = 0;
613 }
Mark Thompson1f26a232016-10-21 17:57:12614
Zhong Li00d0a4a2019-08-13 06:11:09615 if (!q->initialized) {
616 ret = qsv_decode_init(avctx, q, &param);
Mark Thompson1f26a232016-10-21 17:57:12617 if (ret < 0)
618 goto reinit_fail;
Zhong Li00d0a4a2019-08-13 06:11:09619 q->initialized = 1;
Mark Thompson1f26a232016-10-21 17:57:12620 }
621
622 return qsv_decode(avctx, q, frame, got_frame, pkt);
623
624reinit_fail:
Zhong Li0dfcfc52019-08-13 06:11:10625 q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE;
Mark Thompson1f26a232016-10-21 17:57:12626 return ret;
627}
628
629void ff_qsv_decode_flush(AVCodecContext *avctx, QSVContext *q)
630{
631 q->orig_pix_fmt = AV_PIX_FMT_NONE;
Zhong Li00d0a4a2019-08-13 06:11:09632 q->initialized = 0;
Mark Thompson1f26a232016-10-21 17:57:12633}