一、引言
在《音视频入门基础:RTP专题(3)——SDP简介》中对SDP协议进行了简介,以H.264为例介绍了视频的SDP的媒体描述。本文对该文章进行补充,以AAC为例,讲述音频的SDP媒体描述。
二、文档下载
《RFC 3640》和《RFC 6416》分别定义了两种对MPEG-4流的RTP封包方式,这两个文档都可以从RFC官网下载:» RFC Editor
本文主要对《RFC 3640》中的音频的SDP媒体描述进行简介。《RFC 3640》总共有43页,本文下面所说的“页数”是指在pdf阅读器中显示的页数:
三、rtpmap
由 《音视频入门基础:RTP专题(3)——SDP简介》可以知道,SDP协议中,
a=rtpmap属性将 RTP有效载荷类型编号(如 “m=”行中使用的)映射到表示有效载荷格式的编码名称。它还提供有关时钟速率和编码参数的信息。格式为:
a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
encoding name参数跟音视频压缩编码格式相关联。根据《RFC 4566》第26页,对于音频,clock rate参数指定音频采样频率,encoding parameters参数指定音频声道数:
示例:
a=rtpmap:97 MPEG4-GENERIC/48000/2
上述例子表示映射PT值(有效载荷类型)为97的负载类型到AAC编码。音频的采样频率为48000Hz,音频声道数为2。
关于“MPEG4-GENERIC”有两种说法,第一种说法是:它可以用来描述MPEG-4标准中的多种不同类型的媒体编码,但它本身并不特指AAC。具体可以参考:《MPEG-4 Generic》。
第二种说法是:SDP协议中出现“MPEG4-GENERIC”就是指AAC。因为在FFmpeg源码(FFmpeg7.0.1的libavformat/rtpdec_mpeg4.c)中,“MPEG4-GENERIC”对应的就是AAC:
const RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = {.enc_name = "mpeg4-generic",.codec_type = AVMEDIA_TYPE_AUDIO,.codec_id = AV_CODEC_ID_AAC,.priv_data_size = sizeof(PayloadContext),.parse_sdp_a_line = parse_sdp_line,.close = close_context,.parse_packet = aac_parse_packet,
};
关于上面哪种说法正确,我查阅了SDP的官方文档,但没发现对应说明。所以就目前而已,我更倾向于第二种说法正确,因为在FFmpeg源码中,“MPEG4-GENERIC”对应的就是AAC。
同理,通过阅读FFmpeg源码,可以发现"opus"对应的是Opus:
static const RTPDynamicProtocolHandler opus_dynamic_handler = {.enc_name = "opus",.codec_type = AVMEDIA_TYPE_AUDIO,.codec_id = AV_CODEC_ID_OPUS,
};
"X-MP3-draft-00"对应MP3ADU:
static const RTPDynamicProtocolHandler realmedia_mp3_dynamic_handler = {.enc_name = "X-MP3-draft-00",.codec_type = AVMEDIA_TYPE_AUDIO,.codec_id = AV_CODEC_ID_MP3ADU,
};
四、fmtp
由 《音视频入门基础:RTP专题(3)——SDP简介》可以知道:SDP协议中,a=fmtp属性允许以SDP所不具备的方式传递特定格式的参数。格式为:
a=fmtp:<format> <format specific parameters>
对于音频,格式一般为:a=fmtp:XX profile-level-id=X;mode=XXX;sizelength=XX;indexlength=X;indexdeltalength=X; config=XX
其中:
(一)profile-level-id
根据《RFC 3640》第28页,profile-level-id参数为MPEG-4配置文件级别指示的十进制表示。该参数必须在能力交换或会话设置程序中使用,以指示相关MPEG-4媒体编解码器能够处理的MPEG-4配置文件和级别组合。对于MPEG-4音频流,该参数是《ISO/IEC 14496-1》 Table 5(audioProfileLevelIndication Values)中的十进制值,表示解码音频流需要哪些MPEG-4音频工具子集:
《ISO/IEC 14496-1》文档的免费版可以在 http://netmedia.zju.edu.cn/multimedia2013/mpeg-4/ISO%20IEC%2014496-1%20MPEG-4%20System%20Standard.pdf 下载。
根据《ISO/IEC 14496-1》第38页,audioProfileLevelIndication(音频配置文件级别指示)为Table 5中定义的指示,表示处理与此InitialObjectDescriptor(初始对象描述符)相关的内容所需的音频配置文件和级别:
《ISO/IEC 14496-1》中的Table 5(audioProfileLevelIndication Values)内容如下:
比如,如果SDP协议中,音频媒体描述的profile-level-id的值为1,则根据上表(Table 5),表示其Profile为:Level为L1的Main Profile。
(二)mode
根据《RFC 3640》第30页,mode参数为《RFC 3640》规范使用的模式。可使用以下模式:
mode=generic
mode=CELP-cbr
mode=CELP-vbr
mode=AAC-lbr
mode=AAC-hbr。
其他mode预计将在未来的RFC文档中定义。
比如:
1.generic
根据《RFC 3640》第22页,generic mode可用于任何MPEG-4数据流。在这种模式下,不会应用特定模式的限制;因此,在generic mode下,可以充分发挥《RFC 3640》规范的灵活性。generic mode的标志是:mode=generic:
下面给出一个传输BIFS-Anim流的示例。在此示例中,一个 RTP 数据包中允许传输多个BIFS-Anim的Access Unit(关于Access Unit的概念可以参考:《音视频入门基础:RTP专题(16)——RTP封装音频时,音频的有效载荷结构》)。AU-header包含AU-size字段、CTS-flag 和(如果CTS标志设置为 1)CTS-delta 字段。AU-size和CTS-delta字段的位数分别为10和16。AU-header还包含RAP标志和4位的Stream-state。因此,每个BIFS-Anim AU的AU-header总大小为2 或4个八进制字节。RTP时间戳使用1 kHz时钟。请注意,媒体类型名称是视频,因为BIFS-Anim 流是音视频演示的一部分:
2.AAC-lbr
根据《RFC 3640》第24页,该模式由mode=AAC-lbr标志。该模式支持传输一个或多个大小可变的完整AAC帧。在这种模式下,AAC帧允许交错,因此接收器必须支持去交错。在此模式下,AAC帧的最大大小为63个八位字节。使用该模式时,AAC帧不得分片。因此,使用该模式时,编码器必须确保每个AAC帧的大小最多为63个八进制字节。
该模式的有效载荷配置与《RFC 3640》中定义的可变比特率CELP模式相同。RTP有效载荷由AU Header Section和连接的AAC帧组成。Auxiliary Section必须为空。对于有效载荷中包含的每个AAC帧,一个八位字节的AU-header必须提供以下信息:
a) 有效载荷中每个AAC帧的大小,以及
b) 用于计算每个AAC帧的序列(进而计时)的索引信息。
在AU-header Section,连接的AU-header前面必须有16 位AU-headers-length字段。
除了所需的MIME格式参数外,还必须包含以下参数:sizeLength、indexLength和indexDeltaLength。AAC帧的每个Access Unit总是有固定的持续时间;在此模式下进行交错时,必须用MIME格式参数constantDuration来表示特定的持续时间。此外,交错时必须有maxDisplacement(最大位移)参数。
例子:
注:上述例子中,a=fmtp这一行已被包装,以适应页面大小;它在SDP文件中只占一行。config 参数的十六进制值是《ISO/IEC 14496-3》中定义的AudioSpecificConfig。AudioSpecificConfig指定了采样率为22.05kHz的单声道AAC流。
3.AAC-hbr
根据《RFC 3640》第25页,该模式由mode=AAC-hbr标志发出。该模式支持传输大小可变的AAC 帧。在一个RTP数据包中,既可以传输一个或多个完整的AAC帧,也可以传输AAC帧的单个片段。在这种模式下,AAC帧允许交错,因此接收器必须支持去交错。在此模式下,AAC帧的最大大小为 8191个八进制字节。
在这种模式下,RTP有效载荷由AU Header Section组成,其后是一个AAC帧、几个连接的AAC帧或一个fragmented(片段)AAC帧。 Auxiliary Section(辅助部分)必须为空。对于有效载荷中包含的每个AAC 帧,AU Header Section必须有一个 AU-header,以提供以下信息:
a) 有效载荷中每个 AAC 帧的大小和
b) 用于计算每个 AAC 帧的序列(以及时序)的索引信息。
对AAC帧的最大尺寸进行编码需要13位。因此,在此配置中,13比特分配给AU-size字段,3比特分配给AU-Index(-delta) 字段。因此,每 AU Header的大小为2个八位字节。每个AU-Index字段的编码值必须为0。在AU Header Section,按照《RFC 3640》第3.2.1节的规定,连接的AU-headers前面必须有一个 16 位的 AU-headers-length字段。
除了所需的MIME 格式参数外,还必须包含以下参数:sizeLength、indexLengthh和indexDeltaLength。每个接入单元的AAC帧总是有固定的持续时间;在此模式下进行交错时,必须用MIME格式参数constantDuration来表示这一特定持续时间。此外,交错时必须有maxDisplacement(最大位移)参数。
例子:
注意:a=fmtp这一行已被包起来以适应页面大小;它在 SDP 文件中只占一行。config 参数的十六进制值是《ISO/IEC 14496-3》中定义的AudioSpecificConfig。AudioSpecificConfig指定了采样率为48kHz的5.1 声道AAC流。
(三)sizelength
根据《RFC 3640》第31页,sizelength参数为AU-header中对AU-size字段进行编码的比特数。sizeLength和constantSize参数不得同时存在:
(四)indexlength
根据《RFC 3640》第31页,indexlength参数为在第一个 AU-header中对AU-Index进行编码的位数。默认值为0,表示每个第一AU-header信息中没有AU-Index字段:
(五)indexdeltalength
根据《RFC 3640》第31页,indexdeltalength参数为在任何非第一AU-header中对AU-Index-delta 字段进行编码的比特数。默认值为0,表示每个非第一AU-header信息中没有 AU-Index-delta字段:
(六)config
根据《RFC 3640》第29页,config参数为媒体有效载荷配置的八进制字符串的十六进制表示。配置数据以MSB优先的方式映射到十六进制八进制串上。配置数据的第一位应位于第一个八位位组的MSB。在最后一个八位位组中,如果需要实现八位位组对齐,配置数据后面应最多有7个零值填充位。
对于MPEG-4音频流,config是《ISO/IEC 14496-3》中定义的音频对象类型特定解码器配置数据 AudioSpecificConfig(关于AudioSpecificConfig可以参考《音视频入门基础:AAC专题(11)——AudioSpecificConfig简介》)。对于结构化音频,AudioSpecificConfig() 可通过本规范未定义的其他方式传递。如果结构化音频的 AudioSpecificConfig() 是通过其他方式传送的,那么配置必须是一个带引号的空十六进制八位字符串,如下所示:config=“”。请注意,未来使用结构化音频 RTP 有效负载格式的模式可能会定义这种其他方式:
例子:
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=1190
上述例子中:config=1190
0x1190就是二进制的0b0001000110010000。
使用《音视频入门基础:AAC专题(11)——AudioSpecificConfig简介》中的方法进行解析,0b0001000110010000的前5位为:0b00010,也就是十进制的2,所以音频压缩编码格式为:AAC LC (Low Complexity)。
0b0001000110010000中间的4位为:0b0011,也就是十进制的3,所以音频采样频率为48000Hz。
之后的4位为:0010,也就是十进制的2,所以是双声道(立体声)。