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) {}
|
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()
|
RTPHeader::RTPHeader()
|
||||||
: markerBit(false),
|
: markerBit(false),
|
||||||
payloadType(0),
|
payloadType(0),
|
||||||
|
@ -792,20 +792,14 @@ struct PacketTime {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RTPHeaderExtension {
|
struct RTPHeaderExtension {
|
||||||
RTPHeaderExtension()
|
RTPHeaderExtension();
|
||||||
: hasTransmissionTimeOffset(false),
|
|
||||||
transmissionTimeOffset(0),
|
|
||||||
hasAbsoluteSendTime(false),
|
|
||||||
absoluteSendTime(0),
|
|
||||||
hasAudioLevel(false),
|
|
||||||
audioLevel(0),
|
|
||||||
hasVideoRotation(false),
|
|
||||||
videoRotation(0) {}
|
|
||||||
|
|
||||||
bool hasTransmissionTimeOffset;
|
bool hasTransmissionTimeOffset;
|
||||||
int32_t transmissionTimeOffset;
|
int32_t transmissionTimeOffset;
|
||||||
bool hasAbsoluteSendTime;
|
bool hasAbsoluteSendTime;
|
||||||
uint32_t absoluteSendTime;
|
uint32_t absoluteSendTime;
|
||||||
|
bool hasTransportSequenceNumber;
|
||||||
|
uint16_t transportSequenceNumber;
|
||||||
|
|
||||||
// Audio Level includes both level in dBov and voiced/unvoiced bit. See:
|
// Audio Level includes both level in dBov and voiced/unvoiced bit. See:
|
||||||
// https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
|
// https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
|
||||||
|
@ -79,7 +79,8 @@ enum RTPExtensionType {
|
|||||||
kRtpExtensionTransmissionTimeOffset,
|
kRtpExtensionTransmissionTimeOffset,
|
||||||
kRtpExtensionAudioLevel,
|
kRtpExtensionAudioLevel,
|
||||||
kRtpExtensionAbsoluteSendTime,
|
kRtpExtensionAbsoluteSendTime,
|
||||||
kRtpExtensionVideoRotation
|
kRtpExtensionVideoRotation,
|
||||||
|
kRtpExtensionTransportSequenceNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RTCPAppSubTypes
|
enum RTCPAppSubTypes
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
|
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
|
||||||
|
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -119,6 +120,8 @@ size_t RtpHeaderExtensionMap::GetTotalLengthInBytes() const {
|
|||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
length += kRtpOneByteHeaderLength;
|
length += kRtpOneByteHeaderLength;
|
||||||
}
|
}
|
||||||
|
// Pad up to nearest 32bit word.
|
||||||
|
length = RtpUtility::Word32Align(length);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +22,10 @@ const uint16_t kRtpOneByteHeaderExtensionId = 0xBEDE;
|
|||||||
|
|
||||||
const size_t kRtpOneByteHeaderLength = 4;
|
const size_t kRtpOneByteHeaderLength = 4;
|
||||||
const size_t kTransmissionTimeOffsetLength = 4;
|
const size_t kTransmissionTimeOffsetLength = 4;
|
||||||
const size_t kAudioLevelLength = 4;
|
const size_t kAudioLevelLength = 2;
|
||||||
const size_t kAbsoluteSendTimeLength = 4;
|
const size_t kAbsoluteSendTimeLength = 4;
|
||||||
const size_t kVideoRotationLength = 4;
|
const size_t kVideoRotationLength = 2;
|
||||||
|
const size_t kTransportSequenceNumberLength = 3;
|
||||||
|
|
||||||
struct HeaderExtension {
|
struct HeaderExtension {
|
||||||
HeaderExtension(RTPExtensionType extension_type)
|
HeaderExtension(RTPExtensionType extension_type)
|
||||||
@ -46,13 +47,16 @@ struct HeaderExtension {
|
|||||||
case kRtpExtensionVideoRotation:
|
case kRtpExtensionVideoRotation:
|
||||||
length = kVideoRotationLength;
|
length = kVideoRotationLength;
|
||||||
break;
|
break;
|
||||||
|
case kRtpExtensionTransportSequenceNumber:
|
||||||
|
length = kTransportSequenceNumberLength;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RTPExtensionType type;
|
const RTPExtensionType type;
|
||||||
uint8_t length;
|
uint8_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RtpHeaderExtensionMap {
|
class RtpHeaderExtensionMap {
|
||||||
|
@ -128,6 +128,7 @@ RTPSender::RTPSender(int32_t id,
|
|||||||
transmission_time_offset_(0),
|
transmission_time_offset_(0),
|
||||||
absolute_send_time_(0),
|
absolute_send_time_(0),
|
||||||
rotation_(kVideoRotation_0),
|
rotation_(kVideoRotation_0),
|
||||||
|
transport_sequence_number_(0),
|
||||||
// NACK.
|
// NACK.
|
||||||
nack_byte_count_times_(),
|
nack_byte_count_times_(),
|
||||||
nack_byte_count_(),
|
nack_byte_count_(),
|
||||||
@ -255,6 +256,12 @@ void RTPSender::SetVideoRotation(VideoRotation rotation) {
|
|||||||
rotation_ = 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,
|
int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type,
|
||||||
uint8_t id) {
|
uint8_t id) {
|
||||||
CriticalSectionScoped cs(send_critsect_.get());
|
CriticalSectionScoped cs(send_critsect_.get());
|
||||||
@ -1180,24 +1187,23 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer,
|
|||||||
RTPExtensionType type = rtp_header_extension_map_.First();
|
RTPExtensionType type = rtp_header_extension_map_.First();
|
||||||
while (type != kRtpExtensionNone) {
|
while (type != kRtpExtensionNone) {
|
||||||
uint8_t block_length = 0;
|
uint8_t block_length = 0;
|
||||||
|
uint8_t* extension_data = &data_buffer[kHeaderLength + total_block_length];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case kRtpExtensionTransmissionTimeOffset:
|
case kRtpExtensionTransmissionTimeOffset:
|
||||||
block_length = BuildTransmissionTimeOffsetExtension(
|
block_length = BuildTransmissionTimeOffsetExtension(extension_data);
|
||||||
data_buffer + kHeaderLength + total_block_length);
|
|
||||||
break;
|
break;
|
||||||
case kRtpExtensionAudioLevel:
|
case kRtpExtensionAudioLevel:
|
||||||
block_length = BuildAudioLevelExtension(
|
block_length = BuildAudioLevelExtension(extension_data);
|
||||||
data_buffer + kHeaderLength + total_block_length);
|
|
||||||
break;
|
break;
|
||||||
case kRtpExtensionAbsoluteSendTime:
|
case kRtpExtensionAbsoluteSendTime:
|
||||||
block_length = BuildAbsoluteSendTimeExtension(
|
block_length = BuildAbsoluteSendTimeExtension(extension_data);
|
||||||
data_buffer + kHeaderLength + total_block_length);
|
|
||||||
break;
|
break;
|
||||||
case kRtpExtensionVideoRotation:
|
case kRtpExtensionVideoRotation:
|
||||||
if (marker_bit) {
|
if (marker_bit)
|
||||||
block_length = BuildVideoRotationExtension(
|
block_length = BuildVideoRotationExtension(extension_data);
|
||||||
data_buffer + kHeaderLength + total_block_length);
|
break;
|
||||||
}
|
case kRtpExtensionTransportSequenceNumber:
|
||||||
|
block_length = BuildTransportSequenceNumberExtension(extension_data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -1209,8 +1215,14 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer,
|
|||||||
// No extension added.
|
// No extension added.
|
||||||
return 0;
|
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).
|
// Set header length (in number of Word32, header excluded).
|
||||||
assert(total_block_length % 4 == 0);
|
|
||||||
RtpUtility::AssignUWord16ToBuffer(data_buffer + kPosLength,
|
RtpUtility::AssignUWord16ToBuffer(data_buffer + kPosLength,
|
||||||
total_block_length / 4);
|
total_block_length / 4);
|
||||||
// Total added length.
|
// Total added length.
|
||||||
@ -1260,16 +1272,12 @@ uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const {
|
|||||||
//
|
//
|
||||||
// The form of the audio level extension block:
|
// The form of the audio level extension block:
|
||||||
//
|
//
|
||||||
// 0 1 2 3
|
// 0 1
|
||||||
// 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
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
// | ID | len=0 |V| level | 0x00 | 0x00 |
|
// | 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.
|
// Get id defined by user.
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
@ -1281,9 +1289,6 @@ uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const {
|
|||||||
const uint8_t len = 0;
|
const uint8_t len = 0;
|
||||||
data_buffer[pos++] = (id << 4) + len;
|
data_buffer[pos++] = (id << 4) + len;
|
||||||
data_buffer[pos++] = (1 << 7) + 0; // Voice, 0 dBov.
|
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);
|
assert(pos == kAudioLevelLength);
|
||||||
return 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 {
|
uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const {
|
||||||
// Coordination of Video Orientation in RTP streams.
|
// 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
|
// orientation of the image captured on the sender side to the receiver for
|
||||||
// appropriate rendering and displaying.
|
// appropriate rendering and displaying.
|
||||||
//
|
//
|
||||||
// 0 1 2 3
|
// 0 1
|
||||||
// 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
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
// | ID | len=0 |V|0 0 0 0 C F R R| 0x00 | 0x00 |
|
// | ID | len=0 |0 0 0 0 C F R R|
|
||||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
//
|
|
||||||
// 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.
|
// Get id defined by user.
|
||||||
@ -1350,12 +1350,35 @@ uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const {
|
|||||||
const uint8_t len = 0;
|
const uint8_t len = 0;
|
||||||
data_buffer[pos++] = (id << 4) + len;
|
data_buffer[pos++] = (id << 4) + len;
|
||||||
data_buffer[pos++] = ConvertVideoRotationToCVOByte(rotation_);
|
data_buffer[pos++] = ConvertVideoRotationToCVOByte(rotation_);
|
||||||
data_buffer[pos++] = 0; // padding
|
|
||||||
data_buffer[pos++] = 0; // padding
|
|
||||||
assert(pos == kVideoRotationLength);
|
assert(pos == kVideoRotationLength);
|
||||||
return 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,
|
bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type,
|
||||||
const uint8_t* rtp_packet,
|
const uint8_t* rtp_packet,
|
||||||
size_t rtp_packet_length,
|
size_t rtp_packet_length,
|
||||||
|
@ -153,6 +153,7 @@ class RTPSender : public RTPSenderInterface {
|
|||||||
int32_t SetTransmissionTimeOffset(int32_t transmission_time_offset);
|
int32_t SetTransmissionTimeOffset(int32_t transmission_time_offset);
|
||||||
int32_t SetAbsoluteSendTime(uint32_t absolute_send_time);
|
int32_t SetAbsoluteSendTime(uint32_t absolute_send_time);
|
||||||
void SetVideoRotation(VideoRotation rotation);
|
void SetVideoRotation(VideoRotation rotation);
|
||||||
|
int32_t SetTransportSequenceNumber(uint16_t sequence_number);
|
||||||
|
|
||||||
int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id);
|
int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id);
|
||||||
virtual bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override;
|
virtual bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override;
|
||||||
@ -166,6 +167,7 @@ class RTPSender : public RTPSenderInterface {
|
|||||||
uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const;
|
uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const;
|
||||||
uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const;
|
uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const;
|
||||||
uint8_t BuildVideoRotationExtension(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,
|
bool UpdateAudioLevel(uint8_t* rtp_packet,
|
||||||
size_t rtp_packet_length,
|
size_t rtp_packet_length,
|
||||||
@ -376,6 +378,7 @@ class RTPSender : public RTPSenderInterface {
|
|||||||
int32_t transmission_time_offset_;
|
int32_t transmission_time_offset_;
|
||||||
uint32_t absolute_send_time_;
|
uint32_t absolute_send_time_;
|
||||||
VideoRotation rotation_;
|
VideoRotation rotation_;
|
||||||
|
uint16_t transport_sequence_number_;
|
||||||
|
|
||||||
// NACK
|
// NACK
|
||||||
uint32_t nack_byte_count_times_[NACK_BYTECOUNT_SIZE];
|
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.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
|
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
|
||||||
#include "webrtc/system_wrappers/interface/stl_util.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/test/mock_transport.h"
|
||||||
#include "webrtc/typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ namespace webrtc {
|
|||||||
namespace {
|
namespace {
|
||||||
const int kTransmissionTimeOffsetExtensionId = 1;
|
const int kTransmissionTimeOffsetExtensionId = 1;
|
||||||
const int kAbsoluteSendTimeExtensionId = 14;
|
const int kAbsoluteSendTimeExtensionId = 14;
|
||||||
|
const int kTransportSequenceNumberExtensionId = 13;
|
||||||
const int kPayload = 100;
|
const int kPayload = 100;
|
||||||
const uint32_t kTimestamp = 10;
|
const uint32_t kTimestamp = 10;
|
||||||
const uint16_t kSeqNum = 33;
|
const uint16_t kSeqNum = 33;
|
||||||
@ -40,6 +42,7 @@ const int kTimeOffset = 22222;
|
|||||||
const int kMaxPacketLength = 1500;
|
const int kMaxPacketLength = 1500;
|
||||||
const uint32_t kAbsoluteSendTime = 0x00aabbcc;
|
const uint32_t kAbsoluteSendTime = 0x00aabbcc;
|
||||||
const uint8_t kAudioLevel = 0x5a;
|
const uint8_t kAudioLevel = 0x5a;
|
||||||
|
const uint16_t kTransportSequenceNumber = 0xaabbu;
|
||||||
const uint8_t kAudioLevelExtensionId = 9;
|
const uint8_t kAudioLevelExtensionId = 9;
|
||||||
const int kAudioPayload = 103;
|
const int kAudioPayload = 103;
|
||||||
const uint64_t kStartTime = 123456789;
|
const uint64_t kStartTime = 123456789;
|
||||||
@ -210,7 +213,8 @@ TEST_F(RtpSenderTest, RegisterRtpAbsoluteSendTimeHeaderExtension) {
|
|||||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength,
|
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||||
|
kAbsoluteSendTimeLength),
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||||
kRtpExtensionAbsoluteSendTime));
|
kRtpExtensionAbsoluteSendTime));
|
||||||
@ -221,8 +225,9 @@ TEST_F(RtpSenderTest, RegisterRtpAudioLevelHeaderExtension) {
|
|||||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAudioLevelLength,
|
EXPECT_EQ(
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kAudioLevelLength),
|
||||||
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||||
kRtpExtensionAudioLevel));
|
kRtpExtensionAudioLevel));
|
||||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
@ -232,38 +237,46 @@ TEST_F(RtpSenderTest, RegisterRtpHeaderExtensions) {
|
|||||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
|
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength,
|
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||||
|
kTransmissionTimeOffsetLength),
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||||
kAbsoluteSendTimeLength, rtp_sender_->RtpHeaderExtensionTotalLength());
|
kTransmissionTimeOffsetLength +
|
||||||
|
kAbsoluteSendTimeLength),
|
||||||
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
EXPECT_EQ(RtpUtility::Word32Align(
|
||||||
kAbsoluteSendTimeLength + kAudioLevelLength,
|
kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
kAbsoluteSendTimeLength + kAudioLevelLength),
|
||||||
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
|
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||||
kAbsoluteSendTimeLength + kAudioLevelLength +
|
kTransmissionTimeOffsetLength +
|
||||||
kVideoRotationLength,
|
kAbsoluteSendTimeLength +
|
||||||
|
kAudioLevelLength + kVideoRotationLength),
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
|
|
||||||
// Deregister starts.
|
// Deregister starts.
|
||||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||||
kRtpExtensionTransmissionTimeOffset));
|
kRtpExtensionTransmissionTimeOffset));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength +
|
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||||
kAudioLevelLength + kVideoRotationLength,
|
kAbsoluteSendTimeLength +
|
||||||
|
kAudioLevelLength + kVideoRotationLength),
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||||
kRtpExtensionAbsoluteSendTime));
|
kRtpExtensionAbsoluteSendTime));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kAudioLevelLength + kVideoRotationLength,
|
EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength +
|
||||||
|
kAudioLevelLength + kVideoRotationLength),
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
|
||||||
kRtpExtensionAudioLevel));
|
kRtpExtensionAudioLevel));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kVideoRotationLength,
|
EXPECT_EQ(
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kVideoRotationLength),
|
||||||
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
0, rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionVideoRotation));
|
0, rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionVideoRotation));
|
||||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
@ -273,8 +286,9 @@ TEST_F(RtpSenderTest, RegisterRtpVideoRotationHeaderExtension) {
|
|||||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kVideoRotationLength,
|
EXPECT_EQ(
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kVideoRotationLength),
|
||||||
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
0, rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionVideoRotation));
|
0, rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionVideoRotation));
|
||||||
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
@ -500,12 +514,17 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithAudioLevelExtension) {
|
|||||||
TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
||||||
EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kTimeOffset));
|
EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kTimeOffset));
|
||||||
EXPECT_EQ(0, rtp_sender_->SetAbsoluteSendTime(kAbsoluteSendTime));
|
EXPECT_EQ(0, rtp_sender_->SetAbsoluteSendTime(kAbsoluteSendTime));
|
||||||
|
EXPECT_EQ(0,
|
||||||
|
rtp_sender_->SetTransportSequenceNumber(kTransportSequenceNumber));
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
|
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
|
||||||
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
|
kRtpExtensionTransportSequenceNumber,
|
||||||
|
kTransportSequenceNumberExtensionId));
|
||||||
|
|
||||||
size_t length = static_cast<size_t>(rtp_sender_->BuildRTPheader(
|
size_t length = static_cast<size_t>(rtp_sender_->BuildRTPheader(
|
||||||
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
packet_, kPayload, kMarkerBit, kTimestamp, 0));
|
||||||
@ -525,6 +544,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
|||||||
kTransmissionTimeOffsetExtensionId);
|
kTransmissionTimeOffsetExtensionId);
|
||||||
map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId);
|
map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId);
|
||||||
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
|
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
|
||||||
|
map.Register(kRtpExtensionTransportSequenceNumber,
|
||||||
|
kTransportSequenceNumberExtensionId);
|
||||||
const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map);
|
const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map);
|
||||||
|
|
||||||
ASSERT_TRUE(valid_rtp_header);
|
ASSERT_TRUE(valid_rtp_header);
|
||||||
@ -534,9 +555,12 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
|||||||
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
|
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
|
||||||
EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime);
|
EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime);
|
||||||
EXPECT_TRUE(rtp_header.extension.hasAudioLevel);
|
EXPECT_TRUE(rtp_header.extension.hasAudioLevel);
|
||||||
|
EXPECT_TRUE(rtp_header.extension.hasTransportSequenceNumber);
|
||||||
EXPECT_EQ(kTimeOffset, rtp_header.extension.transmissionTimeOffset);
|
EXPECT_EQ(kTimeOffset, rtp_header.extension.transmissionTimeOffset);
|
||||||
EXPECT_EQ(kAbsoluteSendTime, rtp_header.extension.absoluteSendTime);
|
EXPECT_EQ(kAbsoluteSendTime, rtp_header.extension.absoluteSendTime);
|
||||||
EXPECT_EQ(kAudioLevel + 0x80u, rtp_header.extension.audioLevel);
|
EXPECT_EQ(kAudioLevel + 0x80u, rtp_header.extension.audioLevel);
|
||||||
|
EXPECT_EQ(kTransportSequenceNumber,
|
||||||
|
rtp_header.extension.transportSequenceNumber);
|
||||||
|
|
||||||
// Parse without map extension
|
// Parse without map extension
|
||||||
webrtc::RTPHeader rtp_header2;
|
webrtc::RTPHeader rtp_header2;
|
||||||
@ -548,9 +572,12 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
|||||||
EXPECT_FALSE(rtp_header2.extension.hasTransmissionTimeOffset);
|
EXPECT_FALSE(rtp_header2.extension.hasTransmissionTimeOffset);
|
||||||
EXPECT_FALSE(rtp_header2.extension.hasAbsoluteSendTime);
|
EXPECT_FALSE(rtp_header2.extension.hasAbsoluteSendTime);
|
||||||
EXPECT_FALSE(rtp_header2.extension.hasAudioLevel);
|
EXPECT_FALSE(rtp_header2.extension.hasAudioLevel);
|
||||||
|
EXPECT_FALSE(rtp_header2.extension.hasTransportSequenceNumber);
|
||||||
|
|
||||||
EXPECT_EQ(0, rtp_header2.extension.transmissionTimeOffset);
|
EXPECT_EQ(0, rtp_header2.extension.transmissionTimeOffset);
|
||||||
EXPECT_EQ(0u, rtp_header2.extension.absoluteSendTime);
|
EXPECT_EQ(0u, rtp_header2.extension.absoluteSendTime);
|
||||||
EXPECT_EQ(0u, rtp_header2.extension.audioLevel);
|
EXPECT_EQ(0u, rtp_header2.extension.audioLevel);
|
||||||
|
EXPECT_EQ(0u, rtp_header2.extension.transportSequenceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
|
TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
|
||||||
@ -1313,8 +1340,9 @@ TEST_F(RtpSenderVideoTest, SendVideoWithCVO) {
|
|||||||
|
|
||||||
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
|
||||||
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
kRtpExtensionVideoRotation, kVideoRotationExtensionId));
|
||||||
EXPECT_EQ(kRtpOneByteHeaderLength + kVideoRotationLength,
|
EXPECT_EQ(
|
||||||
rtp_sender_->RtpHeaderExtensionTotalLength());
|
RtpUtility::Word32Align(kRtpOneByteHeaderLength + kVideoRotationLength),
|
||||||
|
rtp_sender_->RtpHeaderExtensionTotalLength());
|
||||||
|
|
||||||
rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload,
|
rtp_sender_video_->SendVideo(kRtpVideoGeneric, kVideoFrameKey, kPayload,
|
||||||
kTimestamp, 0, packet_, sizeof(packet_), NULL,
|
kTimestamp, 0, packet_, sizeof(packet_), NULL,
|
||||||
|
@ -184,6 +184,13 @@ uint32_t BufferToUWord32(const uint8_t* dataBuffer) {
|
|||||||
#endif
|
#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) {
|
uint32_t pow2(uint8_t exp) {
|
||||||
return 1 << exp;
|
return 1 << exp;
|
||||||
}
|
}
|
||||||
@ -480,11 +487,11 @@ void RtpHeaderParser::ParseOneByteExtensionHeader(
|
|||||||
LOG(LS_WARNING) << "Incorrect audio level len: " << len;
|
LOG(LS_WARNING) << "Incorrect audio level len: " << len;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 0 1 2 3
|
// 0 1
|
||||||
// 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
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
// | ID | len=0 |V| level | 0x00 | 0x00 |
|
// | ID | len=0 |V| level |
|
||||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
//
|
//
|
||||||
|
|
||||||
// Parse out the fields but only use it for debugging for now.
|
// 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;
|
<< "Incorrect coordination of video coordination len: " << len;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 0 1 2 3
|
// 0 1
|
||||||
// 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
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
// | ID | len=0 |V|0 0 0 0 C F R R| 0x00 | 0x00 |
|
// | ID | len=0 |0 0 0 0 C F R R|
|
||||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
header.extension.hasVideoRotation = true;
|
header.extension.hasVideoRotation = true;
|
||||||
header.extension.videoRotation = ptr[0];
|
header.extension.videoRotation = ptr[0];
|
||||||
break;
|
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: {
|
default: {
|
||||||
LOG(LS_WARNING) << "Extension type not implemented: " << type;
|
LOG(LS_WARNING) << "Extension type not implemented: " << type;
|
||||||
return;
|
return;
|
||||||
|
@ -91,6 +91,9 @@ namespace RtpUtility {
|
|||||||
*/
|
*/
|
||||||
uint32_t BufferToUWord32(const uint8_t* dataBuffer);
|
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 {
|
class RtpHeaderParser {
|
||||||
public:
|
public:
|
||||||
RtpHeaderParser(const uint8_t* rtpData, size_t rtpDataLength);
|
RtpHeaderParser(const uint8_t* rtpData, size_t rtpDataLength);
|
||||||
|
Loading…
Reference in New Issue
Block a user