Создать CMSampleBuffer из данных AAC - PullRequest
1 голос
/ 09 июля 2019

Я использую внешнюю камеру, которая записывает аудио и видео.

Мое приложение получает аудио в формате AAC со следующей структурой:

struct AudioPacket {
   let timestamp: TimeInterval
   let data: Data
   let asbd: AudioStreamBasicDescription
   let magicCookie: Data
   let audioSpecificConfigData: Data
}

Свойство AudioStreamBasicDescription имеет следующее содержимое:

- mSampleRate : 48000.0
- mFormatID : 1633772320
- mFormatFlags : 0
- mBytesPerPacket : 0
- mFramesPerPacket : 1024
- mBytesPerFrame : 0
- mChannelsPerFrame : 1
- mBitsPerChannel : 0
- mReserved : 0

Я записываю как аудио, так и видео в файл, используя AVAssetWriter, и мне нужно предоставить CMSampleBuffer -s для средства записи активов.

Так, как я могу преобразовать вышеупомянутую AudioPacket структуру в CMSampleBuffer?

1 Ответ

1 голос
/ 12 июля 2019

Не точный ответ, но я бы попробовал что-то вроде следующего:

func convertPacket(_ packet: AudioPacket) -> CMSampleBuffer? {
    var data = packet.data
    var asbd = packet.asbd
    var magicCookie = packet.magicCookie
    var blockBuffer: CMBlockBuffer?
    var formatDescription: CMFormatDescription?
    var sampleBuffer: CMSampleBuffer?
    CMBlockBufferCreateWithMemoryBlock(
        allocator: nil, memoryBlock: &data, blockLength: data.count,
        blockAllocator: nil, customBlockSource: nil, offsetToData: 0,
        dataLength: data.count, flags: 0, blockBufferOut: &blockBuffer
    )
    CMAudioFormatDescriptionCreate(
        allocator: nil, asbd: &asbd, layoutSize: 0, layout: nil,
        magicCookieSize: magicCookie.count, magicCookie: &magicCookie,
        extensions: nil, formatDescriptionOut: &formatDescription
    )
    CMAudioSampleBufferCreateWithPacketDescriptions(
        allocator: nil, dataBuffer: blockBuffer, dataReady: true,
        makeDataReadyCallback: nil, refcon: nil, formatDescription: formatDescription!,
        sampleCount: 1, // <- provide correct number
        presentationTimeStamp: CMTime(seconds: packet.timestamp, preferredTimescale: 100),
        packetDescriptions: nil, sampleBufferOut: &sampleBuffer
    )
    return sampleBuffer
}
...