(快速)当AudioStreamPacketDescription为零时调试CrashIfClientProvidedBogusAudioBufferList的方法?

尝试一次我得到一个CrashIfClientProvidedBogusAudioBufferList异常

AudioConverterFillComplexBuffer回调返回.抛出此异常有什么可能的原因?

供参考,这是我的电话

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的结构:

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为零,这个回调将正常工作

最佳答案 看起来像AudioStreamPacketDescription是nil不是问题.

根据Apple文档,它可以是零,基本上它取决于音频格式:

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)

希望它能解决您的问题.

点赞