rtsp/rtp基础学习-1

#协议规范

1.协议规范地址 https://tools.ietf.org/html/rfc1889
    下面首先给出有关 RTP 的一些定义:
• RTP会话(RTP session):RTP传输服务使用者之间的连接被称为RTP会话,就每一个会话参加者而言,会话由一对传输层地址(即一个网络层地址加上 两个端口地址,一个端口为 RTP 报文所占用,另一个端口为 RTCP 报文标识。

• RTP媒体类型:由一个RTP会话传送的所有净荷类型的集合。RTP应用 文档指定 RTP 媒体类型和 RTP 净荷类型的关系。

• RTP 净荷:由 RTP 传送的数据,如音频抽样信号,压缩视频数据等。净荷 格式及其解释由应用层规定。

• RTP分组:由RTP头部和净荷数据组成。通常下层传送协议的一个数据 包(如一个 UDP 包)只含一个 RTP 分组;如果采用一定的封装方法,也可以包 含多个 RTP 分组。
    主要内容包括RTP Fixed Header Fields、Multiplexing RTP Sessions、 RTP Header Extension、Profile-Specific Modifications to the RTP Header、RTP Header Extension
rtp fixed head

rtp_read_header细节

    一般情况下都是判断头部的时候ffurl_read(in, recvbuf, sizeof(recvbuf))获取到RTP_MAX_PACKET_LENGTH字节数,然后判断第一个字节(recvbuf[0] & 0xc0) != 0x80,找到最高位version为1。
RTP_PT_IS_RTCP(recvbuf[1] )接口的意义:rtp媒体包数据之后可能会mix一些rtcp的数据,rtcp中的第二个字节通常为RTCP_FIR 等等RTCP_SR 的一些信息

#define RTP_PT_IS_RTCP(x) (((x) >= RTCP_FIR && (x) <= RTCP_IJ) || \
                           ((x) >= RTCP_SR  && (x) <= RTCP_TOKEN))

ff_rtsp_fetch_packet

    utils.c里面av_read_internal_frame/read_frame_internal来获取一帧的es数据,如果AVInputFormat为ff_rtp_demuxer那么就会依次调用到ff_rtsp_fetch_packet来获取帧packet数据,(ff_rtp_handler_find_by_id最后获取到对应格式的的处理包函数parse_packet)这个是在rtsp.c中最开始处理sdp描述符的时候获取得到的,接着ret = ff_rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);最终Rtpdec.c中rtp_parse_one_packet来获取AVPacket数据包

rtp_read

    作为URLProtocol结构体中的url_read接口,来获取指定大小的数据url_read接口定义为***read(URLContext *h, uint8_t *buf, int size),指定参数分别为URL上下文,目的地址和大小,上下文包含协议URLProtocol的引用关联,还包括url名称等等。在demux过程中ff_rtsp_fetch_packet会通过read_packet来获取通过网络IO/poll获取数据

ff_sdp_parse

    sdp完全是一种会话描述格式,非传输协议,并结合不同的传输协议使用,一般为SAP、SIP、RTSP、MIME、HTTP协议,sdp是一种文本协议,所以具有很高的扩展性。
    在rtp_read_head的过程中获取了网络协议族、主机地址、端口号、媒体类型:

snprintf(sdp, sizeof(sdp),
             "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
             addr.ss_family == AF_INET ? 4 : 6, host,
             par->codec_type == AVMEDIA_TYPE_DATA  ? "application" :
             par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
             port, payload_type);

    ff_sdp_parse,在获取sdp字符串后,首先过滤掉t\r\n等字符串,然后查找 = 为分割的参数集,并用字符串数组buf来存放值,q为游标获取value的范围。最终sdp_parse_line来解析,下面以字符c为letter解析规范,默认设置跳数为16

"c=" 行:给出连接参数。具体形式为:c=<network type> <address type> <connection address>。其中:
    <network type>是网络类型。最初定义的是"IN",含义是指"Internet"。
    <address type> 是地址类型。这允许SDP被用于不是基于IP的会话。当前只定义了IP4。
    <connection address>是连接地址。可选的附加子域可以加在连接地址后面,这取决于 <address type> 域的值。地址类型是 IP4 的情况,典型的连接地址将会是D类的 IP 多播组地址。使用IP多播组地址作为连接地址时必须增加有一个会话的存活时间 (TTL) 值TTL 值范围是 0-255。。TTL 和IP多播组地址一起定义了会议中的多播包发送的范围。会话的TTL加在地址的后面,通过一个‘/’斜杠分隔。一个例子:c=IN IP4 224.2.1.1/127。     
for (;;) {
        p += strspn(p, SPACE_CHARS);
        letter = *p;
        if (letter == '\0')
            break;
        p++;
        if (*p != '=')
            goto next_line;
        p++;
        /* get the content */
        q = buf;
        while (*p != '\n' && *p != '\r' && *p != '\0') {
            if ((q - buf) < sizeof(buf) - 1)
                *q++ = *p;
            p++;
        }
        *q = '\0';
        sdp_parse_line(s, s1, letter, buf);
    next_line:
        while (*p != '\n' && *p != '\0')
            p++;
        if (*p == '\n')
            p++;
发布了38 篇原创文章 · 获赞 5 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zhiyanzhai563/article/details/83929823