Directly go to the topic. After JPEG compression, the data is transmitted to the network through the RTP/RTCP protocol. This topic uses the RTP/RTCP protocol stack of jrtplib, first, obtain the source code of the jrtplib package on the internet, decompress the configuration, compile and install the package, and OK if no bugs is available.
There are several examples in the source code package, which can be used for reference. When setting the server end, it is different from the TCP/IP protocol. First, set a baseport port when initializing the opened session, and set the Client IP address and port at the same time, then, set the timestamp Based on the video sampling frequency. The specific setting functions can be found in examples and can be reused.
Here we will talk about the sending and receiving code. both sending and receiving are implemented through the thread:
Send:
Ret = send_rtppacket (unsigned char *) videoin. ptframe [frameout], sizeof (struct frame_t) + headerframe-> size );
In the sending thread function, directly send the data pointed to by the ptframe [] pointer. The data size is sizeof (struct frame_t) + headerframe-> size, which contains the data of the frame, and the data structure described for this frame parameter.
Int send_rtppacket (unsigned char * framepointer, int framelength)
{
Int done = 0;
Int flage;
Int sendbyte = 0;
Int N;
Do {
If (framelength> packetmaxsize) // you can specify packetmaxsize as 1400. If the oversize is set, the data is transmitted separately.
Flage = 0;
Else flage = 1;
If (flage = 1)
{
N = session. sendpacket (framepointer, framelength, 1000,); // The fourth parameter of the sending function determines whether the frame is the last
Less than 1400 of data
Done = 1; // if the mark is complete
Sendbyte = framelength;
} Else {
N = session. sendpacket (framepointer, packetmaxsize, 1000 );
Framepointer = framepointer + packetmaxsize; // update send pointer
Framelength = framelength-packetmaxsize;
Sendbyte = sendbyte + packetmaxsize;
}
If (n <0)
{Return-1 ;}
Rtptime: Wait (Delay );
} While (! Done );
Return sendbyte;
}
Receive:
Do {
// Retrieve the RTP data source
Sess. begindataaccess ();
If (sess. gotofirstsourcewithdata ()){
Do {
Rtppacket * packet;
Rtpsourcedata * srcdata;
// Obtain the RTP Datagram
Packetflage = 0;
Recvlength = 0; // initialize the receiving data and data receiving mark
While (packet = sess. getnextpacket ())! = NULL & packetflage = 0) {// The flag is zero. It receives the remaining data of the same packet.
// Printf ("got packet! /N ");
If (processpacket (* srcdata, * packet )){
Packetflage = 1; // processpacket () returns 1. All packages can be called for decoding. SDL displays
// Printf ("Debug... packetflage: % d/N", packetflage );
Bytes size = readjpeg (& Buf, headerframe );
// Printf ("debug..jpeg size: % d/N", maximum size );
If (! Jpegsize & videook)
Close_sdlvideo ();
If (distinct size &&! Videook)
{
Init_sdlvideo ();
Pscreen = sdl_setvideomode (owidth, oheight, BPP * 8, sdl_doublebuf | sdl_swsurface );
P = (unsigned char *) pscreen-> pixels;
}
If (Response size & videook)
{
Pai_decode (& picture, Buf, & width, & height );
Resize (p, picture, owidth, oheight, width, height );
Sdl_wm_setcaption (titer, null );
Sdl_flip (pscreen );
}
If (sdl_pollevent (& sdlevent) <0) goto error;
}
Else packetflage = 0; // The returned value is 0. The packet has not been connected to the sess. getnextpacket ()
Delete packet; // Delete RTP Datagram
}
} While (sess. gotonextsourcewithdata (); // receives another packet
}
Sess. enddataaccess ();
// Accept RTP data
Status = sess. Poll ();
Checkerror (Status );
Rtptime: Wait (rtptime (1, 0 ));
} While (1 );
Int processpacket (const rtpsourcedata & srcdat, const rtppacket & rtppack)
{
Unsigned char * payloadpointer = rtppack. getpayloaddata (); // receives the data of this packet
Bool packetmarker = rtppack. hasmarker (); // check whether the packet has been uploaded
Int flage = 1;
// Printf ("Debug... 1/N ");
If (! Packetmarker) // data packets that are not passed
{
Memcpy (recvpointer + recvoffset, payloadpointer, rtppack. getpayloadlength ());
Recvlength + = rtppack. getpayloadlength ();
Recvoffset + = rtppack. getpayloadlength (); // update the pointer to save the received data
// Printf ("Debug... 2/N ");
Flage = 0; // indicates that the receiver continues to execute sess. getnextpacket ()
}
Else {
Memcpy (recvpointer + recvoffset, payloadpointer, rtppack. getpayloadlength ());
Recvlength + = rtppack. getpayloadlength ();
Recvoffset = 0; // After uploading, initialize
// Printf ("Debug... 3/N ");
}
Return flage;
}
Summary:
RTP/RTCP data transmission process:
Server:
Send the fixed-length data to the client in batches and send it to the client in the form of packet. That is to say, a packet needs to be sent several times by packet. After the packet is sent successfully, the next packet always calls the function: Session. sendpacket ();
Client:
Call sess cyclically. getnextpacket () is used to receive packet data of a certain data packet. The arrival of packet is not in order. After fully receiving the packets used by the data packet, the RTP database re-sorts the received packages based on the timestamp to generate the final data packet. After successfully receiving the data packet, call sess. gotonextsourcewithdata () to receive the next data packet.