Wire up BitrateAllocation to be sent as RTCP TargetBitrate
This is the video parts of https://codereview.webrtc.org/2531383002/ Wire up BitrateAllocation to be sent as RTCP TargetBitrate BUG=webrtc:6301 Review-Url: https://codereview.webrtc.org/2541303003 Cr-Commit-Position: refs/heads/master@{#15359}
This commit is contained in:
@ -25,6 +25,15 @@ class VideoBitrateAllocator {
|
|||||||
virtual uint32_t GetPreferredBitrateBps(uint32_t framerate) = 0;
|
virtual uint32_t GetPreferredBitrateBps(uint32_t framerate) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VideoBitrateAllocationObserver {
|
||||||
|
public:
|
||||||
|
VideoBitrateAllocationObserver() {}
|
||||||
|
virtual ~VideoBitrateAllocationObserver() {}
|
||||||
|
|
||||||
|
virtual void OnBitrateAllocationUpdated(
|
||||||
|
const BitrateAllocation& allocation) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_BITRATE_ALLOCATOR_H_
|
#endif // WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_BITRATE_ALLOCATOR_H_
|
||||||
|
|||||||
@ -146,7 +146,7 @@ class VideoCodingModuleImpl : public VideoCodingModule {
|
|||||||
uint8_t lossRate,
|
uint8_t lossRate,
|
||||||
int64_t rtt) override {
|
int64_t rtt) override {
|
||||||
return sender_.SetChannelParameters(target_bitrate, lossRate, rtt,
|
return sender_.SetChannelParameters(target_bitrate, lossRate, rtt,
|
||||||
rate_allocator_.get());
|
rate_allocator_.get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t RegisterProtectionCallback(
|
int32_t RegisterProtectionCallback(
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class VideoBitrateAllocator;
|
class VideoBitrateAllocator;
|
||||||
|
class VideoBitrateAllocationObserver;
|
||||||
|
|
||||||
namespace vcm {
|
namespace vcm {
|
||||||
|
|
||||||
@ -79,14 +80,23 @@ class VideoSender : public Module {
|
|||||||
int Bitrate(unsigned int* bitrate) const;
|
int Bitrate(unsigned int* bitrate) const;
|
||||||
int FrameRate(unsigned int* framerate) const;
|
int FrameRate(unsigned int* framerate) const;
|
||||||
|
|
||||||
int32_t SetChannelParameters(uint32_t target_bitrate_bps,
|
// Update the channel parameters based on new rates and rtt. This will also
|
||||||
uint8_t lossRate,
|
// cause an immediate call to VideoEncoder::SetRateAllocation().
|
||||||
int64_t rtt,
|
int32_t SetChannelParameters(
|
||||||
VideoBitrateAllocator* bitrate_allocator);
|
uint32_t target_bitrate_bps,
|
||||||
// Updates the channel parameters, with a reallocated bitrate based on a
|
uint8_t loss_rate,
|
||||||
// presumably updated codec configuration, but does not update the encoder
|
int64_t rtt,
|
||||||
// itself (it will be updated on the next frame).
|
VideoBitrateAllocator* bitrate_allocator,
|
||||||
void UpdateChannelParemeters(VideoBitrateAllocator* bitrate_allocator);
|
VideoBitrateAllocationObserver* bitrate_updated_callback);
|
||||||
|
|
||||||
|
// Updates the channel parameters with a new bitrate allocation, but using the
|
||||||
|
// current targit_bitrate, loss rate and rtt. That is, the distribution or
|
||||||
|
// caps may be updated to a change to a new VideoCodec or allocation mode.
|
||||||
|
// The new parameters will be stored as pending EncoderParameters, and the
|
||||||
|
// encoder will only be updated on the next frame.
|
||||||
|
void UpdateChannelParemeters(
|
||||||
|
VideoBitrateAllocator* bitrate_allocator,
|
||||||
|
VideoBitrateAllocationObserver* bitrate_updated_callback);
|
||||||
|
|
||||||
// Deprecated:
|
// Deprecated:
|
||||||
// TODO(perkj): Remove once no projects use it.
|
// TODO(perkj): Remove once no projects use it.
|
||||||
|
|||||||
@ -63,7 +63,6 @@ void VideoSender::Process() {
|
|||||||
send_stats_callback_->SendStatistics(bitRate, frameRate);
|
send_stats_callback_->SendStatistics(bitRate, frameRate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
rtc::CritScope cs(¶ms_crit_);
|
rtc::CritScope cs(¶ms_crit_);
|
||||||
// Force an encoder parameters update, so that incoming frame rate is
|
// Force an encoder parameters update, so that incoming frame rate is
|
||||||
@ -122,6 +121,7 @@ int32_t VideoSender::RegisterSendCodec(const VideoCodec* sendCodec,
|
|||||||
} else if (frame_dropper_enabled_) {
|
} else if (frame_dropper_enabled_) {
|
||||||
_mediaOpt.EnableFrameDropper(true);
|
_mediaOpt.EnableFrameDropper(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
rtc::CritScope cs(¶ms_crit_);
|
rtc::CritScope cs(¶ms_crit_);
|
||||||
next_frame_types_.clear();
|
next_frame_types_.clear();
|
||||||
@ -212,30 +212,41 @@ EncoderParameters VideoSender::UpdateEncoderParameters(
|
|||||||
bitrate_allocation = default_allocator.GetAllocation(video_target_rate_bps,
|
bitrate_allocation = default_allocator.GetAllocation(video_target_rate_bps,
|
||||||
input_frame_rate);
|
input_frame_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
EncoderParameters new_encoder_params = {bitrate_allocation, params.loss_rate,
|
EncoderParameters new_encoder_params = {bitrate_allocation, params.loss_rate,
|
||||||
params.rtt, input_frame_rate};
|
params.rtt, input_frame_rate};
|
||||||
return new_encoder_params;
|
return new_encoder_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoSender::UpdateChannelParemeters(
|
void VideoSender::UpdateChannelParemeters(
|
||||||
VideoBitrateAllocator* bitrate_allocator) {
|
VideoBitrateAllocator* bitrate_allocator,
|
||||||
rtc::CritScope cs(¶ms_crit_);
|
VideoBitrateAllocationObserver* bitrate_updated_callback) {
|
||||||
encoder_params_ =
|
BitrateAllocation target_rate;
|
||||||
UpdateEncoderParameters(encoder_params_, bitrate_allocator,
|
{
|
||||||
encoder_params_.target_bitrate.get_sum_bps());
|
rtc::CritScope cs(¶ms_crit_);
|
||||||
|
encoder_params_ =
|
||||||
|
UpdateEncoderParameters(encoder_params_, bitrate_allocator,
|
||||||
|
encoder_params_.target_bitrate.get_sum_bps());
|
||||||
|
target_rate = encoder_params_.target_bitrate;
|
||||||
|
}
|
||||||
|
if (bitrate_updated_callback)
|
||||||
|
bitrate_updated_callback->OnBitrateAllocationUpdated(target_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t VideoSender::SetChannelParameters(
|
int32_t VideoSender::SetChannelParameters(
|
||||||
uint32_t target_bitrate_bps,
|
uint32_t target_bitrate_bps,
|
||||||
uint8_t lossRate,
|
uint8_t loss_rate,
|
||||||
int64_t rtt,
|
int64_t rtt,
|
||||||
VideoBitrateAllocator* bitrate_allocator) {
|
VideoBitrateAllocator* bitrate_allocator,
|
||||||
|
VideoBitrateAllocationObserver* bitrate_updated_callback) {
|
||||||
EncoderParameters encoder_params;
|
EncoderParameters encoder_params;
|
||||||
encoder_params.loss_rate = lossRate;
|
encoder_params.loss_rate = loss_rate;
|
||||||
encoder_params.rtt = rtt;
|
encoder_params.rtt = rtt;
|
||||||
encoder_params = UpdateEncoderParameters(encoder_params, bitrate_allocator,
|
encoder_params = UpdateEncoderParameters(encoder_params, bitrate_allocator,
|
||||||
target_bitrate_bps);
|
target_bitrate_bps);
|
||||||
|
if (bitrate_updated_callback) {
|
||||||
|
bitrate_updated_callback->OnBitrateAllocationUpdated(
|
||||||
|
encoder_params.target_bitrate);
|
||||||
|
}
|
||||||
|
|
||||||
bool encoder_has_internal_source;
|
bool encoder_has_internal_source;
|
||||||
{
|
{
|
||||||
|
|||||||
@ -312,7 +312,7 @@ TEST_F(TestVideoSenderWithMockEncoder, TestSetRate) {
|
|||||||
.Times(1)
|
.Times(1)
|
||||||
.WillOnce(Return(0));
|
.WillOnce(Return(0));
|
||||||
sender_->SetChannelParameters(new_bitrate_kbps * 1000, 0, 200,
|
sender_->SetChannelParameters(new_bitrate_kbps * 1000, 0, 200,
|
||||||
rate_allocator_.get());
|
rate_allocator_.get(), nullptr);
|
||||||
AddFrame();
|
AddFrame();
|
||||||
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
|
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
|
||||||
|
|
||||||
@ -334,7 +334,7 @@ TEST_F(TestVideoSenderWithMockEncoder, TestSetRate) {
|
|||||||
|
|
||||||
// Expect no call to encoder_.SetRates if the new bitrate is zero.
|
// Expect no call to encoder_.SetRates if the new bitrate is zero.
|
||||||
EXPECT_CALL(encoder_, SetRateAllocation(_, _)).Times(0);
|
EXPECT_CALL(encoder_, SetRateAllocation(_, _)).Times(0);
|
||||||
sender_->SetChannelParameters(0, 0, 200, rate_allocator_.get());
|
sender_->SetChannelParameters(0, 0, 200, rate_allocator_.get(), nullptr);
|
||||||
AddFrame();
|
AddFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,12 +372,12 @@ TEST_F(TestVideoSenderWithMockEncoder, TestEncoderParametersForInternalSource) {
|
|||||||
.Times(1)
|
.Times(1)
|
||||||
.WillOnce(Return(0));
|
.WillOnce(Return(0));
|
||||||
sender_->SetChannelParameters(new_bitrate_kbps * 1000, 0, 200,
|
sender_->SetChannelParameters(new_bitrate_kbps * 1000, 0, 200,
|
||||||
rate_allocator_.get());
|
rate_allocator_.get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestVideoSenderWithMockEncoder, EncoderFramerateUpdatedViaProcess) {
|
TEST_F(TestVideoSenderWithMockEncoder, EncoderFramerateUpdatedViaProcess) {
|
||||||
sender_->SetChannelParameters(settings_.startBitrate * 1000, 0, 200,
|
sender_->SetChannelParameters(settings_.startBitrate * 1000, 0, 200,
|
||||||
rate_allocator_.get());
|
rate_allocator_.get(), nullptr);
|
||||||
const int64_t kRateStatsWindowMs = 2000;
|
const int64_t kRateStatsWindowMs = 2000;
|
||||||
const uint32_t kInputFps = 20;
|
const uint32_t kInputFps = 20;
|
||||||
int64_t start_time = clock_.TimeInMilliseconds();
|
int64_t start_time = clock_.TimeInMilliseconds();
|
||||||
@ -406,7 +406,7 @@ TEST_F(TestVideoSenderWithMockEncoder,
|
|||||||
.Times(1)
|
.Times(1)
|
||||||
.WillOnce(Return(0));
|
.WillOnce(Return(0));
|
||||||
sender_->SetChannelParameters(settings_.startBitrate * 1000, kLossRate, kRtt,
|
sender_->SetChannelParameters(settings_.startBitrate * 1000, kLossRate, kRtt,
|
||||||
rate_allocator_.get());
|
rate_allocator_.get(), nullptr);
|
||||||
while (clock_.TimeInMilliseconds() < start_time + kRateStatsWindowMs) {
|
while (clock_.TimeInMilliseconds() < start_time + kRateStatsWindowMs) {
|
||||||
AddFrame();
|
AddFrame();
|
||||||
clock_.AdvanceTimeMilliseconds(1000 / kInputFps);
|
clock_.AdvanceTimeMilliseconds(1000 / kInputFps);
|
||||||
@ -427,7 +427,7 @@ TEST_F(TestVideoSenderWithMockEncoder,
|
|||||||
.Times(1)
|
.Times(1)
|
||||||
.WillOnce(Return(0));
|
.WillOnce(Return(0));
|
||||||
sender_->SetChannelParameters(new_bitrate_bps, kLossRate, kRtt,
|
sender_->SetChannelParameters(new_bitrate_bps, kLossRate, kRtt,
|
||||||
rate_allocator_.get());
|
rate_allocator_.get(), nullptr);
|
||||||
AddFrame();
|
AddFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,9 +481,9 @@ class TestVideoSenderWithVp8 : public TestVideoSender {
|
|||||||
// Note: SetChannelParameters fails if less than 2 frames are in the
|
// Note: SetChannelParameters fails if less than 2 frames are in the
|
||||||
// buffer since it will fail to calculate the framerate.
|
// buffer since it will fail to calculate the framerate.
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
EXPECT_EQ(VCM_OK,
|
EXPECT_EQ(VCM_OK, sender_->SetChannelParameters(
|
||||||
sender_->SetChannelParameters(available_bitrate_kbps_ * 1000,
|
available_bitrate_kbps_ * 1000, 0, 200,
|
||||||
0, 200, rate_allocator_.get()));
|
rate_allocator_.get(), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,7 +125,6 @@ class EndToEndTest : public test::CallTest,
|
|||||||
void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
|
void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
|
||||||
void ReceivesPliAndRecovers(int rtp_history_ms);
|
void ReceivesPliAndRecovers(int rtp_history_ms);
|
||||||
void RespectsRtcpMode(RtcpMode rtcp_mode);
|
void RespectsRtcpMode(RtcpMode rtcp_mode);
|
||||||
void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
|
|
||||||
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
|
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
|
||||||
void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
|
void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
|
||||||
void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
|
void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
|
||||||
@ -2435,89 +2434,6 @@ TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
|
|||||||
VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
|
VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
|
|
||||||
static const int kNumRtcpReportPacketsToObserve = 5;
|
|
||||||
class RtcpXrObserver : public test::EndToEndTest {
|
|
||||||
public:
|
|
||||||
explicit RtcpXrObserver(bool enable_rrtr)
|
|
||||||
: EndToEndTest(kDefaultTimeoutMs),
|
|
||||||
enable_rrtr_(enable_rrtr),
|
|
||||||
sent_rtcp_sr_(0),
|
|
||||||
sent_rtcp_rr_(0),
|
|
||||||
sent_rtcp_rrtr_(0),
|
|
||||||
sent_rtcp_dlrr_(0) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Receive stream should send RR packets (and RRTR packets if enabled).
|
|
||||||
Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
|
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
test::RtcpPacketParser parser;
|
|
||||||
EXPECT_TRUE(parser.Parse(packet, length));
|
|
||||||
|
|
||||||
sent_rtcp_rr_ += parser.receiver_report()->num_packets();
|
|
||||||
EXPECT_EQ(0, parser.sender_report()->num_packets());
|
|
||||||
EXPECT_GE(1, parser.xr()->num_packets());
|
|
||||||
if (parser.xr()->num_packets() > 0) {
|
|
||||||
if (parser.xr()->rrtr())
|
|
||||||
++sent_rtcp_rrtr_;
|
|
||||||
EXPECT_FALSE(parser.xr()->dlrr());
|
|
||||||
}
|
|
||||||
|
|
||||||
return SEND_PACKET;
|
|
||||||
}
|
|
||||||
// Send stream should send SR packets (and DLRR packets if enabled).
|
|
||||||
Action OnSendRtcp(const uint8_t* packet, size_t length) override {
|
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
test::RtcpPacketParser parser;
|
|
||||||
EXPECT_TRUE(parser.Parse(packet, length));
|
|
||||||
|
|
||||||
sent_rtcp_sr_ += parser.sender_report()->num_packets();
|
|
||||||
EXPECT_GE(1, parser.xr()->num_packets());
|
|
||||||
if (parser.xr()->num_packets() > 0) {
|
|
||||||
EXPECT_FALSE(parser.xr()->rrtr());
|
|
||||||
if (parser.xr()->dlrr())
|
|
||||||
++sent_rtcp_dlrr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
|
|
||||||
sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
|
|
||||||
if (enable_rrtr_) {
|
|
||||||
EXPECT_LT(0, sent_rtcp_rrtr_);
|
|
||||||
EXPECT_LT(0, sent_rtcp_dlrr_);
|
|
||||||
} else {
|
|
||||||
EXPECT_EQ(0, sent_rtcp_rrtr_);
|
|
||||||
EXPECT_EQ(0, sent_rtcp_dlrr_);
|
|
||||||
}
|
|
||||||
observation_complete_.Set();
|
|
||||||
}
|
|
||||||
return SEND_PACKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModifyVideoConfigs(
|
|
||||||
VideoSendStream::Config* send_config,
|
|
||||||
std::vector<VideoReceiveStream::Config>* receive_configs,
|
|
||||||
VideoEncoderConfig* encoder_config) override {
|
|
||||||
(*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
|
|
||||||
(*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
|
|
||||||
enable_rrtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PerformTest() override {
|
|
||||||
EXPECT_TRUE(Wait())
|
|
||||||
<< "Timed out while waiting for RTCP SR/RR packets to be sent.";
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::CriticalSection crit_;
|
|
||||||
bool enable_rrtr_;
|
|
||||||
int sent_rtcp_sr_;
|
|
||||||
int sent_rtcp_rr_ GUARDED_BY(&crit_);
|
|
||||||
int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
|
|
||||||
int sent_rtcp_dlrr_;
|
|
||||||
} test(enable_rrtr);
|
|
||||||
|
|
||||||
RunBaseTest(&test);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
|
void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
|
||||||
bool send_single_ssrc_first) {
|
bool send_single_ssrc_first) {
|
||||||
class SendsSetSsrcs : public test::EndToEndTest {
|
class SendsSetSsrcs : public test::EndToEndTest {
|
||||||
@ -3064,12 +2980,99 @@ TEST_P(EndToEndTest, GetStats) {
|
|||||||
RunBaseTest(&test);
|
RunBaseTest(&test);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
|
class RtcpXrObserver : public test::EndToEndTest {
|
||||||
TestXrReceiverReferenceTimeReport(true);
|
public:
|
||||||
|
explicit RtcpXrObserver(bool enable_rrtr)
|
||||||
|
: EndToEndTest(test::CallTest::kDefaultTimeoutMs),
|
||||||
|
enable_rrtr_(enable_rrtr),
|
||||||
|
sent_rtcp_sr_(0),
|
||||||
|
sent_rtcp_rr_(0),
|
||||||
|
sent_rtcp_rrtr_(0),
|
||||||
|
sent_rtcp_target_bitrate_(false),
|
||||||
|
sent_rtcp_dlrr_(0) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Receive stream should send RR packets (and RRTR packets if enabled).
|
||||||
|
Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
|
||||||
|
rtc::CritScope lock(&crit_);
|
||||||
|
test::RtcpPacketParser parser;
|
||||||
|
EXPECT_TRUE(parser.Parse(packet, length));
|
||||||
|
|
||||||
|
sent_rtcp_rr_ += parser.receiver_report()->num_packets();
|
||||||
|
EXPECT_EQ(0, parser.sender_report()->num_packets());
|
||||||
|
EXPECT_GE(1, parser.xr()->num_packets());
|
||||||
|
if (parser.xr()->num_packets() > 0) {
|
||||||
|
if (parser.xr()->rrtr())
|
||||||
|
++sent_rtcp_rrtr_;
|
||||||
|
EXPECT_FALSE(parser.xr()->dlrr());
|
||||||
|
}
|
||||||
|
|
||||||
|
return SEND_PACKET;
|
||||||
|
}
|
||||||
|
// Send stream should send SR packets (and DLRR packets if enabled).
|
||||||
|
Action OnSendRtcp(const uint8_t* packet, size_t length) override {
|
||||||
|
rtc::CritScope lock(&crit_);
|
||||||
|
test::RtcpPacketParser parser;
|
||||||
|
EXPECT_TRUE(parser.Parse(packet, length));
|
||||||
|
|
||||||
|
sent_rtcp_sr_ += parser.sender_report()->num_packets();
|
||||||
|
EXPECT_LE(parser.xr()->num_packets(), 1);
|
||||||
|
if (parser.xr()->num_packets() > 0) {
|
||||||
|
EXPECT_FALSE(parser.xr()->rrtr());
|
||||||
|
if (parser.xr()->dlrr())
|
||||||
|
++sent_rtcp_dlrr_;
|
||||||
|
if (parser.xr()->target_bitrate())
|
||||||
|
sent_rtcp_target_bitrate_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
|
||||||
|
sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
|
||||||
|
sent_rtcp_target_bitrate_) {
|
||||||
|
if (enable_rrtr_) {
|
||||||
|
EXPECT_GT(sent_rtcp_rrtr_, 0);
|
||||||
|
EXPECT_GT(sent_rtcp_dlrr_, 0);
|
||||||
|
} else {
|
||||||
|
EXPECT_EQ(sent_rtcp_rrtr_, 0);
|
||||||
|
EXPECT_EQ(sent_rtcp_dlrr_, 0);
|
||||||
|
}
|
||||||
|
observation_complete_.Set();
|
||||||
|
}
|
||||||
|
return SEND_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModifyVideoConfigs(
|
||||||
|
VideoSendStream::Config* send_config,
|
||||||
|
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||||
|
VideoEncoderConfig* encoder_config) override {
|
||||||
|
(*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
|
||||||
|
(*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
|
||||||
|
enable_rrtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerformTest() override {
|
||||||
|
EXPECT_TRUE(Wait())
|
||||||
|
<< "Timed out while waiting for RTCP SR/RR packets to be sent.";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int kNumRtcpReportPacketsToObserve = 5;
|
||||||
|
|
||||||
|
rtc::CriticalSection crit_;
|
||||||
|
bool enable_rrtr_;
|
||||||
|
int sent_rtcp_sr_;
|
||||||
|
int sent_rtcp_rr_ GUARDED_BY(&crit_);
|
||||||
|
int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
|
||||||
|
bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
|
||||||
|
int sent_rtcp_dlrr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(EndToEndTest, TestExtendedReportsWithRrtr) {
|
||||||
|
RtcpXrObserver test(true);
|
||||||
|
RunBaseTest(&test);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
|
TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtr) {
|
||||||
TestXrReceiverReferenceTimeReport(false);
|
RtcpXrObserver test(false);
|
||||||
|
RunBaseTest(&test);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
|
TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
|
||||||
|
|||||||
@ -101,7 +101,7 @@ size_t PayloadRouter::DefaultMaxPayloadLength() {
|
|||||||
return IP_PACKET_SIZE - kIpUdpSrtpLength;
|
return IP_PACKET_SIZE - kIpUdpSrtpLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PayloadRouter::set_active(bool active) {
|
void PayloadRouter::SetActive(bool active) {
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
if (active_ == active)
|
if (active_ == active)
|
||||||
return;
|
return;
|
||||||
@ -113,7 +113,7 @@ void PayloadRouter::set_active(bool active) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PayloadRouter::active() {
|
bool PayloadRouter::IsActive() {
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
return active_ && !rtp_modules_.empty();
|
return active_ && !rtp_modules_.empty();
|
||||||
}
|
}
|
||||||
@ -158,4 +158,24 @@ size_t PayloadRouter::MaxPayloadLength() const {
|
|||||||
return min_payload_length;
|
return min_payload_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PayloadRouter::OnBitrateAllocationUpdated(
|
||||||
|
const BitrateAllocation& bitrate) {
|
||||||
|
rtc::CritScope lock(&crit_);
|
||||||
|
if (IsActive()) {
|
||||||
|
if (rtp_modules_.size() == 1) {
|
||||||
|
// If spatial scalability is enabled, it is covered by a single stream.
|
||||||
|
rtp_modules_[0]->SetVideoBitrateAllocation(bitrate);
|
||||||
|
} else {
|
||||||
|
// Simulcast is in use, split the BitrateAllocation into one struct per
|
||||||
|
// rtp stream, moving over the temporal layer allocation.
|
||||||
|
for (size_t si = 0; si < rtp_modules_.size(); ++si) {
|
||||||
|
BitrateAllocation layer_bitrate;
|
||||||
|
for (int tl = 0; tl < kMaxTemporalStreams; ++tl)
|
||||||
|
layer_bitrate.SetBitrate(0, tl, bitrate.GetBitrate(si, tl));
|
||||||
|
rtp_modules_[si]->SetVideoBitrateAllocation(layer_bitrate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -40,8 +40,8 @@ class PayloadRouter : public EncodedImageCallback {
|
|||||||
|
|
||||||
// PayloadRouter will only route packets if being active, all packets will be
|
// PayloadRouter will only route packets if being active, all packets will be
|
||||||
// dropped otherwise.
|
// dropped otherwise.
|
||||||
void set_active(bool active);
|
void SetActive(bool active);
|
||||||
bool active();
|
bool IsActive();
|
||||||
|
|
||||||
// Implements EncodedImageCallback.
|
// Implements EncodedImageCallback.
|
||||||
// Returns 0 if the packet was routed / sent, -1 otherwise.
|
// Returns 0 if the packet was routed / sent, -1 otherwise.
|
||||||
@ -54,6 +54,8 @@ class PayloadRouter : public EncodedImageCallback {
|
|||||||
// and RTP headers.
|
// and RTP headers.
|
||||||
size_t MaxPayloadLength() const;
|
size_t MaxPayloadLength() const;
|
||||||
|
|
||||||
|
void OnBitrateAllocationUpdated(const BitrateAllocation& bitrate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateModuleSendingState() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
void UpdateModuleSendingState() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ TEST(PayloadRouterTest, SendOnOneModule) {
|
|||||||
EncodedImageCallback::Result::OK,
|
EncodedImageCallback::Result::OK,
|
||||||
payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
|
payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
|
||||||
|
|
||||||
payload_router.set_active(true);
|
payload_router.SetActive(true);
|
||||||
EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
|
EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
|
||||||
encoded_image._timeStamp,
|
encoded_image._timeStamp,
|
||||||
encoded_image.capture_time_ms_, &payload,
|
encoded_image.capture_time_ms_, &payload,
|
||||||
@ -60,7 +60,7 @@ TEST(PayloadRouterTest, SendOnOneModule) {
|
|||||||
EncodedImageCallback::Result::OK,
|
EncodedImageCallback::Result::OK,
|
||||||
payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
|
payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
|
||||||
|
|
||||||
payload_router.set_active(false);
|
payload_router.SetActive(false);
|
||||||
EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
|
EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
|
||||||
encoded_image._timeStamp,
|
encoded_image._timeStamp,
|
||||||
encoded_image.capture_time_ms_, &payload,
|
encoded_image.capture_time_ms_, &payload,
|
||||||
@ -70,7 +70,7 @@ TEST(PayloadRouterTest, SendOnOneModule) {
|
|||||||
EncodedImageCallback::Result::OK,
|
EncodedImageCallback::Result::OK,
|
||||||
payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
|
payload_router.OnEncodedImage(encoded_image, nullptr, nullptr).error);
|
||||||
|
|
||||||
payload_router.set_active(true);
|
payload_router.SetActive(true);
|
||||||
EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
|
EXPECT_CALL(rtp, SendOutgoingData(encoded_image._frameType, payload_type,
|
||||||
encoded_image._timeStamp,
|
encoded_image._timeStamp,
|
||||||
encoded_image.capture_time_ms_, &payload,
|
encoded_image.capture_time_ms_, &payload,
|
||||||
@ -106,7 +106,7 @@ TEST(PayloadRouterTest, SendSimulcast) {
|
|||||||
codec_info_1.codecType = kVideoCodecVP8;
|
codec_info_1.codecType = kVideoCodecVP8;
|
||||||
codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
|
codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
|
||||||
|
|
||||||
payload_router.set_active(true);
|
payload_router.SetActive(true);
|
||||||
EXPECT_CALL(rtp_1, SendOutgoingData(encoded_image._frameType, payload_type,
|
EXPECT_CALL(rtp_1, SendOutgoingData(encoded_image._frameType, payload_type,
|
||||||
encoded_image._timeStamp,
|
encoded_image._timeStamp,
|
||||||
encoded_image.capture_time_ms_, &payload,
|
encoded_image.capture_time_ms_, &payload,
|
||||||
@ -136,7 +136,7 @@ TEST(PayloadRouterTest, SendSimulcast) {
|
|||||||
.error);
|
.error);
|
||||||
|
|
||||||
// Inactive.
|
// Inactive.
|
||||||
payload_router.set_active(false);
|
payload_router.SetActive(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(_, _, _, _, _, _, _, _, _))
|
||||||
@ -182,4 +182,52 @@ TEST(PayloadRouterTest, MaxPayloadLength) {
|
|||||||
.WillOnce(Return(kTestMinPayloadLength));
|
.WillOnce(Return(kTestMinPayloadLength));
|
||||||
EXPECT_EQ(kTestMinPayloadLength, payload_router.MaxPayloadLength());
|
EXPECT_EQ(kTestMinPayloadLength, payload_router.MaxPayloadLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PayloadRouterTest, SimulcastTargetBitrate) {
|
||||||
|
NiceMock<MockRtpRtcp> rtp_1;
|
||||||
|
NiceMock<MockRtpRtcp> rtp_2;
|
||||||
|
std::vector<RtpRtcp*> modules;
|
||||||
|
modules.push_back(&rtp_1);
|
||||||
|
modules.push_back(&rtp_2);
|
||||||
|
PayloadRouter payload_router(modules, 42);
|
||||||
|
payload_router.SetActive(true);
|
||||||
|
|
||||||
|
BitrateAllocation bitrate;
|
||||||
|
bitrate.SetBitrate(0, 0, 10000);
|
||||||
|
bitrate.SetBitrate(0, 1, 20000);
|
||||||
|
bitrate.SetBitrate(1, 0, 40000);
|
||||||
|
bitrate.SetBitrate(1, 1, 80000);
|
||||||
|
|
||||||
|
BitrateAllocation layer0_bitrate;
|
||||||
|
layer0_bitrate.SetBitrate(0, 0, 10000);
|
||||||
|
layer0_bitrate.SetBitrate(0, 1, 20000);
|
||||||
|
|
||||||
|
BitrateAllocation layer1_bitrate;
|
||||||
|
layer1_bitrate.SetBitrate(0, 0, 40000);
|
||||||
|
layer1_bitrate.SetBitrate(0, 1, 80000);
|
||||||
|
|
||||||
|
EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(layer0_bitrate)).Times(1);
|
||||||
|
EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(layer1_bitrate)).Times(1);
|
||||||
|
|
||||||
|
payload_router.OnBitrateAllocationUpdated(bitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(PayloadRouterTest, SvcTargetBitrate) {
|
||||||
|
NiceMock<MockRtpRtcp> rtp_1;
|
||||||
|
std::vector<RtpRtcp*> modules;
|
||||||
|
modules.push_back(&rtp_1);
|
||||||
|
PayloadRouter payload_router(modules, 42);
|
||||||
|
payload_router.SetActive(true);
|
||||||
|
|
||||||
|
BitrateAllocation bitrate;
|
||||||
|
bitrate.SetBitrate(0, 0, 10000);
|
||||||
|
bitrate.SetBitrate(0, 1, 20000);
|
||||||
|
bitrate.SetBitrate(1, 0, 40000);
|
||||||
|
bitrate.SetBitrate(1, 1, 80000);
|
||||||
|
|
||||||
|
EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(bitrate)).Times(1);
|
||||||
|
|
||||||
|
payload_router.OnBitrateAllocationUpdated(bitrate);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
|
#include "webrtc/common_video/include/video_bitrate_allocator.h"
|
||||||
#include "webrtc/base/checks.h"
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/base/file.h"
|
#include "webrtc/base/file.h"
|
||||||
#include "webrtc/base/logging.h"
|
#include "webrtc/base/logging.h"
|
||||||
@ -289,7 +290,8 @@ namespace internal {
|
|||||||
class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
|
class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
|
||||||
public webrtc::OverheadObserver,
|
public webrtc::OverheadObserver,
|
||||||
public webrtc::VCMProtectionCallback,
|
public webrtc::VCMProtectionCallback,
|
||||||
public ViEEncoder::EncoderSink {
|
public ViEEncoder::EncoderSink,
|
||||||
|
public VideoBitrateAllocationObserver {
|
||||||
public:
|
public:
|
||||||
VideoSendStreamImpl(SendStatisticsProxy* stats_proxy,
|
VideoSendStreamImpl(SendStatisticsProxy* stats_proxy,
|
||||||
rtc::TaskQueue* worker_queue,
|
rtc::TaskQueue* worker_queue,
|
||||||
@ -357,6 +359,9 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
|
|||||||
const CodecSpecificInfo* codec_specific_info,
|
const CodecSpecificInfo* codec_specific_info,
|
||||||
const RTPFragmentationHeader* fragmentation) override;
|
const RTPFragmentationHeader* fragmentation) override;
|
||||||
|
|
||||||
|
// Implements VideoBitrateAllocationObserver.
|
||||||
|
void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
|
||||||
|
|
||||||
void ConfigureProtection();
|
void ConfigureProtection();
|
||||||
void ConfigureSsrcs();
|
void ConfigureSsrcs();
|
||||||
void SignalEncoderTimedOut();
|
void SignalEncoderTimedOut();
|
||||||
@ -598,7 +603,6 @@ VideoSendStream::VideoSendStream(
|
|||||||
vie_encoder_.reset(new ViEEncoder(
|
vie_encoder_.reset(new ViEEncoder(
|
||||||
num_cpu_cores, &stats_proxy_, config_.encoder_settings,
|
num_cpu_cores, &stats_proxy_, config_.encoder_settings,
|
||||||
config_.pre_encode_callback, config_.post_encode_callback));
|
config_.pre_encode_callback, config_.post_encode_callback));
|
||||||
|
|
||||||
worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
|
worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
|
||||||
&send_stream_, &thread_sync_event_, &stats_proxy_, vie_encoder_.get(),
|
&send_stream_, &thread_sync_event_, &stats_proxy_, vie_encoder_.get(),
|
||||||
module_process_thread, call_stats, congestion_controller, packet_router,
|
module_process_thread, call_stats, congestion_controller, packet_router,
|
||||||
@ -610,7 +614,7 @@ VideoSendStream::VideoSendStream(
|
|||||||
// it was created on.
|
// it was created on.
|
||||||
thread_sync_event_.Wait(rtc::Event::kForever);
|
thread_sync_event_.Wait(rtc::Event::kForever);
|
||||||
send_stream_->RegisterProcessThread(module_process_thread);
|
send_stream_->RegisterProcessThread(module_process_thread);
|
||||||
|
vie_encoder_->SetBitrateObserver(send_stream_.get());
|
||||||
vie_encoder_->RegisterProcessThread(module_process_thread);
|
vie_encoder_->RegisterProcessThread(module_process_thread);
|
||||||
|
|
||||||
ReconfigureVideoEncoder(std::move(encoder_config));
|
ReconfigureVideoEncoder(std::move(encoder_config));
|
||||||
@ -849,7 +853,7 @@ void VideoSendStreamImpl::DeRegisterProcessThread() {
|
|||||||
|
|
||||||
VideoSendStreamImpl::~VideoSendStreamImpl() {
|
VideoSendStreamImpl::~VideoSendStreamImpl() {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
RTC_DCHECK(!payload_router_.active())
|
RTC_DCHECK(!payload_router_.IsActive())
|
||||||
<< "VideoSendStreamImpl::Stop not called";
|
<< "VideoSendStreamImpl::Stop not called";
|
||||||
LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
|
LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
|
||||||
|
|
||||||
@ -873,10 +877,10 @@ bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
|
|||||||
void VideoSendStreamImpl::Start() {
|
void VideoSendStreamImpl::Start() {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
LOG(LS_INFO) << "VideoSendStream::Start";
|
LOG(LS_INFO) << "VideoSendStream::Start";
|
||||||
if (payload_router_.active())
|
if (payload_router_.IsActive())
|
||||||
return;
|
return;
|
||||||
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
|
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
|
||||||
payload_router_.set_active(true);
|
payload_router_.SetActive(true);
|
||||||
|
|
||||||
bitrate_allocator_->AddObserver(
|
bitrate_allocator_->AddObserver(
|
||||||
this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
|
this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
|
||||||
@ -898,10 +902,10 @@ void VideoSendStreamImpl::Start() {
|
|||||||
void VideoSendStreamImpl::Stop() {
|
void VideoSendStreamImpl::Stop() {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
LOG(LS_INFO) << "VideoSendStream::Stop";
|
LOG(LS_INFO) << "VideoSendStream::Stop";
|
||||||
if (!payload_router_.active())
|
if (!payload_router_.IsActive())
|
||||||
return;
|
return;
|
||||||
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
|
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
|
||||||
payload_router_.set_active(false);
|
payload_router_.SetActive(false);
|
||||||
bitrate_allocator_->RemoveObserver(this);
|
bitrate_allocator_->RemoveObserver(this);
|
||||||
{
|
{
|
||||||
rtc::CritScope lock(&encoder_activity_crit_sect_);
|
rtc::CritScope lock(&encoder_activity_crit_sect_);
|
||||||
@ -923,6 +927,11 @@ void VideoSendStreamImpl::SignalEncoderTimedOut() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoSendStreamImpl::OnBitrateAllocationUpdated(
|
||||||
|
const BitrateAllocation& allocation) {
|
||||||
|
payload_router_.OnBitrateAllocationUpdated(allocation);
|
||||||
|
}
|
||||||
|
|
||||||
void VideoSendStreamImpl::SignalEncoderActive() {
|
void VideoSendStreamImpl::SignalEncoderActive() {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
|
LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
|
||||||
@ -965,7 +974,7 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
|
|||||||
streams[0].width, streams[0].height, number_of_temporal_layers,
|
streams[0].width, streams[0].height, number_of_temporal_layers,
|
||||||
config_->rtp.max_packet_size);
|
config_->rtp.max_packet_size);
|
||||||
|
|
||||||
if (payload_router_.active()) {
|
if (payload_router_.IsActive()) {
|
||||||
// The send stream is started already. Update the allocator with new bitrate
|
// The send stream is started already. Update the allocator with new bitrate
|
||||||
// limits.
|
// limits.
|
||||||
bitrate_allocator_->AddObserver(
|
bitrate_allocator_->AddObserver(
|
||||||
@ -1174,7 +1183,7 @@ uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
|
|||||||
int64_t rtt,
|
int64_t rtt,
|
||||||
int64_t probing_interval_ms) {
|
int64_t probing_interval_ms) {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
RTC_DCHECK(payload_router_.active())
|
RTC_DCHECK(payload_router_.IsActive())
|
||||||
<< "VideoSendStream::Start has not been called.";
|
<< "VideoSendStream::Start has not been called.";
|
||||||
|
|
||||||
if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") ==
|
if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") ==
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "webrtc/base/logging.h"
|
#include "webrtc/base/logging.h"
|
||||||
#include "webrtc/base/trace_event.h"
|
#include "webrtc/base/trace_event.h"
|
||||||
#include "webrtc/base/timeutils.h"
|
#include "webrtc/base/timeutils.h"
|
||||||
|
#include "webrtc/common_video/include/video_bitrate_allocator.h"
|
||||||
#include "webrtc/modules/pacing/paced_sender.h"
|
#include "webrtc/modules/pacing/paced_sender.h"
|
||||||
#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
|
#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
|
||||||
#include "webrtc/modules/video_coding/include/video_coding.h"
|
#include "webrtc/modules/video_coding/include/video_coding.h"
|
||||||
@ -26,7 +27,6 @@
|
|||||||
#include "webrtc/video/overuse_frame_detector.h"
|
#include "webrtc/video/overuse_frame_detector.h"
|
||||||
#include "webrtc/video/send_statistics_proxy.h"
|
#include "webrtc/video/send_statistics_proxy.h"
|
||||||
#include "webrtc/video_frame.h"
|
#include "webrtc/video_frame.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -270,6 +270,7 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
|||||||
last_frame_log_ms_(clock_->TimeInMilliseconds()),
|
last_frame_log_ms_(clock_->TimeInMilliseconds()),
|
||||||
captured_frame_count_(0),
|
captured_frame_count_(0),
|
||||||
dropped_frame_count_(0),
|
dropped_frame_count_(0),
|
||||||
|
bitrate_observer_(nullptr),
|
||||||
encoder_queue_("EncoderQueue") {
|
encoder_queue_("EncoderQueue") {
|
||||||
encoder_queue_.PostTask([this] {
|
encoder_queue_.PostTask([this] {
|
||||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||||
@ -292,6 +293,7 @@ void ViEEncoder::Stop() {
|
|||||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||||
overuse_detector_.StopCheckForOveruse();
|
overuse_detector_.StopCheckForOveruse();
|
||||||
rate_allocator_.reset();
|
rate_allocator_.reset();
|
||||||
|
bitrate_observer_ = nullptr;
|
||||||
video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type,
|
video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type,
|
||||||
false);
|
false);
|
||||||
quality_scaler_ = nullptr;
|
quality_scaler_ = nullptr;
|
||||||
@ -314,6 +316,16 @@ void ViEEncoder::DeRegisterProcessThread() {
|
|||||||
module_process_thread_->DeRegisterModule(&video_sender_);
|
module_process_thread_->DeRegisterModule(&video_sender_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViEEncoder::SetBitrateObserver(
|
||||||
|
VideoBitrateAllocationObserver* bitrate_observer) {
|
||||||
|
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||||
|
encoder_queue_.PostTask([this, bitrate_observer] {
|
||||||
|
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||||
|
RTC_DCHECK(!bitrate_observer_);
|
||||||
|
bitrate_observer_ = bitrate_observer;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void ViEEncoder::SetSource(
|
void ViEEncoder::SetSource(
|
||||||
rtc::VideoSourceInterface<VideoFrame>* source,
|
rtc::VideoSourceInterface<VideoFrame>* source,
|
||||||
const VideoSendStream::DegradationPreference& degradation_preference) {
|
const VideoSendStream::DegradationPreference& degradation_preference) {
|
||||||
@ -405,7 +417,9 @@ void ViEEncoder::ReconfigureEncoder() {
|
|||||||
RTC_DCHECK(success);
|
RTC_DCHECK(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
video_sender_.UpdateChannelParemeters(rate_allocator_.get());
|
video_sender_.UpdateChannelParemeters(rate_allocator_.get(),
|
||||||
|
bitrate_observer_);
|
||||||
|
|
||||||
if (stats_proxy_) {
|
if (stats_proxy_) {
|
||||||
int framerate = stats_proxy_->GetSendFrameRate();
|
int framerate = stats_proxy_->GetSendFrameRate();
|
||||||
if (framerate == 0)
|
if (framerate == 0)
|
||||||
@ -660,7 +674,8 @@ void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps,
|
|||||||
<< " rtt " << round_trip_time_ms;
|
<< " rtt " << round_trip_time_ms;
|
||||||
|
|
||||||
video_sender_.SetChannelParameters(bitrate_bps, fraction_lost,
|
video_sender_.SetChannelParameters(bitrate_bps, fraction_lost,
|
||||||
round_trip_time_ms, rate_allocator_.get());
|
round_trip_time_ms, rate_allocator_.get(),
|
||||||
|
bitrate_observer_);
|
||||||
|
|
||||||
encoder_start_bitrate_bps_ =
|
encoder_start_bitrate_bps_ =
|
||||||
bitrate_bps != 0 ? bitrate_bps : encoder_start_bitrate_bps_;
|
bitrate_bps != 0 ? bitrate_bps : encoder_start_bitrate_bps_;
|
||||||
|
|||||||
@ -37,6 +37,7 @@ namespace webrtc {
|
|||||||
|
|
||||||
class ProcessThread;
|
class ProcessThread;
|
||||||
class SendStatisticsProxy;
|
class SendStatisticsProxy;
|
||||||
|
class VideoBitrateAllocationObserver;
|
||||||
|
|
||||||
// VieEncoder represent a video encoder that accepts raw video frames as input
|
// VieEncoder represent a video encoder that accepts raw video frames as input
|
||||||
// and produces an encoded bit stream.
|
// and produces an encoded bit stream.
|
||||||
@ -91,6 +92,8 @@ class ViEEncoder : public rtc::VideoSinkInterface<VideoFrame>,
|
|||||||
// TODO(perkj): Can we remove VideoCodec.startBitrate ?
|
// TODO(perkj): Can we remove VideoCodec.startBitrate ?
|
||||||
void SetStartBitrate(int start_bitrate_bps);
|
void SetStartBitrate(int start_bitrate_bps);
|
||||||
|
|
||||||
|
void SetBitrateObserver(VideoBitrateAllocationObserver* bitrate_observer);
|
||||||
|
|
||||||
void ConfigureEncoder(VideoEncoderConfig config,
|
void ConfigureEncoder(VideoEncoderConfig config,
|
||||||
size_t max_data_payload_length,
|
size_t max_data_payload_length,
|
||||||
bool nack_enabled);
|
bool nack_enabled);
|
||||||
@ -231,6 +234,8 @@ class ViEEncoder : public rtc::VideoSinkInterface<VideoFrame>,
|
|||||||
int captured_frame_count_ ACCESS_ON(&encoder_queue_);
|
int captured_frame_count_ ACCESS_ON(&encoder_queue_);
|
||||||
int dropped_frame_count_ ACCESS_ON(&encoder_queue_);
|
int dropped_frame_count_ ACCESS_ON(&encoder_queue_);
|
||||||
|
|
||||||
|
VideoBitrateAllocationObserver* bitrate_observer_ ACCESS_ON(&encoder_queue_);
|
||||||
|
|
||||||
// All public methods are proxied to |encoder_queue_|. It must must be
|
// All public methods are proxied to |encoder_queue_|. It must must be
|
||||||
// destroyed first to make sure no tasks are run that use other members.
|
// destroyed first to make sure no tasks are run that use other members.
|
||||||
rtc::TaskQueue encoder_queue_;
|
rtc::TaskQueue encoder_queue_;
|
||||||
|
|||||||
Reference in New Issue
Block a user