AAC编解码

AAC编码可以使用faac

/**
 初始化

 @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;
}

 

posted @ 2017-02-07 12:59  陆俊杰_iOS  阅读(1101)  评论(0编辑  收藏  举报

版权信息:©Copyright © 2010-2050 陆俊杰的博客