diff options
author | Mark Thompson <sw@jkqxz.net> | 2017-03-04 23:57:28 +0000 |
---|---|---|
committer | Mark Thompson <sw@jkqxz.net> | 2017-03-20 23:15:43 +0000 |
commit | b266ad56fe0e4ce5bb70118ba2e2b1dabfaf76ce (patch) | |
tree | 9ffc32c7d86e1c40ea8c4c343a8339b7d6387b48 /libavutil/hwcontext.c | |
parent | b864230c49089b087eef56988a3d6a784f6f9827 (diff) | |
download | ffmpeg-b266ad56fe0e4ce5bb70118ba2e2b1dabfaf76ce.tar.gz |
hwcontext: Add device derivation
Creates a new device context from another of a different type which
refers to the same underlying hardware.
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 608da68727..252dd32e38 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -65,6 +65,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); @@ -535,6 +537,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; |