audioCMSampleBuffer的深度副本

我正在尝试创build一个由CaptureOutput在AVCaptureAudioDataOutputSampleBufferDelegate返回的CMSampleBuffer的副本。

我遇到的问题是,我的框架来自委托方法captureOutput:didOutputSampleBuffer:fromConnection:在我长时间保留在CFArray后被删除。

显然,我需要创build传入缓冲区的深层副本进行进一步处理。 我也知道CMSampleBufferCreateCopy只创build浅拷贝。

SO上提出的相关问题很less:

  • 从CMSampleBuffer提取数据以创build深层副本
  • 在Swift中创buildCMSampleBuffer的副本将返回OSStatus -12743(无效的媒体格式)
  • CMImageBuffer或CVImageBuffer的深度拷贝

但是他们都没有帮我正确使用具有12个参数的CMSampleBufferCreate函数:

  CMSampleBufferRef copyBuffer; CMBlockBufferRef data = CMSampleBufferGetDataBuffer(sampleBuffer); CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer); CMItemCount itemCount = CMSampleBufferGetNumSamples(sampleBuffer); CMTime duration = CMSampleBufferGetDuration(sampleBuffer); CMTime presentationStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); CMSampleTimingInfo timingInfo; timingInfo.duration = duration; timingInfo.presentationTimeStamp = presentationStamp; timingInfo.decodeTimeStamp = CMSampleBufferGetDecodeTimeStamp(sampleBuffer); size_t sampleSize = CMBlockBufferGetDataLength(data); CMBlockBufferRef sampleData; if (CMBlockBufferCopyDataBytes(data, 0, sampleSize, &sampleData) != kCMBlockBufferNoErr) { VLog(@"error during copying sample buffer"); } // Here I tried data and sampleData CMBlockBuffer instance, but no success OSStatus status = CMSampleBufferCreate(kCFAllocatorDefault, data, isDataReady, nil, nil, formatDescription, itemCount, 1, &timingInfo, 1, &sampleSize, &copyBuffer); if (!self.sampleBufferArray) { self.sampleBufferArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); //EXC_BAD_ACCESS crash when trying to add sampleBuffer to the array CFArrayAppendValue(self.sampleBufferArray, copyBuffer); } else { CFArrayAppendValue(self.sampleBufferArray, copyBuffer); } 

你如何深层复制Audio CMSampleBuffer? 随意在你的答案中使用任何语言(swift / objective-c)。

这是我最终实施的一个工作解决scheme。 我将这段代码发送给了Apple Developer Technical Support,并要求他们检查复制传入缓冲区是否正确。 基本的想法是复制AudioBufferList ,然后创build一个CMSampleBuffer ,并将AudioBufferList设置为此示例。

  AudioBufferList audioBufferList; CMBlockBufferRef blockBuffer; //Create an AudioBufferList containing the data from the CMSampleBuffer, //and a CMBlockBuffer which references the data in that AudioBufferList. CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); NSUInteger size = sizeof(audioBufferList); char buffer[size]; memcpy(buffer, &audioBufferList, size); //This is the Audio data. NSData *bufferData = [NSData dataWithBytes:buffer length:size]; const void *copyBufferData = [bufferData bytes]; copyBufferData = (char *)copyBufferData; CMSampleBufferRef copyBuffer = NULL; OSStatus status = -1; /* Format Description */ AudioStreamBasicDescription audioFormat = *CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef) CMSampleBufferGetFormatDescription(sampleBuffer)); CMFormatDescriptionRef format = NULL; status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &audioFormat, 0, nil, 0, nil, nil, &format); CMFormatDescriptionRef formatdes = NULL; status = CMFormatDescriptionCreate(NULL, kCMMediaType_Audio, 'lpcm', NULL, &formatdes); if (status != noErr) { NSLog(@"Error in CMAudioFormatDescriptionCreator"); CFRelease(blockBuffer); return; } /* Create sample Buffer */ CMItemCount framesCount = CMSampleBufferGetNumSamples(sampleBuffer); CMSampleTimingInfo timing = {.duration= CMTimeMake(1, 44100), .presentationTimeStamp= CMSampleBufferGetPresentationTimeStamp(sampleBuffer), .decodeTimeStamp= CMSampleBufferGetDecodeTimeStamp(sampleBuffer)}; status = CMSampleBufferCreate(kCFAllocatorDefault, nil , NO,nil,nil,format, framesCount, 1, &timing, 0, nil, &copyBuffer); if( status != noErr) { NSLog(@"Error in CMSampleBufferCreate"); CFRelease(blockBuffer); return; } /* Copy BufferList to Sample Buffer */ AudioBufferList receivedAudioBufferList; memcpy(&receivedAudioBufferList, copyBufferData, sizeof(receivedAudioBufferList)); //Creates a CMBlockBuffer containing a copy of the data from the //AudioBufferList. status = CMSampleBufferSetDataBufferFromAudioBufferList(copyBuffer, kCFAllocatorDefault , kCFAllocatorDefault, 0, &receivedAudioBufferList); if (status != noErr) { NSLog(@"Error in CMSampleBufferSetDataBufferFromAudioBufferList"); CFRelease(blockBuffer); return; } 

代码级支持答案:

这段代码看起来不错(尽pipe你会想添加一些额外的错误检查)。 我已经在一个实现了AVCaptureAudioDataOutput委托captureOutput:didOutputSampleBuffer:fromConnection:方法的应用程序中成功地testing了它,以捕获和loggingaudio。 使用此深度复制代码时所捕获的audio看起来与直接使用所提供的示例缓冲区(不带深度复制)时所获得的audio相同。

苹果开发者技术支持