2 * Intel MediaSDK QSV codec-independent code
4 * copyright (c) 2013 Luca Barbato
5 * copyright (c) 2015 Anton Khirnov <anton@khirnov.net>
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * 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.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * 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.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <sys/types.h>
27 #include <mfx/mfxvideo.h>
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"
38 #include "qsv_internal.h"
41 int ff_qsv_map_pixfmt(enum AVPixelFormat format)
44 case AV_PIX_FMT_YUV420P:
45 case AV_PIX_FMT_YUVJ420P:
46 return AV_PIX_FMT_NV12;
48 return AVERROR(ENOSYS);
52 static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt)
54 mfxVideoParam param = { { 0 } };
55 mfxBitstream bs = { { { 0 } } };
57 enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV,
61 ret = ff_get_format(avctx, pix_fmts);
67 q->iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
68 if (avctx->hwaccel_context) {
69 AVQSVContext *qsv = avctx->hwaccel_context;
71 q->session = qsv->session;
72 q->iopattern = qsv->iopattern;
73 q->ext_buffers = qsv->ext_buffers;
74 q->nb_ext_buffers = qsv->nb_ext_buffers;
77 if (!q->internal_qs.session) {
78 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
84 q->session = q->internal_qs.session;
88 bs.Data = avpkt->data;
89 bs.DataLength = avpkt->size;
90 bs.MaxLength = bs.DataLength;
91 bs.TimeStamp = avpkt->pts;
93 return AVERROR_INVALIDDATA;
95 ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
97 av_log(avctx, AV_LOG_ERROR, "Unsupported codec_id %08x\n", avctx->codec_id);
101 param.mfx.CodecId = ret;
103 ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, ¶m);
104 if (MFX_ERR_MORE_DATA==ret) {
105 /* this code means that header not found so we return packet size to skip
109 } else if (ret < 0) {
110 av_log(avctx, AV_LOG_ERROR, "Decode header error %d\n", ret);
111 return ff_qsv_error(ret);
113 param.IOPattern = q->iopattern;
114 param.AsyncDepth = q->async_depth;
115 param.ExtParam = q->ext_buffers;
116 param.NumExtParam = q->nb_ext_buffers;
117 param.mfx.FrameInfo.BitDepthLuma = 8;
118 param.mfx.FrameInfo.BitDepthChroma = 8;
120 ret = MFXVideoDECODE_Init(q->session, ¶m);
122 if (MFX_ERR_INVALID_VIDEO_PARAM==ret) {
123 av_log(avctx, AV_LOG_ERROR,
124 "Error initializing the MFX video decoder, unsupported video\n");
126 av_log(avctx, AV_LOG_ERROR,
127 "Error initializing the MFX video decoder %d\n", ret);
129 return ff_qsv_error(ret);
132 avctx->profile = param.mfx.CodecProfile;
133 avctx->level = param.mfx.CodecLevel;
134 avctx->coded_width = param.mfx.FrameInfo.Width;
135 avctx->coded_height = param.mfx.FrameInfo.Height;
136 avctx->width = param.mfx.FrameInfo.CropW - param.mfx.FrameInfo.CropX;
137 avctx->height = param.mfx.FrameInfo.CropH - param.mfx.FrameInfo.CropY;
139 /* maximum decoder latency should be not exceed max DPB size for h.264 and
140 HEVC which is 16 for both cases.
141 So weare pre-allocating fifo big enough for 17 elements:
143 if (!q->async_fifo) {
144 q->async_fifo = av_fifo_alloc((1 + 16) *
145 (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
147 return AVERROR(ENOMEM);
150 if (!q->input_fifo) {
151 q->input_fifo = av_fifo_alloc(1024*16);
153 return AVERROR(ENOMEM);
157 q->pkt_fifo = av_fifo_alloc( sizeof(AVPacket) * (1 + 16) );
159 return AVERROR(ENOMEM);
166 static int alloc_frame(AVCodecContext *avctx, QSVFrame *frame)
170 ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
174 if (frame->frame->format == AV_PIX_FMT_QSV) {
175 frame->surface = (mfxFrameSurface1*)frame->frame->data[3];
177 frame->surface_internal.Info.BitDepthLuma = 8;
178 frame->surface_internal.Info.BitDepthChroma = 8;
179 frame->surface_internal.Info.FourCC = MFX_FOURCC_NV12;
180 frame->surface_internal.Info.Width = avctx->coded_width;
181 frame->surface_internal.Info.Height = avctx->coded_height;
182 frame->surface_internal.Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
184 frame->surface_internal.Data.PitchLow = frame->frame->linesize[0];
185 frame->surface_internal.Data.Y = frame->frame->data[0];
186 frame->surface_internal.Data.UV = frame->frame->data[1];
188 frame->surface = &frame->surface_internal;
194 static void qsv_clear_unused_frames(QSVContext *q)
196 QSVFrame *cur = q->work_frames;
198 if (cur->surface && !cur->surface->Data.Locked && !cur->queued) {
200 av_frame_unref(cur->frame);
206 static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
208 QSVFrame *frame, **last;
211 qsv_clear_unused_frames(q);
213 frame = q->work_frames;
214 last = &q->work_frames;
216 if (!frame->surface) {
217 ret = alloc_frame(avctx, frame);
220 *surf = frame->surface;
228 frame = av_mallocz(sizeof(*frame));
230 return AVERROR(ENOMEM);
231 frame->frame = av_frame_alloc();
234 return AVERROR(ENOMEM);
238 ret = alloc_frame(avctx, frame);
242 *surf = frame->surface;
247 static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
249 QSVFrame *cur = q->work_frames;
251 if (surf == cur->surface)
258 /* This function uses for 'smart' releasing of consumed data
259 from the input bitstream fifo.
260 Since the input fifo mapped to mfxBitstream which does not understand
261 a wrapping of data over fifo end, we should also to relocate a possible
262 data rest to fifo begin. If rest of data is absent then we just reset fifo's
263 pointers to initial positions.
264 NOTE the case when fifo does contain unconsumed data is rare and typical
265 amount of such data is 1..4 bytes.
267 static void qsv_fifo_relocate(AVFifoBuffer *f, int bytes_to_free)
272 av_fifo_drain(f, bytes_to_free);
274 data_size = av_fifo_size(f);
276 if (f->buffer!=f->rptr) {
277 if ( (f->end - f->rptr) < data_size) {
278 data_rest = data_size - (f->end - f->rptr);
279 data_size-=data_rest;
280 memmove(f->buffer+data_size, f->buffer, data_rest);
282 memmove(f->buffer, f->rptr, data_size);
283 data_size+= data_rest;
287 f->wptr = f->buffer + data_size;
293 static void close_decoder(QSVContext *q)
298 MFXVideoDECODE_Close(q->session);
300 cur = q->work_frames;
302 q->work_frames = cur->next;
303 av_frame_free(&cur->frame);
305 cur = q->work_frames;
309 q->reinit_pending = 0;
312 static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
313 AVFrame *frame, int *got_frame,
317 mfxFrameSurface1 *insurf;
318 mfxFrameSurface1 *outsurf;
320 mfxBitstream bs = { { { 0 } } };
324 int flush = !avpkt->size || q->reinit_pending;
326 if (!q->engine_ready) {
327 ret = qsv_decode_init(avctx, q, avpkt);
333 if (av_fifo_size(q->input_fifo)) {
334 /* we have got rest of previous packet into buffer */
335 if (av_fifo_space(q->input_fifo) < avpkt->size) {
336 ret = av_fifo_grow(q->input_fifo, avpkt->size);
340 av_fifo_generic_write(q->input_fifo, avpkt->data, avpkt->size, NULL);
341 bs.Data = q->input_fifo->rptr;
342 bs.DataLength = av_fifo_size(q->input_fifo);
345 bs.Data = avpkt->data;
346 bs.DataLength = avpkt->size;
348 bs.MaxLength = bs.DataLength;
349 bs.TimeStamp = avpkt->pts;
353 ret = get_surface(avctx, q, &insurf);
357 ret = MFXVideoDECODE_DecodeFrameAsync(q->session, flush ? NULL : &bs,
358 insurf, &outsurf, &sync);
359 if (ret != MFX_WRN_DEVICE_BUSY)
364 if (MFX_WRN_VIDEO_PARAM_CHANGED==ret) {
365 /* TODO: handle here minor sequence header changing */
366 } else if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM==ret) {
367 av_fifo_reset(q->input_fifo);
368 flush = q->reinit_pending = 1;
373 QSVFrame *out_frame = find_frame(q, outsurf);
376 av_log(avctx, AV_LOG_ERROR,
377 "The returned surface does not correspond to any frame\n");
381 out_frame->queued = 1;
382 av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
383 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
387 if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
391 /* make sure we do not enter an infinite loop if the SDK
392 * did not consume any data and did not return anything */
393 if (!sync && !bs.DataOffset && !flush) {
394 av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n");
395 bs.DataOffset = avpkt->size;
399 qsv_fifo_relocate(q->input_fifo, bs.DataOffset);
400 } else if (bs.DataOffset!=avpkt->size) {
401 /* some data of packet was not consumed. store it to local buffer */
402 av_fifo_generic_write(q->input_fifo, avpkt->data+bs.DataOffset,
403 avpkt->size - bs.DataOffset, NULL);
406 if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
407 av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
408 return ff_qsv_error(ret);
410 n_out_frames = av_fifo_size(q->async_fifo) / (sizeof(out_frame)+sizeof(sync));
412 if (n_out_frames > q->async_depth || (flush && n_out_frames) ) {
415 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
416 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
417 out_frame->queued = 0;
419 MFXVideoCORE_SyncOperation(q->session, sync, 60000);
421 src_frame = out_frame->frame;
423 ret = av_frame_ref(frame, src_frame);
427 outsurf = out_frame->surface;
429 frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
432 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
433 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
434 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
435 frame->top_field_first =
436 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
437 frame->interlaced_frame =
438 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
446 This function inserts a packet at fifo front.
448 static void qsv_packet_push_front(QSVContext *q, AVPacket *avpkt)
450 int fifo_size = av_fifo_size(q->pkt_fifo);
452 /* easy case fifo is empty */
453 av_fifo_generic_write(q->pkt_fifo, avpkt, sizeof(*avpkt), NULL);
455 /* realloc necessary */
457 AVFifoBuffer *fifo = av_fifo_alloc(fifo_size+av_fifo_space(q->pkt_fifo));
459 av_fifo_generic_write(fifo, avpkt, sizeof(*avpkt), NULL);
461 while (av_fifo_size(q->pkt_fifo)) {
462 av_fifo_generic_read(q->pkt_fifo, &pkt, sizeof(pkt), NULL);
463 av_fifo_generic_write(fifo, &pkt, sizeof(pkt), NULL);
465 av_fifo_free(q->pkt_fifo);
469 int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
470 AVFrame *frame, int *got_frame,
473 AVPacket pkt_ref = { 0 };
476 if (q->pkt_fifo && av_fifo_size(q->pkt_fifo) >= sizeof(AVPacket)) {
477 /* we already have got some buffered packets. so add new to tail */
478 ret = av_packet_ref(&pkt_ref, avpkt);
481 av_fifo_generic_write(q->pkt_fifo, &pkt_ref, sizeof(pkt_ref), NULL);
483 if (q->reinit_pending) {
484 ret = do_qsv_decode(avctx, q, frame, got_frame, avpkt);
487 /* Flushing complete, no more frames */
489 //return ff_qsv_decode(avctx, q, frame, got_frame, avpkt);
492 if (!q->reinit_pending) {
493 if (q->pkt_fifo && av_fifo_size(q->pkt_fifo) >= sizeof(AVPacket)) {
494 /* process buffered packets */
495 while (!*got_frame && av_fifo_size(q->pkt_fifo) >= sizeof(AVPacket)) {
496 av_fifo_generic_read(q->pkt_fifo, &pkt_ref, sizeof(pkt_ref), NULL);
497 ret = do_qsv_decode(avctx, q, frame, got_frame, &pkt_ref);
498 if (q->reinit_pending) {
500 A rare case: new reinit pending when buffering existing.
501 We should to return the pkt_ref back to same place of fifo
503 qsv_packet_push_front(q, &pkt_ref);
505 av_packet_unref(&pkt_ref);
509 /* general decoding */
510 ret = do_qsv_decode(avctx, q, frame, got_frame, avpkt);
511 if (q->reinit_pending) {
512 ret = av_packet_ref(&pkt_ref, avpkt);
515 av_fifo_generic_write(q->pkt_fifo, &pkt_ref, sizeof(pkt_ref), NULL);
523 This function resets decoder and corresponded buffers before seek operation
525 void ff_qsv_decode_reset(AVCodecContext *avctx, QSVContext *q)
530 mfxVideoParam param = { { 0 } };
532 if (q->reinit_pending) {
534 } else if (q->engine_ready) {
535 ret = MFXVideoDECODE_GetVideoParam(q->session, ¶m);
537 av_log(avctx, AV_LOG_ERROR, "MFX decode get param error %d\n", ret);
540 ret = MFXVideoDECODE_Reset(q->session, ¶m);
542 av_log(avctx, AV_LOG_ERROR, "MFX decode reset error %d\n", ret);
546 cur = q->work_frames;
548 q->work_frames = cur->next;
549 av_frame_free(&cur->frame);
551 cur = q->work_frames;
555 /* Reset output surfaces */
556 av_fifo_reset(q->async_fifo);
558 /* Reset input packets fifo */
559 while (av_fifo_size(q->pkt_fifo)) {
560 av_fifo_generic_read(q->pkt_fifo, &pkt, sizeof(pkt), NULL);
561 av_packet_unref(&pkt);
564 /* Reset input bitstream fifo */
565 av_fifo_reset(q->input_fifo);
568 int ff_qsv_decode_close(QSVContext *q)
574 ff_qsv_close_internal_session(&q->internal_qs);
576 av_fifo_free(q->async_fifo);
577 q->async_fifo = NULL;
579 av_fifo_free(q->input_fifo);
580 q->input_fifo = NULL;
582 av_fifo_free(q->pkt_fifo);