Parse next RTCP XR report block after an unsupported block type.
R=stefan@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/2649004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@5114 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index c33cf23..25670f5 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -162,6 +162,17 @@
}
}
+ void AddXrUnknownBlock() {
+ Add8(6); // Block type.
+ Add8(0); // Reserved.
+ Add16(9); // Length.
+ Add32(0); // Receiver SSRC.
+ Add64(0, 0); // Remaining fields (RFC 3611) are set to zero.
+ Add64(0, 0);
+ Add64(0, 0);
+ Add64(0, 0);
+ }
+
void AddXrVoipBlock(uint32_t remote_ssrc, uint8_t loss) {
Add8(7); // Block type.
Add8(0); // Reserved.
@@ -452,6 +463,27 @@
EXPECT_TRUE(rtcp_packet_info_.xr_dlrr_item);
}
+TEST_F(RtcpReceiverTest, InjectXrPacketWithUnknownReportBlock) {
+ const uint8_t kLossRate = 123;
+ const uint32_t kSourceSsrc = 0x123456;
+ std::set<uint32_t> ssrcs;
+ ssrcs.insert(kSourceSsrc);
+ rtcp_receiver_->SetSsrcs(kSourceSsrc, ssrcs);
+ std::vector<uint32_t> remote_ssrcs;
+ remote_ssrcs.push_back(kSourceSsrc);
+
+ PacketBuilder p;
+ p.AddXrHeader(0x2345);
+ p.AddXrVoipBlock(kSourceSsrc, kLossRate);
+ p.AddXrUnknownBlock();
+ p.AddXrReceiverReferenceTimeBlock(0x10203, 0x40506);
+
+ EXPECT_EQ(0, InjectRtcpPacket(p.packet(), p.length()));
+ EXPECT_EQ(static_cast<unsigned int>(kRtcpXrReceiverReferenceTime +
+ kRtcpXrVoipMetric),
+ rtcp_packet_info_.rtcpPacketTypeFlags);
+}
+
TEST(RtcpUtilityTest, MidNtp) {
const uint32_t kNtpSec = 0x12345678;
const uint32_t kNtpFrac = 0x23456789;
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc
index 8ab783f..705a38b 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc
@@ -224,7 +224,7 @@
}
case PT_XR:
{
- const bool ok = ParseXR();
+ const bool ok = ParseXr();
if (!ok)
{
// Nothing supported found, continue to next block!
@@ -243,7 +243,7 @@
void
RTCPUtility::RTCPParserV2::IterateXrItem()
{
- const bool success = ParseXRItem();
+ const bool success = ParseXrItem();
if (!success)
{
Iterate();
@@ -253,7 +253,7 @@
void
RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
{
- const bool success = ParseXRDLRRReportBlockItem();
+ const bool success = ParseXrDlrrItem();
if (!success)
{
Iterate();
@@ -851,7 +851,7 @@
return true;
}
/*
- 0 1 2 3
+ 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|reserved | PT=XR=207 | length |
@@ -861,7 +861,7 @@
: report blocks :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-bool RTCPUtility::RTCPParserV2::ParseXR()
+bool RTCPUtility::RTCPParserV2::ParseXr()
{
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < 8)
@@ -882,55 +882,47 @@
return true;
}
-/*
+/* Extended report block format (RFC 3611).
+ BT: block type.
+ block length: length of report block in 32-bits words minus one (including
+ the header).
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
+ 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT | type-specific | block length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: type-specific block contents :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-bool
-RTCPUtility::RTCPParserV2::ParseXRItem()
-{
+bool RTCPUtility::RTCPParserV2::ParseXrItem() {
+ const int kBlockHeaderLengthInBytes = 4;
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
-
- if (length < 4) {
+ if (length < kBlockHeaderLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
- uint8_t blockType = *_ptrRTCPData++;
+ uint8_t block_type = *_ptrRTCPData++;
_ptrRTCPData++; // Ignore reserved.
- uint16_t blockLength = *_ptrRTCPData++ << 8;
- blockLength = *_ptrRTCPData++;
+ uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
+ block_length_in_4bytes += *_ptrRTCPData++;
- if (blockType == 4 && blockLength == 2)
- {
- return ParseXRReceiverReferenceTimeItem();
+ switch (block_type) {
+ case kBtReceiverReferenceTime:
+ return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
+ case kBtDlrr:
+ return ParseXrDlrr(block_length_in_4bytes);
+ case kBtVoipMetric:
+ return ParseXrVoipMetricItem(block_length_in_4bytes);
+ default:
+ return ParseXrUnsupportedBlockType(block_length_in_4bytes);
}
- else if (blockType == 5 && (blockLength % 3) == 0)
- {
- _packetType = kRtcpXrDlrrReportBlockCode;
- _state = State_XR_DLLRItem;
- _numberOfBlocks = blockLength / 3;
- return true;
- }
- else if (blockType == 7 && blockLength == 8)
- {
- return ParseXRVOIPMetricItem();
- }
-
- // Not supported.
- _state = State_TopLevel;
- EndCurrentBlock();
- return false;
}
-/* 0 1 2 3
+/* Receiver Reference Time Report 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT=4 | reserved | block length = 2 |
@@ -940,37 +932,35 @@
| NTP timestamp, least significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-
-bool RTCPUtility::RTCPParserV2::ParseXRReceiverReferenceTimeItem() {
+bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
+ int block_length_4bytes) {
+ const int kBlockLengthIn4Bytes = 2;
+ const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
- if (length < 8) {
+ if (block_length_4bytes != kBlockLengthIn4Bytes ||
+ length < kBlockLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
- _packet.XRReceiverReferenceTimeItem.NTPMostSignificant =
- *_ptrRTCPData++ << 24;
- _packet.XRReceiverReferenceTimeItem.NTPMostSignificant +=
- *_ptrRTCPData++ << 16;
- _packet.XRReceiverReferenceTimeItem.NTPMostSignificant +=
- *_ptrRTCPData++ << 8;
- _packet.XRReceiverReferenceTimeItem.NTPMostSignificant += *_ptrRTCPData++;
+ _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
+ _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
+ _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
+ _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
- _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant =
- *_ptrRTCPData++ << 24;
- _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant +=
- *_ptrRTCPData++ << 16;
- _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant +=
- *_ptrRTCPData++ << 8;
- _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant += *_ptrRTCPData++;
+ _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
+ _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
+ _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
+ _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
_packetType = kRtcpXrReceiverReferenceTimeCode;
_state = State_XRItem;
return true;
}
-/* 0 1 2 3
+/* DLRR Report 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT=5 | reserved | block length |
@@ -986,14 +976,28 @@
: ... : 2
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
+bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
+ const int kSubBlockLengthIn4Bytes = 3;
+ if (block_length_4bytes < 0 ||
+ (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
+ _state = State_TopLevel;
+ EndCurrentBlock();
+ return false;
+ }
+ _packetType = kRtcpXrDlrrReportBlockCode;
+ _state = State_XR_DLLRItem;
+ _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
+ return true;
+}
-bool RTCPUtility::RTCPParserV2::ParseXRDLRRReportBlockItem() {
- const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
+bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
if (_numberOfBlocks == 0) {
_state = State_XRItem;
return false;
}
- if (length < 12) {
+ const int kSubBlockLengthInBytes = 12;
+ const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
+ if (length < kSubBlockLengthInBytes) {
_state = State_TopLevel;
EndCurrentBlock();
return false;
@@ -1019,8 +1023,8 @@
_state = State_XR_DLLRItem;
return true;
}
-/*
- 0 1 2 3
+/* VoIP Metrics Report 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| BT=7 | reserved | block length = 8 |
@@ -1043,63 +1047,77 @@
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-bool
-RTCPUtility::RTCPParserV2::ParseXRVOIPMetricItem()
-{
- const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
+bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
+ const int kBlockLengthIn4Bytes = 8;
+ const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
+ const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
+ if (block_length_4bytes != kBlockLengthIn4Bytes ||
+ length < kBlockLengthInBytes) {
+ _state = State_TopLevel;
+ EndCurrentBlock();
+ return false;
+ }
- if (length < 28)
- {
- _state = State_TopLevel;
- EndCurrentBlock();
- return false;
- }
- _packetType = kRtcpXrVoipMetricCode;
+ _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
+ _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
+ _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
- _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
- _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
+ _ptrRTCPData++; // skip reserved
- _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
- _ptrRTCPData++; // skip reserved
+ _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
+ _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
+ _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
- _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
- _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
+ _packetType = kRtcpXrVoipMetricCode;
+ _state = State_XRItem;
+ return true;
+}
- _state = State_XRItem;
- return true;
+bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
+ int block_length_4bytes) {
+ const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
+ const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
+ if (length < kBlockLengthInBytes) {
+ _state = State_TopLevel;
+ EndCurrentBlock();
+ return false;
+ }
+ // Skip block.
+ _ptrRTCPData += kBlockLengthInBytes;
+ _state = State_XRItem;
+ return false;
}
bool
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility.h b/webrtc/modules/rtp_rtcp/source/rtcp_utility.h
index c954f44..f0867a7 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_utility.h
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_utility.h
@@ -335,6 +335,13 @@
PT_XR = 207
};
+ // Extended report blocks, RFC 3611.
+ enum RtcpXrBlockType {
+ kBtReceiverReferenceTime = 4,
+ kBtDlrr = 5,
+ kBtVoipMetric = 7
+ };
+
bool RTCPParseCommonHeader( const uint8_t* ptrDataBegin,
const uint8_t* ptrDataEnd,
RTCPCommonHeader& parsedHeader);
@@ -413,11 +420,13 @@
bool ParseIJ();
bool ParseIJItem();
- bool ParseXR();
- bool ParseXRItem();
- bool ParseXRReceiverReferenceTimeItem();
- bool ParseXRDLRRReportBlockItem();
- bool ParseXRVOIPMetricItem();
+ bool ParseXr();
+ bool ParseXrItem();
+ bool ParseXrReceiverReferenceTimeItem(int block_length_4bytes);
+ bool ParseXrDlrr(int block_length_4bytes);
+ bool ParseXrDlrrItem();
+ bool ParseXrVoipMetricItem(int block_length_4bytes);
+ bool ParseXrUnsupportedBlockType(int block_length_4bytes);
bool ParseFBCommon(const RTCPCommonHeader& header);
bool ParseNACKItem();