FFMPEG對攝像頭進行RTP推流,以及RTP轉發服務

RTP在流媒體傳輸中是廣爲應用的一種協議,包括大家熟知的GB28181協議以及很多視頻會議的應用,都是採用RTP。常用的RTSP協議實際上也是在RTP基礎上實現的。RTP並不複雜,本質上可以理解爲RAW數據加上一些頭,封裝以後進行UDP傳輸。報文結構是這樣的:

0 1 2 3
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
V P X CC(4bit) M PT(7bit) Sequence Number(16bit)
timestamp(32bit)
SSRC標識符(32bit)
CSRC標識符(n個32bit)
playload

每個字段具體的含義可查閱相關資料。RTP傳輸的時候,並不保證數據包按序號傳送,即使下層網絡提供可靠性傳送,也不能保證數據包的順序到達,包含在RTP中的序列號就是供接收方重新對數據包排序之用。與RTP對應的,還有RTCP是控制協議。正常情況下,RTP和RTCP是使用配套的兩個端口,RTP都是使用偶數端口,例如,要給目標地址的30010端口發送RTP數據,則30011端口會發送RTCP數據。
 

使用FFMPEG可以進行RTP的推流測試,接收端可以用VLC,也可以用FFPLAY。以下命令行使用內置攝像頭採集實時視頻,h.264編碼,幀率25fps,GOP爲25,低延時,以RTP推送到本機的30010端口,並生成一個sdp文件用於播放使用:

ffmpeg -f dshow -i video="Integrated Camera" -b:v 500k  -r 25 -g 25 -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f rtp rtp://127.0.0.1:30010 > v.sdp

攝像頭的名字每個電腦不一定相同,可以用ffmpeg命令查看,也可以在電腦屬性裏面看設備名稱。如果要播放,可以把生成的這個sdp文件拷貝下來,用VLC打開播放。但是注意生成的文件第一行有SDP這幾個字母,要把這行刪掉,不然VLC播放出錯。用ffplay也可以播放,命令行如下:

ffplay -protocol_whitelist "file,udp,rtp" -i v.sdp

類似地,也可以採集麥克風數據,推送AAC音頻,命令行如下:

ffmpeg -f dshow -i audio="Microphone Array (Realtek High " -acodec aac -ar 32000 -b:a 128k -f rtp rtp://127.0.0.1:30012 > a.sdp

麥克風的名字同樣自己去查。

以上的命令行推流,都是用的RTP裸流,也有一些場景是要求對數據採用PS或TS進行封裝以後再推送的。此外,視頻音頻也可以在一個命令行進行推送,,播放方式類似:

ffmpeg -fflags +genpts -f dshow -i video="Integrated Camera":audio="Microphone Array (Realtek High " -an -s 720x576 -b:v 500k -r 25 -g 25 -bufsize 2000k -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f rtp rtp://127.0.0.1:30010 -vn -acodec aac -ar 32000 -b:a 128k -f rtp rtp://127.0.0.1:30012 > av.sdp

實際使用的時候,很多情況下是需要一個發送端,多個接收端,這個時候就需要有RTP的轉發服務器。自己寫代碼的話,有兩種方式,一種是直接UDP接收,數據放在隊列裏,開一個線程把隊列裏面的UDP數據發出去。因爲RTP實際上就是UDP的數據,所以這種方式也是能轉發的,但是丟包情況很感人,實測發現播放經常花屏、亂序。另外一種方式,可以使用開源的jrtplib,收到數據放到隊列以後,調用jrtplib的接口重新對裸數據封裝rtp包,打時間戳,加序號以後再發送。這樣的效果就非常好。兩個程序都寫了,做了對比,最後用rtp的這種形式,封裝了接口,很好用。目前還欠缺的是srtp的加密數據有點問題,還在研究中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章