blob: e3c076da3019a4ae2763b00c31578b0ebc3a7a1f [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"
30#include "libavutil/mem.h"
31#include "libavutil/log.h"
32#include "libavutil/pixfmt.h"
33#include "libavutil/time.h"
34
35#include "avcodec.h"
36#include "internal.h"
Ivan Uskov6e127992015-07-14 11:07:0437#include "qsv.h"
Anton Khirnovd0a63d82015-03-13 07:13:0038#include "qsv_internal.h"
Anton Khirnovb04d0092015-03-13 06:55:5339#include "qsvdec.h"
Anton Khirnov4e08c822015-02-10 09:40:5940
Anton Khirnov4e08c822015-02-10 09:40:5941int ff_qsv_map_pixfmt(enum AVPixelFormat format)
42{
43 switch (format) {
44 case AV_PIX_FMT_YUV420P:
45 case AV_PIX_FMT_YUVJ420P:
46 return AV_PIX_FMT_NV12;
47 default:
48 return AVERROR(ENOSYS);
49 }
50}
51
Ivan Uskov1acb19d2015-07-20 15:07:3452int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt)
Anton Khirnov4e08c822015-02-10 09:40:5953{
54 mfxVideoParam param = { { 0 } };
Ivan Uskov1acb19d2015-07-20 15:07:3455 mfxBitstream bs = { { { 0 } } };
Anton Khirnov4e08c822015-02-10 09:40:5956 int ret;
57
Ivan Uskov6e127992015-07-14 11:07:0458 q->iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
Ivan Uskov6e127992015-07-14 11:07:0459 if (!q->session) {
Ivan Uskov1acb19d2015-07-20 15:07:3460 if (avctx->hwaccel_context) {
61 AVQSVContext *qsv = avctx->hwaccel_context;
Ivan Uskov6e127992015-07-14 11:07:0462
Ivan Uskov1acb19d2015-07-20 15:07:3463 q->session = qsv->session;
64 q->iopattern = qsv->iopattern;
65 q->ext_buffers = qsv->ext_buffers;
66 q->nb_ext_buffers = qsv->nb_ext_buffers;
67 }
68 if (!q->session) {
Michael Niedermayer508b79e2015-07-25 23:20:4669 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
70 q->load_plugins);
Ivan Uskov1acb19d2015-07-20 15:07:3471 if (ret < 0)
72 return ret;
73
74 q->session = q->internal_qs.session;
75 }
Ivan Uskov6e127992015-07-14 11:07:0476 }
Anton Khirnov4e08c822015-02-10 09:40:5977
Ivan Uskov1acb19d2015-07-20 15:07:3478 if (avpkt->size) {
79 bs.Data = avpkt->data;
80 bs.DataLength = avpkt->size;
81 bs.MaxLength = bs.DataLength;
82 bs.TimeStamp = avpkt->pts;
83 } else
84 return AVERROR_INVALIDDATA;
85
Anton Khirnovd0a63d82015-03-13 07:13:0086 ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
Ivan Uskov1acb19d2015-07-20 15:07:3487 if (ret < 0) {
88 av_log(avctx, AV_LOG_ERROR, "Unsupported codec_id %08x\n", avctx->codec_id);
Anton Khirnov4e08c822015-02-10 09:40:5989 return ret;
Ivan Uskov1acb19d2015-07-20 15:07:3490 }
Anton Khirnov4e08c822015-02-10 09:40:5991
Ivan Uskov1acb19d2015-07-20 15:07:3492 param.mfx.CodecId = ret;
Anton Khirnov4e08c822015-02-10 09:40:5993
Ivan Uskov1acb19d2015-07-20 15:07:3494 ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, &param);
95 if (MFX_ERR_MORE_DATA==ret) {
Ivan Uskovd50ab822015-07-23 09:14:4196 /* this code means that header not found so we return packet size to skip
97 a current packet
98 */
99 return avpkt->size;
Ivan Uskov1acb19d2015-07-20 15:07:34100 } else if (ret < 0) {
101 av_log(avctx, AV_LOG_ERROR, "Decode header error %d\n", ret);
102 return ff_qsv_error(ret);
103 }
Anton Khirnov4e08c822015-02-10 09:40:59104 param.IOPattern = q->iopattern;
105 param.AsyncDepth = q->async_depth;
106 param.ExtParam = q->ext_buffers;
107 param.NumExtParam = q->nb_ext_buffers;
Ivan Uskov1acb19d2015-07-20 15:07:34108 param.mfx.FrameInfo.BitDepthLuma = 8;
109 param.mfx.FrameInfo.BitDepthChroma = 8;
Anton Khirnov4e08c822015-02-10 09:40:59110
111 ret = MFXVideoDECODE_Init(q->session, &param);
112 if (ret < 0) {
Ivan Uskov44857e72015-08-06 13:30:42113 if (MFX_ERR_INVALID_VIDEO_PARAM==ret) {
114 av_log(avctx, AV_LOG_ERROR,
115 "Error initializing the MFX video decoder, unsupported video\n");
116 } else {
117 av_log(avctx, AV_LOG_ERROR,
118 "Error initializing the MFX video decoder %d\n", ret);
119 }
Anton Khirnov4e08c822015-02-10 09:40:59120 return ff_qsv_error(ret);
121 }
122
Ivan Uskov1acb19d2015-07-20 15:07:34123 avctx->pix_fmt = AV_PIX_FMT_NV12;
124 avctx->profile = param.mfx.CodecProfile;
125 avctx->level = param.mfx.CodecLevel;
126 avctx->coded_width = param.mfx.FrameInfo.Width;
127 avctx->coded_height = param.mfx.FrameInfo.Height;
128 avctx->width = param.mfx.FrameInfo.CropW - param.mfx.FrameInfo.CropX;
129 avctx->height = param.mfx.FrameInfo.CropH - param.mfx.FrameInfo.CropY;
130
Ivan Uskovc90dbc62015-07-24 10:26:14131 /* maximum decoder latency should be not exceed max DPB size for h.264 and
132 HEVC which is 16 for both cases.
133 So weare pre-allocating fifo big enough for 17 elements:
134 */
Michael Niedermayerc3413a72015-07-25 21:28:39135 if (!q->async_fifo) {
136 q->async_fifo = av_fifo_alloc((1 + 16) *
137 (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
138 if (!q->async_fifo)
139 return AVERROR(ENOMEM);
140 }
Ivan Uskov1acb19d2015-07-20 15:07:34141
Ivan Uskovc90dbc62015-07-24 10:26:14142 q->input_fifo = av_fifo_alloc(1024*16);
143 if (!q->input_fifo)
144 return AVERROR(ENOMEM);
145
Ivan Uskovd50ab822015-07-23 09:14:41146 q->engine_ready = 1;
Ivan Uskov1acb19d2015-07-20 15:07:34147
Anton Khirnov4e08c822015-02-10 09:40:59148 return 0;
149}
150
151static int alloc_frame(AVCodecContext *avctx, QSVFrame *frame)
152{
153 int ret;
154
155 ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
156 if (ret < 0)
157 return ret;
158
159 if (frame->frame->format == AV_PIX_FMT_QSV) {
160 frame->surface = (mfxFrameSurface1*)frame->frame->data[3];
161 } else {
162 frame->surface_internal.Info.BitDepthLuma = 8;
163 frame->surface_internal.Info.BitDepthChroma = 8;
164 frame->surface_internal.Info.FourCC = MFX_FOURCC_NV12;
165 frame->surface_internal.Info.Width = avctx->coded_width;
166 frame->surface_internal.Info.Height = avctx->coded_height;
167 frame->surface_internal.Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
168
169 frame->surface_internal.Data.PitchLow = frame->frame->linesize[0];
170 frame->surface_internal.Data.Y = frame->frame->data[0];
171 frame->surface_internal.Data.UV = frame->frame->data[1];
172
173 frame->surface = &frame->surface_internal;
174 }
175
176 return 0;
177}
178
179static void qsv_clear_unused_frames(QSVContext *q)
180{
181 QSVFrame *cur = q->work_frames;
182 while (cur) {
Anton Khirnovf5c4d382015-07-14 16:16:26183 if (cur->surface && !cur->surface->Data.Locked && !cur->queued) {
Anton Khirnov4e08c822015-02-10 09:40:59184 cur->surface = NULL;
185 av_frame_unref(cur->frame);
186 }
187 cur = cur->next;
188 }
189}
190
191static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
192{
193 QSVFrame *frame, **last;
194 int ret;
195
196 qsv_clear_unused_frames(q);
197
198 frame = q->work_frames;
199 last = &q->work_frames;
200 while (frame) {
201 if (!frame->surface) {
202 ret = alloc_frame(avctx, frame);
203 if (ret < 0)
204 return ret;
205 *surf = frame->surface;
206 return 0;
207 }
208
209 last = &frame->next;
210 frame = frame->next;
211 }
212
213 frame = av_mallocz(sizeof(*frame));
214 if (!frame)
215 return AVERROR(ENOMEM);
216 frame->frame = av_frame_alloc();
217 if (!frame->frame) {
218 av_freep(&frame);
219 return AVERROR(ENOMEM);
220 }
221 *last = frame;
222
223 ret = alloc_frame(avctx, frame);
224 if (ret < 0)
225 return ret;
226
227 *surf = frame->surface;
228
229 return 0;
230}
231
Anton Khirnovf5c4d382015-07-14 16:16:26232static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
Anton Khirnov4e08c822015-02-10 09:40:59233{
234 QSVFrame *cur = q->work_frames;
235 while (cur) {
236 if (surf == cur->surface)
Anton Khirnovf5c4d382015-07-14 16:16:26237 return cur;
Anton Khirnov4e08c822015-02-10 09:40:59238 cur = cur->next;
239 }
240 return NULL;
241}
242
Ivan Uskovc90dbc62015-07-24 10:26:14243/* This function uses for 'smart' releasing of consumed data
244 from the input bitstream fifo.
245 Since the input fifo mapped to mfxBitstream which does not understand
246 a wrapping of data over fifo end, we should also to relocate a possible
247 data rest to fifo begin. If rest of data is absent then we just reset fifo's
248 pointers to initial positions.
249 NOTE the case when fifo does contain unconsumed data is rare and typical
250 amount of such data is 1..4 bytes.
251*/
252static void qsv_fifo_relocate(AVFifoBuffer *f, int bytes_to_free)
253{
254 int data_size;
255 int data_rest = 0;
256
257 av_fifo_drain(f, bytes_to_free);
258
259 data_size = av_fifo_size(f);
260 if (data_size > 0) {
261 if (f->buffer!=f->rptr) {
262 if ( (f->end - f->rptr) < data_size) {
263 data_rest = data_size - (f->end - f->rptr);
264 data_size-=data_rest;
265 memmove(f->buffer+data_size, f->buffer, data_rest);
266 }
267 memmove(f->buffer, f->rptr, data_size);
268 data_size+= data_rest;
269 }
270 }
271 f->rptr = f->buffer;
272 f->wptr = f->buffer + data_size;
273 f->wndx = data_size;
274 f->rndx = 0;
275}
276
Anton Khirnov4e08c822015-02-10 09:40:59277int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
278 AVFrame *frame, int *got_frame,
279 AVPacket *avpkt)
280{
Anton Khirnovf5c4d382015-07-14 16:16:26281 QSVFrame *out_frame;
Anton Khirnov4e08c822015-02-10 09:40:59282 mfxFrameSurface1 *insurf;
283 mfxFrameSurface1 *outsurf;
284 mfxSyncPoint sync;
285 mfxBitstream bs = { { { 0 } } };
286 int ret;
Ivan Uskovc90dbc62015-07-24 10:26:14287 int n_out_frames;
288 int buffered = 0;
Anton Khirnov4e08c822015-02-10 09:40:59289
Ivan Uskovd50ab822015-07-23 09:14:41290 if (!q->engine_ready) {
291 ret = ff_qsv_decode_init(avctx, q, avpkt);
292 if (ret)
293 return ret;
294 }
Ivan Uskovc90dbc62015-07-24 10:26:14295
296 if (avpkt->size ) {
297 if (av_fifo_size(q->input_fifo)) {
298 /* we have got rest of previous packet into buffer */
299 if (av_fifo_space(q->input_fifo) < avpkt->size) {
300 ret = av_fifo_grow(q->input_fifo, avpkt->size);
301 if (ret < 0)
302 return ret;
303 }
304 av_fifo_generic_write(q->input_fifo, avpkt->data, avpkt->size, NULL);
305 bs.Data = q->input_fifo->rptr;
306 bs.DataLength = av_fifo_size(q->input_fifo);
307 buffered = 1;
308 } else {
309 bs.Data = avpkt->data;
310 bs.DataLength = avpkt->size;
311 }
Anton Khirnov4e08c822015-02-10 09:40:59312 bs.MaxLength = bs.DataLength;
313 bs.TimeStamp = avpkt->pts;
314 }
315
Ivan Uskovc90dbc62015-07-24 10:26:14316 while (1) {
Anton Khirnov4e08c822015-02-10 09:40:59317 ret = get_surface(avctx, q, &insurf);
318 if (ret < 0)
319 return ret;
Ivan Uskovc90dbc62015-07-24 10:26:14320 do {
321 ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
322 insurf, &outsurf, &sync);
323 if (ret != MFX_WRN_DEVICE_BUSY)
324 break;
Ivan Uskov9f543e02015-07-24 11:45:38325 av_usleep(500);
Ivan Uskovc90dbc62015-07-24 10:26:14326 } while (1);
Anton Khirnov4e08c822015-02-10 09:40:59327
Ivan Uskovc90dbc62015-07-24 10:26:14328 if (MFX_WRN_VIDEO_PARAM_CHANGED==ret) {
329 /* TODO: handle here sequence header changing */
Anton Khirnov4e08c822015-02-10 09:40:59330 }
331
Ivan Uskovc90dbc62015-07-24 10:26:14332 if (sync) {
333 QSVFrame *out_frame = find_frame(q, outsurf);
334
335 if (!out_frame) {
336 av_log(avctx, AV_LOG_ERROR,
337 "The returned surface does not correspond to any frame\n");
338 return AVERROR_BUG;
339 }
340
341 out_frame->queued = 1;
342 av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
343 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
344
345 continue;
346 }
347 if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
348 break;
Anton Khirnovf5c4d382015-07-14 16:16:26349 }
350
Anton Khirnovaa9d15d2015-07-09 18:08:13351 /* make sure we do not enter an infinite loop if the SDK
352 * did not consume any data and did not return anything */
353 if (!sync && !bs.DataOffset) {
354 av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n");
355 bs.DataOffset = avpkt->size;
356 }
357
Ivan Uskovc90dbc62015-07-24 10:26:14358 if (buffered) {
359 qsv_fifo_relocate(q->input_fifo, bs.DataOffset);
360 } else if (bs.DataOffset!=avpkt->size) {
361 /* some data of packet was not consumed. store it to local buffer */
362 av_fifo_generic_write(q->input_fifo, avpkt->data+bs.DataOffset,
363 avpkt->size - bs.DataOffset, NULL);
364 }
365
366 if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
367 av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
368 return ff_qsv_error(ret);
369 }
370 n_out_frames = av_fifo_size(q->async_fifo) / (sizeof(out_frame)+sizeof(sync));
371
372 if (n_out_frames > q->async_depth || (!avpkt->size && n_out_frames) ) {
Anton Khirnovf5c4d382015-07-14 16:16:26373 AVFrame *src_frame;
374
375 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
376 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
377 out_frame->queued = 0;
378
379 MFXVideoCORE_SyncOperation(q->session, sync, 60000);
380
381 src_frame = out_frame->frame;
382
Anton Khirnov4e08c822015-02-10 09:40:59383 ret = av_frame_ref(frame, src_frame);
384 if (ret < 0)
385 return ret;
386
Anton Khirnovf5c4d382015-07-14 16:16:26387 outsurf = out_frame->surface;
388
Anton Khirnov4e08c822015-02-10 09:40:59389 frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
390
391 frame->repeat_pict =
392 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
393 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
394 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
395 frame->top_field_first =
396 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
397 frame->interlaced_frame =
398 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
399
400 *got_frame = 1;
401 }
402
Ivan Uskovc90dbc62015-07-24 10:26:14403 return avpkt->size;
Anton Khirnov4e08c822015-02-10 09:40:59404}
405
Anton Khirnov9ba27c22015-03-13 07:21:38406int ff_qsv_decode_close(QSVContext *q)
Anton Khirnov4e08c822015-02-10 09:40:59407{
408 QSVFrame *cur = q->work_frames;
409
410 while (cur) {
411 q->work_frames = cur->next;
412 av_frame_free(&cur->frame);
413 av_freep(&cur);
414 cur = q->work_frames;
415 }
416
Anton Khirnovf5c4d382015-07-14 16:16:26417 av_fifo_free(q->async_fifo);
418 q->async_fifo = NULL;
419
Ivan Uskovc90dbc62015-07-24 10:26:14420 av_fifo_free(q->input_fifo);
421 q->input_fifo = NULL;
422
Ivan Uskov264ba3d2015-07-20 13:48:29423 MFXVideoDECODE_Close(q->session);
424 q->session = NULL;
425
Ivan Uskovce91bab2015-07-13 14:17:54426 ff_qsv_close_internal_session(&q->internal_qs);
Anton Khirnov4e08c822015-02-10 09:40:59427
Ivan Uskovd50ab822015-07-23 09:14:41428 q->engine_ready = 0;
429
Anton Khirnov4e08c822015-02-10 09:40:59430 return 0;
431}