FFmpeg
qsvdec_other.c
Go to the documentation of this file.
1 /*
2  * Intel MediaSDK QSV based MPEG-2, VC-1, VP8, MJPEG and VP9 decoders
3  *
4  * copyright (c) 2015 Anton Khirnov
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 #include <stdint.h>
25 #include <string.h>
26 
27 #include <mfx/mfxvideo.h>
28 
29 #include "libavutil/common.h"
30 #include "libavutil/fifo.h"
31 #include "libavutil/opt.h"
32 
33 #include "avcodec.h"
34 #include "internal.h"
35 #include "qsv_internal.h"
36 #include "qsvdec.h"
37 #include "qsv.h"
38 
39 typedef struct QSVOtherContext {
40  AVClass *class;
42 
44 
47 
49 {
50  AVPacket pkt;
51  while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) {
52  av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL);
53  av_packet_unref(&pkt);
54  }
55 
57 }
58 
60 {
61  QSVOtherContext *s = avctx->priv_data;
62 
63 #if CONFIG_VP8_QSV_DECODER || CONFIG_VP9_QSV_DECODER
64  if (avctx->codec_id == AV_CODEC_ID_VP8 || avctx->codec_id == AV_CODEC_ID_VP9)
66 #endif
67 
69 
71 
73 
74  return 0;
75 }
76 
78 {
79  QSVOtherContext *s = avctx->priv_data;
80  int ret;
81 
82 #if CONFIG_VP8_QSV_DECODER
83  if (avctx->codec_id == AV_CODEC_ID_VP8) {
84  static const char *uid_vp8dec_hw = "f622394d8d87452f878c51f2fc9b4131";
85 
87  s->qsv.load_plugins = av_strdup(uid_vp8dec_hw);
88  if (!s->qsv.load_plugins)
89  return AVERROR(ENOMEM);
90  }
91 #endif
92 
93 #if CONFIG_VP9_QSV_DECODER
94  if (avctx->codec_id == AV_CODEC_ID_VP9) {
95  static const char *uid_vp9dec_hw = "a922394d8d87452f878c51f2fc9b4131";
96 
98  s->qsv.load_plugins = av_strdup(uid_vp9dec_hw);
99  if (!s->qsv.load_plugins)
100  return AVERROR(ENOMEM);
101  }
102 #endif
103 
105  s->packet_fifo = av_fifo_alloc(sizeof(AVPacket));
106  if (!s->packet_fifo) {
107  ret = AVERROR(ENOMEM);
108  goto fail;
109  }
110 
111  return 0;
112 fail:
113  qsv_decode_close(avctx);
114  return ret;
115 }
116 
117 static int qsv_decode_frame(AVCodecContext *avctx, void *data,
118  int *got_frame, AVPacket *avpkt)
119 {
120  QSVOtherContext *s = avctx->priv_data;
121  AVFrame *frame = data;
122  int ret;
123 
124  /* buffer the input packet */
125  if (avpkt->size) {
127 
128  if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) {
129  ret = av_fifo_realloc2(s->packet_fifo,
130  av_fifo_size(s->packet_fifo) + sizeof(input_ref));
131  if (ret < 0)
132  return ret;
133  }
134 
135  ret = av_packet_ref(&input_ref, avpkt);
136  if (ret < 0)
137  return ret;
138  av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
139  }
140 
141  /* process buffered data */
142  while (!*got_frame) {
143  if (s->input_ref.size <= 0) {
144  /* no more data */
145  if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket))
146  return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt);
147  /* in progress of reinit, no read from fifo and keep the buffer_pkt */
148  if (!s->qsv.reinit_flag) {
151  }
152  }
153 
154  ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->input_ref);
155  if (ret < 0) {
156  /* Drop input packet when failed to decode the packet. Otherwise,
157  the decoder will keep decoding the failure packet. */
159 
160  return ret;
161  }
162  if (s->qsv.reinit_flag)
163  continue;
164 
165  s->input_ref.size -= ret;
166  s->input_ref.data += ret;
167  }
168 
169  return avpkt->size;
170 }
171 
172 static void qsv_decode_flush(AVCodecContext *avctx)
173 {
174  QSVOtherContext *s = avctx->priv_data;
175 
177  ff_qsv_decode_flush(avctx, &s->qsv);
178 }
179 
180 #define OFFSET(x) offsetof(QSVOtherContext, x)
181 #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
182 static const AVOption options[] = {
183  { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
184 
185  { "gpu_copy", "A GPU-accelerated copy between video and system memory", OFFSET(qsv.gpu_copy), AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF, VD, "gpu_copy"},
186  { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"},
187  { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"},
188  { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"},
189  { NULL },
190 };
191 
192 #if CONFIG_MPEG2_QSV_DECODER
193 static const AVClass mpeg2_qsv_class = {
194  .class_name = "mpeg2_qsv",
195  .item_name = av_default_item_name,
196  .option = options,
197  .version = LIBAVUTIL_VERSION_INT,
198 };
199 
201  .name = "mpeg2_qsv",
202  .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"),
203  .priv_data_size = sizeof(QSVOtherContext),
209  .close = qsv_decode_close,
211  .priv_class = &mpeg2_qsv_class,
212  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
214  AV_PIX_FMT_NONE },
215  .hw_configs = ff_qsv_hw_configs,
216  .wrapper_name = "qsv",
217 };
218 #endif
219 
220 #if CONFIG_VC1_QSV_DECODER
221 static const AVClass vc1_qsv_class = {
222  .class_name = "vc1_qsv",
223  .item_name = av_default_item_name,
224  .option = options,
225  .version = LIBAVUTIL_VERSION_INT,
226 };
227 
229  .name = "vc1_qsv",
230  .long_name = NULL_IF_CONFIG_SMALL("VC-1 video (Intel Quick Sync Video acceleration)"),
231  .priv_data_size = sizeof(QSVOtherContext),
233  .id = AV_CODEC_ID_VC1,
237  .close = qsv_decode_close,
239  .priv_class = &vc1_qsv_class,
240  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
242  AV_PIX_FMT_NONE },
243  .hw_configs = ff_qsv_hw_configs,
244  .wrapper_name = "qsv",
245 };
246 #endif
247 
248 #if CONFIG_VP8_QSV_DECODER
249 static const AVClass vp8_qsv_class = {
250  .class_name = "vp8_qsv",
251  .item_name = av_default_item_name,
252  .option = options,
253  .version = LIBAVUTIL_VERSION_INT,
254 };
255 
257  .name = "vp8_qsv",
258  .long_name = NULL_IF_CONFIG_SMALL("VP8 video (Intel Quick Sync Video acceleration)"),
259  .priv_data_size = sizeof(QSVOtherContext),
261  .id = AV_CODEC_ID_VP8,
265  .close = qsv_decode_close,
267  .priv_class = &vp8_qsv_class,
268  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
270  AV_PIX_FMT_NONE },
271  .hw_configs = ff_qsv_hw_configs,
272  .wrapper_name = "qsv",
273 };
274 #endif
275 
276 #if CONFIG_MJPEG_QSV_DECODER
277 static const AVClass mjpeg_qsv_class = {
278  .class_name = "mjpeg_qsv",
279  .item_name = av_default_item_name,
280  .option = options,
281  .version = LIBAVUTIL_VERSION_INT,
282 };
283 
285  .name = "mjpeg_qsv",
286  .long_name = NULL_IF_CONFIG_SMALL("MJPEG video (Intel Quick Sync Video acceleration)"),
287  .priv_data_size = sizeof(QSVOtherContext),
289  .id = AV_CODEC_ID_MJPEG,
293  .close = qsv_decode_close,
295  .priv_class = &mjpeg_qsv_class,
296  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
298  AV_PIX_FMT_NONE },
299 };
300 #endif
301 
302 #if CONFIG_VP9_QSV_DECODER
303 static const AVClass vp9_qsv_class = {
304  .class_name = "vp9_qsv",
305  .item_name = av_default_item_name,
306  .option = options,
307  .version = LIBAVUTIL_VERSION_INT,
308 };
309 
311  .name = "vp9_qsv",
312  .long_name = NULL_IF_CONFIG_SMALL("VP9 video (Intel Quick Sync Video acceleration)"),
313  .priv_data_size = sizeof(QSVOtherContext),
315  .id = AV_CODEC_ID_VP9,
319  .close = qsv_decode_close,
321  .priv_class = &vp9_qsv_class,
322  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
325  AV_PIX_FMT_NONE },
326  .hw_configs = ff_qsv_hw_configs,
327  .wrapper_name = "qsv",
328 };
329 #endif
#define OFFSET(x)
Definition: qsvdec_other.c:180
#define NULL
Definition: coverity.c:32
static void qsv_decode_flush(AVCodecContext *avctx)
Definition: qsvdec_other.c:172
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
static av_cold int qsv_decode_close(AVCodecContext *avctx)
Definition: qsvdec_other.c:59
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static void flush(AVCodecContext *avctx)
AVCodec ff_vc1_qsv_decoder
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: packet.h:356
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
GLint GLenum type
Definition: opengl_enc.c:104
static AVPacket pkt
AVCodec.
Definition: codec.h:190
AVCodec ff_vp8_qsv_decoder
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int(*func)(void *, void *, int))
Feed data from a user-supplied callback to an AVFifoBuffer.
Definition: fifo.c:122
AVCodec ff_mjpeg_qsv_decoder
#define AV_PIX_FMT_P010
Definition: pixfmt.h:446
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: codec.h:75
#define av_cold
Definition: attributes.h:88
AVOptions.
int ff_qsv_decode_close(QSVContext *q)
Definition: qsvdec.c:533
AVFifoBuffer * packet_fifo
Definition: qsvdec_other.c:43
int av_fifo_space(const AVFifoBuffer *f)
Return the amount of space in bytes in the AVFifoBuffer, that is the amount of data you can write int...
Definition: fifo.c:82
uint8_t * data
Definition: packet.h:355
void av_fifo_free(AVFifoBuffer *f)
Free an AVFifoBuffer.
Definition: fifo.c:55
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:614
static const AVOption options[]
Definition: qsvdec_other.c:182
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
int reinit_flag
Definition: qsvdec.h:57
int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void(*func)(void *, void *, int))
Feed data from an AVFifoBuffer to a user-supplied callback.
Definition: fifo.c:213
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:89
const char * name
Name of the codec implementation.
Definition: codec.h:197
#define fail()
Definition: checkasm.h:123
void ff_qsv_decode_flush(AVCodecContext *avctx, QSVContext *q)
Definition: qsvdec.c:631
#define ASYNC_DEPTH_DEFAULT
Definition: qsv_internal.h:49
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define s(width, name)
Definition: cbs_vp9.c:257
AVCodec ff_vp9_qsv_decoder
AVPacket input_ref
Definition: qsvdec_other.c:45
#define VD
Definition: qsvdec_other.c:181
preferred ID for MPEG-1/2 video decoding
Definition: codec_id.h:51
enum AVPixelFormat orig_pix_fmt
Definition: qsvdec.h:59
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
Libavcodec external API header.
AVCodec ff_mpeg2_qsv_decoder
static void qsv_clear_buffers(QSVOtherContext *s)
Definition: qsvdec_other.c:48
enum AVCodecID codec_id
Definition: avcodec.h:536
int av_fifo_size(const AVFifoBuffer *f)
Return the amount of data in bytes in the AVFifoBuffer, that is the amount of data you can read from ...
Definition: fifo.c:77
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
Resize an AVFifoBuffer.
Definition: fifo.c:87
main external API structure.
Definition: avcodec.h:526
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:605
a very simple circular buffer FIFO implementation
#define AV_CODEC_CAP_HYBRID
Codec is potentially backed by a hardware implementation, but not necessarily.
Definition: codec.h:157
Describe the class of an AVClass context structure.
Definition: log.h:67
int gpu_copy
Definition: qsvdec.h:69
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:222
char * load_plugins
Definition: qsvdec.h:71
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
common internal api header.
common internal and external API header
static av_cold int qsv_decode_init(AVCodecContext *avctx)
Definition: qsvdec_other.c:77
static int qsv_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: qsvdec_other.c:117
void * priv_data
Definition: avcodec.h:553
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
Definition: fifo.c:43
#define AV_CODEC_CAP_AVOID_PROBING
Decoder is not a preferred choice for probing.
Definition: codec.h:132
#define av_freep(p)
const AVCodecHWConfigInternal * ff_qsv_hw_configs[]
Definition: qsvdec.c:46
int async_depth
Definition: qsvdec.h:67
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *pkt)
Definition: qsvdec.c:569
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
This structure stores compressed data.
Definition: packet.h:332
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:50
QSVContext qsv
Definition: qsvdec_other.c:41