Move Ownership of RtpModules to VideoSendStream from VieChannel and remove use of vie_channel and vie_receiver from video_send_stream.

The purpose of this refactoring is a first step of separating the encoder parts from the RTP transport.

BUG=webrtc:5687
R=mflodman@webrtc.org, pbos@webrtc.org, stefan@webrtc.org

Review URL: https://codereview.webrtc.org/1864313003 .

Cr-Commit-Position: refs/heads/master@{#12377}
This commit is contained in:
Per
2016-04-15 14:59:13 +02:00
parent 6ca0a31708
commit 83d0910694
17 changed files with 360 additions and 543 deletions

View File

@ -210,10 +210,10 @@ class RtpRtcp : public Module {
*/
virtual void SetSequenceNumber(uint16_t seq) = 0;
// Returns true if the ssrc matched this module, false otherwise.
virtual bool SetRtpStateForSsrc(uint32_t ssrc,
const RtpState& rtp_state) = 0;
virtual bool GetRtpStateForSsrc(uint32_t ssrc, RtpState* rtp_state) = 0;
virtual void SetRtpState(const RtpState& rtp_state) = 0;
virtual void SetRtxState(const RtpState& rtp_state) = 0;
virtual RtpState GetRtpState() const = 0;
virtual RtpState GetRtxState() const = 0;
/*
* Get SSRC

View File

@ -85,12 +85,12 @@ class MockRtpRtcp : public RtpRtcp {
MOCK_CONST_METHOD0(StartTimestamp,
uint32_t());
MOCK_METHOD1(SetStartTimestamp, void(const uint32_t timestamp));
MOCK_CONST_METHOD0(SequenceNumber,
uint16_t());
MOCK_CONST_METHOD0(SequenceNumber, uint16_t());
MOCK_METHOD1(SetSequenceNumber, void(const uint16_t seq));
MOCK_METHOD2(SetRtpStateForSsrc,
bool(uint32_t ssrc, const RtpState& rtp_state));
MOCK_METHOD2(GetRtpStateForSsrc, bool(uint32_t ssrc, RtpState* rtp_state));
MOCK_METHOD1(SetRtpState, void(const RtpState& rtp_state));
MOCK_METHOD1(SetRtxState, void(const RtpState& rtp_state));
MOCK_CONST_METHOD0(GetRtpState, RtpState());
MOCK_CONST_METHOD0(GetRtxState, RtpState());
MOCK_CONST_METHOD0(SSRC,
uint32_t());
MOCK_METHOD1(SetSSRC,

View File

@ -871,6 +871,7 @@ void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
if (receive_statistics_) {
StatisticianMap statisticians =
receive_statistics_->GetActiveStatisticians();
RTC_DCHECK(report_blocks_.empty());
@ -879,6 +880,7 @@ void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
}
}
}
}
bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
uint32_t ssrc,

View File

@ -300,30 +300,21 @@ void ModuleRtpRtcpImpl::SetSequenceNumber(const uint16_t seq_num) {
rtp_sender_.SetSequenceNumber(seq_num);
}
bool ModuleRtpRtcpImpl::SetRtpStateForSsrc(uint32_t ssrc,
const RtpState& rtp_state) {
if (rtp_sender_.SSRC() == ssrc) {
void ModuleRtpRtcpImpl::SetRtpState(const RtpState& rtp_state) {
SetStartTimestamp(rtp_state.start_timestamp);
rtp_sender_.SetRtpState(rtp_state);
return true;
}
if (rtp_sender_.RtxSsrc() == ssrc) {
rtp_sender_.SetRtxRtpState(rtp_state);
return true;
}
return false;
}
bool ModuleRtpRtcpImpl::GetRtpStateForSsrc(uint32_t ssrc, RtpState* rtp_state) {
if (rtp_sender_.SSRC() == ssrc) {
*rtp_state = rtp_sender_.GetRtpState();
return true;
void ModuleRtpRtcpImpl::SetRtxState(const RtpState& rtp_state) {
rtp_sender_.SetRtxRtpState(rtp_state);
}
if (rtp_sender_.RtxSsrc() == ssrc) {
*rtp_state = rtp_sender_.GetRtxRtpState();
return true;
RtpState ModuleRtpRtcpImpl::GetRtpState() const {
return rtp_sender_.GetRtpState();
}
return false;
RtpState ModuleRtpRtcpImpl::GetRtxState() const {
return rtp_sender_.GetRtxRtpState();
}
uint32_t ModuleRtpRtcpImpl::SSRC() const {

View File

@ -75,8 +75,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
// Set SequenceNumber, default is a random number.
void SetSequenceNumber(uint16_t seq) override;
bool SetRtpStateForSsrc(uint32_t ssrc, const RtpState& rtp_state) override;
bool GetRtpStateForSsrc(uint32_t ssrc, RtpState* rtp_state) override;
void SetRtpState(const RtpState& rtp_state) override;
void SetRtxState(const RtpState& rtp_state) override;
RtpState GetRtpState() const override;
RtpState GetRtxState() const override;
uint32_t SSRC() const override;

View File

@ -25,13 +25,6 @@ void EncoderStateFeedback::Init(const std::vector<uint32_t>& ssrcs,
vie_encoder_ = encoder;
}
void EncoderStateFeedback::TearDown() {
rtc::CritScope lock(&crit_);
RTC_DCHECK(vie_encoder_);
ssrcs_.clear();
vie_encoder_ = nullptr;
}
bool EncoderStateFeedback::HasSsrc(uint32_t ssrc) {
for (uint32_t registered_ssrc : ssrcs_) {
if (registered_ssrc == ssrc)

View File

@ -31,12 +31,6 @@ class EncoderStateFeedback : public RtcpIntraFrameObserver {
// Adds an encoder to receive feedback for a set of SSRCs.
void Init(const std::vector<uint32_t>& ssrc, ViEEncoder* encoder);
// Removes the registered encoder. Necessary since RTP modules outlive
// ViEEncoder.
// TODO(pbos): Make sure RTP modules are not running when tearing down
// ViEEncoder, then remove this function.
void TearDown();
void OnReceivedIntraFrameRequest(uint32_t ssrc) override;
void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) override;
void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) override;

View File

@ -16,8 +16,10 @@
namespace webrtc {
PayloadRouter::PayloadRouter()
: active_(false), num_sending_modules_(0) {}
PayloadRouter::PayloadRouter(const std::vector<RtpRtcp*>& rtp_modules)
: active_(false), num_sending_modules_(1), rtp_modules_(rtp_modules) {
UpdateModuleSendingState();
}
PayloadRouter::~PayloadRouter() {}
@ -26,12 +28,6 @@ size_t PayloadRouter::DefaultMaxPayloadLength() {
return IP_PACKET_SIZE - kIpUdpSrtpLength;
}
void PayloadRouter::Init(
const std::vector<RtpRtcp*>& rtp_modules) {
RTC_DCHECK(rtp_modules_.empty());
rtp_modules_ = rtp_modules;
}
void PayloadRouter::set_active(bool active) {
rtc::CritScope lock(&crit_);
if (active_ == active)

View File

@ -29,14 +29,11 @@ struct RTPVideoHeader;
// on the simulcast layer in RTPVideoHeader.
class PayloadRouter {
public:
PayloadRouter();
// Rtp modules are assumed to be sorted in simulcast index order.
explicit PayloadRouter(const std::vector<RtpRtcp*>& rtp_modules);
~PayloadRouter();
static size_t DefaultMaxPayloadLength();
// Rtp modules are assumed to be sorted in simulcast index order.
void Init(const std::vector<RtpRtcp*>& rtp_modules);
void SetSendingRtpModules(size_t num_sending_modules);
// PayloadRouter will only route packets if being active, all packets will be
@ -66,13 +63,13 @@ class PayloadRouter {
private:
void UpdateModuleSendingState() EXCLUSIVE_LOCKS_REQUIRED(crit_);
// TODO(pbos): Set once and for all on construction and make const.
std::vector<RtpRtcp*> rtp_modules_;
rtc::CriticalSection crit_;
bool active_ GUARDED_BY(crit_);
size_t num_sending_modules_ GUARDED_BY(crit_);
// Rtp modules are assumed to be sorted in simulcast index order. Not owned.
const std::vector<RtpRtcp*> rtp_modules_;
RTC_DISALLOW_COPY_AND_ASSIGN(PayloadRouter);
};

View File

@ -23,20 +23,12 @@ using ::testing::Return;
namespace webrtc {
class PayloadRouterTest : public ::testing::Test {
protected:
virtual void SetUp() {
payload_router_.reset(new PayloadRouter());
}
std::unique_ptr<PayloadRouter> payload_router_;
};
TEST_F(PayloadRouterTest, SendOnOneModule) {
TEST(PayloadRouterTest, SendOnOneModule) {
MockRtpRtcp rtp;
std::vector<RtpRtcp*> modules(1, &rtp);
payload_router_->Init(modules);
payload_router_->SetSendingRtpModules(modules.size());
PayloadRouter payload_router(modules);
payload_router.SetSendingRtpModules(modules.size());
uint8_t payload = 'a';
FrameType frame_type = kVideoFrameKey;
@ -45,47 +37,47 @@ TEST_F(PayloadRouterTest, SendOnOneModule) {
EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1,
nullptr, nullptr))
.Times(0);
EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0,
EXPECT_FALSE(payload_router.RoutePayload(frame_type, payload_type, 0, 0,
&payload, 1, nullptr, nullptr));
payload_router_->set_active(true);
payload_router.set_active(true);
EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1,
nullptr, nullptr))
.Times(1);
EXPECT_TRUE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0,
EXPECT_TRUE(payload_router.RoutePayload(frame_type, payload_type, 0, 0,
&payload, 1, nullptr, nullptr));
payload_router_->set_active(false);
payload_router.set_active(false);
EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1,
nullptr, nullptr))
.Times(0);
EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0,
EXPECT_FALSE(payload_router.RoutePayload(frame_type, payload_type, 0, 0,
&payload, 1, nullptr, nullptr));
payload_router_->set_active(true);
payload_router.set_active(true);
EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1,
nullptr, nullptr))
.Times(1);
EXPECT_TRUE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0,
EXPECT_TRUE(payload_router.RoutePayload(frame_type, payload_type, 0, 0,
&payload, 1, nullptr, nullptr));
payload_router_->SetSendingRtpModules(0);
payload_router.SetSendingRtpModules(0);
EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1,
nullptr, nullptr))
.Times(0);
EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0,
EXPECT_FALSE(payload_router.RoutePayload(frame_type, payload_type, 0, 0,
&payload, 1, nullptr, nullptr));
}
TEST_F(PayloadRouterTest, SendSimulcast) {
TEST(PayloadRouterTest, SendSimulcast) {
MockRtpRtcp rtp_1;
MockRtpRtcp rtp_2;
std::vector<RtpRtcp*> modules;
modules.push_back(&rtp_1);
modules.push_back(&rtp_2);
payload_router_->Init(modules);
payload_router_->SetSendingRtpModules(modules.size());
PayloadRouter payload_router(modules);
payload_router.SetSendingRtpModules(modules.size());
uint8_t payload_1 = 'a';
FrameType frame_type_1 = kVideoFrameKey;
@ -93,14 +85,14 @@ TEST_F(PayloadRouterTest, SendSimulcast) {
RTPVideoHeader rtp_hdr_1;
rtp_hdr_1.simulcastIdx = 0;
payload_router_->set_active(true);
payload_router.set_active(true);
EXPECT_CALL(rtp_1, SendOutgoingData(frame_type_1, payload_type_1, 0, 0, _, 1,
nullptr, &rtp_hdr_1))
.Times(1);
EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _))
.Times(0);
EXPECT_TRUE(payload_router_->RoutePayload(
frame_type_1, payload_type_1, 0, 0, &payload_1, 1, nullptr, &rtp_hdr_1));
EXPECT_TRUE(payload_router.RoutePayload(frame_type_1, payload_type_1, 0, 0,
&payload_1, 1, nullptr, &rtp_hdr_1));
uint8_t payload_2 = 'b';
FrameType frame_type_2 = kVideoFrameDelta;
@ -112,46 +104,45 @@ TEST_F(PayloadRouterTest, SendSimulcast) {
.Times(1);
EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _))
.Times(0);
EXPECT_TRUE(payload_router_->RoutePayload(
frame_type_2, payload_type_2, 0, 0, &payload_2, 1, nullptr, &rtp_hdr_2));
EXPECT_TRUE(payload_router.RoutePayload(frame_type_2, payload_type_2, 0, 0,
&payload_2, 1, nullptr, &rtp_hdr_2));
// Inactive.
payload_router_->set_active(false);
payload_router.set_active(false);
EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _))
.Times(0);
EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _))
.Times(0);
EXPECT_FALSE(payload_router_->RoutePayload(
frame_type_1, payload_type_1, 0, 0, &payload_1, 1, nullptr, &rtp_hdr_1));
EXPECT_FALSE(payload_router_->RoutePayload(
frame_type_2, payload_type_2, 0, 0, &payload_2, 1, nullptr, &rtp_hdr_2));
EXPECT_FALSE(payload_router.RoutePayload(frame_type_1, payload_type_1, 0, 0,
&payload_1, 1, nullptr, &rtp_hdr_1));
EXPECT_FALSE(payload_router.RoutePayload(frame_type_2, payload_type_2, 0, 0,
&payload_2, 1, nullptr, &rtp_hdr_2));
// Invalid simulcast index.
payload_router_->SetSendingRtpModules(1);
payload_router_->set_active(true);
payload_router.SetSendingRtpModules(1);
payload_router.set_active(true);
EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _))
.Times(0);
EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _))
.Times(0);
rtp_hdr_1.simulcastIdx = 1;
EXPECT_FALSE(payload_router_->RoutePayload(
frame_type_1, payload_type_1, 0, 0, &payload_1, 1, nullptr, &rtp_hdr_1));
EXPECT_FALSE(payload_router.RoutePayload(frame_type_1, payload_type_1, 0, 0,
&payload_1, 1, nullptr, &rtp_hdr_1));
}
TEST_F(PayloadRouterTest, MaxPayloadLength) {
TEST(PayloadRouterTest, MaxPayloadLength) {
// Without any limitations from the modules, verify we get the max payload
// length for IP/UDP/SRTP with a MTU of 150 bytes.
const size_t kDefaultMaxLength = 1500 - 20 - 8 - 12 - 4;
EXPECT_EQ(kDefaultMaxLength, payload_router_->DefaultMaxPayloadLength());
EXPECT_EQ(kDefaultMaxLength, payload_router_->MaxPayloadLength());
MockRtpRtcp rtp_1;
MockRtpRtcp rtp_2;
std::vector<RtpRtcp*> modules;
modules.push_back(&rtp_1);
modules.push_back(&rtp_2);
payload_router_->Init(modules);
payload_router_->SetSendingRtpModules(modules.size());
PayloadRouter payload_router(modules);
EXPECT_EQ(kDefaultMaxLength, PayloadRouter::DefaultMaxPayloadLength());
payload_router.SetSendingRtpModules(modules.size());
// Modules return a higher length than the default value.
EXPECT_CALL(rtp_1, MaxDataPayloadLength())
@ -160,7 +151,7 @@ TEST_F(PayloadRouterTest, MaxPayloadLength) {
EXPECT_CALL(rtp_2, MaxDataPayloadLength())
.Times(1)
.WillOnce(Return(kDefaultMaxLength + 10));
EXPECT_EQ(kDefaultMaxLength, payload_router_->MaxPayloadLength());
EXPECT_EQ(kDefaultMaxLength, payload_router.MaxPayloadLength());
// The modules return a value lower than default.
const size_t kTestMinPayloadLength = 1001;
@ -170,17 +161,17 @@ TEST_F(PayloadRouterTest, MaxPayloadLength) {
EXPECT_CALL(rtp_2, MaxDataPayloadLength())
.Times(1)
.WillOnce(Return(kTestMinPayloadLength));
EXPECT_EQ(kTestMinPayloadLength, payload_router_->MaxPayloadLength());
EXPECT_EQ(kTestMinPayloadLength, payload_router.MaxPayloadLength());
}
TEST_F(PayloadRouterTest, SetTargetSendBitrates) {
TEST(PayloadRouterTest, SetTargetSendBitrates) {
MockRtpRtcp rtp_1;
MockRtpRtcp rtp_2;
std::vector<RtpRtcp*> modules;
modules.push_back(&rtp_1);
modules.push_back(&rtp_2);
payload_router_->Init(modules);
payload_router_->SetSendingRtpModules(modules.size());
PayloadRouter payload_router(modules);
payload_router.SetSendingRtpModules(modules.size());
const uint32_t bitrate_1 = 10000;
const uint32_t bitrate_2 = 76543;
@ -190,13 +181,13 @@ TEST_F(PayloadRouterTest, SetTargetSendBitrates) {
.Times(1);
EXPECT_CALL(rtp_2, SetTargetSendBitrate(bitrate_2))
.Times(1);
payload_router_->SetTargetSendBitrates(bitrates);
payload_router.SetTargetSendBitrates(bitrates);
bitrates.resize(1);
EXPECT_CALL(rtp_1, SetTargetSendBitrate(bitrate_1))
.Times(1);
EXPECT_CALL(rtp_2, SetTargetSendBitrate(bitrate_2))
.Times(0);
payload_router_->SetTargetSendBitrates(bitrates);
payload_router.SetTargetSendBitrates(bitrates);
}
} // namespace webrtc

View File

@ -172,21 +172,15 @@ VideoReceiveStream::VideoReceiveStream(
stats_proxy_(config_, clock_),
vie_channel_(&transport_adapter_,
process_thread,
nullptr,
vcm_.get(),
nullptr,
nullptr,
nullptr,
congestion_controller_->GetRemoteBitrateEstimator(
UseSendSideBwe(config_)),
call_stats_->rtcp_rtt_stats(),
congestion_controller_->pacer(),
congestion_controller_->packet_router(),
1,
false),
congestion_controller_->packet_router()),
vie_receiver_(vie_channel_.vie_receiver()),
vie_sync_(vcm_.get()),
rtp_rtcp_(vie_channel_.rtp_rtcp().front()) {
rtp_rtcp_(vie_channel_.rtp_rtcp()) {
LOG(LS_INFO) << "VideoReceiveStream: " << config_.ToString();
RTC_DCHECK(process_thread_);

View File

@ -34,6 +34,52 @@ namespace webrtc {
class RtcpIntraFrameObserver;
class TransportFeedbackObserver;
static const int kMinSendSidePacketHistorySize = 600;
namespace {
std::vector<RtpRtcp*> CreateRtpRtcpModules(
Transport* outgoing_transport,
RtcpIntraFrameObserver* intra_frame_callback,
RtcpBandwidthObserver* bandwidth_callback,
TransportFeedbackObserver* transport_feedback_callback,
RtcpRttStats* rtt_stats,
RtpPacketSender* paced_sender,
TransportSequenceNumberAllocator* transport_sequence_number_allocator,
SendStatisticsProxy* stats_proxy,
size_t num_modules) {
RTC_DCHECK_GT(num_modules, 0u);
RtpRtcp::Configuration configuration;
ReceiveStatistics* null_receive_statistics = configuration.receive_statistics;
configuration.audio = false;
configuration.receiver_only = false;
configuration.receive_statistics = null_receive_statistics;
configuration.outgoing_transport = outgoing_transport;
configuration.intra_frame_callback = intra_frame_callback;
configuration.rtt_stats = rtt_stats;
configuration.rtcp_packet_type_counter_observer = stats_proxy;
configuration.paced_sender = paced_sender;
configuration.transport_sequence_number_allocator =
transport_sequence_number_allocator;
configuration.send_bitrate_observer = stats_proxy;
configuration.send_frame_count_observer = stats_proxy;
configuration.send_side_delay_observer = stats_proxy;
configuration.bandwidth_callback = bandwidth_callback;
configuration.transport_feedback_callback = transport_feedback_callback;
std::vector<RtpRtcp*> modules;
for (size_t i = 0; i < num_modules; ++i) {
RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
rtp_rtcp->SetSendingStatus(false);
rtp_rtcp->SetSendingMediaStatus(false);
rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
modules.push_back(rtp_rtcp);
}
return modules;
}
} // namespace
std::string
VideoSendStream::Config::EncoderSettings::ToString() const {
std::stringstream ss;
@ -183,21 +229,6 @@ VideoSendStream::VideoSendStream(
this,
config.post_encode_callback,
&stats_proxy_),
vie_channel_(config.send_transport,
module_process_thread_,
&payload_router_,
nullptr,
&encoder_feedback_,
congestion_controller_->GetBitrateController()
->CreateRtcpBandwidthObserver(),
congestion_controller_->GetTransportFeedbackObserver(),
nullptr,
call_stats_->rtcp_rtt_stats(),
congestion_controller_->pacer(),
congestion_controller_->packet_router(),
config_.rtp.ssrcs.size(),
true),
vie_receiver_(vie_channel_.vie_receiver()),
vie_encoder_(num_cpu_cores,
config_.rtp.ssrcs,
module_process_thread_,
@ -207,7 +238,19 @@ VideoSendStream::VideoSendStream(
congestion_controller_->pacer(),
&payload_router_),
vcm_(vie_encoder_.vcm()),
rtp_rtcp_modules_(vie_channel_.rtp_rtcp()),
bandwidth_observer_(congestion_controller_->GetBitrateController()
->CreateRtcpBandwidthObserver()),
rtp_rtcp_modules_(CreateRtpRtcpModules(
config.send_transport,
&encoder_feedback_,
bandwidth_observer_.get(),
congestion_controller_->GetTransportFeedbackObserver(),
call_stats_->rtcp_rtt_stats(),
congestion_controller_->pacer(),
congestion_controller_->packet_router(),
&stats_proxy_,
config_.rtp.ssrcs.size())),
payload_router_(rtp_rtcp_modules_),
input_(&encoder_wakeup_event_,
config_.local_renderer,
&stats_proxy_,
@ -220,14 +263,16 @@ VideoSendStream::VideoSendStream(
RTC_DCHECK(congestion_controller_);
RTC_DCHECK(remb_);
payload_router_.Init(rtp_rtcp_modules_);
RTC_CHECK(vie_encoder_.Init());
encoder_feedback_.Init(config_.rtp.ssrcs, &vie_encoder_);
RTC_CHECK(vie_channel_.Init() == 0);
vcm_->RegisterProtectionCallback(vie_channel_.vcm_protection_callback());
// RTP/RTCP initialization.
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
module_process_thread_->RegisterModule(rtp_rtcp);
congestion_controller_->packet_router()->AddRtpModule(rtp_rtcp);
}
call_stats_->RegisterStatsObserver(vie_channel_.GetStatsObserver());
vcm_->RegisterProtectionCallback(this);
for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
const std::string& extension = config_.rtp.extensions[i].name;
@ -245,28 +290,7 @@ VideoSendStream::VideoSendStream(
remb_->AddRembSender(rtp_rtcp_modules_[0]);
rtp_rtcp_modules_[0]->SetREMBStatus(true);
// Enable NACK, FEC or both.
const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0;
bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1;
// Payload types without picture ID cannot determine that a stream is complete
// without retransmitting FEC, so using FEC + NACK for H.264 (for instance) is
// a waste of bandwidth since FEC packets still have to be transmitted. Note
// that this is not the case with FLEXFEC.
if (enable_protection_nack &&
!PayloadTypeSupportsSkippingFecPackets(
config_.encoder_settings.payload_name)) {
LOG(LS_WARNING) << "Transmitting payload type without picture ID using"
"NACK+FEC is a waste of bandwidth since FEC packets "
"also have to be retransmitted. Disabling FEC.";
enable_protection_fec = false;
}
// TODO(changbin): Should set RTX for RED mapping in RTP sender in future.
vie_channel_.SetProtectionMode(enable_protection_nack, enable_protection_fec,
config_.rtp.fec.red_payload_type,
config_.rtp.fec.ulpfec_payload_type);
vie_encoder_.SetProtectionMethod(enable_protection_nack,
enable_protection_fec);
ConfigureProtection();
ConfigureSsrcs();
// TODO(pbos): Should we set CNAME on all RTP modules?
@ -295,8 +319,6 @@ VideoSendStream::VideoSendStream(
ReconfigureVideoEncoder(encoder_config);
vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_);
if (config_.post_encode_callback)
vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_);
@ -305,10 +327,6 @@ VideoSendStream::VideoSendStream(
bitrate_allocator_->EnforceMinBitrate(false);
}
vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_);
vie_channel_.RegisterSendBitrateObserver(&stats_proxy_);
vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_);
module_process_thread_->RegisterModule(&overuse_detector_);
encoder_thread_.Start();
@ -330,22 +348,17 @@ VideoSendStream::~VideoSendStream() {
bitrate_allocator_->RemoveObserver(this);
module_process_thread_->DeRegisterModule(&overuse_detector_);
vie_channel_.RegisterSendFrameCountObserver(nullptr);
vie_channel_.RegisterSendBitrateObserver(nullptr);
vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr);
vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type);
call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver());
rtp_rtcp_modules_[0]->SetREMBStatus(false);
remb_->RemoveRembSender(rtp_rtcp_modules_[0]);
// ViEChannel outlives ViEEncoder so remove encoder from feedback before
// destruction.
encoder_feedback_.TearDown();
congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream(
vie_receiver_->GetRemoteSsrc());
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp);
module_process_thread_->DeRegisterModule(rtp_rtcp);
delete rtp_rtcp;
}
}
VideoCaptureInput* VideoSendStream::Input() {
@ -361,7 +374,6 @@ void VideoSendStream::Start() {
// Was not already started, trigger a keyframe.
vie_encoder_.SendKeyFrame();
vie_encoder_.Restart();
vie_receiver_->StartReceive();
}
void VideoSendStream::Stop() {
@ -370,7 +382,6 @@ void VideoSendStream::Stop() {
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
// TODO(pbos): Make sure the encoder stops here.
payload_router_.set_active(false);
vie_receiver_->StopReceive();
}
bool VideoSendStream::EncoderThreadFunction(void* obj) {
@ -535,7 +546,9 @@ void VideoSendStream::ReconfigureVideoEncoder(
}
bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
return vie_receiver_->DeliverRtcp(packet, length);
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
rtp_rtcp->IncomingRtcpPacket(packet, length);
return true;
}
VideoSendStream::Stats VideoSendStream::GetStats() {
@ -552,6 +565,60 @@ void VideoSendStream::NormalUsage() {
config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse);
}
void VideoSendStream::ConfigureProtection() {
// Enable NACK, FEC or both.
const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0;
bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1;
// Payload types without picture ID cannot determine that a stream is complete
// without retransmitting FEC, so using FEC + NACK for H.264 (for instance) is
// a waste of bandwidth since FEC packets still have to be transmitted. Note
// that this is not the case with FLEXFEC.
if (enable_protection_nack &&
!PayloadTypeSupportsSkippingFecPackets(
config_.encoder_settings.payload_name)) {
LOG(LS_WARNING) << "Transmitting payload type without picture ID using"
"NACK+FEC is a waste of bandwidth since FEC packets "
"also have to be retransmitted. Disabling FEC.";
enable_protection_fec = false;
}
// Set to valid uint8_ts to be castable later without signed overflows.
uint8_t payload_type_red = 0;
uint8_t payload_type_fec = 0;
// TODO(changbin): Should set RTX for RED mapping in RTP sender in future.
// Validate payload types. If either RED or FEC payload types are set then
// both should be. If FEC is enabled then they both have to be set.
if (enable_protection_fec || config_.rtp.fec.red_payload_type != -1 ||
config_.rtp.fec.ulpfec_payload_type != -1) {
RTC_DCHECK_GE(config_.rtp.fec.red_payload_type, 0);
RTC_DCHECK_GE(config_.rtp.fec.ulpfec_payload_type, 0);
RTC_DCHECK_LE(config_.rtp.fec.red_payload_type, 127);
RTC_DCHECK_LE(config_.rtp.fec.ulpfec_payload_type, 127);
payload_type_red = static_cast<uint8_t>(config_.rtp.fec.red_payload_type);
payload_type_fec =
static_cast<uint8_t>(config_.rtp.fec.ulpfec_payload_type);
} else {
// Payload types unset.
RTC_DCHECK_EQ(config_.rtp.fec.red_payload_type, -1);
RTC_DCHECK_EQ(config_.rtp.fec.ulpfec_payload_type, -1);
}
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
// Set NACK.
rtp_rtcp->SetStorePacketsStatus(
enable_protection_nack || congestion_controller_->pacer(),
kMinSendSidePacketHistorySize);
// Set FEC.
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
rtp_rtcp->SetGenericFECStatus(enable_protection_fec, payload_type_red,
payload_type_fec);
}
}
vie_encoder_.SetProtectionMethod(enable_protection_nack,
enable_protection_fec);
}
void VideoSendStream::ConfigureSsrcs() {
// Configure regular SSRCs.
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
@ -562,7 +629,7 @@ void VideoSendStream::ConfigureSsrcs() {
// Restore RTP state if previous existed.
RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
if (it != suspended_ssrcs_.end())
rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second);
rtp_rtcp->SetRtpState(it->second);
}
// Set up RTX if available.
@ -577,7 +644,7 @@ void VideoSendStream::ConfigureSsrcs() {
rtp_rtcp->SetRtxSsrc(ssrc);
RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
if (it != suspended_ssrcs_.end())
rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second);
rtp_rtcp->SetRtxState(it->second);
}
// Configure RTX payload types.
@ -600,12 +667,13 @@ std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const {
std::map<uint32_t, RtpState> rtp_states;
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
uint32_t ssrc = config_.rtp.ssrcs[i];
rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc);
RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
}
for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc);
rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
}
return rtp_states;
@ -636,5 +704,28 @@ void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps,
vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt);
}
int VideoSendStream::ProtectionRequest(const FecProtectionParams* delta_params,
const FecProtectionParams* key_params,
uint32_t* sent_video_rate_bps,
uint32_t* sent_nack_rate_bps,
uint32_t* sent_fec_rate_bps) {
*sent_video_rate_bps = 0;
*sent_nack_rate_bps = 0;
*sent_fec_rate_bps = 0;
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
uint32_t not_used = 0;
uint32_t module_video_rate = 0;
uint32_t module_fec_rate = 0;
uint32_t module_nack_rate = 0;
rtp_rtcp->SetFecParameters(delta_params, key_params);
rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
&module_nack_rate);
*sent_video_rate_bps += module_video_rate;
*sent_nack_rate_bps += module_nack_rate;
*sent_fec_rate_bps += module_fec_rate;
}
return 0;
}
} // namespace internal
} // namespace webrtc

View File

@ -42,7 +42,8 @@ namespace internal {
class VideoSendStream : public webrtc::VideoSendStream,
public webrtc::CpuOveruseObserver,
public webrtc::BitrateAllocatorObserver {
public webrtc::BitrateAllocatorObserver,
public webrtc::VCMProtectionCallback {
public:
VideoSendStream(int num_cpu_cores,
ProcessThread* module_process_thread,
@ -81,10 +82,18 @@ class VideoSendStream : public webrtc::VideoSendStream,
uint8_t fraction_loss,
int64_t rtt) override;
// Implements webrtc::VCMProtectionCallback.
int ProtectionRequest(const FecProtectionParams* delta_params,
const FecProtectionParams* key_params,
uint32_t* sent_video_rate_bps,
uint32_t* sent_nack_rate_bps,
uint32_t* sent_fec_rate_bps) override;
private:
static bool EncoderThreadFunction(void* obj);
void EncoderProcess();
void ConfigureProtection();
void ConfigureSsrcs();
SendStatisticsProxy stats_proxy_;
@ -103,16 +112,14 @@ class VideoSendStream : public webrtc::VideoSendStream,
volatile int stop_encoder_thread_;
OveruseFrameDetector overuse_detector_;
PayloadRouter payload_router_;
EncoderStateFeedback encoder_feedback_;
ViEChannel vie_channel_;
ViEReceiver* const vie_receiver_;
ViEEncoder vie_encoder_;
VideoCodingModule* const vcm_;
// TODO(pbos): Move RtpRtcp ownership to VideoSendStream.
// RtpRtcp modules, currently owned by ViEChannel but ownership should
// eventually move here.
const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
// RtpRtcp modules, declared here as they use other members on construction.
const std::vector<RtpRtcp*> rtp_rtcp_modules_;
PayloadRouter payload_router_;
VideoCaptureInput input_;
};
} // namespace internal

View File

@ -35,10 +35,47 @@
namespace webrtc {
static const int kMinSendSidePacketHistorySize = 600;
static const int kMaxPacketAgeToNack = 450;
static const int kMaxNackListSize = 250;
namespace {
std::unique_ptr<RtpRtcp> CreateRtpRtcpModule(
ReceiveStatistics* receive_statistics,
Transport* outgoing_transport,
RtcpRttStats* rtt_stats,
RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtpPacketSender* paced_sender,
TransportSequenceNumberAllocator* transport_sequence_number_allocator) {
RtpRtcp::Configuration configuration;
configuration.audio = false;
configuration.receiver_only = true;
configuration.receive_statistics = receive_statistics;
configuration.outgoing_transport = outgoing_transport;
configuration.intra_frame_callback = nullptr;
configuration.rtt_stats = rtt_stats;
configuration.rtcp_packet_type_counter_observer =
rtcp_packet_type_counter_observer;
configuration.paced_sender = paced_sender;
configuration.transport_sequence_number_allocator =
transport_sequence_number_allocator;
configuration.send_bitrate_observer = nullptr;
configuration.send_frame_count_observer = nullptr;
configuration.send_side_delay_observer = nullptr;
configuration.bandwidth_callback = nullptr;
configuration.transport_feedback_callback = nullptr;
std::unique_ptr<RtpRtcp> rtp_rtcp(RtpRtcp::CreateRtpRtcp(configuration));
rtp_rtcp->SetSendingStatus(false);
rtp_rtcp->SetSendingMediaStatus(false);
rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
return rtp_rtcp;
}
} // namespace
// Helper class receiving statistics callbacks.
class ChannelStatsObserver : public CallStatsObserver {
public:
@ -54,103 +91,46 @@ class ChannelStatsObserver : public CallStatsObserver {
ViEChannel* const owner_;
};
class ViEChannelProtectionCallback : public VCMProtectionCallback {
public:
explicit ViEChannelProtectionCallback(ViEChannel* owner) : owner_(owner) {}
~ViEChannelProtectionCallback() {}
int ProtectionRequest(
const FecProtectionParams* delta_fec_params,
const FecProtectionParams* key_fec_params,
uint32_t* sent_video_rate_bps,
uint32_t* sent_nack_rate_bps,
uint32_t* sent_fec_rate_bps) override {
return owner_->ProtectionRequest(delta_fec_params, key_fec_params,
sent_video_rate_bps, sent_nack_rate_bps,
sent_fec_rate_bps);
}
private:
ViEChannel* owner_;
};
ViEChannel::ViEChannel(Transport* transport,
ProcessThread* module_process_thread,
PayloadRouter* send_payload_router,
VideoCodingModule* vcm,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
TransportFeedbackObserver* transport_feedback_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttStats* rtt_stats,
PacedSender* paced_sender,
PacketRouter* packet_router,
size_t max_rtp_streams,
bool sender)
: sender_(sender),
module_process_thread_(module_process_thread),
send_payload_router_(send_payload_router),
vcm_protection_callback_(new ViEChannelProtectionCallback(this)),
PacketRouter* packet_router)
: module_process_thread_(module_process_thread),
vcm_(vcm),
vie_receiver_(vcm_, remote_bitrate_estimator, this),
stats_observer_(new ChannelStatsObserver(this)),
receive_stats_callback_(nullptr),
incoming_video_stream_(nullptr),
intra_frame_observer_(intra_frame_observer),
rtt_stats_(rtt_stats),
paced_sender_(paced_sender),
packet_router_(packet_router),
bandwidth_observer_(bandwidth_observer),
transport_feedback_observer_(transport_feedback_observer),
max_nack_reordering_threshold_(kMaxPacketAgeToNack),
pre_render_callback_(nullptr),
last_rtt_ms_(0),
rtp_rtcp_modules_(
CreateRtpRtcpModules(!sender,
vie_receiver_.GetReceiveStatistics(),
rtp_rtcp_(CreateRtpRtcpModule(vie_receiver_.GetReceiveStatistics(),
transport,
intra_frame_observer_,
bandwidth_observer_.get(),
transport_feedback_observer_,
rtt_stats_,
&rtcp_packet_type_counter_observer_,
remote_bitrate_estimator,
paced_sender_,
packet_router_,
&send_bitrate_observer_,
&send_frame_count_observer_,
&send_side_delay_observer_,
max_rtp_streams)) {
vie_receiver_.Init(rtp_rtcp_modules_);
if (sender_) {
RTC_DCHECK(send_payload_router_);
RTC_DCHECK(!vcm_);
} else {
RTC_DCHECK(!send_payload_router_);
packet_router_)) {
vie_receiver_.Init(rtp_rtcp_.get());
RTC_DCHECK(vcm_);
vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
}
}
int32_t ViEChannel::Init() {
static const int kDefaultRenderDelayMs = 10;
module_process_thread_->RegisterModule(vie_receiver_.GetReceiveStatistics());
// RTP/RTCP initialization.
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
module_process_thread_->RegisterModule(rtp_rtcp);
packet_router_->AddRtpModule(rtp_rtcp);
}
module_process_thread_->RegisterModule(rtp_rtcp_.get());
packet_router_->AddRtpModule(rtp_rtcp_.get());
rtp_rtcp_modules_[0]->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp);
if (paced_sender_) {
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
}
if (sender_) {
send_payload_router_->SetSendingRtpModules(1);
RTC_DCHECK(!send_payload_router_->active());
} else {
rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp);
if (vcm_->RegisterReceiveCallback(this) != 0) {
return -1;
}
@ -158,7 +138,7 @@ int32_t ViEChannel::Init() {
vcm_->RegisterReceiveStatisticsCallback(this);
vcm_->RegisterDecoderTimingCallback(this);
vcm_->SetRenderDelay(kDefaultRenderDelayMs);
}
return 0;
}
@ -166,14 +146,9 @@ ViEChannel::~ViEChannel() {
// Make sure we don't get more callbacks from the RTP module.
module_process_thread_->DeRegisterModule(
vie_receiver_.GetReceiveStatistics());
if (sender_) {
send_payload_router_->SetSendingRtpModules(0);
}
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
packet_router_->RemoveRtpModule(rtp_rtcp);
module_process_thread_->DeRegisterModule(rtp_rtcp);
delete rtp_rtcp;
}
packet_router_->RemoveRtpModule(rtp_rtcp_.get());
module_process_thread_->DeRegisterModule(rtp_rtcp_.get());
}
void ViEChannel::SetProtectionMode(bool enable_nack,
@ -203,44 +178,32 @@ void ViEChannel::SetProtectionMode(bool enable_nack,
protection_method = kProtectionNone;
}
if (!sender_)
vcm_->SetVideoProtection(protection_method, true);
// Set NACK.
ProcessNACKRequest(enable_nack);
// Set FEC.
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
rtp_rtcp->SetGenericFECStatus(enable_fec,
rtp_rtcp_->SetGenericFECStatus(enable_fec,
static_cast<uint8_t>(payload_type_red),
static_cast<uint8_t>(payload_type_fec));
}
}
void ViEChannel::ProcessNACKRequest(const bool enable) {
if (enable) {
// Turn on NACK.
if (rtp_rtcp_modules_[0]->RTCP() == RtcpMode::kOff)
if (rtp_rtcp_->RTCP() == RtcpMode::kOff)
return;
vie_receiver_.SetNackStatus(true, max_nack_reordering_threshold_);
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
if (!sender_) {
vcm_->RegisterPacketRequestCallback(this);
// Don't introduce errors when NACK is enabled.
vcm_->SetDecodeErrorMode(kNoErrors);
}
} else {
if (!sender_) {
vcm_->RegisterPacketRequestCallback(nullptr);
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
rtp_rtcp->SetStorePacketsStatus(false, 0);
// When NACK is off, allow decoding with errors. Otherwise, the video
// will freeze, and will only recover with a complete key frame.
vcm_->SetDecodeErrorMode(kWithErrors);
}
vie_receiver_.SetNackStatus(false, max_nack_reordering_threshold_);
}
}
@ -253,14 +216,9 @@ int ViEChannel::GetRequiredNackListSize(int target_delay_ms) {
}
RtpState ViEChannel::GetRtpStateForSsrc(uint32_t ssrc) const {
RTC_DCHECK(!rtp_rtcp_modules_[0]->Sending());
RtpState rtp_state;
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
if (rtp_rtcp->GetRtpStateForSsrc(ssrc, &rtp_state))
return rtp_state;
}
LOG(LS_ERROR) << "Couldn't get RTP state for ssrc: " << ssrc;
return rtp_state;
RTC_DCHECK(!rtp_rtcp_->Sending());
RTC_DCHECK_EQ(ssrc, rtp_rtcp_->SSRC());
return rtp_rtcp_->GetRtpState();
}
void ViEChannel::RegisterRtcpPacketTypeCounterObserver(
@ -268,42 +226,14 @@ void ViEChannel::RegisterRtcpPacketTypeCounterObserver(
rtcp_packet_type_counter_observer_.Set(observer);
}
void ViEChannel::GetSendStreamDataCounters(
StreamDataCounters* rtp_counters,
StreamDataCounters* rtx_counters) const {
*rtp_counters = StreamDataCounters();
*rtx_counters = StreamDataCounters();
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
StreamDataCounters rtp_data;
StreamDataCounters rtx_data;
rtp_rtcp->GetSendStreamDataCounters(&rtp_data, &rtx_data);
rtp_counters->Add(rtp_data);
rtx_counters->Add(rtx_data);
}
}
void ViEChannel::RegisterSendSideDelayObserver(
SendSideDelayObserver* observer) {
send_side_delay_observer_.Set(observer);
}
void ViEChannel::RegisterSendBitrateObserver(
BitrateStatisticsObserver* observer) {
send_bitrate_observer_.Set(observer);
}
const std::vector<RtpRtcp*>& ViEChannel::rtp_rtcp() const {
return rtp_rtcp_modules_;
RtpRtcp* ViEChannel::rtp_rtcp() const {
return rtp_rtcp_.get();
}
ViEReceiver* ViEChannel::vie_receiver() {
return &vie_receiver_;
}
VCMProtectionCallback* ViEChannel::vcm_protection_callback() {
return vcm_protection_callback_.get();
}
CallStatsObserver* ViEChannel::GetStatsObserver() {
return stats_observer_.get();
}
@ -325,7 +255,7 @@ int32_t ViEChannel::FrameToRender(VideoFrame& video_frame) { // NOLINT
int32_t ViEChannel::ReceivedDecodedReferenceFrame(
const uint64_t picture_id) {
return rtp_rtcp_modules_[0]->SendRTCPReferencePictureSelection(picture_id);
return rtp_rtcp_->SendRTCPReferencePictureSelection(picture_id);
}
void ViEChannel::OnIncomingPayloadType(int payload_type) {
@ -375,105 +305,29 @@ void ViEChannel::OnDecoderTiming(int decode_ms,
}
int32_t ViEChannel::RequestKeyFrame() {
return rtp_rtcp_modules_[0]->RequestKeyFrame();
return rtp_rtcp_->RequestKeyFrame();
}
int32_t ViEChannel::SliceLossIndicationRequest(
const uint64_t picture_id) {
return rtp_rtcp_modules_[0]->SendRTCPSliceLossIndication(
return rtp_rtcp_->SendRTCPSliceLossIndication(
static_cast<uint8_t>(picture_id));
}
int32_t ViEChannel::ResendPackets(const uint16_t* sequence_numbers,
uint16_t length) {
return rtp_rtcp_modules_[0]->SendNACK(sequence_numbers, length);
return rtp_rtcp_->SendNACK(sequence_numbers, length);
}
void ViEChannel::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
if (!sender_)
vcm_->SetReceiveChannelParameters(max_rtt_ms);
rtc::CritScope lock(&crit_);
last_rtt_ms_ = avg_rtt_ms;
}
int ViEChannel::ProtectionRequest(const FecProtectionParams* delta_fec_params,
const FecProtectionParams* key_fec_params,
uint32_t* video_rate_bps,
uint32_t* nack_rate_bps,
uint32_t* fec_rate_bps) {
*video_rate_bps = 0;
*nack_rate_bps = 0;
*fec_rate_bps = 0;
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
uint32_t not_used = 0;
uint32_t module_video_rate = 0;
uint32_t module_fec_rate = 0;
uint32_t module_nack_rate = 0;
rtp_rtcp->SetFecParameters(delta_fec_params, key_fec_params);
rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
&module_nack_rate);
*video_rate_bps += module_video_rate;
*nack_rate_bps += module_nack_rate;
*fec_rate_bps += module_fec_rate;
}
return 0;
}
std::vector<RtpRtcp*> ViEChannel::CreateRtpRtcpModules(
bool receiver_only,
ReceiveStatistics* receive_statistics,
Transport* outgoing_transport,
RtcpIntraFrameObserver* intra_frame_callback,
RtcpBandwidthObserver* bandwidth_callback,
TransportFeedbackObserver* transport_feedback_callback,
RtcpRttStats* rtt_stats,
RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtpPacketSender* paced_sender,
TransportSequenceNumberAllocator* transport_sequence_number_allocator,
BitrateStatisticsObserver* send_bitrate_observer,
FrameCountObserver* send_frame_count_observer,
SendSideDelayObserver* send_side_delay_observer,
size_t num_modules) {
RTC_DCHECK_GT(num_modules, 0u);
RtpRtcp::Configuration configuration;
ReceiveStatistics* null_receive_statistics = configuration.receive_statistics;
configuration.audio = false;
configuration.receiver_only = receiver_only;
configuration.receive_statistics = receive_statistics;
configuration.outgoing_transport = outgoing_transport;
configuration.intra_frame_callback = intra_frame_callback;
configuration.rtt_stats = rtt_stats;
configuration.rtcp_packet_type_counter_observer =
rtcp_packet_type_counter_observer;
configuration.paced_sender = paced_sender;
configuration.transport_sequence_number_allocator =
transport_sequence_number_allocator;
configuration.send_bitrate_observer = send_bitrate_observer;
configuration.send_frame_count_observer = send_frame_count_observer;
configuration.send_side_delay_observer = send_side_delay_observer;
configuration.bandwidth_callback = bandwidth_callback;
configuration.transport_feedback_callback = transport_feedback_callback;
std::vector<RtpRtcp*> modules;
for (size_t i = 0; i < num_modules; ++i) {
RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
rtp_rtcp->SetSendingStatus(false);
rtp_rtcp->SetSendingMediaStatus(false);
rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
modules.push_back(rtp_rtcp);
// Receive statistics and remote bitrate estimator should only be set for
// the primary (first) module.
configuration.receive_statistics = null_receive_statistics;
configuration.remote_bitrate_estimator = nullptr;
}
return modules;
}
void ViEChannel::RegisterPreRenderCallback(
I420FrameCallback* pre_render_callback) {
RTC_DCHECK(!sender_);
rtc::CritScope lock(&crit_);
pre_render_callback_ = pre_render_callback;
}
@ -491,16 +345,11 @@ int32_t ViEChannel::OnInitializeDecoder(
}
void ViEChannel::OnIncomingSSRCChanged(const uint32_t ssrc) {
rtp_rtcp_modules_[0]->SetRemoteSSRC(ssrc);
rtp_rtcp_->SetRemoteSSRC(ssrc);
}
void ViEChannel::OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) {}
void ViEChannel::RegisterSendFrameCountObserver(
FrameCountObserver* observer) {
send_frame_count_observer_.Set(observer);
}
void ViEChannel::RegisterReceiveStatisticsProxy(
ReceiveStatisticsProxy* receive_statistics_proxy) {
rtc::CritScope lock(&crit_);

View File

@ -42,7 +42,6 @@ class PayloadRouter;
class ProcessThread;
class ReceiveStatisticsProxy;
class RtcpRttStats;
class ViEChannelProtectionCallback;
class ViERTPObserver;
class VideoCodingModule;
class VideoRenderCallback;
@ -61,21 +60,14 @@ class ViEChannel : public VCMFrameTypeCallback,
public RtpFeedback {
public:
friend class ChannelStatsObserver;
friend class ViEChannelProtectionCallback;
ViEChannel(Transport* transport,
ProcessThread* module_process_thread,
PayloadRouter* send_payload_router,
VideoCodingModule* vcm,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
TransportFeedbackObserver* transport_feedback_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttStats* rtt_stats,
PacedSender* paced_sender,
PacketRouter* packet_router,
size_t max_rtp_streams,
bool sender);
PacketRouter* packet_router);
~ViEChannel();
int32_t Init();
@ -87,15 +79,6 @@ class ViEChannel : public VCMFrameTypeCallback,
RtpState GetRtpStateForSsrc(uint32_t ssrc) const;
// Gets send statistics for the rtp and rtx stream.
void GetSendStreamDataCounters(StreamDataCounters* rtp_counters,
StreamDataCounters* rtx_counters) const;
void RegisterSendSideDelayObserver(SendSideDelayObserver* observer);
// Called on any new send bitrate estimate.
void RegisterSendBitrateObserver(BitrateStatisticsObserver* observer);
// Implements RtpFeedback.
int32_t OnInitializeDecoder(const int8_t payload_type,
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
@ -105,11 +88,9 @@ class ViEChannel : public VCMFrameTypeCallback,
void OnIncomingSSRCChanged(const uint32_t ssrc) override;
void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) override;
// Gets the modules used by the channel.
const std::vector<RtpRtcp*>& rtp_rtcp() const;
// Gets the module used by the channel.
RtpRtcp* rtp_rtcp() const;
ViEReceiver* vie_receiver();
VCMProtectionCallback* vcm_protection_callback();
CallStatsObserver* GetStatsObserver();
@ -151,7 +132,6 @@ class ViEChannel : public VCMFrameTypeCallback,
void RegisterPreRenderCallback(I420FrameCallback* pre_render_callback);
void RegisterSendFrameCountObserver(FrameCountObserver* observer);
void RegisterRtcpPacketTypeCounterObserver(
RtcpPacketTypeCounterObserver* observer);
void RegisterReceiveStatisticsProxy(
@ -161,30 +141,7 @@ class ViEChannel : public VCMFrameTypeCallback,
protected:
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms);
int ProtectionRequest(const FecProtectionParams* delta_fec_params,
const FecProtectionParams* key_fec_params,
uint32_t* sent_video_rate_bps,
uint32_t* sent_nack_rate_bps,
uint32_t* sent_fec_rate_bps);
private:
static std::vector<RtpRtcp*> CreateRtpRtcpModules(
bool receiver_only,
ReceiveStatistics* receive_statistics,
Transport* outgoing_transport,
RtcpIntraFrameObserver* intra_frame_callback,
RtcpBandwidthObserver* bandwidth_callback,
TransportFeedbackObserver* transport_feedback_callback,
RtcpRttStats* rtt_stats,
RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtpPacketSender* paced_sender,
TransportSequenceNumberAllocator* transport_sequence_number_allocator,
BitrateStatisticsObserver* send_bitrate_observer,
FrameCountObserver* send_frame_count_observer,
SendSideDelayObserver* send_side_delay_observer,
size_t num_modules);
// Assumed to be protected.
void StartDecodeThread();
void StopDecodeThread();
@ -219,41 +176,6 @@ class ViEChannel : public VCMFrameTypeCallback,
RTC_DISALLOW_COPY_AND_ASSIGN(RegisterableCallback);
};
class RegisterableBitrateStatisticsObserver:
public RegisterableCallback<BitrateStatisticsObserver> {
virtual void Notify(const BitrateStatistics& total_stats,
const BitrateStatistics& retransmit_stats,
uint32_t ssrc) {
rtc::CritScope lock(&critsect_);
if (callback_)
callback_->Notify(total_stats, retransmit_stats, ssrc);
}
} send_bitrate_observer_;
class RegisterableFrameCountObserver
: public RegisterableCallback<FrameCountObserver> {
public:
virtual void FrameCountUpdated(const FrameCounts& frame_counts,
uint32_t ssrc) {
rtc::CritScope lock(&critsect_);
if (callback_)
callback_->FrameCountUpdated(frame_counts, ssrc);
}
private:
} send_frame_count_observer_;
class RegisterableSendSideDelayObserver :
public RegisterableCallback<SendSideDelayObserver> {
void SendSideDelayUpdated(int avg_delay_ms,
int max_delay_ms,
uint32_t ssrc) override {
rtc::CritScope lock(&critsect_);
if (callback_)
callback_->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
}
} send_side_delay_observer_;
class RegisterableRtcpPacketTypeCounterObserver
: public RegisterableCallback<RtcpPacketTypeCounterObserver> {
public:
@ -268,17 +190,12 @@ class ViEChannel : public VCMFrameTypeCallback,
private:
} rtcp_packet_type_counter_observer_;
const bool sender_;
ProcessThread* const module_process_thread_;
PayloadRouter* const send_payload_router_;
// Used for all registered callbacks except rendering.
rtc::CriticalSection crit_;
// Owned modules/classes.
std::unique_ptr<ViEChannelProtectionCallback> vcm_protection_callback_;
VideoCodingModule* const vcm_;
ViEReceiver vie_receiver_;
@ -289,21 +206,17 @@ class ViEChannel : public VCMFrameTypeCallback,
ReceiveStatisticsProxy* receive_stats_callback_ GUARDED_BY(crit_);
FrameCounts receive_frame_counts_ GUARDED_BY(crit_);
IncomingVideoStream* incoming_video_stream_ GUARDED_BY(crit_);
RtcpIntraFrameObserver* const intra_frame_observer_;
RtcpRttStats* const rtt_stats_;
PacedSender* const paced_sender_;
PacketRouter* const packet_router_;
const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
TransportFeedbackObserver* const transport_feedback_observer_;
int max_nack_reordering_threshold_;
I420FrameCallback* pre_render_callback_ GUARDED_BY(crit_);
int64_t last_rtt_ms_ GUARDED_BY(crit_);
// RtpRtcp modules, declared last as they use other members on construction.
const std::vector<RtpRtcp*> rtp_rtcp_modules_;
// RtpRtcp module, declared last as it use other members on construction.
const std::unique_ptr<RtpRtcp> rtp_rtcp_;
};
} // namespace webrtc

View File

@ -124,8 +124,8 @@ int ViEReceiver::GetCsrcs(uint32_t* csrcs) const {
return rtp_receiver_->CSRCs(csrcs);
}
void ViEReceiver::Init(const std::vector<RtpRtcp*>& modules) {
rtp_rtcp_ = modules;
void ViEReceiver::Init(RtpRtcp* rtp_rtcp) {
rtp_rtcp_ = rtp_rtcp;
}
RtpReceiver* ViEReceiver::GetRtpReceiver() const {
@ -318,8 +318,6 @@ void ViEReceiver::NotifyReceiverOfFecPacket(const RTPHeader& header) {
bool ViEReceiver::DeliverRtcp(const uint8_t* rtcp_packet,
size_t rtcp_packet_length) {
// Should be set by owner at construction time.
RTC_DCHECK(!rtp_rtcp_.empty());
{
rtc::CritScope lock(&receive_cs_);
if (!receiving_) {
@ -327,11 +325,10 @@ bool ViEReceiver::DeliverRtcp(const uint8_t* rtcp_packet,
}
}
for (RtpRtcp* rtp_rtcp : rtp_rtcp_)
rtp_rtcp->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
rtp_rtcp_->IncomingRtcpPacket(rtcp_packet, rtcp_packet_length);
int64_t rtt = 0;
rtp_rtcp_[0]->RTT(rtp_receiver_->SSRC(), &rtt, nullptr, nullptr, nullptr);
rtp_rtcp_->RTT(rtp_receiver_->SSRC(), &rtt, nullptr, nullptr, nullptr);
if (rtt == 0) {
// Waiting for valid rtt.
return true;
@ -339,7 +336,7 @@ bool ViEReceiver::DeliverRtcp(const uint8_t* rtcp_packet,
uint32_t ntp_secs = 0;
uint32_t ntp_frac = 0;
uint32_t rtp_timestamp = 0;
if (rtp_rtcp_[0]->RemoteNTP(&ntp_secs, &ntp_frac, nullptr, nullptr,
if (rtp_rtcp_->RemoteNTP(&ntp_secs, &ntp_frac, nullptr, nullptr,
&rtp_timestamp) != 0) {
// Waiting for RTCP.
return true;
@ -382,7 +379,7 @@ bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
return false;
// Check if this is a retransmission.
int64_t min_rtt = 0;
rtp_rtcp_[0]->RTT(rtp_receiver_->SSRC(), nullptr, nullptr, &min_rtt, nullptr);
rtp_rtcp_->RTT(rtp_receiver_->SSRC(), nullptr, nullptr, &min_rtt, nullptr);
return !in_order &&
statistician->IsRetransmitOfOldPacket(header, min_rtt);
}

View File

@ -60,7 +60,7 @@ class ViEReceiver : public RtpData {
uint32_t GetRemoteSsrc() const;
int GetCsrcs(uint32_t* csrcs) const;
void Init(const std::vector<RtpRtcp*>& modules);
void Init(RtpRtcp* rtp_rtcp);
RtpReceiver* GetRtpReceiver() const;
@ -102,7 +102,7 @@ class ViEReceiver : public RtpData {
RemoteBitrateEstimator* const remote_bitrate_estimator_;
// TODO(pbos): Make const and set on construction.
std::vector<RtpRtcp*> rtp_rtcp_;
RtpRtcp* rtp_rtcp_; // Owned by ViEChannel
RemoteNtpTimeEstimator ntp_estimator_;
RTPPayloadRegistry rtp_payload_registry_;