Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call to AudioConverterFillComplexBuffer results in CrashIfClientProvidedBogusAudioBufferList only on MacOS Sierra

I have an audio program that makes a call to AudioConverterFillComplexBuffer with the following code:

OSStatus error = AudioConverterFillComplexBuffer(recorderObj->audioConverter,
                                                     MyAudioConverterCallback,
                                                     (__bridge void *)playerLocal,
                                                     &ioOutputDataPackets,
                                                     convertedData,
                                                     &streamDesc);

When this code runs on 10.6-10.11, it works fine. When the code runs on 10.12, it crashes with the following message

Crashed Thread:        16  com.apple.audio.IOThread.client

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes:       0x0000000000000001, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Illegal instruction: 4
Termination Reason:    Namespace SIGNAL, Code 0x4
Terminating Process:   exc handler [0]

The call stack ends in CrashIfClientProvidedBogusAudioBufferList.

Most articles, documentation and mailing lists would say that I have a bad output buffer but for the life of me, I cannot tell what I would be doing wrong but still have my code work on all versions of MacOS but the latest. Here is how I am setting up the buffer:

AudioBufferList *convertedData = (AudioBufferList*)malloc(sizeof(AudioBufferList) * 2);

convertedData->mNumberBuffers = 1;
convertedData->mBuffers[0].mNumberChannels =  2;
convertedData->mBuffers[0].mDataByteSize = 64 * 1024;
convertedData->mBuffers[0].mData = (UInt8 *)malloc(sizeof(UInt8) * 64 * 1024);

Here is the full stack at the point of the crash

Thread 16 Crashed:: com.apple.audio.IOThread.client
0   com.apple.audio.toolbox.AudioToolbox    0x00007fff89b9a330 CADebuggerStop() + 4
1   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a21e71 CrashIfClientProvidedBogusAudioBufferList + 97
2   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2f710 AudioConverterChain::CallInputProc(unsigned int) + 646
3   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2f386 AudioConverterChain::FillBufferFromInputProc(unsigned int*, CABufferList*) + 130
4   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2f2ee BufferedAudioConverter::GetInputBytes(unsigned int, unsigned int&, CABufferList const*&) + 178
5   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2f1b2 CBRConverter::RenderOutput(CABufferList*, unsigned int, unsigned int&, AudioStreamPacketDescription*) + 106
6   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2225d BufferedAudioConverter::FillBuffer(unsigned int&, AudioBufferList&, AudioStreamPacketDescription*) + 281
7   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2f2c3 BufferedAudioConverter::GetInputBytes(unsigned int, unsigned int&, CABufferList const*&) + 135
8   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a9369b Resampler2Wrapper::RenderOutput(CABufferList*, unsigned int, unsigned int&) + 183
9   com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2225d BufferedAudioConverter::FillBuffer(unsigned int&, AudioBufferList&, AudioStreamPacketDescription*) + 281
10  com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2f2c3 BufferedAudioConverter::GetInputBytes(unsigned int, unsigned int&, CABufferList const*&) + 135
11  com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2f1b2 CBRConverter::RenderOutput(CABufferList*, unsigned int, unsigned int&, AudioStreamPacketDescription*) + 106
12  com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2225d BufferedAudioConverter::FillBuffer(unsigned int&, AudioBufferList&, AudioStreamPacketDescription*) + 281
13  com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2253f AudioConverterChain::RenderOutput(CABufferList*, unsigned int, unsigned int&, AudioStreamPacketDescription*) + 99
14  com.apple.audio.toolbox.AudioToolbox    0x00007fff89a2225d BufferedAudioConverter::FillBuffer(unsigned int&, AudioBufferList&, AudioStreamPacketDescription*) + 281
15  com.apple.audio.toolbox.AudioToolbox    0x00007fff89a21d2f AudioConverterFillComplexBuffer + 282
16  com.pc-intercom.Intercom        0x0000000107a52803 0x107a4a000 + 34819
17  com.apple.audio.units.Components    0x000000010a38c97c AUHAL::AUIOProc(unsigned int, AudioTimeStamp const*, AudioBufferList const*, AudioTimeStamp const*, AudioBufferList*, AudioTimeStamp const*, void*) + 2324
18  com.apple.audio.CoreAudio       0x00007fff8a71f951 HALC_ProxyIOContext::IOWorkLoop() + 4369
19  com.apple.audio.CoreAudio       0x00007fff8a71e667 HALC_ProxyIOContext::IOThreadEntry(void*) + 131
20  com.apple.audio.CoreAudio       0x00007fff8a71e38b HALB_IOThread::Entry(void*) + 75
21  libsystem_pthread.dylib         0x0000000108134aab _pthread_body + 180
22  libsystem_pthread.dylib         0x00000001081349f7 _pthread_start + 286
23  libsystem_pthread.dylib         0x0000000108134221 thread_start + 13

If anyone has any suggestions on how I can debug this issue, I would greatly appreciate the help.

like image 440
Josh Laase Avatar asked Oct 30 '22 17:10

Josh Laase


1 Answers

In MyAudioConverterCallback, ioDataPacketCount is supposed to return frames for LPCM (I guess packets are frames for uncompressed audio), so set it to:

*ioDataPacketCount = recorderObj->inputBuffer->mBuffers[0].mDataByteSize/recorderObj->streamFormat.mBytesPerFrame; 

Pass a NULL AudioStreamPacketDescription to AudioConverterFillComplexBuffer instead of an array of 1 (this was causing crashes for me on 10.11). Your destination format is LPCM, so packet descriptions are unnecessary because your "packets" are all the same size.

Similarly, your source format is LPCM too, so you can remove the code that returns packet descriptions in MyAudioConverterCallback - it's also wrong.

On my machine, I get non-interleaved stereo for streamFormat which means MyAudioConverterCallback has to fill out ioData->mBuffers[1] too.

When setting up your convertedData AudioBufferList, sizePerPacket was using the source format packet size instead of the destination packet size. It should be:

sizePerPacket = mOutputFormat.mBytesPerPacket;

And finally, even when it's not crashing, this code can't be right because you're recording (say) 512 frames from the microphone, then asking the audio converter to convert 16384 - that's going to give you audio glitches.

like image 101
Rhythmic Fistman Avatar answered Nov 12 '22 21:11

Rhythmic Fistman