Chromium Code Reviews| 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); | 
| } |