【问题标题】:Creating copy of CMSampleBuffer in Swift returns OSStatus -12743 (Invalid Media Format)在 Swift 中创建 CMSampleBuffer 的副本返回 OSStatus -12743(无效的媒体格式)
【发布时间】:2016-02-22 19:02:40
【问题描述】:

我正在尝试执行CMSampleBuffer 的深度克隆以存储AVCaptureSession 的输出。当我运行函数CMSampleBufferCreateForImageBuffer 时,我收到错误kCMSampleBufferError_InvalidMediaFormat (OSStatus -12743)。我看不出我是如何与 CVImageBufferCMSampleBuffer 格式描述不匹配的。有谁知道我哪里出错了?她是我的测试代码。

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

【问题讨论】:

    标签: ios avcapturesession core-video core-media cmsamplebuffer


    【解决方案1】:

    我能够通过从新创建的图像缓冲区创建格式描述并使用它而不是原始样本缓冲区的格式描述来解决问题。不幸的是,虽然这解决了这里的问题,但格式描述不匹配并导致问题进一步下降。

    【讨论】:

      【解决方案2】:

      我最近遇到了同样的问题。经过一番调查,CMVideoFormatDescriptionMatchesImageBuffer() 函数文档给出了一些见解。

      此函数使用 CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers 返回的键来比较给定格式描述的扩展名与给定图像缓冲区的附件(如果附件中不存在,则两者都必须不存在)。如果适用,它还会根据 CVPixelBufferGetBytesPerRow 检查 kCMFormatDescriptionExtension_BytesPerRow。

      在我的例子中,我没有复制一些格式描述扩展作为复制像素缓冲区的 CVBuffer 附件。在创建新的 CVPixelBufferRef 后运行这段代码为我解决了这个问题(Objective-C,但应该不难转换为 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);
          }
      }];
      

      【讨论】:

        【解决方案3】:

        雷曼曼答案的 Swift 版本。

        let commonKeys = NSSet(array: CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers() as! [Any])
        
        let propagatedAttachments = NSDictionary(dictionary: CVBufferGetAttachments(pixelBuffer, .shouldPropagate)!)
        propagatedAttachments.enumerateKeysAndObjects { key, obj, stop in
            if commonKeys.contains(key) {
                CVBufferSetAttachment(outputPixelBuffer, key as! CFString, obj as AnyObject, .shouldPropagate)
            }
        }
        
        let nonPropagatedAttachments = NSDictionary(dictionary: CVBufferGetAttachments(pixelBuffer, .shouldPropagate)!)
        nonPropagatedAttachments.enumerateKeysAndObjects { key, obj, stop in
            if commonKeys.contains(key) {
                CVBufferSetAttachment(outputPixelBuffer, key as! CFString, obj as AnyObject, .shouldNotPropagate)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2016-05-29
          • 2016-11-15
          • 1970-01-01
          • 1970-01-01
          • 2017-06-29
          • 1970-01-01
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多