Use of open-source RTP-jrtplib

Source: Internet
Author: User

Session. begindataaccess (); If (session. gotofirstsource () {do {rtppacket * packet; while (packet = session. getnextpacket ())! = 0) {cout <"got packet with extended sequence number" <packet-> getextendedsequencenumber () <"from SSRC" <packet-> getssrc () <Endl; Session. deletepacket (packet) ;}} while (Session. gotonextsource ();} session. enddataaccess ();

For the establishment of the jrtplib environment, I can refer to my previous summary. Now I will mainly talk about how to learn example under jrtplib3.71. I. sample is a simple IPv4 column that implements RTP data transmission on the local machine. 1. initialization. We know that RTP generally uses UDP protocol for data transmission. In Windows, of course, we need to use sockets that we are familiar with, so we need to initialize them first, load the socket library.

Function rtpgterrorstring (...) Inferred based on a negative number returned for an error. The unified error mechanism used by jrtplib protocol returns the standard string STD: String in C ++, indicating the error message, the portbase we specify is not an even number. (Why? I 'd like to explain it below)
2. rtpsession object settings
To use sockets, we must specify a listening port for our listening socket before using it, that is, the portbase value here. We can set this by calling the member function of rtpsession's second Worker Number rtpudpv4transmissionparams,
Transparams. setportbase (portbase );
 
In addition, we need to set the following values through the first Worker Number of rtpsession:

Sessparams. setowntimestampunit (1.0/10.0 );
// Note that we must set this value, the local timestamp unit must be set, otherwise
// RTCP Sender report info will be calculated wrong, in this case, we'll be sending
// 10 samples each second, so we'll put the timestamp unit to (1.0/10.0)
// Setting the timestamp is very important and is another important task in the RTP Session Initialization Process.
// The unit is seconds. For example, when 8 000Hz audio data is transmitted using RTP sessions, the timestamp
// The number increases by 8000 per second, so the timestamp unit should be set to 1/8000:
Sessparams. setacceptownpackets (true );
// Through this function, we can set whether to receive data packets defined by ourselves.
 
3. Data Transmission
I think when we want to establish a connection, we need to let the sender know the IP address of the host to be sent. In jrtplib, we can use the rtpsession member functions adddestination (), deletedestination () and cleardestinations. For example, the following is the Port 6000 that sends data to the local machine:
 
Unsigned long ADDR = ntohl (inet_addr ("127.0.0.1 "));
Sess. adddestination (ADDR, 6000 );
 
Of course, can we still finish this? A client,
 
Rtpipv4address ADDR (destip, destport); // destip is the clientip address, and destport is the client // port number
Status = sess. adddestination (ADDR );
Checkerror (Status );

After all the target addresses are specified, you can call the sendpacket () method of the rtpsession class to send streaming media data to all target addresses. Sendpacket () is an overload function provided by the rtpsession class. It has the following forms:
Int sendpacket (void * data, int Len)
Int sendpacket (void * data, int Len, unsigned char PT, bool mark,
Unsigned long timestampinc)
Int sendpacket (void * data, int Len, unsigned short hdrextid, void * hdrextdata,
Int numhdrextwords)
Int sendpacket (void * data, int Len, unsigned char PT, bool mark,
Unsigned long timestampinc, unsigned short hdrextid,
Void * hdrextdata, int numhdrextwords)
The most typical method of using sendpacket () is similar to the following statement. The first vertex number is the data to be sent, and the second vertex number indicates the length of the data to be sent, the following are the RTP load types, identifiers, and timestamp increments. As shown in the following figure:
Status = sess. sendpacket (void *) "1234567890", false, 10 );
Checkerror (Status );
For the same RTP Session, the load type, identifier, and timestamp increment are usually the same. jrtplib agrees to set them as the default number of sessions, this is done by calling the setdefaultpayloadtype (), setdefaultmark (), and setdefatimetimestampincrement () Methods of the rtpsession class. The advantage of setting the default number of records for RTP sessions is that it can simplify data transmission. For example, assume that the default number of records is set for RTP sessions:
Session. setdefapaypayloadtype (96); // note that the number of tokens cannot be set at will.
Session. setdefamark mark (false );
Session. setdefatimetimestampincrement (160 );
After setting the preceding values, we can send data as follows:
Status = sess. sendpacket (void *) "1234567890", 10 );
3. receive data
For the receiver of streaming media data, you must first call the polldata () method of the rtpsession class to receive the RTP or RTCP datagram sent. Because the same RTP session agrees to have multiple sources, you can call the gotofirstsource () and gotonextsource () Methods of the rtpsession class to traverse all sources, you can also use the gotofirstsourcewithdata () and gotonextsourcewithdata () Methods of the rtpsession class to traverse those sources with data. After a valid data source is obtained from the RTP session, you can call the getnextpacket () method of the rtpsession class to extract the RTP datagram from it. After the received RTP datagram is processed, remember to release it in time. The following code demonstrates how to process the received RTP datagram:

 

 

# Ifdef Win32 wsadata dat; wsastartup (makeword (2, 2), & dat); # endif // Win32 rtpsession sess; # ifdef Win32 wsacleanup (); # endif // Win32 # include "rtpsession. H "# include" rtppacket. H "# include" rtpudpv4transmitter. H "// rtpudpv4transmissionparams # include" rtp00004address. H "# include" rtpsessionparams. H "# include" rtperrors. H "Void checkerror (INT rtperr) {If (rtperr <0) {STD: cout <" error: "<rtpgterrorstring (rtperr) <STD: Endl; exit (-1 );}}

 

Jrtplib defines three receiving modes for RTP datagram, each of which specifies in detail which RTP datagram will be accepted, and which RTP datagram will be rejected. You can set the following receiving modes by calling the setreceivemode () method of the rtpsession class:
① Receivemode_all: the default receiving mode. All received RTP data packets are accepted;
② Receivemode_ignoresome except for some specific senders, all received RTP data packets will be accepted, and the list of rejected senders can call addtoignorelist (), clearignorelist (), and deletefromignorelist () method;
③ Receivemode_acceptsome except for some specific senders, all received RTP datagram data will be rejected, and the list of accepted senders can call addtoacceptlist (), clearacceptlist () and the eletefromacceptlist method.
4. Execute the program
Before executing the program, we need to know that this is a UDP-based datagram service. Our example1 is the RTP transmission implemented on the local machine, and there is only one rtpsession object, so our listening and receiving port are the same, so now we need to add portbase to us? The port to the client in the rtpsession object is the same. For example, we can set the port to 6000 above. but in two threads, we should note that the SERVERPORT and the client port must be different. This is also the main knowledge. Pay attention to and think more when using it.

 

1. set the basic parameters rtpsession m_rtpsocket; m_rtpsocket.create (m_sport); Round (1.0/25.0); m_rtpsocket.setsessionbandwidth (900.0); Round (65535); Round (0); m_rtpsocket.setdefamark mark (false ); m_rtpsocket.setdefatimetimestampincrement (10); 2. send int status = m_rtpsocket.sendpacket (pframe, wsize, 1, name, 10); 3, receive int size = 0; socket sockrtp, SOC Krtcp; struct timeval rttprev = {0, 0}, RTT, TV; fd_set fdset; bool frist = true; int Port = (crnetvideoctrl *) m_pmainclass)-> m_destport; if (Port =-1) stopthread (); rtpsession m_rtpsocket; m_rtpsocket.create (port); then (64); m_rtpsocket.getrtpsocket (& sockrtp); m_rtpsocket.getrtcpsocket (& sockrtcp ); m_pdecoder = new cvideodecode (); m_pdecoder-> dec_init (1); unsigned char * Pbuffer = new unsigned char [320*240*2]; while (! M_bclose) {TV. TV _sec = 0; TV. TV _usec = 100000; fd_zero (& fdset); fd_set (sockrtcp, & fdset); fd_set (sockrtp, & fdset); int maxsize = max (sockrtp, sockrtcp ); int selectret = select (maxsize + 1, & fdset, null, null, & TV); If (-1 = selectret | 0 = selectret) continue; /* poll for incoming data * // call this operation to obtain the data m_rtpsocket.polldata (); /* check incoming packets * // The original RTP data packet if (fd_isset (sockrtp, & fdset) {if (M_rtpsocket.gotofirstsourcewithdata () {rtppacket * pack; while (pack = m_rtpsocket.getnextpacket ())! = NULL) {If (frist) {// check whether it is a key frame if (pack-> ismarked () {If (crnetvideoctrl *) m_pmainclass) {m_pdecoder-> dec_main (pack-> getpayload (), pbuffer, pack-> getpayloadlength (), & size); (crnetvideoctrl *) m_pmainclass)-> decodevideo (pbuffer, size); trace ("client received ed IFRAME/N"); frist = false ;}} else {// decodes and displays m_pdecoder-> dec_main (pack-> getpayload (), pbuffer, pack-> getpayloadlength (), & size); (crnetvide Octrl *) m_pmainclass)-> decodevideo (pbuffer, size);} Delete pack ;}}if (fd_isset (sockrtcp, & fdset) {If (m_rtpsocket.gotofirstsource ()) {do {rtpsourcedata * srcdat; srcdat = m_rtpsocket.getcurrentsourceinfo (); If (null! = Srcdat) {RTT = srcdat-> inf_getroundtriptime (); If (RTT. TV _sec! = 0 | RTT. TV _usec! = 0) {double T; t = (double) RTT. TV _sec; t + = (double) RTT. TV _usec)/1000000.0; T * = 1000.0; // We want milliseconds; trace ("RTT: % F MS/N", (float) T); rttprev = RTT ;} if (parent-> m_cansend) {sprintf (MSG, "packet loss: % F/N", srcdat-> rr_getpacketslost (); sprintf (MSG, "Package number: % d/N ", srcdat-> rr_getextendedhighestsequencenumber (); sprintf (MSG," jitter: % d/N ", srcdat-> rr_getjitter (); reportnum = 0 ;} srcdat-> flushpackets (); // we don't need the actual data} srcdat = NULL;} while (m_rtpsocket.gotonextsource () ;}} if (m_pdecoder) delete m_pdecoder; m_pdecoder = NULL; Delete [] pbuffer; return 1l;

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.