blob: 55fe59b5319bb6ce9d8fc0306c73d0b75785848a [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"
37
38#include "avcodec.h"
39#include "internal.h"
Ivan Uskov6e127992015-07-14 11:07:0440#include "qsv.h"
Anton Khirnovd0a63d82015-03-13 07:13:0041#include "qsv_internal.h"
Anton Khirnovb04d0092015-03-13 06:55:5342#include "qsvdec.h"
Anton Khirnov4e08c822015-02-10 09:40:5943
Mark Thompson758fbc52017-10-25 23:18:4044const AVCodecHWConfigInternal *ff_qsv_hw_configs[] = {
45 &(const AVCodecHWConfigInternal) {
46 .public = {
47 .pix_fmt = AV_PIX_FMT_QSV,
48 .methods = AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX |
49 AV_CODEC_HW_CONFIG_METHOD_AD_HOC,
50 .device_type = AV_HWDEVICE_TYPE_QSV,
51 },
52 .hwaccel = NULL,
53 },
54 NULL
55};
56
Mark Thompson1f26a232016-10-21 17:57:1257static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session,
Mark Thompson8aa3c2d2017-03-04 23:57:3658 AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref)
Anton Khirnov4e08c822015-02-10 09:40:5959{
Mark Thompson1f26a232016-10-21 17:57:1260 int ret;
61
62 if (session) {
63 q->session = session;
64 } else if (hw_frames_ref) {
65 if (q->internal_session) {
66 MFXClose(q->internal_session);
67 q->internal_session = NULL;
68 }
69 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
70
71 q->frames_ctx.hw_frames_ctx = av_buffer_ref(hw_frames_ref);
72 if (!q->frames_ctx.hw_frames_ctx)
73 return AVERROR(ENOMEM);
74
Mark Thompson91c3b502017-03-04 23:57:3575 ret = ff_qsv_init_session_frames(avctx, &q->internal_session,
76 &q->frames_ctx, q->load_plugins,
77 q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY);
Mark Thompson1f26a232016-10-21 17:57:1278 if (ret < 0) {
79 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
80 return ret;
81 }
82
83 q->session = q->internal_session;
Mark Thompson8aa3c2d2017-03-04 23:57:3684 } else if (hw_device_ref) {
85 if (q->internal_session) {
86 MFXClose(q->internal_session);
87 q->internal_session = NULL;
88 }
89
90 ret = ff_qsv_init_session_device(avctx, &q->internal_session,
91 hw_device_ref, q->load_plugins);
92 if (ret < 0)
93 return ret;
94
95 q->session = q->internal_session;
Mark Thompson1f26a232016-10-21 17:57:1296 } else {
97 if (!q->internal_session) {
98 ret = ff_qsv_init_internal_session(avctx, &q->internal_session,
99 q->load_plugins);
Anton Khirnovd0a63d82015-03-13 07:13:00100 if (ret < 0)
101 return ret;
Anton Khirnov4e08c822015-02-10 09:40:59102 }
103
Mark Thompson1f26a232016-10-21 17:57:12104 q->session = q->internal_session;
Anton Khirnov4e08c822015-02-10 09:40:59105 }
106
Mark Thompson1f26a232016-10-21 17:57:12107 /* make sure the decoder is uninitialized */
108 MFXVideoDECODE_Close(q->session);
109
110 return 0;
Anton Khirnov4e08c822015-02-10 09:40:59111}
112
Mark Thompson1f26a232016-10-21 17:57:12113static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q)
Anton Khirnov4e08c822015-02-10 09:40:59114{
Anton Khirnov92736c72016-06-22 09:53:00115 const AVPixFmtDescriptor *desc;
Anton Khirnov6f19bbc2016-05-21 16:26:40116 mfxSession session = NULL;
Mark Thompson1f26a232016-10-21 17:57:12117 int iopattern = 0;
Diego Biurrun76167142016-11-15 15:19:30118 mfxVideoParam param = { 0 };
Anton Khirnov924e2ec2016-06-22 09:57:36119 int frame_width = avctx->coded_width;
120 int frame_height = avctx->coded_height;
Anton Khirnov4e08c822015-02-10 09:40:59121 int ret;
122
Anton Khirnov92736c72016-06-22 09:53:00123 desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
124 if (!desc)
125 return AVERROR_BUG;
126
Mark Thompson1f26a232016-10-21 17:57:12127 if (!q->async_fifo) {
128 q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
129 (sizeof(mfxSyncPoint*) + sizeof(QSVFrame*)));
130 if (!q->async_fifo)
131 return AVERROR(ENOMEM);
Hendrik Leppkesb54d6452015-10-22 15:00:49132 }
Hendrik Leppkesb54d6452015-10-22 15:00:49133
Anton Khirnove3281782016-07-30 14:38:51134 if (avctx->pix_fmt == AV_PIX_FMT_QSV && avctx->hwaccel_context) {
Mark Thompson1f26a232016-10-21 17:57:12135 AVQSVContext *user_ctx = avctx->hwaccel_context;
136 session = user_ctx->session;
137 iopattern = user_ctx->iopattern;
138 q->ext_buffers = user_ctx->ext_buffers;
139 q->nb_ext_buffers = user_ctx->nb_ext_buffers;
140 }
141
142 if (avctx->hw_frames_ctx) {
143 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
144 AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
145
146 if (!iopattern) {
147 if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
148 iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
149 else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
150 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
151 }
Anton Khirnov924e2ec2016-06-22 09:57:36152
153 frame_width = frames_hwctx->surfaces[0].Info.Width;
154 frame_height = frames_hwctx->surfaces[0].Info.Height;
Mark Thompson1f26a232016-10-21 17:57:12155 }
156
157 if (!iopattern)
158 iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
159 q->iopattern = iopattern;
160
Mark Thompson8aa3c2d2017-03-04 23:57:36161 ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx);
Anton Khirnov4e08c822015-02-10 09:40:59162 if (ret < 0) {
163 av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
164 return ret;
Ivan Uskov6e127992015-07-14 11:07:04165 }
Anton Khirnov4e08c822015-02-10 09:40:59166
Anton Khirnovd0a63d82015-03-13 07:13:00167 ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
Mark Thompson1f26a232016-10-21 17:57:12168 if (ret < 0)
Anton Khirnov4e08c822015-02-10 09:40:59169 return ret;
Mark Thompson1f26a232016-10-21 17:57:12170
171 param.mfx.CodecId = ret;
172 param.mfx.CodecProfile = ff_qsv_profile_to_mfx(avctx->codec_id, avctx->profile);
173 param.mfx.CodecLevel = avctx->level == FF_LEVEL_UNKNOWN ? MFX_LEVEL_UNKNOWN : avctx->level;
174
Anton Khirnov92736c72016-06-22 09:53:00175 param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth;
176 param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth;
177 param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8;
Anton Khirnov536bb172016-06-22 09:41:26178 param.mfx.FrameInfo.FourCC = q->fourcc;
Anton Khirnov924e2ec2016-06-22 09:57:36179 param.mfx.FrameInfo.Width = frame_width;
180 param.mfx.FrameInfo.Height = frame_height;
Mark Thompson1f26a232016-10-21 17:57:12181 param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
182
183 switch (avctx->field_order) {
184 case AV_FIELD_PROGRESSIVE:
185 param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
186 break;
187 case AV_FIELD_TT:
188 param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
189 break;
190 case AV_FIELD_BB:
191 param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_BFF;
192 break;
193 default:
194 param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_UNKNOWN;
195 break;
Ivan Uskov1acb19d2015-07-20 15:07:34196 }
Anton Khirnov4e08c822015-02-10 09:40:59197
Anton Khirnov4e08c822015-02-10 09:40:59198 param.IOPattern = q->iopattern;
199 param.AsyncDepth = q->async_depth;
200 param.ExtParam = q->ext_buffers;
201 param.NumExtParam = q->nb_ext_buffers;
202
203 ret = MFXVideoDECODE_Init(q->session, &param);
Anton Khirnov95414eb2016-06-25 19:38:10204 if (ret < 0)
205 return ff_qsv_print_error(avctx, ret,
206 "Error initializing the MFX video decoder");
Anton Khirnov4e08c822015-02-10 09:40:59207
Anton Khirnovce320cf2016-06-22 09:44:09208 q->frame_info = param.mfx.FrameInfo;
209
Anton Khirnov4e08c822015-02-10 09:40:59210 return 0;
211}
212
Anton Khirnovce320cf2016-06-22 09:44:09213static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame)
Anton Khirnov4e08c822015-02-10 09:40:59214{
215 int ret;
216
217 ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
218 if (ret < 0)
219 return ret;
220
221 if (frame->frame->format == AV_PIX_FMT_QSV) {
Anton Khirnov404e5142016-08-09 10:05:49222 frame->surface = *(mfxFrameSurface1*)frame->frame->data[3];
Anton Khirnov4e08c822015-02-10 09:40:59223 } else {
Anton Khirnov404e5142016-08-09 10:05:49224 frame->surface.Info = q->frame_info;
Anton Khirnov4e08c822015-02-10 09:40:59225
Anton Khirnov404e5142016-08-09 10:05:49226 frame->surface.Data.PitchLow = frame->frame->linesize[0];
227 frame->surface.Data.Y = frame->frame->data[0];
228 frame->surface.Data.UV = frame->frame->data[1];
Anton Khirnov4e08c822015-02-10 09:40:59229 }
230
Anton Khirnov00aeedd2016-08-10 06:29:23231 if (q->frames_ctx.mids) {
232 ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame);
233 if (ret < 0)
234 return ret;
235
236 frame->surface.Data.MemId = &q->frames_ctx.mids[ret];
237 }
238
Anton Khirnov404e5142016-08-09 10:05:49239 frame->used = 1;
240
Anton Khirnov4e08c822015-02-10 09:40:59241 return 0;
242}
243
244static void qsv_clear_unused_frames(QSVContext *q)
245{
246 QSVFrame *cur = q->work_frames;
247 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49248 if (cur->used && !cur->surface.Data.Locked && !cur->queued) {
249 cur->used = 0;
Anton Khirnov4e08c822015-02-10 09:40:59250 av_frame_unref(cur->frame);
251 }
252 cur = cur->next;
253 }
254}
255
256static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
257{
258 QSVFrame *frame, **last;
259 int ret;
260
261 qsv_clear_unused_frames(q);
262
263 frame = q->work_frames;
264 last = &q->work_frames;
265 while (frame) {
Anton Khirnov404e5142016-08-09 10:05:49266 if (!frame->used) {
Anton Khirnovce320cf2016-06-22 09:44:09267 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59268 if (ret < 0)
269 return ret;
Anton Khirnov404e5142016-08-09 10:05:49270 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59271 return 0;
272 }
273
274 last = &frame->next;
275 frame = frame->next;
276 }
277
278 frame = av_mallocz(sizeof(*frame));
279 if (!frame)
280 return AVERROR(ENOMEM);
281 frame->frame = av_frame_alloc();
282 if (!frame->frame) {
283 av_freep(&frame);
284 return AVERROR(ENOMEM);
285 }
286 *last = frame;
287
Anton Khirnovce320cf2016-06-22 09:44:09288 ret = alloc_frame(avctx, q, frame);
Anton Khirnov4e08c822015-02-10 09:40:59289 if (ret < 0)
290 return ret;
291
Anton Khirnov404e5142016-08-09 10:05:49292 *surf = &frame->surface;
Anton Khirnov4e08c822015-02-10 09:40:59293
294 return 0;
295}
296
Anton Khirnovf5c4d382015-07-14 16:16:26297static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
Anton Khirnov4e08c822015-02-10 09:40:59298{
299 QSVFrame *cur = q->work_frames;
300 while (cur) {
Anton Khirnov404e5142016-08-09 10:05:49301 if (surf == &cur->surface)
Anton Khirnovf5c4d382015-07-14 16:16:26302 return cur;
Anton Khirnov4e08c822015-02-10 09:40:59303 cur = cur->next;
304 }
305 return NULL;
306}
307
Mark Thompson1f26a232016-10-21 17:57:12308static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
309 AVFrame *frame, int *got_frame,
310 AVPacket *avpkt)
Anton Khirnov4e08c822015-02-10 09:40:59311{
Anton Khirnovf5c4d382015-07-14 16:16:26312 QSVFrame *out_frame;
Anton Khirnov4e08c822015-02-10 09:40:59313 mfxFrameSurface1 *insurf;
314 mfxFrameSurface1 *outsurf;
Mark Thompson1f26a232016-10-21 17:57:12315 mfxSyncPoint *sync;
Anton Khirnov4e08c822015-02-10 09:40:59316 mfxBitstream bs = { { { 0 } } };
317 int ret;
318
Mark Thompson1f26a232016-10-21 17:57:12319 if (avpkt->size) {
320 bs.Data = avpkt->data;
321 bs.DataLength = avpkt->size;
Anton Khirnov4e08c822015-02-10 09:40:59322 bs.MaxLength = bs.DataLength;
323 bs.TimeStamp = avpkt->pts;
324 }
325
Mark Thompson1f26a232016-10-21 17:57:12326 sync = av_mallocz(sizeof(*sync));
327 if (!sync) {
328 av_freep(&sync);
329 return AVERROR(ENOMEM);
330 }
331
332 do {
Anton Khirnov4e08c822015-02-10 09:40:59333 ret = get_surface(avctx, q, &insurf);
Timothy Gub6f80b12016-12-05 18:20:26334 if (ret < 0) {
335 av_freep(&sync);
Anton Khirnov4e08c822015-02-10 09:40:59336 return ret;
Timothy Gub6f80b12016-12-05 18:20:26337 }
Mark Thompson1f26a232016-10-21 17:57:12338
339 ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
340 insurf, &outsurf, sync);
341 if (ret == MFX_WRN_DEVICE_BUSY)
Ivan Uskov9f543e02015-07-24 11:45:38342 av_usleep(500);
Anton Khirnov4e08c822015-02-10 09:40:59343
Mark Thompson1f26a232016-10-21 17:57:12344 } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
Anton Khirnov4e08c822015-02-10 09:40:59345
Mark Thompson1f26a232016-10-21 17:57:12346 if (ret != MFX_ERR_NONE &&
347 ret != MFX_ERR_MORE_DATA &&
348 ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
349 ret != MFX_ERR_MORE_SURFACE) {
Mark Thompson1f26a232016-10-21 17:57:12350 av_freep(&sync);
Anton Khirnov95414eb2016-06-25 19:38:10351 return ff_qsv_print_error(avctx, ret,
352 "Error during QSV decoding.");
Anton Khirnovf5c4d382015-07-14 16:16:26353 }
354
Anton Khirnovaa9d15d2015-07-09 18:08:13355 /* make sure we do not enter an infinite loop if the SDK
356 * did not consume any data and did not return anything */
Mark Thompson1f26a232016-10-21 17:57:12357 if (!*sync && !bs.DataOffset) {
Anton Khirnovaa9d15d2015-07-09 18:08:13358 bs.DataOffset = avpkt->size;
Mark Thompson0940b742016-10-30 16:58:23359 ++q->zero_consume_run;
360 if (q->zero_consume_run > 1)
361 ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data");
362 } else {
363 q->zero_consume_run = 0;
Anton Khirnovaa9d15d2015-07-09 18:08:13364 }
365
Mark Thompson1f26a232016-10-21 17:57:12366 if (*sync) {
367 QSVFrame *out_frame = find_frame(q, outsurf);
368
369 if (!out_frame) {
370 av_log(avctx, AV_LOG_ERROR,
371 "The returned surface does not correspond to any frame\n");
372 av_freep(&sync);
373 return AVERROR_BUG;
374 }
375
376 out_frame->queued = 1;
377 av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
378 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
379 } else {
380 av_freep(&sync);
Ivan Uskovc90dbc62015-07-24 10:26:14381 }
382
Mark Thompson1f26a232016-10-21 17:57:12383 if (!av_fifo_space(q->async_fifo) ||
384 (!avpkt->size && av_fifo_size(q->async_fifo))) {
Anton Khirnovf5c4d382015-07-14 16:16:26385 AVFrame *src_frame;
386
387 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
388 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
389 out_frame->queued = 0;
390
Anton Khirnovb68e3532017-01-07 20:06:16391 if (avctx->pix_fmt != AV_PIX_FMT_QSV) {
392 do {
393 ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
394 } while (ret == MFX_WRN_IN_EXECUTION);
395 }
Anton Khirnovf5c4d382015-07-14 16:16:26396
Mark Thompson1f26a232016-10-21 17:57:12397 av_freep(&sync);
398
Anton Khirnovf5c4d382015-07-14 16:16:26399 src_frame = out_frame->frame;
400
Anton Khirnov4e08c822015-02-10 09:40:59401 ret = av_frame_ref(frame, src_frame);
402 if (ret < 0)
403 return ret;
404
Anton Khirnov404e5142016-08-09 10:05:49405 outsurf = &out_frame->surface;
Anton Khirnovf5c4d382015-07-14 16:16:26406
Anton Khirnov32c83592016-03-19 20:45:24407#if FF_API_PKT_PTS
408FF_DISABLE_DEPRECATION_WARNINGS
409 frame->pkt_pts = outsurf->Data.TimeStamp;
410FF_ENABLE_DEPRECATION_WARNINGS
411#endif
412 frame->pts = outsurf->Data.TimeStamp;
Anton Khirnov4e08c822015-02-10 09:40:59413
414 frame->repeat_pict =
415 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
416 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
417 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
418 frame->top_field_first =
419 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
420 frame->interlaced_frame =
421 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
422
Anton Khirnov404e5142016-08-09 10:05:49423 /* update the surface properties */
424 if (avctx->pix_fmt == AV_PIX_FMT_QSV)
425 ((mfxFrameSurface1*)frame->data[3])->Info = outsurf->Info;
426
Anton Khirnov4e08c822015-02-10 09:40:59427 *got_frame = 1;
428 }
429
Mark Thompson1f26a232016-10-21 17:57:12430 return bs.DataOffset;
Ivan Uskov3f8e2e92015-08-06 16:10:24431}
Anton Khirnov4e08c822015-02-10 09:40:59432
Anton Khirnov9ba27c22015-03-13 07:21:38433int ff_qsv_decode_close(QSVContext *q)
Anton Khirnov4e08c822015-02-10 09:40:59434{
Mark Thompson1f26a232016-10-21 17:57:12435 QSVFrame *cur = q->work_frames;
Anton Khirnov4e08c822015-02-10 09:40:59436
Mark Thompson1f26a232016-10-21 17:57:12437 if (q->session)
438 MFXVideoDECODE_Close(q->session);
Ivan Uskovcc167f72015-08-04 10:40:06439
Mark Thompson1f26a232016-10-21 17:57:12440 while (q->async_fifo && av_fifo_size(q->async_fifo)) {
441 QSVFrame *out_frame;
442 mfxSyncPoint *sync;
443
444 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
445 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
446
447 av_freep(&sync);
448 }
449
450 while (cur) {
451 q->work_frames = cur->next;
452 av_frame_free(&cur->frame);
453 av_freep(&cur);
454 cur = q->work_frames;
455 }
Anton Khirnov4e08c822015-02-10 09:40:59456
Anton Khirnovf5c4d382015-07-14 16:16:26457 av_fifo_free(q->async_fifo);
458 q->async_fifo = NULL;
459
Mark Thompson1f26a232016-10-21 17:57:12460 av_parser_close(q->parser);
461 avcodec_free_context(&q->avctx_internal);
Ivan Uskovc90dbc62015-07-24 10:26:14462
Mark Thompson1f26a232016-10-21 17:57:12463 if (q->internal_session)
464 MFXClose(q->internal_session);
465
466 av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
Anton Khirnov4ab61cd2016-08-10 07:38:21467 av_buffer_unref(&q->frames_ctx.mids_buf);
Ivan Uskovd50ab822015-07-23 09:14:41468
Anton Khirnov4e08c822015-02-10 09:40:59469 return 0;
470}
Mark Thompson1f26a232016-10-21 17:57:12471
472int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q,
473 AVFrame *frame, int *got_frame, AVPacket *pkt)
474{
475 uint8_t *dummy_data;
476 int dummy_size;
477 int ret;
478
479 if (!q->avctx_internal) {
480 q->avctx_internal = avcodec_alloc_context3(NULL);
481 if (!q->avctx_internal)
482 return AVERROR(ENOMEM);
483
484 q->parser = av_parser_init(avctx->codec_id);
485 if (!q->parser)
486 return AVERROR(ENOMEM);
487
488 q->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
489 q->orig_pix_fmt = AV_PIX_FMT_NONE;
490 }
491
492 if (!pkt->size)
493 return qsv_decode(avctx, q, frame, got_frame, pkt);
494
495 /* we assume the packets are already split properly and want
496 * just the codec parameters here */
497 av_parser_parse2(q->parser, q->avctx_internal,
498 &dummy_data, &dummy_size,
499 pkt->data, pkt->size, pkt->pts, pkt->dts,
500 pkt->pos);
501
502 /* TODO: flush delayed frames on reinit */
503 if (q->parser->format != q->orig_pix_fmt ||
504 q->parser->coded_width != avctx->coded_width ||
505 q->parser->coded_height != avctx->coded_height) {
506 enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV,
507 AV_PIX_FMT_NONE,
508 AV_PIX_FMT_NONE };
509 enum AVPixelFormat qsv_format;
510
Anton Khirnov536bb172016-06-22 09:41:26511 qsv_format = ff_qsv_map_pixfmt(q->parser->format, &q->fourcc);
Mark Thompson1f26a232016-10-21 17:57:12512 if (qsv_format < 0) {
513 av_log(avctx, AV_LOG_ERROR,
Anton Khirnov92736c72016-06-22 09:53:00514 "Decoding pixel format '%s' is not supported\n",
515 av_get_pix_fmt_name(q->parser->format));
Mark Thompson1f26a232016-10-21 17:57:12516 ret = AVERROR(ENOSYS);
517 goto reinit_fail;
518 }
519
520 q->orig_pix_fmt = q->parser->format;
521 avctx->pix_fmt = pix_fmts[1] = qsv_format;
522 avctx->width = q->parser->width;
523 avctx->height = q->parser->height;
524 avctx->coded_width = q->parser->coded_width;
525 avctx->coded_height = q->parser->coded_height;
526 avctx->field_order = q->parser->field_order;
527 avctx->level = q->avctx_internal->level;
528 avctx->profile = q->avctx_internal->profile;
529
530 ret = ff_get_format(avctx, pix_fmts);
531 if (ret < 0)
532 goto reinit_fail;
533
534 avctx->pix_fmt = ret;
535
536 ret = qsv_decode_init(avctx, q);
537 if (ret < 0)
538 goto reinit_fail;
539 }
540
541 return qsv_decode(avctx, q, frame, got_frame, pkt);
542
543reinit_fail:
544 q->orig_pix_fmt = q->parser->format = avctx->pix_fmt = AV_PIX_FMT_NONE;
545 return ret;
546}
547
548void ff_qsv_decode_flush(AVCodecContext *avctx, QSVContext *q)
549{
550 q->orig_pix_fmt = AV_PIX_FMT_NONE;
551}