RFC3016,也就是《RTP Payload Format for MPEG-4 Audio/Visual Streams》中定义了LATM的封装格式。实现AAC编码后的RTP封装有两种,LATM就是其中的一种。本文将对LATM SDP字段,LATM负载格式做个简单的描述(其余的字段由于现有工程暂时没用上,所以不做描述了)。一来记录下笔记,二来,如果后续有人也捣鼓AAC,可以阅读本文并获得一些帮助。
SDP字段
MIME字段名称: MP4A-LATM
采样率:这个是必需参数,一般音频的采样率都是8k,16k,48k之类的,但是LATM的默认采样率却是90000,与视频的默认采样率一致。如果当SDP中LATM的采样是90000的话,那么一般情况是带内传输的方式,至于带内/带外,在后面RTP格式中,会有所说明。带外的话,则采样率可以是准确的,比如MP4A-LATM/8000,也就是8k的采样。
profile-level-id:这个是可选参数,AAC是有profile-level-id的概念的,RFC3016里面介绍定义在ISO/IEC 14496-1 ([6] and its amendments),由于我下载的是ISO/IEC 14496-3:2009,定义其实在Table 1.14 – audioProfileLevelIndication values表格中,我讲表格给截图了出来,方便阅读:
profile level的定义比较多,如果到时候有用到,就参考列表即可。其中,一般用于RTP传输,以AAC-LD为主,Low Delay Audio Profile对应的level列表如下:
通过上表,就可以根据level查询到目前流所支持的AAC-LD的最大声道数量,最大采样率等信息。
object:可选参数,object其实就是AOT(audioObjectType),RFC3016中说定义在ISO/IEC 14496-3 [5],我也将其截图出来,如下:
AOT是一个重要的参数,不过在这里是可选的,因为有带内的方式,如果是带外的话,则需要解析这个字段,因为你初始化编码器是需要AOT的。
bitrate:可选参数,表明当前AAC流所使用的比特率大小。如果使用FDK-AAC,刚好有可以配置的比特率的参数。
cpresent:可选参数,是一个bool值,当为1时,表明当前LATM封包有采用多路复用,而为0时,则没有。而如果该字段没有,则默认是有采用多路复用。在FDK-AAC中,有个AACENC_TPSUBFRAMES参数,可以设置subframes的个数。
config:可选参数,这个是带外封包非常重要的一个参数SMC(StreamMuxConfig),表明了当前LATM流的所有能力。如果是FDK-AAC可以通过函数aacDecoder_ConfigRaw来解析这个字段。
ptime:可选参数,打包时间。之前我的另一篇文章《AAC打包时间计算以及估算平均帧大小》中有了打包时间的说明,如果要兼容G711这类的,最好是选择LD/ELD 480samples。
以上就是SDP中字段的说明了。其实在开发中对接一些支持AAC LATM的终端设备,很多都是使用的带外传输的方式。也就是采样默认使用了90000,你需要去解码报文后,才能够具体知道其使用的真实采样是多少。
RTP报文
RTP报文的话,在RFC3016中,给出了这么一个简要图示:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |V=2|P|X| CC |M| PT | sequence number |RTP +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp |Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | synchronization source (SSRC) identifier | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | contributing source (CSRC) identifiers | | .... | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | |RTP : audioMuxElement (byte aligned) :Payload | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | :...OPTIONAL RTP padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
上图中,其实是带内传输的一种,这里就说一下带内/带外的区别吧。其实带内就是携带了AME来表明当前AAC的相关编解码参数。而带外的话,则是在SDP中表明了AAC的相关编解码参数,RTP负载中,则不会再次携带这部分参数了。我们从FDK-AAC的文章《Application Bulletin: AAC Transport Formats》中,其很好的将LATM的报文给图示出来。
LOAS就是比LATM多了LOAS Syncword以及Frame Length,普通的LATM,则是直接从AME开始的。所以上面这个图示,则容易看出来LATM的负载格式了。由于目前wireshark还不能解析LATM报文的格式,不过区分LOAS/LATM的话,还是比较容易的,因为LOAS的Syncword是0x2b7,16进制看到的就是,0x56开头的。如果使用FDK-AAC,从目前对接开发来看,大部分支持LATM的使用的并非是LOAS的封包,而是普通的LATM的封包,如果到时候需要使用FDK-AAC开发的话,则TT_MP4_LATM_MCP1的传输方式即可。
转载请注明: 转载自elkPi.com
本文链接地址: RFC3016 LATM
2020年2月21日
你好,想向你提个AAC LATM裸流保存的问题,但是你邮箱满了,邮件没发过去。可以在评论里直接问吗?
2020年2月21日
可以说说看,不一定能帮上忙!
2020年2月21日
你好,最近我在做一个项目,需要把RTP发送的MP4A-LATM流存下来,并交给FFMPEG来处理。
sdp的config是这样的:profile-level-id=24; object=23; bitrate=64000; cpresent=1;
我通过ISO/IEC 14496-3里介绍的AudioMuxElement函数,能从第一个包(第一个Bit为0)中解析到StreamMuxConfig的各项信息,通过这些信息也能拼成ADTS HEADER,但是到了payloadMux这一步,不知道如何保存里面的Raw Data,用了很多方式,存下来的文件,FFMPEG转换都会报错。我用的最简单的命令:ffmpeg -i audio.aac -acodec copy output.wav
2020年2月21日
你这个直接ffmpeg来处理就行了,ffmpeg可以直接读取sdp并解析以及存储的,具体代码实现,我倒是没做过这方面的实现,可以去参考ffmpeg的代码,存储以及打开log跟一下!
ffmpeg -i sdp -vn -acodec-copy xxx.aac 应该是差不多这样的命令
2020年2月21日
好的,我试试看,谢谢