Q:現在小弟初次嘗試H264的編碼通過RTP方式傳輸,具體實驗環境的問題如下:
環境:
服務器端,H264的幀數據(可能超過64k),分成N個1460字節的包,然后加上RTP頭發送。
客戶端,VLC播放器,通過RTSP協議建立連接,然后接收數據解碼播放。
結果:
VLC不能解碼接收到的數據,解碼出錯,VLC的信息中顯示不能解碼幀數據。
我已經閱讀了一遍rfc3984的文檔,對里面的如何進行打包和用rtp傳輸不是非常理解,希望各位大蝦能夠幫小弟一把,告訴小弟這些和H264的幀該如何發送,該如何分包,該如何加頭信息等等。
(其中看到FUs的方式好像適合分包發送,因為小弟的數據幀可能超過64k,所以忘大蝦們能夠仔細解釋一下對于小弟這種情況下的RTP傳輸)
A:我覺得所有的問題在 RFC3984 里面都已經說得很清楚了。不知道你有哪點不懂,請具體提出來。
Q:斑竹好,我這邊是用VLC和服務器端進行通訊的,他們是用RTSP協議建立開始時的連接的,服務器返回DISCRIBERS請求的SDP和下面描述的相同,我使用的packetization-mode=1,即FU-As方式打包,因為我這邊上來的數據幀可能超過64k數據。能否麻煩斑竹看看我這邊的SDP寫的是否正確。 SDP: v=0 o=- 1 1 IN IP4 127.0.0.1 s=VStream Live a=type:broadcast t=0 0 c=IN?? IP4 0.0.0.0 m=video 49170 RTP/AVP 99 a=rtpmap:99 H264/90000 a=fmtp:99 profile-level-id=42A01E; packetization-mode=1; sprop-parameter-ets=Z0IACpZTBYmI, aMljiA== a=control:trackID=0
還有就是在RTP發送時,我打好包的數據方式如下面所示: 上來的幀數據為:NALU頭+EBSP數據 因為幀數據大于1460字節,所以我把數據分為N個不大于1460字節的包,每個包前面加上RTP頭發出去。 其中NALU頭的數值I幀為0x65,參數集為0x67和0x68,這個值是不是有點錯誤,我看RFC3984上面說的好像和我現在的有點不同,RFC3984上面說FU-As方式打包類型值為28,我不知道這個是否十進制的,如果按照RFC3984上說的NALU頭應該是多少?還是用FU-As方式的FU indicator代替原來的NALU頭。 還有這個FU-As方式的頭好像是有兩個值,一個是FU indicator,另外一個是FU header,這兩個值我應該填寫什么?
按照我現在填寫的內容,VLC會出現解不出碼的情況,希望斑竹可以幫我回答的細致一點。謝謝了。 A:我覺得 RFC3984 上面說得非常清楚啊。 首先你把一個 NALU 的 EBSP 根據需求拆分為多個包,例如 3 個,則:
第一個 FU-A 包的 FU indicator 應該是:F = NALU 頭中的 F;NRI = NALU 頭中的 NRI;Type = 28。FU header 應該是:S = 1;E = 0;R = 0;Type = NALU 頭中的 Type。
第二個 FU-A 包的 FU indicator 應該是:F = NALU 頭中的 F;NRI = NALU 頭中的 NRI;Type = 28。FU header 應該是:S = 0;E = 0;R = 0;Type = NALU 頭中的 Type。
第三個 FU-A 包的 FU indicator 應該是:F = NALU 頭中的 F;NRI = NALU 頭中的 NRI;Type = 28。FU header 應該是:S = 0;E = 1;R = 0;Type = NALU 頭中的 Type。 Q:版主,我按照你的方式分好包發送了,發現VLC不會出現不能解幀的情況了,但是,還是出不來圖像。我想可能是因為發送序列參數集和圖像參數集的方法不對,他們兩個的長度都很小,只要一個包就可以了,我現在將他們按照singal NALU的方式發送,就是直接在NALU包前加一個RTP的頭,然后發出去。 是不是我這樣發參數集存在著問題,反正我這邊VLC是解不了這個參數集,因為參數集解不了,所以下面的幀肯定解不了,所以出不了圖像。 麻煩版主再解釋一下如何發參數集。 A:今天剛接受了流媒體的相關培訓。懂得看你的?? SDP 了。
對于你的問題,不知道 SPS、PPS 打包是否有問題。按照 RFC3984,而且感覺你打單一包的方式也是錯的。我希望你能通過自己學習的方式去把這個問題弄清楚,因為 RFC3984 里面說得很清楚,請你自己學習學習 RFC3984 吧。既然你在做這個工作,還是應該仔細學習一下 RFC3984。
另外, SDP 中的 sprop-parameter-ets=Z0IACpZTBYmI 實際就是 SPS 和 PPS 的 BASE64 轉碼,你不用在碼流中再傳輸 SPS/PPS,直接從 SDP 就可以得到。 A2:1. SDP中已經包括SPS&PPS,碼流中完全可以不用傳輸SPS&PPS 2. profile-level-id=42A01E,這是SPS的開頭幾個字節,剩下的在sprop-parameter-ets=Z0IACpZTBYmI, aMljiA==中,BASE64編碼,把“Z0IACpZTBYmI, aMljiA==”反BASE64轉換回去,應該剛好是SPS&PPS的內容 3. 打包注意,要求H.264碼流不是byte stream格式的,即沒有0x000001分隔,也沒有插入0x03,具體如何生成,檢查你的編碼器選項。 4. packetization-mode=1模式下,要求每個RTP中只有一個NAL單元,或者一個FU,不分段的NAL不做任何修改,直接作為RTP負載;分段的NAL注意,NAL頭不傳輸,有效負載從NAL頭之后開始,根據NAL頭的信息生成FU的頭兩個字節(相當于NAL頭拆為兩部分),具體生成方式版主已經講得很清楚。 5. RTP的payload type要與SDP中一致,不然解的出才怪 |