RTP over TCP/UDP example in jrtplib
昨天写了一段rtp over tcp, 还没来得及调试,突然想起来jrtplib里会不会有现成的,进去一顿翻,靠,真有一个,🤮
https://research.edm.uhasselt.be/jori/page/Cs/JrtplibOld.html
1) 安装库文件
_install.sh
cmake -DCMAKE_INSTALL_PREFIX=./_install
make
make install
交叉编译
cmake -DCMAKE_INSTALL_PREFIX=./_install -DCMAKE_C_COMPILER=/usr/local/gcc-linaro-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=/usr/local/gcc-linaro-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++
make
make install
或者直接在根目录下的CMakeLists.txt文件首行加上
SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_C_COMPILER "arm-linux-gnueabihf-gcc") SET(CMAKE_CXX_COMPILER "arm-linux-gnueabihf-g++") SET(CMAKE_INSTALL_PREFIX "./_INSTALL")
2) rtp over tcp
jrtplib-3.11.1/tests/tcptest.cpp
#include "rtpconfig.h" #include "rtpsocketutil.h" #include "rtpsocketutilinternal.h" #include "rtpsession.h" #include "rtpsessionparams.h" #include "rtperrors.h" #include "rtpsourcedata.h" #include "rtptcpaddress.h" #include "rtptcptransmitter.h" #include "rtppacket.h" #include <string.h> #include <stdlib.h> #include <iostream> #include <vector> using namespace std; using namespace jrtplib; inline void checkerror(int rtperr) { if (rtperr < 0) { cerr << "ERROR: " << RTPGetErrorString(rtperr) << std::endl; exit(-1); } } class MyRTPSession : public RTPSession { public: MyRTPSession() : RTPSession() { } ~MyRTPSession() { } protected: void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled) { printf("SSRC %x Got packet (%d bytes) in OnValidatedRTPPacket from source 0x%04x!\n", GetLocalSSRC(), (int)rtppack->GetPayloadLength(), srcdat->GetSSRC()); DeletePacket(rtppack); *ispackethandled = true; } void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t, const void *itemdata, size_t itemlength) { char msg[1024]; memset(msg, 0, sizeof(msg)); if (itemlength >= sizeof(msg)) itemlength = sizeof(msg)-1; memcpy(msg, itemdata, itemlength); printf("SSRC %x Received SDES item (%d): %s from SSRC %x\n", GetLocalSSRC(), (int)t, msg, srcdat->GetSSRC()); } }; class MyTCPTransmitter : public RTPTCPTransmitter { public: MyTCPTransmitter(const string &name) : RTPTCPTransmitter(0), m_name(name) { } void OnSendError(SocketType sock) { cout << m_name << ": Error sending over socket " << sock << ", removing destination" << endl; DeleteDestination(RTPTCPAddress(sock)); } void OnReceiveError(SocketType sock) { cout << m_name << ": Error receiving from socket " << sock << ", removing destination" << endl; DeleteDestination(RTPTCPAddress(sock)); } private: string m_name; }; void runTest(int sock1, int sock2) { const int packSize = 1500; RTPSessionParams sessParams; MyTCPTransmitter trans1("Transmitter1"), trans2("Transmitter2"); MyRTPSession sess1, sess2; sessParams.SetProbationType(RTPSources::NoProbation); sessParams.SetOwnTimestampUnit(1.0/packSize); sessParams.SetMaximumPacketSize(packSize + 64); // some extra room for rtp header bool threadsafe = false; #ifdef RTP_SUPPORT_THREAD threadsafe = true; #endif // RTP_SUPPORT_THREAD checkerror(trans1.Init(threadsafe)); checkerror(trans2.Init(threadsafe)); checkerror(trans1.Create(65535, 0)); checkerror(trans2.Create(65535, 0)); checkerror(sess1.Create(sessParams, &trans1)); cout << "Session 1 created " << endl; checkerror(sess2.Create(sessParams, &trans2)); cout << "Session 2 created " << endl; checkerror(sess1.AddDestination(RTPTCPAddress(sock1))); checkerror(sess2.AddDestination(RTPTCPAddress(sock2))); vector<uint8_t> pack(packSize); int num = 10; for (int i = 1 ; i <= num ; i++) { printf("\nSending packet %d/%d\n",i,num); // send a packet, alternating between a large packet and a zero length one //int len = (i%2 == 0)?pack.size():0; int len = 1500; checkerror(sess1.SendPacket((void *)&pack[0],len,0,false,10)); //if (i == 10) // RTPCLOSE(sock1); // Induce an error when sending/receiving // Either the background thread or the poll function itself will // cause the OnValidatedRTPPacket and OnRTCPSDESItem functions to // be called, so in this loop there's not much left to do. sess2.BeginDataAccess(); // check incoming packets if (sess2.GotoFirstSourceWithData()) { do { RTPPacket *pack; while ((pack = sess2.GetNextPacket()) != NULL) { // You can examine the data here printf("Got packet !\n"); // we don't longer need the packet, so // we'll delete it sess2.DeletePacket(pack); } } while (sess2.GotoNextSourceWithData()); } sess2.EndDataAccess(); #ifndef RTP_SUPPORT_THREAD checkerror(sess1.Poll()); checkerror(sess2.Poll()); #endif // RTP_SUPPORT_THREAD //RTPTime::Wait(RTPTime(1,0)); } sess1.BYEDestroy(RTPTime(10,0),0,0); sess2.BYEDestroy(RTPTime(10,0),0,0); } int main(int argc, char *argv[]) { if (argc != 2) { cerr << "Usage: " << argv[0] << " portnumber" << endl; return -1; } // Create a listener socket and listen on it SocketType listener = socket(AF_INET, SOCK_STREAM, 0); if (listener == RTPSOCKERR) { cerr << "Can't create listener socket" << endl; return -1; } struct sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(atoi(argv[1])); if (bind(listener, (struct sockaddr *)&servAddr, sizeof(servAddr)) != 0) { cerr << "Can't bind listener socket" << endl; return -1; } listen(listener, 1); // Create a client socket and connect to the listener SocketType client = socket(AF_INET, SOCK_STREAM, 0); if (client == RTPSOCKERR) { cerr << "Can't create client socket" << endl; return -1; } servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(client, (struct sockaddr *)&servAddr, sizeof(servAddr)) != 0) { cerr << "Can't connect to the listener socket" << endl; return -1; } SocketType server = accept(listener, 0, 0); if (server == RTPSOCKERR) { cerr << "Can't accept incoming connection" << endl; return -1; } RTPCLOSE(listener); cout << "Got connected socket pair" << endl; runTest(server, client); cout << "Done." << endl; RTPCLOSE(server); RTPCLOSE(client); return 0; }
build.sh
export LD_LIBRARY_PATH=$(pwd)/_install/lib:$LD_LIBRARY_PATH rm ./example1 ./tcptest g++ example1.cpp -I./_install/include -I./_install/include/jrtplib3 -L./_install/lib -g -o example1 -lpthread -ljrtp -lm g++ tcptest.cpp -I./_install/include -I./_install/include/jrtplib3 -L./_install/lib -g -o tcptest -lpthread -ljrtp -lm
dong@ubuntu:~/jrtplib_example$ ./tcptest 15000
Got connected socket pair
Session 1 created
Session 2 created
Sending packet 1/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 2/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 3/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 4/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 5/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 6/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 7/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 8/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 9/10
SSRC fed93305 Got packet (1500 bytes) in OnValidatedRTPPacket from source 0xd244e47a!
Sending packet 10/10
Done.
dong@ubuntu:~/jrtplib_example$
将jrtplib-3.11.1/test2/tcptest.cpp拆分成发送和接收
tcptest1.cpp
#include "rtpconfig.h" #include "rtpsocketutil.h" #include "rtpsocketutilinternal.h" #include "rtpsession.h" #include "rtpsessionparams.h" #include "rtperrors.h" #include "rtpsourcedata.h" #include "rtptcpaddress.h" #include "rtptcptransmitter.h" #include "rtppacket.h" #include <string.h> #include <stdlib.h> #include <iostream> #include <vector> using namespace jrtplib; int main() { RTPSession session; RTPAbortDescriptors m_descriptors; RTPSessionParams sessionparams; sessionparams.SetAcceptOwnPackets(true); sessionparams.SetOwnTimestampUnit(1.0/10.0); m_descriptors.Init(); RTPTCPTransmissionParams transparams; transparams.SetCreatedAbortDescriptors(&m_descriptors); int status = session.Create(sessionparams,&transparams,RTPTransmitter::TCPProto); if (status < 0) { //std::cerr << "[session.Create]" << QString::fromStdString(RTPGetErrorString(status)); std::cout << "ERROR: " << RTPGetErrorString(status) << std::endl; return -1; } //初始化socket SocketType sockSrv = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1"); //addrSrv.sin_addr.s_addr = inet_addr("172.16.23.240"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(15000); //连接服务器 connect( sockSrv, (struct sockaddr*)&addrSrv, sizeof(struct sockaddr)); RTPTCPAddress addr(sockSrv); status = session.AddDestination(addr); if (status < 0) { //std::cerr << "session.AddDestination" << QString::fromStdString(RTPGetErrorString(status)); std::cout << "ERROR: " << RTPGetErrorString(status) << std::endl; return -1; } session.SetDefaultPayloadType(96); session.SetDefaultMark(false); session.SetDefaultTimestampIncrement(160); //发送数据 std::vector<uint8_t> pack(1500); int len = 1200; int num = 10; for (int i = 1 ; i <= num ; i++) { session.SendPacket((void *)&pack[0],len,0,false,10); //session.SendPacket((void *)&pack[0],len,0,false,10); //RTPTime delay(0.020); RTPTime::Wait(RTPTime(1,0)); } //session.BYEDestroy(delay,"Client End",9); session.BYEDestroy(RTPTime(10,0),0,0); //RTPCLOSE(sock1); RTPCLOSE(sockSrv); return 0; }
tcptest2.cpp
#include "rtpconfig.h" #include "rtpsocketutil.h" #include "rtpsocketutilinternal.h" #include "rtpsession.h" #include "rtpsessionparams.h" #include "rtperrors.h" #include "rtpsourcedata.h" #include "rtptcpaddress.h" #include "rtptcptransmitter.h" #include "rtppacket.h" #include <string.h> #include <stdlib.h> #include <iostream> #include <vector> using namespace std; using namespace jrtplib; inline void checkerror(int rtperr) { if (rtperr < 0) { cerr << "ERROR: " << RTPGetErrorString(rtperr) << std::endl; exit(-1); } } /* class MyRTPSession : public RTPSession { public: MyRTPSession() : RTPSession() { } ~MyRTPSession() { } protected: void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled) { printf("SSRC %x Got packet (%d bytes) in OnValidatedRTPPacket from source 0x%04x!\n", GetLocalSSRC(), (int)rtppack->GetPayloadLength(), srcdat->GetSSRC()); DeletePacket(rtppack); *ispackethandled = true; } void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t, const void *itemdata, size_t itemlength) { char msg[1024]; memset(msg, 0, sizeof(msg)); if (itemlength >= sizeof(msg)) itemlength = sizeof(msg)-1; memcpy(msg, itemdata, itemlength); printf("SSRC %x Received SDES item (%d): %s from SSRC %x\n", GetLocalSSRC(), (int)t, msg, srcdat->GetSSRC()); } }; class MyTCPTransmitter : public RTPTCPTransmitter { public: MyTCPTransmitter(const string &name) : RTPTCPTransmitter(0), m_name(name) { } void OnSendError(SocketType sock) { cout << m_name << ": Error sending over socket " << sock << ", removing destination" << endl; DeleteDestination(RTPTCPAddress(sock)); } void OnReceiveError(SocketType sock) { cout << m_name << ": Error receiving from socket " << sock << ", removing destination" << endl; DeleteDestination(RTPTCPAddress(sock)); } private: string m_name; }; */ void runTest(/*int sock1, */int sock2) { const int packSize = 1500; RTPSessionParams sessParams; //MyTCPTransmitter trans1("Transmitter1"), trans2("Transmitter2"); RTPTCPTransmitter trans2 = RTPTCPTransmitter(0); //MyRTPSession sess1, sess2; RTPSession sess2; sessParams.SetProbationType(RTPSources::NoProbation); sessParams.SetOwnTimestampUnit(1.0/packSize); sessParams.SetMaximumPacketSize(packSize + 64); // some extra room for rtp header bool threadsafe = false; #ifdef RTP_SUPPORT_THREAD threadsafe = true; #endif // RTP_SUPPORT_THREAD //checkerror(trans1.Init(threadsafe)); checkerror(trans2.Init(threadsafe)); //checkerror(trans1.Create(65535, 0)); checkerror(trans2.Create(65535, 0)); //checkerror(sess1.Create(sessParams, &trans1)); //cout << "Session 1 created " << endl; checkerror(sess2.Create(sessParams, &trans2)); cout << "Session 2 created " << endl; //checkerror(sess1.AddDestination(RTPTCPAddress(sock1))); checkerror(sess2.AddDestination(RTPTCPAddress(sock2))); vector<uint8_t> pack(packSize); //int num = 10; //for (int i = 1 ; i <= num ; i++) while(1) { //printf("\nSending packet %d/%d\n",i,num); // send a packet, alternating between a large packet and a zero length one //int len = (i%2 == 0)?pack.size():0; //int len = 1500; //checkerror(sess1.SendPacket((void *)&pack[0],len,0,false,10)); //if (i == 10) // RTPCLOSE(sock1); // Induce an error when sending/receiving // Either the background thread or the poll function itself will // cause the OnValidatedRTPPacket and OnRTCPSDESItem functions to // be called, so in this loop there's not much left to do. sess2.BeginDataAccess(); // check incoming packets if (sess2.GotoFirstSourceWithData()) { do { RTPPacket *pack; while ((pack = sess2.GetNextPacket()) != NULL) { // You can examine the data here printf("Got packet !\n"); // we don't longer need the packet, so // we'll delete it sess2.DeletePacket(pack); } } while (sess2.GotoNextSourceWithData()); } sess2.EndDataAccess(); #ifndef RTP_SUPPORT_THREAD //checkerror(sess1.Poll()); checkerror(sess2.Poll()); #endif // RTP_SUPPORT_THREAD //RTPTime::Wait(RTPTime(1,0)); //you need add timeout } //sess1.BYEDestroy(RTPTime(10,0),0,0); sess2.BYEDestroy(RTPTime(10,0),0,0); } int main(int argc, char *argv[]) { // Create a listener socket and listen on it SocketType listener = socket(AF_INET, SOCK_STREAM, 0); if (listener == RTPSOCKERR) { cerr << "Can't create listener socket" << endl; return -1; } struct sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(15000); if (bind(listener, (struct sockaddr *)&servAddr, sizeof(servAddr)) != 0) { cerr << "Can't bind listener socket" << endl; return -1; } listen(listener, 1); // Create a client socket and connect to the listener /* SocketType client = socket(AF_INET, SOCK_STREAM, 0); if (client == RTPSOCKERR) { cerr << "Can't create client socket" << endl; return -1; } servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(client, (struct sockaddr *)&servAddr, sizeof(servAddr)) != 0) { cerr << "Can't connect to the listener socket" << endl; return -1; } */ SocketType server = accept(listener, 0, 0); if (server == RTPSOCKERR) { cerr << "Can't accept incoming connection" << endl; return -1; } RTPCLOSE(listener); cout << "Got connected socket pair" << endl; runTest(server); cout << "Done." << endl; RTPCLOSE(server); //RTPCLOSE(client); return 0; }
build.sh
export LD_LIBRARY_PATH=$(pwd)/_install/lib:$LD_LIBRARY_PATH rm ./tcptest ./tcptest1 ./tcptest2 g++ tcptest.cpp -I./_install/include -I./_install/include/jrtplib3 -L./_install/lib -g -o tcptest -lpthread -ljrtp -lm g++ tcptest1.cpp -I./_install/include -I./_install/include/jrtplib3 -L./_install/lib -g -o tcptest1 -lpthread -ljrtp -lm g++ tcptest2.cpp -I./_install/include -I./_install/include/jrtplib3 -L./_install/lib -g -o tcptest2 -lpthread -ljrtp -lm
tcp accept非阻塞模式需要改下socket配置
SocketType listener = socket(PF_INET, SOCK_STREAM, 0);
int flags = fcntl(listener, F_GETFL, 0);
fcntl(listener, F_SETFL, flags | O_NONBLOCK);
要用这个代码就自己清理吧,我就是随手改的,也懒得整理了。
3)rtp over udp
jrtplib-3.11.1/example/example1.cpp
_build.sh
export LD_LIBRARY_PATH=$(pwd)/_install/lib:$LD_LIBRARY_PATH
rm ./test
g++ example1.cpp -I./_install/include/jrtplib3 -L./_install/lib -g -o test -ljrtp
dong@ubuntu:~/sip/jrtplib/example$ ls
_build.sh example1.cpp _install test
dong@ubuntu:~/sip/jrtplib/example$ ./test
Using version 3.11.1
Enter local portbase:
4000
Enter the destination IP address
127.0.0.1
Enter the destination port
4000
Number of packets you wish to be sent:
10
Sending packet 1/10
Sending packet 2/10
Got packet !
Sending packet 3/10
Got packet !
Sending packet 4/10
Got packet !
Sending packet 5/10
Got packet !
Sending packet 6/10
Got packet !
Sending packet 7/10
Got packet !
Sending packet 8/10
Got packet !
Sending packet 9/10
Got packet !
Sending packet 10/10
Got packet !
dong@ubuntu:~/sip/jrtplib/example$
将jrtplib-3.11.1/examples/example1.cpp拆分成发送和接收
send.cpp
/*
Here's a small IPv4 example: it asks for a portbase and a destination and
starts sending packets to that destination.
*/
#include "rtpsession.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtplibraryversion.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace jrtplib;
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
int main(void)
{
RTPSession sess;
uint16_t portbase = 3000;
uint16_t destport = 4000;
uint32_t destip;
int status,i;
int num = 10;
destip = inet_addr("127.0.0.1");
if (destip == INADDR_NONE)
{
std::cerr << "Bad IP address specified" << std::endl;
return -1;
}
destip = ntohl(destip);
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
status = sess.Create(sessparams,&transparams);
checkerror(status);
RTPIPv4Address addr(destip,destport);
status = sess.AddDestination(addr);
checkerror(status);
for (i = 1 ; i <= num ; i++)
{
printf("\nSending packet %d/%d\n",i,num);
// send the packet
status = sess.SendPacket((void *)"1234567890",10,0,false,10);
checkerror(status);
RTPTime::Wait(RTPTime(1,0));
}
sess.BYEDestroy(RTPTime(10,0),0,0);
return 0;
}
recv.cpp
/*
Here's a small IPv4 example: it asks for a portbase and a destination and
starts sending packets to that destination.
*/
#include "rtpsession.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtplibraryversion.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace jrtplib;
void checkerror(int rtperr)
{
if (rtperr < 0)
{
std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
exit(-1);
}
}
int main(void)
{
RTPSession sess;
uint16_t portbase = 4000;
int status;
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
status = sess.Create(sessparams,&transparams);
checkerror(status);
while(1)
{
sess.BeginDataAccess();
// check incoming packets
if (sess.GotoFirstSourceWithData())
{
do
{
RTPPacket *pack;
while ((pack = sess.GetNextPacket()) != NULL)
{
// You can examine the data here
printf("Got packet !\n");
// we don't longer need the packet, so
// we'll delete it
sess.DeletePacket(pack);
}
} while (sess.GotoNextSourceWithData());
}
sess.EndDataAccess();
#ifndef RTP_SUPPORT_THREAD
status = sess.Poll();
checkerror(status);
#endif // RTP_SUPPORT_THREAD
}
sess.BYEDestroy(RTPTime(10,0),0,0);
return 0;
}
_build.sh
export LD_LIBRARY_PATH=$(pwd)/_install/lib:$LD_LIBRARY_PATH
rm ./send ./recv
g++ send.cpp -I./_install/include/jrtplib3 -L./_install/lib -g -o send -ljrtp
g++ recv.cpp -I./_install/include/jrtplib3 -L./_install/lib -g -o recv -ljrtp
4)jrtplib的rtp大小端问题
README.md里有一句话
- `RTP_BIG_ENDIAN`: If set, assume big-endian byte ordering.
CMakeLists.txt里有一段代码
if (CMAKE_CROSSCOMPILING)
option (JRTPLIB_USE_BIGENDIAN "Target platform is big endian" ON)
if (JRTPLIB_USE_BIGENDIAN)
set(RTP_ENDIAN "#define RTP_BIG_ENDIAN")
else (JRTPLIB_USE_BIGENDIAN)
set(RTP_ENDIAN "// Little endian system")
endif (JRTPLIB_USE_BIGENDIAN)
else (CMAKE_CROSSCOMPILING)
test_big_endian(JRTPLIB_BIGENDIAN)
if (JRTPLIB_BIGENDIAN)
set(RTP_ENDIAN "#define RTP_BIG_ENDIAN")
else (JRTPLIB_BIGENDIAN)
set(RTP_ENDIAN "// Little endian system")
endif (JRTPLIB_BIGENDIAN)
endif (CMAKE_CROSSCOMPILING)
从以上信息可以确认默认是大端模式
注释掉jrtplib-3.11.1/src/rtpconfig.h.in的56行就是小端模式
//${RTP_ENDIAN}
5) ERR_RTP_SESSION_CANTGETLOGINNAME
如果因为login不能创建会话,rtpsession.cpp文件的1593行直接填个root
if (!gotlogin) { //char *logname = getenv("LOGNAME"); const char *logname = "root"; if (logname == 0) return ERR_RTP_SESSION_CANTGETLOGINNAME; strncpy((char *)buffer,logname,*bufferlength); }
参考文献
jrtplib-3.11.1/doc/jrtplib.h
jrtplib-3.11.1/tests/tcptest.cpp
jrtplib-3.11.1/example/example1.cpp