Bug 1036049: Support H.264 STAP-A depacketization in webrtc r=ehugg

This commit is contained in:
Randell Jesup 2014-07-11 01:48:14 -04:00
parent 046773aaca
commit cc394c3799
2 changed files with 85 additions and 0 deletions

View File

@ -10,6 +10,13 @@
#include <string.h> // memcpy
#ifdef WIN32
#include <winsock2.h>
#endif
#ifdef WEBRTC_LINUX
#include <netinet/in.h>
#endif
#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
#include "webrtc/system_wrappers/interface/trace.h"
@ -55,6 +62,29 @@ int RtpFormatH264::NextPacket(uint8_t* buffer,
uint8_t header = payload_data_[0];
uint8_t type = header & kH264NAL_TypeMask;
if (payload_size_ <= max_payload_len_) {
//#define TEST_STAP_A
#ifdef TEST_STAP_A
static uint8_t sps_buffer[256];
static uint32_t sps_size;
if (type == kH264NALU_SPS) {
sps_buffer[0] = kH264NALU_STAPA;
*(reinterpret_cast<uint16_t*>(&sps_buffer[1])) = htons(payload_size_); // include NAL byte
memcpy(&sps_buffer[1 + sizeof(uint16_t)], payload_data_, payload_size_);
sps_size = 1 + sizeof(uint16_t) + payload_size_;
*bytes_to_send = 0;
return -1;
} else if (type == kH264NALU_PPS && sps_size != 0) {
// Send a STAP-A of SPS/PPS
*(reinterpret_cast<uint16_t*>(&sps_buffer[sps_size])) = htons(payload_size_);
memcpy(&sps_buffer[sps_size + sizeof(uint16_t)], payload_data_, payload_size_);
memcpy(buffer, sps_buffer, sps_size + 2 + payload_size_);
*bytes_to_send = sps_size + 2 + payload_size_;
sps_size = 0;
*last_packet = false;
return 0;
}
#endif
// single NAL_UNIT
*bytes_to_send = payload_size_;
// TODO(jesup) - this doesn't work correctly for Mode 0.

View File

@ -13,6 +13,13 @@
#include <assert.h>
#include <string.h>
#ifdef WIN32
#include <winsock2.h>
#endif
#ifdef WEBRTC_LINUX
#include <netinet/in.h>
#endif
#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
@ -265,7 +272,55 @@ int32_t RTPReceiverVideo::ReceiveH264Codec(WebRtcRTPHeader* rtp_header,
RTPVideoHeaderH264* h264_header = &rtp_header->type.Video.codecHeader.H264;
h264_header->nalu_header = original_nal_header;
h264_header->single_nalu = false;
} else if (nal_type == RtpFormatH264::kH264NALU_STAPA) {
payload = const_cast<uint8_t*> (payload_data) +
RtpFormatH264::kH264NALHeaderLengthInBytes;
size_t size = payload_data_length -
RtpFormatH264::kH264NALHeaderLengthInBytes;
uint32_t timestamp = rtp_header->header.timestamp;
rtp_header->type.Video.codec = kRtpVideoH264;
rtp_header->type.Video.isFirstPacket = true;
RTPVideoHeaderH264* h264_header = &rtp_header->type.Video.codecHeader.H264;
h264_header->single_nalu = true;
while (size > 0) {
payload_length = ntohs(*(reinterpret_cast<uint16_t*>(payload)));
// payload_length includes the NAL type byte
payload += sizeof(uint16_t); // points to NAL byte and then N bytes of NAL data
h264_header->nalu_header = payload[0];
switch (*payload & RtpFormatH264::kH264NAL_TypeMask) {
case RtpFormatH264::kH264NALU_SPS:
// TODO(jesup): Evil hack. see below
rtp_header->header.timestamp = timestamp - 20;
rtp_header->frameType = kVideoFrameKey;
break;
case RtpFormatH264::kH264NALU_PPS:
// TODO(jesup): Evil hack. see below
rtp_header->header.timestamp = timestamp - 10;
rtp_header->frameType = kVideoFrameKey;
break;
case RtpFormatH264::kH264NALU_IDR:
rtp_header->frameType = kVideoFrameKey;
break;
default:
rtp_header->frameType = kVideoFrameDelta;
break;
}
if (data_callback_->OnReceivedPayloadData(payload,
payload_length,
rtp_header) != 0) {
return -1;
}
payload += payload_length;
assert(size >= sizeof(uint16_t) + payload_length);
size -= sizeof(uint16_t) + payload_length;
}
return 0;
} else {
// single NALU
payload = const_cast<uint8_t*> (payload_data);
payload_length = payload_data_length;