1. 程式人生 > >rtsp/rtp基礎學習-1

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++;