--- a/media/webrtc/trunk/webrtc/common_types.cc
+++ b/media/webrtc/trunk/webrtc/common_types.cc
@@ -45,17 +45,18 @@ RTPHeaderExtension::RTPHeaderExtension()
hasAbsoluteSendTime(false),
absoluteSendTime(0),
hasTransportSequenceNumber(false),
transportSequenceNumber(0),
hasAudioLevel(false),
voiceActivity(false),
audioLevel(0),
hasVideoRotation(false),
- videoRotation(kVideoRotation_0) {
+ videoRotation(kVideoRotation_0),
+ csrcAudioLevels() {
}
RTPHeaderExtension::RTPHeaderExtension(const RTPHeaderExtension& rhs) {
*this = rhs;
}
RTPHeaderExtension&
RTPHeaderExtension::operator=(const RTPHeaderExtension& rhs) {
--- a/media/webrtc/trunk/webrtc/common_types.h
+++ b/media/webrtc/trunk/webrtc/common_types.h
@@ -854,16 +854,27 @@ class StreamId {
friend bool operator!=(const StreamId& lhs, const StreamId& rhs) {
return !(lhs == rhs);
}
private:
char value_[kMaxSize+1]; // mozilla: make sure we have space to null term.
};
+// Audio level of CSRCs See:
+// https://tools.ietf.org/html/rfc6465
+struct CsrcAudioLevelList {
+ CsrcAudioLevelList() : numAudioLevels(0) { }
+ CsrcAudioLevelList(const CsrcAudioLevelList&) = default;
+ CsrcAudioLevelList& operator=(const CsrcAudioLevelList&) = default;
+ uint8_t numAudioLevels;
+ // arrOfAudioLevels has the same ordering as RTPHeader.arrOfCSRCs
+ uint8_t arrOfAudioLevels[kRtpCsrcSize];
+};
+
struct RTPHeaderExtension {
RTPHeaderExtension();
RTPHeaderExtension(const RTPHeaderExtension& rhs);
RTPHeaderExtension& operator=(const RTPHeaderExtension& rhs);
bool hasTransmissionTimeOffset;
int32_t transmissionTimeOffset;
bool hasAbsoluteSendTime;
@@ -887,16 +898,17 @@ struct RTPHeaderExtension {
// For identification of a stream when ssrc is not signaled. See
// https://tools.ietf.org/html/draft-ietf-avtext-rid-09
// TODO(danilchap): Update url from draft to release version.
StreamId rtpStreamId;
StreamId repairedRtpStreamId;
StreamId mId;
+ CsrcAudioLevelList csrcAudioLevels;
};
struct RTPHeader {
RTPHeader();
bool markerBit;
uint8_t payloadType;
uint16_t sequenceNumber;
--- a/media/webrtc/trunk/webrtc/config.cc
+++ b/media/webrtc/trunk/webrtc/config.cc
@@ -79,22 +79,26 @@ const int RtpExtension::kRtpStreamIdDefa
const char* RtpExtension::kRepairedRtpStreamIdUri =
"urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
const int RtpExtension::kRepairedRtpStreamIdDefaultId = 8;
const char* RtpExtension::kMIdUri =
"urn:ietf:params:rtp-hdrext:sdes:mid";
const int RtpExtension::kMIdDefaultId = 9;
+const char* RtpExtension::kCsrcAudioLevelUri =
+ "urn:ietf:params:rtp-hdrext:csrc-audio-level";
+const int RtpExtension::kCsrcAudioLevelDefaultId = 10;
+
bool RtpExtension::IsSupportedForAudio(const std::string& uri) {
return uri == webrtc::RtpExtension::kAudioLevelUri ||
uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
uri == webrtc::RtpExtension::kRtpStreamIdUri ||
- uri == webrtc::RtpExtension::kRepairedRtpStreamIdUri ||
- uri == webrtc::RtpExtension::kMIdUri;
+ uri == webrtc::RtpExtension::kMIdUri ||
+ uri == webrtc::RtpExtension::kCsrcAudioLevelUri;
}
bool RtpExtension::IsSupportedForVideo(const std::string& uri) {
return uri == webrtc::RtpExtension::kTimestampOffsetUri ||
uri == webrtc::RtpExtension::kAbsSendTimeUri ||
uri == webrtc::RtpExtension::kVideoRotationUri ||
uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
uri == webrtc::RtpExtension::kPlayoutDelayUri ||
--- a/media/webrtc/trunk/webrtc/config.h
+++ b/media/webrtc/trunk/webrtc/config.h
@@ -102,16 +102,19 @@ struct RtpExtension {
static const int kRtpStreamIdDefaultId;
static const char* kRepairedRtpStreamIdUri;
static const int kRepairedRtpStreamIdDefaultId;
static const char* kMIdUri;
static const int kMIdDefaultId;
+ static const char* kCsrcAudioLevelUri;
+ static const int kCsrcAudioLevelDefaultId;
+
std::string uri;
int id;
};
struct VideoStream {
VideoStream();
~VideoStream();
std::string ToString() const;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h
@@ -73,16 +73,17 @@ enum RTPExtensionType {
kRtpExtensionAudioLevel,
kRtpExtensionAbsoluteSendTime,
kRtpExtensionVideoRotation,
kRtpExtensionTransportSequenceNumber,
kRtpExtensionPlayoutDelay,
kRtpExtensionRtpStreamId,
kRtpExtensionRepairedRtpStreamId,
kRtpExtensionMId,
+ kRtpExtensionCsrcAudioLevel,
kRtpExtensionNumberOfExtensions // Must be the last entity in the enum.
};
enum RTCPAppSubTypes { kAppSubtypeBwe = 0x00 };
// TODO(sprang): Make this an enum class once rtcp_receiver has been cleaned up.
enum RTCPPacketType : uint32_t {
kRtcpReport = 0x0001,
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
@@ -36,16 +36,17 @@ constexpr ExtensionInfo kExtensions[] =
CreateExtensionInfo<AudioLevel>(),
CreateExtensionInfo<AbsoluteSendTime>(),
CreateExtensionInfo<VideoOrientation>(),
CreateExtensionInfo<TransportSequenceNumber>(),
CreateExtensionInfo<PlayoutDelayLimits>(),
CreateExtensionInfo<RtpStreamId>(),
CreateExtensionInfo<RepairedRtpStreamId>(),
CreateExtensionInfo<MId>(),
+ CreateExtensionInfo<CsrcAudioLevel>(),
};
// Because of kRtpExtensionNone, NumberOfExtension is 1 bigger than the actual
// number of known extensions.
static_assert(arraysize(kExtensions) ==
static_cast<int>(kRtpExtensionNumberOfExtensions) - 1,
"kExtensions expect to list all known extensions");
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc
@@ -2,17 +2,16 @@
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
-
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
namespace webrtc {
@@ -311,9 +310,48 @@ bool MId::Parse(rtc::ArrayView<const uin
size_t MId::ValueSize(const std::string& mid) {
return RtpStreamId::ValueSize(mid);
}
bool MId::Write(uint8_t* data, const std::string& mid) {
return RtpStreamId::Write(data, mid);
}
+// CSRCAudioLevel
+// Sample Audio Level Encoding Using the One-Byte Header Format
+// Note that the range of len is 1 to 15 which is encoded as 0 to 14
+// 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 |0| level 1 |0| level 2 |0| level 3 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+constexpr RTPExtensionType CsrcAudioLevel::kId;
+constexpr const char* CsrcAudioLevel::kUri;
+
+bool CsrcAudioLevel::Parse(rtc::ArrayView<const uint8_t> data,
+ CsrcAudioLevelList* csrcAudioLevels) {
+ if (data.size() < 1 || data.size() > kRtpCsrcSize)
+ return false;
+ csrcAudioLevels->numAudioLevels = data.size();
+ for(uint8_t i = 0; i < csrcAudioLevels->numAudioLevels; i++) {
+ // Ensure range is 0 to 127 inclusive
+ csrcAudioLevels->arrOfAudioLevels[i] = 0x7f & data[i];
+ }
+ return true;
+}
+
+size_t CsrcAudioLevel::ValueSize(const CsrcAudioLevelList& csrcAudioLevels) {
+ return csrcAudioLevels.numAudioLevels;
+}
+
+bool CsrcAudioLevel::Write(uint8_t* data,
+ const CsrcAudioLevelList& csrcAudioLevels) {
+ RTC_DCHECK_GE(csrcAudioLevels.numAudioLevels, 0);
+ for(uint8_t i = 0; i < csrcAudioLevels.numAudioLevels; i++) {
+ data[i] = csrcAudioLevels.arrOfAudioLevels[i] & 0x7f;
+ }
+ // This extension if used must have at least one audio level
+ return csrcAudioLevels.numAudioLevels;
+}
+
} // namespace webrtc
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h
@@ -147,10 +147,22 @@ class MId {
static size_t ValueSize(const StreamId& mid);
static bool Write(uint8_t* data, const StreamId& mid);
static bool Parse(rtc::ArrayView<const uint8_t> data, std::string* mid);
static size_t ValueSize(const std::string& mid);
static bool Write(uint8_t* data, const std::string& mid);
};
+class CsrcAudioLevel {
+ public:
+ static constexpr RTPExtensionType kId = kRtpExtensionCsrcAudioLevel;
+ static constexpr const char* kUri =
+ "urn:ietf:params:rtp-hdrext:csrc-audio-level";
+
+ static bool Parse(rtc::ArrayView<const uint8_t> data,
+ CsrcAudioLevelList* csrcAudioLevels);
+ static size_t ValueSize(const CsrcAudioLevelList& csrcAudioLevels);
+ static bool Write(uint8_t* data, const CsrcAudioLevelList& csrcAudioLevels);
+};
+
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_packet.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_packet.cc
@@ -170,16 +170,17 @@ void Packet::GetHeader(RTPHeader* header
header->extension.hasAudioLevel = GetExtension<AudioLevel>(
&header->extension.voiceActivity, &header->extension.audioLevel);
header->extension.hasVideoRotation =
GetExtension<VideoOrientation>(&header->extension.videoRotation);
GetExtension<RtpStreamId>(&header->extension.rtpStreamId);
GetExtension<RepairedRtpStreamId>(&header->extension.repairedRtpStreamId);
GetExtension<PlayoutDelayLimits>(&header->extension.playout_delay);
GetExtension<MId>(&header->extension.mId);
+ GetExtension<CsrcAudioLevel>(&header->extension.csrcAudioLevels);
}
size_t Packet::headers_size() const {
return payload_offset_;
}
size_t Packet::payload_size() const {
return payload_size_;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_packet_unittest.cc
@@ -70,16 +70,28 @@ constexpr char kMId[] = "midval";
constexpr uint8_t kPacketWithMid[] = {
0x90, kPayloadType, kSeqNumFirstByte, kSeqNumSecondByte,
0x65, 0x43, 0x12, 0x78,
0x12, 0x34, 0x56, 0x78,
0xbe, 0xde, 0x00, 0x02,
0xb5, 'm', 'i', 'd',
'v', 'a', 'l', 0x00};
+constexpr uint8_t kCsrcAudioLevelExtensionId = 0xc;
+constexpr uint8_t kCsrcAudioLevelsSize = 4;
+constexpr uint8_t kCsrcAudioLevels[] = {0x7f, 0x00, 0x10, 0x08};
+constexpr uint8_t kPacketWithCsrcAudioLevels[] = {
+ 0x90, kPayloadType, kSeqNumFirstByte, kSeqNumSecondByte,
+ 0x65, 0x43, 0x12, 0x78,
+ 0x12, 0x34, 0x56, 0x78,
+ 0xbe, 0xde, 0x00, 0x02,
+ (kCsrcAudioLevelExtensionId << 4) | (kCsrcAudioLevelsSize - 1),
+ 0x7f, 0x00, 0x10,
+ 0x08, 0x00, 0x00, 0x00};
+
constexpr uint32_t kCsrcs[] = {0x34567890, 0x32435465};
constexpr uint8_t kPayload[] = {'p', 'a', 'y', 'l', 'o', 'a', 'd'};
constexpr uint8_t kPacketPaddingSize = 8;
constexpr uint8_t kPacket[] = {
0xb2, kPayloadType, kSeqNumFirstByte, kSeqNumSecondByte,
0x65, 0x43, 0x12, 0x78,
0x12, 0x34, 0x56, 0x78,
0x34, 0x56, 0x78, 0x90,
@@ -159,16 +171,34 @@ TEST(RtpPacketTest, CreateWithDynamicSiz
packet.SetPayloadType(kPayloadType);
packet.SetSequenceNumber(kSeqNum);
packet.SetTimestamp(kTimestamp);
packet.SetSsrc(kSsrc);
packet.SetExtension<RtpStreamId>(kMId);
EXPECT_THAT(kPacketWithMid, ElementsAreArray(packet.data(), packet.size()));
}
+TEST(RtpPacketTest, CreateWithDynamicSizedExtensionCsrcAudioLevel) {
+ RtpPacketToSend::ExtensionManager extensions;
+ extensions.Register<CsrcAudioLevel>(kCsrcAudioLevelExtensionId);
+ RtpPacketToSend packet(&extensions);
+ packet.SetPayloadType(kPayloadType);
+ packet.SetSequenceNumber(kSeqNum);
+ packet.SetTimestamp(kTimestamp);
+ packet.SetSsrc(kSsrc);
+ CsrcAudioLevelList levels;
+ levels.numAudioLevels = kCsrcAudioLevelsSize;
+ for (uint8_t i = 0; i < kCsrcAudioLevelsSize; i++) {
+ levels.arrOfAudioLevels[i] = kCsrcAudioLevels[i];
+ }
+ packet.SetExtension<CsrcAudioLevel>(levels);
+ EXPECT_THAT(kPacketWithCsrcAudioLevels,
+ ElementsAreArray(packet.data(), packet.size()));
+}
+
TEST(RtpPacketTest, TryToCreateWithEmptyRsid) {
RtpPacketToSend::ExtensionManager extensions;
extensions.Register<RtpStreamId>(kRtpStreamIdExtensionId);
RtpPacketToSend packet(&extensions);
EXPECT_FALSE(packet.SetExtension<RtpStreamId>(""));
}
TEST(RtpPacketTest, TryToCreateWithLongRsid) {
@@ -448,21 +478,32 @@ TEST(RtpPacketTest, ParseDynamicSizeExte
0x90, kPayloadType, kSeqNumFirstByte, kSeqNumSecondByte,
0x65, 0x43, 0x12, 0x78, // Timestamp.
0x12, 0x34, 0x56, 0x78, // Ssrc.
0xbe, 0xde, 0x00, 0x04, // Extensions block of size 4x32bit words.
0x21, 'H', 'D', // Extension with id = 2, size = (1+1).
0x12, 'r', 't', 'x', // Extension with id = 1, size = (2+1).
0x35, 'm', 'i', 'd', 'v', 'a', 'l', // Extension with id = 3, size = (5+1).
0x00, 0x00}; // Extension padding.
+ const uint8_t kPacket4[] = {
+ 0x90, kPayloadType, kSeqNumFirstByte, kSeqNumSecondByte,
+ 0x65, 0x43, 0x12, 0x78, // Timestamp.
+ 0x12, 0x34, 0x56, 0x78, // Ssrc.
+ 0xbe, 0xde, 0x00, 0x05, // Extensions block of size 5x32bit words.
+ 0x21, 'H', 'D', // Extension with id = 2, size = (1+1).
+ 0x12, 'r', 't', 'x', // Extension with id = 1, size = (2+1).
+ 0x35, 'm', 'i', 'd', 'v', 'a', 'l', // Extension with id = 3, size = (5+1).
+ 0x43, 0x01, 0x10, 0x00, // Extenstionwith id = 4, size = (3+1)
+ 0x7f, 0x00}; // Extension 4 cont. 1 byte of padding.
// clang-format on
RtpPacketReceived::ExtensionManager extensions;
extensions.Register<RtpStreamId>(1);
extensions.Register<RepairedRtpStreamId>(2);
extensions.Register<MId>(3);
+ extensions.Register<CsrcAudioLevel>(4);
RtpPacketReceived packet(&extensions);
ASSERT_TRUE(packet.Parse(kPacket1, sizeof(kPacket1)));
std::string rsid;
EXPECT_TRUE(packet.GetExtension<RtpStreamId>(&rsid));
EXPECT_EQ(rsid, "rtx");
std::string repaired_rsid;
@@ -479,16 +520,33 @@ TEST(RtpPacketTest, ParseDynamicSizeExte
ASSERT_TRUE(packet.Parse(kPacket3, sizeof(kPacket3)));
EXPECT_TRUE(packet.GetExtension<RtpStreamId>(&rsid));
EXPECT_EQ(rsid, "rtx");
EXPECT_TRUE(packet.GetExtension<RepairedRtpStreamId>(&repaired_rsid));
EXPECT_EQ(repaired_rsid, "HD");
std::string mid;
EXPECT_TRUE(packet.GetExtension<MId>(&mid));
EXPECT_EQ(mid, "midval");
+
+ // Parse another packet with RtpStreamId, RepairedRtpStreamId, MId,
+ // CsrcAudioLevels
+ ASSERT_TRUE(packet.Parse(kPacket4, sizeof(kPacket4)));
+ EXPECT_TRUE(packet.GetExtension<RtpStreamId>(&rsid));
+ EXPECT_EQ(rsid, "rtx");
+ EXPECT_TRUE(packet.GetExtension<RepairedRtpStreamId>(&repaired_rsid));
+ EXPECT_EQ(repaired_rsid, "HD");
+ EXPECT_TRUE(packet.GetExtension<MId>(&mid));
+ EXPECT_EQ(mid, "midval");
+ CsrcAudioLevelList csrcAudioLevels;
+ EXPECT_TRUE(packet.GetExtension<CsrcAudioLevel>(&csrcAudioLevels));
+ EXPECT_EQ(csrcAudioLevels.numAudioLevels, 4);
+ EXPECT_EQ(csrcAudioLevels.arrOfAudioLevels[0], 0x01);
+ EXPECT_EQ(csrcAudioLevels.arrOfAudioLevels[1], 0x10);
+ EXPECT_EQ(csrcAudioLevels.arrOfAudioLevels[2], 0x00);
+ EXPECT_EQ(csrcAudioLevels.arrOfAudioLevels[3], 0x7f);
}
TEST(RtpPacketTest, RawExtensionFunctionsAcceptZeroIdAndReturnFalse) {
RtpPacketReceived::ExtensionManager extensions;
RtpPacketReceived packet(&extensions);
// Use ExtensionManager to set kInvalidId to 0 to demonstrate natural way for
// using zero value as a parameter to Packet::*RawExtension functions.
const int kInvalidId = extensions.GetId(TransmissionOffset::kId);
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -42,16 +42,18 @@ RTPExtensionType StringToRtpExtensionTyp
if (extension == RtpExtension::kPlayoutDelayUri)
return kRtpExtensionPlayoutDelay;
if (extension == RtpExtension::kRtpStreamIdUri)
return kRtpExtensionRtpStreamId;
if (extension == RtpExtension::kRepairedRtpStreamIdUri)
return kRtpExtensionRepairedRtpStreamId;
if (extension == RtpExtension::kMIdUri)
return kRtpExtensionMId;
+ if (extension == RtpExtension::kCsrcAudioLevelUri)
+ return kRtpExtensionCsrcAudioLevel;
RTC_NOTREACHED() << "Looking up unsupported RTP extension.";
return kRtpExtensionNone;
}
RtpRtcp::Configuration::Configuration()
: receive_statistics(NullObjectReceiveStatistics()) {}
RtpRtcp* RtpRtcp::CreateRtpRtcp(const RtpRtcp::Configuration& configuration) {
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
@@ -464,16 +464,30 @@ void RtpHeaderParser::ParseOneByteExtens
header->extension.repairedRtpStreamId.Set(
rtc::MakeArrayView(ptr, len + 1));
break;
}
case kRtpExtensionMId: {
header->extension.mId.Set(rtc::MakeArrayView(ptr, len + 1));
break;
}
+ case kRtpExtensionCsrcAudioLevel: {
+ auto& levels = header->extension.csrcAudioLevels;
+ levels.numAudioLevels = static_cast<uint8_t>(len + 1);
+ if (levels.numAudioLevels > kRtpCsrcSize) {
+ LOG(LS_WARNING) << "Incorrect number of CSRC audio levels: " <<
+ levels.numAudioLevels;
+ levels.numAudioLevels = 0;
+ return;
+ }
+ for (uint8_t i = 0; i < levels.numAudioLevels; i++) {
+ levels.arrOfAudioLevels[i] = ptr[i] & 0x7f;
+ }
+ break;
+ }
default:
case kRtpExtensionNone:
case kRtpExtensionNumberOfExtensions: {
RTC_NOTREACHED() << "Invalid extension type: " << type;
return;
}
}
}
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility_unittest.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility_unittest.cc
@@ -143,48 +143,50 @@ TEST(RtpHeaderParser, ParseWithOverSized
EXPECT_TRUE(parser.Parse(&header, &extensions));
// Parse should ignore extension.
EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
EXPECT_EQ(sizeof(kPacket), header.headerLength);
}
-TEST(RtpHeaderParser, ParseAll9Extensions) {
+TEST(RtpHeaderParser, ParseAll10Extensions) {
const uint8_t kAudioLevel = 0x5a;
// clang-format off
const uint8_t kPacket[] = {
0x90, kPayloadType, 0x00, kSeqNum,
0x65, 0x43, 0x12, 0x78, // kTimestamp.
0x12, 0x34, 0x56, 0x78, // kSsrc.
- 0xbe, 0xde, 0x00, 0x0a, // Extension of size 10x32bit words.
+ 0xbe, 0xde, 0x00, 0x0b, // Extension of size 10x32bit words.
0x40, 0x80|kAudioLevel, // AudioLevel.
0x22, 0x01, 0x56, 0xce, // TransmissionOffset.
0x62, 0x12, 0x34, 0x56, // AbsoluteSendTime.
+ 0x72, 0x7f, 0x01, 0x10, // CsrcAudioLevel
0x81, 0xce, 0xab, // TransportSequenceNumber.
0xa0, 0x03, // VideoRotation.
0xb2, 0x12, 0x48, 0x76, // PlayoutDelayLimits.
0xc2, 'r', 't', 'x', // RtpStreamId
0xd5, 's', 't', 'r', 'e', 'a', 'm', // RepairedRtpStreamId
0xe7, 'm', 'i', 'd', 'v', 'a', 'l', 'u', 'e', // MId
0x00, // Padding to 32bit boundary.
};
// clang-format on
ASSERT_EQ(sizeof(kPacket) % 4, 0u);
RtpHeaderExtensionMap extensions;
- extensions.Register<TransmissionOffset>(2);
- extensions.Register<AudioLevel>(4);
- extensions.Register<AbsoluteSendTime>(6);
- extensions.Register<TransportSequenceNumber>(8);
- extensions.Register<VideoOrientation>(0xa);
- extensions.Register<PlayoutDelayLimits>(0xb);
- extensions.Register<RtpStreamId>(0xc);
- extensions.Register<RepairedRtpStreamId>(0xd);
- extensions.Register<MId>(0xe);
+ EXPECT_TRUE(extensions.Register<TransmissionOffset>(2));
+ EXPECT_TRUE(extensions.Register<AudioLevel>(4));
+ EXPECT_TRUE(extensions.Register<AbsoluteSendTime>(6));
+ EXPECT_TRUE(extensions.Register<CsrcAudioLevel>(7));
+ EXPECT_TRUE(extensions.Register<TransportSequenceNumber>(8));
+ EXPECT_TRUE(extensions.Register<VideoOrientation>(0xa));
+ EXPECT_TRUE(extensions.Register<PlayoutDelayLimits>(0xb));
+ EXPECT_TRUE(extensions.Register<RtpStreamId>(0xc));
+ EXPECT_TRUE(extensions.Register<RepairedRtpStreamId>(0xd));
+ EXPECT_TRUE(extensions.Register<MId>(0xe));
RtpUtility::RtpHeaderParser parser(kPacket, sizeof(kPacket));
RTPHeader header;
EXPECT_TRUE(parser.Parse(&header, &extensions));
EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
EXPECT_EQ(0x156ce, header.extension.transmissionTimeOffset);
@@ -203,16 +205,20 @@ TEST(RtpHeaderParser, ParseAll9Extension
EXPECT_EQ(0x124 * PlayoutDelayLimits::kGranularityMs,
header.extension.playout_delay.min_ms);
EXPECT_EQ(0x876 * PlayoutDelayLimits::kGranularityMs,
header.extension.playout_delay.max_ms);
EXPECT_EQ(header.extension.rtpStreamId, StreamId("rtx"));
EXPECT_EQ(header.extension.repairedRtpStreamId, StreamId("stream"));
EXPECT_EQ(header.extension.mId, StreamId("midvalue"));
+ EXPECT_EQ(header.extension.csrcAudioLevels.numAudioLevels, 3);
+ EXPECT_EQ(header.extension.csrcAudioLevels.arrOfAudioLevels[0], 0x7f);
+ EXPECT_EQ(header.extension.csrcAudioLevels.arrOfAudioLevels[1], 0x01);
+ EXPECT_EQ(header.extension.csrcAudioLevels.arrOfAudioLevels[2], 0x10);
}
TEST(RtpHeaderParser, ParseMalformedRsidExtensions) {
// clang-format off
const uint8_t kPacket[] = {
0x90, kPayloadType, 0x00, kSeqNum,
0x65, 0x43, 0x12, 0x78, // kTimestamp.
0x12, 0x34, 0x56, 0x78, // kSsrc.
--- a/media/webrtc/trunk/webrtc/test/fuzzers/rtp_packet_fuzzer.cc
+++ b/media/webrtc/trunk/webrtc/test/fuzzers/rtp_packet_fuzzer.cc
@@ -96,12 +96,17 @@ void FuzzOneInput(const uint8_t* data, s
packet.GetExtension<RepairedRtpStreamId>(&rsid);
break;
}
case kRtpExtensionMId: {
std::string mid;
packet.GetExtension<MId>(&mid);
break;
}
+ case kRtpExtensionCsrcAudioLevel: {
+ CsrcAudioLevelList levels;
+ packet.GetExtension<CsrcAudioLevel>(&levels);
+ break;
+ }
}
}
}
} // namespace webrtc
--- a/media/webrtc/trunk/webrtc/video/rtp_stream_receiver.cc
+++ b/media/webrtc/trunk/webrtc/video/rtp_stream_receiver.cc
@@ -407,16 +407,24 @@ bool RtpStreamReceiver::DeliverRtp(const
if (header.extension.hasAbsoluteSendTime)
ss << ", abs send time: " << header.extension.absoluteSendTime;
if (!header.extension.rtpStreamId.empty())
ss << ", rid: " << header.extension.rtpStreamId.data();
if (!header.extension.repairedRtpStreamId.empty())
ss << ", repaired rid: " << header.extension.repairedRtpStreamId.data();
if (!header.extension.mId.empty())
ss << ", mid: " << header.extension.mId.data();
+ const auto& csrcLevels = header.extension.csrcAudioLevels;
+ if (csrcLevels.numAudioLevels) {
+ ss << ", csrc audio levels : {" << csrcLevels.arrOfAudioLevels[0];
+ for (uint8_t i = 1; i < csrcLevels.numAudioLevels; i++) {
+ ss << ", " << csrcLevels.arrOfAudioLevels[i];
+ }
+ ss << "}";
+ }
LOG(LS_INFO) << ss.str();
last_packet_log_ms_ = now_ms;
}
}
remote_bitrate_estimator_->IncomingPacket(arrival_time_ms, payload_length,
header);
header.payload_type_frequency = kVideoPayloadTypeFrequency;