Index: webrtc/common_video/incoming_video_stream.cc |
diff --git a/webrtc/common_video/incoming_video_stream.cc b/webrtc/common_video/incoming_video_stream.cc |
index b0d8c01bd78d7f9302ceb3a64db7f6116e4a8820..a5e7ba755d35023ad9ba063d37b0e6b928305077 100644 |
--- a/webrtc/common_video/incoming_video_stream.cc |
+++ b/webrtc/common_video/incoming_video_stream.cc |
@@ -10,7 +10,8 @@ |
#include "webrtc/common_video/include/incoming_video_stream.h" |
-#include "webrtc/base/atomicops.h" |
+#include <assert.h> |
+ |
#include "webrtc/base/platform_thread.h" |
#include "webrtc/base/timeutils.h" |
#include "webrtc/common_video/video_render_frames.h" |
@@ -19,46 +20,103 @@ |
namespace webrtc { |
-IncomingVideoStream::IncomingVideoStream( |
- int32_t delay_ms, |
- rtc::VideoSinkInterface<VideoFrame>* callback) |
- : incoming_render_thread_(&IncomingVideoStreamThreadFun, |
- this, |
- "IncomingVideoStreamThread"), |
+IncomingVideoStream::IncomingVideoStream(bool disable_prerenderer_smoothing) |
+ : disable_prerenderer_smoothing_(disable_prerenderer_smoothing), |
+ incoming_render_thread_(), |
deliver_buffer_event_(EventTimerWrapper::Create()), |
- external_callback_(callback), |
- render_buffers_(new VideoRenderFrames(delay_ms)) { |
- RTC_DCHECK(external_callback_); |
- |
- render_thread_checker_.DetachFromThread(); |
- decoder_thread_checker_.DetachFromThread(); |
- |
- incoming_render_thread_.Start(); |
- incoming_render_thread_.SetPriority(rtc::kRealtimePriority); |
- deliver_buffer_event_->StartTimer(false, kEventStartupTimeMs); |
-} |
+ running_(false), |
+ external_callback_(nullptr), |
+ render_buffers_(new VideoRenderFrames()) {} |
IncomingVideoStream::~IncomingVideoStream() { |
- RTC_DCHECK(main_thread_checker_.CalledOnValidThread()); |
- |
- { |
- rtc::CritScope cs(&buffer_critsect_); |
- render_buffers_.reset(); |
- } |
- |
- deliver_buffer_event_->Set(); |
- incoming_render_thread_.Stop(); |
- deliver_buffer_event_->StopTimer(); |
+ Stop(); |
} |
void IncomingVideoStream::OnFrame(const VideoFrame& video_frame) { |
- RTC_DCHECK_RUN_ON(&decoder_thread_checker_); |
+ rtc::CritScope csS(&stream_critsect_); |
+ |
+ if (!running_) { |
+ return; |
+ } |
// Hand over or insert frame. |
- rtc::CritScope csB(&buffer_critsect_); |
- if (render_buffers_->AddFrame(video_frame) == 1) { |
- deliver_buffer_event_->Set(); |
+ if (disable_prerenderer_smoothing_) { |
+ DeliverFrame(video_frame); |
+ } else { |
+ rtc::CritScope csB(&buffer_critsect_); |
+ if (render_buffers_->AddFrame(video_frame) == 1) { |
+ deliver_buffer_event_->Set(); |
+ } |
} |
+} |
+ |
+int32_t IncomingVideoStream::SetExpectedRenderDelay( |
+ int32_t delay_ms) { |
+ rtc::CritScope csS(&stream_critsect_); |
+ if (running_) { |
+ return -1; |
+ } |
+ rtc::CritScope cs(&buffer_critsect_); |
+ return render_buffers_->SetRenderDelay(delay_ms); |
+} |
+ |
+void IncomingVideoStream::SetExternalCallback( |
+ rtc::VideoSinkInterface<VideoFrame>* external_callback) { |
+ rtc::CritScope cs(&thread_critsect_); |
+ external_callback_ = external_callback; |
+} |
+ |
+int32_t IncomingVideoStream::Start() { |
+ rtc::CritScope csS(&stream_critsect_); |
+ if (running_) { |
+ return 0; |
+ } |
+ |
+ if (!disable_prerenderer_smoothing_) { |
+ rtc::CritScope csT(&thread_critsect_); |
+ assert(incoming_render_thread_ == NULL); |
+ |
+ incoming_render_thread_.reset(new rtc::PlatformThread( |
+ IncomingVideoStreamThreadFun, this, "IncomingVideoStreamThread")); |
+ if (!incoming_render_thread_) { |
+ return -1; |
+ } |
+ |
+ incoming_render_thread_->Start(); |
+ incoming_render_thread_->SetPriority(rtc::kRealtimePriority); |
+ deliver_buffer_event_->StartTimer(false, kEventStartupTimeMs); |
+ } |
+ |
+ running_ = true; |
+ return 0; |
+} |
+ |
+int32_t IncomingVideoStream::Stop() { |
+ rtc::CritScope cs_stream(&stream_critsect_); |
+ |
+ if (!running_) { |
+ return 0; |
+ } |
+ |
+ rtc::PlatformThread* thread = NULL; |
+ { |
+ rtc::CritScope cs_thread(&thread_critsect_); |
+ if (incoming_render_thread_) { |
+ // Setting the incoming render thread to NULL marks that we're performing |
+ // a shutdown and will make IncomingVideoStreamProcess abort after wakeup. |
+ thread = incoming_render_thread_.release(); |
+ deliver_buffer_event_->StopTimer(); |
+ // Set the event to allow the thread to wake up and shut down without |
+ // waiting for a timeout. |
+ deliver_buffer_event_->Set(); |
+ } |
+ } |
+ if (thread) { |
+ thread->Stop(); |
+ delete thread; |
+ } |
+ running_ = false; |
+ return 0; |
} |
bool IncomingVideoStream::IncomingVideoStreamThreadFun(void* obj) { |
@@ -66,18 +124,18 @@ |
} |
bool IncomingVideoStream::IncomingVideoStreamProcess() { |
- RTC_DCHECK_RUN_ON(&render_thread_checker_); |
+ if (kEventError != deliver_buffer_event_->Wait(kEventMaxWaitTimeMs)) { |
+ rtc::CritScope cs(&thread_critsect_); |
+ if (incoming_render_thread_ == NULL) { |
+ // Terminating |
+ return false; |
+ } |
- if (kEventError != deliver_buffer_event_->Wait(kEventMaxWaitTimeMs)) { |
// Get a new frame to render and the time for the frame after this one. |
rtc::Optional<VideoFrame> frame_to_render; |
uint32_t wait_time; |
{ |
rtc::CritScope cs(&buffer_critsect_); |
- if (!render_buffers_.get()) { |
- // Terminating |
- return false; |
- } |
frame_to_render = render_buffers_->FrameToRender(); |
wait_time = render_buffers_->TimeToNextFrameRelease(); |
} |
@@ -86,26 +144,21 @@ |
if (wait_time > kEventMaxWaitTimeMs) { |
wait_time = kEventMaxWaitTimeMs; |
} |
- |
deliver_buffer_event_->StartTimer(false, wait_time); |
- if (frame_to_render) { |
- external_callback_->OnFrame(*frame_to_render); |
- } |
+ if (frame_to_render) |
+ DeliverFrame(*frame_to_render); |
} |
return true; |
} |
-//////////////////////////////////////////////////////////////////////////////// |
-IncomingVideoStreamNoSmoothing::IncomingVideoStreamNoSmoothing( |
- rtc::VideoSinkInterface<VideoFrame>* callback) |
- : callback_(callback), queue_("InVideoStream") { |
- decoder_thread_checker_.DetachFromThread(); |
-} |
+void IncomingVideoStream::DeliverFrame(const VideoFrame& video_frame) { |
+ rtc::CritScope cs(&thread_critsect_); |
-void IncomingVideoStreamNoSmoothing::OnFrame(const VideoFrame& video_frame) { |
- RTC_DCHECK_RUN_ON(&decoder_thread_checker_); |
- queue_.PostTask([video_frame, this]() { callback_->OnFrame(video_frame); }); |
+ // Send frame for rendering. |
+ if (external_callback_) { |
+ external_callback_->OnFrame(video_frame); |
+ } |
} |
} // namespace webrtc |