【协议开发】RTSP协议开发-2 【AAC封包RTP】
本节内容主要讲解:
RTP之AAC封包和解包2-原理和源码分析
1.源码编译及结果运行
最后会生成文件sdp文件;
运行方式1:装有vlc的环境,直接双击test.sdp文件使用vlc播放;
运行方式2:使用ffmplay运行;运行的 时候要声明白名单;
2.AAC的sdp类型
有两种aac的sdp类型:一种是mpeg4-generic,另外一种是MP4A-LATM;
3.怎么在原有的结构添加支持mpeg4-generic(AAC)?代码解析
文件1:rtp-payload-internal.h
在头文件中增加封装接口:与h264的封装的包返回的结构体的格式是一致的;

文件2:封装接口实现文件



函数1:


关键的两个函数:
【关键函数1】rtp_mpeg4_generic_pack_input--封包;
【关键函数2】rtp_decode_mpeg4_generic--解包;
下面的profile不是固定的,但是需要提前约定好;

文件3:封装aac源码 aac-util.c 和aac-util.h
1 #ifndef _aac_util_h_ 2 #define _aac_util_h_ 3 #include <stdio.h> 4 #include <stdint.h> 5 6 typedef struct{ 7 unsigned int syncword; //12 bit 同步字 '1111 1111 1111',说明一个ADTS帧的开始 8 unsigned int id; //1 bit MPEG 标示符, 0 for MPEG-4,1 for MPEG-2 9 unsigned int layer; //2 bit 总是'00' 10 unsigned int protection_absent; //1 bit 1表示没有crc,0表示有crc 11 unsigned int profile; //2 bit 表示使用哪个级别的AAC 12 unsigned int sampling_frequency_index; //4 bit 表示使用的采样频率 13 unsigned int private_bit; //1 bit 14 unsigned int channel_configuration; //3 bit 表示声道数 15 unsigned int original_copy; //1 bit 16 unsigned int home; //1 bit 17 18 /*下面的为改变的参数即每一帧都不同*/ 19 unsigned int copyright_id; //1 bit 20 unsigned int copyright_id_start; //1 bit 21 unsigned int aac_frame_length; //13 bit 一个ADTS帧的长度包括ADTS头和AAC原始流 22 unsigned int adts_buffer_fullness; //11 bit 0x7FF adts buffer fullness 23 24 /* number_of_raw_data_blocks_in_frame 25 * 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧 26 * 所以说number_of_raw_data_blocks_in_frame == 0 27 * 表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) 28 */ 29 unsigned int num_raw_data_blocks; //2 bit 30 }aac_header_t; 31 32 typedef struct 33 { 34 aac_header_t header; // 存储到是adts头部解析后的参数 35 uint8_t adts_buf[9]; // adts header最多9字节,从文件读取出来的数据先放到adts_buf里面 36 int adts_len; // adts 头部长度 37 uint8_t frame_buf[8192]; // 包括adts header 13bit最多8192字节 38 int frame_len; // 包括adts header + data length 39 }aac_frame_t; 40 41 extern int aac_freq[]; 42 43 // 打开文件 44 FILE *aac_open_bitstream_file (char *filename); 45 // 根据传入的adts header buffer 解析出来对应的参数, show=1的时候打印解析结果,=0就不打印了 46 int aac_parse_header(uint8_t* in, aac_header_t* res, uint8_t show); 47 // 读取一帧完整的AAC帧(adts header + data),不会去查找sync word 48 int aac_get_one_frame (aac_frame_t *aac_frame, FILE *bits); 49 void aac_rtp_create_sdp(uint8_t *file, uint8_t *ip, uint16_t port, 50 uint16_t profile, uint16_t chn, 51 uint16_t freq, uint16_t type); 52 #endif // _aac_util_h_
aac-util.c
读取一帧数据:
1 /** 2 * 取一帧数据; 3 * 数据组成的形式:header+data; 4 * 1.先取7个字节,然后解析; 5 * 3.根据解析结果查看有没有校验,如果有校验,则adts_header是9个字节; 6 */ 7 //这里没有去检测sync word,如果中间有数据丢失该函数将不起作用 8 int aac_get_one_frame (aac_frame_t *aac_frame, FILE *bits) 9 { 10 // 1. 先读取7个字节,放到adts_buf 11 if (7 != fread (aac_frame->adts_buf, 1, 7, bits))//从码流中读3个字节 12 { 13 printf("read adts_buf failed\n"); 14 return -1; 15 } 16 // 2.解析adts header 17 if(aac_parse_header(aac_frame->adts_buf, &aac_frame->header, 0) < 0) 18 { 19 return -1; 20 } 21 // 3.根据解析结果查看有没有校验 22 if(0 == aac_frame->header.protection_absent) 23 { 24 aac_frame->adts_len = 9; // 变成adts header长度就是9个字节 25 // 0表示有CRC校验 26 if (2 != fread (&aac_frame->adts_buf[7], 1, 2, bits))//从码流中读2个字节 27 { 28 return -1; 29 } 30 } else { 31 aac_frame->adts_len = 7; 32 } 33 34 //4. 拷贝header部分到buff中; 35 aac_frame->frame_len = aac_frame->header.aac_frame_length; // 整帧长度 36 memcpy(aac_frame->frame_buf, aac_frame->adts_buf, aac_frame->adts_len); // 拷贝adts header 37 38 //5.读取dadta部分到buff;因为5中已经读取header; 39 if ((aac_frame->frame_len - aac_frame->adts_len) // 从文件读取data部分 40 != fread (&aac_frame->frame_buf[aac_frame->adts_len], 1, 41 aac_frame->frame_len - aac_frame->adts_len, bits)) 42 { 43 printf("read aac frame data failed\n"); 44 return -1; 45 } 46 47 return 0; 48 }
3.3 main逻辑
aac编码和aac解码;

3.4 验证封装的数据是否正确
对比验证

封装前数据 in.aac VS 封装好的RTP数据包然后解封装写入到out.aac 进行对比;

修改代码:
使用200k的数据:


3.5 如何保证RTP数据是实时播放的?
在合适的时间内发送适量的数据,如果数据过多则多少发送一些数据;

4.对AAC进行封包的步骤
【1】只有一个AU_HEADER_LENGTH,但是可以有多个AU_HEADER;
【2】有多少个AU_HEADER,就有多少个AU;

4.2 AU的关键字段
在编写sdp信息的时候需要将AU-size和AU_lenght,还有AU_LENGHET_DELTA都要加上,否则ffplay无法正常播放;
下面是ffplay的源码,需要使用到这三个字段进行计算。

SDP信息中描述的关键字段信息:




【特别说明】关于这些计算关系有点乱;



浙公网安备 33010602011771号