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.
---
libavcodec/vdpau.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-
libavcodec/vdpau.h | 9 ++++++
libavcodec/vdpau_internal.h | 26 +++++++++++++++++
3 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c
index d96b71c..2639272 100644
--- a/libavcodec/vdpau.c
+++ b/libavcodec/vdpau.c
@@ -22,7 +22,9 @@
*/
#include <limits.h>
+#include "libavutil/avassert.h"
#include "avcodec.h"
+#include "internal.h"
#include "h264.h"
#include "vc1.h"
@@ -62,6 +64,66 @@ static int ff_vdpau_error(VdpStatus status)
}
}
+static void *ff_vdpau_get_proc_address(AVCodecContext *avctx, VdpFuncId id)
+{
+ struct vdpau_context *vdctx = avctx->internal->hwaccel_priv_data;
+ void *ret;
+
+ av_assert0(vdctx->device != VDP_INVALID_HANDLE);
+
+ if (vdctx->get_proc_address(vdctx->device, id, &ret) != VDP_STATUS_OK)
+ ret = NULL;
+ return ret;
+}
+
+int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
+ int level, uint32_t surfaces)
+{
+ AVVDPAUContext *hwctx = avctx->hwaccel_context;
+ struct vdpau_context *vdctx = avctx->internal->hwaccel_priv_data;
+ VdpDecoderCreate *create;
+ VdpStatus status;
+ uint32_t width = (avctx->coded_width + 1) & ~1;
+ uint32_t height = (avctx->coded_height + 3) & ~3;
+
+ vdctx->device = hwctx->device;
+ vdctx->get_proc_address = hwctx->get_proc_address;
+
+ if (hwctx->device == VDP_INVALID_HANDLE) {
+ vdctx->decoder = hwctx->decoder;
+ vdctx->render = hwctx->render;
+ return 0; /* Decoder created by user */
+ }
+
+ create = ff_vdpau_get_proc_address(avctx, VDP_FUNC_ID_DECODER_CREATE);
+ vdctx->render = ff_vdpau_get_proc_address(avctx,
+ VDP_FUNC_ID_DECODER_RENDER);
+ if (create == NULL || vdctx->render == NULL)
+ return AVERROR(ENOSYS);
+
+ status = create(vdctx->device, profile, width, height, surfaces,
+ &vdctx->decoder);
+
+ return ff_vdpau_error(status);
+}
+
+int ff_vdpau_common_uninit(AVCodecContext *avctx)
+{
+ struct vdpau_context *vdctx = avctx->internal->hwaccel_priv_data;
+ VdpDecoderDestroy *destroy;
+ VdpStatus status;
+
+ if (vdctx->device == VDP_INVALID_HANDLE)
+ return 0; /* Decoder created and destroyed by user */
+
+ destroy = ff_vdpau_get_proc_address(avctx, VDP_FUNC_ID_DECODER_DESTROY);
+ if (destroy == NULL)
+ return AVERROR(ENOSYS);
+
+ status = destroy(vdctx->decoder);
+ return ff_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)
@@ -170,7 +232,12 @@ do { \
AVVDPAUContext *av_vdpau_alloc_context(void)
{
- return av_mallocz(sizeof(AVVDPAUContext));
+ AVVDPAUContext *hwctx = av_mallocz(sizeof(AVVDPAUContext));
+ if (!hwctx)
+ return NULL;
+
+ hwctx->device = VDP_INVALID_HANDLE;
+ return hwctx;
}
/* @}*/
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index 75cb1bf..b246768 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -128,6 +128,15 @@ typedef struct AVVDPAUContext {
attribute_deprecated
VdpBitstreamBuffer *bitstream_buffers;
#endif
+ /*****************************************************************
+ * No fields below this line are part of the public API. They
+ * may not be used outside of libavcodec and can be changed and
+ * removed at will.
+ * No new public fields will be added to this structure.
+ *****************************************************************
+ */
+ VdpDevice device;
+ VdpGetProcAddress *get_proc_address;
} AVVDPAUContext;
/**
diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h
index 3f55ee7..cefc0a1 100644
--- a/libavcodec/vdpau_internal.h
+++ b/libavcodec/vdpau_internal.h
@@ -48,6 +48,28 @@ union AVVDPAUPictureInfo {
#include "vdpau.h"
#endif
+struct vdpau_context {
+ /**
+ * VDPAU device handle
+ */
+ VdpDevice device;
+
+ /**
+ * VDPAU decoder handle
+ */
+ VdpDecoder decoder;
+
+ /**
+ * VDPAU device driver
+ */
+ VdpGetProcAddress *get_proc_address;
+
+ /**
+ * VDPAU decoder render callback
+ */
+ VdpDecoderRender *render;
+};
+
struct vdpau_picture_context {
/**
* VDPAU picture information.
@@ -70,6 +92,10 @@ struct vdpau_picture_context {
VdpBitstreamBuffer *bitstream_buffers;
};
+int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
+ int level, uint32_t surfaces);
+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,
--
1.8.1.5
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel