Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavutil/hwcontext.c38
-rw-r--r--libavutil/hwcontext.h1
-rw-r--r--libavutil/hwcontext_internal.h6
-rw-r--r--libavutil/hwcontext_qsv.c13
4 files changed, 55 insertions, 3 deletions
diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 31c7840dba..1a50635018 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -122,6 +122,7 @@ static const AVClass hwdevice_ctx_class = {
static void hwdevice_ctx_free(void *opaque, uint8_t *data)
{
AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
+ int i;
/* uninit might still want access the hw context and the user
* free() callback might destroy it, so uninit has to be called first */
@@ -132,6 +133,8 @@ static void hwdevice_ctx_free(void *opaque, uint8_t *data)
ctx->free(ctx);
av_buffer_unref(&ctx->internal->source_device);
+ for (i = 0; i < AV_HWDEVICE_TYPE_NB; i++)
+ av_buffer_unref(&ctx->internal->derived_devices[i]);
av_freep(&ctx->hwctx);
av_freep(&ctx->internal->priv);
@@ -643,6 +646,26 @@ fail:
return ret;
}
+static AVBufferRef* find_derived_hwdevice_ctx(AVBufferRef *src_ref, enum AVHWDeviceType type)
+{
+ AVBufferRef *tmp_ref;
+ AVHWDeviceContext *src_ctx;
+ int i;
+
+ src_ctx = (AVHWDeviceContext*)src_ref->data;
+ if (src_ctx->type == type)
+ return src_ref;
+
+ for (i = 0; i < AV_HWDEVICE_TYPE_NB; i++)
+ if (src_ctx->internal->derived_devices[i]) {
+ tmp_ref = find_derived_hwdevice_ctx(src_ctx->internal->derived_devices[i], type);
+ if (tmp_ref)
+ return tmp_ref;
+ }
+
+ return NULL;
+}
+
int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr,
enum AVHWDeviceType type,
AVBufferRef *src_ref,
@@ -666,6 +689,16 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr,
tmp_ref = tmp_ctx->internal->source_device;
}
+ tmp_ref = find_derived_hwdevice_ctx(src_ref, type);
+ if (tmp_ref) {
+ dst_ref = av_buffer_ref(tmp_ref);
+ if (!dst_ref) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ goto done;
+ }
+
dst_ref = av_hwdevice_ctx_alloc(type);
if (!dst_ref) {
ret = AVERROR(ENOMEM);
@@ -687,6 +720,11 @@ int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr,
ret = AVERROR(ENOMEM);
goto fail;
}
+ tmp_ctx->internal->derived_devices[type] = av_buffer_ref(dst_ref);
+ if (!tmp_ctx->internal->derived_devices[type]) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
ret = av_hwdevice_ctx_init(dst_ref);
if (ret < 0)
goto fail;
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 04d19d89c2..0979fa2715 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -37,6 +37,7 @@ enum AVHWDeviceType {
AV_HWDEVICE_TYPE_OPENCL,
AV_HWDEVICE_TYPE_MEDIACODEC,
AV_HWDEVICE_TYPE_VULKAN,
+ AV_HWDEVICE_TYPE_NB, ///< number of hw device types, not part of API/ABI.
};
typedef struct AVHWDeviceInternal AVHWDeviceInternal;
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
index e6266494ac..f6fb67c491 100644
--- a/libavutil/hwcontext_internal.h
+++ b/libavutil/hwcontext_internal.h
@@ -109,6 +109,12 @@ struct AVHWDeviceInternal {
* context it was derived from.
*/
AVBufferRef *source_device;
+
+ /**
+ * An array of reference to device contexts which
+ * were derived from this device.
+ */
+ AVBufferRef *derived_devices[AV_HWDEVICE_TYPE_NB];
};
struct AVHWFramesInternal {
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 853fb7f60d..91457c9c9e 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -274,7 +274,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx)
av_buffer_unref(&s->child_frames_ref);
}
-static void qsv_pool_release_dummy(void *opaque, uint8_t *data)
+static void qsv_release_dummy(void *opaque, uint8_t *data)
{
}
@@ -287,7 +287,7 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size)
if (s->nb_surfaces_used < hwctx->nb_surfaces) {
s->nb_surfaces_used++;
return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1),
- sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0);
+ sizeof(*hwctx->surfaces), qsv_release_dummy, NULL, 0);
}
return NULL;
@@ -1596,8 +1596,15 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
impl = choose_implementation(device, child_device_type);
+ ret = qsv_device_derive_from_child(ctx, impl, child_device, 0);
+ if (ret >= 0) {
+ ctx->internal->source_device = av_buffer_ref(priv->child_device_ctx);
+ child_device->internal->derived_devices[ctx->type] = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), qsv_release_dummy, ctx, 0);
+ if (!child_device->internal->derived_devices[ctx->type])
+ return AVERROR(ENOMEM);
+ }
- return qsv_device_derive_from_child(ctx, impl, child_device, 0);
+ return ret;
}
const HWContextType ff_hwcontext_type_qsv = {