音频编码
从AVCaptureVideoDataOutputSampleBufferDelegate代理方法中获取sampleBuffer
- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
dispatch_sync(mCaptureQueue, ^{
[self.audioEncode encodeSampleBuffer:sampleBuffer];
});
}
复制代码
创建音频转换器
//获取原音频格式设置
AudioStreamBasicDescription inAudioStreamBasicDecription = *CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)CMSampleBufferGetFormatDescription(smapleBuffer));
//初始化输出流的结构体描述为0
AudioStreamBasicDescription outAudioStreamBasicDescription = {0};
//音频流,正常播放情况下的帧率。如果是压缩格式。这个属性表示为解压缩后的帧率。帧率不能为0
outAudioStreamBasicDescription.mSampleRate = inAudioStreamBasicDecription.mSampleRate;
//编码格式
outAudioStreamBasicDescription.mFormatID = kAudioFormatMPEG4AAC;
//无损编码 0表示没有
outAudioStreamBasicDescription.mFormatFlags = kMPEG4Object_AAC_LC;
//每一个packet的音频数据大小。如果动态大小,设置为0。动态大小的格式,需要用AudioStreamPacketDescription来确定每个packet的大小
outAudioStreamBasicDescription.mBytesPerPacket = 0;
//每个packet的帧数。如果未压缩的音频数据值是1 动态码率格式,这个值是一个较大的固定数字,比如AAC的1024
outAudioStreamBasicDescription.mFramesPerPacket = 1024;
outAudioStreamBasicDescription.mBytesPerFrame = 0;
//声道数
outAudioStreamBasicDescription.mChannelsPerFrame = 1;
//压缩格式设置为0
outAudioStreamBasicDescription.mBitsPerChannel = 0;
//8字节对齐
outAudioStreamBasicDescription.mReserved = 0;
//软编 获取编码区
AudioClassDescription *description = [self getAudioClassDescriptionWithType:kAudioFormatMPEG4AAC fromManuFacturer:kAppleSoftwareAudioCodecManufacturer];
//创建音频转换器
OSStatus status = AudioConverterNewSpecific(&inAudioStreamBasicDecription, &outAudioStreamBasicDescription, 1, description, &_audioConverter);
NSAssert(status == noErr, [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil].localizedDescription);
复制代码
将smapleBuffer数据转为所需格式, 并将数据存储到pcm中
//获取samplebuffer数据
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
CFRetain(blockBuffer);
//pcm
OSStatus status = CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &pcmBufferSize , &pcmBuffer);
NSError *error = nil;
if (status != kCMBlockBufferNoErr) {
error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];
return ;
}
复制代码
清空AAC缓存,并初始化缓存列表
//AAC清空
memset(aacBuffer, 0, aacBufferSize);
//初始化缓存列表
AudioBufferList outAudioBufferList = {0};
//缓冲区个数
outAudioBufferList.mNumberBuffers = 1;
//数据通道
outAudioBufferList.mBuffers[0].mNumberChannels = 1;
//缓冲数据大小
outAudioBufferList.mBuffers[0].mDataByteSize = (int)aacBufferSize;
//缓冲区内容
outAudioBufferList.mBuffers[0].mData = aacBuffer;
复制代码
将数据从pcm缓存 提取到缓存列表
//编码到缓存列表
AudioStreamPacketDescription *outPacketDescription = NULL;
UInt32 ioOutputDataPacketSize = 1;
status = AudioConverterFillComplexBuffer(_audioConverter, inInputDataProc, (__bridge void *)self, &ioOutputDataPacketSize, &outAudioBufferList, outPacketDescription);
复制代码
头文件为固定格式
/**
* Add ADTS header at the beginning of each and every AAC packet.
* This is needed as MediaCodec encoder generates a packet of raw
* AAC data.
*
* Note the packetLen must count in the ADTS header itself.
* See: http://wiki.multimedia.cx/index.php?title=ADTS
* Also: http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Channel_Configurations
**/
/**模认添加头文件*/
- (NSData *)adtsDataForPacketLength:(NSUInteger)packetLength{
int adtsLength = 7;
char * packet = malloc(sizeof(char) * adtsLength);
int proFile = 2;
int freqIdx = 4;
int chanCfg = 1;
NSUInteger fullLength = adtsLength + packetLength;
packet[0] = (char)0xFF; //32
packet[1] = (char)0xF9; //25
packet[2] = (char)(((proFile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
packet[3] = (char)(((chanCfg & 3)<<6) + (fullLength >> 11));
packet[4] = (char)((fullLength & 0x7FF) >> 3);
packet[5] = (char)(((fullLength & 7) << 5) + 0x1F);
packet[6] = (char)0xFC;
NSData * data = [NSData dataWithBytesNoCopy:packet length:adtsLength freeWhenDone:YES];
return data;
}
复制代码