diff --git a/webrtc/call/bitrate_estimator_tests.cc b/webrtc/call/bitrate_estimator_tests.cc index 2896c67f37..b8a148c79a 100644 --- a/webrtc/call/bitrate_estimator_tests.cc +++ b/webrtc/call/bitrate_estimator_tests.cc @@ -177,10 +177,9 @@ class BitrateEstimatorTest : public test::CallTest { test_->video_encoder_config_.Copy()); RTC_DCHECK_EQ(1u, test_->video_encoder_config_.streams.size()); frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create( - test_->video_encoder_config_.streams[0].width, + send_stream_->Input(), test_->video_encoder_config_.streams[0].width, test_->video_encoder_config_.streams[0].height, 30, Clock::GetRealTimeClock())); - send_stream_->SetSource(frame_generator_capturer_.get()); send_stream_->Start(); frame_generator_capturer_->Start(); @@ -217,8 +216,8 @@ class BitrateEstimatorTest : public test::CallTest { ~Stream() { EXPECT_FALSE(is_sending_receiving_); - test_->sender_call_->DestroyVideoSendStream(send_stream_); frame_generator_capturer_.reset(nullptr); + test_->sender_call_->DestroyVideoSendStream(send_stream_); send_stream_ = nullptr; if (audio_receive_stream_) { test_->receiver_call_->DestroyAudioReceiveStream(audio_receive_stream_); diff --git a/webrtc/media/engine/fakewebrtccall.cc b/webrtc/media/engine/fakewebrtccall.cc index 9437fa0fba..cb904df66f 100644 --- a/webrtc/media/engine/fakewebrtccall.cc +++ b/webrtc/media/engine/fakewebrtccall.cc @@ -103,17 +103,11 @@ FakeVideoSendStream::FakeVideoSendStream( : sending_(false), config_(std::move(config)), codec_settings_set_(false), - source_(nullptr), num_swapped_frames_(0) { RTC_DCHECK(config.encoder_settings.encoder != NULL); ReconfigureVideoEncoder(std::move(encoder_config)); } -FakeVideoSendStream::~FakeVideoSendStream() { - if (source_) - source_->RemoveSink(this); -} - const webrtc::VideoSendStream::Config& FakeVideoSendStream::GetConfig() const { return config_; } @@ -168,7 +162,8 @@ int64_t FakeVideoSendStream::GetLastTimestamp() const { return last_frame_.render_time_ms(); } -void FakeVideoSendStream::OnFrame(const webrtc::VideoFrame& frame) { +void FakeVideoSendStream::IncomingCapturedFrame( + const webrtc::VideoFrame& frame) { ++num_swapped_frames_; last_frame_.ShallowCopy(frame); } @@ -209,6 +204,10 @@ void FakeVideoSendStream::ReconfigureVideoEncoder( ++num_encoder_reconfigurations_; } +webrtc::VideoCaptureInput* FakeVideoSendStream::Input() { + return this; +} + void FakeVideoSendStream::Start() { sending_ = true; } @@ -217,16 +216,6 @@ void FakeVideoSendStream::Stop() { sending_ = false; } -void FakeVideoSendStream::SetSource( - rtc::VideoSourceInterface* source) { - RTC_DCHECK(source != source_); - if (source_) - source_->RemoveSink(this); - source_ = source; - if (source) - source->AddOrUpdateSink(this, rtc::VideoSinkWants()); -} - FakeVideoReceiveStream::FakeVideoReceiveStream( webrtc::VideoReceiveStream::Config config) : config_(std::move(config)), receiving_(false) {} diff --git a/webrtc/media/engine/fakewebrtccall.h b/webrtc/media/engine/fakewebrtccall.h index 29142c18b7..d3af222489 100644 --- a/webrtc/media/engine/fakewebrtccall.h +++ b/webrtc/media/engine/fakewebrtccall.h @@ -99,13 +99,11 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream { bool started_ = false; }; -class FakeVideoSendStream final - : public webrtc::VideoSendStream, - public rtc::VideoSinkInterface { +class FakeVideoSendStream final : public webrtc::VideoSendStream, + public webrtc::VideoCaptureInput { public: FakeVideoSendStream(webrtc::VideoSendStream::Config config, webrtc::VideoEncoderConfig encoder_config); - ~FakeVideoSendStream() override; const webrtc::VideoSendStream::Config& GetConfig() const; const webrtc::VideoEncoderConfig& GetEncoderConfig() const; std::vector GetVideoStreams(); @@ -124,16 +122,14 @@ class FakeVideoSendStream final } private: - // rtc::VideoSinkInterface implementation. - void OnFrame(const webrtc::VideoFrame& frame) override; + void IncomingCapturedFrame(const webrtc::VideoFrame& frame) override; // webrtc::VideoSendStream implementation. void Start() override; void Stop() override; - void SetSource( - rtc::VideoSourceInterface* source) override; webrtc::VideoSendStream::Stats GetStats() override; void ReconfigureVideoEncoder(webrtc::VideoEncoderConfig config) override; + webrtc::VideoCaptureInput* Input() override; bool sending_; webrtc::VideoSendStream::Config config_; @@ -143,7 +139,6 @@ class FakeVideoSendStream final webrtc::VideoCodecVP8 vp8; webrtc::VideoCodecVP9 vp9; } vpx_settings_; - rtc::VideoSourceInterface* source_; int num_swapped_frames_; webrtc::VideoFrame last_frame_; webrtc::VideoSendStream::Stats stats_; diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc index 8a2b373d91..60f51be8d1 100644 --- a/webrtc/media/engine/webrtcvideoengine2.cc +++ b/webrtc/media/engine/webrtcvideoengine2.cc @@ -1580,7 +1580,6 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( source_(nullptr), external_encoder_factory_(external_encoder_factory), stream_(nullptr), - encoder_sink_(nullptr), parameters_(std::move(config), options, max_bitrate_bps, codec_settings), rtp_parameters_(CreateRtpParametersWithOneEncoding()), pending_encoder_reconfiguration_(false), @@ -1659,7 +1658,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( << ", texture=" << last_frame_info_.is_texture; } - if (encoder_sink_ == NULL) { + if (stream_ == NULL) { // Frame input before send codecs are configured, dropping frame. return; } @@ -1682,7 +1681,7 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( if (cpu_restricted_counter_ > 0) ++cpu_restricted_frame_count_; - encoder_sink_->OnFrame(video_frame); + stream_->Input()->IncomingCapturedFrame(video_frame); } bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( @@ -1705,7 +1704,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( if (options_present) { VideoOptions old_options = parameters_.options; parameters_.options.SetAll(*options); - // Reconfigure encoder settings on the next frame or stream + // Reconfigure encoder settings on the naext frame or stream // recreation if the options changed. if (parameters_.options != old_options) { pending_encoder_reconfiguration_ = true; @@ -1713,7 +1712,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( } if (source_changing) { - if (source == nullptr && encoder_sink_ != nullptr) { + if (source == nullptr && stream_ != nullptr) { LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; // Force this black frame not to be dropped due to timestamp order // check. As IncomingCapturedFrame will drop the frame if this frame's @@ -1726,8 +1725,9 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( last_frame_info_.height)); black_buffer->SetToBlack(); - encoder_sink_->OnFrame(webrtc::VideoFrame( - black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); + stream_->Input()->IncomingCapturedFrame(webrtc::VideoFrame( + black_buffer, last_frame_info_.rotation, + last_frame_timestamp_us_)); } source_ = source; } @@ -1743,7 +1743,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() { RTC_DCHECK(thread_checker_.CalledOnValidThread()); - if (source_ == nullptr) { + if (source_ == NULL) { return; } @@ -2049,23 +2049,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { UpdateSendState(); } -void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( - VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) { - // TODO(perkj): Actually consider the encoder |wants| and remove - // WebRtcVideoSendStream::OnLoadUpdate(Load load). - rtc::CritScope cs(&lock_); - RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink); - encoder_sink_ = sink; -} - -void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( - VideoSinkInterface* sink) { - rtc::CritScope cs(&lock_); - RTC_DCHECK_EQ(encoder_sink_, sink); - encoder_sink_ = nullptr; -} - void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { if (worker_thread_ != rtc::Thread::Current()) { invoker_.AsyncInvoke( @@ -2258,7 +2241,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { } stream_ = call_->CreateVideoSendStream(std::move(config), parameters_.encoder_config.Copy()); - stream_->SetSource(this); parameters_.encoder_config.encoder_specific_settings = NULL; pending_encoder_reconfiguration_ = false; diff --git a/webrtc/media/engine/webrtcvideoengine2.h b/webrtc/media/engine/webrtcvideoengine2.h index b8d17e8105..7e32116608 100644 --- a/webrtc/media/engine/webrtcvideoengine2.h +++ b/webrtc/media/engine/webrtcvideoengine2.h @@ -243,7 +243,6 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { // frames are then converted from cricket frames to webrtc frames. class WebRtcVideoSendStream : public rtc::VideoSinkInterface, - public rtc::VideoSourceInterface, public webrtc::LoadObserver { public: WebRtcVideoSendStream( @@ -263,16 +262,6 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { bool SetRtpParameters(const webrtc::RtpParameters& parameters); webrtc::RtpParameters GetRtpParameters() const; - // Implements rtc::VideoSourceInterface. - // WebRtcVideoSendStream acts as a source to the webrtc::VideoSendStream - // in |stream_|. The reason is that WebRtcVideoSendStream receives - // cricket::VideoFrames and forwards webrtc::VideoFrames to |source_|. - // TODO(perkj, nisse): Refactor WebRtcVideoSendStream to directly connect - // the camera input |source_| - void AddOrUpdateSink(VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override; - void RemoveSink(VideoSinkInterface* sink) override; - void OnFrame(const cricket::VideoFrame& frame) override; bool SetVideoSend(bool mute, const VideoOptions* options, @@ -400,8 +389,6 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { rtc::CriticalSection lock_; webrtc::VideoSendStream* stream_ GUARDED_BY(lock_); - rtc::VideoSinkInterface* encoder_sink_ - GUARDED_BY(lock_); // Contains settings that are the same for all streams in the MediaChannel, // such as codecs, header extensions, and the global bitrate limit for the // entire channel. diff --git a/webrtc/test/BUILD.gn b/webrtc/test/BUILD.gn index 5ac393df1c..4c750eae1f 100644 --- a/webrtc/test/BUILD.gn +++ b/webrtc/test/BUILD.gn @@ -298,6 +298,7 @@ rtc_source_set("test_common") { "statistics.h", "vcm_capturer.cc", "vcm_capturer.h", + "video_capturer.cc", "video_capturer.h", "win/run_loop_win.cc", ] diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc index d6cbaa6d7e..e81d947c30 100644 --- a/webrtc/test/call_test.cc +++ b/webrtc/test/call_test.cc @@ -239,15 +239,15 @@ void CallTest::CreateFrameGeneratorCapturerWithDrift(Clock* clock, float speed) { VideoStream stream = video_encoder_config_.streams.back(); frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create( - stream.width, stream.height, stream.max_framerate * speed, clock)); - video_send_stream_->SetSource(frame_generator_capturer_.get()); + video_send_stream_->Input(), stream.width, stream.height, + stream.max_framerate * speed, clock)); } void CallTest::CreateFrameGeneratorCapturer() { VideoStream stream = video_encoder_config_.streams.back(); frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create( - stream.width, stream.height, stream.max_framerate, clock_)); - video_send_stream_->SetSource(frame_generator_capturer_.get()); + video_send_stream_->Input(), stream.width, stream.height, + stream.max_framerate, clock_)); } void CallTest::CreateFakeAudioDevices() { diff --git a/webrtc/test/frame_generator.cc b/webrtc/test/frame_generator.cc index dbf39c4e09..ed7e95a126 100644 --- a/webrtc/test/frame_generator.cc +++ b/webrtc/test/frame_generator.cc @@ -239,27 +239,6 @@ class ScrollingImageFrameGenerator : public FrameGenerator { } // namespace -FrameForwarder::FrameForwarder() : sink_(nullptr) {} - -void FrameForwarder::IncomingCapturedFrame(const VideoFrame& video_frame) { - rtc::CritScope lock(&crit_); - if (sink_) - sink_->OnFrame(video_frame); -} - -void FrameForwarder::AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) { - rtc::CritScope lock(&crit_); - RTC_DCHECK(!sink_ || sink_ == sink); - sink_ = sink; -} - -void FrameForwarder::RemoveSink(rtc::VideoSinkInterface* sink) { - rtc::CritScope lock(&crit_); - RTC_DCHECK_EQ(sink, sink_); - sink_ = nullptr; -} - FrameGenerator* FrameGenerator::CreateChromaGenerator(size_t width, size_t height) { return new ChromaGenerator(width, height); diff --git a/webrtc/test/frame_generator.h b/webrtc/test/frame_generator.h index fc3f306998..7f20c749e8 100644 --- a/webrtc/test/frame_generator.h +++ b/webrtc/test/frame_generator.h @@ -7,14 +7,12 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_TEST_FRAME_GENERATOR_H_ -#define WEBRTC_TEST_FRAME_GENERATOR_H_ +#ifndef WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_ +#define WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_ #include #include -#include "webrtc/base/criticalsection.h" -#include "webrtc/media/base/videosourceinterface.h" #include "webrtc/typedefs.h" #include "webrtc/video_frame.h" @@ -22,25 +20,6 @@ namespace webrtc { class Clock; namespace test { -// FrameForwarder can be used as an implementation -// of rtc::VideoSourceInterface where the caller controls when -// a frame should be forwarded to its sink. -// Currently this implementation only support one sink. -class FrameForwarder : public rtc::VideoSourceInterface { - public: - FrameForwarder(); - // Forwards |video_frame| to the registered |sink_|. - void IncomingCapturedFrame(const VideoFrame& video_frame); - - private: - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override; - void RemoveSink(rtc::VideoSinkInterface* sink) override; - - rtc::CriticalSection crit_; - rtc::VideoSinkInterface* sink_ GUARDED_BY(crit_); -}; - class FrameGenerator { public: FrameGenerator() {} @@ -82,4 +61,4 @@ class FrameGenerator { } // namespace test } // namespace webrtc -#endif // WEBRTC_TEST_FRAME_GENERATOR_H_ +#endif // WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_ diff --git a/webrtc/test/frame_generator_capturer.cc b/webrtc/test/frame_generator_capturer.cc index 7e929095f0..95ac624c42 100644 --- a/webrtc/test/frame_generator_capturer.cc +++ b/webrtc/test/frame_generator_capturer.cc @@ -21,12 +21,14 @@ namespace webrtc { namespace test { -FrameGeneratorCapturer* FrameGeneratorCapturer::Create(size_t width, +FrameGeneratorCapturer* FrameGeneratorCapturer::Create(VideoCaptureInput* input, + size_t width, size_t height, int target_fps, Clock* clock) { FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( - clock, FrameGenerator::CreateChromaGenerator(width, height), target_fps); + clock, input, FrameGenerator::CreateChromaGenerator(width, height), + target_fps); if (!capturer->Init()) { delete capturer; return NULL; @@ -36,14 +38,16 @@ FrameGeneratorCapturer* FrameGeneratorCapturer::Create(size_t width, } FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile( + VideoCaptureInput* input, const std::string& file_name, size_t width, size_t height, int target_fps, Clock* clock) { FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( - clock, FrameGenerator::CreateFromYuvFile( - std::vector(1, file_name), width, height, 1), + clock, input, + FrameGenerator::CreateFromYuvFile(std::vector(1, file_name), + width, height, 1), target_fps); if (!capturer->Init()) { delete capturer; @@ -54,18 +58,20 @@ FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile( } FrameGeneratorCapturer::FrameGeneratorCapturer(Clock* clock, + VideoCaptureInput* input, FrameGenerator* frame_generator, int target_fps) - : clock_(clock), + : VideoCapturer(input), + clock_(clock), sending_(false), - sink_(nullptr), tick_(EventTimerWrapper::Create()), thread_(FrameGeneratorCapturer::Run, this, "FrameGeneratorCapturer"), frame_generator_(frame_generator), target_fps_(target_fps), first_frame_capture_time_(-1) { - RTC_DCHECK(frame_generator); - RTC_DCHECK_GT(target_fps, 0); + assert(input != NULL); + assert(frame_generator != NULL); + assert(target_fps > 0); } FrameGeneratorCapturer::~FrameGeneratorCapturer() { @@ -107,8 +113,7 @@ void FrameGeneratorCapturer::InsertFrame() { if (first_frame_capture_time_ == -1) { first_frame_capture_time_ = frame->ntp_time_ms(); } - if (sink_) - sink_->OnFrame(*frame); + input_->IncomingCapturedFrame(*frame); } } tick_->Wait(WEBRTC_EVENT_INFINITE); @@ -124,21 +129,6 @@ void FrameGeneratorCapturer::Stop() { sending_ = false; } -void FrameGeneratorCapturer::AddOrUpdateSink( - rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) { - rtc::CritScope cs(&lock_); - RTC_CHECK(!sink_); - sink_ = sink; -} - -void FrameGeneratorCapturer::RemoveSink( - rtc::VideoSinkInterface* sink) { - rtc::CritScope cs(&lock_); - RTC_CHECK(sink_ == sink); - sink_ = nullptr; -} - void FrameGeneratorCapturer::ForceFrame() { tick_->Set(); } diff --git a/webrtc/test/frame_generator_capturer.h b/webrtc/test/frame_generator_capturer.h index 2b2cfbc821..1d6fb62664 100644 --- a/webrtc/test/frame_generator_capturer.h +++ b/webrtc/test/frame_generator_capturer.h @@ -18,7 +18,6 @@ #include "webrtc/common_video/rotation.h" #include "webrtc/test/video_capturer.h" #include "webrtc/typedefs.h" -#include "webrtc/video_frame.h" namespace webrtc { @@ -31,12 +30,14 @@ class FrameGenerator; class FrameGeneratorCapturer : public VideoCapturer { public: - static FrameGeneratorCapturer* Create(size_t width, + static FrameGeneratorCapturer* Create(VideoCaptureInput* input, + size_t width, size_t height, int target_fps, Clock* clock); - static FrameGeneratorCapturer* CreateFromYuvFile(const std::string& file_name, + static FrameGeneratorCapturer* CreateFromYuvFile(VideoCaptureInput* input, + const std::string& file_name, size_t width, size_t height, int target_fps, @@ -45,17 +46,13 @@ class FrameGeneratorCapturer : public VideoCapturer { void Start() override; void Stop() override; - - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override; - void RemoveSink(rtc::VideoSinkInterface* sink) override; - void ForceFrame(); void SetFakeRotation(VideoRotation rotation); int64_t first_frame_capture_time() const { return first_frame_capture_time_; } FrameGeneratorCapturer(Clock* clock, + VideoCaptureInput* input, FrameGenerator* frame_generator, int target_fps); bool Init(); @@ -66,7 +63,6 @@ class FrameGeneratorCapturer : public VideoCapturer { Clock* const clock_; bool sending_; - rtc::VideoSinkInterface* sink_ GUARDED_BY(&lock_); std::unique_ptr tick_; rtc::CriticalSection lock_; diff --git a/webrtc/test/test.gyp b/webrtc/test/test.gyp index ae36da8ffe..3ca146bfbd 100644 --- a/webrtc/test/test.gyp +++ b/webrtc/test/test.gyp @@ -187,6 +187,7 @@ 'statistics.h', 'vcm_capturer.cc', 'vcm_capturer.h', + 'video_capturer.cc', 'video_capturer.h', 'win/run_loop_win.cc', ], diff --git a/webrtc/test/vcm_capturer.cc b/webrtc/test/vcm_capturer.cc index 49d97101e9..792b97ff08 100644 --- a/webrtc/test/vcm_capturer.cc +++ b/webrtc/test/vcm_capturer.cc @@ -16,7 +16,9 @@ namespace webrtc { namespace test { -VcmCapturer::VcmCapturer() : started_(false), sink_(nullptr), vcm_(NULL) {} +VcmCapturer::VcmCapturer(webrtc::VideoCaptureInput* input) + : VideoCapturer(input), started_(false), vcm_(NULL) { +} bool VcmCapturer::Init(size_t width, size_t height, size_t target_fps) { VideoCaptureModule::DeviceInfo* device_info = @@ -52,10 +54,11 @@ bool VcmCapturer::Init(size_t width, size_t height, size_t target_fps) { return true; } -VcmCapturer* VcmCapturer::Create(size_t width, +VcmCapturer* VcmCapturer::Create(VideoCaptureInput* input, + size_t width, size_t height, size_t target_fps) { - VcmCapturer* vcm_capturer = new VcmCapturer(); + VcmCapturer* vcm_capturer = new VcmCapturer(input); if (!vcm_capturer->Init(width, height, target_fps)) { // TODO(pbos): Log a warning that this failed. delete vcm_capturer; @@ -75,19 +78,6 @@ void VcmCapturer::Stop() { started_ = false; } -void VcmCapturer::AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) { - rtc::CritScope lock(&crit_); - RTC_CHECK(!sink_); - sink_ = sink; -} - -void VcmCapturer::RemoveSink(rtc::VideoSinkInterface* sink) { - rtc::CritScope lock(&crit_); - RTC_CHECK(sink_ == sink); - sink_ = nullptr; -} - void VcmCapturer::Destroy() { if (!vcm_) return; @@ -103,8 +93,8 @@ VcmCapturer::~VcmCapturer() { Destroy(); } void VcmCapturer::OnIncomingCapturedFrame(const int32_t id, const VideoFrame& frame) { rtc::CritScope lock(&crit_); - if (started_ && sink_) - sink_->OnFrame(frame); + if (started_) + input_->IncomingCapturedFrame(frame); } void VcmCapturer::OnCaptureDelayChanged(const int32_t id, const int32_t delay) { diff --git a/webrtc/test/vcm_capturer.h b/webrtc/test/vcm_capturer.h index a6c4b5ca37..65916ec52e 100644 --- a/webrtc/test/vcm_capturer.h +++ b/webrtc/test/vcm_capturer.h @@ -22,31 +22,29 @@ namespace test { class VcmCapturer : public VideoCapturer, public VideoCaptureDataCallback { public: - static VcmCapturer* Create(size_t width, size_t height, size_t target_fps); + static VcmCapturer* Create(VideoCaptureInput* input, + size_t width, + size_t height, + size_t target_fps); virtual ~VcmCapturer(); void Start() override; void Stop() override; - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override; - void RemoveSink(rtc::VideoSinkInterface* sink) override; void OnIncomingCapturedFrame(const int32_t id, const VideoFrame& frame) override; // NOLINT void OnCaptureDelayChanged(const int32_t id, const int32_t delay) override; private: - VcmCapturer(); + explicit VcmCapturer(VideoCaptureInput* input); bool Init(size_t width, size_t height, size_t target_fps); void Destroy(); rtc::CriticalSection crit_; bool started_ GUARDED_BY(crit_); - rtc::VideoSinkInterface* sink_ GUARDED_BY(crit_); rtc::scoped_refptr vcm_; VideoCaptureCapability capability_; }; - } // test } // webrtc diff --git a/webrtc/test/video_capturer.cc b/webrtc/test/video_capturer.cc new file mode 100644 index 0000000000..840378f013 --- /dev/null +++ b/webrtc/test/video_capturer.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/test/video_capturer.h" + +#include "webrtc/test/testsupport/fileutils.h" +#include "webrtc/test/frame_generator_capturer.h" +#include "webrtc/test/vcm_capturer.h" + +namespace webrtc { +namespace test { + +class NullCapturer : public VideoCapturer { + public: + NullCapturer() : VideoCapturer(NULL) {} + virtual ~NullCapturer() {} + + virtual void Start() {} + virtual void Stop() {} +}; + +VideoCapturer::VideoCapturer(VideoCaptureInput* input) : input_(input) { +} + +VideoCapturer* VideoCapturer::Create(VideoCaptureInput* input, + size_t width, + size_t height, + int fps, + Clock* clock) { + VcmCapturer* vcm_capturer = VcmCapturer::Create(input, width, height, fps); + + if (vcm_capturer != NULL) { + return vcm_capturer; + } + // TODO(pbos): Log a warning that this failed. + + FrameGeneratorCapturer* frame_generator_capturer = + FrameGeneratorCapturer::Create(input, width, height, fps, clock); + if (frame_generator_capturer != NULL) { + return frame_generator_capturer; + } + // TODO(pbos): Log a warning that this failed. + + return new NullCapturer(); +} +} // test +} // webrtc diff --git a/webrtc/test/video_capturer.h b/webrtc/test/video_capturer.h index 9b761eb2a5..169fd7151d 100644 --- a/webrtc/test/video_capturer.h +++ b/webrtc/test/video_capturer.h @@ -12,21 +12,29 @@ #include -#include "webrtc/media/base/videosourceinterface.h" -#include "webrtc/video_frame.h" - namespace webrtc { class Clock; +class VideoCaptureInput; + namespace test { -class VideoCapturer : public rtc::VideoSourceInterface { +class VideoCapturer { public: + static VideoCapturer* Create(VideoCaptureInput* input, + size_t width, + size_t height, + int fps, + Clock* clock); virtual ~VideoCapturer() {} virtual void Start() = 0; virtual void Stop() = 0; + + protected: + explicit VideoCapturer(VideoCaptureInput* input); + VideoCaptureInput* input_; }; } // test } // webrtc diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc index 2f7b7463a0..55d5cc073d 100644 --- a/webrtc/video/end_to_end_tests.cc +++ b/webrtc/video/end_to_end_tests.cc @@ -214,10 +214,8 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) { // check that the callbacks are done after processing video. std::unique_ptr frame_generator( test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight)); - test::FrameForwarder frame_forwarder; - video_send_stream_->SetSource(&frame_forwarder); - - frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame()); + video_send_stream_->Input()->IncomingCapturedFrame( + *frame_generator->NextFrame()); EXPECT_TRUE(pre_render_callback.Wait()) << "Timed out while waiting for pre-render callback."; EXPECT_TRUE(renderer.Wait()) @@ -261,9 +259,8 @@ TEST_F(EndToEndTest, TransmitsFirstFrame) { test::FrameGenerator::CreateChromaGenerator( video_encoder_config_.streams[0].width, video_encoder_config_.streams[0].height)); - test::FrameForwarder frame_forwarder; - video_send_stream_->SetSource(&frame_forwarder); - frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame()); + video_send_stream_->Input()->IncomingCapturedFrame( + *frame_generator->NextFrame()); EXPECT_TRUE(renderer.Wait()) << "Timed out while waiting for the frame to render."; @@ -1307,8 +1304,8 @@ class MultiStreamTest { receive_streams[i]->Start(); frame_generators[i] = test::FrameGeneratorCapturer::Create( - width, height, 30, Clock::GetRealTimeClock()); - send_streams[i]->SetSource(frame_generators[i]); + send_streams[i]->Input(), width, height, 30, + Clock::GetRealTimeClock()); frame_generators[i]->Start(); } @@ -1768,9 +1765,8 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) { test::FrameGenerator::CreateChromaGenerator( video_encoder_config_.streams[0].width, video_encoder_config_.streams[0].height)); - test::FrameForwarder forwarder; - video_send_stream_->SetSource(&forwarder); - forwarder.IncomingCapturedFrame(*frame_generator->NextFrame()); + video_send_stream_->Input()->IncomingCapturedFrame( + *frame_generator->NextFrame()); EXPECT_TRUE(post_encode_observer.Wait()) << "Timed out while waiting for send-side encoded-frame callback."; diff --git a/webrtc/video/video_quality_test.cc b/webrtc/video/video_quality_test.cc index c606c86c18..aa1c9b1728 100644 --- a/webrtc/video/video_quality_test.cc +++ b/webrtc/video/video_quality_test.cc @@ -7,9 +7,8 @@ * 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_quality_test.h" - #include + #include #include #include @@ -18,6 +17,7 @@ #include #include "testing/gtest/include/gtest/gtest.h" + #include "webrtc/base/checks.h" #include "webrtc/base/event.h" #include "webrtc/base/format_macros.h" @@ -32,8 +32,8 @@ #include "webrtc/test/run_loop.h" #include "webrtc/test/statistics.h" #include "webrtc/test/testsupport/fileutils.h" -#include "webrtc/test/vcm_capturer.h" #include "webrtc/test/video_renderer.h" +#include "webrtc/video/video_quality_test.h" #include "webrtc/voice_engine/include/voe_base.h" #include "webrtc/voice_engine/include/voe_codec.h" @@ -99,6 +99,7 @@ namespace webrtc { class VideoAnalyzer : public PacketReceiver, public Transport, public rtc::VideoSinkInterface, + public VideoCaptureInput, public EncodedFrameObserver { public: VideoAnalyzer(test::LayerFilteringTransport* transport, @@ -109,10 +110,10 @@ class VideoAnalyzer : public PacketReceiver, FILE* graph_data_output_file, const std::string& graph_title, uint32_t ssrc_to_analyze) - : transport_(transport), + : input_(nullptr), + transport_(transport), receiver_(nullptr), send_stream_(nullptr), - captured_frame_forwarder_(this), test_label_(test_label), graph_data_output_file_(graph_data_output_file), graph_title_(graph_title), @@ -168,19 +169,6 @@ class VideoAnalyzer : public PacketReceiver, virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } - void SetSendStream(VideoSendStream* stream) { - rtc::CritScope lock(&crit_); - RTC_DCHECK(!send_stream_); - send_stream_ = stream; - } - - rtc::VideoSinkInterface* InputInterface() { - return &captured_frame_forwarder_; - } - rtc::VideoSourceInterface* OutputInterface() { - return &captured_frame_forwarder_; - } - DeliveryStatus DeliverPacket(MediaType media_type, const uint8_t* packet, size_t length, @@ -210,6 +198,17 @@ class VideoAnalyzer : public PacketReceiver, samples_encode_time_ms_[ntp_time_ms] = encode_time_ms; } + void IncomingCapturedFrame(const VideoFrame& video_frame) override { + VideoFrame copy = video_frame; + copy.set_timestamp(copy.ntp_time_ms() * 90); + { + rtc::CritScope lock(&crit_); + frames_.push_back(copy); + } + + input_->IncomingCapturedFrame(video_frame); + } + void PreEncodeOnFrame(const VideoFrame& video_frame) { rtc::CritScope lock(&crit_); if (!first_send_timestamp_ && rtp_timestamp_delta_ == 0) { @@ -347,8 +346,10 @@ class VideoAnalyzer : public PacketReceiver, } EncodedFrameObserver* encode_timing_proxy() { return &encode_timing_proxy_; } + VideoCaptureInput* input_; test::LayerFilteringTransport* const transport_; PacketReceiver* receiver_; + VideoSendStream* send_stream_; private: struct FrameComparison { @@ -696,55 +697,6 @@ class VideoAnalyzer : public PacketReceiver, } } - // Implements VideoSinkInterface to receive captured frames from a - // FrameGeneratorCapturer. Implements VideoSourceInterface to be able to act - // as a source to VideoSendStream. - // It forwards all input frames to the VideoAnalyzer for later comparison and - // forwards the captured frames to the VideoSendStream. - class CapturedFrameForwarder : public rtc::VideoSinkInterface, - public rtc::VideoSourceInterface { - public: - explicit CapturedFrameForwarder(VideoAnalyzer* analyzer) - : analyzer_(analyzer), send_stream_input_(nullptr) {} - - private: - void OnFrame(const VideoFrame& video_frame) override { - VideoFrame copy = video_frame; - copy.set_timestamp(copy.ntp_time_ms() * 90); - - analyzer_->AddCapturedFrameForComparison(video_frame); - rtc::CritScope lock(&crit_); - if (send_stream_input_) - send_stream_input_->OnFrame(video_frame); - } - - // Called when |send_stream_.SetSource()| is called. - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override { - rtc::CritScope lock(&crit_); - RTC_DCHECK(!send_stream_input_ || send_stream_input_ == sink); - send_stream_input_ = sink; - } - - // Called by |send_stream_| when |send_stream_.SetSource()| is called. - void RemoveSink(rtc::VideoSinkInterface* sink) override { - rtc::CritScope lock(&crit_); - RTC_DCHECK(sink == send_stream_input_); - send_stream_input_ = nullptr; - } - - VideoAnalyzer* const analyzer_; - rtc::CriticalSection crit_; - rtc::VideoSinkInterface* send_stream_input_ GUARDED_BY(crit_); - }; - - void AddCapturedFrameForComparison(const VideoFrame& video_frame) { - rtc::CritScope lock(&crit_); - frames_.push_back(video_frame); - } - - VideoSendStream* send_stream_; - CapturedFrameForwarder captured_frame_forwarder_; const std::string test_label_; FILE* const graph_data_output_file_; const std::string graph_title_; @@ -1076,20 +1028,21 @@ void VideoQualityTest::SetupScreenshare() { } } -void VideoQualityTest::CreateCapturer() { +void VideoQualityTest::CreateCapturer(VideoCaptureInput* input) { if (params_.screenshare.enabled) { test::FrameGeneratorCapturer* frame_generator_capturer = - new test::FrameGeneratorCapturer(clock_, frame_generator_.release(), - params_.common.fps); + new test::FrameGeneratorCapturer( + clock_, input, frame_generator_.release(), params_.common.fps); EXPECT_TRUE(frame_generator_capturer->Init()); capturer_.reset(frame_generator_capturer); } else { if (params_.video.clip_name.empty()) { - capturer_.reset(test::VcmCapturer::Create( - params_.common.width, params_.common.height, params_.common.fps)); + capturer_.reset(test::VideoCapturer::Create(input, params_.common.width, + params_.common.height, + params_.common.fps, clock_)); } else { capturer_.reset(test::FrameGeneratorCapturer::CreateFromYuvFile( - test::ResourcePath(params_.video.clip_name, "yuv"), + input, test::ResourcePath(params_.video.clip_name, "yuv"), params_.common.width, params_.common.height, params_.common.fps, clock_)); ASSERT_TRUE(capturer_) << "Could not create capturer for " @@ -1174,12 +1127,10 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) { SetupScreenshare(); CreateVideoStreams(); - analyzer.SetSendStream(video_send_stream_); - video_send_stream_->SetSource(analyzer.OutputInterface()); + analyzer.input_ = video_send_stream_->Input(); + analyzer.send_stream_ = video_send_stream_; - CreateCapturer(); - rtc::VideoSinkWants wants; - capturer_->AddOrUpdateSink(analyzer.InputInterface(), wants); + CreateCapturer(&analyzer); video_send_stream_->Start(); for (VideoReceiveStream* receive_stream : video_receive_streams_) @@ -1271,8 +1222,7 @@ void VideoQualityTest::RunWithRenderers(const Params& params) { video_send_config_.Copy(), video_encoder_config_.Copy()); VideoReceiveStream* video_receive_stream = call->CreateVideoReceiveStream(video_receive_configs_[stream_id].Copy()); - CreateCapturer(); - video_send_stream_->SetSource(capturer_.get()); + CreateCapturer(video_send_stream_->Input()); AudioReceiveStream* audio_receive_stream = nullptr; if (params_.audio) { diff --git a/webrtc/video/video_quality_test.h b/webrtc/video/video_quality_test.h index e29bf80d94..e5c85aa231 100644 --- a/webrtc/video/video_quality_test.h +++ b/webrtc/video/video_quality_test.h @@ -103,7 +103,7 @@ class VideoQualityTest : public test::CallTest { static std::vector ParseCSV(const std::string& str); // Helper methods for setting up the call. - void CreateCapturer(); + void CreateCapturer(VideoCaptureInput* input); void SetupCommon(Transport* send_transport, Transport* recv_transport); void SetupScreenshare(); diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc index e9654dd293..2f8241e28e 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -545,10 +545,12 @@ void VideoSendStream::Stop() { worker_queue_->PostTask([send_stream] { send_stream->Stop(); }); } -void VideoSendStream::SetSource( - rtc::VideoSourceInterface* source) { - RTC_DCHECK_RUN_ON(&thread_checker_); - vie_encoder_->SetSource(source); +VideoCaptureInput* VideoSendStream::Input() { + // Input() will be called on the thread that deliverers video frames from + // libjingle. + // TODO(perkj): Refactor ViEEncoder to register directly as a VideoSink to the + // VideoSource. + return vie_encoder_.get(); } void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) { diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h index dd5081d0d2..932264265d 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -71,10 +71,7 @@ class VideoSendStream : public webrtc::VideoSendStream { // webrtc::VideoSendStream implementation. void Start() override; void Stop() override; - - void SetSource( - rtc::VideoSourceInterface* source) override; - + VideoCaptureInput* Input() override; void ReconfigureVideoEncoder(VideoEncoderConfig) override; Stats GetStats() override; diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc index ba15b17c85..8129af9ab2 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -33,7 +33,6 @@ #include "webrtc/test/call_test.h" #include "webrtc/test/configurable_frame_size_encoder.h" #include "webrtc/test/fake_texture_frame.h" -#include "webrtc/test/frame_generator.h" #include "webrtc/test/frame_utils.h" #include "webrtc/test/null_transport.h" #include "webrtc/test/testsupport/perf_test.h" @@ -1474,10 +1473,8 @@ TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) { handle3, width, height, 5, 5, kVideoRotation_0)); video_send_stream_->Start(); - test::FrameForwarder forwarder; - video_send_stream_->SetSource(&forwarder); for (size_t i = 0; i < input_frames.size(); i++) { - forwarder.IncomingCapturedFrame(input_frames[i]); + video_send_stream_->Input()->IncomingCapturedFrame(input_frames[i]); // Do not send the next frame too fast, so the frame dropper won't drop it. if (i < input_frames.size() - 1) SleepMs(1000 / video_encoder_config_.streams[0].max_framerate); @@ -1486,7 +1483,6 @@ TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) { observer.WaitOutputFrame(); } video_send_stream_->Stop(); - video_send_stream_->SetSource(nullptr); // Test if the input and output frames are the same. render_time_ms and // timestamp are not compared because capturer sets those values. diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc index cd6d88dafc..74e1bc02e8 100644 --- a/webrtc/video/vie_encoder.cc +++ b/webrtc/video/vie_encoder.cc @@ -241,47 +241,6 @@ 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* source) { - RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_); - rtc::VideoSourceInterface* 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* 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, @@ -290,7 +249,6 @@ 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), @@ -330,27 +288,23 @@ 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() { - 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); + 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(); } 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_); @@ -358,15 +312,9 @@ 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* 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_); @@ -436,7 +384,7 @@ void ViEEncoder::ConfigureEncoderInternal(const VideoCodec& video_codec, } } -void ViEEncoder::OnFrame(const VideoFrame& video_frame) { +void ViEEncoder::IncomingCapturedFrame(const VideoFrame& video_frame) { RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_); stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height()); diff --git a/webrtc/video/vie_encoder.h b/webrtc/video/vie_encoder.h index eaf2536dab..1b524e5bb9 100644 --- a/webrtc/video/vie_encoder.h +++ b/webrtc/video/vie_encoder.h @@ -40,11 +40,11 @@ class SendStatisticsProxy; // and produces an encoded bit stream. // Usage: // Instantiate. -// Call SetSink. -// Call SetSource. +// Call SetStartRate and SetSink. // Call ConfigureEncoder with the codec settings. +// Provide frames to encode by calling IncomingCapturedFrame. // Call Stop() when done. -class ViEEncoder : public rtc::VideoSinkInterface, +class ViEEncoder : public VideoCaptureInput, public EncodedImageCallback, public VCMSendStatisticsCallback, public CpuOveruseObserver { @@ -63,7 +63,6 @@ class ViEEncoder : public rtc::VideoSinkInterface, void RegisterProcessThread(ProcessThread* module_process_thread); void DeRegisterProcessThread(); - void SetSource(rtc::VideoSourceInterface* source); void SetSink(EncodedImageCallback* sink); // TODO(perkj): Can we remove VideoCodec.startBitrate ? @@ -76,6 +75,11 @@ class ViEEncoder : public rtc::VideoSinkInterface, // guaranteed that no encoded frames will be delivered to the sink. void Stop(); + // Implements VideoCaptureInput. + // TODO(perkj): Refactor ViEEncoder to inherit rtc::VideoSink instead of + // VideoCaptureInput. + void IncomingCapturedFrame(const VideoFrame& video_frame) override; + void SendKeyFrame(); // virtual to test EncoderStateFeedback with mocks. @@ -89,14 +93,10 @@ class ViEEncoder : public rtc::VideoSinkInterface, private: class EncodeTask; - class VideoSourceProxy; void ConfigureEncoderInternal(const VideoCodec& video_codec, size_t max_data_payload_length); - // Implements VideoSinkInterface. - void OnFrame(const VideoFrame& video_frame) override; - // Implements VideoSendStatisticsCallback. void SendStatistics(uint32_t bit_rate, uint32_t frame_rate) override; @@ -121,8 +121,6 @@ class ViEEncoder : public rtc::VideoSinkInterface, rtc::Event shutdown_event_; const uint32_t number_of_cores_; - - const std::unique_ptr source_proxy_; EncodedImageCallback* sink_; const VideoSendStream::Config::EncoderSettings settings_; @@ -136,9 +134,6 @@ class ViEEncoder : public rtc::VideoSinkInterface, rtc::VideoSinkInterface* const pre_encode_callback_; ProcessThread* module_process_thread_; rtc::ThreadChecker module_process_thread_checker_; - // |thread_checker_| checks that public methods that are related to lifetime - // of ViEEncoder are called on the same thread. - rtc::ThreadChecker thread_checker_; VideoCodec encoder_config_ ACCESS_ON(&encoder_queue_); @@ -165,8 +160,6 @@ class ViEEncoder : public rtc::VideoSinkInterface, // All public methods are proxied to |encoder_queue_|. It must must be // destroyed first to make sure no tasks are run that use other members. rtc::TaskQueue encoder_queue_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ViEEncoder); }; } // namespace webrtc diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc index ba25a1da4d..698dd3a540 100644 --- a/webrtc/video/vie_encoder_unittest.cc +++ b/webrtc/video/vie_encoder_unittest.cc @@ -12,7 +12,6 @@ #include "webrtc/base/logging.h" #include "webrtc/test/encoder_settings.h" #include "webrtc/test/fake_encoder.h" -#include "webrtc/test/frame_generator.h" #include "webrtc/video/send_statistics_proxy.h" #include "webrtc/video/vie_encoder.h" @@ -43,7 +42,6 @@ class ViEEncoderTest : public ::testing::Test { video_send_config_.encoder_settings, nullptr /* pre_encode_callback */, nullptr /* overuse_callback */, nullptr /* encoder_timing */)); vie_encoder_->SetSink(&sink_); - vie_encoder_->SetSource(&video_source_); vie_encoder_->SetStartBitrate(10000); vie_encoder_->ConfigureEncoder(video_encoder_config_, 1440); } @@ -97,7 +95,7 @@ class ViEEncoderTest : public ::testing::Test { int32_t result = FakeEncoder::Encode(input_image, codec_specific_info, frame_types); if (block_encode) - EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs)); + continue_encode_event_.Wait(kDefaultTimeoutMs); return result; } @@ -140,7 +138,7 @@ class ViEEncoderTest : public ::testing::Test { void WaitForEncodedFrame(int64_t expected_ntp_time) { uint32_t timestamp = 0; - EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs)); + encoded_frame_event_.Wait(kDefaultTimeoutMs); { rtc::CritScope lock(&crit_); timestamp = timestamp_; @@ -166,7 +164,6 @@ class ViEEncoderTest : public ::testing::Test { TestEncoder fake_encoder_; SendStatisticsProxy stats_proxy_; TestSink sink_; - test::FrameForwarder video_source_; std::unique_ptr vie_encoder_; }; @@ -174,22 +171,22 @@ TEST_F(ViEEncoderTest, EncodeOneFrame) { const int kTargetBitrateBps = 100000; vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); rtc::Event frame_destroyed_event(false, false); - video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); sink_.WaitForEncodedFrame(1); - EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs)); + frame_destroyed_event.Wait(kDefaultTimeoutMs); vie_encoder_->Stop(); } TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) { // Dropped since no target bitrate has been set. rtc::Event frame_destroyed_event(false, false); - video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); - EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); + frame_destroyed_event.Wait(kDefaultTimeoutMs); const int kTargetBitrateBps = 100000; vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); - video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); sink_.WaitForEncodedFrame(2); vie_encoder_->Stop(); } @@ -197,15 +194,15 @@ TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) { TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) { const int kTargetBitrateBps = 100000; vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); - video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); sink_.WaitForEncodedFrame(1); vie_encoder_->OnBitrateUpdated(0, 0, 0); // Dropped since bitrate is zero. - video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); - video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(3, nullptr)); sink_.WaitForEncodedFrame(3); vie_encoder_->Stop(); } @@ -213,13 +210,13 @@ TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) { TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) { const int kTargetBitrateBps = 100000; vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); - video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); sink_.WaitForEncodedFrame(1); // This frame will be dropped since it has the same ntp timestamp. - video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); - video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); sink_.WaitForEncodedFrame(2); vie_encoder_->Stop(); } @@ -228,14 +225,14 @@ TEST_F(ViEEncoderTest, DropsFrameAfterStop) { const int kTargetBitrateBps = 100000; vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); - video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); sink_.WaitForEncodedFrame(1); vie_encoder_->Stop(); sink_.SetExpectNoFrames(); rtc::Event frame_destroyed_event(false, false); - video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event)); - EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event)); + frame_destroyed_event.Wait(kDefaultTimeoutMs); } TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) { @@ -243,12 +240,12 @@ TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) { vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); fake_encoder_.BlockNextEncode(); - video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); sink_.WaitForEncodedFrame(1); // Here, the encoder thread will be blocked in the TestEncoder waiting for a // call to ContinueEncode. - video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr)); - video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); + vie_encoder_->IncomingCapturedFrame(CreateFrame(3, nullptr)); fake_encoder_.ContinueEncode(); sink_.WaitForEncodedFrame(3); diff --git a/webrtc/video_send_stream.h b/webrtc/video_send_stream.h index 2948d46874..afdec43c74 100644 --- a/webrtc/video_send_stream.h +++ b/webrtc/video_send_stream.h @@ -19,7 +19,6 @@ #include "webrtc/common_video/include/frame_callback.h" #include "webrtc/config.h" #include "webrtc/media/base/videosinkinterface.h" -#include "webrtc/media/base/videosourceinterface.h" #include "webrtc/transport.h" namespace webrtc { @@ -27,6 +26,18 @@ namespace webrtc { class LoadObserver; class VideoEncoder; +// Class to deliver captured frame to the video send stream. +class VideoCaptureInput { + public: + // These methods do not lock internally and must be called sequentially. + // If your application switches input sources synchronization must be done + // externally to make sure that any old frames are not delivered concurrently. + virtual void IncomingCapturedFrame(const VideoFrame& video_frame) = 0; + + protected: + virtual ~VideoCaptureInput() {} +}; + class VideoSendStream { public: struct StreamStats { @@ -182,8 +193,9 @@ class VideoSendStream { // When a stream is stopped, it can't receive, process or deliver packets. virtual void Stop() = 0; - virtual void SetSource( - rtc::VideoSourceInterface* source) = 0; + // Gets interface used to insert captured frames. Valid as long as the + // VideoSendStream is valid. + virtual VideoCaptureInput* Input() = 0; // Set which streams to send. Must have at least as many SSRCs as configured // in the config. Encoder settings are passed on to the encoder instance along