Index: webrtc/video/video_send_stream.cc |
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc |
index 1c2a6423c16461d36bf337a5b24677233befc534..894117307091dcf4c4e1eb4629d0ca437332c104 100644 |
--- a/webrtc/video/video_send_stream.cc |
+++ b/webrtc/video/video_send_stream.cc |
@@ -13,6 +13,7 @@ |
#include <algorithm> |
#include <sstream> |
#include <string> |
+#include <utility> |
#include <vector> |
#include "webrtc/base/checks.h" |
@@ -36,6 +37,7 @@ class RtcpIntraFrameObserver; |
class TransportFeedbackObserver; |
static const int kMinSendSidePacketHistorySize = 600; |
+static const int kEncoderTimeOutMs = 2000; |
namespace { |
@@ -344,6 +346,27 @@ VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config, |
return video_codec; |
} |
+int CalulcateMaxPadBitrateBps(const VideoEncoderConfig& config, |
+ bool pad_to_min_bitrate) { |
+ int pad_up_to_bitrate_bps = 0; |
+ // Calculate max padding bitrate for a multi layer codec. |
+ if (config.streams.size() > 1) { |
+ // Pad to min bitrate of the highest layer. |
+ pad_up_to_bitrate_bps = |
+ config.streams[config.streams.size() - 1].min_bitrate_bps; |
+ // Add target_bitrate_bps of the lower layers. |
+ for (size_t i = 0; i < config.streams.size() - 1; ++i) |
+ pad_up_to_bitrate_bps += config.streams[i].target_bitrate_bps; |
+ } else if (pad_to_min_bitrate) { |
+ pad_up_to_bitrate_bps = config.streams[0].min_bitrate_bps; |
+ } |
+ |
+ pad_up_to_bitrate_bps = |
+ std::max(pad_up_to_bitrate_bps, config.min_transmit_bitrate_bps); |
+ |
+ return pad_up_to_bitrate_bps; |
+} |
+ |
} // namespace |
namespace internal { |
@@ -373,6 +396,7 @@ VideoSendStream::VideoSendStream( |
encoder_thread_(EncoderThreadFunction, this, "EncoderThread"), |
encoder_wakeup_event_(false, false), |
stop_encoder_thread_(0), |
+ send_stream_registered_as_observer_(false), |
overuse_detector_( |
Clock::GetRealTimeClock(), |
GetCpuOveruseOptions(config.encoder_settings.full_overuse_time), |
@@ -536,46 +560,52 @@ void VideoSendStream::EncoderProcess() { |
config_.encoder_settings.internal_source)); |
while (true) { |
- encoder_wakeup_event_.Wait(rtc::Event::kForever); |
+ // Wake up every kEncodeCheckForActivityPeriodMs to check if the encoder is |
+ // active. If not, deregister as BitrateAllocatorObserver. |
+ const int kEncodeCheckForActivityPeriodMs = 1000; |
+ encoder_wakeup_event_.Wait(kEncodeCheckForActivityPeriodMs); |
if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) |
break; |
- rtc::Optional<EncoderSettings> encoder_settings; |
+ bool change_settings = false; |
{ |
rtc::CritScope lock(&encoder_settings_crit_); |
if (pending_encoder_settings_) { |
- encoder_settings = pending_encoder_settings_; |
- pending_encoder_settings_ = rtc::Optional<EncoderSettings>(); |
+ std::swap(current_encoder_settings_, pending_encoder_settings_); |
+ pending_encoder_settings_.reset(); |
+ change_settings = true; |
} |
} |
- if (encoder_settings) { |
- encoder_settings->video_codec.startBitrate = |
+ if (change_settings) { |
+ current_encoder_settings_->video_codec.startBitrate = |
bitrate_allocator_->AddObserver( |
- this, encoder_settings->video_codec.minBitrate * 1000, |
- encoder_settings->video_codec.maxBitrate * 1000, |
+ this, current_encoder_settings_->video_codec.minBitrate * 1000, |
+ current_encoder_settings_->video_codec.maxBitrate * 1000, |
+ CalulcateMaxPadBitrateBps(current_encoder_settings_->config, |
+ config_.suspend_below_min_bitrate), |
!config_.suspend_below_min_bitrate) / |
1000; |
+ send_stream_registered_as_observer_ = true; |
- payload_router_.SetSendStreams(encoder_settings->streams); |
- vie_encoder_.SetEncoder(encoder_settings->video_codec, |
- encoder_settings->min_transmit_bitrate_bps, |
+ payload_router_.SetSendStreams(current_encoder_settings_->config.streams); |
+ vie_encoder_.SetEncoder(current_encoder_settings_->video_codec, |
payload_router_.MaxPayloadLength()); |
// Clear stats for disabled layers. |
- for (size_t i = encoder_settings->streams.size(); |
+ for (size_t i = current_encoder_settings_->config.streams.size(); |
i < config_.rtp.ssrcs.size(); ++i) { |
stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]); |
} |
size_t number_of_temporal_layers = |
- encoder_settings->streams.back() |
+ current_encoder_settings_->config.streams.back() |
.temporal_layer_thresholds_bps.size() + |
1; |
protection_bitrate_calculator_.SetEncodingData( |
- encoder_settings->video_codec.startBitrate * 1000, |
- encoder_settings->video_codec.width, |
- encoder_settings->video_codec.height, |
- encoder_settings->video_codec.maxFramerate, number_of_temporal_layers, |
- payload_router_.MaxPayloadLength()); |
+ current_encoder_settings_->video_codec.startBitrate * 1000, |
+ current_encoder_settings_->video_codec.width, |
+ current_encoder_settings_->video_codec.height, |
+ current_encoder_settings_->video_codec.maxFramerate, |
+ number_of_temporal_layers, payload_router_.MaxPayloadLength()); |
// We might've gotten new settings while configuring the encoder settings, |
// restart from the top to see if that's the case before trying to encode |
@@ -593,6 +623,29 @@ void VideoSendStream::EncoderProcess() { |
} |
vie_encoder_.EncodeVideoFrame(frame); |
} |
+ |
+ // Check if the encoder has produced anything the last kEncoderTimeOutMs. |
+ // If not, deregister as BitrateAllocatorObserver. |
+ if (send_stream_registered_as_observer_ && |
+ vie_encoder_.time_of_last_frame_activity_ms() < |
+ rtc::TimeMillis() - kEncoderTimeOutMs) { |
+ // The encoder has timed out. |
+ LOG_F(LS_INFO) << "Encoder timed out."; |
+ bitrate_allocator_->RemoveObserver(this); |
+ send_stream_registered_as_observer_ = false; |
+ } |
+ if (!send_stream_registered_as_observer_ && |
+ vie_encoder_.time_of_last_frame_activity_ms() > |
+ rtc::TimeMillis() - kEncoderTimeOutMs) { |
+ LOG_F(LS_INFO) << "Encoder is active."; |
+ bitrate_allocator_->AddObserver( |
+ this, current_encoder_settings_->video_codec.minBitrate * 1000, |
+ current_encoder_settings_->video_codec.maxBitrate * 1000, |
+ CalulcateMaxPadBitrateBps(current_encoder_settings_->config, |
+ config_.suspend_below_min_bitrate), |
+ !config_.suspend_below_min_bitrate); |
+ send_stream_registered_as_observer_ = true; |
+ } |
} |
vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); |
} |
@@ -607,8 +660,7 @@ void VideoSendStream::ReconfigureVideoEncoder( |
config_.encoder_settings.payload_type); |
{ |
rtc::CritScope lock(&encoder_settings_crit_); |
- pending_encoder_settings_ = rtc::Optional<EncoderSettings>( |
- {video_codec, config.min_transmit_bitrate_bps, config.streams}); |
+ pending_encoder_settings_.reset(new EncoderSettings({video_codec, config})); |
} |
encoder_wakeup_event_.Set(); |
} |
@@ -787,10 +839,6 @@ void VideoSendStream::SignalNetworkState(NetworkState state) { |
} |
} |
-int VideoSendStream::GetPaddingNeededBps() const { |
- return vie_encoder_.GetPaddingNeededBps(); |
-} |
- |
void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, |
uint8_t fraction_loss, |
int64_t rtt) { |