@@ -25,13 +25,14 @@ @interface CameraTextureDelegate : NSObject <AVCaptureVideoDataOutputSampleBuffe
2525{
2626 @public AVCaptureVideoOrientation videoOrientation;
2727
28- std::shared_ptr<Babylon::Plugins::Camera::Impl::ImplData> implData ;
28+ CVMetalTextureCacheRef textureCache ;
2929 bool orientationUpdated;
3030}
3131
32- - (id )init : (std::shared_ptr<Babylon::Plugins::Camera::Impl::ImplData>) implData ;
32+ - (id )init : (CVMetalTextureCacheRef) textureCache ;
3333- (id <MTLTexture >)getCameraTextureY ;
3434- (id <MTLTexture >)getCameraTextureCbCr ;
35+ - (void )reset ;
3536
3637@end
3738
@@ -140,7 +141,9 @@ fragment float4 fragmentShader(RasterizerData in [[stage_in]],
140141 [currentCommandBuffer waitUntilCompleted ];
141142 }
142143
143- [avCaptureSession stopRunning ];
144+ dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
145+ [avCaptureSession stopRunning ];
146+ });
144147
145148 if (textureCache)
146149 {
@@ -152,7 +155,7 @@ fragment float4 fragmentShader(RasterizerData in [[stage_in]],
152155 CameraTextureDelegate* cameraTextureDelegate{};
153156 AVCaptureSession* avCaptureSession{};
154157 CVMetalTextureCacheRef textureCache{};
155- id <MTLTexture > textureRGBA{};
158+ id <MTLTexture > textureRGBA{};
156159 id <MTLRenderPipelineState > cameraPipelineState{};
157160 id <MTLDevice > metalDevice{};
158161 id <MTLCommandQueue > commandQueue{};
@@ -191,7 +194,7 @@ fragment float4 fragmentShader(RasterizerData in [[stage_in]],
191194
192195 dispatch_async (dispatch_get_main_queue (), ^{
193196 CVMetalTextureCacheCreate (nullptr , nullptr , m_implData->metalDevice , nullptr , &m_implData->textureCache );
194- m_implData->cameraTextureDelegate = [[CameraTextureDelegate alloc ]init:m_implData];
197+ m_implData->cameraTextureDelegate = [[CameraTextureDelegate alloc ]init:m_implData->textureCache ];
195198 m_implData->avCaptureSession = [[AVCaptureSession alloc ] init ];
196199 m_implData->textureRGBA = nil ;
197200
@@ -347,7 +350,9 @@ fragment float4 fragmentShader(RasterizerData in [[stage_in]],
347350 // Actually start the camera session.
348351 [m_implData->avCaptureSession addOutput: dataOutput];
349352 [m_implData->avCaptureSession commitConfiguration ];
350- [m_implData->avCaptureSession startRunning ];
353+ dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
354+ [m_implData->avCaptureSession startRunning ];
355+ });
351356
352357 // Create a pipeline state for converting the camera output to RGBA.
353358 id <MTLLibrary > lib = CompileShader (m_implData->metalDevice , shaderSource);
@@ -463,7 +468,9 @@ fragment float4 fragmentShader(RasterizerData in [[stage_in]],
463468
464469 void Camera::Impl::Close ()
465470 {
466- m_implData.reset (new ImplData);
471+ [m_implData->cameraTextureDelegate reset ];
472+ m_implData.reset ();
473+ m_implData = std::make_unique<ImplData>();
467474 }
468475}
469476
@@ -472,10 +479,10 @@ @implementation CameraTextureDelegate {
472479 CVMetalTextureRef cameraTextureCbCr;
473480}
474481
475- - (id )init : (std::shared_ptr<Babylon::Plugins::Camera::Impl::ImplData>) implData
482+ - (id )init : (CVMetalTextureCacheRef) textureCache
476483{
477484 self = [super init ];
478- self->implData = implData ;
485+ self->textureCache = textureCache ;
479486#if (TARGET_OS_IPHONE)
480487 [[NSNotificationCenter defaultCenter ]addObserver:self selector: @selector (OrientationDidChange: ) name: UIDeviceOrientationDidChangeNotification object: nil ];
481488 [self updateOrientation ];
@@ -513,6 +520,12 @@ - (id)init:(std::shared_ptr<Babylon::Plugins::Camera::Impl::ImplData>)implData
513520 return nil ;
514521}
515522
523+ - (void ) reset {
524+ @synchronized (self) {
525+ self->textureCache = nil ;
526+ }
527+ }
528+
516529#if (TARGET_OS_IPHONE)
517530/* *
518531 Updates target video orientation.
@@ -603,11 +616,16 @@ - (CVMetalTextureRef)getCameraTexture:(CVPixelBufferRef)pixelBuffer plane:(int)p
603616 auto pixelFormat = planeIndex ? MTLPixelFormatRG8Unorm : MTLPixelFormatR8Unorm ;
604617 CVMetalTextureRef textureRef;
605618
606- // Create a texture from the corresponding plane.
607- auto status = CVMetalTextureCacheCreateTextureFromImage (kCFAllocatorDefault , implData->textureCache , pixelBuffer, nil , pixelFormat, planeWidth, planeHeight, planeIndex, &textureRef);
608- if (status != kCVReturnSuccess ) {
609- CVBufferRelease (textureRef);
610- textureRef = nil ;
619+ @synchronized (self) {
620+ if (self->textureCache == nil ) {
621+ return {};
622+ }
623+
624+ auto status = CVMetalTextureCacheCreateTextureFromImage (kCFAllocatorDefault , textureCache, pixelBuffer, nil , pixelFormat, planeWidth, planeHeight, planeIndex, &textureRef);
625+ if (status != kCVReturnSuccess ) {
626+ CVBufferRelease (textureRef);
627+ textureRef = nil ;
628+ }
611629 }
612630
613631 return textureRef;
0 commit comments