Delete RTPSender::BuildRtpHeader function
and all dependencies BUG=webrtc:5565 Review-Url: https://codereview.webrtc.org/2399463009 Cr-Commit-Position: refs/heads/master@{#14682}
This commit is contained in:
parent
061ea0df03
commit
b6f1fb5337
@ -92,11 +92,7 @@ RTPSender::RTPSender(
|
||||
payload_type_(-1),
|
||||
payload_type_map_(),
|
||||
rtp_header_extension_map_(),
|
||||
transmission_time_offset_(0),
|
||||
absolute_send_time_(0),
|
||||
rotation_(kVideoRotation_0),
|
||||
video_rotation_active_(false),
|
||||
transport_sequence_number_(0),
|
||||
playout_delay_active_(false),
|
||||
packet_history_(clock),
|
||||
// Statistics
|
||||
@ -184,36 +180,6 @@ uint32_t RTPSender::NackOverheadRate() const {
|
||||
return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
|
||||
}
|
||||
|
||||
int32_t RTPSender::SetTransmissionTimeOffset(int32_t transmission_time_offset) {
|
||||
if (transmission_time_offset > (0x800000 - 1) ||
|
||||
transmission_time_offset < -(0x800000 - 1)) { // Word24.
|
||||
return -1;
|
||||
}
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
transmission_time_offset_ = transmission_time_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t RTPSender::SetAbsoluteSendTime(uint32_t absolute_send_time) {
|
||||
if (absolute_send_time > 0xffffff) { // UWord24.
|
||||
return -1;
|
||||
}
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
absolute_send_time_ = absolute_send_time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RTPSender::SetVideoRotation(VideoRotation rotation) {
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
rotation_ = rotation;
|
||||
}
|
||||
|
||||
int32_t RTPSender::SetTransportSequenceNumber(uint16_t sequence_number) {
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
transport_sequence_number_ = sequence_number;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type,
|
||||
uint8_t id) {
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
@ -868,20 +834,6 @@ size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) {
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
bool RTPSender::SendToNetwork(uint8_t* buffer,
|
||||
size_t payload_length,
|
||||
size_t rtp_header_length,
|
||||
int64_t capture_time_ms,
|
||||
StorageType storage,
|
||||
RtpPacketSender::Priority priority) {
|
||||
size_t length = payload_length + rtp_header_length;
|
||||
std::unique_ptr<RtpPacketToSend> packet(
|
||||
new RtpPacketToSend(&rtp_header_extension_map_, length));
|
||||
RTC_CHECK(packet->Parse(buffer, length));
|
||||
packet->set_capture_time_ms(capture_time_ms);
|
||||
return SendToNetwork(std::move(packet), storage, priority);
|
||||
}
|
||||
|
||||
bool RTPSender::SendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
|
||||
StorageType storage,
|
||||
RtpPacketSender::Priority priority) {
|
||||
@ -1041,44 +993,6 @@ void RTPSender::GetDataCounters(StreamDataCounters* rtp_stats,
|
||||
*rtx_stats = rtx_rtp_stats_;
|
||||
}
|
||||
|
||||
size_t RTPSender::CreateRtpHeader(uint8_t* header,
|
||||
int8_t payload_type,
|
||||
uint32_t ssrc,
|
||||
bool marker_bit,
|
||||
uint32_t timestamp,
|
||||
uint16_t sequence_number,
|
||||
const std::vector<uint32_t>& csrcs) const {
|
||||
header[0] = 0x80; // version 2.
|
||||
header[1] = static_cast<uint8_t>(payload_type);
|
||||
if (marker_bit) {
|
||||
header[1] |= kRtpMarkerBitMask; // Marker bit is set.
|
||||
}
|
||||
ByteWriter<uint16_t>::WriteBigEndian(header + 2, sequence_number);
|
||||
ByteWriter<uint32_t>::WriteBigEndian(header + 4, timestamp);
|
||||
ByteWriter<uint32_t>::WriteBigEndian(header + 8, ssrc);
|
||||
int32_t rtp_header_length = kRtpHeaderLength;
|
||||
|
||||
if (csrcs.size() > 0) {
|
||||
uint8_t* ptr = &header[rtp_header_length];
|
||||
for (size_t i = 0; i < csrcs.size(); ++i) {
|
||||
ByteWriter<uint32_t>::WriteBigEndian(ptr, csrcs[i]);
|
||||
ptr += 4;
|
||||
}
|
||||
header[0] = (header[0] & 0xf0) | csrcs.size();
|
||||
|
||||
// Update length of header.
|
||||
rtp_header_length += sizeof(uint32_t) * csrcs.size();
|
||||
}
|
||||
|
||||
uint16_t len =
|
||||
BuildRtpHeaderExtension(header + rtp_header_length, marker_bit);
|
||||
if (len > 0) {
|
||||
header[0] |= 0x10; // Set extension bit.
|
||||
rtp_header_length += len;
|
||||
}
|
||||
return rtp_header_length;
|
||||
}
|
||||
|
||||
std::unique_ptr<RtpPacketToSend> RTPSender::AllocatePacket() const {
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
std::unique_ptr<RtpPacketToSend> packet(
|
||||
@ -1113,293 +1027,6 @@ bool RTPSender::AssignSequenceNumber(RtpPacketToSend* packet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t RTPSender::BuildRTPheader(uint8_t* data_buffer,
|
||||
int8_t payload_type,
|
||||
bool marker_bit,
|
||||
uint32_t capture_timestamp,
|
||||
int64_t capture_time_ms,
|
||||
bool timestamp_provided,
|
||||
bool inc_sequence_number) {
|
||||
return BuildRtpHeader(data_buffer, payload_type, marker_bit,
|
||||
capture_timestamp, capture_time_ms);
|
||||
}
|
||||
|
||||
int32_t RTPSender::BuildRtpHeader(uint8_t* data_buffer,
|
||||
int8_t payload_type,
|
||||
bool marker_bit,
|
||||
uint32_t rtp_timestamp,
|
||||
int64_t capture_time_ms) {
|
||||
assert(payload_type >= 0);
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
if (!sending_media_)
|
||||
return -1;
|
||||
|
||||
last_rtp_timestamp_ = rtp_timestamp;
|
||||
last_timestamp_time_ms_ = clock_->TimeInMilliseconds();
|
||||
uint32_t sequence_number = sequence_number_++;
|
||||
capture_time_ms_ = capture_time_ms;
|
||||
last_packet_marker_bit_ = marker_bit;
|
||||
return CreateRtpHeader(data_buffer, payload_type, ssrc_, marker_bit,
|
||||
rtp_timestamp, sequence_number, csrcs_);
|
||||
}
|
||||
|
||||
uint16_t RTPSender::BuildRtpHeaderExtension(uint8_t* data_buffer,
|
||||
bool marker_bit) const {
|
||||
if (rtp_header_extension_map_.Size() <= 0) {
|
||||
return 0;
|
||||
}
|
||||
// RTP header extension, RFC 3550.
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | defined by profile | length |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | header extension |
|
||||
// | .... |
|
||||
//
|
||||
const uint32_t kPosLength = 2;
|
||||
const uint32_t kHeaderLength = kRtpOneByteHeaderLength;
|
||||
|
||||
// Add extension ID (0xBEDE).
|
||||
ByteWriter<uint16_t>::WriteBigEndian(data_buffer,
|
||||
kRtpOneByteHeaderExtensionId);
|
||||
|
||||
// Add extensions.
|
||||
uint16_t total_block_length = 0;
|
||||
|
||||
RTPExtensionType type = rtp_header_extension_map_.First();
|
||||
while (type != kRtpExtensionNone) {
|
||||
uint8_t block_length = 0;
|
||||
uint8_t* extension_data = &data_buffer[kHeaderLength + total_block_length];
|
||||
switch (type) {
|
||||
case kRtpExtensionTransmissionTimeOffset:
|
||||
block_length = BuildTransmissionTimeOffsetExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionAudioLevel:
|
||||
block_length = BuildAudioLevelExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionAbsoluteSendTime:
|
||||
block_length = BuildAbsoluteSendTimeExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionVideoRotation:
|
||||
block_length = BuildVideoRotationExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionTransportSequenceNumber:
|
||||
block_length = BuildTransportSequenceNumberExtension(
|
||||
extension_data, transport_sequence_number_);
|
||||
break;
|
||||
case kRtpExtensionPlayoutDelay: {
|
||||
PlayoutDelay playout_delay = playout_delay_oracle_.playout_delay();
|
||||
block_length = BuildPlayoutDelayExtension(
|
||||
extension_data, playout_delay.min_ms, playout_delay.max_ms);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
total_block_length += block_length;
|
||||
type = rtp_header_extension_map_.Next(type);
|
||||
}
|
||||
if (total_block_length == 0) {
|
||||
// No extension added.
|
||||
return 0;
|
||||
}
|
||||
// Add padding elements until we've filled a 32 bit block.
|
||||
size_t padding_bytes =
|
||||
RtpUtility::Word32Align(total_block_length) - total_block_length;
|
||||
if (padding_bytes > 0) {
|
||||
memset(&data_buffer[kHeaderLength + total_block_length], 0, padding_bytes);
|
||||
total_block_length += padding_bytes;
|
||||
}
|
||||
// Set header length (in number of Word32, header excluded).
|
||||
ByteWriter<uint16_t>::WriteBigEndian(data_buffer + kPosLength,
|
||||
total_block_length / 4);
|
||||
// Total added length.
|
||||
return kHeaderLength + total_block_length;
|
||||
}
|
||||
|
||||
uint8_t RTPSender::BuildTransmissionTimeOffsetExtension(
|
||||
uint8_t* data_buffer) const {
|
||||
// From RFC 5450: Transmission Time Offsets in RTP Streams.
|
||||
//
|
||||
// The transmission time is signaled to the receiver in-band using the
|
||||
// general mechanism for RTP header extensions [RFC5285]. The payload
|
||||
// of this extension (the transmitted value) is a 24-bit signed integer.
|
||||
// When added to the RTP timestamp of the packet, it represents the
|
||||
// "effective" RTP transmission time of the packet, on the RTP
|
||||
// timescale.
|
||||
//
|
||||
// The form of the transmission offset extension block:
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=2 | transmission offset |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
// Get id defined by user.
|
||||
uint8_t id;
|
||||
if (rtp_header_extension_map_.GetId(kRtpExtensionTransmissionTimeOffset,
|
||||
&id) != 0) {
|
||||
// Not registered.
|
||||
return 0;
|
||||
}
|
||||
size_t pos = 0;
|
||||
const uint8_t len = 2;
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
ByteWriter<int32_t, 3>::WriteBigEndian(data_buffer + pos,
|
||||
transmission_time_offset_);
|
||||
pos += 3;
|
||||
assert(pos == kTransmissionTimeOffsetLength);
|
||||
return kTransmissionTimeOffsetLength;
|
||||
}
|
||||
|
||||
uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const {
|
||||
// An RTP Header Extension for Client-to-Mixer Audio Level Indication
|
||||
//
|
||||
// https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
|
||||
//
|
||||
// The form of the audio level extension block:
|
||||
//
|
||||
// 0 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=0 |V| level |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
|
||||
// Get id defined by user.
|
||||
uint8_t id;
|
||||
if (rtp_header_extension_map_.GetId(kRtpExtensionAudioLevel, &id) != 0) {
|
||||
// Not registered.
|
||||
return 0;
|
||||
}
|
||||
size_t pos = 0;
|
||||
const uint8_t len = 0;
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
data_buffer[pos++] = (1 << 7) + 0; // Voice, 0 dBov.
|
||||
assert(pos == kAudioLevelLength);
|
||||
return kAudioLevelLength;
|
||||
}
|
||||
|
||||
uint8_t RTPSender::BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const {
|
||||
// Absolute send time in RTP streams.
|
||||
//
|
||||
// The absolute send time is signaled to the receiver in-band using the
|
||||
// general mechanism for RTP header extensions [RFC5285]. The payload
|
||||
// of this extension (the transmitted value) is a 24-bit unsigned integer
|
||||
// containing the sender's current time in seconds as a fixed point number
|
||||
// with 18 bits fractional part.
|
||||
//
|
||||
// The form of the absolute send time extension block:
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=2 | absolute send time |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
// Get id defined by user.
|
||||
uint8_t id;
|
||||
if (rtp_header_extension_map_.GetId(kRtpExtensionAbsoluteSendTime,
|
||||
&id) != 0) {
|
||||
// Not registered.
|
||||
return 0;
|
||||
}
|
||||
size_t pos = 0;
|
||||
const uint8_t len = 2;
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
ByteWriter<uint32_t, 3>::WriteBigEndian(data_buffer + pos,
|
||||
absolute_send_time_);
|
||||
pos += 3;
|
||||
assert(pos == kAbsoluteSendTimeLength);
|
||||
return kAbsoluteSendTimeLength;
|
||||
}
|
||||
|
||||
uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const {
|
||||
// Coordination of Video Orientation in RTP streams.
|
||||
//
|
||||
// Coordination of Video Orientation consists in signaling of the current
|
||||
// orientation of the image captured on the sender side to the receiver for
|
||||
// appropriate rendering and displaying.
|
||||
//
|
||||
// 0 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=0 |0 0 0 0 C F R R|
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
|
||||
// Get id defined by user.
|
||||
uint8_t id;
|
||||
if (rtp_header_extension_map_.GetId(kRtpExtensionVideoRotation, &id) != 0) {
|
||||
// Not registered.
|
||||
return 0;
|
||||
}
|
||||
size_t pos = 0;
|
||||
const uint8_t len = 0;
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
data_buffer[pos++] = ConvertVideoRotationToCVOByte(rotation_);
|
||||
assert(pos == kVideoRotationLength);
|
||||
return kVideoRotationLength;
|
||||
}
|
||||
|
||||
uint8_t RTPSender::BuildTransportSequenceNumberExtension(
|
||||
uint8_t* data_buffer,
|
||||
uint16_t sequence_number) const {
|
||||
// 0 1 2
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | L=1 |transport wide sequence number |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
// Get id defined by user.
|
||||
uint8_t id;
|
||||
if (rtp_header_extension_map_.GetId(kRtpExtensionTransportSequenceNumber,
|
||||
&id) != 0) {
|
||||
// Not registered.
|
||||
return 0;
|
||||
}
|
||||
size_t pos = 0;
|
||||
const uint8_t len = 1;
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
ByteWriter<uint16_t>::WriteBigEndian(data_buffer + pos, sequence_number);
|
||||
pos += 2;
|
||||
assert(pos == kTransportSequenceNumberLength);
|
||||
return kTransportSequenceNumberLength;
|
||||
}
|
||||
|
||||
uint8_t RTPSender::BuildPlayoutDelayExtension(
|
||||
uint8_t* data_buffer,
|
||||
uint16_t min_playout_delay_ms,
|
||||
uint16_t max_playout_delay_ms) const {
|
||||
RTC_DCHECK_LE(min_playout_delay_ms, kPlayoutDelayMaxMs);
|
||||
RTC_DCHECK_LE(max_playout_delay_ms, kPlayoutDelayMaxMs);
|
||||
RTC_DCHECK_LE(min_playout_delay_ms, max_playout_delay_ms);
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=2 | MIN delay | MAX delay |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
uint8_t id;
|
||||
if (rtp_header_extension_map_.GetId(kRtpExtensionPlayoutDelay, &id) != 0) {
|
||||
// Not registered.
|
||||
return 0;
|
||||
}
|
||||
size_t pos = 0;
|
||||
const uint8_t len = 2;
|
||||
// Convert MS to value to be sent on extension header.
|
||||
uint16_t min_playout = min_playout_delay_ms / kPlayoutDelayGranularityMs;
|
||||
uint16_t max_playout = max_playout_delay_ms / kPlayoutDelayGranularityMs;
|
||||
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
data_buffer[pos++] = min_playout >> 4;
|
||||
data_buffer[pos++] = ((min_playout & 0xf) << 4) | (max_playout >> 8);
|
||||
data_buffer[pos++] = max_playout & 0xff;
|
||||
assert(pos == kPlayoutDelayLength);
|
||||
return kPlayoutDelayLength;
|
||||
}
|
||||
|
||||
bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type,
|
||||
const uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
@ -1438,83 +1065,6 @@ bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type,
|
||||
return true;
|
||||
}
|
||||
|
||||
RTPSender::ExtensionStatus RTPSender::VerifyExtension(
|
||||
RTPExtensionType extension_type,
|
||||
uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
const RTPHeader& rtp_header,
|
||||
size_t extension_length_bytes,
|
||||
size_t* extension_offset) const {
|
||||
// Get id.
|
||||
uint8_t id = 0;
|
||||
if (rtp_header_extension_map_.GetId(extension_type, &id) != 0)
|
||||
return ExtensionStatus::kNotRegistered;
|
||||
|
||||
size_t block_pos = 0;
|
||||
if (!FindHeaderExtensionPosition(extension_type, rtp_packet,
|
||||
rtp_packet_length, rtp_header, &block_pos))
|
||||
return ExtensionStatus::kError;
|
||||
|
||||
// Verify first byte in block.
|
||||
const uint8_t first_block_byte = (id << 4) + (extension_length_bytes - 2);
|
||||
if (rtp_packet[block_pos] != first_block_byte)
|
||||
return ExtensionStatus::kError;
|
||||
|
||||
*extension_offset = block_pos;
|
||||
return ExtensionStatus::kOk;
|
||||
}
|
||||
|
||||
bool RTPSender::UpdateAudioLevel(uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
const RTPHeader& rtp_header,
|
||||
bool is_voiced,
|
||||
uint8_t dBov) const {
|
||||
size_t offset;
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
|
||||
switch (VerifyExtension(kRtpExtensionAudioLevel, rtp_packet,
|
||||
rtp_packet_length, rtp_header, kAudioLevelLength,
|
||||
&offset)) {
|
||||
case ExtensionStatus::kNotRegistered:
|
||||
return false;
|
||||
case ExtensionStatus::kError:
|
||||
LOG(LS_WARNING) << "Failed to update audio level.";
|
||||
return false;
|
||||
case ExtensionStatus::kOk:
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
|
||||
rtp_packet[offset + 1] = (is_voiced ? 0x80 : 0x00) + (dBov & 0x7f);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTPSender::UpdateVideoRotation(uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
const RTPHeader& rtp_header,
|
||||
VideoRotation rotation) const {
|
||||
size_t offset;
|
||||
rtc::CritScope lock(&send_critsect_);
|
||||
|
||||
switch (VerifyExtension(kRtpExtensionVideoRotation, rtp_packet,
|
||||
rtp_packet_length, rtp_header, kVideoRotationLength,
|
||||
&offset)) {
|
||||
case ExtensionStatus::kNotRegistered:
|
||||
return false;
|
||||
case ExtensionStatus::kError:
|
||||
LOG(LS_WARNING) << "Failed to update CVO.";
|
||||
return false;
|
||||
case ExtensionStatus::kOk:
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
|
||||
rtp_packet[offset + 1] = ConvertVideoRotationToCVOByte(rotation);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTPSender::UpdateTransportSequenceNumber(RtpPacketToSend* packet,
|
||||
int* packet_id) const {
|
||||
RTC_DCHECK(packet);
|
||||
|
||||
@ -112,66 +112,12 @@ class RTPSender {
|
||||
uint32_t* transport_frame_id_out);
|
||||
|
||||
// RTP header extension
|
||||
int32_t SetTransmissionTimeOffset(int32_t transmission_time_offset);
|
||||
int32_t SetAbsoluteSendTime(uint32_t absolute_send_time);
|
||||
void SetVideoRotation(VideoRotation rotation);
|
||||
int32_t SetTransportSequenceNumber(uint16_t sequence_number);
|
||||
|
||||
int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id);
|
||||
bool IsRtpHeaderExtensionRegistered(RTPExtensionType type);
|
||||
int32_t DeregisterRtpHeaderExtension(RTPExtensionType type);
|
||||
|
||||
size_t RtpHeaderExtensionLength() const;
|
||||
|
||||
uint16_t BuildRtpHeaderExtension(uint8_t* data_buffer, bool marker_bit) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
|
||||
uint8_t BuildTransmissionTimeOffsetExtension(uint8_t* data_buffer) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
uint8_t BuildVideoRotationExtension(uint8_t* data_buffer) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
uint8_t BuildTransportSequenceNumberExtension(uint8_t* data_buffer,
|
||||
uint16_t sequence_number) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
uint8_t BuildPlayoutDelayExtension(uint8_t* data_buffer,
|
||||
uint16_t min_playout_delay_ms,
|
||||
uint16_t max_playout_delay_ms) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
|
||||
// Verifies that the specified extension is registered, and that it is
|
||||
// present in rtp packet. If extension is not registered kNotRegistered is
|
||||
// returned. If extension cannot be found in the rtp header, or if it is
|
||||
// malformed, kError is returned. Otherwise *extension_offset is set to the
|
||||
// offset of the extension from the beginning of the rtp packet and kOk is
|
||||
// returned.
|
||||
enum class ExtensionStatus {
|
||||
kNotRegistered,
|
||||
kOk,
|
||||
kError,
|
||||
};
|
||||
ExtensionStatus VerifyExtension(RTPExtensionType extension_type,
|
||||
uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
const RTPHeader& rtp_header,
|
||||
size_t extension_length_bytes,
|
||||
size_t* extension_offset) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
|
||||
bool UpdateAudioLevel(uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
const RTPHeader& rtp_header,
|
||||
bool is_voiced,
|
||||
uint8_t dBov) const;
|
||||
|
||||
bool UpdateVideoRotation(uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
const RTPHeader& rtp_header,
|
||||
VideoRotation rotation) const;
|
||||
|
||||
bool TimeToSendPacket(uint16_t sequence_number,
|
||||
int64_t capture_time_ms,
|
||||
bool retransmission,
|
||||
@ -210,33 +156,12 @@ class RTPSender {
|
||||
// Return false if sending was turned off.
|
||||
bool AssignSequenceNumber(RtpPacketToSend* packet);
|
||||
|
||||
// Functions wrapping RTPSenderInterface.
|
||||
int32_t BuildRTPheader(uint8_t* data_buffer,
|
||||
int8_t payload_type,
|
||||
bool marker_bit,
|
||||
uint32_t capture_timestamp,
|
||||
int64_t capture_time_ms,
|
||||
bool timestamp_provided = true,
|
||||
bool inc_sequence_number = true);
|
||||
int32_t BuildRtpHeader(uint8_t* data_buffer,
|
||||
int8_t payload_type,
|
||||
bool marker_bit,
|
||||
uint32_t capture_timestamp,
|
||||
int64_t capture_time_ms);
|
||||
|
||||
size_t RtpHeaderLength() const;
|
||||
uint16_t AllocateSequenceNumber(uint16_t packets_to_send);
|
||||
size_t MaxPayloadLength() const;
|
||||
|
||||
uint32_t SSRC() const;
|
||||
|
||||
// Deprecated. Create RtpPacketToSend instead and use next function.
|
||||
bool SendToNetwork(uint8_t* data_buffer,
|
||||
size_t payload_length,
|
||||
size_t rtp_header_length,
|
||||
int64_t capture_time_ms,
|
||||
StorageType storage,
|
||||
RtpPacketSender::Priority priority);
|
||||
bool SendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
|
||||
StorageType storage,
|
||||
RtpPacketSender::Priority priority);
|
||||
@ -305,15 +230,6 @@ class RTPSender {
|
||||
int64_t capture_time_ms,
|
||||
int probe_cluster_id);
|
||||
|
||||
size_t CreateRtpHeader(uint8_t* header,
|
||||
int8_t payload_type,
|
||||
uint32_t ssrc,
|
||||
bool marker_bit,
|
||||
uint32_t timestamp,
|
||||
uint16_t sequence_number,
|
||||
const std::vector<uint32_t>& csrcs) const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(send_critsect_);
|
||||
|
||||
bool PrepareAndSendPacket(std::unique_ptr<RtpPacketToSend> packet,
|
||||
bool send_over_rtx,
|
||||
bool is_retransmit,
|
||||
@ -380,11 +296,7 @@ class RTPSender {
|
||||
std::map<int8_t, RtpUtility::Payload*> payload_type_map_;
|
||||
|
||||
RtpHeaderExtensionMap rtp_header_extension_map_ GUARDED_BY(send_critsect_);
|
||||
int32_t transmission_time_offset_;
|
||||
uint32_t absolute_send_time_;
|
||||
VideoRotation rotation_;
|
||||
bool video_rotation_active_;
|
||||
uint16_t transport_sequence_number_;
|
||||
|
||||
// Tracks the current request for playout delay limits from application
|
||||
// and decides whether the current RTP frame should include the playout
|
||||
|
||||
@ -41,9 +41,7 @@ const int kPayload = 100;
|
||||
const int kRtxPayload = 98;
|
||||
const uint32_t kTimestamp = 10;
|
||||
const uint16_t kSeqNum = 33;
|
||||
const int kTimeOffset = 22222;
|
||||
const int kMaxPacketLength = 1500;
|
||||
const uint32_t kAbsoluteSendTime = 0x00aabbcc;
|
||||
const uint8_t kAudioLevel = 0x5a;
|
||||
const uint16_t kTransportSequenceNumber = 0xaabbu;
|
||||
const uint8_t kAudioLevelExtensionId = 9;
|
||||
@ -51,7 +49,6 @@ const int kAudioPayload = 103;
|
||||
const uint64_t kStartTime = 123456789;
|
||||
const size_t kMaxPaddingSize = 224u;
|
||||
const int kVideoRotationExtensionId = 5;
|
||||
const VideoRotation kRotation = kVideoRotation_270;
|
||||
const size_t kGenericHeaderLength = 1;
|
||||
const uint8_t kPayloadData[] = {47, 11, 32, 93, 89};
|
||||
|
||||
@ -176,7 +173,6 @@ class RtpSenderTest : public ::testing::Test {
|
||||
int payload_;
|
||||
LoopbackTransportTest transport_;
|
||||
const bool kMarkerBit;
|
||||
uint8_t packet_[kMaxPacketLength];
|
||||
|
||||
void VerifyRTPHeaderCommon(const RTPHeader& rtp_header) {
|
||||
VerifyRTPHeaderCommon(rtp_header, kMarkerBit, 0);
|
||||
@ -198,16 +194,29 @@ class RtpSenderTest : public ::testing::Test {
|
||||
EXPECT_EQ(0U, rtp_header.paddingLength);
|
||||
}
|
||||
|
||||
std::unique_ptr<RtpPacketToSend> BuildRtpPacket(int payload_type,
|
||||
bool marker_bit,
|
||||
uint32_t timestamp,
|
||||
int64_t capture_time_ms) {
|
||||
auto packet = rtp_sender_->AllocatePacket();
|
||||
packet->SetPayloadType(payload_type);
|
||||
packet->SetMarker(marker_bit);
|
||||
packet->SetTimestamp(timestamp);
|
||||
packet->set_capture_time_ms(capture_time_ms);
|
||||
EXPECT_TRUE(rtp_sender_->AssignSequenceNumber(packet.get()));
|
||||
return packet;
|
||||
}
|
||||
|
||||
void SendPacket(int64_t capture_time_ms, int payload_length) {
|
||||
uint32_t timestamp = capture_time_ms * 90;
|
||||
int32_t rtp_length = rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, timestamp, capture_time_ms);
|
||||
ASSERT_GE(rtp_length, 0);
|
||||
auto packet =
|
||||
BuildRtpPacket(kPayload, kMarkerBit, timestamp, capture_time_ms);
|
||||
packet->AllocatePayload(payload_length);
|
||||
|
||||
// Packet should be stored in a send bucket.
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(
|
||||
packet_, payload_length, rtp_length, capture_time_ms,
|
||||
kAllowRetransmission, RtpPacketSender::kNormalPriority));
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
||||
kAllowRetransmission,
|
||||
RtpPacketSender::kNormalPriority));
|
||||
}
|
||||
|
||||
void SendGenericPayload() {
|
||||
@ -250,14 +259,6 @@ class RtpSenderVideoTest : public RtpSenderTest {
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(data, len);
|
||||
|
||||
webrtc::RTPHeader rtp_header;
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, expect_cvo /* marker_bit */, kTimestamp, 0));
|
||||
if (expect_cvo) {
|
||||
ASSERT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionLength(),
|
||||
length);
|
||||
} else {
|
||||
ASSERT_EQ(kRtpHeaderSize, length);
|
||||
}
|
||||
ASSERT_TRUE(rtp_parser.Parse(&rtp_header, map));
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
EXPECT_EQ(payload_, rtp_header.payloadType);
|
||||
@ -470,134 +471,6 @@ TEST_F(RtpSenderTestWithoutPacer, AssignSequenceNumberSetPaddingTimestamps) {
|
||||
EXPECT_EQ(kTimestamp, padding_packet.Timestamp());
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacket) {
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize, length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, nullptr);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header);
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_FALSE(rtp_header.extension.hasTransmissionTimeOffset);
|
||||
EXPECT_FALSE(rtp_header.extension.hasAbsoluteSendTime);
|
||||
EXPECT_FALSE(rtp_header.extension.hasAudioLevel);
|
||||
EXPECT_EQ(0, rtp_header.extension.transmissionTimeOffset);
|
||||
EXPECT_EQ(0u, rtp_header.extension.absoluteSendTime);
|
||||
EXPECT_FALSE(rtp_header.extension.voiceActivity);
|
||||
EXPECT_EQ(0u, rtp_header.extension.audioLevel);
|
||||
EXPECT_EQ(0u, rtp_header.extension.videoRotation);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer,
|
||||
BuildRTPPacketWithTransmissionOffsetExtension) {
|
||||
EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kTimeOffset));
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionTransmissionTimeOffset,
|
||||
kTransmissionTimeOffsetExtensionId));
|
||||
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionLength(), length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionTransmissionTimeOffset,
|
||||
kTransmissionTimeOffsetExtensionId);
|
||||
const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header);
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
|
||||
EXPECT_EQ(kTimeOffset, rtp_header.extension.transmissionTimeOffset);
|
||||
|
||||
// Parse without map extension
|
||||
webrtc::RTPHeader rtp_header2;
|
||||
const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header2);
|
||||
VerifyRTPHeaderCommon(rtp_header2);
|
||||
EXPECT_EQ(length, rtp_header2.headerLength);
|
||||
EXPECT_FALSE(rtp_header2.extension.hasTransmissionTimeOffset);
|
||||
EXPECT_EQ(0, rtp_header2.extension.transmissionTimeOffset);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer,
|
||||
BuildRTPPacketWithNegativeTransmissionOffsetExtension) {
|
||||
const int kNegTimeOffset = -500;
|
||||
EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kNegTimeOffset));
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionTransmissionTimeOffset,
|
||||
kTransmissionTimeOffsetExtensionId));
|
||||
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionLength(), length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionTransmissionTimeOffset,
|
||||
kTransmissionTimeOffsetExtensionId);
|
||||
const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header);
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
|
||||
EXPECT_EQ(kNegTimeOffset, rtp_header.extension.transmissionTimeOffset);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAbsoluteSendTimeExtension) {
|
||||
EXPECT_EQ(0, rtp_sender_->SetAbsoluteSendTime(kAbsoluteSendTime));
|
||||
EXPECT_EQ(
|
||||
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
||||
kAbsoluteSendTimeExtensionId));
|
||||
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionLength(), length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId);
|
||||
const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header);
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime);
|
||||
EXPECT_EQ(kAbsoluteSendTime, rtp_header.extension.absoluteSendTime);
|
||||
|
||||
// Parse without map extension
|
||||
webrtc::RTPHeader rtp_header2;
|
||||
const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header2);
|
||||
VerifyRTPHeaderCommon(rtp_header2);
|
||||
EXPECT_EQ(length, rtp_header2.headerLength);
|
||||
EXPECT_FALSE(rtp_header2.extension.hasAbsoluteSendTime);
|
||||
EXPECT_EQ(0u, rtp_header2.extension.absoluteSendTime);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer, SendsPacketsWithTransportSequenceNumber) {
|
||||
rtp_sender_.reset(new RTPSender(
|
||||
false, &fake_clock_, &transport_, nullptr,
|
||||
@ -652,204 +525,6 @@ TEST_F(RtpSenderTestWithoutPacer, OnSendPacketUpdated) {
|
||||
SendGenericPayload();
|
||||
}
|
||||
|
||||
// Test CVO header extension is only set when marker bit is true.
|
||||
TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithVideoRotation_MarkerBit) {
|
||||
rtp_sender_->SetVideoRotation(kRotation);
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||
EXPECT_TRUE(rtp_sender_->ActivateCVORtpHeaderExtension());
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionVideoRotation, kVideoRotationExtensionId);
|
||||
|
||||
size_t length = static_cast<size_t>(
|
||||
rtp_sender_->BuildRtpHeader(packet_, kPayload, true, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionLength(), length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
ASSERT_TRUE(rtp_parser.Parse(&rtp_header, &map));
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_TRUE(rtp_header.extension.hasVideoRotation);
|
||||
EXPECT_EQ(kRotation, rtp_header.extension.videoRotation);
|
||||
}
|
||||
|
||||
// Test CVO header extension is not set when marker bit is false.
|
||||
TEST_F(RtpSenderTestWithoutPacer,
|
||||
DISABLED_BuildRTPPacketWithVideoRotation_NoMarkerBit) {
|
||||
rtp_sender_->SetVideoRotation(kRotation);
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||
EXPECT_TRUE(rtp_sender_->ActivateCVORtpHeaderExtension());
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionVideoRotation, kVideoRotationExtensionId);
|
||||
|
||||
size_t length = static_cast<size_t>(
|
||||
rtp_sender_->BuildRtpHeader(packet_, kPayload, false, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize, length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
ASSERT_TRUE(rtp_parser.Parse(&rtp_header, &map));
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header, false);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_FALSE(rtp_header.extension.hasVideoRotation);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAudioLevelExtension) {
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
|
||||
kAudioLevelExtensionId));
|
||||
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionLength(), length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
// Updating audio level is done in RTPSenderAudio, so simulate it here.
|
||||
rtp_parser.Parse(&rtp_header);
|
||||
rtp_sender_->UpdateAudioLevel(packet_, length, rtp_header, true, kAudioLevel);
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
|
||||
const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header);
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_TRUE(rtp_header.extension.hasAudioLevel);
|
||||
EXPECT_TRUE(rtp_header.extension.voiceActivity);
|
||||
EXPECT_EQ(kAudioLevel, rtp_header.extension.audioLevel);
|
||||
|
||||
// Parse without map extension
|
||||
webrtc::RTPHeader rtp_header2;
|
||||
const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header2);
|
||||
VerifyRTPHeaderCommon(rtp_header2);
|
||||
EXPECT_EQ(length, rtp_header2.headerLength);
|
||||
EXPECT_FALSE(rtp_header2.extension.hasAudioLevel);
|
||||
EXPECT_FALSE(rtp_header2.extension.voiceActivity);
|
||||
EXPECT_EQ(0u, rtp_header2.extension.audioLevel);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer,
|
||||
BuildRTPPacketWithCSRCAndAudioLevelExtension) {
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
|
||||
kAudioLevelExtensionId));
|
||||
std::vector<uint32_t> csrcs;
|
||||
csrcs.push_back(0x23456789);
|
||||
rtp_sender_->SetCsrcs(csrcs);
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
// Updating audio level is done in RTPSenderAudio, so simulate it here.
|
||||
rtp_parser.Parse(&rtp_header);
|
||||
EXPECT_TRUE(rtp_sender_->UpdateAudioLevel(packet_, length, rtp_header, true,
|
||||
kAudioLevel));
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
|
||||
const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header);
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header, kMarkerBit, csrcs.size());
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_TRUE(rtp_header.extension.hasAudioLevel);
|
||||
EXPECT_TRUE(rtp_header.extension.voiceActivity);
|
||||
EXPECT_EQ(kAudioLevel, rtp_header.extension.audioLevel);
|
||||
EXPECT_EQ(1u, rtp_header.numCSRCs);
|
||||
EXPECT_EQ(csrcs[0], rtp_header.arrOfCSRCs[0]);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithHeaderExtensions) {
|
||||
EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kTimeOffset));
|
||||
EXPECT_EQ(0, rtp_sender_->SetAbsoluteSendTime(kAbsoluteSendTime));
|
||||
EXPECT_EQ(0,
|
||||
rtp_sender_->SetTransportSequenceNumber(kTransportSequenceNumber));
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionTransmissionTimeOffset,
|
||||
kTransmissionTimeOffsetExtensionId));
|
||||
EXPECT_EQ(
|
||||
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
||||
kAbsoluteSendTimeExtensionId));
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
|
||||
kAudioLevelExtensionId));
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionTransportSequenceNumber,
|
||||
kTransportSequenceNumberExtensionId));
|
||||
|
||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||
ASSERT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionLength(), length);
|
||||
|
||||
// Verify
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
// Updating audio level is done in RTPSenderAudio, so simulate it here.
|
||||
rtp_parser.Parse(&rtp_header);
|
||||
rtp_sender_->UpdateAudioLevel(packet_, length, rtp_header, true, kAudioLevel);
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionTransmissionTimeOffset,
|
||||
kTransmissionTimeOffsetExtensionId);
|
||||
map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId);
|
||||
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
|
||||
map.Register(kRtpExtensionTransportSequenceNumber,
|
||||
kTransportSequenceNumberExtensionId);
|
||||
const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header);
|
||||
ASSERT_FALSE(rtp_parser.RTCP());
|
||||
VerifyRTPHeaderCommon(rtp_header);
|
||||
EXPECT_EQ(length, rtp_header.headerLength);
|
||||
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
|
||||
EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime);
|
||||
EXPECT_TRUE(rtp_header.extension.hasAudioLevel);
|
||||
EXPECT_TRUE(rtp_header.extension.hasTransportSequenceNumber);
|
||||
EXPECT_EQ(kTimeOffset, rtp_header.extension.transmissionTimeOffset);
|
||||
EXPECT_EQ(kAbsoluteSendTime, rtp_header.extension.absoluteSendTime);
|
||||
EXPECT_TRUE(rtp_header.extension.voiceActivity);
|
||||
EXPECT_EQ(kAudioLevel, rtp_header.extension.audioLevel);
|
||||
EXPECT_EQ(kTransportSequenceNumber,
|
||||
rtp_header.extension.transportSequenceNumber);
|
||||
|
||||
// Parse without map extension
|
||||
webrtc::RTPHeader rtp_header2;
|
||||
const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr);
|
||||
|
||||
ASSERT_TRUE(valid_rtp_header2);
|
||||
VerifyRTPHeaderCommon(rtp_header2);
|
||||
EXPECT_EQ(length, rtp_header2.headerLength);
|
||||
EXPECT_FALSE(rtp_header2.extension.hasTransmissionTimeOffset);
|
||||
EXPECT_FALSE(rtp_header2.extension.hasAbsoluteSendTime);
|
||||
EXPECT_FALSE(rtp_header2.extension.hasAudioLevel);
|
||||
EXPECT_FALSE(rtp_header2.extension.hasTransportSequenceNumber);
|
||||
|
||||
EXPECT_EQ(0, rtp_header2.extension.transmissionTimeOffset);
|
||||
EXPECT_EQ(0u, rtp_header2.extension.absoluteSendTime);
|
||||
EXPECT_FALSE(rtp_header2.extension.voiceActivity);
|
||||
EXPECT_EQ(0u, rtp_header2.extension.audioLevel);
|
||||
EXPECT_EQ(0u, rtp_header2.extension.transportSequenceNumber);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTest, SendsPacketsWithTransportSequenceNumber) {
|
||||
rtp_sender_.reset(new RTPSender(
|
||||
false, &fake_clock_, &transport_, &mock_paced_sender_,
|
||||
@ -908,14 +583,13 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
|
||||
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
||||
kAbsoluteSendTimeExtensionId));
|
||||
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
||||
int rtp_length_int = rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, capture_time_ms);
|
||||
ASSERT_NE(-1, rtp_length_int);
|
||||
size_t rtp_length = static_cast<size_t>(rtp_length_int);
|
||||
auto packet =
|
||||
BuildRtpPacket(kPayload, kMarkerBit, kTimestamp, capture_time_ms);
|
||||
size_t packet_size = packet->size();
|
||||
|
||||
// Packet should be stored in a send bucket.
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(packet_, 0, rtp_length,
|
||||
capture_time_ms, kAllowRetransmission,
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
||||
kAllowRetransmission,
|
||||
RtpPacketSender::kNormalPriority));
|
||||
|
||||
EXPECT_EQ(0, transport_.packets_sent_);
|
||||
@ -928,10 +602,10 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
|
||||
|
||||
// Process send bucket. Packet should now be sent.
|
||||
EXPECT_EQ(1, transport_.packets_sent_);
|
||||
EXPECT_EQ(rtp_length, transport_.last_sent_packet_len_);
|
||||
EXPECT_EQ(packet_size, transport_.last_sent_packet_len_);
|
||||
// Parse sent packet.
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(transport_.last_sent_packet_,
|
||||
rtp_length);
|
||||
packet_size);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionTransmissionTimeOffset,
|
||||
@ -961,14 +635,13 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
|
||||
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
|
||||
kAbsoluteSendTimeExtensionId));
|
||||
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
||||
int rtp_length_int = rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, kTimestamp, capture_time_ms);
|
||||
ASSERT_NE(-1, rtp_length_int);
|
||||
size_t rtp_length = static_cast<size_t>(rtp_length_int);
|
||||
auto packet =
|
||||
BuildRtpPacket(kPayload, kMarkerBit, kTimestamp, capture_time_ms);
|
||||
size_t packet_size = packet->size();
|
||||
|
||||
// Packet should be stored in a send bucket.
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(packet_, 0, rtp_length,
|
||||
capture_time_ms, kAllowRetransmission,
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
||||
kAllowRetransmission,
|
||||
RtpPacketSender::kNormalPriority));
|
||||
|
||||
EXPECT_EQ(0, transport_.packets_sent_);
|
||||
@ -979,7 +652,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
|
||||
const int kStoredTimeInMs = 100;
|
||||
fake_clock_.AdvanceTimeMilliseconds(kStoredTimeInMs);
|
||||
|
||||
EXPECT_EQ(rtp_length_int, rtp_sender_->ReSendPacket(kSeqNum));
|
||||
EXPECT_EQ(static_cast<int>(packet_size), rtp_sender_->ReSendPacket(kSeqNum));
|
||||
EXPECT_EQ(0, transport_.packets_sent_);
|
||||
|
||||
rtp_sender_->TimeToSendPacket(kSeqNum, capture_time_ms, false,
|
||||
@ -987,11 +660,11 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
|
||||
|
||||
// Process send bucket. Packet should now be sent.
|
||||
EXPECT_EQ(1, transport_.packets_sent_);
|
||||
EXPECT_EQ(rtp_length, transport_.last_sent_packet_len_);
|
||||
EXPECT_EQ(packet_size, transport_.last_sent_packet_len_);
|
||||
|
||||
// Parse sent packet.
|
||||
webrtc::RtpUtility::RtpHeaderParser rtp_parser(transport_.last_sent_packet_,
|
||||
rtp_length);
|
||||
packet_size);
|
||||
webrtc::RTPHeader rtp_header;
|
||||
RtpHeaderExtensionMap map;
|
||||
map.Register(kRtpExtensionTransmissionTimeOffset,
|
||||
@ -1042,15 +715,14 @@ TEST_F(RtpSenderTest, SendPadding) {
|
||||
webrtc::RTPHeader rtp_header;
|
||||
|
||||
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
|
||||
int rtp_length_int = rtp_sender_->BuildRtpHeader(
|
||||
packet_, kPayload, kMarkerBit, timestamp, capture_time_ms);
|
||||
auto packet =
|
||||
BuildRtpPacket(kPayload, kMarkerBit, timestamp, capture_time_ms);
|
||||
const uint32_t media_packet_timestamp = timestamp;
|
||||
ASSERT_NE(-1, rtp_length_int);
|
||||
size_t rtp_length = static_cast<size_t>(rtp_length_int);
|
||||
size_t packet_size = packet->size();
|
||||
|
||||
// Packet should be stored in a send bucket.
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(packet_, 0, rtp_length,
|
||||
capture_time_ms, kAllowRetransmission,
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
||||
kAllowRetransmission,
|
||||
RtpPacketSender::kNormalPriority));
|
||||
|
||||
int total_packets_sent = 0;
|
||||
@ -1100,27 +772,25 @@ TEST_F(RtpSenderTest, SendPadding) {
|
||||
|
||||
// Send a regular video packet again.
|
||||
capture_time_ms = fake_clock_.TimeInMilliseconds();
|
||||
rtp_length_int = rtp_sender_->BuildRtpHeader(packet_, kPayload, kMarkerBit,
|
||||
timestamp, capture_time_ms);
|
||||
ASSERT_NE(-1, rtp_length_int);
|
||||
rtp_length = static_cast<size_t>(rtp_length_int);
|
||||
packet = BuildRtpPacket(kPayload, kMarkerBit, timestamp, capture_time_ms);
|
||||
packet_size = packet->size();
|
||||
|
||||
EXPECT_CALL(mock_paced_sender_,
|
||||
InsertPacket(RtpPacketSender::kNormalPriority, _, _, _, _, _));
|
||||
|
||||
// Packet should be stored in a send bucket.
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(packet_, 0, rtp_length,
|
||||
capture_time_ms, kAllowRetransmission,
|
||||
EXPECT_TRUE(rtp_sender_->SendToNetwork(std::move(packet),
|
||||
kAllowRetransmission,
|
||||
RtpPacketSender::kNormalPriority));
|
||||
|
||||
rtp_sender_->TimeToSendPacket(seq_num, capture_time_ms, false,
|
||||
PacketInfo::kNotAProbe);
|
||||
// Process send bucket.
|
||||
EXPECT_EQ(++total_packets_sent, transport_.packets_sent_);
|
||||
EXPECT_EQ(rtp_length, transport_.last_sent_packet_len_);
|
||||
EXPECT_EQ(packet_size, transport_.last_sent_packet_len_);
|
||||
// Parse sent packet.
|
||||
ASSERT_TRUE(
|
||||
rtp_parser->Parse(transport_.last_sent_packet_, rtp_length, &rtp_header));
|
||||
ASSERT_TRUE(rtp_parser->Parse(transport_.last_sent_packet_, packet_size,
|
||||
&rtp_header));
|
||||
|
||||
// Verify sequence number and timestamp.
|
||||
EXPECT_EQ(seq_num, rtp_header.sequenceNumber);
|
||||
@ -1759,6 +1429,7 @@ TEST_F(RtpSenderTestWithoutPacer, RespectsNackBitrateLimit) {
|
||||
|
||||
// Verify that all packets of a frame have CVO byte set.
|
||||
TEST_F(RtpSenderVideoTest, SendVideoWithCVO) {
|
||||
uint8_t kFrame[kMaxPacketLength];
|
||||
RTPVideoHeader hdr = {0};
|
||||
hdr.rotation = kVideoRotation_90;
|
||||
|
||||
@ -1771,7 +1442,7 @@ TEST_F(RtpSenderVideoTest, SendVideoWithCVO) {
|
||||
rtp_sender_->RtpHeaderExtensionLength());
|
||||
|
||||
rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload,
|
||||
kTimestamp, 0, packet_, sizeof(packet_), nullptr,
|
||||
kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
|
||||
&hdr);
|
||||
|
||||
RtpHeaderExtensionMap map;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user