如何从绑定到 ExoPlayer 的 Android SurfaceTexture 创建 Vulkan VkImage?

问题描述 投票:0回答:1

我正在开发一个 Android 应用程序,其中有一个

SurfaceTexture
绑定到 ExoPlayer 用于视频播放。纹理使用
GL_TEXTURE_EXTERNAL_OES
目标。我需要从此
VkImage
创建一个 Vulkan
SurfaceTexture
,以便我可以使用 Vulkan 进行进一步渲染。

如何从使用

VkImage
SurfaceTexture
创建
GL_TEXTURE_EXTERNAL_OES
?我是否需要在此过程中使用特定的 Vulkan 扩展(如
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
)?

android opengl-es textures vulkan exoplayer
1个回答
0
投票

要使用 GL_TEXTURE_EXTERNAL_OES 从 Android SurfaceTexture 创建 Vulkan VkImage,您需要利用 Android 的 AHardwareBuffer 和专为 Android 与 Vulkan 之间交互而设计的 Vulkan 扩展。一般方法包括从 SurfaceTexture 获取 AHardwareBuffer,然后使用 Vulkan 扩展 VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER 从缓冲区创建 VkImage。

使用说明如下:

  1. 从SurfaceTexture获取AHardwareBuffer 当从 GL_TEXTURE_EXTERNAL_OES 使用 SurfaceTexture 进行动画时,底层数据通常由 AHardwareBuffer 处理。您可以使用Android NDK来存储与SurfaceTexture关联的AHardwareBuffer:

CPP

#include <android/hardware_buffer.h>
#include <android/native_window.h>

// Assume `surfaceTexture` is your SurfaceTexture instance
ANativeWindow* nativeWindow = ANativeWindow_fromSurface(env, 
surfaceTexture);
ANativeWindowBuffer* buffer;
nativeWindow->dequeueBuffer(nativeWindow, &buffer);

AHardwareBuffer* hardwareBuffer = buffer->handle;
  1. 使用Vulkan扩展VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER 扩展允许您让 Vulkan 从 AHcm 了解渲染图像需要外接。

CPP

VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
externalMemoryImageCreateInfo.sType =         
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
externalMemoryImageCreateInfo.handleTypes =         
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;

创建 VkImageCreateInfo 结构:

您需要设置 VkImageCreateInfo 来创建 Vulkan 映像。

CPP

VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.extent.width = ...;  // Set width from your SurfaceTexture
imageCreateInfo.extent.height = ...; // Set height from your     
SurfaceTexture
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.format = ...; // Appropriate format matching the     
`SurfaceTexture`
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT |     
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.flags = 0;
imageCreateInfo.pNext = &externalMemoryImageCreateInfo;

创建 VkImage:

使用 VkImageCreateInfo 创建 VkImage。

CPP

VkImage vkImage;
VkResult result = vkCreateImage(device, &imageCreateInfo, nullptr,     
&vkImage);

分配和绑定内存:

使用AHardwareBuffer为图像分配内存。 VkImportAndroidHardwareBufferInfoANDROID 结构体用于导入 AHardwareBuffer。

CPP

VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(device, vkImage, &memoryRequirements);

VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
importHardwareBufferInfo.sType =     
VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
importHardwareBufferInfo.buffer = hardwareBuffer;

VkMemoryAllocateInfo memoryAllocateInfo = {};
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memoryAllocateInfo.allocationSize = memoryRequirements.size;
memoryAllocateInfo.memoryTypeIndex = ...; // Find suitable memory type
memoryAllocateInfo.pNext = &importHardwareBufferInfo;

VkDeviceMemory deviceMemory;
result = vkAllocateMemory(device, &memoryAllocateInfo, nullptr,     
&deviceMemory);

vkBindImageMemory(device, vkImage, deviceMemory, 0);
  1. 使用VkImage进行渲染 将 VkImage 绑定到内存后,您可以像任何其他 Vulkan 图像一样使用它。您可能想要转换其布局,将其附加到帧缓冲区,或在着色器中对其进行采样。

关键扩展和注意事项: VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER:这对于从 AHardwareBuffer 创建 VkImage 至关重要。 AHardwareBuffer:支持 SurfaceTexture 的底层缓冲区,可用于 Vulkan 互操作。 同步:确保跨不同 API(OpenGL ES 和 Vulkan)访问缓冲区时正确同步。 这种方法允许您从 SurfaceTexture 创建 Vulkan VkImage 并使用 Vulkan 进行进一步的渲染操作。

© www.soinside.com 2019 - 2024. All rights reserved.