`
yang_danny
  • 浏览: 5917 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

解密H264、AAC硬件解码的关键扩展数据处理

阅读更多

    通过上一篇文章,我们用ffmpeg分离出一个多媒体容器中的音视频数据,但是很可能这些数据是不能被正确解码的。为什么呢?因为在解码这些数据之前,需要对解码器做一些配置,典型的就是目前流行的高清编码“黄金搭档”组合H264 + AAC的搭配。本文将讲述H264AAC的关键解码配置参数的解析,如果没有这些配置信息,数据帧往往不完整,导致了解码器不能解码。

  • H264的配置信息解析

    前面我们知道,ffmpegavformat_find_stream_info函数可以取得音视频媒体多种,比如播放持续时间、音视频压缩格式、音轨信息、字幕信息、帧率、采样率等。在信息结果中有一项扩展数据描述(avcodec.h文件中):

          AVCodecContext定义如下:

    如果视频流是H264,这个extradate里面就包含了H264的配置信息,这个扩展数据有如下定义:

    详细解释可以参考ISO-14496-15 AVC file format文档。里面最重要的就是NAL长度和SPSPPS数据和对应的长度信息。对该数据的解析在ffmpeg里面有现成的函数:ff_h264_decode_extradata,在我的项目里面是自己写的扩展数据解析。

  • AAC的配置信息解析及设置

    如果音频数据是AAC流,在解码时需要ADTS(Audio Data Transport Stream)头部,不管是容器封装还是流媒体,没有这个,一般都是不能播放的。很多朋友在做AAC流播放时遇到播不出声音,很可能就是这个原因导致。

    ADTS所需的数据仍然是放在上面的扩展数据extradata中,我们需要先解码这个扩展数据,然后再从解码后的数据信息里面重新封装成ADTS头信息,加到每一帧AAC数据之前再送解码器,这样就可以正常解码了。

    extradate数据定义如下:

     

        详细信息及说明请参考“ISO-IEC-14496-3 (Audio)”的AudioSpecificConfig部分。里面最重要的部分有采样频率、通道配置和音频对象类型,这几个一般都是AAC解码器需要的配置参数。

        这个数据在ffmpeg中也有相应的解码函数:avpriv_aac_parse_header。在我的项目中,我没有使用这个函数,而是自己实现的

typedef struct  

{

      int write_adts;  

      int objecttype;  

      int sample_rate_index;  

      int channel_conf;  

}ADTSContext;  

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;  

}  

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

           上面的pbuf就是extradata

    接下来,再用ADTSContext数据编码为ADTS头信息插入每一个AAC帧前面:

        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;  

}  

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

  这个头部是固定的7字节长度,所以可提前空出这7个字节供ADTS占用。

  通过以上对H264AAC的扩展数据处理,播放各种“黄金搭档”的多媒体文件、流媒体、视频点播等都应该没有问题了。

 

  想第一时间获得更多原创文章,请关注个人微信公众平台:程序员互动联盟(coder_online),扫一扫下方二维码或者搜索微信号coder_online即可关注,里面有大量AndroidChromiumLinux等相关文章等着您,我们还可以在线交流。

 

        如需转载本文,请注明出处:谢谢合作!

分享到:
评论

相关推荐

    MVC万用解码器

    **MVC万用解码器**是一款专门针对编码...总之,MVC万用解码器是一个强大的工具,结合了编码和加密的核心原理,为用户提供了一站式的解码和解密解决方案,保障了数据的安全性和隐私性,同时也简化了处理这类问题的过程。

    HI3796M技术参考资料

    **最大支持96个硬件PID过滤器**:提高了数据处理效率。 **支持DVB-CSA/AES/DES解扰算法**:确保数据传输的安全性。 #### 十、安全处理 HI3796M具备全面的安全处理机制,包括: - **支持Download CA** - **支持TVOS...

    gpac_extra_libs-0.4.5

    例如,可能包含 AAC、H.264 或其他格式的编解码库,这些库使得 MP4Box 能够处理各种编码的媒体数据。 2. **容器支持库**:除了 MP4 文件,MP4Box 也可能需要处理其他类型的容器格式,如 3GP、TS 或 M2TS。这些库...

    player支持多种播放格式.rar

    例如,MP4容器可以包含H.264编码的视频流和AAC编码的音频流。不同的容器格式对音视频流的处理方式不同,因此播放器需要理解这些差异以正确解析文件。 4. **硬件加速**:为了流畅播放高清晰度或高码率的视频,播放器...

    全新32位微控制器实现真正的单芯片DRM数字音频编解码器.pdf

    该系列微控制器的AVR32 CPU核心拥有丰富的DSP指令集,性能接近高端DSP,能够在较低的工作频率(比如20MHz)下解码MP3数据流,同时还能处理AAC和AAC+等更为繁重的音频格式。此外,AVR32核心还能够运行操作系统、进行...

    易语言MP4视屏观看源代码

    1. **视频解码器**:用于将MP4文件中的H.264或其他编码格式的视频流转换成原始像素数据。 2. **音频解码器**:处理MP4文件中的AAC或其他音频流,将其转换为可播放的声音信号。 3. **时间同步**:确保视频和音频的...

    【国科微】GK6323V100BL DataBrief-V1.0_产品介绍.pdf

    - 同时兼容H.264的4K@P60解码,以及AVS、AVS+、MPEG2、MPEG4、VC-1等多种高清视频格式。 - 视频显示支持4K@P60的HDR效果,提升色彩表现力和动态范围。 3. **音频处理** - 音频解码支持DD、DD+、DRA、AAC、MPEG等...

    行业分类-设备装置-多媒体信息播放方法和装置.zip

    首先,我们需要理解多媒体信息的编码格式,如MPEG、H.264、AAC等,这些都是标准的压缩编码方式,用于减小文件大小以便存储和传输。编码过程中,可能会涉及帧间预测、熵编码、运动补偿等一系列复杂算法。 多媒体信息...

    ALAC decoder

    此外,解码器还需要处理元数据,确保正确识别和读取文件中的音频信息。 "alac_decoder"可能是一个ALAC解码器的实现源代码或者二进制库,用于将ALAC压缩的音频数据转换回原始的未压缩音频流。这个组件对于支持ALAC的...

    通信与网络中的Sigma Designs IPTV处理器可支持多流解码

    该处理器的关键特性在于其强大的多流解码能力,能够处理多种视频编码格式,包括高效视频编码(H.264,也称为AVC),视频编码标准1(VC-1)以及MPEG-2,这些标准在现代多媒体应用中极为常见。 多流解码功能意味着SMP8634...

    嵌入式系统的各种常见外设总结.docx

    7. Audio Codec(音频解码):硬件音频解码器支持AAC、MP3、WMA等格式,还可能包括均衡等功能,提供高质量的音频播放。 8. 晶振与CCU:晶振提供基础时钟信号,CCU(Clock Unit Control)则用于调整时钟频率,以适应...

    新型MCU实现带DRM的单芯片数字音频解码器

    - **高音频解码能力**:能够在稍高于20MHz的速度下解码立体声MP3音频流,同时还能处理更复杂的AAC和AAC+格式。 - **加密支持**:内置256位AES加密单元,加快加密音频格式的解密过程,支持数字版权管理(DRM)。 - **...

    Broadcom Product Brief BCM7400

    - **双通道 AVC/MPEG-2/VC-1 解码器**:BCM7400 支持双通道的 H.264/AVC 主配置文件和高配置文件(至 Level 4.1),以及 VC-1 先进配置文件(Level 3)。 - **兼容多种视频格式**:除了支持主流的 AVC 和 VC-1 外,...

    多人聊天软件

    4. **语音与视频通话**:多人聊天软件往往集成语音和视频通话功能,这需要高质量的音频编码/解码技术(如Opus或AAC)和视频编码/解码技术(如H.264或VP9),以及网络适应策略来处理不同网络条件下的流畅通信。...

    MTK6225_datasheet

    - **音频处理**:支持MP3、AAC等音频格式的解码。 - **存储接口**:集成有SD/MMC卡接口,用于扩展存储空间。 #### 一般描述 MT6225采用了高度集成的设计理念,将多种功能集成在一个芯片内,以减少整体系统的复杂性...

    Linphone的编译与代码分析

    3. **oRTP的初始化**:oRTP(Real-time Transport Protocol)库负责处理实时传输协议的低层操作,如媒体数据的加密和解密。它的初始化确保了安全的数据传输。 4. **MediaStream2的初始化**:MediaStream2库用于管理...

Global site tag (gtag.js) - Google Analytics