lavc: external hardware frame pool initialization
[ffmpeg.git] / libavcodec / vdpau.c
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 "decode.h"
28 #include "internal.h"
29 #include "h264dec.h"
30 #include "vc1.h"
31 #include "vdpau.h"
32 #include "vdpau_internal.h"
33
34 /**
35  * @addtogroup VDPAU_Decoding
36  *
37  * @{
38  */
39
40 static int vdpau_error(VdpStatus status)
41 {
42     switch (status) {
43     case VDP_STATUS_OK:
44         return 0;
45     case VDP_STATUS_NO_IMPLEMENTATION:
46         return AVERROR(ENOSYS);
47     case VDP_STATUS_DISPLAY_PREEMPTED:
48         return AVERROR(EIO);
49     case VDP_STATUS_INVALID_HANDLE:
50         return AVERROR(EBADF);
51     case VDP_STATUS_INVALID_POINTER:
52         return AVERROR(EFAULT);
53     case VDP_STATUS_RESOURCES:
54         return AVERROR(ENOBUFS);
55     case VDP_STATUS_HANDLE_DEVICE_MISMATCH:
56         return AVERROR(EXDEV);
57     case VDP_STATUS_ERROR:
58         return AVERROR(EIO);
59     default:
60         return AVERROR(EINVAL);
61     }
62 }
63
64 int av_vdpau_get_surface_parameters(AVCodecContext *avctx,
65                                     VdpChromaType *type,
66                                     uint32_t *width, uint32_t *height)
67 {
68     VdpChromaType t;
69     uint32_t w = avctx->coded_width;
70     uint32_t h = avctx->coded_height;
71
72     /* See <vdpau/vdpau.h> for per-type alignment constraints. */
73     switch (avctx->sw_pix_fmt) {
74     case AV_PIX_FMT_YUV420P:
75     case AV_PIX_FMT_YUVJ420P:
76         t = VDP_CHROMA_TYPE_420;
77         w = (w + 1) & ~1;
78         h = (h + 3) & ~3;
79         break;
80     case AV_PIX_FMT_YUV422P:
81     case AV_PIX_FMT_YUVJ422P:
82         t = VDP_CHROMA_TYPE_422;
83         w = (w + 1) & ~1;
84         h = (h + 1) & ~1;
85         break;
86     case AV_PIX_FMT_YUV444P:
87     case AV_PIX_FMT_YUVJ444P:
88         t = VDP_CHROMA_TYPE_444;
89         h = (h + 1) & ~1;
90         break;
91     default:
92         return AVERROR(ENOSYS);
93     }
94
95     if (type)
96         *type = t;
97     if (width)
98         *width = w;
99     if (height)
100         *height = h;
101     return 0;
102 }
103
104 int ff_vdpau_common_frame_params(AVCodecContext *avctx,
105                                  AVBufferRef *hw_frames_ctx)
106 {
107     AVHWFramesContext *hw_frames = (AVHWFramesContext*)hw_frames_ctx->data;
108     VdpChromaType type;
109     uint32_t width;
110     uint32_t height;
111
112     if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height))
113         return AVERROR(EINVAL);
114
115     hw_frames->format    = AV_PIX_FMT_VDPAU;
116     hw_frames->sw_format = avctx->sw_pix_fmt;
117     hw_frames->width     = width;
118     hw_frames->height    = height;
119
120     return 0;
121 }
122
123 int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
124                          int level)
125 {
126     VDPAUHWContext *hwctx = avctx->hwaccel_context;
127     VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
128     VdpVideoSurfaceQueryCapabilities *surface_query_caps;
129     VdpDecoderQueryCapabilities *decoder_query_caps;
130     VdpDecoderCreate *create;
131     void *func;
132     VdpStatus status;
133     VdpBool supported;
134     uint32_t max_level, max_mb, max_width, max_height;
135     VdpChromaType type;
136     uint32_t width;
137     uint32_t height;
138     int ret;
139
140     vdctx->width            = UINT32_MAX;
141     vdctx->height           = UINT32_MAX;
142
143     if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height))
144         return AVERROR(ENOSYS);
145
146     if (hwctx) {
147         hwctx->reset            = 0;
148
149         if (hwctx->context.decoder != VDP_INVALID_HANDLE) {
150             vdctx->decoder = hwctx->context.decoder;
151             vdctx->render  = hwctx->context.render;
152             vdctx->device  = VDP_INVALID_HANDLE;
153             return 0; /* Decoder created by user */
154         }
155
156         vdctx->device           = hwctx->device;
157         vdctx->get_proc_address = hwctx->get_proc_address;
158
159         if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL)
160             level = 0;
161
162         if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) &&
163             type != VDP_CHROMA_TYPE_420)
164             return AVERROR(ENOSYS);
165     } else {
166         AVHWFramesContext *frames_ctx;
167         AVVDPAUDeviceContext *dev_ctx;
168
169         ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VDPAU);
170         if (ret < 0)
171             return ret;
172
173         frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
174         dev_ctx = frames_ctx->device_ctx->hwctx;
175
176         vdctx->device           = dev_ctx->device;
177         vdctx->get_proc_address = dev_ctx->get_proc_address;
178
179         if (avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL)
180             level = 0;
181     }
182
183     if (level < 0)
184         return AVERROR(ENOTSUP);
185
186     status = vdctx->get_proc_address(vdctx->device,
187                                      VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,
188                                      &func);
189     if (status != VDP_STATUS_OK)
190         return vdpau_error(status);
191     else
192         surface_query_caps = func;
193
194     status = surface_query_caps(vdctx->device, type, &supported,
195                                 &max_width, &max_height);
196     if (status != VDP_STATUS_OK)
197         return vdpau_error(status);
198     if (supported != VDP_TRUE ||
199         max_width < width || max_height < height)
200         return AVERROR(ENOTSUP);
201
202     status = vdctx->get_proc_address(vdctx->device,
203                                      VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES,
204                                      &func);
205     if (status != VDP_STATUS_OK)
206         return vdpau_error(status);
207     else
208         decoder_query_caps = func;
209
210     status = decoder_query_caps(vdctx->device, profile, &supported, &max_level,
211                                 &max_mb, &max_width, &max_height);
212 #ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE
213     if ((status != VDP_STATUS_OK || supported != VDP_TRUE) && profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE) {
214         profile = VDP_DECODER_PROFILE_H264_MAIN;
215         status = decoder_query_caps(vdctx->device, profile, &supported,
216                                     &max_level, &max_mb,
217                                     &max_width, &max_height);
218     }
219 #endif
220     if (status != VDP_STATUS_OK)
221         return vdpau_error(status);
222
223     if (supported != VDP_TRUE || max_level < level ||
224         max_width < width || max_height < height)
225         return AVERROR(ENOTSUP);
226
227     status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_CREATE,
228                                      &func);
229     if (status != VDP_STATUS_OK)
230         return vdpau_error(status);
231     else
232         create = func;
233
234     status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_RENDER,
235                                      &func);
236     if (status != VDP_STATUS_OK)
237         return vdpau_error(status);
238     else
239         vdctx->render = func;
240
241     status = create(vdctx->device, profile, width, height, avctx->refs,
242                     &vdctx->decoder);
243     if (status == VDP_STATUS_OK) {
244         vdctx->width  = avctx->coded_width;
245         vdctx->height = avctx->coded_height;
246     }
247
248     return vdpau_error(status);
249 }
250
251 int ff_vdpau_common_uninit(AVCodecContext *avctx)
252 {
253     VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
254     VdpDecoderDestroy *destroy;
255     void *func;
256     VdpStatus status;
257
258     if (vdctx->device == VDP_INVALID_HANDLE)
259         return 0; /* Decoder created and destroyed by user */
260     if (vdctx->width == UINT32_MAX && vdctx->height == UINT32_MAX)
261         return 0;
262
263     status = vdctx->get_proc_address(vdctx->device,
264                                      VDP_FUNC_ID_DECODER_DESTROY, &func);
265     if (status != VDP_STATUS_OK)
266         return vdpau_error(status);
267     else
268         destroy = func;
269
270     status = destroy(vdctx->decoder);
271     return vdpau_error(status);
272 }
273
274 static int ff_vdpau_common_reinit(AVCodecContext *avctx)
275 {
276     VDPAUHWContext *hwctx = avctx->hwaccel_context;
277     VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
278
279     if (vdctx->device == VDP_INVALID_HANDLE)
280         return 0; /* Decoder created by user */
281     if (avctx->coded_width == vdctx->width &&
282         avctx->coded_height == vdctx->height && (!hwctx || !hwctx->reset))
283         return 0;
284
285     avctx->hwaccel->uninit(avctx);
286     return avctx->hwaccel->init(avctx);
287 }
288
289 int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx,
290                                 av_unused const uint8_t *buffer,
291                                 av_unused uint32_t size)
292 {
293     pic_ctx->bitstream_buffers_allocated = 0;
294     pic_ctx->bitstream_buffers_used      = 0;
295     pic_ctx->bitstream_buffers           = NULL;
296     return 0;
297 }
298
299 int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
300                               struct vdpau_picture_context *pic_ctx)
301 {
302     VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
303     VdpVideoSurface surf = ff_vdpau_get_surface_id(frame);
304     VdpStatus status;
305     int val;
306
307     val = ff_vdpau_common_reinit(avctx);
308     if (val < 0)
309         return val;
310
311     status = vdctx->render(vdctx->decoder, surf, &pic_ctx->info,
312                            pic_ctx->bitstream_buffers_used,
313                            pic_ctx->bitstream_buffers);
314
315     av_freep(&pic_ctx->bitstream_buffers);
316     return vdpau_error(status);
317 }
318
319 #if CONFIG_MPEG1_VDPAU_HWACCEL || \
320     CONFIG_MPEG2_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL || \
321     CONFIG_VC1_VDPAU_HWACCEL   || CONFIG_WMV3_VDPAU_HWACCEL
322 int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx)
323 {
324     MpegEncContext *s = avctx->priv_data;
325     Picture *pic = s->current_picture_ptr;
326     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
327     int val;
328
329     val = ff_vdpau_common_end_frame(avctx, pic->f, pic_ctx);
330     if (val < 0)
331         return val;
332
333     ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
334     return 0;
335 }
336 #endif
337
338 int ff_vdpau_add_buffer(struct vdpau_picture_context *pic_ctx,
339                         const uint8_t *buf, uint32_t size)
340 {
341     VdpBitstreamBuffer *buffers = pic_ctx->bitstream_buffers;
342
343     buffers = av_fast_realloc(buffers, &pic_ctx->bitstream_buffers_allocated,
344                               (pic_ctx->bitstream_buffers_used + 1) * sizeof(*buffers));
345     if (!buffers)
346         return AVERROR(ENOMEM);
347
348     pic_ctx->bitstream_buffers = buffers;
349     buffers += pic_ctx->bitstream_buffers_used++;
350
351     buffers->struct_version  = VDP_BITSTREAM_BUFFER_VERSION;
352     buffers->bitstream       = buf;
353     buffers->bitstream_bytes = size;
354     return 0;
355 }
356
357 #if FF_API_VDPAU_PROFILE
358 int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile)
359 {
360 #define PROFILE(prof)                      \
361 do {                                       \
362     *profile = VDP_DECODER_PROFILE_##prof; \
363     return 0;                              \
364 } while (0)
365
366     switch (avctx->codec_id) {
367     case AV_CODEC_ID_MPEG1VIDEO:               PROFILE(MPEG1);
368     case AV_CODEC_ID_MPEG2VIDEO:
369         switch (avctx->profile) {
370         case FF_PROFILE_MPEG2_MAIN:            PROFILE(MPEG2_MAIN);
371         case FF_PROFILE_MPEG2_SIMPLE:          PROFILE(MPEG2_SIMPLE);
372         default:                               return AVERROR(EINVAL);
373         }
374     case AV_CODEC_ID_H263:                     PROFILE(MPEG4_PART2_ASP);
375     case AV_CODEC_ID_MPEG4:
376         switch (avctx->profile) {
377         case FF_PROFILE_MPEG4_SIMPLE:          PROFILE(MPEG4_PART2_SP);
378         case FF_PROFILE_MPEG4_ADVANCED_SIMPLE: PROFILE(MPEG4_PART2_ASP);
379         default:                               return AVERROR(EINVAL);
380         }
381     case AV_CODEC_ID_H264:
382         switch (avctx->profile & ~FF_PROFILE_H264_INTRA) {
383         case FF_PROFILE_H264_BASELINE:         PROFILE(H264_BASELINE);
384         case FF_PROFILE_H264_CONSTRAINED_BASELINE:
385         case FF_PROFILE_H264_MAIN:             PROFILE(H264_MAIN);
386         case FF_PROFILE_H264_HIGH:             PROFILE(H264_HIGH);
387 #ifdef VDP_DECODER_PROFILE_H264_EXTENDED
388         case FF_PROFILE_H264_EXTENDED:         PROFILE(H264_EXTENDED);
389 #endif
390         default:                               return AVERROR(EINVAL);
391         }
392     case AV_CODEC_ID_WMV3:
393     case AV_CODEC_ID_VC1:
394         switch (avctx->profile) {
395         case FF_PROFILE_VC1_SIMPLE:            PROFILE(VC1_SIMPLE);
396         case FF_PROFILE_VC1_MAIN:              PROFILE(VC1_MAIN);
397         case FF_PROFILE_VC1_ADVANCED:          PROFILE(VC1_ADVANCED);
398         default:                               return AVERROR(EINVAL);
399         }
400     }
401     return AVERROR(EINVAL);
402 #undef PROFILE
403 }
404 #endif /* FF_API_VDPAU_PROFILE */
405
406 AVVDPAUContext *av_vdpau_alloc_context(void)
407 {
408     return av_mallocz(sizeof(AVVDPAUContext));
409 }
410
411 int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,
412                           VdpGetProcAddress *get_proc, unsigned flags)
413 {
414     VDPAUHWContext *hwctx;
415
416     if (flags & ~(AV_HWACCEL_FLAG_IGNORE_LEVEL|AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH))
417         return AVERROR(EINVAL);
418
419     if (av_reallocp(&avctx->hwaccel_context, sizeof(*hwctx)))
420         return AVERROR(ENOMEM);
421
422     hwctx = avctx->hwaccel_context;
423
424     memset(hwctx, 0, sizeof(*hwctx));
425     hwctx->context.decoder  = VDP_INVALID_HANDLE;
426     hwctx->device           = device;
427     hwctx->get_proc_address = get_proc;
428     hwctx->flags            = flags;
429     hwctx->reset            = 1;
430     return 0;
431 }
432
433 /* @}*/