diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index b0b37113b8..b49a5d3dca 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -322,6 +322,7 @@ 'rtp_rtcp/source/rtcp_packet/fir_unittest.cc', 'rtp_rtcp/source/rtcp_packet/nack_unittest.cc', 'rtp_rtcp/source/rtcp_packet/pli_unittest.cc', + 'rtp_rtcp/source/rtcp_packet/rapid_resync_request_unittest.cc', 'rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc', 'rtp_rtcp/source/rtcp_packet/remb_unittest.cc', 'rtp_rtcp/source/rtcp_packet/report_block_unittest.cc', diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn index 55f38867b1..511f69de6d 100644 --- a/webrtc/modules/rtp_rtcp/BUILD.gn +++ b/webrtc/modules/rtp_rtcp/BUILD.gn @@ -66,6 +66,8 @@ source_set("rtp_rtcp") { "source/rtcp_packet/pli.h", "source/rtcp_packet/psfb.cc", "source/rtcp_packet/psfb.h", + "source/rtcp_packet/rapid_resync_request.cc", + "source/rtcp_packet/rapid_resync_request.h", "source/rtcp_packet/receiver_report.cc", "source/rtcp_packet/receiver_report.h", "source/rtcp_packet/remb.cc", diff --git a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi index bc2f8c34f9..f72e71030a 100644 --- a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi +++ b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi @@ -61,6 +61,8 @@ 'source/rtcp_packet/pli.h', 'source/rtcp_packet/psfb.cc', 'source/rtcp_packet/psfb.h', + 'source/rtcp_packet/rapid_resync_request.cc', + 'source/rtcp_packet/rapid_resync_request.h', 'source/rtcp_packet/receiver_report.cc', 'source/rtcp_packet/receiver_report.h', 'source/rtcp_packet/remb.cc', diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.cc new file mode 100644 index 0000000000..394b3cf543 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.cc @@ -0,0 +1,65 @@ +/* + * 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/rtcp_packet/rapid_resync_request.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { +// RFC 4585: Feedback format. +// Rapid Resynchronisation Request (draft-perkins-avt-rapid-rtp-sync-03). +// +// 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| FMT=5 | PT=205 | length=2 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +bool RapidResyncRequest::Parse(const RtcpCommonHeader& header, + const uint8_t* payload) { + RTC_CHECK(header.packet_type == kPacketType); + RTC_CHECK(header.count_or_format == kFeedbackMessageType); + + if (header.payload_size_bytes != kCommonFeedbackLength) { + LOG(LS_WARNING) << "Packet payload size should be " << kCommonFeedbackLength + << " instead of " << header.payload_size_bytes + << " to be a valid Rapid Resynchronisation Request"; + return false; + } + + ParseCommonFeedback(payload); + return true; +} + +bool RapidResyncRequest::Create( + uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + + CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet, + index); + CreateCommonFeedback(packet + *index); + *index += kCommonFeedbackLength; + return true; +} +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h new file mode 100644 index 0000000000..866eb2ce52 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RAPID_RESYNC_REQUEST_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RAPID_RESYNC_REQUEST_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { +// draft-perkins-avt-rapid-rtp-sync-03 +class RapidResyncRequest : public Rtpfb { + public: + static const uint8_t kFeedbackMessageType = 5; + + RapidResyncRequest() {} + ~RapidResyncRequest() override {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + size_t BlockLength() const override { + return kHeaderLength + kCommonFeedbackLength; + } + + RTC_DISALLOW_COPY_AND_ASSIGN(RapidResyncRequest); +}; +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RAPID_RESYNC_REQUEST_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request_unittest.cc new file mode 100644 index 0000000000..896933d51d --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request_unittest.cc @@ -0,0 +1,70 @@ +/* + * 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/rtcp_packet/rapid_resync_request.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::ElementsAreArray; +using testing::make_tuple; +using webrtc::rtcp::RapidResyncRequest; +using webrtc::rtcp::RawPacket; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kRemoteSsrc = 0x23456789; +// Manually created packet matching constants above. +const uint8_t kPacket[] = {0x85, 205, 0x00, 0x02, + 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89}; +const size_t kPacketLength = sizeof(kPacket); +} // namespace + +TEST(RtcpPacketRapidResyncRequestTest, Parse) { + RtcpCommonHeader header; + ASSERT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); + RapidResyncRequest mutable_parsed; + EXPECT_TRUE(mutable_parsed.Parse( + header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); + const RapidResyncRequest& parsed = mutable_parsed; + + EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); + EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); +} + +TEST(RtcpPacketRapidResyncRequestTest, Create) { + RapidResyncRequest rrr; + rrr.From(kSenderSsrc); + rrr.To(kRemoteSsrc); + + rtc::scoped_ptr packet = rrr.Build(); + + EXPECT_THAT(make_tuple(packet->Buffer(), packet->Length()), + ElementsAreArray(kPacket)); +} + +TEST(RtcpPacketRapidResyncRequestTest, ParseFailsOnWrongSizePacket) { + RapidResyncRequest parsed; + RtcpCommonHeader header; + ASSERT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); + const size_t kCorrectPayloadSize = header.payload_size_bytes; + const uint8_t* payload = kPacket + RtcpCommonHeader::kHeaderSizeBytes; + + header.payload_size_bytes = kCorrectPayloadSize - 1; + EXPECT_FALSE(parsed.Parse(header, payload)); + + header.payload_size_bytes = kCorrectPayloadSize + 1; + EXPECT_FALSE(parsed.Parse(header, payload)); +} +} // namespace webrtc