基于ffmpeg的rtsp拉流代碼分析流水賬

概念

RTP: Real-time Transport Protocol,實時傳輸協(xié)議,一般用于多媒體數據的傳輸。

RTCP: RTP Control Protocol,實時傳輸控制協(xié)議,同RTP一起用于數據傳輸的監(jiān)視,控制功能。

RTSP: Real Time Streaming Protocol,實時流協(xié)議,用于多媒體數據流的控制,如播放,暫停等。

RTP/RTCP相對于底層傳輸層,和RTSP,SIP等上層協(xié)議一起可以實現視頻會議,視頻直播等應用

RTP/RTSP/RTCP的區(qū)別 用一句簡單的話總結:RTSP發(fā)起/終結流媒體、RTP傳輸流媒體數據 、RTCP對RTP進行控制,同步。

UDP:

TCP:

HTTP:

SDP:

rtsp服務器配置

基本流程 rtsp服務器配置
但是有一點需要主要的

將此mkv文件復制到和上面live555MediaServer可執(zhí)行文件的同一個目錄,

這里不需要將媒體文件放在live555MediaServer同一個目錄,具體是看執(zhí)行l(wèi)ive555MediaServer進程的所在文件夾
例如:

Download $ ~/vendor/live/mediaServer/live555MediaServer

這時視頻是Download目錄下的

  • live555MediaServer傳輸1080p視頻
    默認配置,在terminal會打印如下錯誤
MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size (100452).  27300 bytes of trailing data was dropped!  Correct this by increasing "OutPacketBuffer::maxSize" to at least 127300, *before* creating this 'RTPSink'.  (Current value is 100000.)

OutPacketBuffer::maxSize默認大小為100000
需要修改DynamicRTSPServer的代碼

} else if (strcmp(extension, ".264") == 0) {
    // Assumed to be a H.264 Video Elementary Stream file:
    NEW_SMS("H.264 Video");
    OutPacketBuffer::maxSize = 157300; // allow for some possibly large H.264 frames
    sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
  } 

然后重新編譯

  • 如何使用rtp over tcp
    在ffmpeg 命令中
 -rtsp_transport tcp -i rtsp://192.168.0.172:8554/bb.264  ./bbo.264

在ffmpeg 代碼中

  if (av_stristart(filename, "rtsp", NULL)) {
        av_dict_set(&o->g->format_opts, "rtsp_transport", "tcp", 0);
    }

err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);
  • rtsp over http
    這時候就不要使用live555MediaServer開啟時打印信息中的http端口
    例如
(We use port 8000 for optional RTSP-over-HTTP tunneling, or for HTTP live streaming (for indexed Transport Stream files only).)

把url的端口號換一下

  if (av_stristart(filename, "rtsp", NULL)) {
        av_dict_set(&o->g->format_opts, "rtsp_transport", "tcp", 0);
    }

err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);

ffmpeg代碼分析

  • ffmpeg rtsp代碼位置
    liveformat/rtsp.c 這個是udp里面的實現
    liveformat/rtspdec.c

avformat_open_input

avformat_open_input >>
 rtsp_read_header >>
ff_rtsp_connect>>
ff_rtsp_setup_input_streams

rtsp連接 ff_rtsp_connect

rtsp的控制方式
RTSP_MODE_PLAIN 普通rtsp
RTSP_MODE_TUNNEL 基于HTTP

  • 分割url:proto, auth, host ,port ,path

  • rtsp HTTP打開連接
    ffmpeg會在http的請求報文頭發(fā)送如下格式

"x-sessioncookie: %s\r\n"
                 "Accept: application/x-rtsp-tunnelled\r\n"
                 "Pragma: no-cache\r\n"
                 "Cache-Control: no-cache\r\n",

x-sessioncookie:只是一個隨機的值
即使不看方法體也能猜出來

     snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",
                 av_get_random_seed(), av_get_random_seed());
  • rtsp tcp打開連接
    簡單的建立信道

  • rtsp 發(fā)送OPTIONS命令,獲取支持的命令
    rtsp 傳輸方式

RAW/RAW ::Support receiving plain data over UDP without any RTP encapsulation
RTP/AVP: RTP transport / audio , video , control protocol
x-pn-tng: 不懂

  • rtsp 發(fā)送 SETUP命令 ff_rtsp_make_setup_request()函數
    status_code = 461 /* Unsupported protocol */
    status_
    驗證c s兩端的協(xié)議,必須一致(大概是怕我們亂改代碼)

interleaved :
The channel identifier is defined in the Transport header with the
interleaved parameter(Section 12.39).
個人理解,tcp是一個持續(xù)的流,所以需要一個interleaved來分割包

ff_rtsp_make_setup_request

  • ffmpeg會執(zhí)行三個動作
    OPTIONS
    查看支持命令
    這里的live555并沒有收到任何的報文信息

DESCRIBE 獲取視頻信息 --就是SDP報文
SETUP 建立RTP通道

rtsp_read_play

ff_read_packet

rtsp_read_packet >> ff_rtsp_fetch_packet

rtp playload格式

參考鏈接:
http://blog.rongpmcu.com/rtpxue-xi/

packetization-mode 0 : 單一NALU

單NAL單元包(Single NAL Unit Packet):負載中只包含單一的NAL單元。NAL頭的類型等同于原始的NAL單元類型,也就是,1~23的范圍。此種包必須只包含單個NAL單元,聚合包和分片單元都不能在這種包內使用。必須按解碼順序發(fā)送.

packetization-mode 1 : non-interleaved 非交錯封包模式

用于聚合多個NAL單元為單個RTP負載。這種包存在四種版本:單時間聚合包(STAP-A),單時間聚合包(STAP-B),多時間聚合包(MTAP)帶16位偏移(MTAP16),多時間聚合包(MTAP)帶24位偏移(MTAP24). NAL類型號分配給STAP-A,STAP-B,MTAP16和MTAP24分別為24,25,26,27。

packetization-mode 2 : interleaved 交錯封包模式

用于分割單一的NAL單元為多個RTP包,共有兩個版本,FU-A和FU-B. 它們的NAL類型號分別為28,29.
分片的原因是為了傳輸大于64KB的NAL單元。
分片針對單個NAL單元,而不是聚合包。
FU不能嵌套。
FU的時戳設置為被分片NAL單元的NALU時間
FU-A包括一個字節(jié)的FU indicator+一個字節(jié)的FU header+FU payload

FU-B比FU-A多了一個字節(jié)的decoding order number(DON).
FU-B必須只被用在交叉包裝模式下NAL分片的第一片。換句話說,在交叉包裝模式,每個NALU被分片為FU-B+FU-A+FU-A+...+FU-A

ff_rtsp_fetch_packet

ff_rtsp_fetch_packet 根據lower_transport 調用不同協(xié)議read_packet的方法

執(zhí)行流程
OPTIONS-> DESCRIBE->RTSP/SDP

  • SDP(Session Description Protocol)
    SDP 會話描述協(xié)議

  • 簡單報文分析

v=0 協(xié)議版本
o=- 1476286318262307 1 IN IP4 192.168.31.194 (所有者/創(chuàng)建者和會話標識符)
s=H.264 Video, streamed by the LIVE555 Media Server (會話名稱)
i=bb.264(會話信息)
t=0 0(會話活動時間)
a=tool:LIVE555 Streaming Media v2016.09.22
a=type:broadcast 
a=control:*
a=range:npt=0-
a=x-qt-text-nam:H.264 Video, streamed by the LIVE555 Media Server
a=x-qt-text-inf:bb.264
m=video 0 RTP/AVP 96(媒體名稱和傳輸地址)
c=IN IP4 0.0.0.0(連接信息 ― 如果包含在所有媒體中,則不需要該字段)
b=AS:500(帶寬信息)
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=640028;sprop-parametersets=Z2QAKKzZQHgCJ+WEAAADAAQAAAMA8Dxgxlg=,aOvjyyLA
a=control:track1
  • a=rtpmap
    H264 編碼名稱
    90000 時鐘頻率
    96 dynamically assigned
    "a=rtpmap" 行中的編碼名稱必須是 "H264".
    "a=rtpmap" 行中的時鐘頻率必須是 90000.
  • packetization-mode:表示支持的封包模式.
    當 packetization-mode 的值為 0 時或不存在時, 必須使用單一 NALU 單元模式.
    當 packetization-mode 的值為 1 時必須使用非交錯(non-interleaved)封包模式.
    當 packetization-mode 的值為 2 時必須使用交錯(interleaved)封包模式.

  • sprop-parameter-sets: SPS,PPS
    這個參數可以用于傳輸 H.264 的序列參數集和圖像參數 NAL 單元. 這個參數的值
    采用 Base64 進行編碼. 不同的參數集間用","號隔開

  • profile-level-id:
    這個參數用于指示 H.264 流的 profile 類型和級別. 由 Base16(十六進制) 表示的 3 個字節(jié). 第一個字節(jié)表示 H.264 的 Profile 類型, 第三個字節(jié)表示 H.264 的 Profile 級別:

參考資料

用實例分析H264 RTP payload

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容