diff options
author | Mark Thompson <sw@jkqxz.net> | 2017-03-04 23:57:28 +0000 |
---|---|---|
committer | Mark Thompson <sw@jkqxz.net> | 2017-06-14 22:25:57 +0100 |
commit | b22172f6f3530b8bd9d1d2c38a31b1e9c3729e42 (patch) | |
tree | 481a74e995b2bd82dba7eebee805eac5e2708598 /libavutil/hwcontext.c | |
parent | 92bd08974541611731b2d58723826ea26ecbe47d (diff) | |
download | ffmpeg-b22172f6f3530b8bd9d1d2c38a31b1e9c3729e42.tar.gz |
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 b266ad56fe0e4ce5bb70118ba2e2b1dabfaf76ce)
Diffstat (limited to 'libavutil/hwcontext.c')
-rw-r--r-- | libavutil/hwcontext.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 8d50a32b84..86d290d322 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -68,6 +68,8 @@ static void hwdevice_ctx_free(void *opaque, uint8_t *data) if (ctx->free) ctx->free(ctx); + av_buffer_unref(&ctx->internal->source_device); + av_freep(&ctx->hwctx); av_freep(&ctx->internal->priv); av_freep(&ctx->internal); @@ -538,6 +540,69 @@ fail: 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) { HWMapDescriptor *hwmap = (HWMapDescriptor*)data; |