This allows for users who derive devices to set options for the new device context they derive. The main use case of this is to allow users to enable extensions (such as surface drawing extensions) in Vulkan while deriving from the device their frames are on. That way, users don't need to write any initialization code themselves, since the Vulkan spec invalidates mixing instances, physical devices and active devices. Apart from Vulkan, other hwcontexts ignore the opts argument since they don't support options at all (or in VAAPI and OpenCL's case, options are currently only used for device selection, which device_derive overrides).
Unified · Split
| @@ -15,6 +15,9 @@ libavutil: 2017-10-21 · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | API changes, most recent first: |
| 17 | 17 | |
| 18 | +2020-05-23 - xxxxxxxxxx - lavu 56.48.100 - hwcontext.h | |
| 19 | + Add av_hwdevice_ctx_create_derived_opts. | |
| 20 | + | |
| 18 | 21 | 2020-05-23 - xxxxxxxxxx - lavu 56.47.100 - rational.h |
| 19 | 22 | Add av_gcd_q(). |
| 20 | 23 | |
| @@ -643,9 +643,10 @@ fail: · 642 unmodified lines | ||
| 643 | 643 | return ret; |
| 644 | 644 | } |
| 645 | 645 | |
| 646 | −int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, | |
| 647 | − enum AVHWDeviceType type, | |
| 648 | − AVBufferRef *src_ref, int flags) | |
| 646 | +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, | |
| 647 | + enum AVHWDeviceType type, | |
| 648 | + AVBufferRef *src_ref, | |
| 649 | + AVDictionary *options, int flags) | |
| 649 | 650 | { |
| 650 | 651 | AVBufferRef *dst_ref = NULL, *tmp_ref; |
| 651 | 652 | AVHWDeviceContext *dst_ctx, *tmp_ctx; |
| @@ -678,6 +679,7 @@ int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, · 26 unmodified lines | ||
| 678 | 679 | if (dst_ctx->internal->hw_type->device_derive) { |
| 679 | 680 | ret = dst_ctx->internal->hw_type->device_derive(dst_ctx, |
| 680 | 681 | tmp_ctx, |
| 682 | + options, | |
| 681 | 683 | flags); |
| 682 | 684 | if (ret == 0) { |
| 683 | 685 | dst_ctx->internal->source_device = av_buffer_ref(src_ref); |
| @@ -709,6 +711,14 @@ fail: · 25 unmodified lines | ||
| 709 | 711 | return ret; |
| 710 | 712 | } |
| 711 | 713 | |
| 714 | +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, | |
| 715 | + enum AVHWDeviceType type, | |
| 716 | + AVBufferRef *src_ref, int flags) | |
| 717 | +{ | |
| 718 | + return av_hwdevice_ctx_create_derived_opts(dst_ref_ptr, type, src_ref, | |
| 719 | + NULL, flags); | |
| 720 | +} | |
| 721 | + | |
| 712 | 722 | static void ff_hwframe_unmap(void *opaque, uint8_t *data) |
| 713 | 723 | { |
| 714 | 724 | HWMapDescriptor *hwmap = (HWMapDescriptor*)data; |
| @@ -328,6 +328,26 @@ int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx, · 327 unmodified lines | ||
| 328 | 328 | enum AVHWDeviceType type, |
| 329 | 329 | AVBufferRef *src_ctx, int flags); |
| 330 | 330 | |
| 331 | +/** | |
| 332 | + * Create a new device of the specified type from an existing device. | |
| 333 | + * | |
| 334 | + * This function performs the same action as av_hwdevice_ctx_create_derived, | |
| 335 | + * however, it is able to set options for the new device to be derived. | |
| 336 | + * | |
| 337 | + * @param dst_ctx On success, a reference to the newly-created | |
| 338 | + * AVHWDeviceContext. | |
| 339 | + * @param type The type of the new device to create. | |
| 340 | + * @param src_ctx A reference to an existing AVHWDeviceContext which will be | |
| 341 | + * used to create the new device. | |
| 342 | + * @param options Options for the new device to create, same format as in | |
| 343 | + * av_hwdevice_ctx_create. | |
| 344 | + * @param flags Currently unused; should be set to zero. | |
| 345 | + * @return Zero on success, a negative AVERROR code on failure. | |
| 346 | + */ | |
| 347 | +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx, | |
| 348 | + enum AVHWDeviceType type, | |
| 349 | + AVBufferRef *src_ctx, | |
| 350 | + AVDictionary *options, int flags); | |
| 331 | 351 | |
| 332 | 352 | /** |
| 333 | 353 | * Allocate an AVHWFramesContext tied to a given device context. |
| @@ -395,7 +395,7 @@ error: · 394 unmodified lines | ||
| 395 | 395 | } |
| 396 | 396 | |
| 397 | 397 | static int cuda_device_derive(AVHWDeviceContext *device_ctx, |
| 398 | − AVHWDeviceContext *src_ctx, | |
| 398 | + AVHWDeviceContext *src_ctx, AVDictionary *opts, | |
| 399 | 399 | int flags) { |
| 400 | 400 | AVCUDADeviceContext *hwctx = device_ctx->hwctx; |
| 401 | 401 | CudaFunctions *cu; |
| @@ -67,7 +67,8 @@ typedef struct HWContextType { · 66 unmodified lines | ||
| 67 | 67 | int (*device_create)(AVHWDeviceContext *ctx, const char *device, |
| 68 | 68 | AVDictionary *opts, int flags); |
| 69 | 69 | int (*device_derive)(AVHWDeviceContext *dst_ctx, |
| 70 | − AVHWDeviceContext *src_ctx, int flags); | |
| 70 | + AVHWDeviceContext *src_ctx, | |
| 71 | + AVDictionary *opts, int flags); | |
| 71 | 72 | |
| 72 | 73 | int (*device_init)(AVHWDeviceContext *ctx); |
| 73 | 74 | void (*device_uninit)(AVHWDeviceContext *ctx); |
| @@ -1194,7 +1194,7 @@ static int opencl_filter_drm_arm_device(AVHWDeviceContext *hwdev, · 1193 unmodified lines | ||
| 1194 | 1194 | #endif |
| 1195 | 1195 | |
| 1196 | 1196 | static int opencl_device_derive(AVHWDeviceContext *hwdev, |
| 1197 | − AVHWDeviceContext *src_ctx, | |
| 1197 | + AVHWDeviceContext *src_ctx, AVDictionary *opts, | |
| 1198 | 1198 | int flags) |
| 1199 | 1199 | { |
| 1200 | 1200 | int err; |
| @@ -1207,16 +1207,16 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, · 6 unmodified lines | ||
| 1207 | 1207 | // Surface mapping works via DRM PRIME fds with no special |
| 1208 | 1208 | // initialisation required in advance. This just finds the |
| 1209 | 1209 | // Beignet ICD by name. |
| 1210 | − AVDictionary *opts = NULL; | |
| 1210 | + AVDictionary *selector_opts = NULL; | |
| 1211 | 1211 | |
| 1212 | − err = av_dict_set(&opts, "platform_vendor", "Intel", 0); | |
| 1212 | + err = av_dict_set(&selector_opts, "platform_vendor", "Intel", 0); | |
| 1213 | 1213 | if (err >= 0) |
| 1214 | − err = av_dict_set(&opts, "platform_version", "beignet", 0); | |
| 1214 | + err = av_dict_set(&selector_opts, "platform_version", "beignet", 0); | |
| 1215 | 1215 | if (err >= 0) { |
| 1216 | 1216 | OpenCLDeviceSelector selector = { |
| 1217 | 1217 | .platform_index = -1, |
| 1218 | 1218 | .device_index = 0, |
| 1219 | − .context = opts, | |
| 1219 | + .context = selector_opts, | |
| 1220 | 1220 | .enumerate_platforms = &opencl_enumerate_platforms, |
| 1221 | 1221 | .filter_platform = &opencl_filter_platform, |
| 1222 | 1222 | .enumerate_devices = &opencl_enumerate_devices, |
| @@ -1224,7 +1224,7 @@ static int opencl_device_derive(AVHWDeviceContext *hwdev, · 1 unmodified line | ||
| 1224 | 1224 | }; |
| 1225 | 1225 | err = opencl_device_create_internal(hwdev, &selector, NULL); |
| 1226 | 1226 | } |
| 1227 | − av_dict_free(&opts); | |
| 1227 | + av_dict_free(&selector_opts); | |
| 1228 | 1228 | } |
| 1229 | 1229 | break; |
| 1230 | 1230 | #endif |
| @@ -1213,7 +1213,8 @@ fail: · 1212 unmodified lines | ||
| 1213 | 1213 | } |
| 1214 | 1214 | |
| 1215 | 1215 | static int qsv_device_derive(AVHWDeviceContext *ctx, |
| 1216 | − AVHWDeviceContext *child_device_ctx, int flags) | |
| 1216 | + AVHWDeviceContext *child_device_ctx, | |
| 1217 | + AVDictionary *opts, int flags) | |
| 1217 | 1218 | { |
| 1218 | 1219 | return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY, |
| 1219 | 1220 | child_device_ctx, flags); |
| @@ -1624,7 +1624,8 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, · 1623 unmodified lines | ||
| 1624 | 1624 | } |
| 1625 | 1625 | |
| 1626 | 1626 | static int vaapi_device_derive(AVHWDeviceContext *ctx, |
| 1627 | − AVHWDeviceContext *src_ctx, int flags) | |
| 1627 | + AVHWDeviceContext *src_ctx, | |
| 1628 | + AVDictionary *opts, int flags) | |
| 1628 | 1629 | { |
| 1629 | 1630 | #if HAVE_VAAPI_DRM |
| 1630 | 1631 | if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) { |
| @@ -950,7 +950,8 @@ static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device, · 949 unmodified lines | ||
| 950 | 950 | } |
| 951 | 951 | |
| 952 | 952 | static int vulkan_device_derive(AVHWDeviceContext *ctx, |
| 953 | − AVHWDeviceContext *src_ctx, int flags) | |
| 953 | + AVHWDeviceContext *src_ctx, | |
| 954 | + AVDictionary *opts, int flags) | |
| 954 | 955 | { |
| 955 | 956 | av_unused VulkanDeviceSelection dev_select = { 0 }; |
| 956 | 957 | |
| @@ -974,7 +975,7 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, · 17 unmodified lines | ||
| 974 | 975 | if (strstr(vendor, "AMD")) |
| 975 | 976 | dev_select.vendor_id = 0x1002; |
| 976 | 977 | |
| 977 | − return vulkan_device_create_internal(ctx, &dev_select, NULL, flags); | |
| 978 | + return vulkan_device_create_internal(ctx, &dev_select, opts, flags); | |
| 978 | 979 | } |
| 979 | 980 | #endif |
| 980 | 981 | case AV_HWDEVICE_TYPE_DRM: { |
| @@ -992,7 +993,7 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, · 11 unmodified lines | ||
| 992 | 993 | |
| 993 | 994 | drmFreeDevice(&drm_dev_info); |
| 994 | 995 | |
| 995 | − return vulkan_device_create_internal(ctx, &dev_select, NULL, flags); | |
| 996 | + return vulkan_device_create_internal(ctx, &dev_select, opts, flags); | |
| 996 | 997 | } |
| 997 | 998 | #endif |
| 998 | 999 | #if CONFIG_CUDA |
| @@ -1011,7 +1012,7 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, · 12 unmodified lines | ||
| 1011 | 1012 | |
| 1012 | 1013 | dev_select.has_uuid = 1; |
| 1013 | 1014 | |
| 1014 | − return vulkan_device_create_internal(ctx, &dev_select, NULL, flags); | |
| 1015 | + return vulkan_device_create_internal(ctx, &dev_select, opts, flags); | |
| 1015 | 1016 | } |
| 1016 | 1017 | #endif |
| 1017 | 1018 | default: |
| @@ -79,7 +79,7 @@ · 78 unmodified lines | ||
| 79 | 79 | */ |
| 80 | 80 | |
| 81 | 81 | #define LIBAVUTIL_VERSION_MAJOR 56 |
| 82 | −#define LIBAVUTIL_VERSION_MINOR 47 | |
| 82 | +#define LIBAVUTIL_VERSION_MINOR 48 | |
| 83 | 83 | #define LIBAVUTIL_VERSION_MICRO 100 |
| 84 | 84 | |
| 85 | 85 | #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ |