From ce083282f0a8b7d63c4047c30b7bac498f9806dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sat, 4 Oct 2014 16:55:04 +0300 Subject: [PATCH] vdpau: common support for managing the VdpDecoder in avcodec Using the not so new init and uninit callbacks, avcodec can now take care of creating and destroying the VDPAU decoder instance. The application is still responsible for creating the VDPAU device and allocating video surfaces - this is necessary to keep video surfaces on the GPU all the way to the output. But the application will no longer needs to care about any codec-specific aspects. Signed-off-by: Anton Khirnov --- libavcodec/vdpau.c | 64 +++++++++++++++++++++++++++++++++++++ libavcodec/vdpau_internal.h | 32 +++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index 0a4b7965f7..48bc3653c9 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -22,7 +22,9 @@ */ #include +#include "libavutil/avassert.h" #include "avcodec.h" +#include "internal.h" #include "h264.h" #include "vc1.h" @@ -62,6 +64,68 @@ static int vdpau_error(VdpStatus status) } } +int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, + int level) +{ + VDPAUHWContext *hwctx = avctx->hwaccel_context; + VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data; + VdpDecoderCreate *create; + void *func; + VdpStatus status; + /* See vdpau/vdpau.h for alignment constraints. */ + uint32_t width = (avctx->coded_width + 1) & ~1; + uint32_t height = (avctx->coded_height + 3) & ~3; + + if (hwctx->context.decoder != VDP_INVALID_HANDLE) { + vdctx->decoder = hwctx->context.decoder; + vdctx->render = hwctx->context.render; + vdctx->device = VDP_INVALID_HANDLE; + return 0; /* Decoder created by user */ + } + + vdctx->device = hwctx->device; + vdctx->get_proc_address = hwctx->get_proc_address; + + status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_CREATE, + &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + create = func; + + status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_RENDER, + &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + vdctx->render = func; + + status = create(vdctx->device, profile, width, height, avctx->refs, + &vdctx->decoder); + return vdpau_error(status); +} + +int ff_vdpau_common_uninit(AVCodecContext *avctx) +{ + VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data; + VdpDecoderDestroy *destroy; + void *func; + VdpStatus status; + + if (vdctx->device == VDP_INVALID_HANDLE) + return 0; /* Decoder created and destroyed by user */ + + status = vdctx->get_proc_address(vdctx->device, + VDP_FUNC_ID_DECODER_DESTROY, &func); + if (status != VDP_STATUS_OK) + return vdpau_error(status); + else + destroy = func; + + status = destroy(vdctx->decoder); + return vdpau_error(status); +} + int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx, av_unused const uint8_t *buffer, av_unused uint32_t size) diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h index 3f55ee7dc9..94fa9aae89 100644 --- a/libavcodec/vdpau_internal.h +++ b/libavcodec/vdpau_internal.h @@ -48,6 +48,34 @@ union AVVDPAUPictureInfo { #include "vdpau.h" #endif +typedef struct VDPAUHWContext { + AVVDPAUContext context; + VdpDevice device; + VdpGetProcAddress *get_proc_address; +} VDPAUHWContext; + +typedef struct VDPAUContext { + /** + * VDPAU device handle + */ + VdpDevice device; + + /** + * VDPAU decoder handle + */ + VdpDecoder decoder; + + /** + * VDPAU device driver + */ + VdpGetProcAddress *get_proc_address; + + /** + * VDPAU decoder render callback + */ + VdpDecoderRender *render; +} VDPAUContext; + struct vdpau_picture_context { /** * VDPAU picture information. @@ -70,6 +98,10 @@ struct vdpau_picture_context { VdpBitstreamBuffer *bitstream_buffers; }; +int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, + int level); +int ff_vdpau_common_uninit(AVCodecContext *avctx); + int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic, const uint8_t *buffer, uint32_t size); int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame,