[英]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.