This example demonstrates how to use the jrtplib library to encapsulate the RTP protocol in Linux. This routine can be used as a basic routine for streaming media transmission.
Only the source code is provided here (these can be found in the official jrtplib files)
Sender:
/*
* Sending Program (for Windows and Linux)
* For IPv4-based transmission routines, a port number and destination address must be provided.
* Reference: http://blog.csdn.net/ipromiseu/article/details/4531656
*/
# Include "rtpsession. H" // defines some rtpsession implementations
# Include "rtppacket. H" // defines rtppacket packets
# Include "rtpudpv4transmitter. H" // defines the second parameter class of rtpsession
# Include "rtp00004address. H" // defines rtp00004address
# Include "rtpsessionparams. H" // defines the first parameter class of rtpsession.
# Include "rtperrors. H" // defines the error message in RTP.
# Ifndef Win32
# Include <netinet/in. h>
# Include <ARPA/inet. h>
# Else
# Include <winsock2.h>
# Endif // Win32
# Include <stdlib. h>
# Include <stdio. h>
# Include <iostream>
# Include <string>
// Check whether an RTP error occurs. If an error occurs, the error message is printed.
Void checkerror (INT rtperr)
{
If (rtperr <0)
{
STD: cout <"error:" <rtpgterrorstring (rtperr) <STD: Endl;
Exit (-1 );
}
}
// Main Loop
Int main (void)
{
// In Windows, We need to load the socket for the first time.
# Ifdef Win32
Wsadata dat;
Wsastartup (makeword (2, 2), & dat );
# Endif // Win32
Rtpsession sess;
// Rtpsession class to instantiate this RTP session
Uint16_t portbase, destport;
// Local port number, destination port number
Uint32_t destip;
// Destination IP address
STD: String ipstr;
Int status, I, num;
// Obtain required information first
STD: cout <"enter local portbase:" <STD: Endl;
STD: CIN> portbase;
STD: cout <STD: Endl;
STD: cout <"Enter the destination IP address" <STD: Endl;
STD: CIN> ipstr;
Destip = inet_addr (ipstr. c_str ());
If (destip = inaddr_none)
{
STD: cerr <"Bad IP address specified" <STD: Endl;
Return-1;
}
// Inet_addr returns a network-based byte sequence. What we need is a native byte sequence,
// You also need to use ntohl
Destip = ntohl (destip );
STD: cout <"Enter the destination port" <STD: Endl;
STD: CIN> destport;
STD: cout <STD: Endl;
STD: cout <"number of packets you wish to be sent:" <STD: Endl;
STD: CIN> num;
// Create an RTP session below to send incoming data packets
// This is the second parameter class of rtpsession. Its member function can set the listening port.
Rtpudpv4transmissionparams transparams;
// This is the first parameter class of rtpsession. Its member functions can be used to set an appropriate timestamp unit.
Rtpsessionparams sessparams;
// Set the appropriate timestamp unit. We need to send 10 times per second, so the parameter is 1.0/10.
Sessparams. setowntimestampunit (1.0/10.0 );
// Set whether to receive custom data packets.
Sessparams. setacceptownpackets (true );
// Set the local port
Transparams. setportbase (portbase );
// Initialize and create a RTP session
Status = sess. Create (sessparams, & transparams );
Checkerror (Status );
// Combine the destination address
Rtp00004address ADDR (destip, destport );
// Set the destination address and add the destination address for sending. Of course, you can add many addresses for multicast.
// You can also use deletedestination () and cleardestinations () to delete and clear the target address.
// It can also be written as unsigned long ADDR = ntohl (inet_addr ("127.0.0.1 "));
// Sess. adddestination (ADDR, 6000 );
Status = sess. adddestination (ADDR );
Checkerror (Status );
For (I = 1; I <= num; I ++)
{
Printf ("\ nsending packet % d/% d \ n", I, num );
// Send streaming media data. The first parameter is the sent data, the second parameter is the data length, followed by the RTP load type, identifier, and timestamp.
// Of course, jrtplib allows them to be set as the default parameter of the session. This is done by calling the setdefapaypayloadtype () and setdefaultmark methods of the rtpsession class. If this is done, we can send data like this:
// Status = sess. sendpacket (void *) "1234567890", 10 );
Status = sess. sendpacket (void *) "1234567890", false, 10 );
Checkerror (Status );
/*
Sess. begindataaccess ();
// The received message traverses all the data sources (because one RTP session allows multiple participants (sources ))
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
Rtptime: Wait (rtptime (1, 0 ));
}
Sess. byedestroy (rtptime (10, 0), 0, 0 );
// In Windows, we have finally uninstalled the socket.
# Ifdef Win32
Wsacleanup ();
# Endif // Win32
Return 0;
}
Acceptor:
/*
* Jrtplib data receiving routine
* Http://blog.sina.com.cn/s/blog_57e2e18901008s4h.html
*/
# Include "rtpsession. H"
# Include "rtppacket. H"
# Include "rtpudpv4transmitter. H"
# Include "rtp00004address. H"
# Include "rtpsessionparams. H"
# Include "rtperrors. H"
# Ifndef Win32
# Include <netinet/in. h>
# Include <ARPA/inet. h>
# Else
# Include <winsock2.h>
# Endif // Win32
# Include "rtpsourcedata. H"
# Include <stdlib. h>
# Include <stdio. h>
# Include <iostream>
# Include <string>
// Check for errors
Void checkerror (INT rtperr)
{
If (rtperr <0)
{
STD: cout <"error:" <rtpgterrorstring (rtperr) <STD: Endl;
Exit (-1 );
}
}
// Re-encapsulate a class
Class myrtpsession: Public rtpsession
{
Protected:
Void onnewsource (rtpsourcedata * dat)
{
If (dat-> isownssrc ())
Return;
Uint32_t IP address;
Uint16_t port;
If (dat-> getrtpdataaddress ()! = 0)
{
Const rtp00004address * ADDR = (const rtp00004address *) (dat-> getrtpdataaddress ());
IP = ADDR-> getip ();
Port = ADDR-> getport ();
}
Else if (dat-> getrtcpdataaddress ()! = 0)
{
Const rtp00004address * ADDR = (const rtp00004address *) (dat-> getrtcpdataaddress ());
IP = ADDR-> getip ();
Port = ADDR-> getport ()-1;
}
Else
Return;
Rtp00004address DEST (IP, Port );
Adddestination (DEST );
Struct in_addr inaddr;
Inaddr. s_addr = htonl (IP );
STD: cout <"adding destination" <STD: string (inet_ntoa (inaddr) <":" <port <STD: Endl;
}
Void onbyepacket (rtpsourcedata * dat)
{
If (dat-> isownssrc ())
Return;
Uint32_t IP address;
Uint16_t port;
If (dat-> getrtpdataaddress ()! = 0)
{
Const rtp00004address * ADDR = (const rtp00004address *) (dat-> getrtpdataaddress ());
IP = ADDR-> getip ();
Port = ADDR-> getport ();
}
Else if (dat-> getrtcpdataaddress ()! = 0)
{
Const rtp00004address * ADDR = (const rtp00004address *) (dat-> getrtcpdataaddress ());
IP = ADDR-> getip ();
Port = ADDR-> getport ()-1;
}
Else
Return;
Rtp00004address DEST (IP, Port );
Deletedestination (DEST );
Struct in_addr inaddr;
Inaddr. s_addr = htonl (IP );
STD: cout <"deleting destination" <STD: string (inet_ntoa (inaddr) <":" <port <STD: Endl;
}
Void onremovesource (rtpsourcedata * dat)
{
If (dat-> isownssrc ())
Return;
If (dat-> receivedbye ())
Return;
Uint32_t IP address;
Uint16_t port;
If (dat-> getrtpdataaddress ()! = 0)
{
Const rtp00004address * ADDR = (const rtp00004address *) (dat-> getrtpdataaddress ());
IP = ADDR-> getip ();
Port = ADDR-> getport ();
}
Else if (dat-> getrtcpdataaddress ()! = 0)
{
Const rtp00004address * ADDR = (const rtp00004address *) (dat-> getrtcpdataaddress ());
IP = ADDR-> getip ();
Port = ADDR-> getport ()-1;
}
Else
Return;
Rtp00004address DEST (IP, Port );
Deletedestination (DEST );
Struct in_addr inaddr;
Inaddr. s_addr = htonl (IP );
STD: cout <"deleting destination" <STD: string (inet_ntoa (inaddr) <":" <port <STD: Endl;
}
};
//
// The main routine
//
Int main (void)
{
# Ifdef Win32
Wsadata dat;
Wsastartup (makeword (2, 2), & dat );
# Endif // Win32
Myrtpsession sess;
Uint16_t portbase;
STD: String ipstr;
Int status, I, num;
Unsigned char * payloadpointer;
Int J, Len;
// First, we'll ask for the necessary information
STD: cout <"enter local portbase:" <STD: Endl;
STD: CIN> portbase;
STD: cout <STD: Endl;
STD: cout <STD: Endl;
STD: cout <"number of seconds you wish to wait:" <STD: Endl;
STD: CIN> num;
Rtpudpv4transmissionparams transparams;
Rtpsessionparams sessparams;
// Important: the local timestamp unit must be set, otherwise
// RTCP Sender report info will be calculated wrong
// In this case, we'll be just use 8000 samples per second.
Sessparams. setowntimestampunit (1.0/8000.0 );
Sessparams. setacceptownpackets (true );
Transparams. setportbase (portbase );
Status = sess. Create (sessparams, & transparams );
Checkerror (Status );
For (I = 1; I <= num; I ++)
{
Sess. begindataaccess ();
// Traverse all data sources
If (sess. gotofirstsourcewithdata ())
{
Do
{
Rtppacket * pack;
While (pack = sess. getnextpacket ())! = NULL)
{
// You can examine the data here
Printf ("got packet! \ N ");
Payloadpointer = pack-> getpayloaddata (); // get the Data Pointer
Len = pack-> getpayloadlength (); // obtain the Data Length
For (j = 0; j <Len; j ++)
{
Printf ("% C", * (payloadpointer + J); // print data
}
Printf ("\ n ");
// Delete the obtained data
Sess. deletepacket (pack );
}
} While (sess. gotonextsourcewithdata ());
}
Sess. enddataaccess ();
# Ifndef rtp_support_thread
Status = sess. Poll ();
Checkerror (Status );
# Endif // rtp_support_thread
Rtptime: Wait (rtptime (1, 0 ));
}
Sess. byedestroy (rtptime (10, 0), 0, 0 );
# Ifdef Win32
Wsacleanup ();
# Endif // Win32
Return 0;
}
Compile: G ++-O example1 example1.cpp-I/usr/local/include/jrtplib3/-ljrtp