rtp问题引领汇总
視頻網(wǎng)絡(luò)傳輸一定要用rtp嗎?
RTP/RTCP有一套很好的反饋機(jī)制,通過其可以估算網(wǎng)絡(luò)狀況,然后在編碼端進(jìn)行調(diào)整,如網(wǎng)絡(luò)繁忙時(shí)適當(dāng)?shù)?strong>降低畫面質(zhì)量,減小碼率等,主要是想通過RTP/RTCP協(xié)議實(shí)現(xiàn)QoS!同時(shí)也可以用http或udp啊,都可以的,自己再加一些控制信息。利用rtp/rtcp的好處是這個(gè)協(xié)議本身幫你加入了 一些控制信息。
相信有不少人和我一樣,希望實(shí)現(xiàn)H264格式視頻的流媒體播放。但是對于一個(gè)新手來說,往往不知道從何入手。利用百度,GOOGLE等搜索資料真是沙里淘金。在琢磨了N周之后,才弄出來了點(diǎn)成果,其中費(fèi)了很多無用的功夫,光看英文協(xié)議就費(fèi)了一周,后來才知道有中文版,并且我所達(dá)到的目的很簡單,只要讓VLC實(shí)時(shí)播放就行,不需要了解整個(gè)協(xié)議。我也很希望能直接搜出來一套代碼,都一直沒找到,還是得自己動手。現(xiàn)在我把代碼貼出來,希望對做類似工程的朋友有所幫助。
????????? 一、本示例代碼在我的電腦上實(shí)現(xiàn)了對標(biāo)準(zhǔn)H264碼流的RTP打包發(fā)送到本機(jī)的1234端口,用VLC播放器從1234端口能接收到該碼流并實(shí)時(shí)播放。代碼附有詳細(xì)的注釋,應(yīng)該很容易理解(前提是大家稍微對RFC3550 RFC3984協(xié)議有了解)。
????????? 二、本示例代碼是按照RFC3984協(xié)議僅完成了RTP打包,并沒有完成發(fā)送RTCP。原因就引用這位達(dá)人的話:“1.RTCP里頭有很多關(guān)于RTCP發(fā)送簡隔的時(shí)間計(jì)算,RTP信息的統(tǒng)計(jì),這種操作不是難,而是煩,我不想去寫。2.RTCP和RTP一開始出來的時(shí)候并不是因?yàn)橐曨l的點(diǎn)播等應(yīng)用的,而是視頻會議。RTCP有管理與會者的層面含義,這一功能在很多場合并不會用到。3.我想簡單,沒有寫多個(gè)流間的同步,如一個(gè)影片的視頻和音頻流。這些其實(shí)是RTCP來完成的。我懶得去寫,因?yàn)檫@些功作RTP的各個(gè)庫類(例如JRTPLIB庫)都做得很好。我覺得用庫的最大優(yōu)點(diǎn)就在這吧”。
????????? 三、和代碼相關(guān)的原理性的東西,大家應(yīng)該去看看RFC3550,RFC3984.這兩份協(xié)議都有熱心網(wǎng)友翻譯好的中文版。我把他們放在壓縮包里,大家就不用再累個(gè)半死去搜索注冊下載了。如果為了更省事,我覺得看看這位網(wǎng)友總結(jié)的RFC3984的內(nèi)容就夠了。網(wǎng)址是http://www.cppblog.com/czanyou/archive/2009/12/25/67940.html。如果打不開網(wǎng)頁,就到壓縮包里資料文件夾下找吧。我已經(jīng)把網(wǎng)頁保存下來了。
????????? 四、代碼并非是我完全原創(chuàng)的,而是我在搜索到得網(wǎng)友的代碼的基礎(chǔ)上修改的。這里要特別感謝以下幾位網(wǎng)友:
1.貓頭上的鷹(他的博客地址http://blog.csdn.net/Tinnal/archive/2008/09/03/2871734.aspx)在他的博客里我第一次找到了有價(jià)值的東西,并且他無償提供的MPEG的RTP打包源碼只要拷貝下來建個(gè)工程就能實(shí)現(xiàn)MPEG的流媒體,對我啟發(fā)很大。
2.liming,他提供的代碼已經(jīng)實(shí)現(xiàn)了H264的碼流分析,將其中的每個(gè)NALU單元分離開來,并分析出了NALU的類型,長度等信息。為我實(shí)現(xiàn)RTP打包提供了很大的方便,事實(shí)上,這份示例代碼就是在他的代碼上添加了RTP打包部分,我連工程名字都沒有改。他的源代碼在這里
3.luny,他提供的SDP文件在關(guān)鍵時(shí)候幫了我大忙,我發(fā)送的RTP數(shù)據(jù)包通過Wireshark抓包工具分析一直沒錯(cuò),可VLC播放器就是沒任何反應(yīng)。直到下載了他的SDP文件文件后終于出畫面了。某位網(wǎng)友說VLC對H264只能通過TS封包或SDP文件打開RTP碼流,在此我這么懷疑。
4.jessiepan和他的帖子,http://topic.csdn.net/u/20090725/11/5FBC75B0-1091-4DD4-9154-3E3D59F9B6D1.html,這里提供了很多有用的信息。
??????????? 使用方法:直接在VC6上打開工程,編譯。(需要注意的是大家要把IP地址改為自己的。在h264.h的#define DEST_IP ?? ??? "192.168.0.30"和#define DEST_PORT 1234這兩行修改就行了。同時(shí)w.sdp文件里也要改成一致的IP和端口號,不然VLC是接受不到數(shù)據(jù)的。在c=IN IP4 192.168.0.30 和m=video 1234 RTP/AVP 96這兩行。中間的1234是我設(shè)置的端口號。)在執(zhí)行程序之前,先用VLC打開w.sdp文件,然后執(zhí)行程序,就可以看到畫面了:)。同樣需要注意的是VLC1.0以后的版本不支持直接打開h.264視頻文件,但是0.97版本就支持。這里我測試用1.03和0.97兩份版本]的VLC都可以接受并播放h.264RTP碼流。
目前還有幾個(gè)問題我沒有弄明白,希望有高手在看完這個(gè)帖子后能幫我解答:
1.關(guān)于時(shí)間戳的設(shè)置。RFC3984里沒有提到時(shí)間戳具體如何計(jì)算,我也是按照各方面的小道消息這樣設(shè)置。unsigned int timestamp_increse=0;timestamp_increse=(unsigned int)(90000.0 / framerate); 即初始值設(shè)為0,時(shí)間戳增量設(shè)為90000.0 / framerate,framerate我設(shè)為25,即每秒25幀。每發(fā)送一個(gè)NALU單元,時(shí)間戳增加。若是該NALU大于1400字節(jié),需要分片時(shí),則多個(gè)分片擁有相同的時(shí)間戳。這樣設(shè)置是否正確。請牛人給個(gè)權(quán)威解答。
2.按照我的理解,SDP文件僅實(shí)現(xiàn)了告訴VLC在哪個(gè)IP和端口接受264RTP包,同樣的信息我也通過在VLC的媒體-》打開網(wǎng)絡(luò)串流,協(xié)議選RTP,然后填寫IP和端口號中設(shè)置好了,為什么用打開SDP文件的方法能接收,但用后者VLC卻沒有一點(diǎn)反應(yīng)。
3.當(dāng)我將幀率設(shè)為25時(shí)(即代碼里的float framerate=25;)vlc能接受碼流,但會比較卡,常緩沖,提示錯(cuò)誤為main error: ES_OUT_SET_(GROUP_)PCR?? is called too late, increasing pts_delay to 339 ms。我懷疑是我的電腦發(fā)送UDP包速度不夠每秒播放25幀的所需要的UDP包數(shù)量,因此在SDP文件我添加了a=framerate:15來限制播放器每秒播放15幀,同時(shí)在代碼里的相應(yīng)行float framerate=15;也將幀率改為15這樣雖然解決了卡的問題,但是視頻播放很慢。請問要是我想達(dá)到每秒播放25幀,難道只能換臺好電腦了?
5.下一步我想用jrtplib來打包RTP,因?yàn)槁犝f用這個(gè)庫實(shí)現(xiàn)RTCP很方便,是不是這個(gè)庫會根據(jù)網(wǎng)絡(luò)狀況自動發(fā)送RTCP信息。如果哪位高手有這方面的代碼或者是實(shí)現(xiàn)了RTSP的代碼,希望能拿出來交流,哪怕是部分代碼或者是實(shí)現(xiàn)部分功能也好。
1、第一個(gè)問題,如果你看過 RFC3984 就應(yīng)該知道答案;
2、第三個(gè)問題,我認(rèn)為不是發(fā)包速度的問題,發(fā)包其實(shí)是非常快的;
3、第四個(gè)問題,可以參考 Darwin 的源代碼(下載地址:http://dss.macosforge.org/),不過這套代碼非常龐大。VLC 的服務(wù)端源代碼也應(yīng)該會發(fā) RTCP 吧?
A:RFC里說時(shí)間戳是RTP數(shù)據(jù)包里第一個(gè)字節(jié)的采樣時(shí)間,就是說我在給一個(gè)NALU數(shù)據(jù)打上報(bào)頭的時(shí)候調(diào)用系統(tǒng)函數(shù)time()來獲取當(dāng)前的系統(tǒng)時(shí)間(從1970年1月一日到現(xiàn)在所經(jīng)過的秒數(shù)),這個(gè)秒數(shù)就是應(yīng)該打在RTP包頭上的時(shí)間戳嗎? 還有RFC3984里提到必須使用90K的時(shí)鐘,這個(gè)90K的時(shí)鐘是干什么用的了?麻煩解答一下
我認(rèn)為其實(shí)時(shí)間戳從 0 開始也可以。90K 是一個(gè)參考時(shí)鐘,例如你的系統(tǒng)是 30fps,那么幀與幀之間的時(shí)間戳增量就該是 90000 / 30 = 3000。
A:謝謝版主,那我在第一個(gè)問題中敘述的時(shí)間戳設(shè)置方法看來是蒙對了啊。
不過關(guān)于第三個(gè)問題,當(dāng)我把幀率設(shè)為25fps時(shí),VLC經(jīng)常緩沖,然后就會有馬賽克了。版主知道這可能是什么原因嗎??? 經(jīng)過我測試,只要幀率設(shè)為18fps以下,就沒有這個(gè)問題。
這個(gè)得做實(shí)驗(yàn)具體分析了。有誤碼,說明碼流出錯(cuò)了。先截取一下 VLC 收到的碼流,看是否是正確的。
A:我用LZ的程序進(jìn)行傳輸并播放,LZ程序中自帶的兩個(gè).264文件都能正常播放,但是我用JM編碼生成的.264文件就不能播放,這是為什么呢?請高手解答~~~
因?yàn)?JM 編碼生成的 RTP 格式的 264 碼流不是標(biāo)準(zhǔn) RTP 格式。
A:我想請教您一個(gè)問題?? 如果不打成RTP包 直接打成TCP包可以么 我這個(gè)問題問的很無知 但是還是請您回答我下
如果打成TCP包,那就只有你自己的播放器能播了,因?yàn)橥ㄓ玫牟シ牌?#xff0c;或者說是標(biāo)準(zhǔn)的播放器,都是播放RTP打包的數(shù)據(jù)。
A:如何判斷nalu是否屬于同一幀圖像呢,難道根據(jù)unit_type嗎?貌似這樣也不對啊,nalu里有沒有什么信息可以用來判斷的嗎,等待牛人指導(dǎo)。
編碼器自己本來就知道哪些 NALU 屬于一幀。
總結(jié)
- 上一篇: 使用oprofile分析性能瓶颈
- 下一篇: Winsock网络编程快速入门