Запись закодированного аудио CMSampleBuffer не работает - PullRequest
1 голос
/ 11 января 2020

Я использую AudioConverter для преобразования несжатого CMSampleBuffer, захваченного через AVCaptureSession, в AudioBufferList:

let packetDescriptionsPtr = UnsafeMutablePointer<AudioStreamPacketDescription>.allocate(capacity: 1)

AudioConverterFillComplexBuffer(
                converter,
                inputDataProc,
                Unmanaged.passUnretained(self).toOpaque(),
                &ioOutputDataPacketSize,
                outOutputData.unsafeMutablePointer,
                packetDescriptionsPtr
            )

Затем я создаю 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)

Когда я попытался сохранить буфер с помощью AVAssetWriter, я получил следующую ошибку: - [AVAs setWriterInput appendSampleBuffer:] Cannot append sample buffer: First input buffer must have an appropriate kCMSampleBufferAttachmentKey_TrimDurationAtStart since the codec has encoder delay'

Я решил заполнить первые три буфера, зная, что каждый из них имеет одинаковую длину:

if self.receivedAudioBuffers < 2 {
                    let primingDuration = CMTimeMake(value: 1024, timescale: 44100)
                    CMSetAttachment(sampleBuffer,
                                    key: kCMSampleBufferAttachmentKey_TrimDurationAtStart,
                                    value: CMTimeCopyAsDictionary(primingDuration, allocator: kCFAllocatorDefault),
                                    attachmentMode: kCMAttachmentMode_ShouldNotPropagate)
                    self.receivedAudioBuffers += 1
                }
                else if self.receivedAudioBuffers == 2 {
                    let primingDuration = CMTimeMake(value: 64, timescale: 44100)
                    CMSetAttachment(sampleBuffer,
                                    key: kCMSampleBufferAttachmentKey_TrimDurationAtStart,
                                    value: CMTimeCopyAsDictionary(primingDuration, allocator: kCFAllocatorDefault),
                                    attachmentMode: kCMAttachmentMode_ShouldNotPropagate)
                    self.receivedAudioBuffers += 1
                }

Теперь я больше не получаю сообщение об ошибке, и при добавлении семпла я не получаю никаких ошибок, но звук не воспроизводится в записи, а также портит весь видеофайл (кажется, что информация о синхронизации искажается).

Есть ли здесь что-то, чего мне не хватает? Как правильно добавить аудио CMSampleBuffer?

...