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;
|
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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -871,6 +871,7 @@ 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;
|
||||||
|
|
||||||
|
if (receive_statistics_) {
|
||||||
StatisticianMap statisticians =
|
StatisticianMap statisticians =
|
||||||
receive_statistics_->GetActiveStatisticians();
|
receive_statistics_->GetActiveStatisticians();
|
||||||
RTC_DCHECK(report_blocks_.empty());
|
RTC_DCHECK(report_blocks_.empty());
|
||||||
@ -878,6 +879,7 @@ void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
|
|||||||
AddReportBlock(feedback_state, it.first, it.second);
|
AddReportBlock(feedback_state, it.first, it.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
|
bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
|
||||||
|
|||||||
@ -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) {
|
|
||||||
if (rtp_sender_.SSRC() == ssrc) {
|
|
||||||
SetStartTimestamp(rtp_state.start_timestamp);
|
SetStartTimestamp(rtp_state.start_timestamp);
|
||||||
rtp_sender_.SetRtpState(rtp_state);
|
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 {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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_);
|
||||||
|
|||||||
@ -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(¬_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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
|
||||||
vie_receiver_.GetReceiveStatistics(),
|
|
||||||
transport,
|
transport,
|
||||||
intra_frame_observer_,
|
|
||||||
bandwidth_observer_.get(),
|
|
||||||
transport_feedback_observer_,
|
|
||||||
rtt_stats_,
|
rtt_stats_,
|
||||||
&rtcp_packet_type_counter_observer_,
|
&rtcp_packet_type_counter_observer_,
|
||||||
remote_bitrate_estimator,
|
remote_bitrate_estimator,
|
||||||
paced_sender_,
|
paced_sender_,
|
||||||
packet_router_,
|
packet_router_)) {
|
||||||
&send_bitrate_observer_,
|
vie_receiver_.Init(rtp_rtcp_.get());
|
||||||
&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_);
|
RTC_DCHECK(vcm_);
|
||||||
vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
|
vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ViEChannel::Init() {
|
int32_t ViEChannel::Init() {
|
||||||
@ -137,20 +127,10 @@ 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_) {
|
|
||||||
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 {
|
|
||||||
if (vcm_->RegisterReceiveCallback(this) != 0) {
|
if (vcm_->RegisterReceiveCallback(this) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -158,7 +138,7 @@ int32_t ViEChannel::Init() {
|
|||||||
vcm_->RegisterReceiveStatisticsCallback(this);
|
vcm_->RegisterReceiveStatisticsCallback(this);
|
||||||
vcm_->RegisterDecoderTimingCallback(this);
|
vcm_->RegisterDecoderTimingCallback(this);
|
||||||
vcm_->SetRenderDelay(kDefaultRenderDelayMs);
|
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_);
|
||||||
|
|
||||||
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
|
|
||||||
rtp_rtcp->SetStorePacketsStatus(true, kMinSendSidePacketHistorySize);
|
|
||||||
|
|
||||||
if (!sender_) {
|
|
||||||
vcm_->RegisterPacketRequestCallback(this);
|
vcm_->RegisterPacketRequestCallback(this);
|
||||||
// Don't introduce errors when NACK is enabled.
|
// Don't introduce errors when NACK is enabled.
|
||||||
vcm_->SetDecodeErrorMode(kNoErrors);
|
vcm_->SetDecodeErrorMode(kNoErrors);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!sender_) {
|
|
||||||
vcm_->RegisterPacketRequestCallback(nullptr);
|
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
|
// When NACK is off, allow decoding with errors. Otherwise, the video
|
||||||
// will freeze, and will only recover with a complete key frame.
|
// will freeze, and will only recover with a complete key frame.
|
||||||
vcm_->SetDecodeErrorMode(kWithErrors);
|
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(¬_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_);
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,7 +336,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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_;
|
||||||
|
|||||||
Reference in New Issue
Block a user