#include "pixdesc.h"
#include "pixfmt.h"
-static const HWContextType *hw_table[] = {
+static const HWContextType * const hw_table[] = {
#if CONFIG_CUDA
&ff_hwcontext_type_cuda,
#endif
+#if CONFIG_D3D11VA
+ &ff_hwcontext_type_d3d11va,
+#endif
+#if CONFIG_LIBDRM
+ &ff_hwcontext_type_drm,
+#endif
#if CONFIG_DXVA2
&ff_hwcontext_type_dxva2,
#endif
#endif
#if CONFIG_VDPAU
&ff_hwcontext_type_vdpau,
+#endif
+#if CONFIG_VIDEOTOOLBOX
+ &ff_hwcontext_type_videotoolbox,
#endif
NULL,
};
+static const char *const hw_type_names[] = {
+ [AV_HWDEVICE_TYPE_CUDA] = "cuda",
+ [AV_HWDEVICE_TYPE_DRM] = "drm",
+ [AV_HWDEVICE_TYPE_DXVA2] = "dxva2",
+ [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va",
+ [AV_HWDEVICE_TYPE_QSV] = "qsv",
+ [AV_HWDEVICE_TYPE_VAAPI] = "vaapi",
+ [AV_HWDEVICE_TYPE_VDPAU] = "vdpau",
+ [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox",
+};
+
+enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
+{
+ int type;
+ for (type = 0; type < FF_ARRAY_ELEMS(hw_type_names); type++) {
+ if (hw_type_names[type] && !strcmp(hw_type_names[type], name))
+ return type;
+ }
+ return AV_HWDEVICE_TYPE_NONE;
+}
+
+const char *av_hwdevice_get_type_name(enum AVHWDeviceType type)
+{
+ if (type >= 0 && type < FF_ARRAY_ELEMS(hw_type_names))
+ return hw_type_names[type];
+ else
+ return NULL;
+}
+
+enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev)
+{
+ enum AVHWDeviceType next;
+ int i, set = 0;
+ for (i = 0; hw_table[i]; i++) {
+ if (prev != AV_HWDEVICE_TYPE_NONE && hw_table[i]->type <= prev)
+ continue;
+ if (!set || hw_table[i]->type < next) {
+ next = hw_table[i]->type;
+ set = 1;
+ }
+ }
+ return set ? next : AV_HWDEVICE_TYPE_NONE;
+}
+
static const AVClass hwdevice_ctx_class = {
.class_name = "AVHWDeviceContext",
.item_name = av_default_item_name,
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);
// and map the frame immediately.
AVFrame *src_frame;
+ frame->format = ctx->format;
+ frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
+ if (!frame->hw_frames_ctx)
+ return AVERROR(ENOMEM);
+
src_frame = av_frame_alloc();
if (!src_frame)
return AVERROR(ENOMEM);
if (ret < 0)
return ret;
- ret = av_hwframe_map(frame, src_frame, 0);
+ ret = av_hwframe_map(frame, src_frame,
+ ctx->internal->source_allocation_map_flags);
if (ret) {
av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived "
"frame context: %d.\n", 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)
{
HWMapDescriptor *hwmap = (HWMapDescriptor*)data;
goto fail;
}
- ret = av_hwframe_ctx_init(dst_ref);
+ dst->internal->source_allocation_map_flags =
+ flags & (AV_HWFRAME_MAP_READ |
+ AV_HWFRAME_MAP_WRITE |
+ AV_HWFRAME_MAP_OVERWRITE |
+ AV_HWFRAME_MAP_DIRECT);
+
+ ret = AVERROR(ENOSYS);
+ if (src->internal->hw_type->frames_derive_from)
+ ret = src->internal->hw_type->frames_derive_from(dst, src, flags);
+ if (ret == AVERROR(ENOSYS) &&
+ dst->internal->hw_type->frames_derive_to)
+ ret = dst->internal->hw_type->frames_derive_to(dst, src, flags);
+ if (ret == AVERROR(ENOSYS))
+ ret = 0;
if (ret)
goto fail;