简体   繁体   English

如何使用AudioConverterFillComplexBuffer iOS将AAC压缩帧解码为PCM

[英]How to decode AAC compressed frames to PCM using AudioConverterFillComplexBuffer iOS

I want to implement SIP calls in my application, and first problem, that I need to solve, is converting audio from compressed AAC format with ADTS header to linear PCM. 我想在我的应用程序中实现SIP调用,我需要解决的第一个问题是将带有ADTS标头的压缩AAC格式的音频转换为线性PCM。

My input data is an NSArray of ADTS frames with different framesize. 我的输入数据是具有不同帧大小的ADTS帧的NSArray。 Each frame is typeof NSMutableData. 每个帧都是NSMutableData类型。 Each frame is of the same format and sample rate, only difference is framesize. 每个帧具有相同的格式和采样率,唯一的区别是帧大小。

I tried to implement sample code, suggested by Igor Rotaru for this issue , but can't make it work. 我尝试实现Igor Rotaru 为此问题建议的示例代码,但无法使其工作。

Now my code looks like this. 现在我的代码看起来像这样。 First of all, I configure the AudioConverter: 首先,我配置AudioConverter:

- (void)configureAudioConverter {
    AudioStreamBasicDescription inFormat;
    memset(&inFormat, 0, sizeof(inFormat));
    inputFormat.mBitsPerChannel = 0;
    inputFormat.mBytesPerFrame = 0;
    inputFormat.mBytesPerPacket = 0;
    inputFormat.mChannelsPerFrame = 1;
    inputFormat.mFormatFlags = kMPEG4Object_AAC_LC;
    inputFormat.mFormatID = kAudioFormatMPEG4AAC;
    inputFormat.mFramesPerPacket = 1024;
    inputFormat.mReserved = 0;
    inputFormat.mSampleRate = 22050;

    AudioStreamBasicDescription outputFormat;
    memset(&outputFormat, 0, sizeof(outputFormat));
    outputFormat.mSampleRate       = inputFormat.mSampleRate;
    outputFormat.mFormatID         = kAudioFormatLinearPCM;
    outputFormat.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger;
    outputFormat.mBytesPerPacket   = 2;
    outputFormat.mFramesPerPacket  = 1;
    outputFormat.mBytesPerFrame    = 2;
    outputFormat.mChannelsPerFrame = 1;
    outputFormat.mBitsPerChannel   = 16;
    outputFormat.mReserved         = 0;

    AudioClassDescription *description = [self
                                      getAudioClassDescriptionWithType:kAudioFormatMPEG4AAC
                                      fromManufacturer:kAppleSoftwareAudioCodecManufacturer];

    OSStatus status =  AudioConverterNewSpecific(&inputFormat, &outputFormat, 1, description, &_audioConverter);

    if (status != 0) {
        printf("setup converter error, status: %i\n", (int)status);
    }
}

After that I wrote the callback function: 之后我编写了回调函数:

struct MyUserData {
    UInt32 mChannels;
    UInt32 mDataSize;
    const void* mData;
    AudioStreamPacketDescription mPacket;
};

OSStatus inInputDataProc(AudioConverterRef inAudioConverter,
                         UInt32 *ioNumberDataPackets,
                         AudioBufferList *ioData,
                         AudioStreamPacketDescription **outDataPacketDescription,
                         void *inUserData)
{
    struct MyUserData* userData = (struct MyUserData*)(inUserData);

    if (!userData->mDataSize) {
        *ioNumberDataPackets = 0;
        return kNoMoreDataError;
    }

    if (outDataPacketDescription) {
        userData->mPacket.mStartOffset = 0;
        userData->mPacket.mVariableFramesInPacket = 0;
        userData->mPacket.mDataByteSize = userData->mDataSize;
        *outDataPacketDescription = &userData->mPacket;
    }

    ioData->mBuffers[0].mNumberChannels = userData->mChannels;
    ioData->mBuffers[0].mDataByteSize = userData->mDataSize;
    ioData->mBuffers[0].mData = (void *)userData->mData;

    // No more data to provide following this run.
    userData->mDataSize = 0;

    return noErr;
}

And my function for decoding frames looks like this: 我的解码帧功能如下:

- (void)startDecodingAudio {
    if (!_converterConfigured){
        return;
    }

    while (true){
        if ([self hasFramesToDecode]){
            struct MyUserData userData = {1, (UInt32)_decoderBuffer[_currPosInDecoderBuf].length, _decoderBuffer[_currPosInDecoderBuf].bytes};

            uint8_t *buffer = (uint8_t *)malloc(128 * sizeof(short int));
            AudioBufferList decBuffer;
            decBuffer.mNumberBuffers = 1;
            decBuffer.mBuffers[0].mNumberChannels = 1;
            decBuffer.mBuffers[0].mDataByteSize = 128 * sizeof(short int);
            decBuffer.mBuffers[0].mData = buffer;

            UInt32 numFrames = 128;

            AudioStreamPacketDescription outPacketDescription;
            memset(&outPacketDescription, 0, sizeof(AudioStreamPacketDescription));
            outPacketDescription.mDataByteSize = 128;
            outPacketDescription.mStartOffset = 0;
            outPacketDescription.mVariableFramesInPacket = 0;

            OSStatus status = AudioConverterFillComplexBuffer(_audioConverter,
                                                              inInputDataProc,
                                                              &userData,
                                                              &numFrames,
                                                              &decBuffer,
                                                              &outPacketDescription);

            NSError *error = nil;

            if (status == kNoMoreDataError) {
                NSLog(@"%u bytes decoded", (unsigned int)decBuffer.mBuffers[0].mDataByteSize);
                [_decodedData appendData:[NSData dataWithBytes:decBuffer.mBuffers[0].mData length:decBuffer.mBuffers[0].mDataByteSize]];
                _currPosInDecoderBuf += 1;
            } else {
                error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];
            }
        } else {
            break;
        }
    }
}

Each time, AudioConverterFillComplexBuffer returns status 1852797029 which is, according to Apple API, kAudioCodecIllegalOperationError. 每次,AudioConverterFillComplexBuffer都返回状态1852797029,根据Apple API,它是kAudioCodecIllegalOperationError。 If somebody succeded in converting with such formats, please, share some examples, or advice. 如果有人成功转换这些格式,请分享一些例子或建议。

最后,我使用StreamingKit库解码了我的字节(可以在这里找到原始的reposiory)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 输出不是生成AudioConverterFillComplexBuffer 以从AAC 转换为PCM? - Output is not generated AudioConverterFillComplexBuffer to convert from AAC to PCM? 使用AVAudioConverter Swift将AAC解码为PCM格式 - Decode AAC to PCM format using AVAudioConverter Swift iPhone:使用 AudioConverterFillComplexBuffer 将 32KHz PCM 编码为 96Kbit AAC 时出现问题 - iPhone: Problems encoding 32KHz PCM to 96Kbit AAC using AudioConverterFillComplexBuffer 在 iOS 上将 PCM (CMSampleBufferRef) 编码为 AAC - 如何设置频率和比特率? - Encoding PCM (CMSampleBufferRef) to AAC on iOS - How to set frequency and bitrate? 通过AudioConverterFillComplexBuffer将AAC转换为LPCM - Converting AAC into LPCM via AudioConverterFillComplexBuffer 为iOS录制时如何将PCM缓冲区实时转换为AAC数据? - How to real-time convert the PCM buffer to AAC data when recording for iOS? 无法使用 AudioFileStreamOpen 的 AudioFileStream_PacketsProc 回调中的 AudioConverterFillComplexBuffer 将 mp3 转换为 PCM - Unable to convert mp3 into PCM using AudioConverterFillComplexBuffer in AudioFileStreamOpen's AudioFileStream_PacketsProc callback 在iOS中使用AudioConverterFillComplexBuffer进行实时音频压缩 - Realtime audio compression with AudioConverterFillComplexBuffer in iOS 在iOS中的mp4文件中随机访问和解码AAC音轨 - Random access and decode AAC audio track in a mp4 file in iOS iOS:如何在运行时使用音频单元重新采样音频(PCM数据)? - iOS: How to resample audio(PCM data) using Audio Unit at runtime?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM