Libav
vdpau.c
Go to the documentation of this file.
1 /*
2  * Video Decode and Presentation API for UNIX (VDPAU) is used for
3  * HW decode acceleration for MPEG-1/2, MPEG-4 ASP, H.264 and VC-1.
4  *
5  * Copyright (c) 2008 NVIDIA
6  *
7  * This file is part of Libav.
8  *
9  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include <limits.h>
25 
26 #include "avcodec.h"
27 #include "internal.h"
28 #include "h264dec.h"
29 #include "vc1.h"
30 #include "vdpau.h"
31 #include "vdpau_internal.h"
32 
39 static int vdpau_error(VdpStatus status)
40 {
41  switch (status) {
42  case VDP_STATUS_OK:
43  return 0;
44  case VDP_STATUS_NO_IMPLEMENTATION:
45  return AVERROR(ENOSYS);
46  case VDP_STATUS_DISPLAY_PREEMPTED:
47  return AVERROR(EIO);
48  case VDP_STATUS_INVALID_HANDLE:
49  return AVERROR(EBADF);
50  case VDP_STATUS_INVALID_POINTER:
51  return AVERROR(EFAULT);
52  case VDP_STATUS_RESOURCES:
53  return AVERROR(ENOBUFS);
54  case VDP_STATUS_HANDLE_DEVICE_MISMATCH:
55  return AVERROR(EXDEV);
56  case VDP_STATUS_ERROR:
57  return AVERROR(EIO);
58  default:
59  return AVERROR(EINVAL);
60  }
61 }
62 
64  VdpChromaType *type,
65  uint32_t *width, uint32_t *height)
66 {
67  VdpChromaType t;
68  uint32_t w = avctx->coded_width;
69  uint32_t h = avctx->coded_height;
70 
71  /* See <vdpau/vdpau.h> for per-type alignment constraints. */
72  switch (avctx->sw_pix_fmt) {
73  case AV_PIX_FMT_YUV420P:
75  t = VDP_CHROMA_TYPE_420;
76  w = (w + 1) & ~1;
77  h = (h + 3) & ~3;
78  break;
79  case AV_PIX_FMT_YUV422P:
81  t = VDP_CHROMA_TYPE_422;
82  w = (w + 1) & ~1;
83  h = (h + 1) & ~1;
84  break;
85  case AV_PIX_FMT_YUV444P:
87  t = VDP_CHROMA_TYPE_444;
88  h = (h + 1) & ~1;
89  break;
90  default:
91  return AVERROR(ENOSYS);
92  }
93 
94  if (type)
95  *type = t;
96  if (width)
97  *width = w;
98  if (height)
99  *height = h;
100  return 0;
101 }
102 
103 int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
104  int level)
105 {
106  VDPAUHWContext *hwctx = avctx->hwaccel_context;
107  VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
108  VdpVideoSurfaceQueryCapabilities *surface_query_caps;
109  VdpDecoderQueryCapabilities *decoder_query_caps;
110  VdpDecoderCreate *create;
111  void *func;
112  VdpStatus status;
113  VdpBool supported;
114  uint32_t max_level, max_mb, max_width, max_height;
115  VdpChromaType type;
116  uint32_t width;
117  uint32_t height;
118 
119  vdctx->width = UINT32_MAX;
120  vdctx->height = UINT32_MAX;
121  hwctx->reset = 0;
122 
123  if (hwctx->context.decoder != VDP_INVALID_HANDLE) {
124  vdctx->decoder = hwctx->context.decoder;
125  vdctx->render = hwctx->context.render;
126  vdctx->device = VDP_INVALID_HANDLE;
127  return 0; /* Decoder created by user */
128  }
129 
130  vdctx->device = hwctx->device;
131  vdctx->get_proc_address = hwctx->get_proc_address;
132 
133  if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL)
134  level = 0;
135  else if (level < 0)
136  return AVERROR(ENOTSUP);
137 
138  if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height))
139  return AVERROR(ENOSYS);
140 
141  if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) &&
142  type != VDP_CHROMA_TYPE_420)
143  return AVERROR(ENOSYS);
144 
145  status = vdctx->get_proc_address(vdctx->device,
146  VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,
147  &func);
148  if (status != VDP_STATUS_OK)
149  return vdpau_error(status);
150  else
151  surface_query_caps = func;
152 
153  status = surface_query_caps(vdctx->device, type, &supported,
154  &max_width, &max_height);
155  if (status != VDP_STATUS_OK)
156  return vdpau_error(status);
157  if (supported != VDP_TRUE ||
158  max_width < width || max_height < height)
159  return AVERROR(ENOTSUP);
160 
161  status = vdctx->get_proc_address(vdctx->device,
162  VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES,
163  &func);
164  if (status != VDP_STATUS_OK)
165  return vdpau_error(status);
166  else
167  decoder_query_caps = func;
168 
169  status = decoder_query_caps(vdctx->device, profile, &supported, &max_level,
170  &max_mb, &max_width, &max_height);
171 #ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE
172  if ((status != VDP_STATUS_OK || supported != VDP_TRUE) && profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE) {
173  profile = VDP_DECODER_PROFILE_H264_MAIN;
174  status = decoder_query_caps(vdctx->device, profile, &supported,
175  &max_level, &max_mb,
176  &max_width, &max_height);
177  }
178 #endif
179  if (status != VDP_STATUS_OK)
180  return vdpau_error(status);
181 
182  if (supported != VDP_TRUE || max_level < level ||
183  max_width < width || max_height < height)
184  return AVERROR(ENOTSUP);
185 
186  status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_CREATE,
187  &func);
188  if (status != VDP_STATUS_OK)
189  return vdpau_error(status);
190  else
191  create = func;
192 
193  status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_RENDER,
194  &func);
195  if (status != VDP_STATUS_OK)
196  return vdpau_error(status);
197  else
198  vdctx->render = func;
199 
200  status = create(vdctx->device, profile, width, height, avctx->refs,
201  &vdctx->decoder);
202  if (status == VDP_STATUS_OK) {
203  vdctx->width = avctx->coded_width;
204  vdctx->height = avctx->coded_height;
205  }
206 
207  return vdpau_error(status);
208 }
209 
211 {
212  VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
213  VdpDecoderDestroy *destroy;
214  void *func;
215  VdpStatus status;
216 
217  if (vdctx->device == VDP_INVALID_HANDLE)
218  return 0; /* Decoder created and destroyed by user */
219  if (vdctx->width == UINT32_MAX && vdctx->height == UINT32_MAX)
220  return 0;
221 
222  status = vdctx->get_proc_address(vdctx->device,
223  VDP_FUNC_ID_DECODER_DESTROY, &func);
224  if (status != VDP_STATUS_OK)
225  return vdpau_error(status);
226  else
227  destroy = func;
228 
229  status = destroy(vdctx->decoder);
230  return vdpau_error(status);
231 }
232 
234 {
235  VDPAUHWContext *hwctx = avctx->hwaccel_context;
236  VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
237 
238  if (vdctx->device == VDP_INVALID_HANDLE)
239  return 0; /* Decoder created by user */
240  if (avctx->coded_width == vdctx->width &&
241  avctx->coded_height == vdctx->height && !hwctx->reset)
242  return 0;
243 
244  avctx->hwaccel->uninit(avctx);
245  return avctx->hwaccel->init(avctx);
246 }
247 
249  av_unused const uint8_t *buffer,
250  av_unused uint32_t size)
251 {
252  pic_ctx->bitstream_buffers_allocated = 0;
253  pic_ctx->bitstream_buffers_used = 0;
254  pic_ctx->bitstream_buffers = NULL;
255  return 0;
256 }
257 
259  struct vdpau_picture_context *pic_ctx)
260 {
261  VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
262  VdpVideoSurface surf = ff_vdpau_get_surface_id(frame);
263  VdpStatus status;
264  int val;
265 
266  val = ff_vdpau_common_reinit(avctx);
267  if (val < 0)
268  return val;
269 
270  status = vdctx->render(vdctx->decoder, surf, (void *)&pic_ctx->info,
271  pic_ctx->bitstream_buffers_used,
272  pic_ctx->bitstream_buffers);
273 
274  av_freep(&pic_ctx->bitstream_buffers);
275  return vdpau_error(status);
276 }
277 
278 #if CONFIG_MPEG1_VDPAU_HWACCEL || \
279  CONFIG_MPEG2_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL || \
280  CONFIG_VC1_VDPAU_HWACCEL || CONFIG_WMV3_VDPAU_HWACCEL
282 {
283  MpegEncContext *s = avctx->priv_data;
284  Picture *pic = s->current_picture_ptr;
285  struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
286  int val;
287 
288  val = ff_vdpau_common_end_frame(avctx, pic->f, pic_ctx);
289  if (val < 0)
290  return val;
291 
293  return 0;
294 }
295 #endif
296 
298  const uint8_t *buf, uint32_t size)
299 {
300  VdpBitstreamBuffer *buffers = pic_ctx->bitstream_buffers;
301 
302  buffers = av_fast_realloc(buffers, &pic_ctx->bitstream_buffers_allocated,
303  (pic_ctx->bitstream_buffers_used + 1) * sizeof(*buffers));
304  if (!buffers)
305  return AVERROR(ENOMEM);
306 
307  pic_ctx->bitstream_buffers = buffers;
308  buffers += pic_ctx->bitstream_buffers_used++;
309 
310  buffers->struct_version = VDP_BITSTREAM_BUFFER_VERSION;
311  buffers->bitstream = buf;
312  buffers->bitstream_bytes = size;
313  return 0;
314 }
315 
316 #if FF_API_VDPAU_PROFILE
317 int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile)
318 {
319 #define PROFILE(prof) \
320 do { \
321  *profile = VDP_DECODER_PROFILE_##prof; \
322  return 0; \
323 } while (0)
324 
325  switch (avctx->codec_id) {
326  case AV_CODEC_ID_MPEG1VIDEO: PROFILE(MPEG1);
328  switch (avctx->profile) {
329  case FF_PROFILE_MPEG2_MAIN: PROFILE(MPEG2_MAIN);
330  case FF_PROFILE_MPEG2_SIMPLE: PROFILE(MPEG2_SIMPLE);
331  default: return AVERROR(EINVAL);
332  }
333  case AV_CODEC_ID_H263: PROFILE(MPEG4_PART2_ASP);
334  case AV_CODEC_ID_MPEG4:
335  switch (avctx->profile) {
336  case FF_PROFILE_MPEG4_SIMPLE: PROFILE(MPEG4_PART2_SP);
337  case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: PROFILE(MPEG4_PART2_ASP);
338  default: return AVERROR(EINVAL);
339  }
340  case AV_CODEC_ID_H264:
341  switch (avctx->profile & ~FF_PROFILE_H264_INTRA) {
342  case FF_PROFILE_H264_BASELINE: PROFILE(H264_BASELINE);
344  case FF_PROFILE_H264_MAIN: PROFILE(H264_MAIN);
345  case FF_PROFILE_H264_HIGH: PROFILE(H264_HIGH);
346 #ifdef VDP_DECODER_PROFILE_H264_EXTENDED
347  case FF_PROFILE_H264_EXTENDED: PROFILE(H264_EXTENDED);
348 #endif
349  default: return AVERROR(EINVAL);
350  }
351  case AV_CODEC_ID_WMV3:
352  case AV_CODEC_ID_VC1:
353  switch (avctx->profile) {
354  case FF_PROFILE_VC1_SIMPLE: PROFILE(VC1_SIMPLE);
355  case FF_PROFILE_VC1_MAIN: PROFILE(VC1_MAIN);
356  case FF_PROFILE_VC1_ADVANCED: PROFILE(VC1_ADVANCED);
357  default: return AVERROR(EINVAL);
358  }
359  }
360  return AVERROR(EINVAL);
361 #undef PROFILE
362 }
363 #endif /* FF_API_VDPAU_PROFILE */
364 
366 {
367  return av_mallocz(sizeof(AVVDPAUContext));
368 }
369 
370 int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,
371  VdpGetProcAddress *get_proc, unsigned flags)
372 {
373  VDPAUHWContext *hwctx;
374 
376  return AVERROR(EINVAL);
377 
378  if (av_reallocp(&avctx->hwaccel_context, sizeof(*hwctx)))
379  return AVERROR(ENOMEM);
380 
381  hwctx = avctx->hwaccel_context;
382 
383  memset(hwctx, 0, sizeof(*hwctx));
384  hwctx->context.decoder = VDP_INVALID_HANDLE;
385  hwctx->device = device;
386  hwctx->get_proc_address = get_proc;
387  hwctx->flags = flags;
388  hwctx->reset = 1;
389  return 0;
390 }
391 
392 /* @}*/
#define FF_PROFILE_H264_MAIN
Definition: avcodec.h:2914
#define FF_PROFILE_MPEG4_SIMPLE
Definition: avcodec.h:2933
#define FF_PROFILE_MPEG2_MAIN
Definition: avcodec.h:2906
int size
This structure describes decoded (raw) audio or video data.
Definition: frame.h:140
VdpDevice device
VDPAU device handle.
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:1595
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:64
VdpGetProcAddress * get_proc_address
VdpDecoder decoder
VDPAU decoder handle.
int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: vdpau.c:248
#define FF_PROFILE_H264_INTRA
Definition: avcodec.h:2910
int bitstream_buffers_used
Useful bitstream buffers in the bitstream buffers table.
Public libavcodec VDPAU header.
int profile
profile
Definition: avcodec.h:2880
AVVDPAUContext * av_vdpau_alloc_context(void)
Allocate an AVVDPAUContext.
Definition: vdpau.c:365
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:202
int(* uninit)(AVCodecContext *avctx)
Uninitialize the hwaccel private data.
Definition: avcodec.h:3351
int av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type, uint32_t *width, uint32_t *height)
Gets the parameters to create an adequate VDPAU video surface for the codec context using VDPAU hardw...
Definition: vdpau.c:63
struct AVHWAccel * hwaccel
Hardware accelerator in use.
Definition: avcodec.h:2696
void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h)
Definition: mpegvideo.c:1737
VdpBitstreamBuffer * bitstream_buffers
Table of bitstream buffers.
#define FF_PROFILE_H264_BASELINE
Definition: avcodec.h:2912
static char buffer[20]
Definition: seek.c:32
int ff_vdpau_common_uninit(AVCodecContext *avctx)
Definition: vdpau.c:210
uint8_t
void * hwaccel_context
Hardware accelerator context.
Definition: avcodec.h:2708
VdpGetProcAddress * get_proc_address
VDPAU device driver.
int av_reallocp(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:140
static int flags
Definition: log.c:50
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:72
VdpDecoder decoder
VDPAU decoder handle.
Definition: vdpau.h:88
#define FF_PROFILE_H264_EXTENDED
Definition: avcodec.h:2915
int(* init)(AVCodecContext *avctx)
Initialize the hwaccel private data.
Definition: avcodec.h:3343
AVVDPAUContext context
int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile)
Get a decoder profile that should be used for initializing a VDPAU decoder.
Definition: vdpau.c:317
VdpDevice device
#define AV_HWACCEL_FLAG_IGNORE_LEVEL
Hardware acceleration should be used for decoding even if the codec level used is unknown or higher t...
Definition: avcodec.h:3365
#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH
Hardware acceleration can output YUV pixel formats with a different chroma sampling than 4:2:0 and/or...
Definition: avcodec.h:3371
#define PROFILE(prof)
int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, int level)
Definition: vdpau.c:103
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given block if it is not large enough, otherwise do nothing.
Definition: mem.c:375
This structure is used to share data between the libavcodec library and the client video application...
Definition: vdpau.h:82
#define AVERROR(e)
Definition: error.h:43
#define FF_PROFILE_H264_HIGH
Definition: avcodec.h:2916
int bitstream_buffers_allocated
Allocated size of the bitstream_buffers table.
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:63
int refs
number of reference frames
Definition: avcodec.h:2071
uint32_t width
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:71
#define FF_PROFILE_VC1_MAIN
Definition: avcodec.h:2929
Picture * current_picture_ptr
pointer to the current picture
Definition: mpegvideo.h:179
Picture.
Definition: mpegpicture.h:45
void * hwaccel_picture_private
Hardware accelerator private data.
Definition: mpegpicture.h:74
static int vdpau_error(VdpStatus status)
Definition: vdpau.c:39
H.264 / AVC / MPEG-4 part10 codec.
#define FF_PROFILE_VC1_SIMPLE
Definition: avcodec.h:2928
preferred ID for MPEG-1/2 video decoding
Definition: avcodec.h:198
NULL
Definition: eval.c:55
static int width
Definition: utils.c:156
Libavcodec external API header.
enum AVCodecID codec_id
Definition: avcodec.h:1426
void(* func)(void)
Definition: checkasm.c:65
int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx)
main external API structure.
Definition: avcodec.h:1409
#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE
Definition: avcodec.h:2948
VdpDecoderRender * render
VDPAU decoder render callback.
int coded_height
Definition: avcodec.h:1595
struct AVFrame * f
Definition: mpegpicture.h:46
VdpDecoderRender * render
VDPAU decoder render callback.
Definition: vdpau.h:95
mfxU16 profile
Definition: qsvenc.c:43
int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device, VdpGetProcAddress *get_proc, unsigned flags)
Associate a VDPAU device with a codec context for hardware acceleration.
Definition: vdpau.c:370
uint8_t level
Definition: svq3.c:204
int height
Definition: gxfenc.c:72
MpegEncContext.
Definition: mpegvideo.h:76
struct AVCodecContext * avctx
Definition: mpegvideo.h:93
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:59
common internal api header.
int ff_vdpau_add_buffer(struct vdpau_picture_context *pic_ctx, const uint8_t *buf, uint32_t size)
Definition: vdpau.c:297
void * hwaccel_priv_data
hwaccel-specific private data
Definition: internal.h:142
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:73
unsigned char flags
int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame, struct vdpau_picture_context *pic_ctx)
Definition: vdpau.c:258
void * priv_data
Definition: avcodec.h:1451
#define FF_PROFILE_VC1_ADVANCED
Definition: avcodec.h:2931
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:1459
union VDPAUPictureInfo info
VDPAU picture information.
#define FF_PROFILE_MPEG2_SIMPLE
Definition: avcodec.h:2907
#define FF_PROFILE_H264_CONSTRAINED_BASELINE
Definition: avcodec.h:2913
uint32_t height
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:211
static int ff_vdpau_common_reinit(AVCodecContext *avctx)
Definition: vdpau.c:233
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:3070
#define av_unused
Definition: attributes.h:86
static uintptr_t ff_vdpau_get_surface_id(AVFrame *pic)
Extract VdpVideoSurface from an AVFrame.