]> git.sesse.net Git - ffmpeg/blob - libavcodec/qsvdec.c
Merge commit '317cfaa5e09755ed0b34af512ec687963a67bdbf'
[ffmpeg] / libavcodec / qsvdec.c
1 /*
2  * Intel MediaSDK QSV codec-independent code
3  *
4  * copyright (c) 2013 Luca Barbato
5  * copyright (c) 2015 Anton Khirnov <anton@khirnov.net>
6  *
7  * This file is part of FFmpeg.
8  *
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.
13  *
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.
18  *
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
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"
37 #include "qsv.h"
38 #include "qsv_internal.h"
39 #include "qsvdec.h"
40
41 int 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
52 int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt)
53 {
54     mfxVideoParam param = { { 0 } };
55     mfxBitstream bs   = { { { 0 } } };
56     int ret;
57
58     q->iopattern  = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
59     if (!q->session) {
60         if (avctx->hwaccel_context) {
61             AVQSVContext *qsv = avctx->hwaccel_context;
62
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;
67         }
68         if (!q->session) {
69             ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
70                                                q->load_plugins);
71             if (ret < 0)
72                 return ret;
73
74             q->session = q->internal_qs.session;
75         }
76     }
77
78     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
86     ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
87     if (ret < 0) {
88         av_log(avctx, AV_LOG_ERROR, "Unsupported codec_id %08x\n", avctx->codec_id);
89         return ret;
90     }
91
92     param.mfx.CodecId = ret;
93
94     ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, &param);
95     if (MFX_ERR_MORE_DATA==ret) {
96         /* this code means that header not found so we return packet size to skip
97            a current packet
98          */
99         return avpkt->size;
100     } else if (ret < 0) {
101         av_log(avctx, AV_LOG_ERROR, "Decode header error %d\n", ret);
102         return ff_qsv_error(ret);
103     }
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;
110
111     ret = MFXVideoDECODE_Init(q->session, &param);
112     if (ret < 0) {
113         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         }
120         return ff_qsv_error(ret);
121     }
122
123     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
131     /* 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      */
135     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     }
141
142     q->input_fifo = av_fifo_alloc(1024*16);
143     if (!q->input_fifo)
144         return AVERROR(ENOMEM);
145
146     q->engine_ready = 1;
147
148     return 0;
149 }
150
151 static 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
179 static void qsv_clear_unused_frames(QSVContext *q)
180 {
181     QSVFrame *cur = q->work_frames;
182     while (cur) {
183         if (cur->surface && !cur->surface->Data.Locked && !cur->queued) {
184             cur->surface = NULL;
185             av_frame_unref(cur->frame);
186         }
187         cur = cur->next;
188     }
189 }
190
191 static 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
232 static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
233 {
234     QSVFrame *cur = q->work_frames;
235     while (cur) {
236         if (surf == cur->surface)
237             return cur;
238         cur = cur->next;
239     }
240     return NULL;
241 }
242
243 /*  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 */
252 static 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
277 int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
278                   AVFrame *frame, int *got_frame,
279                   AVPacket *avpkt)
280 {
281     QSVFrame *out_frame;
282     mfxFrameSurface1 *insurf;
283     mfxFrameSurface1 *outsurf;
284     mfxSyncPoint sync;
285     mfxBitstream bs = { { { 0 } } };
286     int ret;
287     int n_out_frames;
288     int buffered = 0;
289
290     if (!q->engine_ready) {
291         ret = ff_qsv_decode_init(avctx, q, avpkt);
292         if (ret)
293             return ret;
294     }
295
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         }
312         bs.MaxLength  = bs.DataLength;
313         bs.TimeStamp  = avpkt->pts;
314     }
315
316     while (1) {
317         ret = get_surface(avctx, q, &insurf);
318         if (ret < 0)
319             return ret;
320         do {
321             ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
322                                                   insurf, &outsurf, &sync);
323             if (ret != MFX_WRN_DEVICE_BUSY)
324                 break;
325             av_usleep(500);
326         } while (1);
327
328         if (MFX_WRN_VIDEO_PARAM_CHANGED==ret) {
329             /* TODO: handle here sequence header changing */
330         }
331
332         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;
349     }
350
351     /* 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
358     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) ) {
373         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
383         ret = av_frame_ref(frame, src_frame);
384         if (ret < 0)
385             return ret;
386
387         outsurf = out_frame->surface;
388
389         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
403     return avpkt->size;
404 }
405
406 int ff_qsv_decode_close(QSVContext *q)
407 {
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
417     av_fifo_free(q->async_fifo);
418     q->async_fifo = NULL;
419
420     av_fifo_free(q->input_fifo);
421     q->input_fifo = NULL;
422
423     MFXVideoDECODE_Close(q->session);
424     q->session = NULL;
425
426     ff_qsv_close_internal_session(&q->internal_qs);
427
428     q->engine_ready = 0;
429
430     return 0;
431 }