编写静默CMSampleBuffer会导致崩溃:CrashIfClientProvidedBogusAudioBufferList

时间:2015-12-04 12:09:50

标签: objective-c macos avfoundation core-audio cmsamplebufferref

我正在使用AVAssetwriter录制视频/音频,并希望能够编写静音样本缓冲区。我对CoreAudio没有经验,所以我无法找到一个可行的解决方案。

想法是在音频设备断开连接之前继续录制视频,直到重新连接。问题是,AVFoundation以某种方式将音频推到前面,因此生成的电影文件不同步。

我当前的实现尝试创建一个空的/静默的CMSampleBuffer,以放置在没有连接音频设备的段之间。

if (audioOutput == captureOutput && audioWriterInput.readyForMoreMediaData) {
    if (needToFillAudioGap) {

        CMTime temp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
        CMItemCount numSamples = temp.value - lastAudioDisconnect.value;
        OSStatus status;
        CMBlockBufferRef bbuf = NULL;
        CMSampleBufferRef sbuf = NULL;
        int nchans = 2;
        size_t buflen = numSamples * nchans * sizeof(float);


        NSMutableData* data = [NSMutableData dataWithLength:buflen];
        void* samples = [data mutableBytes];
        status = CMBlockBufferCreateWithMemoryBlock(
                                                    kCFAllocatorDefault,
                                                    samples,
                                                    buflen,
                                                    kCFAllocatorNull,
                                                    NULL,
                                                    0,
                                                    buflen,
                                                    0,
                                                    &bbuf);
        if (status != noErr) {
            NSLog(@"CMBlockBufferCreateWithMemoryBlock error: %d", (int)status);
            return;
        }
        CMBlockBufferRef blockBufferContiguous;
        status = CMBlockBufferCreateContiguous(kCFAllocatorDefault,
                                               bbuf,
                                               kCFAllocatorNull,
                                               NULL,
                                               0,
                                               buflen,
                                               0,
                                               &blockBufferContiguous);

        CFRelease(bbuf);
        if(status != noErr)
        {
            printf("CMBlockBufferCreateContiguous failed with error %d\n", (int)status);
            return;
        }

        status = CMAudioSampleBufferCreateReadyWithPacketDescriptions(kCFAllocatorDefault, blockBufferContiguous, CMSampleBufferGetFormatDescription(sampleBuffer), numSamples, lastAudioDisconnect, NULL, &sbuf);
        CFRelease(blockBufferContiguous);

        if (status != noErr) {
            NSLog(@"CMSampleBufferCreate error: %d", (int)status);
            return;
        }
        BOOL r = [audioWriterInput appendSampleBuffer:sbuf];
        if (!r) {
            NSLog(@"appendSampleBuffer error: %d", (int)status);
            return;
        }
        CFRelease(sbuf);
        NSLog(@"Filling Audio Gap");
        needToFillAudioGap = false;
    } else {

        if ([audioWriterInput appendSampleBuffer:sampleBuffer])
            lastAudioDisconnect = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    }
}

顶部的sampleBuffer是重新连接音频设备后的第一个samplebuffer。这给了我关于我必须填补多长时间的信息。 LastAudioDisconnect始终保存已写入的最后一个音频samplebuffer的Presentation Timestamp。

启用Guard Malloc后,程序崩溃:CrashIfClientProvidedBogusAudioBufferList

编辑: 禁用Guard Malloc后,我可以在录制时多次重新连接音频设备,当我停止录制时,间隙就没有问题了。

问题是我在重新连接设备后只有几分钟的时间来停止录制,因为AVAssetWriter随机失败,错误代码为11800(AVErrorUnknown)。

1 个答案:

答案 0 :(得分:0)

错误是因为您创建的CMSampleBuffer太长。

创建的CMSampleBuffer应该与填充实时音频的前进样本缓冲区的长度相同(包含相同数量的样本)。如有必要,您可以创建多个静默缓冲区,并以与实时音频缓冲区相同的速率传送它们。