1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/video/video_capture_input.h" 12 13 #include "webrtc/base/checks.h" 14 #include "webrtc/base/logging.h" 15 #include "webrtc/base/trace_event.h" 16 #include "webrtc/modules/include/module_common_types.h" 17 #include "webrtc/modules/utility/include/process_thread.h" 18 #include "webrtc/modules/video_capture/video_capture_factory.h" 19 #include "webrtc/modules/video_processing/include/video_processing.h" 20 #include "webrtc/modules/video_render/video_render_defines.h" 21 #include "webrtc/system_wrappers/include/clock.h" 22 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 23 #include "webrtc/system_wrappers/include/tick_util.h" 24 #include "webrtc/video/overuse_frame_detector.h" 25 #include "webrtc/video/send_statistics_proxy.h" 26 #include "webrtc/video/vie_encoder.h" 27 28 namespace webrtc { 29 30 namespace internal { 31 VideoCaptureInput::VideoCaptureInput( 32 ProcessThread* module_process_thread, 33 VideoCaptureCallback* frame_callback, 34 VideoRenderer* local_renderer, 35 SendStatisticsProxy* stats_proxy, 36 CpuOveruseObserver* overuse_observer, 37 EncodingTimeObserver* encoding_time_observer) 38 : capture_cs_(CriticalSectionWrapper::CreateCriticalSection()), 39 module_process_thread_(module_process_thread), 40 frame_callback_(frame_callback), 41 local_renderer_(local_renderer), 42 stats_proxy_(stats_proxy), 43 incoming_frame_cs_(CriticalSectionWrapper::CreateCriticalSection()), 44 encoder_thread_(EncoderThreadFunction, this, "EncoderThread"), 45 capture_event_(false, false), 46 stop_(0), 47 last_captured_timestamp_(0), 48 delta_ntp_internal_ms_( 49 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() - 50 TickTime::MillisecondTimestamp()), 51 overuse_detector_(new OveruseFrameDetector(Clock::GetRealTimeClock(), 52 CpuOveruseOptions(), 53 overuse_observer, 54 stats_proxy)), 55 encoding_time_observer_(encoding_time_observer) { 56 encoder_thread_.Start(); 57 encoder_thread_.SetPriority(rtc::kHighPriority); 58 module_process_thread_->RegisterModule(overuse_detector_.get()); 59 } 60 61 VideoCaptureInput::~VideoCaptureInput() { 62 module_process_thread_->DeRegisterModule(overuse_detector_.get()); 63 64 // Stop the thread. 65 rtc::AtomicOps::ReleaseStore(&stop_, 1); 66 capture_event_.Set(); 67 encoder_thread_.Stop(); 68 } 69 70 void VideoCaptureInput::IncomingCapturedFrame(const VideoFrame& video_frame) { 71 // TODO(pbos): Remove local rendering, it should be handled by the client code 72 // if required. 73 if (local_renderer_) 74 local_renderer_->RenderFrame(video_frame, 0); 75 76 stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height()); 77 78 VideoFrame incoming_frame = video_frame; 79 80 if (incoming_frame.ntp_time_ms() != 0) { 81 // If a NTP time stamp is set, this is the time stamp we will use. 82 incoming_frame.set_render_time_ms(incoming_frame.ntp_time_ms() - 83 delta_ntp_internal_ms_); 84 } else { // NTP time stamp not set. 85 int64_t render_time = incoming_frame.render_time_ms() != 0 86 ? incoming_frame.render_time_ms() 87 : TickTime::MillisecondTimestamp(); 88 89 incoming_frame.set_render_time_ms(render_time); 90 incoming_frame.set_ntp_time_ms(render_time + delta_ntp_internal_ms_); 91 } 92 93 // Convert NTP time, in ms, to RTP timestamp. 94 const int kMsToRtpTimestamp = 90; 95 incoming_frame.set_timestamp( 96 kMsToRtpTimestamp * static_cast<uint32_t>(incoming_frame.ntp_time_ms())); 97 98 CriticalSectionScoped cs(capture_cs_.get()); 99 if (incoming_frame.ntp_time_ms() <= last_captured_timestamp_) { 100 // We don't allow the same capture time for two frames, drop this one. 101 LOG(LS_WARNING) << "Same/old NTP timestamp (" 102 << incoming_frame.ntp_time_ms() 103 << " <= " << last_captured_timestamp_ 104 << ") for incoming frame. Dropping."; 105 return; 106 } 107 108 captured_frame_.ShallowCopy(incoming_frame); 109 last_captured_timestamp_ = incoming_frame.ntp_time_ms(); 110 111 overuse_detector_->FrameCaptured(captured_frame_.width(), 112 captured_frame_.height(), 113 captured_frame_.render_time_ms()); 114 115 TRACE_EVENT_ASYNC_BEGIN1("webrtc", "Video", video_frame.render_time_ms(), 116 "render_time", video_frame.render_time_ms()); 117 118 capture_event_.Set(); 119 } 120 121 bool VideoCaptureInput::EncoderThreadFunction(void* obj) { 122 return static_cast<VideoCaptureInput*>(obj)->EncoderProcess(); 123 } 124 125 bool VideoCaptureInput::EncoderProcess() { 126 static const int kThreadWaitTimeMs = 100; 127 int64_t capture_time = -1; 128 if (capture_event_.Wait(kThreadWaitTimeMs)) { 129 if (rtc::AtomicOps::AcquireLoad(&stop_)) 130 return false; 131 132 int64_t encode_start_time = -1; 133 VideoFrame deliver_frame; 134 { 135 CriticalSectionScoped cs(capture_cs_.get()); 136 if (!captured_frame_.IsZeroSize()) { 137 deliver_frame = captured_frame_; 138 captured_frame_.Reset(); 139 } 140 } 141 if (!deliver_frame.IsZeroSize()) { 142 capture_time = deliver_frame.render_time_ms(); 143 encode_start_time = Clock::GetRealTimeClock()->TimeInMilliseconds(); 144 frame_callback_->DeliverFrame(deliver_frame); 145 } 146 // Update the overuse detector with the duration. 147 if (encode_start_time != -1) { 148 int encode_time_ms = static_cast<int>( 149 Clock::GetRealTimeClock()->TimeInMilliseconds() - encode_start_time); 150 stats_proxy_->OnEncodedFrame(encode_time_ms); 151 if (encoding_time_observer_) { 152 encoding_time_observer_->OnReportEncodedTime( 153 deliver_frame.ntp_time_ms(), encode_time_ms); 154 } 155 } 156 } 157 // We're done! 158 if (capture_time != -1) { 159 overuse_detector_->FrameSent(capture_time); 160 } 161 return true; 162 } 163 164 } // namespace internal 165 } // namespace webrtc 166