![](/img/trans.png)
[英]macOS App Crashes on 10.13 with Symbol not found: _NSAppearanceNameDarkAqua
[英]CVMetalTextureCacheCreateTextureFromImage returns -6660 on macOS 10.13
我正在将屏幕从我的 iPhone 设备录制到我的 Mac。 作为预览层,我直接从AVCaptureVideoDataOutput
收集样本缓冲区,从中我创建纹理并使用Metal
渲染它们。 我遇到的问题是,在10.13
之前在 macOS 中工作的代码在更新到10.13
后停止工作。 即,
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(_currentSampleBuffer);
if (!imageBuffer) return;
CVPixelBufferLockBaseAddress(imageBuffer,0);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
CVMetalTextureRef metalTexture = NULL;
CVReturn result = CVMetalTextureCacheCreateTextureFromImage(nil,
self.textureCache,
imageBuffer,
nil,
self.pixelFormat,
width,
height,
0,
&metalTexture);
if (result == kCVReturnSuccess) {
self.texture = CVMetalTextureGetTexture(metalTexture);
}
返回result = -6660
,这可以转换为通用的kCVReturnError
,如Apple 官方文档中所示,以及metalTexture = NULL
。
我使用的像素格式是MTLPixelFormatBGRG422
因为来自相机的样本是2vuy
。
作为从sampleBuffer
创建metalTexture
一种解决方法,我现在正在创建一个中间NSImage
如下所示:
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(_currentSampleBuffer);
NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:[CIImage imageWithCVImageBuffer:imageBuffer]];
NSImage *image = [[NSImage alloc] initWithSize:[imageRep size]];
[image addRepresentation:imageRep];
并MTLTexture
创建MTLTexture
。 这显然是直接使用CVMetalTextureCacheCreateTextureFromImage
的次要解决方案。
再一次,有问题的代码在macOS < 10.13
工作得很好,我想知道是否有人有类似的问题,如果有,你有什么想法如何克服这个问题吗?
我遇到了同样的问题,问题不是在配置AVCaptureVideoDataOutput
时要求金属兼容性。 我猜系统开始在 macOS 10.13 中检查这个,可能是在没有请求时应用一些优化。
解决方案是将kCVPixelBufferMetalCompatibilityKey
添加到AVCaptureVideoDataOutput
的videoSettings
属性。
在 Objective-C 中:
outputCapture.videoSettings = @{
/* ... */
(NSString *)kCVPixelBufferMetalCompatibilityKey: @YES
};
在斯威夫特:
outputCapture.videoSettings = [
/* ... */
kCVPixelBufferMetalCompatibilityKey as String: true
]
我认为这需要一个雷达,要求 Apple 在发生这种情况时至少打印一条警告消息。 如果我得到它,我会更新它。
我找到了一个解决方法,它将2vuy
格式保留在像素缓冲区中,但不好的是你制作了影响性能的像素缓冲区数据的副本。 我将其发布以供将来参考,或者如果其他人认为它有用。 基本上我们拦截像素缓冲区,然后在复制数据的同时添加属性。
NSDictionary *attributes = @{
@"IOSurfaceCoreAnimationCompatibility": @YES
};
CVPixelBufferRef copy = NULL;
CVPixelBufferCreate(kCFAllocatorDefault,
CVPixelBufferGetWidth(pixelBuffer),
CVPixelBufferGetHeight(pixelBuffer),
CVPixelBufferGetPixelFormatType(pixelBuffer),
(__bridge CFDictionaryRef)attributes,
©);
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
CVPixelBufferLockBaseAddress(copy, 0);
void *baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
void *copyBaseAddress = CVPixelBufferGetBaseAddress(copy);
memcpy(copyBaseAddress, baseAddress, CVPixelBufferGetDataSize(pixelBuffer));
CVPixelBufferUnlockBaseAddress(copy, 0);
CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
另一种从CVPixelBufferRef
到 Metal 纹理的方法,您可以通过CIImage
并使用CIContext
和 Metal 设备(希望最大限度地减少 CPU 参与复制像素缓冲区);
确保您的目标金属纹理大小合适。
CIContext* ciContext = [CIContext contextWithMTLDevice:mtlDevice
options:[NSDictionary dictionaryWithObjectsAndKeys:@(NO),kCIContextUseSoftwareRenderer,nil]
];
id<MTLCommandBuffer> metalCommandBuffer=[mtlCommandQueue commandBufferWithUnretainedReferences];
CIImage* ciImage = [[CIImage alloc] initWithCVPixelBuffer:cvPixelBuffer];
[ciContext render:ciImage
toMTLTexture:metal_texture
commandBuffer:mtlCommandBuffer
bounds:[ciImage extent])
colorSpace:[ciImage colorSpace]];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.