| Index: webrtc/video/video_send_stream.cc
|
| diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
|
| index 01c2fc836c7d4a35dde12d1a13b4cd2fbb8e5cf0..164af9e532cef1c26c34403e6c734307c238a715 100644
|
| --- a/webrtc/video/video_send_stream.cc
|
| +++ b/webrtc/video/video_send_stream.cc
|
| @@ -7,7 +7,6 @@
|
| * in the file PATENTS. All contributing project authors may
|
| * be found in the AUTHORS file in the root of the source tree.
|
| */
|
| -
|
| #include "webrtc/video/video_send_stream.h"
|
|
|
| #include <algorithm>
|
| @@ -37,8 +36,6 @@ class RtcpIntraFrameObserver;
|
| class TransportFeedbackObserver;
|
|
|
| static const int kMinSendSidePacketHistorySize = 600;
|
| -static const int kEncoderTimeOutMs = 2000;
|
| -
|
| namespace {
|
|
|
| std::vector<RtpRtcp*> CreateRtpRtcpModules(
|
| @@ -371,9 +368,229 @@ int CalulcateMaxPadBitrateBps(const VideoEncoderConfig& config,
|
| } // namespace
|
|
|
| namespace internal {
|
| +
|
| +class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
|
| + public:
|
| + ConstructionTask(std::unique_ptr<VideoSendStreamInternal>* send_stream,
|
| + rtc::Event* done_event,
|
| + int num_cpu_cores,
|
| + ProcessThread* module_process_thread,
|
| + CallStats* call_stats,
|
| + CongestionController* congestion_controller,
|
| + BitrateAllocator* bitrate_allocator,
|
| + SendDelayStats* send_delay_stats,
|
| + VieRemb* remb,
|
| + RtcEventLog* event_log,
|
| + const VideoSendStream::Config& config,
|
| + const VideoEncoderConfig& encoder_config,
|
| + const std::map<uint32_t, RtpState>& suspended_ssrcs)
|
| + : send_stream_(send_stream),
|
| + done_event_(done_event),
|
| + num_cpu_cores_(num_cpu_cores),
|
| + call_stats_(call_stats),
|
| + congestion_controller_(congestion_controller),
|
| + bitrate_allocator_(bitrate_allocator),
|
| + send_delay_stats_(send_delay_stats),
|
| + remb_(remb),
|
| + event_log_(event_log),
|
| + config_(config),
|
| + encoder_config_(encoder_config),
|
| + suspended_ssrcs_(suspended_ssrcs) {}
|
| + ~ConstructionTask() { done_event_->Set(); }
|
| +
|
| + bool Run() override {
|
| + send_stream_->reset(new VideoSendStreamInternal(
|
| + num_cpu_cores_, rtc::TaskQueue::Current(), call_stats_,
|
| + congestion_controller_, bitrate_allocator_, send_delay_stats_, remb_,
|
| + event_log_, config_, encoder_config_, suspended_ssrcs_));
|
| + return true;
|
| + }
|
| +
|
| + private:
|
| + std::unique_ptr<VideoSendStreamInternal>* send_stream_;
|
| + rtc::Event* done_event_;
|
| + const int num_cpu_cores_;
|
| + CallStats* const call_stats_;
|
| + CongestionController* const congestion_controller_;
|
| + BitrateAllocator* const bitrate_allocator_;
|
| + SendDelayStats* const send_delay_stats_;
|
| + VieRemb* const remb_;
|
| + RtcEventLog* const event_log_;
|
| + const VideoSendStream::Config config_;
|
| + const VideoEncoderConfig encoder_config_;
|
| + const std::map<uint32_t, RtpState> suspended_ssrcs_;
|
| +};
|
| +
|
| +class VideoSendStream::DestructAndGetRTPStateTask : public rtc::QueuedTask {
|
| + public:
|
| + DestructAndGetRTPStateTask(
|
| + VideoSendStream::RtpStateMap* state_map,
|
| + std::unique_ptr<VideoSendStreamInternal> send_stream,
|
| + rtc::Event* done_event)
|
| + : state_map_(state_map),
|
| + send_stream_(std::move(send_stream)),
|
| + done_event_(done_event) {}
|
| + ~DestructAndGetRTPStateTask() {
|
| + send_stream_.reset();
|
| + done_event_->Set();
|
| + }
|
| +
|
| + bool Run() override {
|
| + send_stream_->Stop();
|
| + *state_map_ = send_stream_->GetRtpStates();
|
| + send_stream_.reset();
|
| + return true;
|
| + }
|
| +
|
| + private:
|
| + VideoSendStream::RtpStateMap* state_map_;
|
| + std::unique_ptr<VideoSendStreamInternal> send_stream_;
|
| + rtc::Event* done_event_;
|
| +};
|
| +
|
| +// CheckEncoderActivityTask is used for tracking when the encoder last produced
|
| +// and encoded video frame. This is used to
|
| +// track when video is stopped long enough that we also want to stop sending
|
| +// padding.
|
| +class VideoSendStreamInternal::CheckEncoderActivityTask
|
| + : public rtc::QueuedTask {
|
| + public:
|
| + static const int kEncoderTimeOutMs = 2000;
|
| + explicit CheckEncoderActivityTask(VideoSendStreamInternal* send_stream)
|
| + : activity_(0), send_stream_(send_stream), timed_out_(false) {
|
| + encoder_thread_checker_.DetachFromThread();
|
| + }
|
| +
|
| + void Stop() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + send_stream_ = nullptr;
|
| + }
|
| +
|
| + void UpdateEncoderActivity() {
|
| + RTC_DCHECK_RUN_ON(&encoder_thread_checker_);
|
| + rtc::AtomicOps::ReleaseStore(&activity_, 1);
|
| + }
|
| +
|
| + private:
|
| + bool Run() override {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + if (!send_stream_)
|
| + return true;
|
| + if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
|
| + if (!timed_out_) {
|
| + send_stream_->EncoderTimedOut();
|
| + }
|
| + timed_out_ = true;
|
| + } else if (timed_out_) {
|
| + send_stream_->EncoderIsActive();
|
| + timed_out_ = false;
|
| + }
|
| + rtc::AtomicOps::ReleaseStore(&activity_, 0);
|
| +
|
| + rtc::TaskQueue::Current()->PostDelayedTask(
|
| + std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
|
| + // Return false to prevent this task from being deleted. Ownership has been
|
| + // transferred to the task queue when PostDelayedTask was called.
|
| + return false;
|
| + }
|
| +
|
| + rtc::ThreadChecker encoder_thread_checker_;
|
| + volatile int activity_;
|
| +
|
| + rtc::ThreadChecker thread_checker_;
|
| + VideoSendStreamInternal* send_stream_;
|
| + bool timed_out_;
|
| +};
|
| +
|
| VideoSendStream::VideoSendStream(
|
| int num_cpu_cores,
|
| ProcessThread* module_process_thread,
|
| + rtc::TaskQueue* worker_queu,
|
| + CallStats* call_stats,
|
| + CongestionController* congestion_controller,
|
| + BitrateAllocator* bitrate_allocator,
|
| + SendDelayStats* send_delay_stats,
|
| + VieRemb* remb,
|
| + RtcEventLog* event_log,
|
| + const VideoSendStream::Config& config,
|
| + const VideoEncoderConfig& encoder_config,
|
| + const std::map<uint32_t, RtpState>& suspended_ssrcs)
|
| + : worker_queu_(worker_queu),
|
| + thread_sync_event_(false /* manual_reset */, false) {
|
| + worker_queu_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
|
| + &send_stream_, &thread_sync_event_, num_cpu_cores, module_process_thread,
|
| + call_stats, congestion_controller, bitrate_allocator, send_delay_stats,
|
| + remb, event_log, config, encoder_config, suspended_ssrcs)));
|
| +
|
| + // Wait for |construction_task| to complete so that |module_process_thread|
|
| + // can be registered.
|
| + thread_sync_event_.Wait(rtc::Event::kForever);
|
| + // |send_stream_| can be null if |worker_queu_| is destroyed before the
|
| + // ConstructionTask runs.
|
| + if (send_stream_)
|
| + send_stream_->RegisterProcessThread(module_process_thread);
|
| +}
|
| +
|
| +VideoSendStream::~VideoSendStream() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + LOG(LS_INFO) << "~VideoSendStream: ";
|
| + RTC_DCHECK(!send_stream_);
|
| +}
|
| +
|
| +void VideoSendStream::Start() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + VideoSendStreamInternal* send_stream = send_stream_.get();
|
| + worker_queu_->PostTask([send_stream] { send_stream->Start(); });
|
| +}
|
| +
|
| +void VideoSendStream::Stop() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + VideoSendStreamInternal* send_stream = send_stream_.get();
|
| + worker_queu_->PostTask([send_stream] { send_stream->Stop(); });
|
| +}
|
| +
|
| +VideoCaptureInput* VideoSendStream::Input() {
|
| + return send_stream_->Input();
|
| +}
|
| +
|
| +void VideoSendStream::ReconfigureVideoEncoder(
|
| + const VideoEncoderConfig& config) {
|
| + // ReconfigureVideoEncoder can be called from multiple threads at the moment
|
| + // in libjingle.
|
| + VideoSendStreamInternal* send_stream = send_stream_.get();
|
| + worker_queu_->PostTask(
|
| + [send_stream, config] { send_stream->ReconfigureVideoEncoder(config); });
|
| +}
|
| +
|
| +VideoSendStream::Stats VideoSendStream::GetStats() {
|
| + return send_stream_->GetStats();
|
| +}
|
| +
|
| +void VideoSendStream::SignalNetworkState(NetworkState state) {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + VideoSendStreamInternal* send_stream = send_stream_.get();
|
| + worker_queu_->PostTask(
|
| + [send_stream, state] { send_stream->SignalNetworkState(state); });
|
| +}
|
| +
|
| +VideoSendStream::RtpStateMap VideoSendStream::StopPermanentlyAndGetRtpStates() {
|
| + RTC_DCHECK_RUN_ON(&thread_checker_);
|
| + VideoSendStream::RtpStateMap state_map;
|
| + send_stream_->DeRegisterProcessThread();
|
| + worker_queu_->PostTask(
|
| + std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRTPStateTask(
|
| + &state_map, std::move(send_stream_), &thread_sync_event_)));
|
| + thread_sync_event_.Wait(rtc::Event::kForever);
|
| + return state_map;
|
| +}
|
| +
|
| +bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
|
| + return send_stream_->DeliverRtcp(packet, length);
|
| +}
|
| +
|
| +VideoSendStreamInternal::VideoSendStreamInternal(
|
| + int num_cpu_cores,
|
| + rtc::TaskQueue* worker_queu,
|
| CallStats* call_stats,
|
| CongestionController* congestion_controller,
|
| BitrateAllocator* bitrate_allocator,
|
| @@ -388,7 +605,9 @@ VideoSendStream::VideoSendStream(
|
| encoder_config.content_type),
|
| config_(config),
|
| suspended_ssrcs_(suspended_ssrcs),
|
| - module_process_thread_(module_process_thread),
|
| + module_process_thread_(nullptr),
|
| + worker_queu_(worker_queu),
|
| + check_encoder_activity_task_(nullptr),
|
| call_stats_(call_stats),
|
| congestion_controller_(congestion_controller),
|
| bitrate_allocator_(bitrate_allocator),
|
| @@ -396,18 +615,15 @@ VideoSendStream::VideoSendStream(
|
| encoder_thread_(EncoderThreadFunction, this, "EncoderThread"),
|
| encoder_wakeup_event_(false, false),
|
| stop_encoder_thread_(0),
|
| - state_(State::kStopped),
|
| + max_padding_bitrate_(0),
|
| + encoder_target_rate_(0),
|
| overuse_detector_(
|
| Clock::GetRealTimeClock(),
|
| GetCpuOveruseOptions(config.encoder_settings.full_overuse_time),
|
| this,
|
| config.post_encode_callback,
|
| &stats_proxy_),
|
| - vie_encoder_(num_cpu_cores,
|
| - module_process_thread_,
|
| - &stats_proxy_,
|
| - &overuse_detector_,
|
| - this),
|
| + vie_encoder_(num_cpu_cores, &stats_proxy_, &overuse_detector_, this),
|
| encoder_feedback_(Clock::GetRealTimeClock(),
|
| config.rtp.ssrcs,
|
| &vie_encoder_),
|
| @@ -432,17 +648,17 @@ VideoSendStream::VideoSendStream(
|
| config_.local_renderer,
|
| &stats_proxy_,
|
| &overuse_detector_) {
|
| - LOG(LS_INFO) << "VideoSendStream: " << config_.ToString();
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| + LOG(LS_INFO) << "VideoSendStreamInternal: " << config_.ToString();
|
| + module_process_thread_checker_.DetachFromThread();
|
|
|
| RTC_DCHECK(!config_.rtp.ssrcs.empty());
|
| - RTC_DCHECK(module_process_thread_);
|
| RTC_DCHECK(call_stats_);
|
| RTC_DCHECK(congestion_controller_);
|
| RTC_DCHECK(remb_);
|
|
|
| // RTP/RTCP initialization.
|
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
| - module_process_thread_->RegisterModule(rtp_rtcp);
|
| congestion_controller_->packet_router()->AddRtpModule(rtp_rtcp);
|
| }
|
|
|
| @@ -486,129 +702,132 @@ VideoSendStream::VideoSendStream(
|
| RTC_DCHECK_LE(config.encoder_settings.payload_type, 127);
|
| ReconfigureVideoEncoder(encoder_config);
|
|
|
| - module_process_thread_->RegisterModule(&overuse_detector_);
|
| -
|
| encoder_thread_checker_.DetachFromThread();
|
| encoder_thread_.Start();
|
| encoder_thread_.SetPriority(rtc::kHighPriority);
|
| }
|
|
|
| -VideoSendStream::~VideoSendStream() {
|
| - LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString();
|
| +void VideoSendStreamInternal::RegisterProcessThread(
|
| + ProcessThread* module_process_thread) {
|
| + RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
|
| + RTC_DCHECK(!module_process_thread_);
|
| + module_process_thread_ = module_process_thread;
|
| +
|
| + for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
| + module_process_thread_->RegisterModule(rtp_rtcp);
|
| + }
|
| + module_process_thread_->RegisterModule(&overuse_detector_);
|
| + vie_encoder_.RegisterProcessThread(module_process_thread);
|
| +}
|
| +
|
| +void VideoSendStreamInternal::DeRegisterProcessThread() {
|
| + RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
|
| + module_process_thread_->DeRegisterModule(&overuse_detector_);
|
| + for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
| + module_process_thread_->DeRegisterModule(rtp_rtcp);
|
| + }
|
| + vie_encoder_.DeRegisterProcessThread();
|
| +}
|
|
|
| - Stop();
|
| +VideoSendStreamInternal::~VideoSendStreamInternal() {
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| + LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_.ToString();
|
|
|
| // Stop the encoder thread permanently.
|
| rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1);
|
| encoder_wakeup_event_.Set();
|
| encoder_thread_.Stop();
|
|
|
| - // This needs to happen after stopping the encoder thread,
|
| - // since the encoder thread calls AddObserver.
|
| bitrate_allocator_->RemoveObserver(this);
|
|
|
| - module_process_thread_->DeRegisterModule(&overuse_detector_);
|
| -
|
| rtp_rtcp_modules_[0]->SetREMBStatus(false);
|
| remb_->RemoveRembSender(rtp_rtcp_modules_[0]);
|
|
|
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
| congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp);
|
| - module_process_thread_->DeRegisterModule(rtp_rtcp);
|
| delete rtp_rtcp;
|
| }
|
| + LOG(LS_INFO) << "~VideoSendStreamInternal: done";
|
| }
|
|
|
| -bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
|
| +bool VideoSendStreamInternal::DeliverRtcp(const uint8_t* packet,
|
| + size_t length) {
|
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
|
| rtp_rtcp->IncomingRtcpPacket(packet, length);
|
| return true;
|
| }
|
|
|
| -void VideoSendStream::Start() {
|
| +void VideoSendStreamInternal::Start() {
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| + LOG_F(LS_INFO) << "Start";
|
| if (payload_router_.active())
|
| return;
|
| TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
|
| payload_router_.set_active(true);
|
| +
|
| + // Add our self as bitrate observer.
|
| + bitrate_allocator_->AddObserver(this, current_video_codec_.minBitrate * 1000,
|
| + current_video_codec_.maxBitrate * 1000,
|
| + max_padding_bitrate_,
|
| + !config_.suspend_below_min_bitrate);
|
| +
|
| + // Start monitoring encoder activity.
|
| {
|
| rtc::CritScope lock(&encoder_settings_crit_);
|
| - pending_state_change_ = rtc::Optional<State>(State::kStarted);
|
| + RTC_DCHECK(!check_encoder_activity_task_);
|
| + check_encoder_activity_task_ = new CheckEncoderActivityTask(this);
|
| + worker_queu_->PostDelayedTask(
|
| + std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
|
| + CheckEncoderActivityTask::kEncoderTimeOutMs);
|
| }
|
| - encoder_wakeup_event_.Set();
|
| +
|
| + vie_encoder_.SendKeyFrame();
|
| }
|
|
|
| -void VideoSendStream::Stop() {
|
| +void VideoSendStreamInternal::Stop() {
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| if (!payload_router_.active())
|
| return;
|
| TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
|
| payload_router_.set_active(false);
|
| + bitrate_allocator_->RemoveObserver(this);
|
| {
|
| rtc::CritScope lock(&encoder_settings_crit_);
|
| - pending_state_change_ = rtc::Optional<State>(State::kStopped);
|
| + check_encoder_activity_task_->Stop();
|
| + check_encoder_activity_task_ = nullptr;
|
| }
|
| - encoder_wakeup_event_.Set();
|
| + vie_encoder_.OnBitrateUpdated(0, 0, 0);
|
| }
|
|
|
| -VideoCaptureInput* VideoSendStream::Input() {
|
| +VideoCaptureInput* VideoSendStreamInternal::Input() {
|
| return &input_;
|
| }
|
|
|
| -bool VideoSendStream::EncoderThreadFunction(void* obj) {
|
| - static_cast<VideoSendStream*>(obj)->EncoderProcess();
|
| +bool VideoSendStreamInternal::EncoderThreadFunction(void* obj) {
|
| + static_cast<VideoSendStreamInternal*>(obj)->EncoderProcess();
|
| // We're done, return false to abort.
|
| return false;
|
| }
|
|
|
| -void VideoSendStream::EncoderProcess() {
|
| +void VideoSendStreamInternal::EncoderProcess() {
|
| RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder(
|
| 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.
|
| - const int kEncodeCheckForActivityPeriodMs = 1000;
|
| - encoder_wakeup_event_.Wait(kEncodeCheckForActivityPeriodMs);
|
| + encoder_wakeup_event_.Wait(rtc::Event::kForever);
|
| if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_))
|
| break;
|
| - bool change_settings = false;
|
| - rtc::Optional<State> pending_state_change;
|
| + std::unique_ptr<VideoCodec> pending_encoder_settings;
|
| {
|
| 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_);
|
| - }
|
| + std::swap(pending_encoder_settings_, pending_encoder_settings);
|
| }
|
| - if (change_settings) {
|
| - 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,
|
| + if (pending_encoder_settings) {
|
| + vie_encoder_.SetEncoder(*pending_encoder_settings,
|
| payload_router_.MaxPayloadLength());
|
|
|
| - // Clear stats for disabled layers.
|
| - 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 =
|
| - current_encoder_settings_->config.streams.back()
|
| - .temporal_layer_thresholds_bps.size() +
|
| - 1;
|
| - protection_bitrate_calculator_.SetEncodingData(
|
| - 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
|
| // a frame (which might correspond to the last frame size).
|
| @@ -616,51 +835,6 @@ void VideoSendStream::EncoderProcess() {
|
| continue;
|
| }
|
|
|
| - 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.";
|
| - }
|
| - encoder_wakeup_event_.Set();
|
| - continue;
|
| - }
|
| -
|
| - // Check if the encoder has produced anything the last kEncoderTimeOutMs.
|
| - // If not, deregister as BitrateAllocatorObserver.
|
| - 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);
|
| - state_ = State::kEncoderTimedOut;
|
| - }
|
| - if (state_ == State::kEncoderTimedOut &&
|
| - 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);
|
| - state_ = State::kStarted;
|
| - }
|
| -
|
| VideoFrame frame;
|
| if (input_.GetVideoFrame(&frame)) {
|
| // TODO(perkj): |pre_encode_callback| is only used by tests. Tests should
|
| @@ -674,38 +848,87 @@ void VideoSendStream::EncoderProcess() {
|
| vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type);
|
| }
|
|
|
| -void VideoSendStream::ReconfigureVideoEncoder(
|
| +void VideoSendStreamInternal::EncoderTimedOut() {
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| + // If the encoder has not produced anything the last kEncoderTimeOutMs and it
|
| + // is supposed to, deregister as BitrateAllocatorObserver. This can happen
|
| + // if a camera stop producing frames, temporary or permanently during a call.
|
| + if (encoder_target_rate_ > 0) {
|
| + LOG_F(LS_INFO) << "Encoder timed out.";
|
| + bitrate_allocator_->RemoveObserver(this);
|
| + }
|
| +}
|
| +
|
| +void VideoSendStreamInternal::EncoderIsActive() {
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| + LOG_F(LS_INFO) << "Encoder is active.";
|
| + bitrate_allocator_->AddObserver(this, current_video_codec_.minBitrate * 1000,
|
| + current_video_codec_.maxBitrate * 1000,
|
| + max_padding_bitrate_,
|
| + !config_.suspend_below_min_bitrate);
|
| +}
|
| +
|
| +void VideoSendStreamInternal::ReconfigureVideoEncoder(
|
| const VideoEncoderConfig& config) {
|
| + RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size());
|
| TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder");
|
| LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString();
|
| RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size());
|
| - VideoCodec video_codec = VideoEncoderConfigToVideoCodec(
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| +
|
| + current_video_codec_ = VideoEncoderConfigToVideoCodec(
|
| config, config_.encoder_settings.payload_name,
|
| config_.encoder_settings.payload_type);
|
| +
|
| + max_padding_bitrate_ =
|
| + CalulcateMaxPadBitrateBps(config, config_.suspend_below_min_bitrate);
|
| + current_video_codec_.startBitrate =
|
| + bitrate_allocator_->GetStartBitrate(this) / 1000;
|
| +
|
| + payload_router_.SetSendStreams(config.streams);
|
| +
|
| + // Clear stats for disabled layers.
|
| + for (size_t i = config.streams.size(); i < config_.rtp.ssrcs.size(); ++i) {
|
| + stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]);
|
| + }
|
| +
|
| + size_t number_of_temporal_layers =
|
| + config.streams.back().temporal_layer_thresholds_bps.size() + 1;
|
| + protection_bitrate_calculator_.SetEncodingData(
|
| + current_video_codec_.startBitrate * 1000, current_video_codec_.width,
|
| + current_video_codec_.height, current_video_codec_.maxFramerate,
|
| + number_of_temporal_layers, payload_router_.MaxPayloadLength());
|
| +
|
| {
|
| rtc::CritScope lock(&encoder_settings_crit_);
|
| - pending_encoder_settings_.reset(new EncoderSettings({video_codec, config}));
|
| + pending_encoder_settings_.reset(new VideoCodec(current_video_codec_));
|
| }
|
| encoder_wakeup_event_.Set();
|
| }
|
|
|
| -VideoSendStream::Stats VideoSendStream::GetStats() {
|
| +VideoSendStream::Stats VideoSendStreamInternal::GetStats() {
|
| return stats_proxy_.GetStats();
|
| }
|
|
|
| -void VideoSendStream::OveruseDetected() {
|
| +void VideoSendStreamInternal::OveruseDetected() {
|
| if (config_.overuse_callback)
|
| config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse);
|
| }
|
|
|
| -void VideoSendStream::NormalUsage() {
|
| +void VideoSendStreamInternal::NormalUsage() {
|
| if (config_.overuse_callback)
|
| config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse);
|
| }
|
|
|
| -int32_t VideoSendStream::Encoded(const EncodedImage& encoded_image,
|
| - const CodecSpecificInfo* codec_specific_info,
|
| - const RTPFragmentationHeader* fragmentation) {
|
| +int32_t VideoSendStreamInternal::Encoded(
|
| + const EncodedImage& encoded_image,
|
| + const CodecSpecificInfo* codec_specific_info,
|
| + const RTPFragmentationHeader* fragmentation) {
|
| + {
|
| + rtc::CritScope lock(&encoder_settings_crit_);
|
| + if (check_encoder_activity_task_)
|
| + check_encoder_activity_task_->UpdateEncoderActivity();
|
| + }
|
| if (config_.post_encode_callback) {
|
| config_.post_encode_callback->EncodedFrameCallback(
|
| EncodedFrame(encoded_image._buffer, encoded_image._length,
|
| @@ -742,7 +965,7 @@ int32_t VideoSendStream::Encoded(const EncodedImage& encoded_image,
|
| return return_value;
|
| }
|
|
|
| -void VideoSendStream::ConfigureProtection() {
|
| +void VideoSendStreamInternal::ConfigureProtection() {
|
| // Enable NACK, FEC or both.
|
| const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0;
|
| bool enable_protection_fec = config_.rtp.fec.ulpfec_payload_type != -1;
|
| @@ -799,7 +1022,7 @@ void VideoSendStream::ConfigureProtection() {
|
| enable_protection_nack);
|
| }
|
|
|
| -void VideoSendStream::ConfigureSsrcs() {
|
| +void VideoSendStreamInternal::ConfigureSsrcs() {
|
| // Configure regular SSRCs.
|
| for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
|
| uint32_t ssrc = config_.rtp.ssrcs[i];
|
| @@ -807,7 +1030,7 @@ void VideoSendStream::ConfigureSsrcs() {
|
| rtp_rtcp->SetSSRC(ssrc);
|
|
|
| // Restore RTP state if previous existed.
|
| - RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
|
| + VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
|
| if (it != suspended_ssrcs_.end())
|
| rtp_rtcp->SetRtpState(it->second);
|
| }
|
| @@ -822,7 +1045,7 @@ void VideoSendStream::ConfigureSsrcs() {
|
| uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
|
| RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
|
| rtp_rtcp->SetRtxSsrc(ssrc);
|
| - RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
|
| + VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
|
| if (it != suspended_ssrcs_.end())
|
| rtp_rtcp->SetRtxState(it->second);
|
| }
|
| @@ -843,7 +1066,7 @@ void VideoSendStream::ConfigureSsrcs() {
|
| }
|
| }
|
|
|
| -std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const {
|
| +std::map<uint32_t, RtpState> VideoSendStreamInternal::GetRtpStates() const {
|
| std::map<uint32_t, RtpState> rtp_states;
|
| for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
|
| uint32_t ssrc = config_.rtp.ssrcs[i];
|
| @@ -859,29 +1082,36 @@ std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const {
|
| return rtp_states;
|
| }
|
|
|
| -void VideoSendStream::SignalNetworkState(NetworkState state) {
|
| +void VideoSendStreamInternal::SignalNetworkState(NetworkState state) {
|
| for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
| rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_.rtp.rtcp_mode
|
| : RtcpMode::kOff);
|
| }
|
| }
|
|
|
| -void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps,
|
| - uint8_t fraction_loss,
|
| - int64_t rtt) {
|
| +void VideoSendStreamInternal::OnBitrateUpdated(uint32_t bitrate_bps,
|
| + uint8_t fraction_loss,
|
| + int64_t rtt) {
|
| + RTC_DCHECK_RUN_ON(worker_queu_);
|
| + LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate_bps " << bitrate_bps
|
| + << " fraction_loss " << static_cast<int>(fraction_loss)
|
| + << " rtt " << rtt;
|
| payload_router_.SetTargetSendBitrate(bitrate_bps);
|
| // Get the encoder target rate. It is the estimated network rate -
|
| // protection overhead.
|
| - uint32_t encoder_target_rate = protection_bitrate_calculator_.SetTargetRates(
|
| + encoder_target_rate_ = protection_bitrate_calculator_.SetTargetRates(
|
| bitrate_bps, stats_proxy_.GetSendFrameRate(), fraction_loss, rtt);
|
| - vie_encoder_.OnBitrateUpdated(encoder_target_rate, fraction_loss, rtt);
|
| + if (!payload_router_.active())
|
| + return; // The send stream is currently not started.
|
| + vie_encoder_.OnBitrateUpdated(encoder_target_rate_, fraction_loss, rtt);
|
| }
|
|
|
| -int VideoSendStream::ProtectionRequest(const FecProtectionParams* delta_params,
|
| - const FecProtectionParams* key_params,
|
| - uint32_t* sent_video_rate_bps,
|
| - uint32_t* sent_nack_rate_bps,
|
| - uint32_t* sent_fec_rate_bps) {
|
| +int VideoSendStreamInternal::ProtectionRequest(
|
| + const FecProtectionParams* delta_params,
|
| + const FecProtectionParams* key_params,
|
| + uint32_t* sent_video_rate_bps,
|
| + uint32_t* sent_nack_rate_bps,
|
| + uint32_t* sent_fec_rate_bps) {
|
| *sent_video_rate_bps = 0;
|
| *sent_nack_rate_bps = 0;
|
| *sent_fec_rate_bps = 0;
|
|
|