i'm getting a CrashIfClientProvidedBogusAudioBufferList
exception when attempting once my
AudioConverterFillComplexBuffer
callback returns. What are the possibile reasons why this exception would be thrown?
for reference, here is my call
AudioConverterFillComplexBuffer(audioConverterRef,
fillComplexCallback,
&convertInfo,
&framesToDecode,
&localPcmBufferList,
& the callback:
func fillComplexxCallback(myConverter: AudioConverterRef, packetNumber: UnsafeMutablePointer<UInt32>,
ioData: UnsafeMutablePointer<AudioBufferList>, aspd: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>,
userInfo: UnsafeMutablePointer<Void>) -> OSStatus {
var convertInfo = UnsafeMutablePointer<AudioConvertInfo>(userInfo).memory
if (packetNumber.memory > (convertInfo.audioBuffer.mDataByteSize / convertInfo.numberOfPackets)) {
packetNumber.memory = (convertInfo.audioBuffer.mDataByteSize / convertInfo.numberOfPackets)
}
ioData.memory.mNumberBuffers = 1
var buffer = AudioBuffer(mNumberChannels: 2, mDataByteSize: convertInfo.audioBuffer.mDataByteSize, mData: ioData.memory.mBuffers.mData)
ioData.memory.mBuffers = buffer
/* if the following is uncommented out, a exception is thrown */
// aspd.memory = convertInfo.packetDescriptions
packetNumber.memory = convertInfo.numberOfPackets
convertInfo.done = true
return 0
}
here's AudioConvertInfo's
struct:
struct AudioConvertInfo {
var done: Bool! //conversion of audio is finished
var numberOfPackets: UInt32!
var audioBuffer: AudioBuffer!
var audioPlayer: CCPlayer!
var packetDescriptions: AudioStreamPacketDescription!
init(done: Bool?, numberOfPackets: UInt32?, audioBuffer: AudioBuffer?, packetDescriptions: AudioStreamPacketDescription!, audioPlayer: CCPlayer!) {
self.done = done
self.numberOfPackets = numberOfPackets
self.audioBuffer = audioBuffer
self.packetDescriptions = packetDescriptions
self.audioPlayer = audioPlayer
}
}
I can't seem to find any solid documentation around. I've noticed was the aspd (AudioStreamPacketDescription
) is returning nil. This is important to determine one packet in a buffer of audio data where the sizes of the packets differ or where there is non-audio data between audio packets. This code will throw an exception on aspd.memory = convertInfo.packetDescriptions , but if the code is commented out - the CrashIfClientProvidedBogusAudioBufferList is thrown. My theory is that this callback will work fine if i figure out why the AudioStreamPacketDescription is nil
Looks like AudioStreamPacketDescription is nil
is not a problem.
According to Apple documentation it can be nil, basically it depends on audio format:
AudioConverterComplexInputDataProc
outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>
- If not NULL on input, the audio converter expects this callback to provide an array of AudioStreamPacketDescription structures on output, one for each packet of audio data you are providing in the ioData parameter.
AudioConverterFillComplexBuffer
outPacketDescription: UnsafeMutablePointer<AudioStreamPacketDescription>
- On input, must point to a block of memory capable of holding the number of packet descriptions specified in the ioOutputDataPacketSize parameter. (See Audio Format Services Reference for functions that let you determine whether an audio format uses packet descriptions). If not NULL on output and if the audio converter’s output format uses packet descriptions, then this parameter contains an array of packet descriptions.
The real problem is placed in AudioConvertInfo
structure in this line:
var packetDescriptions: AudioStreamPacketDescription!
Structure keeps just single AudioStreamPacketDescription
structure.
Then you use it in fillComplexCallback
function:
outDataPacketDescription.memory.memory = convertInfo.packetDescriptions
So you are trying to set single AudioStreamPacketDescription
structure to parameter outDataPacketDescription
that expects array of AudioStreamPacketDescription
structures (not just single instance).
This problem can be fixed by keeping and using array of AudioStreamPacketDescription
structures.
Updated version of AudioConvertInfo
structure:
struct AudioConvertInfo {
var done: Bool!
var numberOfPackets: UInt32!
var audioBuffer: AudioBuffer!
var audioPlayer: CCPlayer!
var packetDescriptions: UnsafeMutablePointer<AudioStreamPacketDescription>!
init(done: Bool?, numberOfPackets: UInt32?, audioBuffer: AudioBuffer?, packetDescriptions: UnsafeMutablePointer<AudioStreamPacketDescription>!, audioPlayer: CCPlayer!) {
self.done = done
self.numberOfPackets = numberOfPackets
self.audioBuffer = audioBuffer
self.packetDescriptions = packetDescriptions
self.audioPlayer = audioPlayer
}
}
// Usage:
convertInfo = AudioConvertInfo(done: false, numberOfPackets: numberPackets, audioBuffer: AudioBuffer(mNumberChannels: 2, mDataByteSize: numberBytes, mData: &iData), packetDescriptions: packetDescriptions, audioPlayer: self)
Updated version of fillComplexCallback
function:
func fillComplexCallback(inAudioConverter: AudioConverterRef, ioNumberDataPackets: UnsafeMutablePointer<UInt32>, ioData: UnsafeMutablePointer<AudioBufferList>, outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>, inUserData: UnsafeMutablePointer<Void>) -> OSStatus {
var convertInfo = UnsafeMutablePointer<AudioConvertInfo>(inUserData).memory
if convertInfo.done == true {
ioNumberDataPackets.memory = 0
return 100
}
ioData.memory.mNumberBuffers = 1
let buffer = convertInfo.audioBuffer
ioData.memory.mBuffers = buffer
if outDataPacketDescription != nil {
outDataPacketDescription.memory = convertInfo.packetDescriptions
}
ioNumberDataPackets.memory = convertInfo.numberOfPackets
convertInfo.done = true
return 0
}
// Usage:
status = AudioConverterFillComplexBuffer(audioConverterRef, fillComplexCallback, &convertInfo!, &framesToDecode, &localPcmBufferList!, nil)
Hope it will resolve your issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With