【问题标题】:How to convert AudioBufferList containing AAC data to CMSampleBuffer如何将包含 AAC 数据的 AudioBufferList 转换为 CMSampleBuffer
【发布时间】:2020-04-11 13:21:48
【问题描述】:

我正在使用AudioConverter 将通过AVCaptureSession 捕获的未压缩CMSampleBuffer 转换为AudioBufferList

let status: OSStatus = AudioConverterFillComplexBuffer(
            converter,
            inputDataProc,
            Unmanaged.passUnretained(self).toOpaque(),
            &ioOutputDataPacketSize,
            outOutputData.unsafeMutablePointer,
            nil
        )

我的输出asbd设置如下:

AudioStreamBasicDescription
- mSampleRate : 44100.0
- mFormatID : 1633772320
- mFormatFlags : 2
- mBytesPerPacket : 0
- mFramesPerPacket : 1024
- mBytesPerFrame : 0
- mChannelsPerFrame : 1
- mBitsPerChannel : 0
- mReserved : 0

我想将AudioBufferList 转换回包含压缩数据的CMSampleBuffer,这样我就可以使用AVAssetWriter 将它写入一个mp4 文件(我已经想出了如何使用视频),但到目前为止很少。我试过咨询this answer,但在这种情况下,有 PCM 数据,在这里似乎不可用。

我可以访问AudioBufferList 以及原始样本的presentationTimeStamp。我尝试了以下方法,但我不太确定如何计算 numSamples 以及这种方法是否有意义:

 func createCMSampleBuffer(_ data: UnsafeMutableAudioBufferListPointer, presentationTimeStamp: CMTime) -> CMSampleBuffer? {
    let numSamples = // not sure how to get this

    var status: OSStatus = noErr
    var sampleBuffer: CMSampleBuffer?
    var timing: CMSampleTimingInfo = CMSampleTimingInfo(
        duration: CMTime(value: CMTimeValue(numSamples), timescale: presentationTimeStamp.timescale),
        presentationTimeStamp: presentationTimeStamp,
        decodeTimeStamp: CMTime.invalid
    )

    status = CMSampleBufferCreate(
        allocator: kCFAllocatorDefault,
        dataBuffer: nil,
        dataReady: false,
        makeDataReadyCallback: nil,
        refcon: nil,
        formatDescription: formatDescription,
        sampleCount: CMItemCount(numSamples),
        sampleTimingEntryCount: 1,
        sampleTimingArray: &timing,
        sampleSizeEntryCount: 0,
        sampleSizeArray: nil,
        sampleBufferOut: &sampleBuffer
    )

    guard status == noErr else {
        return nil
    }

    status = CMSampleBufferSetDataBufferFromAudioBufferList(
        sampleBuffer!,
        blockBufferAllocator: kCFAllocatorDefault,
        blockBufferMemoryAllocator: kCFAllocatorDefault,
        flags: 0,
        bufferList: data.unsafePointer
    )

    guard status == noErr else {
        return nil
    }

    return sampleBuffer
}

最后我确实设法创建了一个CMSampleBuffer,但是当我尝试完成写作时,我收到以下错误:

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x174442ac0 {Error Domain=NSOSStatusErrorDomain Code=-12735 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12735), NSLocalizedDescription=The operation could not be completed}

【问题讨论】:

    标签: swift avassetwriter cmsamplebuffer video-toolbox audiobufferlist


    【解决方案1】:

    我可以分享一些这方面的研究工作,可能会对你有所帮助......

    CMSampleBufferSetDataBufferFromAudioBufferList returned error: -12731

    解决方案:- https://lists.apple.com/archives/coreaudio-api/2014/Mar/msg00008.html

    或者Converting AudioBuffer to CMSampleBuffer with accurate CMTime

    希望对您有所帮助...:)

    【讨论】:

    • 这是更好的参考资料
    【解决方案2】:

    所以,我已经设法取得了一些进展(但还远未使一切正常)。我没有像上面那样构建 CMSampleBuffer,而是设法使以下(有点)工作:

    CMAudioSampleBufferCreateWithPacketDescriptions(
            allocator: kCFAllocatorDefault,
            dataBuffer: nil,
            dataReady: false,
            makeDataReadyCallback: nil,
            refcon: nil,
            formatDescription: formatDescription!,
            sampleCount: Int(data.unsafePointer.pointee.mNumberBuffers),
            presentationTimeStamp: presentationTimeStamp,
            packetDescriptions: &packetDescriptions,
            sampleBufferOut: &sampleBuffer)
    

    这里的关键是从压缩过程中获取packetDescriptions:

    let packetDescriptionsPtr = UnsafeMutablePointer<AudioStreamPacketDescription>.allocate(capacity: 1)
    
    AudioConverterFillComplexBuffer(
                    converter,
                    inputDataProc,
                    Unmanaged.passUnretained(self).toOpaque(),
                    &ioOutputDataPacketSize,
                    outOutputData.unsafeMutablePointer,
                    packetDescriptionsPtr
                )
    

    音频 CMSampleBuffer 现在似乎已正确创建,但是当我附加它时,音频无法播放,并且会在视频中产生奇怪的时序故障。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多