swift 音频解码
ADTS是AAC音频的传输流格式
1、首先创建解码器
AudioConverterNewSpecific(&sourceASBD,&destASBD, 1, &classspecific, &_audioConverter))中的参数 sourceASBD和destASBD调换一下即可
2、AAC解码为PCM
有两个库faad 和ffmpeg
Ffmpeg : 体积庞大,功能丰富, API略显复杂。
使用Ffmpeg 库,将AAC 解码为pcm采样数据。
代码如下:
private func pushAudioBuffer(_ data: UnsafeRawPointer, size: Int, metadata: AudioBufferMetadata) {
guardletassetWriter =assetWriterelse{return}
letdata = data.assumingMemoryBound(to:UInt8.self)
ifaudioFormat!=nil{
guardletfirstVideoFrameTime =firstVideoFrameTime,
firstVideoFrameTime < metadata.ptselse{
return
}
// 解码器大小
varbufferOut:CMBlockBuffer?
letmemoryBlock =UnsafeMutableRawPointer.allocate(byteCount: size,
alignment:MemoryLayout.alignment)
memoryBlock.initializeMemory(as:UInt8.self,from: data,count: size)
// 接口构造 CMBlockBufferRef
let status = CMBlockBufferCreateWithMemoryBlock(
allocator: kCFAllocatorDefault,
memoryBlock: memoryBlock,
blockLength: size,
blockAllocator: kCFAllocatorDefault,
customBlockSource:nil,
offsetToData:0,
dataLength: size,
flags: kCMBlockBufferAssureMemoryNowFlag,
blockBufferOut: &bufferOut)
//得到CMSampleBuffer 这个待解码的原始数据
guardletbuffer = bufferOutelse{
VCLogger.debug("unexpected return")
return
}
vartimingInfo:CMSampleTimingInfo= .init()
timingInfo.presentationTimeStamp= metadata.pts
timingInfo.decodeTimeStamp= metadata.dts.isNumeric? metadata.dts: metadata.pts
writingQueue.async{ [weakself]in
guardletstrongSelf =self, !strongSelf.exiting.valueelse{return}
strongSelf.audioSamples.insert(.init(buffer: buffer,timingInfo: timingInfo,size: size,isKeyframe: metadata.isKey),at:0)
strongSelf.cond.signal()
}
}else{
letmd = metadata
guardletmetaData = md.dataelse{
VCLogger.debug("unexpected return")
return
}
ifvideoInput==nil|| !assetWriter.inputs.contains(videoInput!) {
return
}
varacl:AudioChannelLayout= .init()
acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono
// 配置解码后ASBD音频流信息
var asbd = AudioStreamBasicDescription(
mSampleRate:48000,
mFormatID: kAudioFormatMPEG4AAC,
mFormatFlags:0,
mBytesPerPacket:0,
mFramesPerPacket:1024,
mBytesPerFrame:0,
mChannelsPerFrame:1,
mBitsPerChannel:16,
mReserved:0)
// 为音频媒体流创建格式描述
CMAudioFormatDescriptionCreate(
allocator: kCFAllocatorDefault,
asbd: &asbd,
layoutSize: MemoryLayout<AudioChannelLayout>.size,
layout: &acl,
magicCookieSize:Int(md.cookieSize),
magicCookie: &md.cookie,
extensions:nil,
formatDescriptionOut: &audioFormat)
//音频设置
let audio = AVAssetWriterInput(mediaType: .audio, outputSettings: nil, sourceFormatHint: audioFormat)
audio.expectsMediaDataInRealTime = true
audio.languageCode="und"
ifassetWriter.canAdd(audio) {
assetWriter.add(audio)
audioInput= audio
print("Writer Debug: Add Auido Input Finish")
}else{
VCLogger.error("cannot add audio input")
}
}
}
网友评论