zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ",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
    ",
                       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;
    }
  • 相关阅读:
    Mongodb操作之查询(循序渐进对比SQL语句)
    Java之IO转换流
    Java之final、finalize、finally的区别
    Java之IO流基础流对象
    lib库实现loadrunner驱动mysql性能测试
    java之集合框架使用细节及常用方法
    java之JAVA异常
    sql注入工具sqlmap使用参数说明
    Java之String类的使用细节
    MySQL引擎介绍ISAM,MyISAM,HEAP,InnoDB
  • 原文地址:https://www.cnblogs.com/-ljj/p/6373631.html
Copyright © 2011-2022 走看看