Ios MTLTexture.getbytes()返回EXC\u BAD\u访问-可能的原因?

Ios MTLTexture.getbytes()返回EXC\u BAD\u访问-可能的原因?,ios,swift,arkit,metal,Ios,Swift,Arkit,Metal,我正在使用ARKit3身体跟踪功能,将3D模型覆盖在摄影机提要上,并允许用户将提要捕获为带有音频的MP4。我已经能够成功地将相机预览绘制到MTL视图。但是,我收到一个EXC_BAD_访问错误,在尝试写入我的资产编写器时,我似乎无法调试该错误。我的应用程序有一个render类,负责渲染提要中的金属纹理,还有一个MetalVideoRecorder类,用于将帧写入mp4文件。我在下面突出显示了生成错误的行: 我的MetalVideoWriter类的相关代码: func writeFrame(forT

我正在使用ARKit3身体跟踪功能,将3D模型覆盖在摄影机提要上,并允许用户将提要捕获为带有音频的MP4。我已经能够成功地将相机预览绘制到MTL视图。但是,我收到一个EXC_BAD_访问错误,在尝试写入我的资产编写器时,我似乎无法调试该错误。我的应用程序有一个render类,负责渲染提要中的金属纹理,还有一个MetalVideoRecorder类,用于将帧写入mp4文件。我在下面突出显示了生成错误的行:

我的MetalVideoWriter类的相关代码:

func writeFrame(forTexture texture: MTLTexture) {

    //Only if recording and our asset writer has been initialized
    if (assetWriter == nil) { return; }
    if !isRecording { return; }
    while !assetWriterVideoInput!.isReadyForMoreMediaData {}

    //Get pixer buffer pool from the asset writer (to write to)
    guard let pixelBufferPool = assetWriterPixelBufferInput!.pixelBufferPool else { return; }

    var maybePixelBuffer: CVPixelBuffer? = nil
    let status  = CVPixelBufferPoolCreatePixelBuffer(nil, pixelBufferPool, &maybePixelBuffer)
    if status != kCVReturnSuccess { return; }
    guard let pixelBuffer = maybePixelBuffer else { return }

    CVPixelBufferLockBaseAddress(pixelBuffer, [])
    let pixelBufferBytes = CVPixelBufferGetBaseAddress(pixelBuffer)!
    let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
    let region = MTLRegionMake2D(0, 0, texture.width, texture.height)

    //########################################
    //#### This line returns the error... ####
    //########################################
    texture.getBytes(pixelBufferBytes, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)

    //Timestamp of the frame
    let frameTime = CACurrentMediaTime() - recordingStartTime
    let presentationTime = CMTimeMakeWithSeconds(frameTime, 240)
    assetWriterPixelBufferInput!.append(pixelBuffer, withPresentationTime: presentationTime)

    CVPixelBufferUnlockBaseAddress(pixelBuffer, [])        
    firstFrameWritten = true;
}
这就是我的渲染器类处理帧的方式:

func update() {

    if (self.metalVideoRecorder == nil) {
        print("Failed - Metal video recorder is nil")
        return;
    }
    // Wait to ensure only kMaxBuffersInFlight are getting proccessed by any stage in the Metal
    //   pipeline (App, Metal, Drivers, GPU, etc)
    let _ = inFlightSemaphore.wait(timeout: DispatchTime.distantFuture)

    // Create a new command buffer for each renderpass to the current drawable

    if let commandBuffer = commandQueue.makeCommandBuffer() {
        commandBuffer.label = "MyCommand"


        // Retain our CVMetalTextures for the duration of the rendering cycle. The MTLTextures
        //   we use from the CVMetalTextures are not valid unless their parent CVMetalTextures
        //   are retained. Since we may release our CVMetalTexture ivars during the rendering
        //   cycle, we must retain them separately here.
        var textures = [capturedImageTextureY, capturedImageTextureCbCr]

        updateBufferStates()
        updateGameState()

        guard let renderDescriptor = renderDestination.currentRenderPassDescriptor else {return}
        renderDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 1) //Black background

        guard let currentDrawable = renderDestination.currentDrawable else {return}

        guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderDescriptor) else {return}
        renderEncoder.label = "MyRenderEncoder"

        let texture = currentDrawable.texture

        // Add completion hander which signal _inFlightSemaphore when Metal and the GPU has fully
        //   finished proccssing the commands we're encoding this frame.  This indicates when the
        //   dynamic buffers, that we're writing to this frame, will no longer be needed by Metal
        //   and the GPU.
        commandBuffer.addCompletedHandler{ [weak self] commandBuffer in
            if let strongSelf = self {
                strongSelf.inFlightSemaphore.signal()

                if (strongSelf.metalVideoRecorder!.isRecording == true)
                {
                    strongSelf.metalVideoRecorder!.writeFrame(forTexture: texture)
                }
            }
            textures.removeAll()
        }

        //Draw camera image
        drawCapturedImage(renderEncoder: renderEncoder)

        //Draw additional items on top (cube etc.)
        drawAnchorGeometry(renderEncoder: renderEncoder)

        // We're done encoding commands
        renderEncoder.endEncoding()

        // Schedule a present once the framebuffer is complete using the current drawable
        commandBuffer.present(currentDrawable)

        // Finalize rendering here & push the command buffer to the GPU
        commandBuffer.commit()

    }
}
这一错误的一些潜在原因是什么?调试错误的最佳方法是什么

请注意,我录制帧的方法受到以下答案的启发:

更新

上述方法假设您的纹理和输出视频大小相同。在我的例子中,我试图生成一个1280x720视频,但我试图录制的MTLView大小不同(它是一个全屏视图,所以不管手机的显示大小如何)。我的选择是以非标准纵横比(恶心)记录或确定裁剪方式。我会继续寻找裁剪框架的方法