從攝像頭擷取的視訊資料,經過編碼後(當然,也可以不編碼,如果你覺得也很ok的話),既可以視訊錄制,同時如果需要,當然也可以視訊遠端傳輸咯,而實時傳輸協定(real-time transport protocol,rtp)是在internet上處理多媒體資料流的一種網絡協定,利用它能夠在一對一(unicast,單點傳播)或者一對多(multicast,多點傳播)的網絡環境中實作傳流媒體資料的實時傳輸(不需要下載下傳完畢後才能看視訊)。rtp通常使用udp來進行多媒體資料的傳輸,但如果需要的話可以使用tcp等其它協定,整個rtp協定由兩個密切相關的部分組成:rtp資料協定和rtcp控制協定。
rtp資料協定負責對流媒體資料進行封包并實作媒體流的實時傳輸,每一個rtp資料報都由頭部(header)和負載(payload)兩個部分組成,其中頭部前12個位元組的含義是固定的,而負載則可以是音頻或者視訊資料。
rtcp 控制協定需要與rtp資料協定一起配合使用,當應用程式啟動一個rtp會話時将同時占用兩個端口,分别供rtp和rtcp使用。 rtp本身并不能為按序傳輸資料包提供可靠的保證,也不提供流量控制和擁塞控制,這些都由rtcp來負責完成。通常rtcp會采用與rtp相同的分發機 制,向會話中的所有成員周期性地發送控制資訊,應用程式通過接收這些資料,從中擷取會話參與者的相關資料,以及網絡狀況、分組丢失機率等回報資訊,進而能 夠對服務品質進行控制或者對網絡狀況進行診斷。
實時流協定(realtime streaming protocol,rtsp),它的意義在于使得實時流媒體資料的受控和點播變得可能。總的說來,rtsp是一個流媒體表示協定, 主要用來控制具有實時特性的資料發送,但它本身并不傳輸資料,而是必須依賴于下層傳輸協定所提供的某些服務。rtsp 可以對流媒體提供諸如播放、暫停、快進等操作,它負責定義具體的控制消息、操作方法、狀态碼等,此外還描述了與rtp間的互動操作。
一、jrtplib庫的安裝
linux:
rtp的運作當然少不了jrtplib庫的支援,jrtplib是一個面向對象的rtp封裝庫,安裝過程如下:
2) 解壓後出現兩個目錄,一個是jrtplib-3.7.1,一個是jthread-1.2.1。jrtplib是一個開源的rtp庫。jthread是一個開源的線程類。
3)進入jthead解壓目錄,運作./configure配置環境. 配置完畢後運作make, 接着安裝make install。
4)jrtplib安裝同上。裝好以後系統環境如下,靜态動态庫安裝到了/usr/local/lib目錄下,包括libjrtplib-3.7.1.so和libjthread-1.2.1.so等。頭檔案在/usr/local/include目錄jrtplib*目錄下。
5)linux預設會在路徑為/lib和/usr/lib下的庫檔案收縮,而上面的庫檔案在/usr/local/lib下,可以在/lib或者在/usr/lib下建立該庫的快捷方式: ln -s /usr/local/lib/libjrtp-3.7.1.so /usr/lib/libjrtp-3.7.1.so
6)在jrtplib源代碼目錄裡有例子程式,make檔案都是寫好的,試驗一下編譯example1.cpp,使用靜态庫libjrtp.a連結,編譯語句如下:g++ -o example1 example1.cpp -i /usr/local/include/jrtplib3/ -ljrtp。
7)最後執行指令:ldconfig,更新庫的資訊,這樣執行檔案./example1,就可以了
windows:
1)解壓 jrtplib-3.7.1和 jthread-1.2.1
2)用 vc打開工程檔案jthread.dsw
3)編譯 jrtplib.lib和jthread.lib需要注意vc6要求安裝vs6sp6,在編譯jrtplib.lib和jthread.lib前,在 project——settings——c/c++——codegeneration:use run-time library中,對于 debug,選擇:debugmultithreaded dll,對于release,則選擇:multithreaded dll。
4)首先編譯 jthread 庫,然後将 jthread-1.2.1\src内的"jmutex.h"和"jthread.h"兩個頭檔案放入jrtplib-3.7.1\src目錄下,然後将 jrtplib-3.7.1\src 檔案夾下所有頭檔案中的和語句修改為"jmutex.h"和"jthread.h",需要修改的檔案為 rtpudpv4transmitter.h、rtpsession.h和 rtppollthread.h。編譯時注意編譯方式和 jthread.lib一緻。
5)編譯生成的 jthread.lib 和 jrtplib.lib 拷貝到系統目錄:c:\program files\microsoft visual studio\vc98\lib 下,将 jrtplib-3.7.1\src下所有的.h 頭檔案複制到 c:\program files\microsoftvisual studio\vc98\include,以便以後使用。
6)現在我們就可以編譯 jrtplib-3.7.1\examples 下的執行個體程式了。建立 vc 工程,打開example1.c,在 project settings 的 link 頁添加 jthread.lib jrtplib.lib ws2_32.lib,在project——settings——c/c++——code generation:use run-time library 中,對于 debug,選擇:debugmultithreaded dll,對于 release,則選擇:multithreaded dll。
7)編譯源程式,運作就ok 啦
二、h.264 rtp payload
在傳輸前,先要了解h.264 rtp payload 格式(負載格式):

2.分片封包模式(核心代碼即為該模式,以及單個nal單元包): 而當 nalu 的長度超過 mtu (1024)時, 就必須對 nalu 單元進行分片封包. 也稱為 fragmentation units (fus).
三、資料(無攝像頭,即黑屏資料)
1)h.246部分資料:
這是一個序列參數集 nal 單元. [00 00 00 01] 是四個位元組的開始碼, 67 是 nalu 頭, 42 開始的資料是nalu内容.
2)rtp,即sendpacket()發送的部分資料:
fu indicator:0x7c (nalu&0x60)|28 ==(0110 0111 & 0110 0000) | 28 == 01100000 | 0001 1100 == 0111 1100 ==0x7c
fu header:0x87 (nalu&0x1f)|0x80 == (0110 0111 &0001 1111) | 0x80 == 0000 0111 | 1000 0000 == 1000 0111 == 0x87
這2個位元組取代了開始碼[00 00 00 01] 。其他的都一樣。
nalu:0x67: 0 11 00111(7)
fu indicator:0x7c:0 11 11100(28)
3)網絡抓包資料
14 e6 e4 1c c9 7a06 ed b5 c3 aa 23 0800 45 00 00 30 00 00 40 00 40 11 b6 b8 c0 a8 01 42 c0 a801 72 3e d0 04 d200 1cf5 da 80e2 a8c1 8c 94f8 dd 31 1f06 d7 61 e2 0b 14 28 00 c6 30(62位元組)
14 e6 e4 1c c9 7a06 ed b5 c3 aa 23 0800 45 00 00 31 00 00 40 00 40 11 b6b7 c0 a8 01 42 c0 a8 01 72 3e d0 04 d2 00 1d ce be 80 e2 a8 d4 8c 96 04 0d 31 1f 06 d7 61e8 01 5c 50 a003 18 c0(63位元組)
14 e6 e4 1c c9 7a06 ed b5 c3 aa 23 0800 45 00 04 29 00 00 40 00 40 11 b2 bf c0 a8 01 42 c0 a8 01 72 3e d0 04 d2 04 15 5a 5b 80 62 a8 c08c 94 ea cd 31 1f 06 d77c 8742e0 1e db 02 c0 49 1000 00 00 01 68 ce 30 a4 80 0000 00 01 06 e5 01 db 80 00 00 00 01 65 b8 00 02 7c 80 6c50 a2 62 80 00 90 3d f7 df 7df7 df 7d f7 df 7d f7 df 7d f7 df 7d f7 df 7d f7 df 7d f7 df 7d f7 df 7d f7 df7d f7 df 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d75d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d75 d7 5d 75 d7 5d 75 d7 5d 75 d7 5d 75(第一個包,1079位元組)
四、rtp視訊傳輸代碼
#define pload_type 98
#define defaulttimestampincrement 90000/25
static rtpsession sess;
//建立rtp會話
static int rtpsetup( uint16_t portbase)
{
int status;
*******************************
*******************************
status = sess.create(sessparams,&transparams);
checkerror(status);
return status;
}
//錯誤判斷
void checkerror(int err)
{
if (err < 0)
{
char* errstr = rtpgeterrorstring(err);
printf("error:%s\\n", errstr);
exit(-1);
}
//增加rtp傳輸目标ip位址,參數為目标ip和端口
int adddestination(uint32_t ipaddr, uint16_t destport)
rtpipv4address addr(ipaddr,destport);
status = sess.adddestination(addr);
//rtp視訊傳輸,val為一幀資料流(264的原始資料),包含0x00 0x00 0x00 0x01資訊,length為資料的長度
int h264sendpacket(unsigned char *val, uint32_t length)
int status=0;
uint32_t timestampincrement;
uint32_t send_length,valid_len=length-4;
char nalu=val[4],*sendstartaddr=null;
#define max_stream_slice 1024
//擷取預設設定
timestampincrement=sess.getdefaulttimestampincrement();
//如果資料小于1024位元組,直接發送:單一nal單元模式
if(valid_len <= max_stream_slice)
{
status = sess.sendpacket((void *)&val[4],valid_len,pload_type,true,defaulttimestampincrement);
checkerror(status);
}
else
//切分為很多個包發送,每個包前要對頭進行處理,如第一個包
sendstartaddr=(char *)(val+4);//發送資料的起始位址
sendstartaddr[pos-1]=(nalu&0x60)|28;//fu indicator
sendstartaddr[pos]=(nalu&0x1f)|0x80;//fu header
send_length=max_stream_slice+1;//要發送資料的長度,1025位元組
………………………………
//第二個至倒數第二個包
//最後一個包
end:
對了,記得要連接配接rtp庫哦!!!!
五、sdp參數
因為程式是在hi35xx開發闆上運作,是以我的工作是把編碼後的視訊發送出去就ok了
。
在windows下,寫了一個腳本xxx.dsp,内容如下:
m=video 1234 rtp/avp 98
a=rtpmap:98 h264/90000;
a=decode_buf=300;
a=framerate:15
c=in ip4 192.168.2.105 //闆子的ip
注:
1)"m=" 行中的媒體名必須是 "video",端口為1234.
2)"a=rtpmap" 行中的編碼名稱必須是 "h264".時鐘頻率必須是 90000.
然後把腳本拖到vlcportable.exe軟體中(vlc是一個标準),就能顯示攝像頭擷取的視訊,就說明rtp傳輸沒問題,我的工作就完成了