Index: webrtc/video/video_capture_input.cc |
diff --git a/webrtc/video/video_capture_input.cc b/webrtc/video/video_capture_input.cc |
index 1c5f2992910737e14b9cf72e036c3af7e358464d..d2353bd82480036c7d011e228478f3b40b894b6b 100644 |
--- a/webrtc/video/video_capture_input.cc |
+++ b/webrtc/video/video_capture_input.cc |
@@ -23,7 +23,7 @@ |
#include "webrtc/system_wrappers/include/tick_util.h" |
#include "webrtc/video/overuse_frame_detector.h" |
#include "webrtc/video/send_statistics_proxy.h" |
-#include "webrtc/video/vie_encoder.h" |
+#include "webrtc/video/video_send_stream.h" |
namespace webrtc { |
@@ -31,16 +31,19 @@ namespace internal { |
VideoCaptureInput::VideoCaptureInput( |
ProcessThread* module_process_thread, |
VideoCaptureCallback* frame_callback, |
- VideoRenderer* local_renderer, |
+ VideoCodingModule* vcm, |
+ VideoSendStream* video_send_stream, |
+ const webrtc::VideoSendStream::Config& config, |
SendStatisticsProxy* stats_proxy, |
- CpuOveruseObserver* overuse_observer, |
- EncodingTimeObserver* encoding_time_observer) |
+ CpuOveruseObserver* overuse_observer) |
: capture_cs_(CriticalSectionWrapper::CreateCriticalSection()), |
module_process_thread_(module_process_thread), |
frame_callback_(frame_callback), |
- local_renderer_(local_renderer), |
+ vcm_(vcm), |
+ video_send_stream_(video_send_stream), |
+ config_(config), |
+ encoder_registered_(false), |
stats_proxy_(stats_proxy), |
- incoming_frame_cs_(CriticalSectionWrapper::CreateCriticalSection()), |
encoder_thread_(EncoderThreadFunction, this, "EncoderThread"), |
capture_event_(false, false), |
stop_(0), |
@@ -51,8 +54,10 @@ VideoCaptureInput::VideoCaptureInput( |
overuse_detector_(new OveruseFrameDetector(Clock::GetRealTimeClock(), |
CpuOveruseOptions(), |
overuse_observer, |
- stats_proxy)), |
- encoding_time_observer_(encoding_time_observer) { |
+ stats_proxy)) { |
+ RTC_DCHECK(config_.encoder_settings.encoder != nullptr); |
+ RTC_DCHECK_GE(config_.encoder_settings.payload_type, 0); |
+ RTC_DCHECK_LE(config_.encoder_settings.payload_type, 127); |
encoder_thread_.Start(); |
encoder_thread_.SetPriority(rtc::kHighPriority); |
module_process_thread_->RegisterModule(overuse_detector_.get()); |
@@ -70,8 +75,8 @@ VideoCaptureInput::~VideoCaptureInput() { |
void VideoCaptureInput::IncomingCapturedFrame(const VideoFrame& video_frame) { |
// TODO(pbos): Remove local rendering, it should be handled by the client code |
// if required. |
- if (local_renderer_) |
- local_renderer_->RenderFrame(video_frame, 0); |
+ if (config_.local_renderer) |
+ config_.local_renderer->RenderFrame(video_frame, 0); |
stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height()); |
@@ -118,6 +123,12 @@ void VideoCaptureInput::IncomingCapturedFrame(const VideoFrame& video_frame) { |
capture_event_.Set(); |
} |
+void VideoCaptureInput::TriggerSetSendCodec(const VideoCodec& video_codec) { |
+ CriticalSectionScoped cs(capture_cs_.get()); |
+ replacement_codec_settings_ = rtc::Optional<VideoCodec>(video_codec); |
+ capture_event_.Set(); |
+} |
+ |
bool VideoCaptureInput::EncoderThreadFunction(void* obj) { |
return static_cast<VideoCaptureInput*>(obj)->EncoderProcess(); |
} |
@@ -126,18 +137,49 @@ bool VideoCaptureInput::EncoderProcess() { |
static const int kThreadWaitTimeMs = 100; |
int64_t capture_time = -1; |
if (capture_event_.Wait(kThreadWaitTimeMs)) { |
- if (rtc::AtomicOps::AcquireLoad(&stop_)) |
+ if (rtc::AtomicOps::AcquireLoad(&stop_)) { |
+ if (encoder_registered_) { |
+ vcm_->RegisterExternalEncoder(nullptr, |
+ config_.encoder_settings.payload_type); |
+ } |
return false; |
+ } |
int64_t encode_start_time = -1; |
VideoFrame deliver_frame; |
+ rtc::Optional<VideoCodec> new_codec_settings; |
{ |
CriticalSectionScoped cs(capture_cs_.get()); |
- if (!captured_frame_.IsZeroSize()) { |
+ if (replacement_codec_settings_) { |
+ new_codec_settings = replacement_codec_settings_; |
+ replacement_codec_settings_ = rtc::Optional<VideoCodec>(); |
+ } else if (encoder_registered_ && !captured_frame_.IsZeroSize()) { |
+ // Only pick up frames when the encoder is registered. This prevents |
+ // encoding old frames from before the encoder was initialized. |
deliver_frame = captured_frame_; |
captured_frame_.Reset(); |
} |
} |
+ if (new_codec_settings) { |
+ if (!encoder_registered_) { |
+ RTC_CHECK_EQ(VCM_OK, vcm_->RegisterExternalEncoder( |
+ config_.encoder_settings.encoder, |
+ config_.encoder_settings.payload_type, |
+ config_.encoder_settings.internal_source)); |
+ } |
+ // TODO(pbos): Mock VideoSendStream and use from tests so |
+ // video_send_stream_ can always be non-null. |
+ if (video_send_stream_) |
+ video_send_stream_->SetSendCodec(*new_codec_settings); |
+ if (config_.suspend_below_min_bitrate) |
+ vcm_->SuspendBelowMinBitrate(); |
+ encoder_registered_ = true; |
+ // We could still have a frame to pick up here since none was picked up |
+ // while the encoder was being registered/configured. |
+ // Flag event again and wake up as soon as possible. |
+ capture_event_.Set(); |
+ return true; |
+ } |
if (!deliver_frame.IsZeroSize()) { |
capture_time = deliver_frame.render_time_ms(); |
encode_start_time = Clock::GetRealTimeClock()->TimeInMilliseconds(); |
@@ -148,8 +190,8 @@ bool VideoCaptureInput::EncoderProcess() { |
int encode_time_ms = static_cast<int>( |
Clock::GetRealTimeClock()->TimeInMilliseconds() - encode_start_time); |
stats_proxy_->OnEncodedFrame(encode_time_ms); |
- if (encoding_time_observer_) { |
- encoding_time_observer_->OnReportEncodedTime( |
+ if (config_.encoding_time_observer) { |
+ config_.encoding_time_observer->OnReportEncodedTime( |
deliver_frame.ntp_time_ms(), encode_time_ms); |
} |
} |