| 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..a504faed95adb8fd4f7ece1f15281b677e5aeded 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_(State::kStopped),
|
| overuse_detector_(
|
| Clock::GetRealTimeClock(),
|
| GetCpuOveruseOptions(config.encoder_settings.full_overuse_time),
|
| @@ -439,7 +439,6 @@ VideoSendStream::VideoSendStream(
|
| RTC_DCHECK(congestion_controller_);
|
| RTC_DCHECK(remb_);
|
|
|
| -
|
| // RTP/RTCP initialization.
|
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
| module_process_thread_->RegisterModule(rtp_rtcp);
|
| @@ -488,6 +487,7 @@ VideoSendStream::VideoSendStream(
|
|
|
| module_process_thread_->RegisterModule(&overuse_detector_);
|
|
|
| + encoder_thread_checker_.DetachFromThread();
|
| encoder_thread_.Start();
|
| encoder_thread_.SetPriority(rtc::kHighPriority);
|
| }
|
| @@ -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<State>(State::kStarted);
|
| + }
|
| + 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<State>(State::kStopped);
|
| + }
|
| + encoder_wakeup_event_.Set();
|
| }
|
|
|
| VideoCaptureInput* VideoSendStream::Input() {
|
| @@ -557,7 +563,7 @@ void VideoSendStream::EncoderProcess() {
|
| config_.encoder_settings.encoder,
|
| config_.encoder_settings.payload_type,
|
| config_.encoder_settings.internal_source));
|
| -
|
| + RTC_DCHECK_RUN_ON(&encoder_thread_checker_);
|
| while (true) {
|
| // Wake up every kEncodeCheckForActivityPeriodMs to check if the encoder is
|
| // active. If not, deregister as BitrateAllocatorObserver.
|
| @@ -566,25 +572,21 @@ void VideoSendStream::EncoderProcess() {
|
| if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_))
|
| break;
|
| bool change_settings = false;
|
| + rtc::Optional<State> 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,39 @@ 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 == State::kStarted &&
|
| + state_ == State::kStopped) {
|
| + 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_ = State::kStarted;
|
| + LOG_F(LS_INFO) << "Encoder started.";
|
| + } else if (*pending_state_change == State::kStopped) {
|
| + bitrate_allocator_->RemoveObserver(this);
|
| + vie_encoder_.OnBitrateUpdated(0, 0, 0);
|
| + state_ = 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_ == 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_ = State::kEncoderTimedOut;
|
| }
|
| - if (!send_stream_registered_as_observer_ &&
|
| + if (state_ == State::kEncoderTimedOut &&
|
| vie_encoder_.time_of_last_frame_activity_ms() >
|
| rtc::TimeMillis() - kEncoderTimeOutMs) {
|
| LOG_F(LS_INFO) << "Encoder is active.";
|
| @@ -643,7 +657,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_ = 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 +873,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);
|
| }
|
|
|
|
|