java调用jrtplib,jrtplib的文档翻译
1 從RTPSession類開始
所有的類和函數都是jrtplib名字空間的一部分,為了簡化代碼,我們聲明我們使用的是如下的名字空間:
using namespace jrtplib;
為了使用RTP,首先要創建一個RTPSession對象.這個構造函數接受兩個參數:一個RTPRandom類的實例,一個RTPMemoryManager類的實例.現在,我們使用最簡單的默認的設置,如下:
RTPSession?session;
1.1 創建Session
調用帶有三個參數的Create函數.
參數1
RTPSessionParams類型.指定這個session的大概的選項.這個類里面的一個參數必須要設置好,否則session就會創建失敗.就是你要發送的數據的時間戳的單位,這個參數可以用一個時間段內的采樣數去除以這個時間段的長度.因此,假設我們要發送一個8000Hz的語音數據,可以用如下的代碼:
RTPSessionParams?sessionParams;
sessionParams.SetOwnTimestampUnit(1.0/8000.0);
參數2
這個參數就真的取決于你想要一起用的RTP profile.
它是一個指向RTPTransmissionParams實例的指針,并且為傳輸部分描述參數.
參數3
選擇要使用的傳輸組件,默認情況下,使用UDP通過IPV4的transmitter,并且對于這個特定的transmitter,那么參數2中的傳輸參數應該設為RTPUDPv4TransmissionParams類型的.因此,假設我們使用8000端口,我們可以使用如下的代碼:
RTPUDPv4TransmissionParams?transparams;
transparams.SetPortbase(8000);
現在我們可以調用RTPSession類的Create成員函數,代碼如下:
int?status?=?session.Create(sessionparams,&transparams);?if?(status?
{
std::cerr?<
exit(-1);
}
如果Create函數出錯,那么返回一個負值,它指出出錯了.可以用RTPGetErrorString()函數來獲得.
當session創建成功了,此時,要設置RTP和RTCP數據要發送的目的地.這是通過調用RTPSession的成員函數AddDestination來實現的.這個函數帶一個RTPAddress類型的參數,RTPAddress是一個抽象類,對于UDP通過IPV4的transmitter,真正的子類是RTPIPv4Address.假設把數據向運行在9000端口的進程發送,那么代碼如下:
uint8_t?localip[]={127,0,0,1};
RTPIPv4Address?addr(localip,9000);
status?=?session.AddDestination(addr);?if?(status?
{
std::cerr?<
exit(-1);
}
如果這個庫是用JThread支持編譯的,那么收到的數據是在后臺處理的.以下兩種情況:
A JThread支持沒有在編譯時使能
B 在session參數中指定不使用poll線程
下,必須使用RTPSession的成員函數Poll來處理到達的數據并且必要時發送RTCP數據.
現在,我們先假定我們使能了poll線程.
假設在一分鐘內,我們想要發送包含20ms(160個采樣)的silence,并且我們想要當一個從其他地方來的包被接收的時候能夠被指出來.同樣假定我們有L8數據,并且要使用負荷類型為96.首先,我們將要設定一些默認值:
session.SetDefaultPayloadType(96);
session.SetDefaultMark(false);
session.SetDefaultTimestampIncrement(160);
下一步,我們要創建包含160個silence采樣的緩沖區,并且創建一個表示20ms的RTPTime實例.我們也保存當前時間,這樣我們可以知道何時1分鐘已經走完了.
uint8_t?silencebuffer[160];
for?(int?i?=?0?;?i?
silencebuffer[i]?=?128;
RTPTime?delay(0.020);
RTPTime?starttime?=?RTPTime::CurrentTime();
下一步,是主循環.這個循環中,要發送一個包含160字節的負載數據.然后,數據處理開始進行,這個稍后闡述.最終,我們等待20ms并檢測是否60s已經過去.
bool?done?=?false;
while?(!done)
{
status?=?session.SendPacket(silencebuffer,160);
if?(status?
{
std::cerr?<
exit(-1);
}
//
//?Inspect?incoming?data?here
//
RTPTime::Wait(delay);
RTPTime?t?=?RTPTime::CurrentTime();
t?-=?starttime;
if?(t?>?RTPTime(60.0))
done?=?true;
}
關于會話參與者的信息,以及獲得包等的信息,都必須在調用成員函數BeginDataAccess和EndDataAccess之間完成.這樣可以保證后臺線程不會在你在訪問數據的時候,同時改變你的數據.我們逐個訪問會話的參與者通過GotoFirstSource和GotoNextSource成員函數.從當前選中的參與者中取得數據包,可以通過成員函數GetNextPacket,這個函數可以返回一個指向RTPPacket類的實例的指針.當你不再需要這個packet的時候,你要delete它.處理到達的數據的過程可以如下:
session.BeginDataAccess();
if?(session.GotoFirstSource())
{
do
{
RTPPacket?*packet;
while?((packet?=?session.GetNextPacket())?!=?0)
{
std::cout?<
<GetExtendedSequenceNumber()
<GetSSRC()
<
session.DeletePacket(packet);
}
}?while?(session.GotoNextSource());
}
session.EndDataAccess();
當前選中的源的信息可以通過GetCurrentSourceInfo成員函數RTPSession類的來獲取.這個函數返回一個指針指向RTPSourceData的指針,這個對象包括了所有的關于source的信息:從那個源來的sender reports,receiver reports,SDES信息等等.
當主循環結束的時候,我們發送一個BYE包來告訴其他參與者我們的分離,并且清理RTPSession類.同樣我們需要等最多10s來讓BYE包被發送出去,否則,我們只是簡單地離開會話,而沒有發送BYE包.
delay?=?RTPTime(10.0);
session.BYEDestroy(delay,"Time's?up",9);
2 錯誤碼
除非特地指定的,否則都是0或者正返回值表示成功,負值表示出錯.可以用RTPGetErrorString獲取.
3 內存管理
可以通過繼承RTPMemoryManager來寫自己的內存管理類.下面是一個簡化的實現代碼:
class?MyMemoryManager?:?public?RTPMemoryManager
{?public:
MyMemoryManager()?{?}
~MyMemoryManager()?{?}
void?*AllocateBuffer(size_t?numbytes,?int?memtype)
{????????????????return?malloc(numbytes);
}????????void?FreeBuffer(void?*p)
{
free(p);
}
};
在RTPSession類的構造函數中,可以指定想要使用這個內存管理:
MyMemoryManager?mgr;
RTPSession?session(0,?&mgr);
此時,所有的內存分配和聲明都可以通過使用mgr的AllocateBuffer和FreeBuffer來完成.
總結
以上是生活随笔為你收集整理的java调用jrtplib,jrtplib的文档翻译的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这样部署防病毒网关才妙啊!2000字详解
- 下一篇: linux 串口驱动解析之2440