Use RTP to send H.264 sample code analysis

Source: Internet
Author: User

First declare that the following code is in post http://topic.csdn.net/u/20090725/11/5FBC75B0-1091-4DD4-9154-3E3D59F9B6D1.html {
Logclickcount (this, 111 );
} "Href =" http://hi.csdn.net/ttxk "target =" _ blank ">TtxkAnnotations are added to ttxk and {
Logclickcount (this, 111 );
} "Href =" http://hi.csdn.net/jessiepan "target =" _ blank "> thank you ,{
Logclickcount (this, 111 );
} "Href =" http://hi.csdn.net/jessiepan "target =" _ blank "> the study spirit of jessiepan is very good, very responsible for the landlord. I guess I will also have problems.

The following are notes for reading ttxk code based on rfc3894. The next phase may be to use an RTP database to complete the RTP transmission part and the corresponding accept processing part.

 

Uint mediastreamh264: transportdata (pbyte pdata, uint datasize, int PTS)
{
// Current cache Header
Pbyte p_buffer = pdata;
// Current cache size
Int I _buffer = datasize;

// Sent size
Uint writesize = 0;

// Search for the first header [3 byte, 0 x, 0 x]
While (I _buffer> 4 & (p_buffer [0]! = 0 | p_buffer [1]! = 0 | p_buffer [2]! = 1 ))
{
I _buffer --;
P_buffer ++;
}

/* Split NAL units */
While (I _buffer> 4)
{
Int I _offset;
Int I _size = I _buffer;
Int I _skip = I _buffer;

/* Search nal end */
For (I _offset = 4; I _offset + 2 <I _buffer; I _offset ++)
{
// Find the next header to find the end position of the current frame
If (p_buffer [I _offset] = 0 & p_buffer [I _offset + 1] = 0 & p_buffer [I _offset + 2] = 1)
{
/* We found another startcode */
// Determine whether the next header is two or three 0x00, if p_buffer [I _offset-1] indicates that the next header is three 0x00 + 0x01, I _size should be reduced by one more
I _size = I _offset-(p_buffer [I _offset-1] = 0? 1: 0 );
I _skip = I _offset;
Break;
}
}
/* Todo add STAP-A to remove a lot of overhead with small slice/SEI /...*/
// Send the currently found Frame
Uint iwrite = transporth1_nal (p_buffer, I _size, PTS, (I _size> = I _buffer ));
If (iwrite> 0)
Writesize + = iwrite;

I _buffer-= I _skip;
P_buffer + = I _skip;
}
Return writesize;
}

// Send a frame of 264 data. Generally, a frame is sent as an RTP packet. an excessively long frame is divided into multiple RTP packets for transmission.
Uint mediastreamh264: transporth1_nal (const pbyte pnal, uint nalsize, int32 pts, bool islast)
{
// The process should be locked
Atlock (& m_tlockrun );

If (m_brun = false)
Return 0;

// The minimum length of each frame must be at least 5
If (nalsize <5)
Return 0;

/* MTU is MTU and should be a global variable. The following describes a value that can be set to around 1500 on the IP network.
The aggregation package is the nal unit aggregation arrangement of this load specification. The introduction of this plan is to reflect two major differences between the target networks: the wired IP Network (MTU is usually limited by the Ethernet MTU; about 1500 bytes ), for an IP or non-IP (ITU-T H.324/m) network based on a wireless communication system, its maximum priority transmission unit is 254 or less. To prevent the conversion of media from connecting to the world and avoid unnecessary packaging burden, an aggregation unit arrangement is introduced.
*/
Uint MTU = m_nmtu;

// According to Opal experience, you can set I _max to 1400.
Const int I _max = Mtu-rtp_header_size;/* payload Max in one packet */
Int I _nal_hdr; // The Nal header.
Int I _nal_type;

I _nal_hdr = pnal [3];
I _nal_type = I _nal_hdr & 0x1f; // the last bit of the first two bytes and the second byte of the first two bytes are type

String SPS;
String PPS;

// For The Nal unit whose nal_unit_type is equal to 264 (indicating the sequence parameter set or image parameter set), the H.264 Encoder should set NRI to 11 (binary format)
If (I _nal_type = 7 | I _nal_type = 8)
{
/* XXX why do you want to remove them? It will break streaming
* SPS/PPS change (broadcast )? */
Return 0;
}

/* Skip start code */
Pbyte p_data = pnal;
Int I _data = nalsize;

// Skip the three byte h264 frame headers (0x00 0x00 0x01)
P_data + = 3;
I _data-= 3; // The length of NAL + nalu

Int writesize = 0;

// If the data length of this frame is smaller than the maximum length of the content of a UDP packet, send multiple packets in one frame according to the Fu format.
If (I _data <= I _max)
// The Transmission sequence of a single nal unit must be consistent with the nal decoding sequence.

{
/* Single nal unit packet */
// Writesize = m_prtptransport-> setrtpdata (p_data, I _data, PTS, islast );
// Send data
Writesize = m_prtptransport-> write (p_data, I _data, m_nrtppayloadtype, PTS, 0, islast );
If (writesize <= 0)
Return 0;
Return writesize;
}
Else
// STAP type package, is the STAP-A method, determined by the following 28
{
/* FU-A fragmentation unit without interleaving */
Const int I _count = (I _data-1 + I _max-2-1)/(I _max-2); // how many packets are needed
Int I;

P_data ++;
I _data --;

For (I = 0; I <I _count; I ++)
{
// Calculate the length of each NALU data, judge whether it is the last package, not the last package is I _max-2, the last package is I _data (that is, the actual length of the last package)
Const int I _payload = (I _data <(I _max-2 ))? I _data: (I _max-2 );
// Calculate the length of each nalu
Const int nalsize = 2 + I _payload;

M_packet.extendbuffer (nalsize );

/* Fu indicator */
/* I _nal_hdr & 0110 0000.
Fu indicates that the byte format is as follows:
+ --------------- +
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+-+
| F | NRI | type |
+ --------------- +
Fu indicates the 28, 29 represents the FU-A and Fu-B of the type field of the byte. F is used in 5. 3. The value of the nri field must be set based on the value of the nri field of the partition nal unit.

28 indicates that it is a FU-A, see rfc3984 5.8, that is, the processing method for fragment units here is a FU-A, no staggered mode is used, no Don
*/
M_packet.m_pdata [0] = 0x00 | (I _nal_hdr & 0x60) | 28;
/* Fu header */
/*
The format of the Fu header is as follows:
+ --------------- +
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+-+
| S | E | r | type |
+ --------------- +
S: 1 bit
When set to 1, the start bit indicates the beginning of the nal unit. When the followed Fu load is not the start of the multipart nal unit load, the start position is set to 0.
That is, (I = 0? 0x80: 0x00)

E: 1 bit
When set to 1, the second bit indicates the end of The multipart nal unit, that is, the last byte of the load is also the last byte of the multipart nal unit. When the followed Fu load is not the last part of the nal unit, the priority is set to 0.
That is (I = I _count-1 )? 0x40: 0x00)
A shard unit cannot be transmitted in one Fu. That is, the start bit and the hidden bit cannot be set in the same Fu header at the same time.

R: 1 bit
The Reserved Bit must be set to 0, and the receiver must ignore this bit.
Not processed

Type: 5 bits
The load types of NAL units are defined in Table 7-1 of [1.
Continue with the general type
*/
M_packet.m_pdata [1] = (I = 0? 0x80: 0x00) | (I = I _count-1 )? 0x40: 0x00) | I _nal_type;

/* Fu payload */
Memcpy (& m_packet.m_pdata [2], p_data, I _payload );

M_packet.m_datasize = nalsize;

/*
Fragments are defined only for a single nal unit and are not used for any aggregation package. A part of a nal unit consists of an integer continuous nal unit bytes. Each nal unit must be part of a part of the nal unit. Fragments of the same nal unit must be continuously sent using an incremental RTP sequence number (no other RTP packet exists between the first and last fragments ). Similarly, the nal unit must be assembled according to the RTP sequence number.
*/
// Int iwrite = m_prtptransport-> setrtpdata (m_packet.m_pdata, m_packet.m_datasize, PTS, islast & (I = I _count-1 ));
Int iwrite = m_prtptransport-> write (m_packet.m_pdata, m_packet.m_datasize, m_nrtppayloadtype, PTS, 0, islast & (I = I _count-1 ));
/*
If one part unit is lost, the receiver should discard all subsequent parts corresponding to the transmission sequence of the same part nal unit.

The receiver in the terminal or mane can aggregate the n-1 fragments of the previous nal unit to an (incomplete) nal unit, or even the N part is not received. in this case, the forbidden_zero_bit of the nal unit must be set to 1 to indicate that the syntax is against.

The receiver includes a receiving buffer to compensate for transmission latency and jitter. The packets stored by the receiver are in the receiving buffer in the order of receipt. The package is unencapsulated In the RTP sequence. If the package is a single nal unit package, the nal Unit contained in the package is passed directly to the decoder. If the unencapsulated package is a STAP-AI, The NAL units contained in the package are passed to the decoder in the encapsulation order they contained in the package. If the unencapsulated package is a FU-A, all the sharded NAL units are connected together and passed to the decoder.

Information: If the decoder supports any part sequence, the encoded image slices can be transmitted to the decoder in any order, regardless of their receipt and Transmission sequence.

*/

If (iwrite> 0)
Writesize + = iwrite;

I _data-= I _payload;
P_data + = I _payload;
}
}
Return writesize;
}

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.