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:
parent
de98478965
commit
a817962bab
@ -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) {
|
||||
|
@ -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_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user