Files
jellyfin-ffmpeg/debian/patches/0078-backport-fixes-for-vulkan-from-upstream.patch
T
2026-05-28 10:53:47 +08:00

510 lines
22 KiB
Diff

Index: FFmpeg/libavcodec/vulkan_encode.c
===================================================================
--- FFmpeg.orig/libavcodec/vulkan_encode.c
+++ FFmpeg/libavcodec/vulkan_encode.c
@@ -772,14 +772,6 @@ av_cold int ff_vulkan_encode_init(AVCode
return AVERROR(EINVAL);
}
- if ((ctx->enc_caps.supportedEncodeFeedbackFlags & feedback_flags) !=
- feedback_flags) {
- av_log (avctx, AV_LOG_ERROR,
- "Driver does not support required encode feedback flags "
- "(BUFFER_OFFSET and BYTES_WRITTEN).\n");
- return AVERROR(ENOTSUP);
- }
-
ctx->base.op = &vulkan_base_encode_ops;
ctx->codec = codec;
@@ -881,6 +873,14 @@ av_cold int ff_vulkan_encode_init(AVCode
return AVERROR_EXTERNAL;
}
+ if ((ctx->enc_caps.supportedEncodeFeedbackFlags & feedback_flags) !=
+ feedback_flags) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Driver does not support required encode feedback flags "
+ "(BUFFER_OFFSET and BYTES_WRITTEN).\n");
+ return AVERROR(ENOTSUP);
+ }
+
err = init_rc(avctx, ctx);
if (err < 0)
return err;
Index: FFmpeg/libavcodec/vulkan_encode.h
===================================================================
--- FFmpeg.orig/libavcodec/vulkan_encode.h
+++ FFmpeg/libavcodec/vulkan_encode.h
@@ -203,7 +203,7 @@ typedef struct FFVulkanEncodeContext {
#define VULKAN_ENCODE_COMMON_OPTIONS \
{ "qp", "Use an explicit constant quantizer for the whole stream", OFFSET(common.opts.qp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, FLAGS }, \
- { "quality", "Set encode quality (trades off against speed, higher is faster)", OFFSET(common.opts.quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, \
+ { "quality", "Set encode quality (trades off against speed, higher is slower)", OFFSET(common.opts.quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, \
{ "rc_mode", "Select rate control type", OFFSET(common.opts.rc_mode), AV_OPT_TYPE_INT, { .i64 = FF_VK_RC_MODE_AUTO }, 0, FF_VK_RC_MODE_AUTO, FLAGS, "rc_mode" }, \
{ "auto", "Choose mode automatically based on parameters", 0, AV_OPT_TYPE_CONST, { .i64 = FF_VK_RC_MODE_AUTO }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
{ "driver", "Driver-specific rate control", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
Index: FFmpeg/libavcodec/vulkan_encode_h265.c
===================================================================
--- FFmpeg.orig/libavcodec/vulkan_encode_h265.c
+++ FFmpeg/libavcodec/vulkan_encode_h265.c
@@ -1595,23 +1595,21 @@ static av_cold int vulkan_encode_h265_in
av_log(avctx, AV_LOG_VERBOSE, " Capability flags:\n");
av_log(avctx, AV_LOG_VERBOSE, " hdr_compliance: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " pred_weight_table_generated: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " row_unaligned_slice: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " different_slice_type: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_SEGMENT_TYPE_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " b_frame_in_l0_list: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " b_frame_in_l1_list: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " per_pict_type_min_max_qp: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " per_slice_constant_qp: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR));
- av_log(avctx, AV_LOG_VERBOSE, " generate_prefix_nalu: %i\n",
- !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR));
+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_KHR));
av_log(avctx, AV_LOG_VERBOSE, " Capabilities:\n");
av_log(avctx, AV_LOG_VERBOSE, " maxLevelIdc: %i\n",
Index: FFmpeg/libavutil/hwcontext_vulkan.c
===================================================================
--- FFmpeg.orig/libavutil/hwcontext_vulkan.c
+++ FFmpeg/libavutil/hwcontext_vulkan.c
@@ -190,11 +190,18 @@ typedef struct VulkanFramesPriv {
/* Properties for DRM modifier for each plane in the image */
VkDrmFormatModifierPropertiesEXT drm_format_modifier_properties[5];
+
+ /* Set when physical device reports DEDICATED_ONLY for DMA-BUF export (try_export_flags) */
+ int export_requires_dedicated;
} VulkanFramesPriv;
typedef struct AVVkFrameInternal {
pthread_mutex_t update_mutex;
+ /* Binary semaphore for SYNC_FD export at DRM map time. Created once lazily,
+ * re-signaled each time via a submit in vulkan_map_to_drm. */
+ VkSemaphore drm_sync_sem;
+
#if CONFIG_CUDA
/* Importing external memory into cuda is really expensive so we keep the
* memory imported all the time */
@@ -2370,7 +2377,7 @@ static int alloc_mem(AVHWDeviceContext *
return 0;
}
-static void vulkan_free_internal(AVVkFrame *f)
+static void vulkan_free_internal(VulkanDevicePriv *p, AVVkFrame *f)
{
av_unused AVVkFrameInternal *internal = f->internal;
@@ -2402,6 +2409,10 @@ static void vulkan_free_internal(AVVkFra
}
#endif
+ if (internal->drm_sync_sem != VK_NULL_HANDLE)
+ p->vkctx.vkfn.DestroySemaphore(p->p.act_dev, internal->drm_sync_sem,
+ p->p.alloc);
+
pthread_mutex_destroy(&internal->update_mutex);
av_freep(&f->internal);
}
@@ -2429,7 +2440,7 @@ static void vulkan_frame_free(AVHWFrames
vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
}
- vulkan_free_internal(f);
+ vulkan_free_internal(p, f);
for (int i = 0; i < nb_images; i++) {
vk->DestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc);
@@ -2476,6 +2487,10 @@ static int alloc_bind_mem(AVHWFramesCont
vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req);
+ av_log(hwfc, AV_LOG_TRACE,
+ "plane %d: driver reports prefersDedicatedAllocation=%i requiresDedicatedAllocation=%i\n",
+ img_cnt, ded_req.prefersDedicatedAllocation, ded_req.requiresDedicatedAllocation);
+
if (f->tiling == VK_IMAGE_TILING_LINEAR)
req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size,
p->props.properties.limits.minMemoryMapAlignment);
@@ -2483,6 +2498,8 @@ static int alloc_bind_mem(AVHWFramesCont
/* In case the implementation prefers/requires dedicated allocation */
use_ded_mem = ded_req.prefersDedicatedAllocation |
ded_req.requiresDedicatedAllocation;
+ if (((VulkanFramesPriv *)hwfc->hwctx)->export_requires_dedicated)
+ use_ded_mem = 1;
if (use_ded_mem)
ded_alloc.image = f->img[img_cnt];
@@ -2854,7 +2871,8 @@ static void try_export_flags(AVHWFramesC
.type = VK_IMAGE_TYPE_2D,
.tiling = hwctx->tiling,
.usage = hwctx->usage,
- .flags = VK_IMAGE_CREATE_ALIAS_BIT,
+ .flags = (hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && has_mods) ?
+ (hwctx->img_flags) : (VkImageCreateFlags)(VK_IMAGE_CREATE_ALIAS_BIT),
};
nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1;
@@ -2865,9 +2883,18 @@ static void try_export_flags(AVHWFramesC
ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
&pinfo, &props);
+ if (has_mods)
+ av_log(hwfc, AV_LOG_VERBOSE, "GetPhysicalDeviceImageFormatProperties2: mod[%d]=0x%llx -> %s\n",
+ i, (unsigned long long)phy_dev_mod_info.drmFormatModifier,
+ ret == VK_SUCCESS ? "OK" : "FAIL");
if (ret == VK_SUCCESS) {
*iexp |= exp;
*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
+ if (exp == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) {
+ VulkanFramesPriv *fp = hwfc->hwctx;
+ fp->export_requires_dedicated = !!(eprops.externalMemoryProperties.externalMemoryFeatures &
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
+ }
}
}
}
@@ -2895,7 +2922,8 @@ static AVBufferRef *vulkan_pool_alloc(vo
? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
: VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT);
#else
- if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY)
+ if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) &&
+ (hwctx->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
try_export_flags(hwfc, &eiinfo.handleTypes, &e,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
@@ -2914,8 +2942,10 @@ static AVBufferRef *vulkan_pool_alloc(vo
err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
hwctx->nb_layers,
eiinfo.handleTypes ? &eiinfo : hwctx->create_pnext);
- if (err)
+ if (err) {
+ av_log(hwfc, AV_LOG_ERROR, "vulkan_pool_alloc failed: create_frame failed: %d\n", err);
return NULL;
+ }
err = alloc_bind_mem(hwfc, f, eminfo, sizeof(*eminfo));
if (err)
@@ -2943,6 +2973,7 @@ static AVBufferRef *vulkan_pool_alloc(vo
return avbuf;
fail:
+ av_log(hwfc, AV_LOG_ERROR, "vulkan_pool_alloc failed with error %d\n", err);
vulkan_frame_free(hwfc, f);
return NULL;
}
@@ -3044,7 +3075,14 @@ static int vulkan_frames_init(AVHWFrames
}
/* Lone DPB images do not need additional flags. */
- if (!is_lone_dpb) {
+ /* With DRM modifier + video profile the caller has already chosen a valid
+ * usage/img_flags/chain; do not add usage or img_flags (supported_usage does
+ * not consider the actual modifier or video profile). */
+ int drm_mod_with_video = (hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
+ ff_vk_find_struct(hwctx->create_pnext,
+ VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR));
+
+ if (!is_lone_dpb && !drm_mod_with_video) {
/* Image usage flags */
hwctx->usage |= supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
@@ -3163,8 +3201,8 @@ static int vulkan_frames_init(AVHWFrames
}
vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp);
- for (uint32_t i = 0; i < modp.drmFormatModifierCount; ++i) {
- VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[i];
+ for (uint32_t j = 0; j < modp.drmFormatModifierCount; ++j) {
+ VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[j];
if (m->drmFormatModifier == drm_mod.drmFormatModifier) {
mod_props = m;
break;
@@ -3502,7 +3540,7 @@ static int vulkan_map_from_drm_frame_des
&f->flags, &f->mem[i]);
if (err) {
close(idesc.fd);
- return err;
+ goto fail;
}
f->size[i] = req2.memoryRequirements.size;
@@ -3969,7 +4007,7 @@ static int vulkan_export_to_cuda(AVHWFra
return 0;
fail:
- vulkan_free_internal(dst_f);
+ vulkan_free_internal(p, dst_f);
return err;
}
@@ -3980,6 +4018,7 @@ static int vulkan_transfer_data_from_cud
CUcontext dummy;
AVVkFrame *dst_f;
AVVkFrameInternal *dst_int;
+ VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
VulkanFramesPriv *fp = hwfc->hwctx;
const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
@@ -4058,7 +4097,7 @@ static int vulkan_transfer_data_from_cud
fail:
CHECK_CU(cu->cuCtxPopCurrent(&dummy));
- vulkan_free_internal(dst_f);
+ vulkan_free_internal(p, dst_f);
av_buffer_unref(&dst->buf[0]);
return err;
}
@@ -4128,6 +4167,72 @@ static VkImageAspectFlags plane_index_to
return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
}
+#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
+static int vulkan_drm_export_sync_fd(AVHWFramesContext *hwfc, AVVkFrame *f,
+ VulkanFramesPriv *fp, int nb_sems)
+{
+ int sync_fd = -1;
+ VkResult ret;
+ VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+ AVVulkanDeviceContext *hwctx = &p->p;
+ FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+ if (f->internal->drm_sync_sem == VK_NULL_HANDLE) {
+ VkExportSemaphoreCreateInfo exp_info = {
+ .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
+ .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
+ };
+ VkSemaphoreTypeCreateInfo type_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
+ .pNext = &exp_info,
+ .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
+ };
+ VkSemaphoreCreateInfo sem_create = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ .pNext = &type_info,
+ };
+ ret = vk->CreateSemaphore(hwctx->act_dev, &sem_create, hwctx->alloc,
+ &f->internal->drm_sync_sem);
+ if (ret != VK_SUCCESS) {
+ av_log(hwctx, AV_LOG_ERROR, "Failed to create DRM export semaphore: %s\n",
+ ff_vk_ret2str(ret));
+ return AVERROR_EXTERNAL;
+ }
+ }
+
+ /* Submit a lightweight exec that waits on the timeline semaphore
+ * (true last operation on the frame) and signals the binary semaphore,
+ * so any Vulkan frame can get a SYNC_FD regardless of origin. */
+ FFVkExecContext *exec = ff_vk_exec_get(&p->vkctx, &fp->compute_exec);
+ if (ff_vk_exec_start(&p->vkctx, exec) >= 0) {
+ for (int i = 0; i < nb_sems; i++)
+ ff_vk_exec_add_dep_wait_sem(&p->vkctx, exec, f->sem[i],
+ f->sem_value[i],
+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
+ ff_vk_exec_add_dep_bool_sem(&p->vkctx, exec, &f->internal->drm_sync_sem, 1,
+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 0);
+ if (ff_vk_exec_submit(&p->vkctx, exec) >= 0) {
+ VkSemaphoreGetFdInfoKHR get_fd_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
+ .semaphore = f->internal->drm_sync_sem,
+ .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
+ };
+ ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &get_fd_info, &sync_fd);
+ if (ret != VK_SUCCESS) {
+ av_log(hwctx, AV_LOG_WARNING,
+ "Failed to get sync fd from DRM map export semaphore: %s\n",
+ ff_vk_ret2str(ret));
+ sync_fd = -1;
+ }
+ } else {
+ ff_vk_exec_discard_deps(&p->vkctx, exec);
+ }
+ }
+
+ return sync_fd;
+}
+#endif
+
static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
const AVFrame *src, int flags)
{
@@ -4138,15 +4243,14 @@ static int vulkan_map_to_drm(AVHWFramesC
AVVulkanDeviceContext *hwctx = &p->p;
FFVulkanFunctions *vk = &p->vkctx.vkfn;
VulkanFramesPriv *fp = hwfc->hwctx;
+ const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
const int nb_images = ff_vk_count_images(f);
VkImageDrmFormatModifierPropertiesEXT drm_mod = {
.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
};
- VkSemaphoreWaitInfo wait_info = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
- .flags = 0x0,
- .semaphoreCount = nb_images,
- };
+ const int nb_sems = nb_images;
+ int free_drm_desc_on_err = 1;
+ int sync_fd = -1;
AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc));
if (!drm_desc)
@@ -4156,16 +4260,36 @@ static int vulkan_map_to_drm(AVHWFramesC
if (err < 0)
goto end;
- /* Wait for the operation to finish so we can cleanly export it. */
- wait_info.pSemaphores = f->sem;
- wait_info.pValues = f->sem_value;
+#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
+ if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM) &&
+ f->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
+ vk->GetSemaphoreFdKHR && vk->CreateSemaphore) {
+ err = vulkan_drm_export_sync_fd(hwfc, f, fp, nb_sems);
+ if (err < 0)
+ goto end;
+ sync_fd = err;
+ err = 0;
+ }
+#endif
- vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX);
+ if (sync_fd < 0) {
+ VkSemaphoreWaitInfo wait_info = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+ .flags = 0x0,
+ .semaphoreCount = nb_sems,
+ .pSemaphores = f->sem,
+ .pValues = f->sem_value,
+ };
+ vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX);
+ }
err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &vulkan_unmap_to_drm, drm_desc);
if (err < 0)
goto end;
+ /* It will be freed in ff_hwframe_map_create callback */
+ free_drm_desc_on_err = 0;
+
ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0],
&drm_mod);
if (ret != VK_SUCCESS) {
@@ -4174,7 +4298,7 @@ static int vulkan_map_to_drm(AVHWFramesC
goto end;
}
- for (int i = 0; (i < nb_images) && (f->mem[i]); i++) {
+ for (int i = 0; (i < planes) && (f->mem[i]); i++) {
VkMemoryGetFdInfoKHR export_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
.memory = f->mem[i],
@@ -4189,12 +4313,30 @@ static int vulkan_map_to_drm(AVHWFramesC
goto end;
}
+#if HAVE_LINUX_DMA_BUF_H && defined(DMA_BUF_IOCTL_IMPORT_SYNC_FILE)
+ if (sync_fd >= 0) {
+ int dup_fd = dup(sync_fd);
+ if (dup_fd >= 0) {
+ struct dma_buf_import_sync_file import_info = {
+ .flags = DMA_BUF_SYNC_WRITE,
+ .fd = dup_fd,
+ };
+ if (ioctl(drm_desc->objects[i].fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &import_info) < 0)
+ av_log(hwfc, AV_LOG_WARNING, "DMA_BUF_IOCTL_IMPORT_SYNC_FILE failed: %s\n", av_err2str(AVERROR(errno)));
+ close(dup_fd);
+ } else {
+ av_log(hwfc, AV_LOG_WARNING, "dup(sync_fd) failed: %s\n", av_err2str(AVERROR(errno)));
+ }
+ }
+#endif
+
drm_desc->nb_objects++;
drm_desc->objects[i].size = f->size[i];
drm_desc->objects[i].format_modifier = drm_mod.drmFormatModifier;
}
- drm_desc->nb_layers = nb_images;
+ /* NV12 has 2 planes but 1 image/semaphore */
+ drm_desc->nb_layers = FFMAX(planes, nb_images);
for (int i = 0; i < drm_desc->nb_layers; i++) {
VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i];
@@ -4209,13 +4351,14 @@ static int vulkan_map_to_drm(AVHWFramesC
for (int j = 0; j < drm_desc->layers[i].nb_planes; j++) {
VkSubresourceLayout layout;
+ int aspect_plane = (nb_images == 1) ? i : j;
VkImageSubresource sub = {
- .aspectMask = plane_index_to_aspect(j),
+ .aspectMask = plane_index_to_aspect(aspect_plane),
};
drm_desc->layers[i].planes[j].object_index = FFMIN(i, drm_desc->nb_objects - 1);
- vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout);
+ vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[FFMIN(i, nb_images - 1)], &sub, &layout);
drm_desc->layers[i].planes[j].offset = layout.offset;
drm_desc->layers[i].planes[j].pitch = layout.rowPitch;
}
@@ -4235,13 +4378,22 @@ static int vulkan_map_to_drm(AVHWFramesC
dst->width = src->width;
dst->height = src->height;
dst->data[0] = (uint8_t *)drm_desc;
+ dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
+
+ if (sync_fd >= 0)
+ close(sync_fd);
av_log(hwfc, AV_LOG_VERBOSE, "Mapped AVVkFrame to a DRM object!\n");
return 0;
end:
- av_free(drm_desc);
+ for (int i = 0; i < drm_desc->nb_objects; i++)
+ close(drm_desc->objects[i].fd);
+ if (free_drm_desc_on_err)
+ av_free(drm_desc);
+ if (sync_fd >= 0)
+ close(sync_fd);
return err;
}
@@ -4751,6 +4903,7 @@ static int vulkan_transfer_data_to_cuda(
CUcontext dummy;
AVVkFrame *dst_f;
AVVkFrameInternal *dst_int;
+ VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
VulkanFramesPriv *fp = hwfc->hwctx;
const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
@@ -4831,7 +4984,7 @@ static int vulkan_transfer_data_to_cuda(
fail:
CHECK_CU(cu->cuCtxPopCurrent(&dummy));
- vulkan_free_internal(dst_f);
+ vulkan_free_internal(p, dst_f);
av_buffer_unref(&dst->buf[0]);
return err;
}