Create skeleton of the rtcp transceiver.
RtcpTransceiver name reserved for thread-safe version that planned to be wrapper of the RtcpTransceiverImpl BUG=webrtc:8239 Change-Id: If8a3092eb1b8e4175e3efd23b52e1043cdabf19f Reviewed-on: https://webrtc-review.googlesource.com/7920 Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Niels Moller <nisse@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20414}
This commit is contained in:

committed by
Commit Bot

parent
d5585ca956
commit
398a7c67b1
@ -218,6 +218,23 @@ rtc_static_library("rtp_rtcp") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_source_set("rtcp_transceiver") {
|
||||||
|
public = [
|
||||||
|
"source/rtcp_transceiver_config.h",
|
||||||
|
"source/rtcp_transceiver_impl.h",
|
||||||
|
]
|
||||||
|
sources = [
|
||||||
|
"source/rtcp_transceiver_config.cc",
|
||||||
|
"source/rtcp_transceiver_impl.cc",
|
||||||
|
]
|
||||||
|
deps = [
|
||||||
|
":rtp_rtcp",
|
||||||
|
"../../api:array_view",
|
||||||
|
"../../api:transport_api",
|
||||||
|
"../../rtc_base:rtc_base_approved",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
rtc_source_set("fec_test_helper") {
|
rtc_source_set("fec_test_helper") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
@ -338,6 +355,7 @@ if (rtc_include_tests) {
|
|||||||
"source/rtcp_packet_unittest.cc",
|
"source/rtcp_packet_unittest.cc",
|
||||||
"source/rtcp_receiver_unittest.cc",
|
"source/rtcp_receiver_unittest.cc",
|
||||||
"source/rtcp_sender_unittest.cc",
|
"source/rtcp_sender_unittest.cc",
|
||||||
|
"source/rtcp_transceiver_impl_unittest.cc",
|
||||||
"source/rtp_fec_unittest.cc",
|
"source/rtp_fec_unittest.cc",
|
||||||
"source/rtp_format_h264_unittest.cc",
|
"source/rtp_format_h264_unittest.cc",
|
||||||
"source/rtp_format_video_generic_unittest.cc",
|
"source/rtp_format_video_generic_unittest.cc",
|
||||||
@ -366,6 +384,7 @@ if (rtc_include_tests) {
|
|||||||
deps = [
|
deps = [
|
||||||
":fec_test_helper",
|
":fec_test_helper",
|
||||||
":mock_rtp_rtcp",
|
":mock_rtp_rtcp",
|
||||||
|
":rtcp_transceiver",
|
||||||
":rtp_rtcp",
|
":rtp_rtcp",
|
||||||
"..:module_api",
|
"..:module_api",
|
||||||
"../..:webrtc_common",
|
"../..:webrtc_common",
|
||||||
|
62
modules/rtp_rtcp/source/rtcp_transceiver_config.cc
Normal file
62
modules/rtp_rtcp/source/rtcp_transceiver_config.cc
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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 "modules/rtp_rtcp/source/rtcp_transceiver_config.h"
|
||||||
|
|
||||||
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
|
#include "rtc_base/logging.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
RtcpTransceiverConfig::RtcpTransceiverConfig() = default;
|
||||||
|
RtcpTransceiverConfig::RtcpTransceiverConfig(const RtcpTransceiverConfig&) =
|
||||||
|
default;
|
||||||
|
RtcpTransceiverConfig& RtcpTransceiverConfig::operator=(
|
||||||
|
const RtcpTransceiverConfig&) = default;
|
||||||
|
RtcpTransceiverConfig::~RtcpTransceiverConfig() = default;
|
||||||
|
|
||||||
|
bool RtcpTransceiverConfig::Validate() const {
|
||||||
|
if (feedback_ssrc == 0)
|
||||||
|
LOG(LS_WARNING)
|
||||||
|
<< debug_id
|
||||||
|
<< "Ssrc 0 may be treated by some implementation as invalid.";
|
||||||
|
if (cname.size() > 255) {
|
||||||
|
LOG(LS_ERROR) << debug_id << "cname can be maximum 255 characters.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (max_packet_size < 100) {
|
||||||
|
LOG(LS_ERROR) << debug_id << "max packet size " << max_packet_size
|
||||||
|
<< " is too small.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (max_packet_size > IP_PACKET_SIZE) {
|
||||||
|
LOG(LS_ERROR) << debug_id << "max packet size " << max_packet_size
|
||||||
|
<< " more than " << IP_PACKET_SIZE << " is unsupported.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (outgoing_transport == nullptr) {
|
||||||
|
LOG(LS_ERROR) << debug_id << "outgoing transport must be set";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (min_periodic_report_ms <= 0) {
|
||||||
|
LOG(LS_ERROR) << debug_id << "period " << min_periodic_report_ms
|
||||||
|
<< "ms between reports should be positive.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO(danilchap): Remove or update the warning when RtcpTransceiver supports
|
||||||
|
// send-only sessions.
|
||||||
|
if (receive_statistics == nullptr)
|
||||||
|
LOG(LS_WARNING)
|
||||||
|
<< debug_id
|
||||||
|
<< "receive statistic should be set to generate rtcp report blocks.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
54
modules/rtp_rtcp/source/rtcp_transceiver_config.h
Normal file
54
modules/rtp_rtcp/source/rtcp_transceiver_config.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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 MODULES_RTP_RTCP_SOURCE_RTCP_TRANSCEIVER_CONFIG_H_
|
||||||
|
#define MODULES_RTP_RTCP_SOURCE_RTCP_TRANSCEIVER_CONFIG_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
class ReceiveStatisticsProvider;
|
||||||
|
class Transport;
|
||||||
|
|
||||||
|
struct RtcpTransceiverConfig {
|
||||||
|
RtcpTransceiverConfig();
|
||||||
|
RtcpTransceiverConfig(const RtcpTransceiverConfig&);
|
||||||
|
RtcpTransceiverConfig& operator=(const RtcpTransceiverConfig&);
|
||||||
|
~RtcpTransceiverConfig();
|
||||||
|
|
||||||
|
// Logs the error and returns false if configuration miss key objects or
|
||||||
|
// is inconsistant. May log warnings.
|
||||||
|
bool Validate() const;
|
||||||
|
|
||||||
|
// Used to prepend all log messages. Can be empty.
|
||||||
|
std::string debug_id;
|
||||||
|
|
||||||
|
// Ssrc to use as default sender ssrc, e.g. for transport-wide feedbacks.
|
||||||
|
uint32_t feedback_ssrc = 1;
|
||||||
|
|
||||||
|
// Cname of the local particiapnt.
|
||||||
|
std::string cname;
|
||||||
|
|
||||||
|
// Maximum packet size outgoing transport accepts.
|
||||||
|
size_t max_packet_size = 1200;
|
||||||
|
|
||||||
|
// Transport to send rtcp packets to. Should be set.
|
||||||
|
Transport* outgoing_transport = nullptr;
|
||||||
|
|
||||||
|
// Minimum period to send receiver reports and attached messages.
|
||||||
|
int min_periodic_report_ms = 1000;
|
||||||
|
|
||||||
|
// Rtcp report block generator for outgoing receiver reports.
|
||||||
|
ReceiveStatisticsProvider* receive_statistics = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MODULES_RTP_RTCP_SOURCE_RTCP_TRANSCEIVER_CONFIG_H_
|
96
modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
Normal file
96
modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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 "modules/rtp_rtcp/source/rtcp_transceiver_impl.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "api/call/transport.h"
|
||||||
|
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
||||||
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtcp_packet.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Helper to put several RTCP packets into lower layer datagram composing
|
||||||
|
// Compound or Reduced-Size RTCP packet, as defined by RFC 5506 section 2.
|
||||||
|
class PacketSender : public rtcp::RtcpPacket::PacketReadyCallback {
|
||||||
|
public:
|
||||||
|
PacketSender(Transport* transport, size_t max_packet_size)
|
||||||
|
: transport_(transport), max_packet_size_(max_packet_size) {
|
||||||
|
RTC_CHECK_LE(max_packet_size, IP_PACKET_SIZE);
|
||||||
|
}
|
||||||
|
~PacketSender() override {
|
||||||
|
RTC_DCHECK_EQ(index_, 0) << "Unsent rtcp packet.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appends a packet to pending compound packet.
|
||||||
|
// Sends rtcp compound packet if buffer was already full and resets buffer.
|
||||||
|
void AppendPacket(const rtcp::RtcpPacket& packet) {
|
||||||
|
packet.Create(buffer_, &index_, max_packet_size_, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sends pending rtcp compound packet.
|
||||||
|
void Send() {
|
||||||
|
if (index_ > 0) {
|
||||||
|
OnPacketReady(buffer_, index_);
|
||||||
|
index_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Implements RtcpPacket::PacketReadyCallback
|
||||||
|
void OnPacketReady(uint8_t* data, size_t length) override {
|
||||||
|
transport_->SendRtcp(data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transport* const transport_;
|
||||||
|
const size_t max_packet_size_;
|
||||||
|
size_t index_ = 0;
|
||||||
|
uint8_t buffer_[IP_PACKET_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
RtcpTransceiverImpl::RtcpTransceiverImpl(const RtcpTransceiverConfig& config)
|
||||||
|
: config_(config) {
|
||||||
|
RTC_CHECK(config_.Validate());
|
||||||
|
}
|
||||||
|
|
||||||
|
RtcpTransceiverImpl::~RtcpTransceiverImpl() = default;
|
||||||
|
|
||||||
|
void RtcpTransceiverImpl::SendCompoundPacket() {
|
||||||
|
PacketSender sender(config_.outgoing_transport, config_.max_packet_size);
|
||||||
|
|
||||||
|
rtcp::ReceiverReport rr;
|
||||||
|
rr.SetSenderSsrc(config_.feedback_ssrc);
|
||||||
|
if (config_.receive_statistics) {
|
||||||
|
// TODO(danilchap): Support sending more than
|
||||||
|
// |ReceiverReport::kMaxNumberOfReportBlocks| per compound rtcp packet.
|
||||||
|
std::vector<rtcp::ReportBlock> report_blocks =
|
||||||
|
config_.receive_statistics->RtcpReportBlocks(
|
||||||
|
rtcp::ReceiverReport::kMaxNumberOfReportBlocks);
|
||||||
|
// TODO(danilchap): Fill in LastSr/DelayLastSr fields of report blocks
|
||||||
|
// when RtcpTransceiver handles incoming sender reports.
|
||||||
|
rr.SetReportBlocks(std::move(report_blocks));
|
||||||
|
}
|
||||||
|
sender.AppendPacket(rr);
|
||||||
|
// TODO(danilchap): Append SDES to conform to the requirements on minimal
|
||||||
|
// compound RTCP packet.
|
||||||
|
|
||||||
|
sender.Send();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
42
modules/rtp_rtcp/source/rtcp_transceiver_impl.h
Normal file
42
modules/rtp_rtcp/source/rtcp_transceiver_impl.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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 MODULES_RTP_RTCP_SOURCE_RTCP_TRANSCEIVER_IMPL_H_
|
||||||
|
#define MODULES_RTP_RTCP_SOURCE_RTCP_TRANSCEIVER_IMPL_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "api/array_view.h"
|
||||||
|
#include "modules/rtp_rtcp/source/rtcp_transceiver_config.h"
|
||||||
|
#include "rtc_base/constructormagic.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
//
|
||||||
|
// Manage incoming and outgoing rtcp messages for multiple BUNDLED streams.
|
||||||
|
//
|
||||||
|
// This class is not thread-safe.
|
||||||
|
class RtcpTransceiverImpl {
|
||||||
|
public:
|
||||||
|
explicit RtcpTransceiverImpl(const RtcpTransceiverConfig& config);
|
||||||
|
~RtcpTransceiverImpl();
|
||||||
|
|
||||||
|
// Sends RTCP packets starting with a sender or receiver report.
|
||||||
|
void SendCompoundPacket();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const RtcpTransceiverConfig config_;
|
||||||
|
|
||||||
|
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtcpTransceiverImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MODULES_RTP_RTCP_SOURCE_RTCP_TRANSCEIVER_IMPL_H_
|
84
modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc
Normal file
84
modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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 "modules/rtp_rtcp/source/rtcp_transceiver_impl.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
||||||
|
#include "rtc_base/ptr_util.h"
|
||||||
|
#include "test/gmock.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
#include "test/mock_transport.h"
|
||||||
|
#include "test/rtcp_packet_parser.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
|
using ::testing::Invoke;
|
||||||
|
using ::testing::Return;
|
||||||
|
using ::testing::SizeIs;
|
||||||
|
using ::webrtc::MockTransport;
|
||||||
|
using ::webrtc::RtcpTransceiverConfig;
|
||||||
|
using ::webrtc::RtcpTransceiverImpl;
|
||||||
|
using ::webrtc::rtcp::ReportBlock;
|
||||||
|
using ::webrtc::test::RtcpPacketParser;
|
||||||
|
|
||||||
|
class MockReceiveStatisticsProvider : public webrtc::ReceiveStatisticsProvider {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD1(RtcpReportBlocks, std::vector<ReportBlock>(size_t));
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(RtcpTransceiverImplTest, ForceSendReportEmitsRtcpPacket) {
|
||||||
|
MockTransport outgoing_transport;
|
||||||
|
RtcpPacketParser rtcp_parser;
|
||||||
|
EXPECT_CALL(outgoing_transport, SendRtcp(_, _))
|
||||||
|
.WillOnce(Invoke(&rtcp_parser, &RtcpPacketParser::Parse));
|
||||||
|
|
||||||
|
RtcpTransceiverConfig config;
|
||||||
|
config.outgoing_transport = &outgoing_transport;
|
||||||
|
RtcpTransceiverImpl rtcp_transceiver(config);
|
||||||
|
|
||||||
|
ASSERT_EQ(rtcp_parser.receiver_report()->num_packets(), 0);
|
||||||
|
rtcp_transceiver.SendCompoundPacket();
|
||||||
|
EXPECT_GT(rtcp_parser.receiver_report()->num_packets(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(RtcpTransceiverImplTest, ReceiverReportUsesReceiveStatistics) {
|
||||||
|
const uint32_t kSenderSsrc = 12345;
|
||||||
|
const uint32_t kMediaSsrc = 54321;
|
||||||
|
MockTransport outgoing_transport;
|
||||||
|
RtcpPacketParser rtcp_parser;
|
||||||
|
EXPECT_CALL(outgoing_transport, SendRtcp(_, _))
|
||||||
|
.WillOnce(Invoke(&rtcp_parser, &RtcpPacketParser::Parse));
|
||||||
|
|
||||||
|
MockReceiveStatisticsProvider receive_statistics;
|
||||||
|
std::vector<ReportBlock> report_blocks(1);
|
||||||
|
report_blocks[0].SetMediaSsrc(kMediaSsrc);
|
||||||
|
EXPECT_CALL(receive_statistics, RtcpReportBlocks(_))
|
||||||
|
.WillRepeatedly(Return(report_blocks));
|
||||||
|
|
||||||
|
RtcpTransceiverConfig config;
|
||||||
|
config.feedback_ssrc = kSenderSsrc;
|
||||||
|
config.outgoing_transport = &outgoing_transport;
|
||||||
|
config.receive_statistics = &receive_statistics;
|
||||||
|
RtcpTransceiverImpl rtcp_transceiver(config);
|
||||||
|
|
||||||
|
rtcp_transceiver.SendCompoundPacket();
|
||||||
|
|
||||||
|
ASSERT_GT(rtcp_parser.receiver_report()->num_packets(), 0);
|
||||||
|
EXPECT_EQ(rtcp_parser.receiver_report()->sender_ssrc(), kSenderSsrc);
|
||||||
|
ASSERT_THAT(rtcp_parser.receiver_report()->report_blocks(),
|
||||||
|
SizeIs(report_blocks.size()));
|
||||||
|
EXPECT_EQ(rtcp_parser.receiver_report()->report_blocks()[0].source_ssrc(),
|
||||||
|
kMediaSsrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
Reference in New Issue
Block a user