Parsing of transport wide sequence number rtp extension header.
Plus some refactoring to correctly handle padding. BUG=4311 R=mflodman@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/45429004 Cr-Commit-Position: refs/heads/master@{#8757} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8757 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1e6925274a
commit
3093390479
@ -20,6 +20,19 @@ int OutStream::Rewind() { return -1; }
|
||||
|
||||
StreamDataCounters::StreamDataCounters() : first_packet_time_ms(-1) {}
|
||||
|
||||
RTPHeaderExtension::RTPHeaderExtension()
|
||||
: hasTransmissionTimeOffset(false),
|
||||
transmissionTimeOffset(0),
|
||||
hasAbsoluteSendTime(false),
|
||||
absoluteSendTime(0),
|
||||
hasTransportSequenceNumber(false),
|
||||
transportSequenceNumber(0),
|
||||
hasAudioLevel(false),
|
||||
audioLevel(0),
|
||||
hasVideoRotation(false),
|
||||
videoRotation(0) {
|
||||
}
|
||||
|
||||
RTPHeader::RTPHeader()
|
||||
: markerBit(false),
|
||||
payloadType(0),
|
||||
|
@ -792,20 +792,14 @@ struct PacketTime {
|
||||
};
|
||||
|
||||
struct RTPHeaderExtension {
|
||||
RTPHeaderExtension()
|
||||
: hasTransmissionTimeOffset(false),
|
||||
transmissionTimeOffset(0),
|
||||
hasAbsoluteSendTime(false),
|
||||
absoluteSendTime(0),
|
||||
hasAudioLevel(false),
|
||||
audioLevel(0),
|
||||
hasVideoRotation(false),
|
||||
videoRotation(0) {}
|
||||
RTPHeaderExtension();
|
||||
|
||||
bool hasTransmissionTimeOffset;
|
||||
int32_t transmissionTimeOffset;
|
||||
bool hasAbsoluteSendTime;
|
||||
uint32_t absoluteSendTime;
|
||||
bool hasTransportSequenceNumber;
|
||||
uint16_t transportSequenceNumber;
|
||||
|
||||
// Audio Level includes both level in dBov and voiced/unvoiced bit. See:
|
||||
// https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
|
||||
|
@ -79,7 +79,8 @@ enum RTPExtensionType {
|
||||
kRtpExtensionTransmissionTimeOffset,
|
||||
kRtpExtensionAudioLevel,
|
||||
kRtpExtensionAbsoluteSendTime,
|
||||
kRtpExtensionVideoRotation
|
||||
kRtpExtensionVideoRotation,
|
||||
kRtpExtensionTransportSequenceNumber,
|
||||
};
|
||||
|
||||
enum RTCPAppSubTypes
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -119,6 +120,8 @@ size_t RtpHeaderExtensionMap::GetTotalLengthInBytes() const {
|
||||
if (length > 0) {
|
||||
length += kRtpOneByteHeaderLength;
|
||||
}
|
||||
// Pad up to nearest 32bit word.
|
||||
length = RtpUtility::Word32Align(length);
|
||||
return length;
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,10 @@ const uint16_t kRtpOneByteHeaderExtensionId = 0xBEDE;
|
||||
|
||||
const size_t kRtpOneByteHeaderLength = 4;
|
||||
const size_t kTransmissionTimeOffsetLength = 4;
|
||||
const size_t kAudioLevelLength = 4;
|
||||
const size_t kAudioLevelLength = 2;
|
||||
const size_t kAbsoluteSendTimeLength = 4;
|
||||
const size_t kVideoRotationLength = 4;
|
||||
const size_t kVideoRotationLength = 2;
|
||||
const size_t kTransportSequenceNumberLength = 3;
|
||||
|
||||
struct HeaderExtension {
|
||||
HeaderExtension(RTPExtensionType extension_type)
|
||||
@ -46,13 +47,16 @@ struct HeaderExtension {
|
||||
case kRtpExtensionVideoRotation:
|
||||
length = kVideoRotationLength;
|
||||
break;
|
||||
case kRtpExtensionTransportSequenceNumber:
|
||||
length = kTransportSequenceNumberLength;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
const RTPExtensionType type;
|
||||
uint8_t length;
|
||||
const RTPExtensionType type;
|
||||
uint8_t length;
|
||||
};
|
||||
|
||||
class RtpHeaderExtensionMap {
|
||||
|
@ -128,6 +128,7 @@ RTPSender::RTPSender(int32_t id,
|
||||
transmission_time_offset_(0),
|
||||
absolute_send_time_(0),
|
||||
rotation_(kVideoRotation_0),
|
||||
transport_sequence_number_(0),
|
||||
// NACK.
|
||||
nack_byte_count_times_(),
|
||||
nack_byte_count_(),
|
||||
@ -255,6 +256,12 @@ void RTPSender::SetVideoRotation(VideoRotation rotation) {
|
||||
rotation_ = rotation;
|
||||
}
|
||||
|
||||
int32_t RTPSender::SetTransportSequenceNumber(uint16_t sequence_number) {
|
||||
CriticalSectionScoped cs(send_critsect_.get());
|
||||
transport_sequence_number_ = sequence_number;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type,
|
||||
uint8_t id) {
|
||||
CriticalSectionScoped cs(send_critsect_.get());
|
||||
@ -1180,24 +1187,23 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer,
|
||||
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(
|
||||
data_buffer + kHeaderLength + total_block_length);
|
||||
block_length = BuildTransmissionTimeOffsetExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionAudioLevel:
|
||||
block_length = BuildAudioLevelExtension(
|
||||
data_buffer + kHeaderLength + total_block_length);
|
||||
block_length = BuildAudioLevelExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionAbsoluteSendTime:
|
||||
block_length = BuildAbsoluteSendTimeExtension(
|
||||
data_buffer + kHeaderLength + total_block_length);
|
||||
block_length = BuildAbsoluteSendTimeExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionVideoRotation:
|
||||
if (marker_bit) {
|
||||
block_length = BuildVideoRotationExtension(
|
||||
data_buffer + kHeaderLength + total_block_length);
|
||||
}
|
||||
if (marker_bit)
|
||||
block_length = BuildVideoRotationExtension(extension_data);
|
||||
break;
|
||||
case kRtpExtensionTransportSequenceNumber:
|
||||
block_length = BuildTransportSequenceNumberExtension(extension_data);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
@ -1209,8 +1215,14 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer,
|
||||
// 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).
|
||||
assert(total_block_length % 4 == 0);
|
||||
RtpUtility::AssignUWord16ToBuffer(data_buffer + kPosLength,
|
||||
total_block_length / 4);
|
||||
// Total added length.
|
||||
@ -1260,16 +1272,12 @@ uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const {
|
||||
//
|
||||
// The form of the audio level 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=0 |V| level | 0x00 | 0x00 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// 0 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=0 |V| level |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// Note that we always include 2 pad bytes, which will result in legal and
|
||||
// correctly parsed RTP, but may be a bit wasteful if more short extensions
|
||||
// are implemented. Right now the pad bytes would anyway be required at end
|
||||
// of the extension block, so it makes no difference.
|
||||
|
||||
// Get id defined by user.
|
||||
uint8_t id;
|
||||
@ -1281,9 +1289,6 @@ uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const {
|
||||
const uint8_t len = 0;
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
data_buffer[pos++] = (1 << 7) + 0; // Voice, 0 dBov.
|
||||
data_buffer[pos++] = 0; // Padding.
|
||||
data_buffer[pos++] = 0; // Padding.
|
||||
// kAudioLevelLength is including pad bytes.
|
||||
assert(pos == kAudioLevelLength);
|
||||
return kAudioLevelLength;
|
||||
}
|
||||
@ -1324,20 +1329,15 @@ uint8_t RTPSender::BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const {
|
||||
uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const {
|
||||
// Coordination of Video Orientation in RTP streams.
|
||||
//
|
||||
// Coordination of Video Orientation consists in signalling of the current
|
||||
// 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 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=0 |V|0 0 0 0 C F R R| 0x00 | 0x00 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// Note that we always include 2 pad bytes, which will result in legal and
|
||||
// correctly parsed RTP, but may be a bit wasteful if more short extensions
|
||||
// are implemented. Right now the pad bytes would anyway be required at end
|
||||
// of the extension block, so it makes no difference.
|
||||
// 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.
|
||||
@ -1350,12 +1350,35 @@ uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const {
|
||||
const uint8_t len = 0;
|
||||
data_buffer[pos++] = (id << 4) + len;
|
||||
data_buffer[pos++] = ConvertVideoRotationToCVOByte(rotation_);
|
||||
data_buffer[pos++] = 0; // padding
|
||||
data_buffer[pos++] = 0; // padding
|
||||
assert(pos == kVideoRotationLength);
|
||||
return kVideoRotationLength;
|
||||
}
|
||||
|
||||
uint8_t RTPSender::BuildTransportSequenceNumberExtension(
|
||||
uint8_t* data_buffer) 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;
|
||||
RtpUtility::AssignUWord16ToBuffer(data_buffer + pos,
|
||||
transport_sequence_number_);
|
||||
pos += 2;
|
||||
assert(pos == kTransportSequenceNumberLength);
|
||||
return kTransportSequenceNumberLength;
|
||||
}
|
||||
|
||||
bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type,
|
||||
const uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
|
@ -153,6 +153,7 @@ class RTPSender : public RTPSenderInterface {
|
||||
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);
|
||||
virtual bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override;
|
||||
@ -166,6 +167,7 @@ class RTPSender : public RTPSenderInterface {
|
||||
uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const;
|
||||
uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const;
|
||||
uint8_t BuildVideoRotationExtension(uint8_t* data_buffer) const;
|
||||
uint8_t BuildTransportSequenceNumberExtension(uint8_t* data_buffer) const;
|
||||
|
||||
bool UpdateAudioLevel(uint8_t* rtp_packet,
|
||||
size_t rtp_packet_length,
|
||||
@ -376,6 +378,7 @@ class RTPSender : public RTPSenderInterface {
|
||||
int32_t transmission_time_offset_;
|
||||
uint32_t absolute_send_time_;
|
||||
VideoRotation rotation_;
|
||||
uint16_t transport_sequence_number_;
|
||||
|
||||
// NACK
|
||||
uint32_t nack_byte_count_times_[NACK_BYTECOUNT_SIZE];
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
|
||||
#include "webrtc/system_wrappers/interface/stl_util.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||
#include "webrtc/test/mock_transport.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
@ -33,6 +34,7 @@ namespace webrtc {
|
||||
namespace {
|
||||
const int kTransmissionTimeOffsetExtensionId = 1;
|
||||
const int kAbsoluteSendTimeExtensionId = 14;
|
||||
const int kTransportSequenceNumberExtensionId = 13;
|
||||
const int kPayload = 100;
|
||||
const uint32_t kTimestamp = 10;
|
||||
const uint16_t kSeqNum = 33;
|
||||
@ -40,6 +42,7 @@ 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;
|
||||
const int kAudioPayload = 103;
|
||||
const uint64_t kStartTime = 123456789;
|
||||
@ -210,7 +213,8 @@ TEST_F(RtpSenderTest, RegisterRtpAbsoluteSendTimeHeaderExtension) {
|
||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength,
|
||||
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||
kAbsoluteSendTimeLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||
kRtpExtensionAbsoluteSendTime));
|
||||
@ -221,8 +225,9 @@ TEST_F(RtpSenderTest, RegisterRtpAudioLevelHeaderExtension) {
|
||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAudioLevelLength,
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(
|
||||
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kAudioLevelLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||
kRtpExtensionAudioLevel));
|
||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
@ -232,38 +237,46 @@ TEST_F(RtpSenderTest, RegisterRtpHeaderExtensions) {
|
||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength,
|
||||
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||
kTransmissionTimeOffsetLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
||||
kAbsoluteSendTimeLength, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||
kTransmissionTimeOffsetLength +
|
||||
kAbsoluteSendTimeLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
||||
kAbsoluteSendTimeLength + kAudioLevelLength,
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(RtpUtility::Word32Align(
|
||||
kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
||||
kAbsoluteSendTimeLength + kAudioLevelLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
||||
kAbsoluteSendTimeLength + kAudioLevelLength +
|
||||
kVideoRotationLength,
|
||||
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||
kTransmissionTimeOffsetLength +
|
||||
kAbsoluteSendTimeLength +
|
||||
kAudioLevelLength + kVideoRotationLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
|
||||
// Deregister starts.
|
||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||
kRtpExtensionTransmissionTimeOffset));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength +
|
||||
kAudioLevelLength + kVideoRotationLength,
|
||||
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||
kAbsoluteSendTimeLength +
|
||||
kAudioLevelLength + kVideoRotationLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||
kRtpExtensionAbsoluteSendTime));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAudioLevelLength + kVideoRotationLength,
|
||||
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||
kAudioLevelLength + kVideoRotationLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||
kRtpExtensionAudioLevel));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kVideoRotationLength,
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(
|
||||
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kVideoRotationLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(
|
||||
0, rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionVideoRotation));
|
||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
@ -273,8 +286,9 @@ TEST_F(RtpSenderTest, RegisterRtpVideoRotationHeaderExtension) {
|
||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kVideoRotationLength,
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(
|
||||
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kVideoRotationLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(
|
||||
0, rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionVideoRotation));
|
||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
@ -500,12 +514,17 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithAudioLevelExtension) {
|
||||
TEST_F(RtpSenderTest, 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));
|
||||
@ -525,6 +544,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
||||
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);
|
||||
@ -534,9 +555,12 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
||||
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_EQ(kAudioLevel + 0x80u, rtp_header.extension.audioLevel);
|
||||
EXPECT_EQ(kTransportSequenceNumber,
|
||||
rtp_header.extension.transportSequenceNumber);
|
||||
|
||||
// Parse without map extension
|
||||
webrtc::RTPHeader rtp_header2;
|
||||
@ -548,9 +572,12 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
||||
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_EQ(0u, rtp_header2.extension.audioLevel);
|
||||
EXPECT_EQ(0u, rtp_header2.extension.transportSequenceNumber);
|
||||
}
|
||||
|
||||
TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
|
||||
@ -1313,8 +1340,9 @@ TEST_F(RtpSenderVideoTest, SendVideoWithCVO) {
|
||||
|
||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||
EXPECT_EQ(kRtpOneByteHeaderLength + kVideoRotationLength,
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
EXPECT_EQ(
|
||||
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kVideoRotationLength),
|
||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||
|
||||
rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload,
|
||||
kTimestamp, 0, packet_, sizeof(packet_), NULL,
|
||||
|
@ -184,6 +184,13 @@ uint32_t BufferToUWord32(const uint8_t* dataBuffer) {
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t Word32Align(size_t size) {
|
||||
uint32_t remainder = size % 4;
|
||||
if (remainder != 0)
|
||||
return size + 4 - remainder;
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t pow2(uint8_t exp) {
|
||||
return 1 << exp;
|
||||
}
|
||||
@ -480,11 +487,11 @@ void RtpHeaderParser::ParseOneByteExtensionHeader(
|
||||
LOG(LS_WARNING) << "Incorrect audio level len: " << len;
|
||||
return;
|
||||
}
|
||||
// 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=0 |V| level | 0x00 | 0x00 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// 0 1
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ID | len=0 |V| level |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
|
||||
// Parse out the fields but only use it for debugging for now.
|
||||
@ -521,15 +528,33 @@ void RtpHeaderParser::ParseOneByteExtensionHeader(
|
||||
<< "Incorrect coordination of video coordination len: " << len;
|
||||
return;
|
||||
}
|
||||
// 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=0 |V|0 0 0 0 C F R R| 0x00 | 0x00 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// 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|
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
header.extension.hasVideoRotation = true;
|
||||
header.extension.videoRotation = ptr[0];
|
||||
break;
|
||||
}
|
||||
case kRtpExtensionTransportSequenceNumber: {
|
||||
if (len != 1) {
|
||||
LOG(LS_WARNING)
|
||||
<< "Incorrect peer connection sequence number len: " << len;
|
||||
return;
|
||||
}
|
||||
// 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 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
uint16_t sequence_number = ptr[0] << 8;
|
||||
sequence_number += ptr[1];
|
||||
header.extension.transportSequenceNumber = sequence_number;
|
||||
header.extension.hasTransportSequenceNumber = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(LS_WARNING) << "Extension type not implemented: " << type;
|
||||
return;
|
||||
|
@ -91,6 +91,9 @@ namespace RtpUtility {
|
||||
*/
|
||||
uint32_t BufferToUWord32(const uint8_t* dataBuffer);
|
||||
|
||||
// Round up to the nearest size that is a multiple of 4.
|
||||
size_t Word32Align(size_t size);
|
||||
|
||||
class RtpHeaderParser {
|
||||
public:
|
||||
RtpHeaderParser(const uint8_t* rtpData, size_t rtpDataLength);
|
||||
|
Loading…
Reference in New Issue
Block a user