linux下基于jrtplib庫的實時傳送實現

linux?下基于jrtplib庫的實時傳送實現
一、RTP?是進行實時流媒體傳輸的標準協議和關鍵技術
?實時傳輸協議(Real-time?Transport?Protocol,PRT)是在?Internet?上處理多媒體數據流的一種網絡協議,利用它能夠在一對一(unicast,單播)或者一對多(multicast,多播)的網絡環境中實現傳流媒體數據的實時傳輸。RTP?通常使用?UDP?來進行多媒體數據的傳輸,但如果需要的話可以使用?TCP?或者?ATM?等其它協議。
?協議分析?:每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,其中頭部前?12?個字節的含義是固定的,而負載則可以是音頻或者視頻數據。

??????RTP?是目前解決流媒體實時傳輸問題的最好辦法,要在?Linux?平臺上進行實時傳送編程,可以考慮使用一些開放源代碼的?RTP?庫,如?LIBRTP、JRTPLIB?等。JRTPLIB?是一個面向對象的?RTP?庫,它完全遵循?RFC?1889?設計,在很多場合下是一個非常不錯的選擇。JRTPLIB?是一個用?C++?語言實現的?RTP?庫,這個庫使用socket?機制實現網絡通訊?因此可以運行在?Windows、Linux、FreeBSD、Solaris、Unix和VxWorks?等多種操作系統上。
二、JRTPLIB?庫的使用方法及程序實現
?(1)JRTPLIB??函數?的使用
?a、在使用?JRTPLIB?進行實時流媒體數據傳輸之前,首先應該生成?RTPSession?類的一個實例來表示此次?RTP?會話,然后調用?Create()?方法來對其進行初始化操作。RTPSession?類的?Create()?方法只有一個參數,用來指明此次?RTP?會話所采用的端口號。
?RTPSession?sess;??sess.Create(5000);?

?b、設置恰當的時戳單元,是?RTP?會話初始化過程所要進行的另外一項重要工作,這是通過調用?RTPSession?類的?SetTimestampUnit()?方法來實現的,該方法同樣也只有一個參數,表示的是以秒為單元的時戳單元。
?sess.SetTimestampUnit(1.0/8000.0);

?c、當?RTP?會話成功建立起來之后,接下去就可以開始進行流媒體數據的實時傳輸了。首先需要設置好數據發送的目標地址,RTP?協議允許同一會話存在多個目標地址,這可以通過調用?RTPSession?類的?AddDestination()、DeleteDestination()?和?ClearDestinations()?方法來完成。例如,下面的語句表示的是讓?RTP?會話將數據發送到本地主機的?6000?端口:?

?unsigned?long?addr?=?ntohl(inet_addr("127.0.0.1"));?
?sess.AddDestination(addr,?6000);
?
?d、目標地址全部指定之后,接著就可以調用?RTPSession?類的?SendPacket()?方法,向所有的目標地址發送流媒體數據。SendPacket()?是?RTPSession?類提供的一個重載函數
對于同一個?RTP?會話來講,負載類型、標識和時戳增量通常來講都是相同的,JRTPLIB?允許將它們設置為會話的默認參數,這是通過調用?RTPSession?類的?SetDefaultPayloadType()、SetDefaultMark()?和?SetDefaultTimeStampIncrement()?方法來完成的。為?RTP?會話設置這些默認參數的好處是可以簡化數據的發送,例如,如果為?RTP?會話設置了默認參數:?

?sess.SetDefaultPayloadType(0);
??sess.SetDefaultMark(false);??
?sess.SetDefaultTimeStampIncrement(10);
?


之后在進行數據發送時只需指明要發送的數據及其長度就可以了:?

?sess.SendPacket(buffer,?5);?


?e、對于流媒體數據的接收端,首先需要調用?RTPSession?類的?PollData()?方法來接收發送過來的?RTP?或者?RTCP?數據報。由于同一個?RTP?會話中允許有多個參與者(源),你既可以通過調用?RTPSession?類的?GotoFirstSource()?和?GotoNextSource()?方法來遍歷所有的源,也可以通過調用?RTPSession?類的?GotoFirstSourceWithData()?和?GotoNextSourceWithData()?方法來遍歷那些攜帶有數據的源。在從?RTP?會話中檢測出有效的數據源之后,接下去就可以調用?RTPSession?類的?GetNextPacket()?方法從中抽取?RTP?數據報,當接收到的?RTP?數據報處理完之后,一定要記得及時釋放。

JRTPLIB?為?RTP?數據報定義了三種接收模式,其中每種接收模式都具體規定了哪些到達的?RTP?數據報將會被接受,而哪些到達的?RTP?數據報將會被拒絕。通過調用?RTPSession?類的?SetReceiveMode()?方法可以設置下列這些接收模式:?
??RECEIVEMODE_ALL  缺省的接收模式,所有到達的?RTP?數據報都將被接受;?
??RECEIVEMODE_IGNORESOME  除了某些特定的發送者之外,所有到達的?RTP?數據報都將被接受,而被拒絕的發送者列表可以通過調用?AddToIgnoreList()、DeleteFromIgnoreList()?和?ClearIgnoreList()?方法來進行設置;?
??RECEIVEMODE_ACCEPTSOME  除了某些特定的發送者之外,所有到達的?RTP?數據報都將被拒絕,而被接受的發送者列表可以通過調用?AddToAcceptList?()、DeleteFromAcceptList?和?ClearAcceptList?()?方法來進行設置。?下面是采用第三種接收模式的程序示例。
?if?(sess.GotoFirstSourceWithData())?{???
??do?{???
???sess.AddToAcceptList(remoteIP,?allports,portbase);
??????????sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME);
?
????RTPPacket?*pack;?????????
????pack?=?sess.GetNextPacket();????????????//?處理接收到的數據????
????delete?pack;???}?
??while?(sess.GotoNextSourceWithData());?
??}


??(2)程序流程圖
發送:獲得接收端的?IP?地址和端口號????????創建?RTP?會話????????指定?RTP?數據接收端?設置?RTP?會話默認參數???發送流媒體數據
接收:獲得用戶指定的端口號??創建RTP會話??設置接收模式??接受RTP數據??檢索RTP數據源??獲取RTP數據報??刪除RTP數據報


三、環境搭建及編譯方法
(1)Toolchain的安裝
?首先找到xscale-arm-toolchain.tgz文件,假設該文件包放在/tmp/下
?#cd?/
?#tar?-zxvf?/tmp/xscale-arm-toolchain.tgz
?再設置環境變量
?#export?PATH=/usr/local/arm-linux/bin:$PATH
?最后檢查一下交叉編譯工具是否安裝成功
?#arm-linux-g++?--version
?看是否顯示arm-linux-g++的版本,如有則安裝成功。
(2)JRTPLIB?庫的交叉編譯及安裝
?首先從?JRTPLIB?的網站(http://lumumba.luc.ac.be/jori/jrtplib/jrtplib.htmll)?下載最新的源碼包,此處使用的是jrtplib-2.8.tar,假設下載后的源碼包放在/tmp下,執?行下面的命令對其解壓縮:
?#cd?/tmp
?#tar?-zxvf?jrtplib-2.8.tar
?然后要對jrtplib進行配置和編譯
?#cd?jrtplib-2.8
?#./configure?CC=arm-linux-g++?cross-compile=yes
?修改Makefile文件
?將鏈接命令ld?和ar改為arm-linux-ld和?arm-linux-ar
?#make
?最后再執行如下命令就可以完成?JRTPLIB?的安裝:
?#make?install
(3)程序編譯
?a、配置編譯環境
?可以用export來配置,也可以用編寫Makefile的方法。這里采用Makefile。
?編寫Makefile&:
INCL?=?-I/usr/local/include
CFLAGS?=?-pipe?-O2?-fno-strength-reduce
LFLAGS?=?/usr/local/lib/libjrtp.a?-L/usr/X11R6/lib
LIBS?=?-LX11?-LXext?/usr/local/lib/libjrtp.a
CC?=?arm-linux-g++

main:main.o
?$(CC)?$(LFLAGS)?$(INCL)?-o?main?main.o?$(LIBS)
main.o:main.cpp

clean:
?rm?-f?main
?rm?-f?*.o
?
.SUFFIXES:.cpp
.cpp.o:
?$(CC)?-c?$(CFLAGS)?$(INCL)?-o?$@?$<?????????/*??$@表示目標的完整名字??????*/
??????????/*?$<表示第一個依賴文件的名字?*/
?b、編譯
?假設發送和接收程序分別放在/tmp/send和/tmp/receive目錄下
?#cd?/tmp/send
?#make
?#cd?/tmp/receive
?#make

四、易出錯誤及注意問題
?1、找不到一些標準的最?基本的一些頭文件。
??主要是因為Toolchain路徑沒安裝對,要?嚴格按照步驟安裝。
?2、找不到使用的jrtplib庫中的一些頭文件。
??在?jrtplib的安裝目錄下,include路徑下不能再有別的目錄。
?3、recieve函數接收數據包不能正確提出所要數據。
??由于每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,若使用getrawdata()是返回整個數據包的數據,包含傳輸媒體的類型、格式、序列號、時間戳以及是否有附加數據等信息。getpayload()函數是返回所發送的數據。兩者一定要分清。
?4、設置RECEIVEMODE_ACCEPTSOME  接收模式后,運行程序接收端不能接包。
??IP地址格式出了問題。iner_addr()與ntohl()函數要用對,否則參數傳不進去,接受列表中無值,當然接收不了數據包。
?5、編譯通過,但測試時接收端不能接收到數據。
??可能是接收機防火墻未關閉。運行:
??#iptables?-F
??也可能是IP地址沒有設置好。運行:
??#ifocnfig?eth0??*.*.*.*??netmask?*.*.*.*
?6、使用jrtolib庫時,在程序中include?后最好加上庫所在的路徑。
五、程序

send:

#include?<stdio.h>
#include?<string.h>
#include?"rtpsession.h"

//?錯誤處理函數
void?checkerror(int?err)
{
??if?(err?<?0)?{
????char*?errstr?=?RTPGetErrorString(err);
????printf("Error:%s\\n",?errstr);
????exit(-1);
??}
}

int?main(int?argc,?char**?argv)
{
??RTPSession?sess;
??unsigned?long?destip;
??int?destport;
??int?portbase?=?6000;
??int?status,?index;
??char?buffer[128];

??if?(argc?!=?3)?{
????printf("Usage:?./sender?destip?destport\\n");
????return?-1;
??}

??//?獲得接收端的IP地址和端口號
??destip?=?inet_addr(argv[1]);
??if?(destip?==?INADDR_NONE)?{
????printf("Bad?IP?address?specified.\\n");
????return?-1;
??}
??destip?=?ntohl(destip);
??destport?=?atoi(argv[2]);

??//?創建RTP會話
??status?=?sess.Create(portbase);
??checkerror(status);

??//?指定RTP數據接收端
??status?=?sess.AddDestination(destip,?destport);
??checkerror(status);

??//?設置RTP會話默認參數
??sess.SetDefaultPayloadType(0);
??sess.SetDefaultMark(false);
??sess.SetDefaultTimeStampIncrement(10);

??//?發送流媒體數據
??index?=?1;
??do?{
????sprintf(buffer,?"%d:?RTP?packet",?index?++);
????sess.SendPacket(buffer,?strlen(buffer));
????printf("Send?packet?!\\n");
??}?while(1);

??return?0;
}






receive:

#include?<stdio.h>
#include?"rtpsession.h"
#include?"rtppacket.h"

//?錯誤處理函數
void?checkerror(int?err)
{
??if?(err?<?0)?{
????char*?errstr?=?RTPGetErrorString(err);
????printf("Error:%s\\n",?errstr);
????exit(-1);
??}
}

int?main(int?argc,?char**?argv)
{
??RTPSession?sess;
??int?localport,portbase;
??int?status;
??unsigned?long?remoteIP;
??if?(argc?!=?4)?{
????printf("Usage:?./sender?localport\\n");
????return?-1;
??}

???//?獲得用戶指定的端口號
???
??remoteIP?=?inet_addr(argv[1]);
??localport?=?atoi(argv[2]);
??portbase?=?atoi(argv[3]);
??//?創建RTP會話
??status?=?sess.Create(localport);
??checkerror(status);
??
??//RTPHeader?*rtphdr;
??unsigned?long?timestamp1;
??unsigned?char?*?RawData;
??unsigned?char?temp[30];
??int?lengh?,i;
??bool?allports?=?1;
??
??sess.AddToAcceptList(remoteIP,?allports,portbase);
??
?????do?{
?//設置接收模式
????????sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME);
???sess.AddToAcceptList(remoteIP,?allports,portbase);

????//?接受RTP數據
????status?=?sess.PollData();

????
?//?檢索RTP數據源
????if?(sess.GotoFirstSourceWithData())?{
??????do?{
????????
????????RTPPacket*?packet;
????????//?獲取RTP數據報
????????while?((packet?=?sess.GetNextPacket())?!=?NULL)?{
??????????printf("Got?packet?!\n");

???timestamp1?=?packet->GetTimeStamp();
???lengh=packet->GetPayloadLength();
???RawData=packet->GetPayload();
???
???for(i=0;i<lengh;i++){
??????temp[i]=RawData[i];
??printf("%c",temp[i]);
???}
???temp[i]='\0';
???printf("??timestamp:?%d?lengh=%d?data:%s\n",timestamp1,lengh,&temp);
??????????//?刪除RTP數據報
???
??????????delete?packet;
????????}
??????}?while?(sess.GotoNextSourceWithData());
????}
??}?while(1);

??return?0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254899.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254899.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254899.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[BZOJ2326] [HNOI2011] 數學作業 (矩陣乘法)

Description Input Output Sample Input Sample Output HINT Source Solution 遞推式長這樣&#xff1a;$f[n]f[n-1]*10^kn$ 對于每一段位數個數相同的$n$&#xff08;如$10\sim99,100\sim999,23333\sim66666,1018701389\sim2147483647$&#xff09;&#xff0c;$k$是個定值 然…

HALCON示例程序texture.hdev檢測樹木

小哥哥小姐姐覺得有用點個贊唄&#xff01; HALCON示例程序texture.hdev檢測樹木 示例程序源碼&#xff08;加注釋&#xff09; 關于顯示類函數解釋 dev_close_window () Interactive : 0 dev_close_window () read_image (MreutHill, ‘mreut_y’) get_image_size (MreutH…

1、python基礎速成

基礎模塊 def prt(age,name):#函數定義 print("%s is %d 年齡 old"%(name,age)) if __name__"__main__":#程序入口 print("Hello World") prt(45,"gaici") 獲取輸入&#xff1a;使用input()函數 nameinput("you name &#x…

老男孩博客園楊海潮MySQL--MySQL機構邏輯2

轉載于:https://blog.51cto.com/yanfeilai528/2103403

法國標致雪鐵龍汽車公司采用通快碟片激光器進行焊接

發布日期&#xff1a;2011-10-14 來源&#xff1a;光電新聞網 發布人&#xff1a;星之球科技 摘要&#xff1a;3月11日消息&#xff0c;十一個碟片激光器&#xff08;disk laser&#xff09;將安裝在標致雪鐵龍集團的工廠&#xff0c;這家法國汽車制造商準備使用4千瓦的激光器…

h.264 rtp打包

(2011-05-27 08:44:13) 轉載標簽&#xff1a; 雜談 payload,H.264 RTP payload 格式 on 2011-2-18 in 博文摘選 | 0 Comment 1. 網絡抽象層單元類型 (NALU) NALU 頭由一個字節組成, 它的語法如下: --------------- |0|1|2|3|4|5|6|7| -------- |F|NRI| Type | --------------…

jquery live hover綁定方法

$(".select_item span").live({mouseenter:function(){$(this).addClass("hover");},mouseleave:function(){$(this).removeClass("hover");} }); 注意&#xff1a;jquery1.9以上版本不支持live&#xff0c;新方法為on 轉載于:https://www.cnblo…

HALCON示例程序vessel.hdev血管的分割與測量

小哥哥小姐姐覺得有用點個贊唄&#xff01; HALCON示例程序vessel.hdev血管的分割與測量 示例程序源碼&#xff08;加注釋&#xff09; 關于顯示類函數解釋 dev_update_window (‘off’) dev_close_window () dev_open_window (0, 0, 512, 512, ‘black’, WindowID) set_d…

電子凸輪

CAM功能是按照一種人為預先設定的曲線關系(可以在線修改,對SEW的變頻/伺服控制器而言)來運動的控制應用。 100%速度前饋的位置控制這個觀點偶不敢茍同.典型的一些應用。比如:全自動包裝機械上,移動鋸,其實大家說的電子齒輪&#xff0c;指的就是一種可以調節主從速度比的同步應用…

浙南聯合訓練賽20180414

這次題目的代碼都不長&#xff0c;CF的一貫風格 A - Game CodeForces - 513A Two players play a simple game. Each player is provided with a box with balls. First players box contains exactly n1 balls and second players box contains exactly n2balls. In one move…

原生JS實現蘋果菜單

今天分享下用原生JS實現蘋果菜單效果&#xff0c;這個效果的重點有以下幾點 圖標中心點到鼠標的距離的算法 利用比例計算圖標的寬度 代碼地址&#xff1a;https://github.com/peng666/blogs/blob/gh-pages/menus/index.html 在線測試地址&#xff1a;http://peng666.github.io/…

Gym 100090D Insomnia

從 n 變到 1&#xff0c;有多少種方案&#xff1f; 打表記憶化。 1 #include <bits/stdc.h>2 3 using namespace std;4 5 int n;6 int dp[1000005];7 int dfs(int n) {8 if(n1)9 return 1; 10 if(dp[n]>0) 11 return dp[n]; 12 int cnt0;…

halcon rectangle1_domain縮減圖像域為矩形

目錄rectangle1_domain&#xff08;算子&#xff09;描述參數rectangle1_domain&#xff08;算子&#xff09; rectangle1_domain - 將圖像的域縮小為矩形。 rectangle1_domain&#xff08;Image&#xff1a;ImageReduced&#xff1a;Row1&#xff0c;Column1&#xff0c;Row…

PC+運動控制卡的控制方案

PC運動控制卡的控制方案&#xff1a; 采用PC&#xff0b;運動控制卡作為上位控制可充分利用計算機資源&#xff0c;用于運動過程、運動軌跡都比較復雜&#xff0c;且柔性比較強的機器和設備。從用戶使用的角度來看&#xff0c;基于PC機的運動控制卡主要是硬件接口&#xff08;輸…

IP/TCP/UDP/RTP/RTCP 包結構圖

IP 包頭結構: TCP 包頭結構: UDP 包頭結構: RTP 包頭結構: RTCP 包頭結構:

你可能不知道的java、python、JavaScript以及jquary循環語句的區別

一.概述 java循環語句分為四種形式&#xff0c;分別是 while, do/while, for, foreach&#xff1b; python中循環語句有兩種&#xff0c;while&#xff0c;for&#xff1b; JavaScript中循環語句有四種&#xff0c;while&#xff0c;do/while&#xff0c;for&#xff0c;for/in…

webservices系列(二)——JAX-WS文件上傳下載

新建ImgData類&#xff0c;存放文件javabean DataHandler&#xff1a;使用這個類型存放文件 XmlRootElement(name"ImaData") XmlAccessorType(XmlAccessType.FIELD) public class ImgData {private Integer id;XmlMimeType("application/octet-stream")pri…

halcon sobel邊緣檢測sobel_amp

目錄sobel_amp&#xff08;算子&#xff09;描述參數sobel_amp&#xff08;算子&#xff09; sobel_amp - 使用Sobel算子檢測邊緣&#xff08;幅度&#xff09;。 sobel_amp&#xff08;圖片&#xff1a;邊緣圖像&#xff1a;濾波器方式&#xff0c;掩膜大小:) 描述 sobel_…

es中的一些知識點記錄

1. forcemerge接口 強制段合并&#xff0c;設置為1時&#xff0c;是期望最終只有1個索引段。但實際情況是&#xff0c;合并的結果是段的總數會減少&#xff0c;但仍大于1&#xff0c;可以多次執行強制合并的命令。 設置的的目標值越小。合并消耗的時間會越久。 curl -XPOST htt…

用live555和ffplay搭建流媒體環境

用live555和ffplay搭建流媒體環境 http://bbs.chinavideo.org/viewthread.php?tid12166