Commit b22172f6 authored by Mark Thompson's avatar Mark Thompson

hwcontext: Add device derivation

Creates a new device context from another of a different type which
refers to the same underlying hardware.

(cherry picked from commit b266ad56)
parent 92bd0897
...@@ -15,6 +15,9 @@ libavutil: 2015-08-28 ...@@ -15,6 +15,9 @@ libavutil: 2015-08-28
API changes, most recent first: API changes, most recent first:
2017-06-14 - xxxxxxx - lavu 55.64.100 - hwcontext.h
Add av_hwdevice_ctx_create_derived().
2017-05-15 - xxxxxxxxxx - lavc 57.96.100 - avcodec.h 2017-05-15 - xxxxxxxxxx - lavc 57.96.100 - avcodec.h
VideoToolbox hardware-accelerated decoding now supports the new hwaccel API, VideoToolbox hardware-accelerated decoding now supports the new hwaccel API,
which can create the decoder context and allocate hardware frames automatically. which can create the decoder context and allocate hardware frames automatically.
......
...@@ -68,6 +68,8 @@ static void hwdevice_ctx_free(void *opaque, uint8_t *data) ...@@ -68,6 +68,8 @@ static void hwdevice_ctx_free(void *opaque, uint8_t *data)
if (ctx->free) if (ctx->free)
ctx->free(ctx); ctx->free(ctx);
av_buffer_unref(&ctx->internal->source_device);
av_freep(&ctx->hwctx); av_freep(&ctx->hwctx);
av_freep(&ctx->internal->priv); av_freep(&ctx->internal->priv);
av_freep(&ctx->internal); av_freep(&ctx->internal);
...@@ -538,6 +540,69 @@ fail: ...@@ -538,6 +540,69 @@ fail:
return ret; return ret;
} }
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr,
enum AVHWDeviceType type,
AVBufferRef *src_ref, int flags)
{
AVBufferRef *dst_ref = NULL, *tmp_ref;
AVHWDeviceContext *dst_ctx, *tmp_ctx;
int ret = 0;
tmp_ref = src_ref;
while (tmp_ref) {
tmp_ctx = (AVHWDeviceContext*)tmp_ref->data;
if (tmp_ctx->type == type) {
dst_ref = av_buffer_ref(tmp_ref);
if (!dst_ref) {
ret = AVERROR(ENOMEM);
goto fail;
}
goto done;
}
tmp_ref = tmp_ctx->internal->source_device;
}
dst_ref = av_hwdevice_ctx_alloc(type);
if (!dst_ref) {
ret = AVERROR(ENOMEM);
goto fail;
}
dst_ctx = (AVHWDeviceContext*)dst_ref->data;
tmp_ref = src_ref;
while (tmp_ref) {
tmp_ctx = (AVHWDeviceContext*)tmp_ref->data;
if (dst_ctx->internal->hw_type->device_derive) {
ret = dst_ctx->internal->hw_type->device_derive(dst_ctx,
tmp_ctx,
flags);
if (ret == 0) {
dst_ctx->internal->source_device = av_buffer_ref(src_ref);
if (!dst_ctx->internal->source_device) {
ret = AVERROR(ENOMEM);
goto fail;
}
goto done;
}
if (ret != AVERROR(ENOSYS))
goto fail;
}
tmp_ref = tmp_ctx->internal->source_device;
}
ret = AVERROR(ENOSYS);
goto fail;
done:
*dst_ref_ptr = dst_ref;
return 0;
fail:
av_buffer_unref(&dst_ref);
*dst_ref_ptr = NULL;
return ret;
}
static void ff_hwframe_unmap(void *opaque, uint8_t *data) static void ff_hwframe_unmap(void *opaque, uint8_t *data)
{ {
HWMapDescriptor *hwmap = (HWMapDescriptor*)data; HWMapDescriptor *hwmap = (HWMapDescriptor*)data;
......
...@@ -270,6 +270,32 @@ int av_hwdevice_ctx_init(AVBufferRef *ref); ...@@ -270,6 +270,32 @@ int av_hwdevice_ctx_init(AVBufferRef *ref);
int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type, int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type,
const char *device, AVDictionary *opts, int flags); const char *device, AVDictionary *opts, int flags);
/**
* Create a new device of the specified type from an existing device.
*
* If the source device is a device of the target type or was originally
* derived from such a device (possibly through one or more intermediate
* devices of other types), then this will return a reference to the
* existing device of the same type as is requested.
*
* Otherwise, it will attempt to derive a new device from the given source
* device. If direct derivation to the new type is not implemented, it will
* attempt the same derivation from each ancestor of the source device in
* turn looking for an implemented derivation method.
*
* @param dst_ctx On success, a reference to the newly-created
* AVHWDeviceContext.
* @param type The type of the new device to create.
* @param src_ctx A reference to an existing AVHWDeviceContext which will be
* used to create the new device.
* @param flags Currently unused; should be set to zero.
* @return Zero on success, a negative AVERROR code on failure.
*/
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx,
enum AVHWDeviceType type,
AVBufferRef *src_ctx, int flags);
/** /**
* Allocate an AVHWFramesContext tied to a given device context. * Allocate an AVHWFramesContext tied to a given device context.
* *
......
...@@ -66,6 +66,8 @@ typedef struct HWContextType { ...@@ -66,6 +66,8 @@ typedef struct HWContextType {
int (*device_create)(AVHWDeviceContext *ctx, const char *device, int (*device_create)(AVHWDeviceContext *ctx, const char *device,
AVDictionary *opts, int flags); AVDictionary *opts, int flags);
int (*device_derive)(AVHWDeviceContext *dst_ctx,
AVHWDeviceContext *src_ctx, int flags);
int (*device_init)(AVHWDeviceContext *ctx); int (*device_init)(AVHWDeviceContext *ctx);
void (*device_uninit)(AVHWDeviceContext *ctx); void (*device_uninit)(AVHWDeviceContext *ctx);
...@@ -95,6 +97,12 @@ typedef struct HWContextType { ...@@ -95,6 +97,12 @@ typedef struct HWContextType {
struct AVHWDeviceInternal { struct AVHWDeviceInternal {
const HWContextType *hw_type; const HWContextType *hw_type;
void *priv; void *priv;
/**
* For a derived device, a reference to the original device
* context it was derived from.
*/
AVBufferRef *source_device;
}; };
struct AVHWFramesInternal { struct AVHWFramesInternal {
......
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
#define LIBAVUTIL_VERSION_MAJOR 55 #define LIBAVUTIL_VERSION_MAJOR 55
#define LIBAVUTIL_VERSION_MINOR 63 #define LIBAVUTIL_VERSION_MINOR 64
#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment