首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OSX MetalKit CVMetalTextureCacheCreateTextureFromImage失败,状态:-6660

OSX MetalKit CVMetalTextureCacheCreateTextureFromImage失败,状态:-6660
EN

Stack Overflow用户
提问于 2020-02-19 15:14:51
回答 1查看 372关注 0票数 2

我试图首先从原始内存中生成,然后从CVPixelBuffer生成MTLTexture,但是在运行以下代码之后,我总是会出错

CVMetalTextureCacheCreateTextureFromImage失败,状态:-66600x0

这个错误从何而来?

代码语言:javascript
复制
    id<MTLTexture> makeTextureWithBytes(id<MTLDevice> mtl_device, 
                                        int width, 
                                        int height, 
                                        void *baseAddress, int bytesPerRow)
    {

    CVMetalTextureCacheRef textureCache = NULL;

    CVReturn status = CVMetalTextureCacheCreate(kCFAllocatorDefault, nullptr, mtl_device, nullptr, &textureCache);
    if(status != kCVReturnSuccess || textureCache == NULL)
    {
        return nullptr;
    }

    NSDictionary* cvBufferProperties = @{
        (__bridge NSString*)kCVPixelBufferOpenGLCompatibilityKey : @YES,
        (__bridge NSString*)kCVPixelBufferMetalCompatibilityKey : @YES,
    };

    CVPixelBufferRef pxbuffer = NULL;

    status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
                                          width,
                                          height,
                                          kCVPixelFormatType_32BGRA,
                                          baseAddress,
                                          bytesPerRow,
                                          releaseCallback,
                                          NULL/*releaseRefCon*/,
                                          (__bridge CFDictionaryRef)cvBufferProperties,
                                          &pxbuffer);

    if(status != kCVReturnSuccess || pxbuffer == NULL)
    {
        return nullptr;
    }

    CVMetalTextureRef cvTexture = NULL;   

    status = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                       textureCache,
                                                       pxbuffer,
                                                       nullptr,
                                                       MTLPixelFormatBGRA8Unorm,
                                                       1920,
                                                       1080,
                                                       0,
                                                       &cvTexture);

    if(status != kCVReturnSuccess || cvTexture == NULL)
    {
        std::cout << "CVMetalTextureCacheCreateTextureFromImage failed, status: " << status << " " << cvTexture << std::endl;
        return nullptr;
    }
    id<MTLTexture> metalTexture = CVMetalTextureGetTexture(cvTexture);

    CFRelease(cvTexture);

    return metalTexture;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-27 13:45:41

当CVPixelBuffer没有由IOSurface支持时,就会发生错误。但是,您不能从Bytes生成一个IOSurface支持的CVPixelBuffer。因此,尽管有kCVPixelBufferMetalCompatibilityKey集,CVPixelBufferCreateWithBytes (及其平面对应的)不会用IOSurface支持缓冲区。

2条路(可能还有第3条)

  1. 创建一个空的CVpixelBuffer并使用memcpy。每个循环都需要创建一个新的像素缓冲区,因此建议使用PixelBufferPool。

代码语言:javascript
复制
CVPixelBufferPoolRef pixelPool; // initialised prior
void *srcBaseAddress;  // initialised prior

CVPixelBufferRef currentFrame; 
CVPixelBufferPoolCreatePixelBuffer(nil, pixelPool, &currentFrame);

CVPixelBufferLockBaseAddress(currentFrame,0);
void *cvBaseAddress=CVPixelBufferGetBaseAddress(currentFrame);
size_t size= CVPixelBufferGetDataSize(currentFrame);
memcpy(cvBaseAddress,srcBaseAddress,size);

  1. 完全跳过CVPixelBuffer并直接写入MTLTexture内存;只要金属支持像素格式。但是,由于您可能正在呈现到RGB显示,所以您可以编写自己的金属内核来转换为RGB。记住首先使用metalTextureDescriptor.

制作纹理

代码语言:javascript
复制
id<MTLDevice> metalDevice; // You know how to get this
unsigned int width; // from your source image data
unsigned int height;// from your source image data
unsigned int rowBytes; // from your source image data

MTLTextureDescriptor *mtd = [MTLTextureDescriptor 
texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRG422 
        width:width
        height:height
        mipmapped:NO];

id<MTLTexture> mtlTexture = [metalDevice newTextureWithDescriptor:mtd];


[mtlTexture replaceRegion:MTLRegionMake2D(0,0,width,height) 
        mipmapLevel:0
        withBytes:srcBaseAddress
        bytesPerRow:rowBytes];

第三种方法可能是将CVPixelBuffer转换为CIImage,并使用金属支持的CIContext。像这样的东西;

代码语言:javascript
复制
id<MTLDevice> metalDevice;
CIContext* ciContext = [CIContext contextWithMTLDevice:metalDevice
        options:[NSDictionary dictionaryWithObjectsAndKeys:@(NO),kCIContextUseSoftwareRenderer,nil]
    ];
CIImage *inputImage = [[CIImage alloc] initWithCVPixelBuffer:currentFrame];

[ciContext render:inputImage 
    toMTLTexture:metalTexture 
    commandBuffer:metalCommandBuffer
    bounds:viewRect
    colorSpace:colorSpace];

我成功地使用它直接渲染到CAMetalLayer的可绘制纹理,但没有多少运气渲染到中间纹理(不是我努力让它工作)希望其中一个为您工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60303458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档