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; virtual void SetSequenceNumber(uint16_t seq) = 0;
// Returns true if the ssrc matched this module, false otherwise. virtual void SetRtpState(const RtpState& rtp_state) = 0;
virtual bool SetRtpStateForSsrc(uint32_t ssrc, virtual void SetRtxState(const RtpState& rtp_state) = 0;
const RtpState& rtp_state) = 0; virtual RtpState GetRtpState() const = 0;
virtual bool GetRtpStateForSsrc(uint32_t ssrc, RtpState* rtp_state) = 0; virtual RtpState GetRtxState() const = 0;
/* /*
* Get SSRC * Get SSRC

View File

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

View File

@ -871,11 +871,13 @@ void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2); random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext; next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
StatisticianMap statisticians = if (receive_statistics_) {
receive_statistics_->GetActiveStatisticians(); StatisticianMap statisticians =
RTC_DCHECK(report_blocks_.empty()); receive_statistics_->GetActiveStatisticians();
for (auto& it : statisticians) { RTC_DCHECK(report_blocks_.empty());
AddReportBlock(feedback_state, it.first, it.second); for (auto& it : statisticians) {
AddReportBlock(feedback_state, it.first, it.second);
}
} }
} }
} }

View File

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

View File

@ -75,8 +75,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
// Set SequenceNumber, default is a random number. // Set SequenceNumber, default is a random number.
void SetSequenceNumber(uint16_t seq) override; void SetSequenceNumber(uint16_t seq) override;
bool SetRtpStateForSsrc(uint32_t ssrc, const RtpState& rtp_state) override; void SetRtpState(const RtpState& rtp_state) override;
bool GetRtpStateForSsrc(uint32_t ssrc, RtpState* rtp_state) override; void SetRtxState(const RtpState& rtp_state) override;
RtpState GetRtpState() const override;
RtpState GetRtxState() const override;
uint32_t SSRC() 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; 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) { bool EncoderStateFeedback::HasSsrc(uint32_t ssrc) {
for (uint32_t registered_ssrc : ssrcs_) { for (uint32_t registered_ssrc : ssrcs_) {
if (registered_ssrc == ssrc) 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. // Adds an encoder to receive feedback for a set of SSRCs.
void Init(const std::vector<uint32_t>& ssrc, ViEEncoder* encoder); 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 OnReceivedIntraFrameRequest(uint32_t ssrc) override;
void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) override; void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) override;
void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) override; void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) override;

View File

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

View File

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

View File

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

View File

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

View File

@ -34,6 +34,52 @@ namespace webrtc {
class RtcpIntraFrameObserver; class RtcpIntraFrameObserver;
class TransportFeedbackObserver; 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 std::string
VideoSendStream::Config::EncoderSettings::ToString() const { VideoSendStream::Config::EncoderSettings::ToString() const {
std::stringstream ss; std::stringstream ss;
@ -183,21 +229,6 @@ VideoSendStream::VideoSendStream(
this, this,
config.post_encode_callback, config.post_encode_callback,
&stats_proxy_), &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, vie_encoder_(num_cpu_cores,
config_.rtp.ssrcs, config_.rtp.ssrcs,
module_process_thread_, module_process_thread_,
@ -207,7 +238,19 @@ VideoSendStream::VideoSendStream(
congestion_controller_->pacer(), congestion_controller_->pacer(),
&payload_router_), &payload_router_),
vcm_(vie_encoder_.vcm()), 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_, input_(&encoder_wakeup_event_,
config_.local_renderer, config_.local_renderer,
&stats_proxy_, &stats_proxy_,
@ -220,14 +263,16 @@ VideoSendStream::VideoSendStream(
RTC_DCHECK(congestion_controller_); RTC_DCHECK(congestion_controller_);
RTC_DCHECK(remb_); RTC_DCHECK(remb_);
payload_router_.Init(rtp_rtcp_modules_);
RTC_CHECK(vie_encoder_.Init()); RTC_CHECK(vie_encoder_.Init());
encoder_feedback_.Init(config_.rtp.ssrcs, &vie_encoder_); 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) { for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
const std::string& extension = config_.rtp.extensions[i].name; const std::string& extension = config_.rtp.extensions[i].name;
@ -245,28 +290,7 @@ VideoSendStream::VideoSendStream(
remb_->AddRembSender(rtp_rtcp_modules_[0]); remb_->AddRembSender(rtp_rtcp_modules_[0]);
rtp_rtcp_modules_[0]->SetREMBStatus(true); rtp_rtcp_modules_[0]->SetREMBStatus(true);
// Enable NACK, FEC or both. ConfigureProtection();
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);
ConfigureSsrcs(); ConfigureSsrcs();
// TODO(pbos): Should we set CNAME on all RTP modules? // TODO(pbos): Should we set CNAME on all RTP modules?
@ -295,8 +319,6 @@ VideoSendStream::VideoSendStream(
ReconfigureVideoEncoder(encoder_config); ReconfigureVideoEncoder(encoder_config);
vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_);
if (config_.post_encode_callback) if (config_.post_encode_callback)
vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_);
@ -305,10 +327,6 @@ VideoSendStream::VideoSendStream(
bitrate_allocator_->EnforceMinBitrate(false); 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_); module_process_thread_->RegisterModule(&overuse_detector_);
encoder_thread_.Start(); encoder_thread_.Start();
@ -330,22 +348,17 @@ VideoSendStream::~VideoSendStream() {
bitrate_allocator_->RemoveObserver(this); bitrate_allocator_->RemoveObserver(this);
module_process_thread_->DeRegisterModule(&overuse_detector_); 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); vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type);
call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver());
rtp_rtcp_modules_[0]->SetREMBStatus(false); rtp_rtcp_modules_[0]->SetREMBStatus(false);
remb_->RemoveRembSender(rtp_rtcp_modules_[0]); remb_->RemoveRembSender(rtp_rtcp_modules_[0]);
// ViEChannel outlives ViEEncoder so remove encoder from feedback before for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
// destruction. congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp);
encoder_feedback_.TearDown(); module_process_thread_->DeRegisterModule(rtp_rtcp);
delete rtp_rtcp;
congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( }
vie_receiver_->GetRemoteSsrc());
} }
VideoCaptureInput* VideoSendStream::Input() { VideoCaptureInput* VideoSendStream::Input() {
@ -361,7 +374,6 @@ void VideoSendStream::Start() {
// Was not already started, trigger a keyframe. // Was not already started, trigger a keyframe.
vie_encoder_.SendKeyFrame(); vie_encoder_.SendKeyFrame();
vie_encoder_.Restart(); vie_encoder_.Restart();
vie_receiver_->StartReceive();
} }
void VideoSendStream::Stop() { void VideoSendStream::Stop() {
@ -370,7 +382,6 @@ void VideoSendStream::Stop() {
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop"); TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
// TODO(pbos): Make sure the encoder stops here. // TODO(pbos): Make sure the encoder stops here.
payload_router_.set_active(false); payload_router_.set_active(false);
vie_receiver_->StopReceive();
} }
bool VideoSendStream::EncoderThreadFunction(void* obj) { bool VideoSendStream::EncoderThreadFunction(void* obj) {
@ -535,7 +546,9 @@ void VideoSendStream::ReconfigureVideoEncoder(
} }
bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { 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() { VideoSendStream::Stats VideoSendStream::GetStats() {
@ -552,6 +565,60 @@ void VideoSendStream::NormalUsage() {
config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); 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() { void VideoSendStream::ConfigureSsrcs() {
// Configure regular SSRCs. // Configure regular SSRCs.
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
@ -562,7 +629,7 @@ void VideoSendStream::ConfigureSsrcs() {
// Restore RTP state if previous existed. // Restore RTP state if previous existed.
RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
if (it != suspended_ssrcs_.end()) if (it != suspended_ssrcs_.end())
rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); rtp_rtcp->SetRtpState(it->second);
} }
// Set up RTX if available. // Set up RTX if available.
@ -577,7 +644,7 @@ void VideoSendStream::ConfigureSsrcs() {
rtp_rtcp->SetRtxSsrc(ssrc); rtp_rtcp->SetRtxSsrc(ssrc);
RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
if (it != suspended_ssrcs_.end()) if (it != suspended_ssrcs_.end())
rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); rtp_rtcp->SetRtxState(it->second);
} }
// Configure RTX payload types. // Configure RTX payload types.
@ -600,12 +667,13 @@ std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const {
std::map<uint32_t, RtpState> rtp_states; std::map<uint32_t, RtpState> rtp_states;
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
uint32_t ssrc = config_.rtp.ssrcs[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) { for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
uint32_t ssrc = config_.rtp.rtx.ssrcs[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; return rtp_states;
@ -636,5 +704,28 @@ void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps,
vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt); 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 internal
} // namespace webrtc } // namespace webrtc

View File

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

View File

@ -35,10 +35,47 @@
namespace webrtc { namespace webrtc {
static const int kMinSendSidePacketHistorySize = 600;
static const int kMaxPacketAgeToNack = 450; static const int kMaxPacketAgeToNack = 450;
static const int kMaxNackListSize = 250; 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. // Helper class receiving statistics callbacks.
class ChannelStatsObserver : public CallStatsObserver { class ChannelStatsObserver : public CallStatsObserver {
public: public:
@ -54,82 +91,35 @@ class ChannelStatsObserver : public CallStatsObserver {
ViEChannel* const owner_; 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, ViEChannel::ViEChannel(Transport* transport,
ProcessThread* module_process_thread, ProcessThread* module_process_thread,
PayloadRouter* send_payload_router,
VideoCodingModule* vcm, VideoCodingModule* vcm,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
TransportFeedbackObserver* transport_feedback_observer,
RemoteBitrateEstimator* remote_bitrate_estimator, RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttStats* rtt_stats, RtcpRttStats* rtt_stats,
PacedSender* paced_sender, PacedSender* paced_sender,
PacketRouter* packet_router, PacketRouter* packet_router)
size_t max_rtp_streams, : module_process_thread_(module_process_thread),
bool sender)
: sender_(sender),
module_process_thread_(module_process_thread),
send_payload_router_(send_payload_router),
vcm_protection_callback_(new ViEChannelProtectionCallback(this)),
vcm_(vcm), vcm_(vcm),
vie_receiver_(vcm_, remote_bitrate_estimator, this), vie_receiver_(vcm_, remote_bitrate_estimator, this),
stats_observer_(new ChannelStatsObserver(this)), stats_observer_(new ChannelStatsObserver(this)),
receive_stats_callback_(nullptr), receive_stats_callback_(nullptr),
incoming_video_stream_(nullptr), incoming_video_stream_(nullptr),
intra_frame_observer_(intra_frame_observer),
rtt_stats_(rtt_stats), rtt_stats_(rtt_stats),
paced_sender_(paced_sender), paced_sender_(paced_sender),
packet_router_(packet_router), packet_router_(packet_router),
bandwidth_observer_(bandwidth_observer),
transport_feedback_observer_(transport_feedback_observer),
max_nack_reordering_threshold_(kMaxPacketAgeToNack), max_nack_reordering_threshold_(kMaxPacketAgeToNack),
pre_render_callback_(nullptr), pre_render_callback_(nullptr),
last_rtt_ms_(0), last_rtt_ms_(0),
rtp_rtcp_modules_( rtp_rtcp_(CreateRtpRtcpModule(vie_receiver_.GetReceiveStatistics(),
CreateRtpRtcpModules(!sender, transport,
vie_receiver_.GetReceiveStatistics(), rtt_stats_,
transport, &rtcp_packet_type_counter_observer_,
intra_frame_observer_, remote_bitrate_estimator,
bandwidth_observer_.get(), paced_sender_,
transport_feedback_observer_, packet_router_)) {
rtt_stats_, vie_receiver_.Init(rtp_rtcp_.get());
&rtcp_packet_type_counter_observer_, RTC_DCHECK(vcm_);
remote_bitrate_estimator, vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
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_);
RTC_DCHECK(vcm_);
vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
}
} }
int32_t ViEChannel::Init() { int32_t ViEChannel::Init() {
@ -137,28 +127,18 @@ int32_t ViEChannel::Init() {
module_process_thread_->RegisterModule(vie_receiver_.GetReceiveStatistics()); module_process_thread_->RegisterModule(vie_receiver_.GetReceiveStatistics());
// RTP/RTCP initialization. // RTP/RTCP initialization.
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { module_process_thread_->RegisterModule(rtp_rtcp_.get());
module_process_thread_->RegisterModule(rtp_rtcp); packet_router_->AddRtpModule(rtp_rtcp_.get());
packet_router_->AddRtpModule(rtp_rtcp);
}
rtp_rtcp_modules_[0]->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp); rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp);
if (paced_sender_) { if (vcm_->RegisterReceiveCallback(this) != 0) {
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) return -1;
rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
}
if (sender_) {
send_payload_router_->SetSendingRtpModules(1);
RTC_DCHECK(!send_payload_router_->active());
} else {
if (vcm_->RegisterReceiveCallback(this) != 0) {
return -1;
}
vcm_->RegisterFrameTypeCallback(this);
vcm_->RegisterReceiveStatisticsCallback(this);
vcm_->RegisterDecoderTimingCallback(this);
vcm_->SetRenderDelay(kDefaultRenderDelayMs);
} }
vcm_->RegisterFrameTypeCallback(this);
vcm_->RegisterReceiveStatisticsCallback(this);
vcm_->RegisterDecoderTimingCallback(this);
vcm_->SetRenderDelay(kDefaultRenderDelayMs);
return 0; return 0;
} }
@ -166,14 +146,9 @@ ViEChannel::~ViEChannel() {
// Make sure we don't get more callbacks from the RTP module. // Make sure we don't get more callbacks from the RTP module.
module_process_thread_->DeRegisterModule( module_process_thread_->DeRegisterModule(
vie_receiver_.GetReceiveStatistics()); vie_receiver_.GetReceiveStatistics());
if (sender_) {
send_payload_router_->SetSendingRtpModules(0); packet_router_->RemoveRtpModule(rtp_rtcp_.get());
} module_process_thread_->DeRegisterModule(rtp_rtcp_.get());
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
packet_router_->RemoveRtpModule(rtp_rtcp);
module_process_thread_->DeRegisterModule(rtp_rtcp);
delete rtp_rtcp;
}
} }
void ViEChannel::SetProtectionMode(bool enable_nack, void ViEChannel::SetProtectionMode(bool enable_nack,
@ -203,44 +178,32 @@ void ViEChannel::SetProtectionMode(bool enable_nack,
protection_method = kProtectionNone; protection_method = kProtectionNone;
} }
if (!sender_) vcm_->SetVideoProtection(protection_method, true);
vcm_->SetVideoProtection(protection_method, true);
// Set NACK. // Set NACK.
ProcessNACKRequest(enable_nack); ProcessNACKRequest(enable_nack);
// Set FEC. // 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_red), static_cast<uint8_t>(payload_type_fec));
static_cast<uint8_t>(payload_type_fec));
}
} }
void ViEChannel::ProcessNACKRequest(const bool enable) { void ViEChannel::ProcessNACKRequest(const bool enable) {
if (enable) { if (enable) {
// Turn on NACK. // Turn on NACK.
if (rtp_rtcp_modules_[0]->RTCP() == RtcpMode::kOff) if (rtp_rtcp_->RTCP() == RtcpMode::kOff)
return; return;
vie_receiver_.SetNackStatus(true, max_nack_reordering_threshold_); vie_receiver_.SetNackStatus(true, max_nack_reordering_threshold_);
vcm_->RegisterPacketRequestCallback(this);
// Don't introduce errors when NACK is enabled.
vcm_->SetDecodeErrorMode(kNoErrors);
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 { } else {
if (!sender_) { vcm_->RegisterPacketRequestCallback(nullptr);
vcm_->RegisterPacketRequestCallback(nullptr); // When NACK is off, allow decoding with errors. Otherwise, the video
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) // will freeze, and will only recover with a complete key frame.
rtp_rtcp->SetStorePacketsStatus(false, 0); vcm_->SetDecodeErrorMode(kWithErrors);
// 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_); 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 { RtpState ViEChannel::GetRtpStateForSsrc(uint32_t ssrc) const {
RTC_DCHECK(!rtp_rtcp_modules_[0]->Sending()); RTC_DCHECK(!rtp_rtcp_->Sending());
RtpState rtp_state; RTC_DCHECK_EQ(ssrc, rtp_rtcp_->SSRC());
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { return rtp_rtcp_->GetRtpState();
if (rtp_rtcp->GetRtpStateForSsrc(ssrc, &rtp_state))
return rtp_state;
}
LOG(LS_ERROR) << "Couldn't get RTP state for ssrc: " << ssrc;
return rtp_state;
} }
void ViEChannel::RegisterRtcpPacketTypeCounterObserver( void ViEChannel::RegisterRtcpPacketTypeCounterObserver(
@ -268,42 +226,14 @@ void ViEChannel::RegisterRtcpPacketTypeCounterObserver(
rtcp_packet_type_counter_observer_.Set(observer); rtcp_packet_type_counter_observer_.Set(observer);
} }
void ViEChannel::GetSendStreamDataCounters( RtpRtcp* ViEChannel::rtp_rtcp() const {
StreamDataCounters* rtp_counters, return rtp_rtcp_.get();
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_;
} }
ViEReceiver* ViEChannel::vie_receiver() { ViEReceiver* ViEChannel::vie_receiver() {
return &vie_receiver_; return &vie_receiver_;
} }
VCMProtectionCallback* ViEChannel::vcm_protection_callback() {
return vcm_protection_callback_.get();
}
CallStatsObserver* ViEChannel::GetStatsObserver() { CallStatsObserver* ViEChannel::GetStatsObserver() {
return stats_observer_.get(); return stats_observer_.get();
} }
@ -325,7 +255,7 @@ int32_t ViEChannel::FrameToRender(VideoFrame& video_frame) { // NOLINT
int32_t ViEChannel::ReceivedDecodedReferenceFrame( int32_t ViEChannel::ReceivedDecodedReferenceFrame(
const uint64_t picture_id) { 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) { void ViEChannel::OnIncomingPayloadType(int payload_type) {
@ -375,105 +305,29 @@ void ViEChannel::OnDecoderTiming(int decode_ms,
} }
int32_t ViEChannel::RequestKeyFrame() { int32_t ViEChannel::RequestKeyFrame() {
return rtp_rtcp_modules_[0]->RequestKeyFrame(); return rtp_rtcp_->RequestKeyFrame();
} }
int32_t ViEChannel::SliceLossIndicationRequest( int32_t ViEChannel::SliceLossIndicationRequest(
const uint64_t picture_id) { const uint64_t picture_id) {
return rtp_rtcp_modules_[0]->SendRTCPSliceLossIndication( return rtp_rtcp_->SendRTCPSliceLossIndication(
static_cast<uint8_t>(picture_id)); static_cast<uint8_t>(picture_id));
} }
int32_t ViEChannel::ResendPackets(const uint16_t* sequence_numbers, int32_t ViEChannel::ResendPackets(const uint16_t* sequence_numbers,
uint16_t length) { 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) { void ViEChannel::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
if (!sender_) vcm_->SetReceiveChannelParameters(max_rtt_ms);
vcm_->SetReceiveChannelParameters(max_rtt_ms);
rtc::CritScope lock(&crit_); rtc::CritScope lock(&crit_);
last_rtt_ms_ = avg_rtt_ms; 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( void ViEChannel::RegisterPreRenderCallback(
I420FrameCallback* pre_render_callback) { I420FrameCallback* pre_render_callback) {
RTC_DCHECK(!sender_);
rtc::CritScope lock(&crit_); rtc::CritScope lock(&crit_);
pre_render_callback_ = pre_render_callback; pre_render_callback_ = pre_render_callback;
} }
@ -491,16 +345,11 @@ int32_t ViEChannel::OnInitializeDecoder(
} }
void ViEChannel::OnIncomingSSRCChanged(const uint32_t ssrc) { 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::OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) {}
void ViEChannel::RegisterSendFrameCountObserver(
FrameCountObserver* observer) {
send_frame_count_observer_.Set(observer);
}
void ViEChannel::RegisterReceiveStatisticsProxy( void ViEChannel::RegisterReceiveStatisticsProxy(
ReceiveStatisticsProxy* receive_statistics_proxy) { ReceiveStatisticsProxy* receive_statistics_proxy) {
rtc::CritScope lock(&crit_); rtc::CritScope lock(&crit_);

View File

@ -42,7 +42,6 @@ class PayloadRouter;
class ProcessThread; class ProcessThread;
class ReceiveStatisticsProxy; class ReceiveStatisticsProxy;
class RtcpRttStats; class RtcpRttStats;
class ViEChannelProtectionCallback;
class ViERTPObserver; class ViERTPObserver;
class VideoCodingModule; class VideoCodingModule;
class VideoRenderCallback; class VideoRenderCallback;
@ -61,21 +60,14 @@ class ViEChannel : public VCMFrameTypeCallback,
public RtpFeedback { public RtpFeedback {
public: public:
friend class ChannelStatsObserver; friend class ChannelStatsObserver;
friend class ViEChannelProtectionCallback;
ViEChannel(Transport* transport, ViEChannel(Transport* transport,
ProcessThread* module_process_thread, ProcessThread* module_process_thread,
PayloadRouter* send_payload_router,
VideoCodingModule* vcm, VideoCodingModule* vcm,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
TransportFeedbackObserver* transport_feedback_observer,
RemoteBitrateEstimator* remote_bitrate_estimator, RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttStats* rtt_stats, RtcpRttStats* rtt_stats,
PacedSender* paced_sender, PacedSender* paced_sender,
PacketRouter* packet_router, PacketRouter* packet_router);
size_t max_rtp_streams,
bool sender);
~ViEChannel(); ~ViEChannel();
int32_t Init(); int32_t Init();
@ -87,15 +79,6 @@ class ViEChannel : public VCMFrameTypeCallback,
RtpState GetRtpStateForSsrc(uint32_t ssrc) const; 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. // Implements RtpFeedback.
int32_t OnInitializeDecoder(const int8_t payload_type, int32_t OnInitializeDecoder(const int8_t payload_type,
const char payload_name[RTP_PAYLOAD_NAME_SIZE], const char payload_name[RTP_PAYLOAD_NAME_SIZE],
@ -105,11 +88,9 @@ class ViEChannel : public VCMFrameTypeCallback,
void OnIncomingSSRCChanged(const uint32_t ssrc) override; void OnIncomingSSRCChanged(const uint32_t ssrc) override;
void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) override; void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) override;
// Gets the modules used by the channel. // Gets the module used by the channel.
const std::vector<RtpRtcp*>& rtp_rtcp() const; RtpRtcp* rtp_rtcp() const;
ViEReceiver* vie_receiver(); ViEReceiver* vie_receiver();
VCMProtectionCallback* vcm_protection_callback();
CallStatsObserver* GetStatsObserver(); CallStatsObserver* GetStatsObserver();
@ -151,7 +132,6 @@ class ViEChannel : public VCMFrameTypeCallback,
void RegisterPreRenderCallback(I420FrameCallback* pre_render_callback); void RegisterPreRenderCallback(I420FrameCallback* pre_render_callback);
void RegisterSendFrameCountObserver(FrameCountObserver* observer);
void RegisterRtcpPacketTypeCounterObserver( void RegisterRtcpPacketTypeCounterObserver(
RtcpPacketTypeCounterObserver* observer); RtcpPacketTypeCounterObserver* observer);
void RegisterReceiveStatisticsProxy( void RegisterReceiveStatisticsProxy(
@ -161,30 +141,7 @@ class ViEChannel : public VCMFrameTypeCallback,
protected: protected:
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms); 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: 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. // Assumed to be protected.
void StartDecodeThread(); void StartDecodeThread();
void StopDecodeThread(); void StopDecodeThread();
@ -219,41 +176,6 @@ class ViEChannel : public VCMFrameTypeCallback,
RTC_DISALLOW_COPY_AND_ASSIGN(RegisterableCallback); 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 class RegisterableRtcpPacketTypeCounterObserver
: public RegisterableCallback<RtcpPacketTypeCounterObserver> { : public RegisterableCallback<RtcpPacketTypeCounterObserver> {
public: public:
@ -268,17 +190,12 @@ class ViEChannel : public VCMFrameTypeCallback,
private: private:
} rtcp_packet_type_counter_observer_; } rtcp_packet_type_counter_observer_;
const bool sender_;
ProcessThread* const module_process_thread_; ProcessThread* const module_process_thread_;
PayloadRouter* const send_payload_router_;
// Used for all registered callbacks except rendering. // Used for all registered callbacks except rendering.
rtc::CriticalSection crit_; rtc::CriticalSection crit_;
// Owned modules/classes.
std::unique_ptr<ViEChannelProtectionCallback> vcm_protection_callback_;
VideoCodingModule* const vcm_; VideoCodingModule* const vcm_;
ViEReceiver vie_receiver_; ViEReceiver vie_receiver_;
@ -289,21 +206,17 @@ class ViEChannel : public VCMFrameTypeCallback,
ReceiveStatisticsProxy* receive_stats_callback_ GUARDED_BY(crit_); ReceiveStatisticsProxy* receive_stats_callback_ GUARDED_BY(crit_);
FrameCounts receive_frame_counts_ GUARDED_BY(crit_); FrameCounts receive_frame_counts_ GUARDED_BY(crit_);
IncomingVideoStream* incoming_video_stream_ GUARDED_BY(crit_); IncomingVideoStream* incoming_video_stream_ GUARDED_BY(crit_);
RtcpIntraFrameObserver* const intra_frame_observer_;
RtcpRttStats* const rtt_stats_; RtcpRttStats* const rtt_stats_;
PacedSender* const paced_sender_; PacedSender* const paced_sender_;
PacketRouter* const packet_router_; PacketRouter* const packet_router_;
const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
TransportFeedbackObserver* const transport_feedback_observer_;
int max_nack_reordering_threshold_; int max_nack_reordering_threshold_;
I420FrameCallback* pre_render_callback_ GUARDED_BY(crit_); I420FrameCallback* pre_render_callback_ GUARDED_BY(crit_);
int64_t last_rtt_ms_ GUARDED_BY(crit_); int64_t last_rtt_ms_ GUARDED_BY(crit_);
// RtpRtcp modules, declared last as they use other members on construction. // RtpRtcp module, declared last as it use other members on construction.
const std::vector<RtpRtcp*> rtp_rtcp_modules_; const std::unique_ptr<RtpRtcp> rtp_rtcp_;
}; };
} // namespace webrtc } // namespace webrtc

View File

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

View File

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