Index: webrtc/video/video_send_stream.cc |
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc |
index df4b2955465045b4b9509628ad625271c8cdad1f..50f58c5b3068424ffa28ac6e04c86c8bd67c76de 100644 |
--- a/webrtc/video/video_send_stream.cc |
+++ b/webrtc/video/video_send_stream.cc |
@@ -395,7 +395,7 @@ VideoSendStream::VideoSendStream( |
encoder_thread_(EncoderThreadFunction, this, "EncoderThread"), |
encoder_wakeup_event_(false, false), |
stop_encoder_thread_(0), |
- send_stream_registered_as_observer_(false), |
+ state_(kStopped), |
overuse_detector_( |
Clock::GetRealTimeClock(), |
GetCpuOveruseOptions(config.encoder_settings.full_overuse_time), |
@@ -529,17 +529,23 @@ void VideoSendStream::Start() { |
return; |
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start"); |
payload_router_.set_active(true); |
- // Was not already started, trigger a keyframe. |
- vie_encoder_.SendKeyFrame(); |
- vie_encoder_.Start(); |
+ { |
+ rtc::CritScope lock(&encoder_settings_crit_); |
+ pending_state_change_ = rtc::Optional<bool>(true); |
+ } |
+ encoder_wakeup_event_.Set(); |
} |
void VideoSendStream::Stop() { |
if (!payload_router_.active()) |
return; |
TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop"); |
- vie_encoder_.Pause(); |
payload_router_.set_active(false); |
+ { |
+ rtc::CritScope lock(&encoder_settings_crit_); |
+ pending_state_change_ = rtc::Optional<bool>(false); |
+ } |
+ encoder_wakeup_event_.Set(); |
} |
VideoCaptureInput* VideoSendStream::Input() { |
@@ -566,25 +572,21 @@ void VideoSendStream::EncoderProcess() { |
if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) |
break; |
bool change_settings = false; |
+ rtc::Optional<bool> pending_state_change; |
{ |
rtc::CritScope lock(&encoder_settings_crit_); |
if (pending_encoder_settings_) { |
std::swap(current_encoder_settings_, pending_encoder_settings_); |
pending_encoder_settings_.reset(); |
change_settings = true; |
+ } else if (pending_state_change_) { |
+ swap(pending_state_change, pending_state_change_); |
} |
} |
if (change_settings) { |
- current_encoder_settings_->video_codec.startBitrate = |
- 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) / |
- 1000; |
- send_stream_registered_as_observer_ = true; |
- |
+ current_encoder_settings_->video_codec.startBitrate = std::max( |
+ bitrate_allocator_->GetStartBitrate(this) / 1000, |
+ static_cast<int>(current_encoder_settings_->video_codec.minBitrate)); |
payload_router_.SetSendStreams(current_encoder_settings_->config.streams); |
vie_encoder_.SetEncoder(current_encoder_settings_->video_codec, |
payload_router_.MaxPayloadLength()); |
@@ -613,27 +615,38 @@ void VideoSendStream::EncoderProcess() { |
continue; |
} |
- VideoFrame frame; |
- if (input_.GetVideoFrame(&frame)) { |
- // TODO(perkj): |pre_encode_callback| is only used by tests. Tests should |
- // register as a sink to the VideoSource instead. |
- if (config_.pre_encode_callback) { |
- config_.pre_encode_callback->OnFrame(frame); |
+ if (pending_state_change) { |
+ if (*pending_state_change == true && state_ == kStopped) { |
pbos-webrtc
2016/06/17 12:38:21
no == true
perkj_webrtc
2016/06/17 13:06:32
Done.
|
+ 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); |
+ vie_encoder_.SendKeyFrame(); |
+ state_ = kStarted; |
+ LOG_F(LS_INFO) << "Encoder started."; |
+ } else if (*pending_state_change == false) { |
pbos-webrtc
2016/06/17 12:38:21
!(*pending_state_change)
perkj_webrtc
2016/06/17 13:06:32
Done.
|
+ bitrate_allocator_->RemoveObserver(this); |
+ vie_encoder_.OnBitrateUpdated(0, 0, 0); |
+ state_ = kStopped; |
+ LOG_F(LS_INFO) << "Encoder stopped."; |
} |
- vie_encoder_.EncodeVideoFrame(frame); |
+ encoder_wakeup_event_.Set(); |
+ continue; |
} |
// Check if the encoder has produced anything the last kEncoderTimeOutMs. |
// If not, deregister as BitrateAllocatorObserver. |
- if (send_stream_registered_as_observer_ && |
+ if (state_ == kStarted && |
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; |
+ state_ = kEncoderTimedOut; |
} |
- if (!send_stream_registered_as_observer_ && |
+ if (state_ == kEncoderTimedOut && |
vie_encoder_.time_of_last_frame_activity_ms() > |
rtc::TimeMillis() - kEncoderTimeOutMs) { |
LOG_F(LS_INFO) << "Encoder is active."; |
@@ -643,7 +656,17 @@ void VideoSendStream::EncoderProcess() { |
CalulcateMaxPadBitrateBps(current_encoder_settings_->config, |
config_.suspend_below_min_bitrate), |
!config_.suspend_below_min_bitrate); |
- send_stream_registered_as_observer_ = true; |
+ state_ = kStarted; |
+ } |
+ |
+ VideoFrame frame; |
+ if (input_.GetVideoFrame(&frame)) { |
+ // TODO(perkj): |pre_encode_callback| is only used by tests. Tests should |
+ // register as a sink to the VideoSource instead. |
+ if (config_.pre_encode_callback) { |
+ config_.pre_encode_callback->OnFrame(frame); |
+ } |
+ vie_encoder_.EncodeVideoFrame(frame); |
} |
} |
vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); |
@@ -849,7 +872,6 @@ void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, |
// protection overhead. |
uint32_t encoder_target_rate = protection_bitrate_calculator_.SetTargetRates( |
bitrate_bps, stats_proxy_.GetSendFrameRate(), fraction_loss, rtt); |
- |
vie_encoder_.OnBitrateUpdated(encoder_target_rate, fraction_loss, rtt); |
} |