Да, это безопасно. Согласно этому образцу кода из архива документации Apple, он выпускается сразу после его назначения, например:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVReturn error;
CVImageBufferRef sourceImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
size_t width = CVPixelBufferGetWidth(sourceImageBuffer);
size_t height = CVPixelBufferGetHeight(sourceImageBuffer);
CVMetalTextureRef textureRef;
error = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _videoTextureCache, sourceImageBuffer, NULL, MTLPixelFormatBGRA8Unorm, width, height, 0, &textureRef);
if (error)
{
NSLog(@">> ERROR: Couldnt create texture from image");
assert(0);
}
_videoTexture[_constantDataBufferIndex] = CVMetalTextureGetTexture(textureRef);
if (!_videoTexture[_constantDataBufferIndex]) {
NSLog(@">> ERROR: Couldn't get texture from texture ref");
assert(0);
}
CVBufferRelease(textureRef);
}
Вы также можете посмотреть исходный код WebRTC из репозитория Google Chromium, они также выпускают CVMetalTextureRef.
- (BOOL)setupTexturesForFrame:(nonnull RTCVideoFrame *)frame {
RTC_DCHECK([frame.buffer isKindOfClass:[RTCCVPixelBuffer class]]);
if (![super setupTexturesForFrame:frame]) {
return NO;
}
CVPixelBufferRef pixelBuffer = ((RTCCVPixelBuffer *)frame.buffer).pixelBuffer;
id<MTLTexture> lumaTexture = nil;
id<MTLTexture> chromaTexture = nil;
CVMetalTextureRef outTexture = nullptr;
// Luma (y) texture.
int lumaWidth = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0);
int lumaHeight = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0);
int indexPlane = 0;
CVReturn result = CVMetalTextureCacheCreateTextureFromImage(
kCFAllocatorDefault, _textureCache, pixelBuffer, nil, MTLPixelFormatR8Unorm, lumaWidth,
lumaHeight, indexPlane, &outTexture);
if (result == kCVReturnSuccess) {
lumaTexture = CVMetalTextureGetTexture(outTexture);
}
// Same as CFRelease except it can be passed NULL without crashing.
CVBufferRelease(outTexture);
outTexture = nullptr;
// Chroma (CrCb) texture.
indexPlane = 1;
result = CVMetalTextureCacheCreateTextureFromImage(
kCFAllocatorDefault, _textureCache, pixelBuffer, nil, MTLPixelFormatRG8Unorm, lumaWidth / 2,
lumaHeight / 2, indexPlane, &outTexture);
if (result == kCVReturnSuccess) {
chromaTexture = CVMetalTextureGetTexture(outTexture);
}
CVBufferRelease(outTexture);
if (lumaTexture != nil && chromaTexture != nil) {
_yTexture = lumaTexture;
_CrCbTexture = chromaTexture;
return YES;
}
return NO;
}