| 副标题[/!--empirenews.page--] 
        
             =====================================================  视音频数据处理入门系列文章:  视音频数据处理入门:RGB、YUV像素数据处理  视音频数据处理入门:PCM音频采样数据处理  视音频数据处理入门:H.264视频码流解析  视音频数据处理入门:AAC音频码流解析  视音频数据处理入门:FLV封装格式解析  视音频数据处理入门:UDP-RTP协议解析  ===================================================== 
  本文继续上一篇文章的内容,介绍一个音频码流处理程序。音频码流在视频播放器中的位置如下所示。   
 
  本文中的程序是一个AAC码流解析程序。该程序可以从AAC码流中分析得到它的基本单元ADTS frame,并且可以简单解析ADTS frame首部的字段。通过修改该程序可以实现不同的AAC码流处理功能。  
  原理 AAC原始码流(又称为“裸流”)是由一个一个的ADTS frame组成的。他们的结构如下图所示。   
 其中每个ADTS frame之间通过syncword(同步字)进行分隔。同步字为0xFFF(二进制“222222222211”)。AAC码流解析的步骤就是首先从码流中搜索0x0FFF,分离出ADTS frame;然后再分析ADTS frame的首部各个字段。本文的程序即实现了上述的两个步骤。
 代码 
整个程序位于simplest_aac_parser()函数中,如下所示。
 
  
  
   
   [cpp]? 
   view plain 
   ?copy 
    
    
   ? 
    
 
 
 /**?
 ?*?最简单的视音频数据处理示例?
?*?Simplest?MediaData?Test?
?*?
?*?雷霄骅?Lei?Xiaohua?
?*?leixiaohua1020@126.com?
?*?中国传媒大学/数字电视技术?
?*?Communication?University?of?China?/?Digital?TV?Technology?
?*?http://blog.csdn.net/leixiaohua1020?
?*?本项目包含如下几种视音频测试示例:?
?*??(1)像素数据处理程序。包含RGB和YUV像素格式处理的函数。?
?*??(2)音频采样数据处理程序。包含PCM音频采样格式处理的函数。?
?*??(3)H.264码流分析程序。可以分离并解析NALU。?
?*??(4)AAC码流分析程序。可以分离并解析ADTS帧。?
?*??(5)FLV封装格式分析程序。可以将FLV中的MP3音频码流分离出来。?
?*??(6)UDP-RTP协议分析程序。可以将分析UDP/RTP/MPEG-TS数据包。?
?*?This?project?contains?following?samples?to?handling?multimedia?data:?
?*??(1)?Video?pixel?data?handling?program.?It?contains?several?examples?to?handle?RGB?and?YUV?data.?
?*??(2)?Audio?sample?data?handling?program.?It?contains?several?examples?to?handle?PCM?data.?
?*??(3)?H.264?stream?analysis?program.?It?can?parse?H.264?bitstream?and?analysis?NALU?of?stream.?
?*??(4)?AAC?stream?analysis?program.?It?can?parse?AAC?bitstream?and?analysis?ADTS?frame?of?stream.?
?*??(5)?FLV?format?analysis?program.?It?can?analysis?FLV?file?and?extract?MP3?audio?stream.?
?*??(6)?UDP-RTP?protocol?analysis?program.?It?can?analysis?UDP/RTP/MPEG-TS?Packet.?
?*/??
 #include?<stdio.h>??
 #include?<stdlib.h>??
 #include?<string.h>??
 ??
 ??
 int?getADTSframe(unsigned?char*?buffer,?int?buf_size,?unsigned?char*?data?,int*?data_size){??
 ????int?size?=?0;??
 ????if(!buffer?||?!data?||?!data_size?){??
 ????????return?-1;??
 ????}??
while(1){??
if(buf_size??<?7?){??
 ????????????return?-1;??
 ????????}??
 ????????//Sync?words??
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;??
 }??
int?simplest_aac_parser(char?*url)??
 {??
 ????int?data_size?=?0;??
int?cnt=0;??
int?offset=0;??
 ????//FILE?*myout=fopen("output_log.txt","wb+");??
FILE?*myout=stdout;??
 ????unsigned?char?*aacframe=(unsigned?char?*)malloc(1024*5);??
 ????unsigned?char?*aacbuffer=(unsigned?char?*)malloc(1024*1024);??
FILE?*ifile?=?fopen(url,?"rb");??
if(!ifile){??
 ????????printf("Open?file?error");??
 ????printf("-----+-?ADTS?Frame?Table?-+------+n");??
 ????printf("?NUM?|?Profile?|?Frequency|?Size?|n");??
 ????printf("-----+---------+----------+------+n");??
while(!feof(ifile)){??
 ????????data_size?=?fread(aacbuffer+offset,?1,?1024*1024-offset,?ifile);??
 ????????unsigned?char*?input_data?=?aacbuffer;??
while(1)??
 ????????{??
 ????????????int?ret=getADTSframe(input_data,?data_size,?aacframe,?&size);??
if(ret==-1){??
 ????????????????break;??
 ????????????}else?if(ret==1){??
 ????????????????memcpy(aacbuffer,input_data,data_size);??
 ????????????????offset=data_size;??
 ????????????}??
 ????????????char?profile_str[10]={0};??
char?frequence_str[10]={0};??
 ????????????unsigned?char?profile=aacframe[2]&0xC0;??
 ????????????profile=profile>>6;??
switch(profile){??
case?0:?sprintf(profile_str,"Main");case?1:?sprintf(profile_str,"LC");case?2:?sprintf(profile_str,"SSR");default:sprintf(profile_str,"unknown"); ????????????unsigned?char?sampling_frequency_index=aacframe[2]&0x3C;??
 ????????????sampling_frequency_index=sampling_frequency_index>>2;??
switch(sampling_frequency_index){??
case?0:?sprintf(frequence_str,"96000Hz");case?1:?sprintf(frequence_str,"88200Hz");case?2:?sprintf(frequence_str,"64000Hz");case?3:?sprintf(frequence_str,"48000Hz");case?4:?sprintf(frequence_str,"44100Hz");case?5:?sprintf(frequence_str,"32000Hz");case?6:?sprintf(frequence_str,"24000Hz");case?7:?sprintf(frequence_str,"22050Hz");case?8:?sprintf(frequence_str,"16000Hz");case?9:?sprintf(frequence_str,"12000Hz");case?10:?sprintf(frequence_str,"11025Hz");case?11:?sprintf(frequence_str,"8000Hz");default:sprintf(frequence_str,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> ????????????fprintf(myout,"%5d|?%8s|??%8s|?%5d|n",cnt,profile_str?,frequence_str,size);??
 ????????????data_size?-=?size;??
 ????????????input_data?+=?size;??
 ????????????cnt++;??
 ????????}?????
 ????fclose(ifile);??
 ????free(aacbuffer);??
 ????free(aacframe);??
return?0;??
 }??
 上文中的函数调用方法如下所示。 
  结果 
本程序的输入为一个AAC原始码流(裸流)的文件路径,输出为该码流中ADTS frame的统计数据,如下图所示。 
 
  
  下载 
  
  Simplest mediadata test 项目主页 
  SourceForge:https://sourceforge.net/projects/simplest-mediadata-test/ 
  Github:https://github.com/leixiaohua1020/simplest_mediadata_test  
开源中国: 
http://git.oschina.net/leixiaohua1020/simplest_mediadata_test 
 CSDN下载地址: 
http://download.csdn.net/detail/leixiaohua1020/9422409 
 本项目包含如下几种视音频数据解析示例: 
 ?(1)像素数据处理程序。包含RGB和YUV像素格式处理的函数。 
 ?(2)音频采样数据处理程序。包含PCM音频采样格式处理的函数。 
 ?(3)H.264码流分析程序。可以分离并解析NALU。 
 ?(4)AAC码流分析程序。可以分离并解析ADTS帧。 
 ?(5)FLV封装格式分析程序。可以将FLV中的MP3音频码流分离出来。 
 ?(6)UDP-RTP协议分析程序。可以将分析UDP/RTP/MPEG-TS数据包。 
 雷霄骅 (Lei Xiaohua)  leixiaohua1020@126.com 
 http://blog.csdn.net/leixiaohua1020 
 (编辑:我爱故事小小网_铜陵站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |