(swift) 当 AudioStreamPacketDescription 为 nil 时调试 CrashIfClientProvidedBogusAudioBufferList 的方法?
(swift) ways to debug CrashIfClientProvidedBogusAudioBufferList when the AudioStreamPacketDescription is nil?
我在尝试一次时遇到 CrashIfClientProvidedBogusAudioBufferList
异常
AudioConverterFillComplexBuffer
回调 returns。抛出此异常的可能原因是什么?
供参考,这是我的电话
AudioConverterFillComplexBuffer(audioConverterRef,
fillComplexCallback,
&convertInfo,
&framesToDecode,
&localPcmBufferList,
&回调:
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
}
这里是 AudioConvertInfo's
结构:
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
}
}
我似乎找不到任何可靠的文档。我注意到 aspd (AudioStreamPacketDescription
) 正在返回 nil。这对于确定音频数据缓冲区中数据包大小不同或音频数据包之间存在非音频数据的数据包很重要。此代码将在 aspd.memory = convertInfo.packetDescriptions 上抛出异常,但如果代码被注释掉 - 将抛出 CrashIfClientProvidedBogusAudioBufferList。我的理论是,如果我弄清楚为什么 AudioStreamPacketDescription 为 nil
,则此回调将正常工作
看起来 AudioStreamPacketDescription is nil
不是问题。
根据 Apple 文档可以是 nil,基本上取决于音频格式:
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.
真正的问题放在AudioConvertInfo
结构这一行:
var packetDescriptions: AudioStreamPacketDescription!
结构只保留单个 AudioStreamPacketDescription
结构。
然后在 fillComplexCallback
函数中使用它:
outDataPacketDescription.memory.memory = convertInfo.packetDescriptions
因此您试图将单个 AudioStreamPacketDescription
结构设置为参数 outDataPacketDescription
,该参数需要 AudioStreamPacketDescription
结构数组(不仅仅是单个实例)。
这个问题可以通过保留和使用 AudioStreamPacketDescription
结构数组来解决。
AudioConvertInfo
结构的更新版本:
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)
fillComplexCallback
函数的更新版本:
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)
希望它能解决您的问题。
我在尝试一次时遇到 CrashIfClientProvidedBogusAudioBufferList
异常
AudioConverterFillComplexBuffer
回调 returns。抛出此异常的可能原因是什么?
供参考,这是我的电话
AudioConverterFillComplexBuffer(audioConverterRef,
fillComplexCallback,
&convertInfo,
&framesToDecode,
&localPcmBufferList,
&回调:
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
}
这里是 AudioConvertInfo's
结构:
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
}
}
我似乎找不到任何可靠的文档。我注意到 aspd (AudioStreamPacketDescription
) 正在返回 nil。这对于确定音频数据缓冲区中数据包大小不同或音频数据包之间存在非音频数据的数据包很重要。此代码将在 aspd.memory = convertInfo.packetDescriptions 上抛出异常,但如果代码被注释掉 - 将抛出 CrashIfClientProvidedBogusAudioBufferList。我的理论是,如果我弄清楚为什么 AudioStreamPacketDescription 为 nil
看起来 AudioStreamPacketDescription is nil
不是问题。
根据 Apple 文档可以是 nil,基本上取决于音频格式:
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.
真正的问题放在AudioConvertInfo
结构这一行:
var packetDescriptions: AudioStreamPacketDescription!
结构只保留单个 AudioStreamPacketDescription
结构。
然后在 fillComplexCallback
函数中使用它:
outDataPacketDescription.memory.memory = convertInfo.packetDescriptions
因此您试图将单个 AudioStreamPacketDescription
结构设置为参数 outDataPacketDescription
,该参数需要 AudioStreamPacketDescription
结构数组(不仅仅是单个实例)。
这个问题可以通过保留和使用 AudioStreamPacketDescription
结构数组来解决。
AudioConvertInfo
结构的更新版本:
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)
fillComplexCallback
函数的更新版本:
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)
希望它能解决您的问题。