This commit is contained in:
2025-10-16 02:07:59 +09:00
parent 0cc37a250b
commit fa846b87b0
2 changed files with 62 additions and 14 deletions

View File

@@ -2547,11 +2547,48 @@ bool VulkanVideoRenderer::RenderVulkanImage(VkImage sourceImage, VkSamplerYcbcrC
LOGI("Created YCbCr ImageView successfully (ImageView=%p)", (void*)ycbcrImageView);
// Update descriptor set to bind single YCbCr image with combined sampler
// CRITICAL FIX: Create YCbCr-aware sampler with matching conversion
// According to Vulkan spec, BOTH ImageView AND Sampler must have the same YCbCr conversion attached
VkSampler ycbcrSampler = VK_NULL_HANDLE;
VkSamplerYcbcrConversionInfo samplerYcbcrInfo = {};
samplerYcbcrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
samplerYcbcrInfo.pNext = nullptr;
samplerYcbcrInfo.conversion = ycbcrConversion;
VkSamplerCreateInfo samplerInfo = {};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.pNext = &samplerYcbcrInfo; // Chain YCbCr conversion to sampler
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
result = vkCreateSampler(m_device, &samplerInfo, nullptr, &ycbcrSampler);
if (result != VK_SUCCESS) {
LOGE("Failed to create YCbCr sampler: %d", result);
vkDestroyImageView(m_device, ycbcrImageView, nullptr);
return false;
}
LOGI("Created YCbCr Sampler successfully (Sampler=%p) with matching conversion", (void*)ycbcrSampler);
// Update descriptor set to bind single YCbCr image with YCbCr-aware sampler
VkDescriptorImageInfo imageInfo = {};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = ycbcrImageView;
imageInfo.sampler = m_textureSampler;
imageInfo.sampler = ycbcrSampler; // Use YCbCr-aware sampler instead of generic m_textureSampler
VkWriteDescriptorSet descriptorWrite = {};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@@ -2572,6 +2609,7 @@ bool VulkanVideoRenderer::RenderVulkanImage(VkImage sourceImage, VkSamplerYcbcrC
// Record and submit command buffer (uses existing pipeline)
if (!RecordCommandBuffer(imageIndex)) {
LOGE("Failed to record command buffer");
vkDestroySampler(m_device, ycbcrSampler, nullptr);
vkDestroyImageView(m_device, ycbcrImageView, nullptr);
return false;
}
@@ -2579,6 +2617,7 @@ bool VulkanVideoRenderer::RenderVulkanImage(VkImage sourceImage, VkSamplerYcbcrC
// End frame and present
if (!EndFrame(imageIndex)) {
LOGE("Failed to end frame");
vkDestroySampler(m_device, ycbcrSampler, nullptr);
vkDestroyImageView(m_device, ycbcrImageView, nullptr);
return false;
}
@@ -2586,10 +2625,11 @@ bool VulkanVideoRenderer::RenderVulkanImage(VkImage sourceImage, VkSamplerYcbcrC
// Update performance metrics
UpdatePerformanceMetrics();
// Clean up YCbCr ImageView after frame is submitted and fence is signaled
// The ImageView is now safe to destroy since EndFrame() waits for submission
// Clean up YCbCr Sampler and ImageView after frame is submitted and fence is signaled
// Both are now safe to destroy since EndFrame() waits for submission
vkDestroySampler(m_device, ycbcrSampler, nullptr);
vkDestroyImageView(m_device, ycbcrImageView, nullptr);
LOGI("YCbCr ImageView destroyed after frame submission");
LOGI("YCbCr Sampler and ImageView destroyed after frame submission");
LOGI("RenderVulkanImage completed successfully");
return true;

View File

@@ -346,19 +346,27 @@ bool MediaCodecSurfaceManager::CreateVulkanImage(void* vk_device, void* vk_insta
ycbcrConversionCreateInfo.format = vulkan_format;
// Force BT.601 color space (most video content uses BT.601, not BT.709)
// MediaCodec often suggests BT.709 which causes incorrect colors
ycbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601; // BT.601
ycbcrConversionCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW; // Limited range (16-235)
// Use MediaCodec suggested YCbCr conversion settings
// MediaCodec provides optimal color space settings based on video metadata
ycbcrConversionCreateInfo.ycbcrModel = static_cast<VkSamplerYcbcrModelConversion>(ahb_format_props.suggestedYcbcrModel);
ycbcrConversionCreateInfo.ycbcrRange = static_cast<VkSamplerYcbcrRange>(ahb_format_props.suggestedYcbcrRange);
// Log suggested vs actual
// Log color space settings
LogInfo("YCbCr conversion:");
LogInfo(" Suggested model: " + std::to_string(ahb_format_props.suggestedYcbcrModel) + " (ignoring - using BT.601)");
LogInfo(" Suggested range: " + std::to_string(ahb_format_props.suggestedYcbcrRange));
LogInfo(" Using model: BT.601 (1)");
LogInfo(" Using range: ITU_NARROW (1)");
LogInfo(" MediaCodec suggested model: " + std::to_string(ahb_format_props.suggestedYcbcrModel));
LogInfo(" MediaCodec suggested range: " + std::to_string(ahb_format_props.suggestedYcbcrRange));
LogInfo(" Using MediaCodec suggested color space settings");
// Log component mapping from MediaCodec
LogInfo(" MediaCodec suggested components:");
LogInfo(" r: " + std::to_string(ahb_format_props.samplerYcbcrConversionComponents.r));
LogInfo(" g: " + std::to_string(ahb_format_props.samplerYcbcrConversionComponents.g));
LogInfo(" b: " + std::to_string(ahb_format_props.samplerYcbcrConversionComponents.b));
LogInfo(" a: " + std::to_string(ahb_format_props.samplerYcbcrConversionComponents.a));
// Use MediaCodec suggested component mapping
ycbcrConversionCreateInfo.components = ahb_format_props.samplerYcbcrConversionComponents;
LogInfo(" Using MediaCodec suggested component mapping");
ycbcrConversionCreateInfo.xChromaOffset = ahb_format_props.suggestedXChromaOffset;
ycbcrConversionCreateInfo.yChromaOffset = ahb_format_props.suggestedYChromaOffset;
ycbcrConversionCreateInfo.chromaFilter = VK_FILTER_LINEAR;