Refactor padding and rtp header functionality.

BUG=1837
R=pbos@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/1611004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4172 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2013-06-04 13:47:36 +00:00
parent de98478965
commit a817962bab
2 changed files with 117 additions and 92 deletions

View File

@ -22,6 +22,9 @@
namespace webrtc {
// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
const int kMaxPaddingLength = 224;
namespace {
const char* FrameTypeToString(const FrameType frame_type) {
@ -57,11 +60,11 @@ RTPSender::RTPSender(const int32_t id, const bool audio, Clock *clock,
packets_sent_(0), payload_bytes_sent_(0), start_time_stamp_forced_(false),
start_time_stamp_(0), ssrc_db_(*SSRCDatabase::GetSSRCDatabase()),
remote_ssrc_(0), sequence_number_forced_(false), ssrc_forced_(false),
time_stamp_(0), csrcs_(0), csrc_(), include_csrcs_(true),
timestamp_(0), num_csrcs_(0), csrcs_(), include_csrcs_(true),
rtx_(kRtxOff), payload_type_rtx_(-1) {
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
memset(csrc_, 0, sizeof(csrc_));
memset(csrcs_, 0, sizeof(csrcs_));
// We need to seed the random generator.
srand(static_cast<uint32_t>(clock_->TimeInMilliseconds()));
ssrc_ = ssrc_db_.CreateSSRC(); // Can't be 0.
@ -375,7 +378,7 @@ int32_t RTPSender::SendOutgoingData(
if (frame_type == kFrameEmpty) {
return SendPaddingAccordingToBitrate(payload_type, capture_timestamp,
capture_time_ms);
capture_time_ms) ? 0 : -1;
}
return video_->SendVideo(video_type, frame_type, payload_type,
capture_timestamp, capture_time_ms, payload_data,
@ -384,7 +387,7 @@ int32_t RTPSender::SendOutgoingData(
}
}
int32_t RTPSender::SendPaddingAccordingToBitrate(
bool RTPSender::SendPaddingAccordingToBitrate(
int8_t payload_type, uint32_t capture_timestamp,
int64_t capture_time_ms) {
// Current bitrate since last estimate(1 second) averaged with the
@ -392,7 +395,7 @@ int32_t RTPSender::SendPaddingAccordingToBitrate(
uint32_t current_bitrate = BitrateNow();
int bitrate_diff = target_send_bitrate_ * 1000 - current_bitrate;
if (bitrate_diff <= 0) {
return 0;
return true;
}
int bytes = 0;
if (current_bitrate == 0) {
@ -409,54 +412,59 @@ int32_t RTPSender::SendPaddingAccordingToBitrate(
return SendPadData(payload_type, capture_timestamp, capture_time_ms, bytes);
}
int32_t RTPSender::SendPadData(
int8_t payload_type, uint32_t capture_timestamp,
int64_t capture_time_ms, int32_t bytes) {
// Drop this packet if we're not sending media packets.
if (!sending_media_) {
int RTPSender::BuildPaddingPacket(uint8_t* packet, int header_length,
int32_t bytes) {
int padding_bytes_in_packet = kMaxPaddingLength;
if (bytes < kMaxPaddingLength) {
// Round to the nearest multiple of 32.
padding_bytes_in_packet = (bytes + 16) & 0xffe0;
}
if (padding_bytes_in_packet < 32) {
// Sanity don't send empty packets.
return 0;
}
// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
int max_length = 224;
packet[0] |= 0x20; // Set padding bit.
int32_t *data =
reinterpret_cast<int32_t *>(&(packet[header_length]));
// Fill data buffer with random data.
for (int j = 0; j < (padding_bytes_in_packet >> 2); ++j) {
data[j] = rand(); // NOLINT
}
// Set number of padding bytes in the last byte of the packet.
packet[header_length + padding_bytes_in_packet - 1] = padding_bytes_in_packet;
return padding_bytes_in_packet;
}
bool RTPSender::SendPadData(int8_t payload_type, uint32_t capture_timestamp,
int64_t capture_time_ms, int32_t bytes) {
// Drop this packet if we're not sending media packets.
if (!sending_media_) {
return true;
}
uint8_t data_buffer[IP_PACKET_SIZE];
for (; bytes > 0; bytes -= max_length) {
int padding_bytes_in_packet = max_length;
if (bytes < max_length) {
padding_bytes_in_packet = (bytes + 16) & 0xffe0; // Keep our modulus 32.
}
if (padding_bytes_in_packet < 32) {
// Sanity don't send empty packets.
break;
}
for (; bytes > 0; bytes -= kMaxPaddingLength) {
// Correct seq num, timestamp and payload type.
int header_length = BuildRTPheader(
data_buffer, payload_type, false, // No markerbit.
capture_timestamp, true, // Timestamp provided.
true); // Increment sequence number.
data_buffer[0] |= 0x20; // Set padding bit.
int32_t *data =
reinterpret_cast<int32_t *>(&(data_buffer[header_length]));
// Fill data buffer with random data.
for (int j = 0; j < (padding_bytes_in_packet >> 2); ++j) {
data[j] = rand(); // NOLINT
}
// Set number of padding bytes in the last byte of the packet.
data_buffer[header_length + padding_bytes_in_packet - 1] =
padding_bytes_in_packet;
int header_length = BuildRTPheader(data_buffer,
payload_type,
false, // No markerbit.
capture_timestamp,
true, // Timestamp provided.
true); // Increment sequence number.
int padding_bytes_in_packet = BuildPaddingPacket(data_buffer, header_length,
bytes);
// Send the packet.
if (0 > SendToNetwork(data_buffer, padding_bytes_in_packet, header_length,
capture_time_ms, kDontRetransmit)) {
if (SendToNetwork(data_buffer, padding_bytes_in_packet, header_length,
capture_time_ms, kDontRetransmit) < 0) {
// Error sending the packet.
break;
}
}
if (bytes > 31) { // 31 due to our modulus 32.
// We did not manage to send all bytes.
return -1;
return false;
}
return 0;
return true;
}
void RTPSender::SetStorePacketsStatus(const bool enable,
@ -781,7 +789,7 @@ void RTPSender::ProcessBitrate() {
uint16_t RTPSender::RTPHeaderLength() const {
uint16_t rtp_header_length = 12;
if (include_csrcs_) {
rtp_header_length += sizeof(uint32_t) * csrcs_;
rtp_header_length += sizeof(uint32_t) * num_csrcs_;
}
rtp_header_length += RtpHeaderExtensionTotalLength();
return rtp_header_length;
@ -808,60 +816,71 @@ uint32_t RTPSender::Bytes() const {
return payload_bytes_sent_;
}
int32_t RTPSender::BuildRTPheader(
uint8_t *data_buffer, const int8_t payload_type,
const bool marker_bit, const uint32_t capture_time_stamp,
const bool time_stamp_provided, const bool inc_sequence_number) {
assert(payload_type >= 0);
CriticalSectionScoped cs(send_critsect_);
data_buffer[0] = static_cast<uint8_t>(0x80); // version 2.
data_buffer[1] = static_cast<uint8_t>(payload_type);
int RTPSender::CreateRTPHeader(
uint8_t* header, int8_t payload_type, uint32_t ssrc, bool marker_bit,
uint32_t timestamp, uint16_t sequence_number, const uint32_t* csrcs,
uint8_t num_csrcs) const {
header[0] = 0x80; // version 2.
header[1] = static_cast<uint8_t>(payload_type);
if (marker_bit) {
data_buffer[1] |= kRtpMarkerBitMask; // Marker bit is set.
header[1] |= kRtpMarkerBitMask; // Marker bit is set.
}
if (time_stamp_provided) {
time_stamp_ = start_time_stamp_ + capture_time_stamp;
} else {
// Make a unique time stamp.
// We can't inc by the actual time, since then we increase the risk of back
// timing.
time_stamp_++;
}
ModuleRTPUtility::AssignUWord16ToBuffer(data_buffer + 2, sequence_number_);
ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 4, time_stamp_);
ModuleRTPUtility::AssignUWord32ToBuffer(data_buffer + 8, ssrc_);
ModuleRTPUtility::AssignUWord16ToBuffer(header + 2, sequence_number);
ModuleRTPUtility::AssignUWord32ToBuffer(header + 4, timestamp);
ModuleRTPUtility::AssignUWord32ToBuffer(header + 8, ssrc);
int32_t rtp_header_length = 12;
// Add the CSRCs if any.
if (include_csrcs_ && csrcs_ > 0) {
if (csrcs_ > kRtpCsrcSize) {
if (num_csrcs > 0) {
if (num_csrcs > kRtpCsrcSize) {
// error
assert(false);
return -1;
}
uint8_t *ptr = &data_buffer[rtp_header_length];
for (uint32_t i = 0; i < csrcs_; ++i) {
ModuleRTPUtility::AssignUWord32ToBuffer(ptr, csrc_[i]);
uint8_t *ptr = &header[rtp_header_length];
for (int i = 0; i < num_csrcs; ++i) {
ModuleRTPUtility::AssignUWord32ToBuffer(ptr, csrcs[i]);
ptr += 4;
}
data_buffer[0] = (data_buffer[0] & 0xf0) | csrcs_;
header[0] = (header[0] & 0xf0) | num_csrcs;
// Update length of header.
rtp_header_length += sizeof(uint32_t) * csrcs_;
rtp_header_length += sizeof(uint32_t) * num_csrcs;
}
sequence_number_++; // Prepare for next packet.
uint16_t len = BuildRTPHeaderExtension(data_buffer + rtp_header_length);
if (len) {
data_buffer[0] |= 0x10; // Set extension bit.
uint16_t len = BuildRTPHeaderExtension(header + rtp_header_length);
if (len > 0) {
header[0] |= 0x10; // Set extension bit.
rtp_header_length += len;
}
return rtp_header_length;
}
uint16_t RTPSender::BuildRTPHeaderExtension(
uint8_t *data_buffer) const {
int32_t RTPSender::BuildRTPheader(
uint8_t *data_buffer, const int8_t payload_type,
const bool marker_bit, const uint32_t capture_timestamp,
const bool time_stamp_provided, const bool inc_sequence_number) {
assert(payload_type >= 0);
CriticalSectionScoped cs(send_critsect_);
if (time_stamp_provided) {
timestamp_ = start_time_stamp_ + capture_timestamp;
capture_timestamp_ = capture_timestamp;
} else {
// Make a unique time stamp.
// We can't inc by the actual time, since then we increase the risk of back
// timing.
timestamp_++;
}
uint32_t sequence_number = sequence_number_++;
int csrcs_length = 0;
if (include_csrcs_)
csrcs_length = num_csrcs_;
return CreateRTPHeader(data_buffer, payload_type, ssrc_, marker_bit,
timestamp_, sequence_number, csrcs_, csrcs_length);
}
uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer) const {
if (rtp_header_extension_map_.Size() <= 0) {
return 0;
}
@ -1145,7 +1164,7 @@ bool RTPSender::SendingMedia() const {
uint32_t RTPSender::Timestamp() const {
CriticalSectionScoped cs(send_critsect_);
return time_stamp_;
return timestamp_;
}
void RTPSender::SetStartTimestamp(uint32_t timestamp, bool force) {
@ -1208,18 +1227,18 @@ void RTPSender::SetCSRCs(const uint32_t arr_of_csrc[kRtpCsrcSize],
CriticalSectionScoped cs(send_critsect_);
for (int i = 0; i < arr_length; i++) {
csrc_[i] = arr_of_csrc[i];
csrcs_[i] = arr_of_csrc[i];
}
csrcs_ = arr_length;
num_csrcs_ = arr_length;
}
int32_t RTPSender::CSRCs(uint32_t arr_of_csrc[kRtpCsrcSize]) const {
assert(arr_of_csrc);
CriticalSectionScoped cs(send_critsect_);
for (int i = 0; i < csrcs_ && i < kRtpCsrcSize; i++) {
arr_of_csrc[i] = csrc_[i];
for (int i = 0; i < num_csrcs_ && i < kRtpCsrcSize; i++) {
arr_of_csrc[i] = csrcs_[i];
}
return csrcs_;
return num_csrcs_;
}
void RTPSender::SetSequenceNumber(uint16_t seq) {

View File

@ -130,9 +130,9 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
VideoCodecInformation *codec_info = NULL,
const RTPVideoTypeHeader * rtp_type_hdr = NULL);
int32_t SendPadData(int8_t payload_type,
uint32_t capture_timestamp,
int64_t capture_time_ms, int32_t bytes);
int BuildPaddingPacket(uint8_t* packet, int header_length, int32_t bytes);
bool SendPadData(int8_t payload_type, uint32_t capture_timestamp,
int64_t capture_time_ms, int32_t bytes);
// RTP header extension
int32_t SetTransmissionTimeOffset(
const int32_t transmission_time_offset);
@ -146,7 +146,7 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
uint16_t RtpHeaderExtensionTotalLength() const;
uint16_t BuildRTPHeaderExtension(uint8_t *data_buffer) const;
uint16_t BuildRTPHeaderExtension(uint8_t* data_buffer) const;
uint8_t BuildTransmissionTimeOffsetExtension(
uint8_t *data_buffer) const;
@ -260,11 +260,16 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
RtpVideoCodecTypes *video_type);
private:
int CreateRTPHeader(uint8_t* header, int8_t payload_type,
uint32_t ssrc, bool marker_bit,
uint32_t timestamp, uint16_t sequence_number,
const uint32_t* csrcs, uint8_t csrcs_length) const;
void UpdateNACKBitRate(const uint32_t bytes, const uint32_t now);
int32_t SendPaddingAccordingToBitrate(int8_t payload_type,
uint32_t capture_timestamp,
int64_t capture_time_ms);
bool SendPaddingAccordingToBitrate(int8_t payload_type,
uint32_t capture_timestamp,
int64_t capture_time_ms);
void BuildRtxPacket(uint8_t* buffer, uint16_t* length,
uint8_t* buffer_rtx);
@ -314,9 +319,10 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
uint16_t sequence_number_rtx_;
bool ssrc_forced_;
uint32_t ssrc_;
uint32_t time_stamp_;
uint8_t csrcs_;
uint32_t csrc_[kRtpCsrcSize];
uint32_t timestamp_;
int64_t capture_timestamp_;
uint8_t num_csrcs_;
uint32_t csrcs_[kRtpCsrcSize];
bool include_csrcs_;
RtxMode rtx_;
uint32_t ssrc_rtx_;