original articles, Forbidden reprint. otherwise pursued.
The information parsing of RTP header in WebRTC has been explained before.
Here to explain the WEBRTC in the RTP parsing, here is the main explanation of h264 analysis;
About class implementations and related test files that are relevant in VP8 and VP9,WEBRTC;
Regarding the RTP file parsing of H264, there are three kinds of RTP packaging protocols implemented in WEBRTC:
Enum H264packetizationtypes {
Kh264singlenalu,//This packet contains a single NAL unit.
Kh264stapa,//This packet contains STAP-A (single time
Aggregation) packets. If This packet have an
Associated NAL unit type, it ' ll is for the
First such aggregated packet.
Kh264fua,//This packet contains a fu-a (fragmentation
Unit) packet, meaning it is a part of a frame
That is too large to fit in a single packet.
};
Refer to: rtp_format_h264_unittest.cc
Simply encapsulate the code as follows:
Class CRtpDepacketizerH264
{
Public
CRtpDepacketizerH264 (): Depacketizer_ (Rtpdepacketizer::create (kRtpVideoH264))
{
M_rtcpbuf = NULL;
Pvectorbuf = NULL;
}
~crtpdepacketizerh264 ()
{
if (Depacketizer_)
{
}
if (M_RTCPBUF)
{
Delete m_rtcpbuf;
M_rtcpbuf = NULL;
}
}
Private
Rtc::buffer * Create_h264buffer ()
{
if (m_rtcpbuf! = NULL)
{
return NULL;
}
uint8_t Startcode[3] = {0};
STARTCODE[2] = 0x01;
M_rtcpbuf = new Rtc::buffer (Startcode, 3);
return m_rtcpbuf;
}
Rtc::buffer * Create_h264buffer_4byte ()
{
if (m_rtcpbuf! = NULL)
{
return NULL;
}
uint8_t Startcode[4] = {0};
STARTCODE[3] = 0x01;
M_rtcpbuf = new Rtc::buffer (Startcode, 4);
return m_rtcpbuf;
}
Public
static int file_size (char* filename)
{
FILE *FP = fopen (filename, "R");
if (!FP) return-1;
Fseek (FP, 0L, seek_end);
int size = Ftell (FP);
Fclose (FP);
return size;
}
static void Clear_vector (Std::vector<rtc::buffer *> * & Pvector_buf)
{
if (PVECTOR_BUF)
{
int nSize = (int) pvector_buf->size ();
for (int n = 0; n<nsize; n++)
{
Delete Pvector_buf->at (n);
}
Delete pvector_buf;
}
Pvector_buf = NULL;
}
Public
Std::vector<rtc::buffer *> * ADD_RTPPACKET_FOR_FRAME (const uint8_t* packet, size_t length)
{
if (pvectorbuf = = NULL)
{
Pvectorbuf = new Std::vector<rtc::buffer *>;
}
Rtpheader header;
std::unique_ptr<rtpheaderparser> parser (Rtpheaderparser::create ());
{
BOOL B = parser->isrtcp (packet, length);
if (b)
{
return NULL;
}
}
BOOL Bparser = parser->parse (packet, length, &header);
if (!bparser)
{
return NULL;
}
size_t Nrtpheaderlen = header.headerlength;
uint8_t * Pbufpayload = (uint8_t *) (packet + Nrtpheaderlen);
size_t nlenpayload = Length-nrtpheaderlen;
//------------------------------------------------------------
Rtpdepacketizer::P arsedpayload payload;
Depacketizer_->parse (&payload, Pbufpayload, nlenpayload);
Expect_eq (Kvideoframekey, Payload.frame_type);
Expect_eq (kRtpVideoH264, Payload.type.Video.codec);
Expect_true (Payload.type.Video.is_first_packet_in_frame);
Expect_eq (Kh264singlenalu, Payload.type.Video.codecHeader.H264.packetization_type);
Expect_eq (KIDR, Payload.type.Video.codecHeader.H264.nalu_type);
Const rtpvideoheaderh264& H264 = payload.type.Video.codecHeader.H264;
Switch (payload.type.Video.codecHeader.H264.packetization_type)
{
Case Kh264singlenalu:
{
{
This->clear_vector (PVECTORBUF);
Pvectorbuf = new Std::vector<rtc::buffer *>;
if (M_RTCPBUF)
{
Delete m_rtcpbuf;
M_rtcpbuf = NULL;
}
}
Rtc::buffer * tempbuf = NULL;
if (H264.nalu_type = = Kslice)
{
Tempbuf = Create_h264buffer_4byte ();
}
Else
{
Tempbuf = Create_h264buffer ();
}
Tempbuf->appenddata (Payload.payload, payload.payload_length); = =//tempbuf->appenddata (pbufpayload, nlenpayload);
Pvectorbuf->push_back (TEMPBUF);
Std::vector<rtc::buffer *> * pvectorbuftemp = pvectorbuf;
Pvectorbuf = NULL;
M_rtcpbuf = NULL;
return pvectorbuftemp;
}
Break
Case KH264FUA:
{
Rtc::buffer * tempbuf = Create_h264buffer ();
Rtc::buffer * tempbuf = NULL;
if (H264.nalu_type = = Kslice)
{
Tempbuf = Create_h264buffer_4byte ();
}
Else
{
Tempbuf = Create_h264buffer ();
}
if (1)
{
_nalu * Pfuindicator = (_nalu *) (payload.payload);
_fuheader * Pfuheader = (_fuheader *) (payload.payload+1);
_nalu * PfuIndicator1 = (_nalu *) (pbufpayload);
_fuheader * PfuHeader1 = (_fuheader *) (pbufpayload + 1);
M_rtcpbuf->appenddata (Payload.payload, payload.payload_length);
if (header.markerbit)
if (pfuheader1->e | | header.markerbit)
{
Tempbuf = M_rtcpbuf;
Pvectorbuf->push_back (M_RTCPBUF);
M_rtcpbuf = NULL;
Std::vector<rtc::buffer *> * pvectorbuftemp = pvectorbuf;
Pvectorbuf = NULL;
return pvectorbuftemp;
}
}
}
Break
Case KH264STAPA:
{
{
This->clear_vector (PVECTORBUF);
Pvectorbuf = new Std::vector<rtc::buffer *>;
if (M_RTCPBUF)
{
Delete m_rtcpbuf;
M_rtcpbuf = NULL;
}
}
LOG (INFO) << "Kh264stapa";
for (size_t i = 0; i < h264.nalus_length; ++i)
{
H264.nalus[i].type;
LOG (INFO) << "H264.nalus[i].offset" << h264.nalus[i].offset;
LOG (INFO) << "h264.nalus[i].size" << h264.nalus[i].size;
uint8_t Startcode[4] = {0}; STARTCODE[3] = 0x01;
Rtc::buffer * ptempbuf = new Rtc::buffer (Startcode, 4);
Ptempbuf->appenddata (Payload.payload + h264.nalus[i].offset, h264.nalus[i].size);
Pvectorbuf->push_back (PTEMPBUF);
}
Std::vector<rtc::buffer *> * pvectorbuftemp = pvectorbuf;
Pvectorbuf = NULL;
return pvectorbuftemp;
}
Break
Default
{
LOG (INFO) << "Default:";
}
Break
}
return NULL;
}
Private
Rtc::buffer * M_RTCPBUF;
Std::vector<rtc::buffer *> * PVECTORBUF;
Public
Std::unique_ptr<rtpdepacketizer> Depacketizer_;
};