AAC編碼可使用faacfetch
/** 初始化 @param sampleRate 音頻採樣率 @param channels 通道數 @param bitSize 音頻採樣精度 16 */ - (void)initWithSampleRate:(int)sampleRate channels:(int)channels bitSize:(int)bitSize { nSampleRate = sampleRate; nChannels = channels; nPCMBitSize = bitSize; hEncoder = faacEncOpen(nSampleRate,nChannels,&nInputSamples,&nMaxOutputBytes); if(hEncoder == NULL) { error = -1; } int pcmBufSize = (int)(nInputSamples*(nPCMBitSize/8)); // 固定計算方式 pcmBuf = (unsigned char *)malloc(pcmBufSize * sizeof(unsigned char)); // pcmBufSize* 1個字節 memset(pcmBuf,0,pcmBufSize); aacBuf = (unsigned char *)malloc(nMaxOutputBytes * sizeof(unsigned char)); memset(aacBuf,0,nMaxOutputBytes); faacEncConfigurationPtr config = faacEncGetCurrentConfiguration(hEncoder); config->aacObjectType = LOW; //LC編碼 編碼類型 config->inputFormat = FAAC_INPUT_16BIT; //輸入數據類型 config->outputFormat = 1; //錄製MP4文件時,0要用raw流; 1是ADTS int ret = faacEncSetConfiguration(hEncoder, config); if (ret < 0) { error = -1; } } /** 編碼 @param data pcm @param dataSize 長度 */ -(void)encoderWithData:(unsigned char *)data dataSize:(int)dataSize { if (error<0) { return; } // 2048 4096 int pcmBufSize = (int)(nInputSamples*(nPCMBitSize/8)); // 固定計算方式 if(data == NULL||dataSize<=0|| dataSize > pcmBufSize){ NSLog(@"error:dataSize大於填充大小"); return; } int copyLength = 0; if(remainBufSize > dataSize){ copyLength = dataSize; } else{ copyLength = remainBufSize; } memcpy((&pcmBuf[0]) + remainWriteSize,data,copyLength); remainBufSize -= copyLength; remainWriteSize += copyLength; if(remainBufSize > 0){ return; } int ret = faacEncEncode(hEncoder,(int*)(pcmBuf),(unsigned int)nInputSamples,aacBuf,(unsigned int)nMaxOutputBytes); if (ret<0) { return; } if ([self.delegate respondsToSelector:@selector(AACEncoderData:dataSize:)]) { if (ret>0) { [self.delegate AACEncoderData:aacBuf dataSize:ret]; } } memset(pcmBuf, 0, pcmBufSize); remainWriteSize = 0; remainBufSize = pcmBufSize; if((dataSize - copyLength) > 0 ){ memcpy((&pcmBuf[0]), data+copyLength, dataSize - copyLength); remainWriteSize = dataSize - copyLength; // 已經填了多少 remainBufSize = pcmBufSize - (dataSize - copyLength); // 還差多少填滿 2048 } }
AAC解碼可使用faad編碼
@implementation AACDecoder - (instancetype)init { self = [super init]; if (self) { decoder = NeAACDecOpen(); samplerate = 0; channels = 0; pcmData = NULL; size = 0; } return self; } /** 解碼 @param data aac @param dataSize 長度 */ -(void)decoderWithData:(unsigned char *)data dataSize:(int)dataSize { if (!loaded) { if(getOneADTSFrame(data, dataSize, frame, &size)== 0) { NeAACDecInit(decoder, frame, size, &samplerate, &channels); printf("samplerate %lu, channels %d\n", samplerate, channels); loaded = YES; } } while(getOneADTSFrame(data,dataSize,frame,&size) == 0) { pcmData = (unsigned char*)NeAACDecDecode(decoder, &frameInfo,frame,size); if(frameInfo.error > 0) { printf("%s\n",NeAACDecGetErrorMessage(frameInfo.error)); } else if(pcmData && frameInfo.samples > 0) { printf("frame info: bytesconsumed %lu, channels %d, header_type %d\ object_type %d, samples %lu, samplerate %lu\n", frameInfo.bytesconsumed, frameInfo.channels, frameInfo.header_type, frameInfo.object_type, frameInfo.samples, frameInfo.samplerate); if ([self.delegate respondsToSelector:@selector(AACDcoderData:dataSize:)]) { [self.delegate AACDcoderData:pcmData dataSize:(int)(frameInfo.samples * frameInfo.channels)]; } } dataSize -= size; data += size; } if ([self.delegate respondsToSelector:@selector(AACDcoderEnd)]) { [self.delegate AACDcoderEnd]; } } - (void)dealloc { NeAACDecClose(decoder); } /** * fetch one ADTS frame 獲取一個ADTS Frame */ int getOneADTSFrame(unsigned char* buffer, size_t buf_size, unsigned char* data ,size_t* data_size) { size_t size = 0; if(!buffer || !data || !data_size ) { return -1; } while(1) { if(buf_size < 7 ) { return -1; } if((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0) ) { size |= ((buffer[3] & 0x03) <<11); //high 2 bit size |= buffer[4]<<3; //middle 8 bit size |= ((buffer[5] & 0xe0)>>5); //low 3bit break; } --buf_size; ++buffer; } if(buf_size < size) { return -1; } memcpy(data, buffer, size); *data_size = size; return 0; }