Deep Copy of Audio CMSampleBuffer

后端 未结 1 819
耶瑟儿~
耶瑟儿~ 2020-12-29 09:32

I am trying to create a copy of a CMSampleBuffer as returned by captureOutput in a AVCaptureAudioDataOutputSampleBufferDelegate.

The problem I am having

相关标签:
1条回答
  • 2020-12-29 10:03

    Here is a working solution I finally implemented. I sent this snippet to Apple Developer Technical support and asked them to check if it is a correct way to copy incoming sample buffer. The basic idea is copy AudioBufferList and then create a CMSampleBuffer and set AudioBufferList to this sample.

    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;
    }
    

    Code-Level Support answer:

    This code looks ok (though you’ll want to add some additional error checking). I've successfully tested it in an app that implements the AVCaptureAudioDataOutput delegate captureOutput:didOutputSampleBuffer:fromConnection: method to capture and record audio. The captured audio I'm getting when using this deep copy code appears to be the same as what I get when directly using the provided sample buffer (without the deep copy).

    Apple Developer Technical Support

    0 讨论(0)
提交回复
热议问题