音频编码
从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));//初始化输出流的结构体描述为0AudioStreamBasicDescription outAudioStreamBasicDescription = {0};//音频流,正常播放情况下的帧率。如果是压缩格式。这个属性表示为解压缩后的帧率。帧率不能为0outAudioStreamBasicDescription.mSampleRate = inAudioStreamBasicDecription.mSampleRate;//编码格式outAudioStreamBasicDescription.mFormatID = kAudioFormatMPEG4AAC;//无损编码 0表示没有outAudioStreamBasicDescription.mFormatFlags = kMPEG4Object_AAC_LC;//每一个packet的音频数据大小。如果动态大小,设置为0。动态大小的格式,需要用AudioStreamPacketDescription来确定每个packet的大小outAudioStreamBasicDescription.mBytesPerPacket = 0;//每个packet的帧数。如果未压缩的音频数据值是1 动态码率格式,这个值是一个较大的固定数字,比如AAC的1024outAudioStreamBasicDescription.mFramesPerPacket = 1024;outAudioStreamBasicDescription.mBytesPerFrame = 0;//声道数outAudioStreamBasicDescription.mChannelsPerFrame = 1;//压缩格式设置为0outAudioStreamBasicDescription.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); //pcmOSStatus 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;}复制代码