天天看點

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

RTP在流媒體傳輸中是廣為應用的一種協定,包括大家熟知的GB28181協定以及很多視訊會議的應用,都是采用RTP。常用的RTSP協定實際上也是在RTP基礎上實作的。RTP并不複雜,本質上可以了解為RAW資料加上一些頭,封裝以後進行UDP傳輸。封包結構是這樣的:

1 2 3
1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 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的加密資料有點問題,還在研究中。

繼續閱讀