ffmpeg编码aac文件通过extradata添加adts头

转载一篇文章:

1:ffmpeg的aac通过pcm编码得到的数据是latm的,如果需要存成adts能播的文件需要加头,ffmpeg并没有给相关的filter,通过extradata自己做解析加头;

2:aac_adtstoasc这个filter是把adts转成latm;

3:h264_mp4toannexb是将4个字节长度前缀的h264转成00 00 00 01 前缀的能播放的h264;

下面为转载;

转载链接:https://blog.csdn.net/lichen18848950451/article/details/78266054

根据雷神的代码,可以获取mp3等音频文件。网址是:http://blog.csdn.net/leixiaohua1020/article/details/39767055

同时,还可以把数据回调出去,进行其他的处理,是没有任何问题的。可是,现在的视频文件大都是H264+AAC。可是,根据雷神的代码是获取的数据,在播放器上播放失败。这是由于获取的aac数据是缺少adts文件头,添加上去就可以了。说着容易,可是做就难了。

网上的文章大都是介绍adts的,进行处理的代码很少。不过还是找到了,网址是http://blog.csdn.net/leixiaohua1020/article/details/39767055

不过,他的代码只是提供一些写好的函数,关于如何调用,自己还是花了不少时间研究。


typedef struct  
 
{
      int write_adts;  
      int objecttype;  
      int sample_rate_index;  
      int channel_conf;  
 
}ADTSContext;  
以上是定义的一个结构体。

int aac_decode_extradata(ADTSContext *adts, unsigned char *pbuf, int bufsize)  
{  
      int aot, aotext, samfreindex;  
      int i, channelconfig;  
      unsigned char *p = pbuf;  
      if (!adts || !pbuf || bufsize<2)  
      {  
            return -1;  
      }  
      aot = (p[0]>>3)&0x1f;  
      if (aot == 31)  
      {  
            aotext = (p[0]<<3 | (p[1]>>5)) & 0x3f;  
            aot = 32 + aotext;  
            samfreindex = (p[1]>>1) & 0x0f;   
            if (samfreindex == 0x0f)  
            {  
                  channelconfig = ((p[4]<<3) | (p[5]>>5)) & 0x0f;  
            }  
            else  
            {  
                  channelconfig = ((p[1]<<3)|(p[2]>>5)) & 0x0f;  
            }  
      }  
      else  
      {  
            samfreindex = ((p[0]<<1)|p[1]>>7) & 0x0f;  
            if (samfreindex == 0x0f)  
            {  
                  channelconfig = (p[4]>>3) & 0x0f;  
            }  
            else  
            {  
                  channelconfig = (p[1]>>3) & 0x0f;  
            }  
      }  
#ifdef AOT_PROFILE_CTRL  
      if (aot < 2) aot = 2;  
#endif  
      adts->objecttype = aot-1;  
      adts->sample_rate_index = samfreindex;  
      adts->channel_conf = channelconfig;  
      adts->write_adts = 1;  
      return 0;  
}  
上面的这个函数用来获取用来获取adts所需要的信息。第一个参数就不必说了,关键是后两个参数。是结构体AVCodecContext中的两个元素:
uint8_t *extradata; int extradata_size;adts中的信息在extradata中。通过处理,就可以获得adts的信息。


 int aac_set_adts_head(ADTSContext *acfg, unsigned char *buf, int size)  
{         
      unsigned char byte;    
      if (size < ADTS_HEADER_SIZE)  
      {  
            return -1;  
      }       
      buf[0] = 0xff;  
      buf[1] = 0xf1;  
      byte = 0;  
      byte |= (acfg->objecttype & 0x03) << 6;  
      byte |= (acfg->sample_rate_index & 0x0f) << 2;  
      byte |= (acfg->channel_conf & 0x07) >> 2;  
      buf[2] = byte;  
      byte = 0;  
      byte |= (acfg->channel_conf & 0x07) << 6;  
      byte |= (ADTS_HEADER_SIZE + size) >> 11;  
      buf[3] = byte;  
      byte = 0;  
      byte |= (ADTS_HEADER_SIZE + size) >> 3;  
      buf[4] = byte;  
      byte = 0;  
      byte |= ((ADTS_HEADER_SIZE + size) & 0x7) << 5;  
      byte |= (0x7ff >> 6) & 0x1f;  
      buf[5] = byte;  
      byte = 0;  
      byte |= (0x7ff & 0x3f) << 2;  
      buf[6] = byte;     
      return 0;  
}  
传入的第一个参数就是上面第一个函数获取的结构体,第二个参数是自己传入的一个指针,用来获取adts。第三个参数是长度,是每个packet的size。
下面是伪代码,希望对大家有所帮助吧:


ADTSContext               AdtsCtx;
AVCodecContext*       pCodecCtx;
while(av_read_frame(,&packet)>=0)
{
    aac_decode_extradata(&AdtsCtx, pCodecCtx->extradata, pCodecCtx->extradata_size);
    char* pAdts = new char [7];
    aac_set_adts_head(&AdtsCtx, pAdts, packet.size);
    fwrite(pAdts, 1, 7, fp);
    fwrite(packet.data, 1, packet.size, fp);
}

————————————————
版权声明:本文为CSDN博主「那年晴天」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lichen18848950451/article/details/78266054

 

上述有不足之处请各位指正。

如有错误请指正:

交流请加QQ群:62054820
QQ:379969650.

你可能感兴趣的:(ffmpeg编码aac文件通过extradata添加adts头)