Creating copy of CMSampleBuffer in Swift returns OSStatus -12743 (Invalid Media Format)

╄→гoц情女王★ 提交于 2020-01-24 05:46:05

问题


I am attempting to perform a deep clone of CMSampleBuffer to store the output of a AVCaptureSession. I am receiving the error kCMSampleBufferError_InvalidMediaFormat (OSStatus -12743) when I run the function CMSampleBufferCreateForImageBuffer. I don't see how I've mismatched the CVImageBuffer and the CMSampleBuffer format description. Anyone know where I've gone wrong? Her is my test code.

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {

    let allocator: CFAllocator = CFAllocatorGetDefault().takeRetainedValue()

    func cloneImageBuffer(imageBuffer: CVImageBuffer!) -> CVImageBuffer? {
        CVPixelBufferLockBaseAddress(imageBuffer, 0)
        let bytesPerRow: size_t = CVPixelBufferGetBytesPerRow(imageBuffer)
        let width: size_t = CVPixelBufferGetWidth(imageBuffer)
        let height: size_t = CVPixelBufferGetHeight(imageBuffer)
        let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
        let pixelFormatType = CVPixelBufferGetPixelFormatType(imageBuffer)

        let data = NSMutableData(bytes: baseAddress, length: bytesPerRow * height)
        CVPixelBufferUnlockBaseAddress(imageBuffer, 0)

        var clonedImageBuffer: CVPixelBuffer?
        let refCon = NSMutableData()

        if CVPixelBufferCreateWithBytes(allocator, width, height, pixelFormatType, data.mutableBytes, bytesPerRow, nil, refCon.mutableBytes, nil, &clonedImageBuffer) == noErr {
            return clonedImageBuffer
        } else {
            return nil
        }
    }

    if let oldImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
        if let newImageBuffer = cloneImageBuffer(oldImageBuffer) {
            if let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) {
                let dataIsReady = CMSampleBufferDataIsReady(sampleBuffer)
                let refCon = NSMutableData()
                var timingInfo: CMSampleTimingInfo = kCMTimingInfoInvalid
                let timingInfoSuccess = CMSampleBufferGetSampleTimingInfo(sampleBuffer, 0, &timingInfo)
                if timingInfoSuccess == noErr {
                    var newSampleBuffer: CMSampleBuffer?
                    let success = CMSampleBufferCreateForImageBuffer(allocator, newImageBuffer, dataIsReady, nil, refCon.mutableBytes, formatDescription, &timingInfo, &newSampleBuffer)
                    if success == noErr {
                        bufferArray.append(newSampleBuffer!)
                    } else {
                        NSLog("Failed to create new image buffer. Error: \(success)")
                    }
                } else {
                    NSLog("Failed to get timing info. Error: \(timingInfoSuccess)")
                }
            }
        }
    }
}

回答1:


I was able to fix the problem by creating a format description off the newly created image buffer and using it instead of the format description off the original sample buffer. Unfortunately while that fixes the problem here, the format descriptions don't match and causes problem further down.




回答2:


I recently came across the same issue. After a bit of investigation, the CMVideoFormatDescriptionMatchesImageBuffer() function documentation gave a bit of insight.

This function uses the keys returned by CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers to compares the extensions of the given format description to the attachments of the given image buffer (if an attachment is absent in either it must be absent in both). It also checks kCMFormatDescriptionExtension_BytesPerRow against CVPixelBufferGetBytesPerRow, if applicable.

In my case, I didn't copy over some of the format description extensions as CVBuffer attachments of the copied pixel buffer. Running this bit of code after creating the new CVPixelBufferRef resolved the issue for me (Objective-C, but shouldn't be hard to convert to Swift)

NSSet *commonKeys = [NSSet setWithArray:(NSArray *)CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers()];
NSDictionary *attachments = (NSDictionary *)CVBufferGetAttachments(originalPixelBuffer, kCVAttachmentMode_ShouldPropagate);
[attachments enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
{
    if ([commonKeys containsObject:key])
    {
        CVBufferSetAttachment(pixelBufferCopy, (__bridge CFStringRef)(key), (__bridge CFTypeRef)(obj), kCVAttachmentMode_ShouldPropagate);
    }
}];
attachments = (NSDictionary *)CVBufferGetAttachments(originalPixelBuffer, kCVAttachmentMode_ShouldNotPropagate);
[attachments enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
{
    if ([commonKeys containsObject:key])
    {
        CVBufferSetAttachment(pixelBufferCopy, (__bridge CFStringRef)(key), (__bridge CFTypeRef)(obj), kCVAttachmentMode_ShouldNotPropagate);
    }
}];


来源:https://stackoverflow.com/questions/35561746/creating-copy-of-cmsamplebuffer-in-swift-returns-osstatus-12743-invalid-media

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!