Создание копии CMSampleBuffer в Swift возвращает OSStatus -12743 (неверный формат мультимедиа)
Я пытаюсь выполнить глубокий клон CMSampleBuffer
хранить выходные данные AVCaptureSession
, Я получаю ошибку kCMSampleBufferError_InvalidMediaFormat
(OSStatus -12743)
когда я запускаю функцию CMSampleBufferCreateForImageBuffer
, Я не вижу, как я не соответствовал CVImageBuffer
и CMSampleBuffer
описание формата. Кто-нибудь знает, где я ошибся? Это мой тестовый код.
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 ответ
Я смог решить проблему, создав описание формата из вновь созданного буфера изображения и используя его вместо описания формата из исходного буфера сэмплов. К сожалению, хотя это решает проблему здесь, описания форматов не совпадают и вызывают проблему дальше.
Недавно я столкнулся с той же проблемой. После небольшого расследования, CMVideoFormatDescriptionMatchesImageBuffer()
Документация по функциям дала немного понимания.
Эта функция использует ключи, возвращаемые CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers, для сравнения расширений данного описания формата с вложениями данного буфера изображения (если вложение отсутствует в любом из них, оно должно отсутствовать в обоих). Он также проверяет kCMFormatDescriptionExtension_BytesPerRow с CVPixelBufferGetBytesPerRow, если это применимо.
В моем случае я не копировал некоторые расширения описания формата в качестве вложений 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);
}
}];
Версия Swift для ответа Raymanman.
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)
}
}