将AudioBufferList转换为CMSampleBuffer会产生意外的结果 [英] Converting an AudioBufferList to a CMSampleBuffer Produces Unexpected Results

查看:421
本文介绍了将AudioBufferList转换为CMSampleBuffer会产生意外的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将从音频单元获得的AudioBufferList转换为CMSampleBuffer,然后可以将其传递到AVAssetWriter,以保存来自麦克风的音频.这种转换有效,因为我进行转换的调用不会失败,但是记录最终不会失败,而且我在日志中看到一些值得关注的输出.

I'm trying to convert an AudioBufferList that I get from an Audio Unit into a CMSampleBuffer that I can pass into an AVAssetWriter to save audio from the microphone. This conversion works, in that the calls I'm making to perform the transformation don't fail, but recording ultimately does fail, and I'm seeing some output in the logs that seems to be cause for concern.

我正在使用的代码如下:

The code I'm using looks like this:

- (void)handleAudioSamples:(AudioBufferList*)samples numSamples:(UInt32)numSamples hostTime:(UInt64)hostTime {
    // Create a CMSampleBufferRef from the list of samples, which we'll own
    AudioStreamBasicDescription monoStreamFormat;
    memset(&monoStreamFormat, 0, sizeof(monoStreamFormat));
    monoStreamFormat.mSampleRate = 48000;
    monoStreamFormat.mFormatID = kAudioFormatLinearPCM;
    monoStreamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved;
    monoStreamFormat.mBytesPerPacket = 2;
    monoStreamFormat.mFramesPerPacket = 1;
    monoStreamFormat.mBytesPerFrame = 2;
    monoStreamFormat.mChannelsPerFrame = 1;
    monoStreamFormat.mBitsPerChannel = 16;

    CMFormatDescriptionRef format = NULL;
    OSStatus status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &monoStreamFormat, 0, NULL, 0, NULL, NULL, &format);
    if (status != noErr) {
        // really shouldn't happen
        return;
    }

    CMSampleTimingInfo timing = { CMTimeMake(1, 48000), kCMTimeZero, kCMTimeInvalid };

    CMSampleBufferRef sampleBuffer = NULL;
    status = CMSampleBufferCreate(kCFAllocatorDefault, NULL, false, NULL, NULL, format, numSamples, 1, &timing, 0, NULL, &sampleBuffer);
    if (status != noErr) {
        // couldn't create the sample buffer
        PTKLogError(@"Failed to create sample buffer");
        CFRelease(format);
      return;
    }

    // add the samples to the buffer
    status = CMSampleBufferSetDataBufferFromAudioBufferList(sampleBuffer,
                                                            kCFAllocatorDefault,
                                                            kCFAllocatorDefault,
                                                            0,
                                                            samples);
    if (status != noErr) {
        PTKLogError(@"Failed to add samples to sample buffer");
        CFRelease(sampleBuffer);
        CFRelease(format);
        return;
    }

    NSLog(@"Original sample buf size: %ld for %d samples from %d buffers, first buffer has size %d", CMSampleBufferGetTotalSampleSize(sampleBuffer), numSamples, samples->mNumberBuffers, samples->mBuffers[0].mDataByteSize);
    NSLog(@"Original sample buf has %ld samples", CMSampleBufferGetNumSamples(sampleBuffer));

正如我提到的那样,代码本身似乎并没有失败,但是AVAssetWriter不喜欢它,基于事实,我正在创建的CMSampleBuffer的大小似乎为0.正在记录以下日志条目:

As I mentioned, the code doesn't seem to be failing, per se, but AVAssetWriter doesn't like it, and the CMSampleBuffer that I'm creating seems to have size 0, based on the fact that the following log entries are being logged:

2015-07-09 19:34:00.710 xxxx[1481:271334] Original sample buf size: 0 for 1024 samples from 1 buffers, first buffer has size 2048
2015-07-09 19:34:00.710 xxxx[1481:271334] Original sample buf has 1024 samples

奇怪的是,样本缓冲区报告它有1024个样本,但大小为0.原始AudioBufferList具有2048字节的数据,这是我期望的1024个2字节样本的数据.

Oddly, the sample buffer reports that it has 1024 samples, but size 0. The original AudioBufferList has 2048 bytes of data, which is what I'd expect for 1024 2-byte samples.

我在初始化和填充CMSampleBuffer的方式上做错了吗?

Am I doing something wrong in terms of the way I'm initializing and populating the CMSampleBuffer?

推荐答案

事实证明,样本大小以0返回的事实是一条红色鲱鱼.清理完几件事后-值得注意的是,我正确设置了时间戳,如下所示:

It turns out that the fact that the sample size was coming back as 0 was a red herring. Once I cleaned up a few things--notably, I set the timestamp correctly, like so:

uint64_t timeNS = (uint64_t)(hostTime * _hostTimeToNSFactor);
CMTime presentationTime = CMTimeMake(timeNS, 1000000000);
CMSampleTimingInfo timing = { CMTimeMake(1, 48000), presentationTime, kCMTimeInvalid };

录制开始工作.

因此,如果其他人因报告的0个样本缓冲区大小而被淘汰,请注意,至少在将数据馈入AVAssetWriter的情况下,这是可以的.

So, in the event that someone else is thrown off by the reportedly 0 sample buffer size, be aware that this is OK, at least in the case in which you're feeding the data into an AVAssetWriter.

这篇关于将AudioBufferList转换为CMSampleBuffer会产生意外的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆