Real-time transfer implementation based on the jrtplib library in Linux
I. RTP is a standard protocol and Key Technology for Real-Time Streaming Media transmission.
Real-Time Transport Protocol (PRT) is a network protocol for processing multimedia data streams over the Internet. It can be used in one-to-one (unicas, unicast) scenarios) or you can transmit streaming media data in real time in a one-to-multiple (multicas) network environment. RTP usually uses UDP for multimedia data transmission, but other protocols such as TCP or ATM can be used if necessary.
Protocol Analysis: Each RTP datagram consists of the header and payload. The meaning of the first 12 bytes of the header is fixed, the load can be audio or video data.
RTP is currently the best solution to the problem of real-time transmission of streaming media. To program real-time transmission on the Linux platform, you can consider using open-source RTP libraries, such as librtp and jrtplib. Jrtplib is an object-oriented RTP database. It fully complies with RFC 1889 and is a good choice in many cases. Jrtplib is a RTP Library implemented in C ++, this library uses the socket mechanism for network communication, so it can run on Windows, Linux, FreeBSD, Solaris, UNIX, and VxWorks.
Ii. jrtplib library usage and program implementation
(1) Use of the jrtplib Function
A. Before using jrtplib for Real-Time Streaming Media data transmission, you should first generate an rtpsession instance to represent the RTP session, and then call the CREATE () method to initialize it. The create () method of the rtpsession class has only one parameter to specify the port number used for this RTP session.
Rtpsession sess; sess. Create (5000 );
B. Setting an appropriate timestamp unit is another important task in the RTP Session Initialization Process. This is achieved by calling the settimestampunit () method of the rtpsession class, this method also has only one parameter, indicating the timestamp unit in seconds.
Sess. settimestampunit (1.0/8000.0 );
C. After the RTP session is successfully established, the streaming media data can be transmitted in real time. First, you need to set the destination address for data transmission. The RTP protocol allows multiple destination addresses for the same session. You can call the adddestination (), deletedestination (), and cleardestinations () of the rtpsession class () method. For example, the following statement indicates that the RTP session sends data to Port 6000 of the local host:
Unsigned long ADDR = ntohl (inet_addr ("127.0.0.1 "));
Sess. adddestination (ADDR, 6000 );
D. After specifying all target addresses, 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.
For the same RTP Session, the load type, identifier, and timestamp increment are usually the same. jrtplib allows you to set them as the default parameters of the session, this is done by calling the setdefaultpayloadtype (), setdefaultmark (), and setdefatimetimestampincrement () Methods of the rtpsession class. Setting these default parameters for RTP sessions can simplify data transmission. For example, if you set the default parameters for RTP sessions:
Sess. setdefapaypayloadtype (0 );
Sess. setdefamark mark (false );
Sess. setdefatimetimestampincrement (10 );
Then, when sending data, you only need to specify the data to be sent and its length:
Sess. sendpacket (buffer, 5 );
E. 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. Multiple participants (sources) are allowed in the same RTP session. 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 the valid data source is detected from the RTP session, you can call the getnextpacket () method of the rtpsession class to extract the RTP data report from it. After the received RTP data report is processed, remember to release it in time.
Jrtplib defines three receiving modes for RTP datagram, each of which specifies 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 some specific senders, all incoming RTP datagram data will be accepted, and the list of rejected senders can be called by addtoignorelist (), deletefromignorelist (), and clearignorelist () method;
? Receivemode_acceptsome except for some specific senders, all incoming RTP datagram data will be rejected, and the list of accepted senders can be called by addtoacceptlist (), deletefromacceptlist, and clearacceptlist () method. The following is a program example using the third receiving mode.
If (sess. gotofirstsourcewithdata ()){
Do {
Sess. addtoacceptlist (remoteip, allports, portbase );
Sess. setreceivemode (receivemode_acceptsome );
Rtppacket * pack;
Pack = sess. getnextpacket (); // process received data
Delete pack ;}
While (sess. gotonextsourcewithdata ());
}
(2) program flowchart
Sending: Obtain the IP address and port number of the receiving end to create an RTP session. Specify the RTP data receiving end. Set the default parameter of the RTP session to send streaming media data.
Receive: Get the user-specified port number, create RTP session, set the receiving mode, accept RTP data retrieval, RTP data source, get RTP datagram, delete RTP Datagram
Iii. Environment setup and compilation methods
(1) toolchain Installation
First find the xscale-arm-toolchain.tgz file, assuming that the package is under/tmp/
# Cd/
# Tar-zxvf/tmp/xscale-arm-toolchain.tgz
Set the environment variable
# Export Path =/usr/local/ARM-Linux/bin: $ path
Finally, check whether the cross-compilation tool is successfully installed.
# Arm-Linux-G ++ -- version
Check whether the arm-Linux-G ++ version is displayed. If yes, the installation is successful.
(2) Cross-compilation and installation of the jrtplib Library
First download the latest source code package from the jrtplib website (http://lumumba.luc.ac.be/jori/jrtplib/jrtplib.htmll), this uses jrtplib-2.8.tar, assuming that the downloaded source code package is placed under/tmp, execute the following command to decompress it:
# Cd/tmp
# Tar-zxvf jrtplib-2.8.tar
Then configure and compile jrtplib.
# Cd jrtplib-2.8
#./Configure cc = arm-Linux-G ++ cross-compile = Yes
Modify makefile
Change the connection commands LD and AR to arm-Linux-LD and arm-Linux-ar.
# Make
Run the following command to install jrtplib:
# Make install
(3) program Compilation
A. Configure the compiling environment
You can use export or makefile. Makefile is used here.
Write 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.
Cc = arm-Linux-G ++
Main: Main. o
$ (CC) $ (lflags) $ (incl)-O main. o $ (libs)
Main. O: Main. cpp
Clean:
Rm-F Main
Rm-f *. o
. Suffixes:. cpp
. Cpp. O:
$ (CC)-C $ (cflags) $ (incl)-o $ </* $ @ indicates the complete name of the target */
/* $ <Indicates the name of the first dependent file */
B. Compile
Assume that the sending and receiving programs are stored in the/tmp/send and/tmp/receive directories respectively.
# Cd/tmp/send
# Make
# Cd/tmp/receive
# Make
4. easy error and attention
1. Some basic standard header files cannot be found.
The main reason is that the toolchain path is not correctly installed and must be installed in strict accordance with the steps.
2. Some header files in the jrtplib library cannot be found.
In the jrtplib installation directory, no other directories can be found in the include path.
3. The recieve function cannot correctly extract the required data from the received data packets.
Each RTP datagram is composed of two parts: header and payload. If getrawdata () is used to return the data of the entire data packet, it contains the type, format, serial number, timestamp, and additional data of the media to be transmitted. The getpayload () function returns the data sent. The two must be distinguished.
4. After the receivemode_acceptsome receiving mode is set, the receiver of the running program cannot receive packets.
The IP address format is incorrect. The iner_addr () and ntohl () functions need to use a pair. Otherwise, the parameter cannot be passed in and there is no value in the acceptance list. Of course, the data packet cannot be received.
5. The compilation is successful, but the receiving end cannot receive data during the test.
It may be that the receiver firewall is not disabled. Run:
# Iptables-F
It may be that the IP address is not properly configured. Run:
# Ifocnfig eth0 *. * netmask *.*.*.*
6. When using the jrtolib library, it is best to add the path of the library after include in the program.
V. Procedures
Send:
# Include <stdio. h>
# Include <string. h>
# Include "rtpsession. H"
// Error handling function
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;
}
// Obtain the IP address and port number of the acceptor.
Destip = inet_addr (argv [1]);
If (destip = inaddr_none ){
Printf ("Bad IP address specified. // n ");
Return-1;
}
Destip = ntohl (destip );
Destport = atoi (argv [2]);
// Create an RTP session
Status = sess. Create (portbase );
Checkerror (Status );
// Specify the RTP data receiving end
Status = sess. adddestination (destip, destport );
Checkerror (Status );
// Set the default parameters of the RTP session
Sess. setdefapaypayloadtype (0 );
Sess. setdefamark mark (false );
Sess. setdefatimetimestampincrement (10 );
// Send streaming media data
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"
// Error handling function
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;
}
// Obtain the user-specified port number
Remoteip = inet_addr (argv [1]);
Localport = atoi (argv [2]);
Portbase = atoi (argv [3]);
// Create an RTP session
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 {
// Set the receiving mode
Sess. setreceivemode (receivemode_acceptsome );
Sess. addtoacceptlist (remoteip, allports, portbase );
// Accept RTP data
Status = sess. polldata ();
// Retrieve the RTP data source
If (sess. gotofirstsourcewithdata ()){
Do {
Rtppacket * packet;
// Obtain the RTP Datagram
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 );
// Delete the RTP Datagram
Delete packet;
}
} While (sess. gotonextsourcewithdata ());
}
} While (1 );
Return 0;
}
I have been reading about jrtplib these days. I have read many articles on the Internet, and most of them use jrtplib versions earlier than 3.0.
I downloaded a library of JRTPLIB-3.7 on the Internet and found some modifications to the function interface. The previous JRTPLIB-3.7-Based Network
For example, if you are interested in the study.
------- Chuckgao
Part 1 jrtplib compilation and Installation
This is a required step. You can find related articles on the Internet. However, some may encounter jrtplib
If compilation fails, an error occurs: 'memcpy' was not declared in this scope. This is because jrtplib
The memcpy function cannot be found in the translation. There is a memcpy patch on the Internet. The content is as follows:
Diff -- git a/src/rtcpcompoundpacketbuilder. cpp B/src/rtcpcompoundpacketbuilder. cpp
Index 8172007 .. 8fd4510 100644
--- A/src/rtcpcompoundpacketbuilder. cpp
++ B/src/rtcpcompoundpacketbuilder. cpp
@-30,6 + 30,8 @@
*/
+ # Include <cstring>
+
# Include "rtcpcompoundpacketbuilder. H"
# Include "rtcpsrpacket. H"
# Include "rtcprrpacket. H"
Diff -- git a/src/rtppacket. cpp B/src/rtppacket. cpp
Index b6d5fda... 8c516c7 100644
--- A/src/rtppacket. cpp
++ B/src/rtppacket. cpp
@-30,6 + 30,8 @@
*/
+ # Include <cstring>
+
# Include "rtppacket. H"
# Include "rtpstructs. H"
# Include "rtpdefines. H"
+ Indicates addition.-Indicates deletion of corresponding content.
Part 2 jrtplib Programming
The following first reproduced part of the Online Guide, red mark is the use of JRTPLIB-3.7 after repair
Real-time transfer implementation based on the jrtplib library in Linux
I. RTP is a standard protocol and Key Technology for Real-Time Streaming Media transmission.
Real-Time Transport Protocol (PRT) is a network protocol used to process multimedia data streams over the Internet.
It can be used to transmit streaming media data in a one-to-one (unicast, unicast) or one-to-many (multicast, multicast) network environment.
Real-time transmission. RTP usually uses UDP for multimedia data transmission, but other protocols such as TCP or ATM can be used if necessary.
Discussion.
Protocol Analysis: Each RTP datagram consists of two parts: header and payload, the first 12 bytes of the header
The meaning is fixed, while the load can be audio or video data.
RTP is currently the best solution to the problem of real-time transmission of streaming media. To program real-time transmission on the Linux platform, consider using
Some Open Source RTP libraries, such as librtp and jrtplib. Jrtplib is an object-oriented RTP Library, which fully complies with RFC
1889 design, in many cases is a very good choice. Jrtplib is a RTP Library implemented in C ++, which uses
The socket mechanism enables network communication, so it can run in windows, Linux, FreeBSD, Solaris, UNIX, and VxWorks.
System.
Ii. jrtplib library usage and program implementation
(1) Use of the jrtplib Function
A. Before using jrtplib for Real-Time Streaming Media data transmission, an rtpsession instance should be generated to represent the RTP
Session, and then call the CREATE () method to initialize it. The create () method of the rtpsession class has only one parameter
To specify the port number used by the RTP session.
Rtpsession sess; sess. Create (5000 );
The create (prot) method has been modified in JRTPLIB-3.7. The new create method is modified to crea (sessparams, & transparams ). The two parameters must be defined as follows:
Rtpudpv4transmissionparams transparams;
Rtpsessionparams sessparams;
Sessparams. setowntimestampunit (1.0/8000.0);/* set the timestamp. 1/8000 indicates 8000 samples per second, that is, 8 kHz during recording */
Sessparams. setacceptownpackets (true );
Transparams. setportbase (portbase);/* local communication port */
B. Setting an appropriate timestamp unit is another important task in the RTP Session Initialization Process. This is done by calling rtpsession
The settimestampunit () method of the class has been mentioned earlier.
C. After the RTP session is successfully established, the streaming media data can be transmitted in real time. First, you need to set Data Transmission
The destination address to be sent. The RTP protocol allows multiple destination addresses in the same session.
Adddestination (), deletedestination (), and cleardestinations () methods. For example, the following statement indicates
Is to let the RTP session send data to Port 6000 of the local host:
Unsigned long ADDR = ntohl (inet_addr ("127.0.0.1 "));
Sess. adddestination (ADDR, 6000 );
D. After all the target addresses are specified, you can call the sendpacket () method of the rtpsession class to send
Streaming media data. Sendpacket () is an overload function provided by the rtpsession class.
For the same RTP Session, the load type, identifier, and timestamp increment are usually the same, and jrtplib allows them to be set
This is the default parameter by calling the setdefapaypayloadtype (), setdefaultmark (), and
Setdefatimetimestampincrement () method. Setting these default parameters for RTP sessions can simplify data transmission.
For example, if the default parameters are set for the RTP session:
Sess. setdefapaypayloadtype (0 );
Sess. setdefamark mark (false );
Sess. setdefatimetimestampincrement (10 );
Then, when sending data, you only need to specify the data to be sent and its length:
Sess. sendpacket (buffer, 5 );
In real voice transmission, the above buffer is the buffer we get during the recording. The above function can be used for simple transmission, but it cannot implement RTP transmission. We need to call another interface: sess. sendpacket (void *) buffer, sizeof (buffer), 0, false, 8000); For detailed instructions, see the instructions of jrtplib.
E. 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.
Change the polldata () method to poll () in the JRTPLIB-3.7, using the same
Since multiple participants (sources) are allowed in the same RTP session, you can call the rtpsession class
The gotofirstsource () and gotonextsource () methods can traverse all sources. You can also call the rtpsession class
The gotofirstsourcewithdata () and gotonextsourcewithdata () Methods traverse those sources with data. At
After detecting the valid data source, you can call the getnextpacket () method of the rtpsession class to extract the RTP number from it.
It is reported that after the received RTP datagram is processed, remember to release it in time.
Jrtplib defines three receiving modes for RTP datagram, each of which specifies which RTP datagram will be
Accept, and which RTP datagram will be rejected. You can set it by calling the setreceivemode () method of the rtpsession class.
The following receiving modes:
Receivemode_all: the default receiving mode. All received RTP data packets are accepted;
Receivemode_ignoresome except for some specific senders, all arriving RTP data packets will be accepted and rejected
You can call addtoignorelist (), deletefromignorelist (), and clearignorelist ()
Row settings;
Receivemode_acceptsome except for some specific senders, all arriving RTP datagram data will be rejected and accepted
The list of senders can be entered by calling the addtoacceptlist (), deletefromacceptlist, and clearacceptlist () methods.
Row settings. The following is a program example using the third receiving mode.
If (sess. gotofirstsourcewithdata ()){
Do {
Sess. addtoacceptlist (remoteip, allports, portbase );
Sess. setreceivemode (receivemode_acceptsome );
Rtppacket * pack;
Pack = sess. getnextpacket (); // process received data
Delete pack ;}
While (sess. gotonextsourcewithdata ());
}
In the complete code, you must first call the poll () method to receive RTP datagram, and then receive data between begindataaccess () and enddataaccess. At this point, we set the program to always do-while wait and process data.
Do {
# Ifndef rtp_support_thread
Error_status = sess_client.poll ();
Checkerror (error_status );
# Endif // rtp_support_thread
Sess_client.begindataaccess ();
// Check incoming packets
If (sess_client.gotofirstsourcewithdata ())
{
Printf ("begin play/N ");
Do
{
Rtppacket * pack;
While (pack = sess_client.getnextpacket ())! = NULL)
{
// You can examine the data here
Printf ("got packet! /N ");
Timestamp1 = pack-> gettimestamp ();
Lengh = pack-> getpayloadlength ();
Rawdata = pack-> getpayloaddata (); // get data
Printf ("timestamp: % d lengh = % d/N", timestamp1, lengh );
// We don't longer need the packet, so
// We'll delete it
// Begin play
Int FD = open ("/dev/DSP", o_rdwr );
Int status = write (FD, rawdata, lengh );
Printf ("play Bytes: % d/N", status );
If (status! = Lengh)
Perror ("wrote wrong number of bytes ");
Status = IOCTL (FD, sound_pcm_sync, 0 );
If (status =-1)
Perror ("sound_pcm_sync IOCTL failed ");
Printf ("play end/N ");
Close (FD );
Sess_client.deletepacket (pack );
}
} While (sess_client.gotonextsourcewithdata ());
// Return 0;
}
Sess_client.enddataaccess ();
} While (1 );
(2) program flowchart
Sending: Obtain the IP address and port number of the receiving end to create an RTP session. Specify the RTP data receiving end. Set the default parameter of the RTP session to send streaming media data.
Receive: Get the user-specified port number, create RTP session, set the receiving mode, accept RTP data retrieval, RTP data source, get RTP datagram, delete RTP Datagram
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/guiterb/archive/2009/10/11/4616123.aspx