]> git.sesse.net Git - ffmpeg/blob - libavcodec/qsvdec.c
Merge commit '5d8bea3bb2357bb304f8f771a4107039037c5549'
[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         av_log(avctx, AV_LOG_ERROR, "Error initializing the MFX video decoder\n");
114         return ff_qsv_error(ret);
115     }
116
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;
124
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:
128      */
129     if (!q->async_fifo) {
130         q->async_fifo = av_fifo_alloc((1 + 16) *
131                                       (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
132         if (!q->async_fifo)
133             return AVERROR(ENOMEM);
134     }
135
136     q->input_fifo = av_fifo_alloc(1024*16);
137     if (!q->input_fifo)
138         return AVERROR(ENOMEM);
139
140     q->engine_ready = 1;
141
142     return 0;
143 }
144
145 static int alloc_frame(AVCodecContext *avctx, QSVFrame *frame)
146 {
147     int ret;
148
149     ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
150     if (ret < 0)
151         return ret;
152
153     if (frame->frame->format == AV_PIX_FMT_QSV) {
154         frame->surface = (mfxFrameSurface1*)frame->frame->data[3];
155     } else {
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;
162
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];
166
167         frame->surface = &frame->surface_internal;
168     }
169
170     return 0;
171 }
172
173 static void qsv_clear_unused_frames(QSVContext *q)
174 {
175     QSVFrame *cur = q->work_frames;
176     while (cur) {
177         if (cur->surface && !cur->surface->Data.Locked && !cur->queued) {
178             cur->surface = NULL;
179             av_frame_unref(cur->frame);
180         }
181         cur = cur->next;
182     }
183 }
184
185 static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
186 {
187     QSVFrame *frame, **last;
188     int ret;
189
190     qsv_clear_unused_frames(q);
191
192     frame = q->work_frames;
193     last  = &q->work_frames;
194     while (frame) {
195         if (!frame->surface) {
196             ret = alloc_frame(avctx, frame);
197             if (ret < 0)
198                 return ret;
199             *surf = frame->surface;
200             return 0;
201         }
202
203         last  = &frame->next;
204         frame = frame->next;
205     }
206
207     frame = av_mallocz(sizeof(*frame));
208     if (!frame)
209         return AVERROR(ENOMEM);
210     frame->frame = av_frame_alloc();
211     if (!frame->frame) {
212         av_freep(&frame);
213         return AVERROR(ENOMEM);
214     }
215     *last = frame;
216
217     ret = alloc_frame(avctx, frame);
218     if (ret < 0)
219         return ret;
220
221     *surf = frame->surface;
222
223     return 0;
224 }
225
226 static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
227 {
228     QSVFrame *cur = q->work_frames;
229     while (cur) {
230         if (surf == cur->surface)
231             return cur;
232         cur = cur->next;
233     }
234     return NULL;
235 }
236
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.
245 */
246 static void qsv_fifo_relocate(AVFifoBuffer *f, int bytes_to_free)
247 {
248     int data_size;
249     int data_rest = 0;
250
251     av_fifo_drain(f, bytes_to_free);
252
253     data_size = av_fifo_size(f);
254     if (data_size > 0) {
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);
260             }
261             memmove(f->buffer, f->rptr, data_size);
262             data_size+= data_rest;
263         }
264     }
265     f->rptr = f->buffer;
266     f->wptr = f->buffer + data_size;
267     f->wndx = data_size;
268     f->rndx = 0;
269 }
270
271 int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
272                   AVFrame *frame, int *got_frame,
273                   AVPacket *avpkt)
274 {
275     QSVFrame *out_frame;
276     mfxFrameSurface1 *insurf;
277     mfxFrameSurface1 *outsurf;
278     mfxSyncPoint sync;
279     mfxBitstream bs = { { { 0 } } };
280     int ret;
281     int n_out_frames;
282     int buffered = 0;
283
284     if (!q->engine_ready) {
285         ret = ff_qsv_decode_init(avctx, q, avpkt);
286         if (ret)
287             return ret;
288     }
289
290     if (avpkt->size ) {
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);
295                 if (ret < 0)
296                     return ret;
297             }
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);
301             buffered = 1;
302         } else {
303             bs.Data       = avpkt->data;
304             bs.DataLength = avpkt->size;
305         }
306         bs.MaxLength  = bs.DataLength;
307         bs.TimeStamp  = avpkt->pts;
308     }
309
310     while (1) {
311         ret = get_surface(avctx, q, &insurf);
312         if (ret < 0)
313             return ret;
314         do {
315             ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
316                                                   insurf, &outsurf, &sync);
317             if (ret != MFX_WRN_DEVICE_BUSY)
318                 break;
319             av_usleep(500);
320         } while (1);
321
322         if (MFX_WRN_VIDEO_PARAM_CHANGED==ret) {
323             /* TODO: handle here sequence header changing */
324         }
325
326         if (sync) {
327             QSVFrame *out_frame = find_frame(q, outsurf);
328
329             if (!out_frame) {
330                 av_log(avctx, AV_LOG_ERROR,
331                        "The returned surface does not correspond to any frame\n");
332                 return AVERROR_BUG;
333             }
334
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);
338
339             continue;
340         }
341         if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
342             break;
343     }
344
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;
350     }
351
352     if (buffered) {
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);
358     }
359
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);
363     }
364     n_out_frames = av_fifo_size(q->async_fifo) / (sizeof(out_frame)+sizeof(sync));
365
366     if (n_out_frames > q->async_depth || (!avpkt->size && n_out_frames) ) {
367         AVFrame *src_frame;
368
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;
372
373         MFXVideoCORE_SyncOperation(q->session, sync, 60000);
374
375         src_frame = out_frame->frame;
376
377         ret = av_frame_ref(frame, src_frame);
378         if (ret < 0)
379             return ret;
380
381         outsurf = out_frame->surface;
382
383         frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
384
385         frame->repeat_pict =
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);
393
394         *got_frame = 1;
395     }
396
397     return avpkt->size;
398 }
399
400 int ff_qsv_decode_close(QSVContext *q)
401 {
402     QSVFrame *cur = q->work_frames;
403
404     while (cur) {
405         q->work_frames = cur->next;
406         av_frame_free(&cur->frame);
407         av_freep(&cur);
408         cur = q->work_frames;
409     }
410
411     av_fifo_free(q->async_fifo);
412     q->async_fifo = NULL;
413
414     av_fifo_free(q->input_fifo);
415     q->input_fifo = NULL;
416
417     MFXVideoDECODE_Close(q->session);
418     q->session = NULL;
419
420     ff_qsv_close_internal_session(&q->internal_qs);
421
422     q->engine_ready = 0;
423
424     return 0;
425 }