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 int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt)
54 mfxVideoParam param = { { 0 } };
55 mfxBitstream bs = { { { 0 } } };
58 q->iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
60 if (avctx->hwaccel_context) {
61 AVQSVContext *qsv = avctx->hwaccel_context;
63 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;
69 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
74 q->session = q->internal_qs.session;
79 bs.Data = avpkt->data;
80 bs.DataLength = avpkt->size;
81 bs.MaxLength = bs.DataLength;
82 bs.TimeStamp = avpkt->pts;
84 return AVERROR_INVALIDDATA;
86 ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
88 av_log(avctx, AV_LOG_ERROR, "Unsupported codec_id %08x\n", avctx->codec_id);
92 param.mfx.CodecId = ret;
94 ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, ¶m);
95 if (MFX_ERR_MORE_DATA==ret) {
96 /* this code means that header not found so we return packet size to skip
100 } else if (ret < 0) {
101 av_log(avctx, AV_LOG_ERROR, "Decode header error %d\n", ret);
102 return ff_qsv_error(ret);
104 param.IOPattern = q->iopattern;
105 param.AsyncDepth = q->async_depth;
106 param.ExtParam = q->ext_buffers;
107 param.NumExtParam = q->nb_ext_buffers;
108 param.mfx.FrameInfo.BitDepthLuma = 8;
109 param.mfx.FrameInfo.BitDepthChroma = 8;
111 ret = MFXVideoDECODE_Init(q->session, ¶m);
113 av_log(avctx, AV_LOG_ERROR, "Error initializing the MFX video decoder\n");
114 return ff_qsv_error(ret);
117 avctx->pix_fmt = AV_PIX_FMT_NV12;
118 avctx->profile = param.mfx.CodecProfile;
119 avctx->level = param.mfx.CodecLevel;
120 avctx->coded_width = param.mfx.FrameInfo.Width;
121 avctx->coded_height = param.mfx.FrameInfo.Height;
122 avctx->width = param.mfx.FrameInfo.CropW - param.mfx.FrameInfo.CropX;
123 avctx->height = param.mfx.FrameInfo.CropH - param.mfx.FrameInfo.CropY;
125 /* maximum decoder latency should be not exceed max DPB size for h.264 and
126 HEVC which is 16 for both cases.
127 So weare pre-allocating fifo big enough for 17 elements:
129 if (!q->async_fifo) {
130 q->async_fifo = av_fifo_alloc((1 + 16) *
131 (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
133 return AVERROR(ENOMEM);
136 q->input_fifo = av_fifo_alloc(1024*16);
138 return AVERROR(ENOMEM);
145 static int alloc_frame(AVCodecContext *avctx, QSVFrame *frame)
149 ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
153 if (frame->frame->format == AV_PIX_FMT_QSV) {
154 frame->surface = (mfxFrameSurface1*)frame->frame->data[3];
156 frame->surface_internal.Info.BitDepthLuma = 8;
157 frame->surface_internal.Info.BitDepthChroma = 8;
158 frame->surface_internal.Info.FourCC = MFX_FOURCC_NV12;
159 frame->surface_internal.Info.Width = avctx->coded_width;
160 frame->surface_internal.Info.Height = avctx->coded_height;
161 frame->surface_internal.Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
163 frame->surface_internal.Data.PitchLow = frame->frame->linesize[0];
164 frame->surface_internal.Data.Y = frame->frame->data[0];
165 frame->surface_internal.Data.UV = frame->frame->data[1];
167 frame->surface = &frame->surface_internal;
173 static void qsv_clear_unused_frames(QSVContext *q)
175 QSVFrame *cur = q->work_frames;
177 if (cur->surface && !cur->surface->Data.Locked && !cur->queued) {
179 av_frame_unref(cur->frame);
185 static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
187 QSVFrame *frame, **last;
190 qsv_clear_unused_frames(q);
192 frame = q->work_frames;
193 last = &q->work_frames;
195 if (!frame->surface) {
196 ret = alloc_frame(avctx, frame);
199 *surf = frame->surface;
207 frame = av_mallocz(sizeof(*frame));
209 return AVERROR(ENOMEM);
210 frame->frame = av_frame_alloc();
213 return AVERROR(ENOMEM);
217 ret = alloc_frame(avctx, frame);
221 *surf = frame->surface;
226 static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
228 QSVFrame *cur = q->work_frames;
230 if (surf == cur->surface)
237 /* This function uses for 'smart' releasing of consumed data
238 from the input bitstream fifo.
239 Since the input fifo mapped to mfxBitstream which does not understand
240 a wrapping of data over fifo end, we should also to relocate a possible
241 data rest to fifo begin. If rest of data is absent then we just reset fifo's
242 pointers to initial positions.
243 NOTE the case when fifo does contain unconsumed data is rare and typical
244 amount of such data is 1..4 bytes.
246 static void qsv_fifo_relocate(AVFifoBuffer *f, int bytes_to_free)
251 av_fifo_drain(f, bytes_to_free);
253 data_size = av_fifo_size(f);
255 if (f->buffer!=f->rptr) {
256 if ( (f->end - f->rptr) < data_size) {
257 data_rest = data_size - (f->end - f->rptr);
258 data_size-=data_rest;
259 memmove(f->buffer+data_size, f->buffer, data_rest);
261 memmove(f->buffer, f->rptr, data_size);
262 data_size+= data_rest;
266 f->wptr = f->buffer + data_size;
271 int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
272 AVFrame *frame, int *got_frame,
276 mfxFrameSurface1 *insurf;
277 mfxFrameSurface1 *outsurf;
279 mfxBitstream bs = { { { 0 } } };
284 if (!q->engine_ready) {
285 ret = ff_qsv_decode_init(avctx, q, avpkt);
291 if (av_fifo_size(q->input_fifo)) {
292 /* we have got rest of previous packet into buffer */
293 if (av_fifo_space(q->input_fifo) < avpkt->size) {
294 ret = av_fifo_grow(q->input_fifo, avpkt->size);
298 av_fifo_generic_write(q->input_fifo, avpkt->data, avpkt->size, NULL);
299 bs.Data = q->input_fifo->rptr;
300 bs.DataLength = av_fifo_size(q->input_fifo);
303 bs.Data = avpkt->data;
304 bs.DataLength = avpkt->size;
306 bs.MaxLength = bs.DataLength;
307 bs.TimeStamp = avpkt->pts;
311 ret = get_surface(avctx, q, &insurf);
315 ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
316 insurf, &outsurf, &sync);
317 if (ret != MFX_WRN_DEVICE_BUSY)
322 if (MFX_WRN_VIDEO_PARAM_CHANGED==ret) {
323 /* TODO: handle here sequence header changing */
327 QSVFrame *out_frame = find_frame(q, outsurf);
330 av_log(avctx, AV_LOG_ERROR,
331 "The returned surface does not correspond to any frame\n");
335 out_frame->queued = 1;
336 av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
337 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
341 if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
345 /* make sure we do not enter an infinite loop if the SDK
346 * did not consume any data and did not return anything */
347 if (!sync && !bs.DataOffset) {
348 av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n");
349 bs.DataOffset = avpkt->size;
353 qsv_fifo_relocate(q->input_fifo, bs.DataOffset);
354 } else if (bs.DataOffset!=avpkt->size) {
355 /* some data of packet was not consumed. store it to local buffer */
356 av_fifo_generic_write(q->input_fifo, avpkt->data+bs.DataOffset,
357 avpkt->size - bs.DataOffset, NULL);
360 if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
361 av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
362 return ff_qsv_error(ret);
364 n_out_frames = av_fifo_size(q->async_fifo) / (sizeof(out_frame)+sizeof(sync));
366 if (n_out_frames > q->async_depth || (!avpkt->size && n_out_frames) ) {
369 av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
370 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
371 out_frame->queued = 0;
373 MFXVideoCORE_SyncOperation(q->session, sync, 60000);
375 src_frame = out_frame->frame;
377 ret = av_frame_ref(frame, src_frame);
381 outsurf = out_frame->surface;
383 frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
386 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
387 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
388 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
389 frame->top_field_first =
390 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
391 frame->interlaced_frame =
392 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
400 int ff_qsv_decode_close(QSVContext *q)
402 QSVFrame *cur = q->work_frames;
405 q->work_frames = cur->next;
406 av_frame_free(&cur->frame);
408 cur = q->work_frames;
411 av_fifo_free(q->async_fifo);
412 q->async_fifo = NULL;
414 av_fifo_free(q->input_fifo);
415 q->input_fifo = NULL;
417 MFXVideoDECODE_Close(q->session);
420 ff_qsv_close_internal_session(&q->internal_qs);