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

View File

@ -130,8 +130,8 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
VideoCodecInformation *codec_info = NULL, VideoCodecInformation *codec_info = NULL,
const RTPVideoTypeHeader * rtp_type_hdr = NULL); const RTPVideoTypeHeader * rtp_type_hdr = NULL);
int32_t SendPadData(int8_t payload_type, int BuildPaddingPacket(uint8_t* packet, int header_length, int32_t bytes);
uint32_t capture_timestamp, bool SendPadData(int8_t payload_type, uint32_t capture_timestamp,
int64_t capture_time_ms, int32_t bytes); int64_t capture_time_ms, int32_t bytes);
// RTP header extension // RTP header extension
int32_t SetTransmissionTimeOffset( int32_t SetTransmissionTimeOffset(
@ -260,9 +260,14 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
RtpVideoCodecTypes *video_type); RtpVideoCodecTypes *video_type);
private: 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); void UpdateNACKBitRate(const uint32_t bytes, const uint32_t now);
int32_t SendPaddingAccordingToBitrate(int8_t payload_type, bool SendPaddingAccordingToBitrate(int8_t payload_type,
uint32_t capture_timestamp, uint32_t capture_timestamp,
int64_t capture_time_ms); int64_t capture_time_ms);
@ -314,9 +319,10 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
uint16_t sequence_number_rtx_; uint16_t sequence_number_rtx_;
bool ssrc_forced_; bool ssrc_forced_;
uint32_t ssrc_; uint32_t ssrc_;
uint32_t time_stamp_; uint32_t timestamp_;
uint8_t csrcs_; int64_t capture_timestamp_;
uint32_t csrc_[kRtpCsrcSize]; uint8_t num_csrcs_;
uint32_t csrcs_[kRtpCsrcSize];
bool include_csrcs_; bool include_csrcs_;
RtxMode rtx_; RtxMode rtx_;
uint32_t ssrc_rtx_; uint32_t ssrc_rtx_;