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:
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_);
|
||||
|
||||
@ -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(¬_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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(¬_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_);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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_;
|
||||
|
||||
Reference in New Issue
Block a user