Index: webrtc/video/vie_encoder.cc |
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc |
index 74e1bc02e85152fa90cafba13a6472ebd0c0c095..cd6d88dafc54f2e2ff5a7a281dcbca458943c5ff 100644 |
--- a/webrtc/video/vie_encoder.cc |
+++ b/webrtc/video/vie_encoder.cc |
@@ -241,6 +241,47 @@ class ViEEncoder::EncodeTask : public rtc::QueuedTask { |
const bool log_stats_; |
}; |
+// VideoSourceProxy is responsible ensuring thread safety between calls to |
+// ViEEncoder::SetSource that will happen on libjingles worker thread when a |
+// video capturer is connected to the encoder and the encoder task queue |
+// (encoder_queue_) where the encoder reports its VideoSinkWants. |
+class ViEEncoder::VideoSourceProxy { |
+ public: |
+ explicit VideoSourceProxy(ViEEncoder* vie_encoder) |
+ : vie_encoder_(vie_encoder), source_(nullptr) {} |
+ |
+ void SetSource(rtc::VideoSourceInterface<VideoFrame>* source) { |
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_); |
+ rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr; |
+ { |
+ rtc::CritScope lock(&crit_); |
+ old_source = source_; |
+ source_ = source; |
+ } |
+ |
+ if (old_source != source && old_source != nullptr) { |
+ old_source->RemoveSink(vie_encoder_); |
+ } |
+ |
+ if (!source) { |
+ return; |
+ } |
+ |
+ // TODO(perkj): Let VideoSourceProxy implement LoadObserver and truly send |
+ // CPU load as sink wants. |
+ rtc::VideoSinkWants wants; |
+ source->AddOrUpdateSink(vie_encoder_, wants); |
+ } |
+ |
+ private: |
+ rtc::CriticalSection crit_; |
+ rtc::SequencedTaskChecker main_checker_; |
+ ViEEncoder* vie_encoder_; |
+ rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); |
+ |
+ RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); |
+}; |
+ |
ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
SendStatisticsProxy* stats_proxy, |
const VideoSendStream::Config::EncoderSettings& settings, |
@@ -249,6 +290,7 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
EncodedFrameObserver* encoder_timing) |
: shutdown_event_(true /* manual_reset */, false), |
number_of_cores_(number_of_cores), |
+ source_proxy_(new VideoSourceProxy(this)), |
settings_(settings), |
vp_(VideoProcessing::Create()), |
video_sender_(Clock::GetRealTimeClock(), this, this), |
@@ -288,23 +330,27 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
} |
ViEEncoder::~ViEEncoder() { |
+ RTC_DCHECK_RUN_ON(&thread_checker_); |
RTC_DCHECK(shutdown_event_.Wait(0)) |
<< "Must call ::Stop() before destruction."; |
} |
void ViEEncoder::Stop() { |
- if (!encoder_queue_.IsCurrent()) { |
- encoder_queue_.PostTask([this] { Stop(); }); |
- shutdown_event_.Wait(rtc::Event::kForever); |
- return; |
- } |
- RTC_DCHECK_RUN_ON(&encoder_queue_); |
- video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type, false); |
- overuse_detector_.StopCheckForOveruse(); |
- shutdown_event_.Set(); |
+ RTC_DCHECK_RUN_ON(&thread_checker_); |
+ source_proxy_->SetSource(nullptr); |
+ encoder_queue_.PostTask([this] { |
+ RTC_DCHECK_RUN_ON(&encoder_queue_); |
+ video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type, |
+ false); |
+ overuse_detector_.StopCheckForOveruse(); |
+ shutdown_event_.Set(); |
+ }); |
+ |
+ shutdown_event_.Wait(rtc::Event::kForever); |
} |
void ViEEncoder::RegisterProcessThread(ProcessThread* module_process_thread) { |
+ RTC_DCHECK_RUN_ON(&thread_checker_); |
RTC_DCHECK(!module_process_thread_); |
module_process_thread_ = module_process_thread; |
module_process_thread_->RegisterModule(&video_sender_); |
@@ -312,9 +358,15 @@ void ViEEncoder::RegisterProcessThread(ProcessThread* module_process_thread) { |
} |
void ViEEncoder::DeRegisterProcessThread() { |
+ RTC_DCHECK_RUN_ON(&thread_checker_); |
module_process_thread_->DeRegisterModule(&video_sender_); |
} |
+void ViEEncoder::SetSource(rtc::VideoSourceInterface<VideoFrame>* source) { |
+ RTC_DCHECK_RUN_ON(&thread_checker_); |
+ source_proxy_->SetSource(source); |
+} |
+ |
void ViEEncoder::SetSink(EncodedImageCallback* sink) { |
encoder_queue_.PostTask([this, sink] { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
@@ -384,7 +436,7 @@ void ViEEncoder::ConfigureEncoderInternal(const VideoCodec& video_codec, |
} |
} |
-void ViEEncoder::IncomingCapturedFrame(const VideoFrame& video_frame) { |
+void ViEEncoder::OnFrame(const VideoFrame& video_frame) { |
RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_); |
stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height()); |