Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
989 views
in Technique[技术] by (71.8m points)

objective c - CVMetalTextureCacheCreateTextureFromImage returns -6660 on macOS 10.13

I'm recording the screen from my iPhone device to my Mac. As a preview layer, I am collecting sample buffers directly from an AVCaptureVideoDataOutput, from which I'm creating textures and rendering them with Metal. The problem I'm having is that code that worked in macOS prior to 10.13 stopped working after updating to 10.13. Namely,

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);
}

Returns result = -6660, which translates to a generic kCVReturnError, as can be seen on the official Apple docs, and the metalTexture = NULL.

The pixel format I'm using is MTLPixelFormatBGRG422 since the samples coming from the camera are 2vuy.

As a workaround to creating metalTexture from sampleBuffer, I am now creating an intermediate NSImage like so:

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(_currentSampleBuffer);
NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:[CIImage imageWithCVImageBuffer:imageBuffer]];
    
NSImage *image = [[NSImage alloc] initWithSize:[imageRep size]];
[image addRepresentation:imageRep];

and creating a MTLTexture from that. That is obviously a subpar solution to using CVMetalTextureCacheCreateTextureFromImage directly.

Once again, the code in question works perfectly fine in macOS < 10.13, I'd like to know if anyone has similar issues, and if so, do you have any ideas how to overcome this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I've come across the same issue, the problem was not asking for Metal compatibility when configuring the AVCaptureVideoDataOutput. I guess the system started to check this in macOS 10.13, possibly to apply some optimization when not requested.

The solution was to add the kCVPixelBufferMetalCompatibilityKey to the videoSettings property of AVCaptureVideoDataOutput.

In Objective-C:

outputCapture.videoSettings = @{
  /* ... */
  (NSString *)kCVPixelBufferMetalCompatibilityKey: @YES
};

In Swift:

outputCapture.videoSettings = [
  /* ... */
  kCVPixelBufferMetalCompatibilityKey as String: true
]

I think this warrants a radar, to ask Apple to at least print a warning message when this occurs. I'll update this if I get to it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...