音频编码

音频编码

从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;
}
复制代码

详细代码可以到Github获取

转载于:https://juejin.im/post/5ac1ecc5f265da237a4d2ee9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值