Re: crashing in calls to AudioConverter on 10.3.9
Re: crashing in calls to AudioConverter on 10.3.9
- Subject: Re: crashing in calls to AudioConverter on 10.3.9
- From: Christopher Ashworth <email@hidden>
- Date: Mon, 27 Mar 2006 21:41:30 -0500
On Mar 27, 2006, at 2:48 PM, William Stewart wrote:
Thoughts?
not alot :-( What do the crash logs look like?
While I am continuing to work on example code that reproduces the
crash, I have been able to narrow it down a bit more:
I have found that if I add a single global semaphore and add one
synchronization block around AudioConverterFillComplexBuffer, this
appears to solve the crashes on 10.3.9.
In other words, the app with:
err = AudioConverterFillComplexBuffer( _converter,
_converterInputProc, ¶meters, &frameCountInOutCoords,
_conversionAudioBufferList, nil );
will crash on 10.3.9, and the one with:
@synchronized(converter_semaphore) {
err = AudioConverterFillComplexBuffer( _converter,
_converterInputProc, ¶meters, &frameCountInOutCoords,
_conversionAudioBufferList, nil );
}
will not. And this only happens when two or more sound file objects
are playing.
This is, naturally, quite odd, since the synchronized block is
protecting completely separate resources. (And since both versions
work on 10.4.)
While this does appear to solve the crash, the performance penalty is
high. (High enough to make the app unusable.)
By placing some logging statements in my converter input proc, I note
that the crash on the unsynchronized version will occur *after* my
input proc has been called and has *successfully* returned the
requested data. In other words, my input proc is called, it returns
the requested number of packets with no errors, and at some point
before AudioConverterFillComplexBuffer returns, the program crashes.
Here is my converter input proc, for reference (is there anything
wrong with it?):
static OSStatus _converterInputProc( AudioConverterRef inAudioConverter,
UInt32 *ioNumberDataPackets,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription,
void * userData )
{
OSStatus err = noErr;
UInt32 conversionBufferByteCount = 0;
AudioFileID fileID = ((conversionParams*)userData)->fileID;
void *conversionBuffer = ((conversionParams*)userData)-
>conversionBuffer;
AudioStreamPacketDescription *conversionPacketDescriptions =
((conversionParams*)userData)->conversionPacketDescriptions;
UInt64 *packetOffset = ((conversionParams*)userData)->packetOffset;
UInt32 fileMaxPacketSize = ((conversionParams*)userData)-
>fileMaxPacketSize;
UInt64 fileTotalPacketCount = ((conversionParams*)userData)-
>fileTotalPacketCount;
UInt32 bufferSizeInFilePackets = ((conversionParams*)userData)-
>bufferSizeInFilePackets;
// Initialize in case of failure.
ioData->mBuffers[0].mData = nil;
ioData->mBuffers[0].mDataByteSize = 0;
// Clear conversion buffer.
memset(conversionBuffer, 0, fileMaxPacketSize *
bufferSizeInFilePackets);
// Confirm that ioNumberDataPackets worth of information will fit
// in the conversion buffer.
if (*ioNumberDataPackets > bufferSizeInFilePackets)
*ioNumberDataPackets = bufferSizeInFilePackets;
// If there are not enough packets left in the file, then read
what's left.
if (*packetOffset + *ioNumberDataPackets > fileTotalPacketCount)
*ioNumberDataPackets = fileTotalPacketCount - *packetOffset;
if (*ioNumberDataPackets) {
err = AudioFileReadPackets( fileID,
NO,
&conversionBufferByteCount,
conversionPacketDescriptions,
*packetOffset,
ioNumberDataPackets,
conversionBuffer );
if (err) {
checkStatus(err);
describeAudioFileError(err);
goto exit;
}
if (*ioNumberDataPackets) {
*packetOffset += *ioNumberDataPackets;
ioData->mBuffers[0].mData = conversionBuffer;
ioData->mBuffers[0].mDataByteSize = conversionBufferByteCount;
if (outDataPacketDescription)
*outDataPacketDescription = conversionPacketDescriptions;
}
}
exit:
return err;
}
The crash tracebacks are unfortunately erratic, but will often look
something like this:
Thread 3 Crashed:
0 <<00000000>> 0xffff87dc __memcpy + 0x3c
1 ....audio.toolbox.AudioToolbox 0x93c0516c
AudioConverterChain::FillBufferFromInputProc(unsigned long*, unsigned
long*, CABufferList*, AudioStreamPacketDescription**) + 0x13c
2 ....audio.toolbox.AudioToolbox 0x93c0147c
BufferedAudioConverter::GetInputBytes(unsigned long, unsigned long&,
CABufferList const*&) + 0xd8
3 ....audio.toolbox.AudioToolbox 0x93c016a8
CBRConverter::RenderOutput(CABufferList*, unsigned long, unsigned
long&, AudioStreamPacketDescription*) + 0x58
4 ....audio.toolbox.AudioToolbox 0x93c012b0
BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&,
AudioStreamPacketDescription*) + 0x124
5 ....audio.toolbox.AudioToolbox 0x93c01450
BufferedAudioConverter::GetInputBytes(unsigned long, unsigned long&,
CABufferList const*&) + 0xac
6 ....audio.toolbox.AudioToolbox 0x93c05c94
Resampler2Wrapper::RenderOutput(CABufferList*, unsigned long,
unsigned long&) + 0x9c
7 ....audio.toolbox.AudioToolbox 0x93c012b0
BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&,
AudioStreamPacketDescription*) + 0x124
8 ....audio.toolbox.AudioToolbox 0x93c04fac
AudioConverterChain::RenderOutput(CABufferList*, unsigned long,
unsigned long&, AudioStreamPacketDescription*) + 0x58
9 ....audio.toolbox.AudioToolbox 0x93c012b0
BufferedAudioConverter::FillBuffer(unsigned long&, AudioBufferList&,
AudioStreamPacketDescription*) + 0x124
10 ....audio.toolbox.AudioToolbox 0x93c01610
AudioConverterFillComplexBuffer + 0x118
11 com.figure53.qlab.SoundCue 0x00813e3c -[Sound(SoundPrivate)
fillBuffer] + 0x25c
12 com.figure53.qlab.SoundCue 0x0080eae4 -[Sound(SoundPrivate)
feedFile:] + 0x11c
13 com.apple.Foundation 0x90a6a510 forkThreadForFunction
+ 0x6c
14 libSystem.B.dylib 0x90024990 _pthread_body + 0x28
I can, of course, provide more if required.
Does this give you any more to go on? The effect of the single
synchronization block seems especially interesting.
Chris
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden