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:
@ -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) {
|
||||||
|
@ -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_;
|
||||||
|
Reference in New Issue
Block a user