From a50924115e47f052a61dc146e350b0677cd2ebd9 Mon Sep 17 00:00:00 2001 From: Per Date: Fri, 12 Feb 2016 13:30:57 +0100 Subject: [PATCH] This reland https://codereview.webrtc.org/1655793003/ with the change that cricket::VideoCapturer::SignalVideoFrame is added back and used for frame forwarding. It is used in Chrome remoting. BUG=webrtc:5426 R=pthatcher@webrtc.org TBR=pthatcher@webrtc.org for moved channelmanager.... Review URL: https://codereview.webrtc.org/1689923002 . Cr-Commit-Position: refs/heads/master@{#11597} --- webrtc/api/androidvideocapturer.cc | 5 +- webrtc/api/remotevideocapturer_unittest.cc | 18 ---- webrtc/media/base/capturemanager.cc | 56 ++-------- webrtc/media/base/capturemanager.h | 7 +- webrtc/media/base/capturerenderadapter.cc | 74 +------------ webrtc/media/base/capturerenderadapter.h | 49 +-------- webrtc/media/base/fakevideorenderer.h | 6 ++ webrtc/media/base/videobroadcaster.cc | 70 +++++++++++- webrtc/media/base/videobroadcaster.h | 46 +++++++- webrtc/media/base/videocapturer.cc | 40 ++++--- webrtc/media/base/videocapturer.h | 40 ++++--- webrtc/media/base/videocapturer_unittest.cc | 113 +++++++++++--------- webrtc/media/base/videoengine_unittest.h | 15 --- webrtc/media/base/videosinkinterface.h | 3 +- webrtc/media/base/videosourceinterface.h | 46 ++++++++ webrtc/media/engine/webrtcvideocapturer.cc | 19 ++-- webrtc/media/engine/webrtcvideocapturer.h | 19 ++-- webrtc/media/engine/webrtcvideoengine2.cc | 48 ++++----- webrtc/media/engine/webrtcvideoengine2.h | 10 +- webrtc/media/media.gyp | 4 +- webrtc/pc/channelmanager.cc | 1 - webrtc/pc/channelmanager.h | 1 - 22 files changed, 347 insertions(+), 343 deletions(-) create mode 100644 webrtc/media/base/videosourceinterface.h diff --git a/webrtc/api/androidvideocapturer.cc b/webrtc/api/androidvideocapturer.cc index 4311fd7a2e..0814dae376 100644 --- a/webrtc/api/androidvideocapturer.cc +++ b/webrtc/api/androidvideocapturer.cc @@ -27,7 +27,8 @@ namespace webrtc { // for ref counted I420 frames instead of this hack. class AndroidVideoCapturer::FrameFactory : public cricket::VideoFrameFactory { public: - FrameFactory(const rtc::scoped_refptr& delegate) + explicit FrameFactory( + const rtc::scoped_refptr& delegate) : delegate_(delegate) { // Create a CapturedFrame that only contains header information, not the // actual pixel data. @@ -141,8 +142,6 @@ AndroidVideoCapturer::AndroidVideoCapturer( formats.push_back(format); } SetSupportedFormats(formats); - // Do not apply frame rotation by default. - SetApplyRotation(false); } AndroidVideoCapturer::~AndroidVideoCapturer() { diff --git a/webrtc/api/remotevideocapturer_unittest.cc b/webrtc/api/remotevideocapturer_unittest.cc index c31272c4d6..6478d214c4 100644 --- a/webrtc/api/remotevideocapturer_unittest.cc +++ b/webrtc/api/remotevideocapturer_unittest.cc @@ -34,13 +34,10 @@ class RemoteVideoCapturerTest : public testing::Test, virtual void SetUp() { capturer_.SignalStateChange.connect( this, &RemoteVideoCapturerTest::OnStateChange); - capturer_.SignalVideoFrame.connect( - this, &RemoteVideoCapturerTest::OnVideoFrame); } ~RemoteVideoCapturerTest() { capturer_.SignalStateChange.disconnect(this); - capturer_.SignalVideoFrame.disconnect(this); } int captured_frame_num() const { @@ -60,11 +57,6 @@ class RemoteVideoCapturerTest : public testing::Test, capture_state_ = capture_state; } - void OnVideoFrame(VideoCapturer* capturer, const VideoFrame* frame) { - EXPECT_EQ(&capturer_, capturer); - ++captured_frame_num_; - } - int captured_frame_num_; CaptureState capture_state_; }; @@ -103,13 +95,3 @@ TEST_F(RemoteVideoCapturerTest, GetBestCaptureFormat) { EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best_format)); EXPECT_EQ(expected_format, best_format); } - -TEST_F(RemoteVideoCapturerTest, InputFrame) { - EXPECT_EQ(0, captured_frame_num()); - - cricket::WebRtcVideoFrame test_frame; - capturer_.SignalVideoFrame(&capturer_, &test_frame); - EXPECT_EQ(1, captured_frame_num()); - capturer_.SignalVideoFrame(&capturer_, &test_frame); - EXPECT_EQ(2, captured_frame_num()); -} diff --git a/webrtc/media/base/capturemanager.cc b/webrtc/media/base/capturemanager.cc index 689b6d7620..3628fb306d 100644 --- a/webrtc/media/base/capturemanager.cc +++ b/webrtc/media/base/capturemanager.cc @@ -23,7 +23,7 @@ class VideoCapturerState { public: static const VideoFormatPod kDefaultCaptureFormat; - static VideoCapturerState* Create(VideoCapturer* video_capturer); + explicit VideoCapturerState(VideoCapturer* capturer); ~VideoCapturerState() {} void AddCaptureResolution(const VideoFormat& desired_format); @@ -32,13 +32,9 @@ class VideoCapturerState { int IncCaptureStartRef(); int DecCaptureStartRef(); - CaptureRenderAdapter* adapter() { - RTC_DCHECK(thread_checker_.CalledOnValidThread()); - return adapter_.get(); - } VideoCapturer* GetVideoCapturer() { RTC_DCHECK(thread_checker_.CalledOnValidThread()); - return adapter()->video_capturer(); + return video_capturer_; } int start_count() const { @@ -53,11 +49,9 @@ class VideoCapturerState { }; typedef std::vector CaptureFormats; - explicit VideoCapturerState(CaptureRenderAdapter* adapter); - rtc::ThreadChecker thread_checker_; - rtc::scoped_ptr adapter_; + VideoCapturer* video_capturer_; int start_count_; CaptureFormats capture_formats_; }; @@ -66,17 +60,8 @@ const VideoFormatPod VideoCapturerState::kDefaultCaptureFormat = { 640, 360, FPS_TO_INTERVAL(30), FOURCC_ANY }; -VideoCapturerState::VideoCapturerState(CaptureRenderAdapter* adapter) - : adapter_(adapter), start_count_(1) {} - -// static -VideoCapturerState* VideoCapturerState::Create(VideoCapturer* video_capturer) { - CaptureRenderAdapter* adapter = CaptureRenderAdapter::Create(video_capturer); - if (!adapter) { - return NULL; - } - return new VideoCapturerState(adapter); -} +VideoCapturerState::VideoCapturerState(VideoCapturer* capturer) + : video_capturer_(capturer), start_count_(1) {} void VideoCapturerState::AddCaptureResolution( const VideoFormat& desired_format) { @@ -276,11 +261,10 @@ void CaptureManager::AddVideoSink(VideoCapturer* video_capturer, if (!video_capturer || !sink) { return; } - CaptureRenderAdapter* adapter = GetAdapter(video_capturer); - if (!adapter) { - return; - } - adapter->AddSink(sink); + rtc::VideoSinkWants wants; + // Renderers must be able to apply rotation. + wants.rotation_applied = false; + video_capturer->AddOrUpdateSink(sink, wants); } void CaptureManager::RemoveVideoSink( @@ -290,11 +274,7 @@ void CaptureManager::RemoveVideoSink( if (!video_capturer || !sink) { return; } - CaptureRenderAdapter* adapter = GetAdapter(video_capturer); - if (!adapter) { - return; - } - adapter->RemoveSink(sink); + video_capturer->RemoveSink(sink); } bool CaptureManager::IsCapturerRegistered(VideoCapturer* video_capturer) const { @@ -304,11 +284,7 @@ bool CaptureManager::IsCapturerRegistered(VideoCapturer* video_capturer) const { bool CaptureManager::RegisterVideoCapturer(VideoCapturer* video_capturer) { RTC_DCHECK(thread_checker_.CalledOnValidThread()); - VideoCapturerState* capture_state = - VideoCapturerState::Create(video_capturer); - if (!capture_state) { - return false; - } + VideoCapturerState* capture_state = new VideoCapturerState(video_capturer); capture_states_[video_capturer] = capture_state; SignalCapturerStateChange.repeat(video_capturer->SignalStateChange); return true; @@ -376,14 +352,4 @@ VideoCapturerState* CaptureManager::GetCaptureState( return iter->second; } -CaptureRenderAdapter* CaptureManager::GetAdapter( - VideoCapturer* video_capturer) const { - RTC_DCHECK(thread_checker_.CalledOnValidThread()); - VideoCapturerState* capture_state = GetCaptureState(video_capturer); - if (!capture_state) { - return NULL; - } - return capture_state->adapter(); -} - } // namespace cricket diff --git a/webrtc/media/base/capturemanager.h b/webrtc/media/base/capturemanager.h index c4f1f69fae..93f8e18610 100644 --- a/webrtc/media/base/capturemanager.h +++ b/webrtc/media/base/capturemanager.h @@ -29,13 +29,13 @@ #include "webrtc/base/sigslotrepeater.h" #include "webrtc/base/thread_checker.h" -#include "webrtc/media/base/capturerenderadapter.h" #include "webrtc/media/base/videocommon.h" +#include "webrtc/media/base/videocapturer.h" +#include "webrtc/media/base/videosinkinterface.h" namespace cricket { -class VideoCapturer; -class VideoRenderer; +class VideoFrame; class VideoCapturerState; class CaptureManager : public sigslot::has_slots<> { @@ -80,7 +80,6 @@ class CaptureManager : public sigslot::has_slots<> { VideoCapturer* video_capturer); VideoCapturerState* GetCaptureState(VideoCapturer* video_capturer) const; - CaptureRenderAdapter* GetAdapter(VideoCapturer* video_capturer) const; rtc::ThreadChecker thread_checker_; CaptureStates capture_states_; diff --git a/webrtc/media/base/capturerenderadapter.cc b/webrtc/media/base/capturerenderadapter.cc index f8d28f792f..4eb738b0db 100644 --- a/webrtc/media/base/capturerenderadapter.cc +++ b/webrtc/media/base/capturerenderadapter.cc @@ -8,76 +8,4 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/media/base/capturerenderadapter.h" - -#include "webrtc/base/logging.h" -#include "webrtc/media/base/videocapturer.h" -#include "webrtc/media/base/videorenderer.h" - -namespace cricket { - -CaptureRenderAdapter::CaptureRenderAdapter(VideoCapturer* video_capturer) - : video_capturer_(video_capturer) { -} - -CaptureRenderAdapter::~CaptureRenderAdapter() { - // Since the signal we're connecting to is multi-threaded, - // disconnect_all() will block until all calls are serviced, meaning any - // outstanding calls to OnVideoFrame will be done when this is done, and no - // more calls will be serviced by this. - // We do this explicitly instead of just letting the has_slots<> destructor - // take care of it because we need to do this *before* sinks_ is - // cleared by the destructor; otherwise we could mess with it while - // OnVideoFrame is running. - // We *don't* take capture_crit_ here since it could deadlock with the lock - // taken by the video frame signal. - disconnect_all(); -} - -CaptureRenderAdapter* CaptureRenderAdapter::Create( - VideoCapturer* video_capturer) { - if (!video_capturer) { - return NULL; - } - CaptureRenderAdapter* return_value = new CaptureRenderAdapter(video_capturer); - return_value->Init(); // Can't fail. - return return_value; -} - -void CaptureRenderAdapter::AddSink(rtc::VideoSinkInterface* sink) { - RTC_DCHECK(sink); - - rtc::CritScope cs(&capture_crit_); - // This implements set semantics, the same renderer can only be - // added once. - // TODO(nisse): Is this really needed? - if (std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end()) - sinks_.push_back(sink); -} - -void CaptureRenderAdapter::RemoveSink( - rtc::VideoSinkInterface* sink) { - RTC_DCHECK(sink); - - rtc::CritScope cs(&capture_crit_); - sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end()); -} - -void CaptureRenderAdapter::Init() { - video_capturer_->SignalVideoFrame.connect( - this, - &CaptureRenderAdapter::OnVideoFrame); -} - -void CaptureRenderAdapter::OnVideoFrame(VideoCapturer* capturer, - const VideoFrame* video_frame) { - rtc::CritScope cs(&capture_crit_); - if (sinks_.empty()) { - return; - } - - for (auto* sink : sinks_) - sink->OnFrame(*video_frame); -} - -} // namespace cricket +// TODO(perkj): Remove this dummy file once Chrome is not depending on it. diff --git a/webrtc/media/base/capturerenderadapter.h b/webrtc/media/base/capturerenderadapter.h index ea457688ef..4eb738b0db 100644 --- a/webrtc/media/base/capturerenderadapter.h +++ b/webrtc/media/base/capturerenderadapter.h @@ -8,51 +8,4 @@ * be found in the AUTHORS file in the root of the source tree. */ -// This file contains the class CaptureRenderAdapter. The class connects a -// VideoCapturer to any number of VideoRenders such that the former feeds the -// latter. -// CaptureRenderAdapter is Thread-unsafe. This means that none of its APIs may -// be called concurrently. - -#ifndef WEBRTC_MEDIA_BASE_CAPTURERENDERADAPTER_H_ -#define WEBRTC_MEDIA_BASE_CAPTURERENDERADAPTER_H_ - -#include - -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/media/base/videocapturer.h" -#include "webrtc/media/base/videosinkinterface.h" - -namespace cricket { - -class VideoCapturer; -class VideoProcessor; - -class CaptureRenderAdapter : public sigslot::has_slots<> { - public: - static CaptureRenderAdapter* Create(VideoCapturer* video_capturer); - ~CaptureRenderAdapter(); - - void AddSink(rtc::VideoSinkInterface* sink); - void RemoveSink(rtc::VideoSinkInterface* sink); - - VideoCapturer* video_capturer() { return video_capturer_; } - private: - - explicit CaptureRenderAdapter(VideoCapturer* video_capturer); - void Init(); - - // Callback for frames received from the capturer. - void OnVideoFrame(VideoCapturer* capturer, const VideoFrame* video_frame); - - // Just pointers since ownership is not handed over to this class. - std::vector*> sinks_; - VideoCapturer* video_capturer_; - // Critical section synchronizing the capture thread. - rtc::CriticalSection capture_crit_; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_CAPTURERENDERADAPTER_H_ +// TODO(perkj): Remove this dummy file once Chrome is not depending on it. diff --git a/webrtc/media/base/fakevideorenderer.h b/webrtc/media/base/fakevideorenderer.h index bc82cbaabf..0854d0ce39 100644 --- a/webrtc/media/base/fakevideorenderer.h +++ b/webrtc/media/base/fakevideorenderer.h @@ -43,6 +43,7 @@ class FakeVideoRenderer : public VideoRenderer { ++num_rendered_frames_; width_ = static_cast(frame->GetWidth()); height_ = static_cast(frame->GetHeight()); + rotation_ = frame->GetVideoRotation(); SignalRenderFrame(frame); return true; } @@ -56,6 +57,10 @@ class FakeVideoRenderer : public VideoRenderer { rtc::CritScope cs(&crit_); return height_; } + int rotation() const { + rtc::CritScope cs(&crit_); + return rotation_; + } int num_rendered_frames() const { rtc::CritScope cs(&crit_); return num_rendered_frames_; @@ -123,6 +128,7 @@ class FakeVideoRenderer : public VideoRenderer { int errors_; int width_; int height_; + webrtc::VideoRotation rotation_; int num_rendered_frames_; bool black_frame_; rtc::CriticalSection crit_; diff --git a/webrtc/media/base/videobroadcaster.cc b/webrtc/media/base/videobroadcaster.cc index a9f6eaee4c..e369ee07c6 100644 --- a/webrtc/media/base/videobroadcaster.cc +++ b/webrtc/media/base/videobroadcaster.cc @@ -10,5 +10,73 @@ #include "webrtc/media/base/videobroadcaster.h" -// TODO(perkj): Implement. +#include "webrtc/base/checks.h" +namespace rtc { + +VideoBroadcaster::VideoBroadcaster() { + thread_checker_.DetachFromThread(); +} + +void VideoBroadcaster::AddOrUpdateSink( + VideoSinkInterface* sink, + const VideoSinkWants& wants) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + RTC_DCHECK(sink != nullptr); + + SinkPair* sink_pair = FindSinkPair(sink); + if (!sink_pair) { + sinks_.push_back(SinkPair(sink, wants)); + } else { + sink_pair->wants = wants; + } + + // Rotation must be applied by the source if one sink wants it. + current_wants_.rotation_applied = false; + for (auto& sink_pair : sinks_) { + current_wants_.rotation_applied |= sink_pair.wants.rotation_applied; + } +} + +void VideoBroadcaster::RemoveSink( + VideoSinkInterface* sink) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + RTC_DCHECK(sink != nullptr); + RTC_DCHECK(FindSinkPair(sink)); + + sinks_.erase(std::remove_if(sinks_.begin(), sinks_.end(), + [sink](const SinkPair& sink_pair) { + return sink_pair.sink == sink; + }), + sinks_.end()); +} + +bool VideoBroadcaster::frame_wanted() const { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return !sinks_.empty(); +} + +VideoSinkWants VideoBroadcaster::wants() const { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return current_wants_; +} + +void VideoBroadcaster::OnFrame(const cricket::VideoFrame& frame) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + for (auto& sink_pair : sinks_) { + sink_pair.sink->OnFrame(frame); + } +} + +VideoBroadcaster::SinkPair* VideoBroadcaster::FindSinkPair( + const VideoSinkInterface* sink) { + auto sink_pair_it = std::find_if( + sinks_.begin(), sinks_.end(), + [sink](const SinkPair& sink_pair) { return sink_pair.sink == sink; }); + if (sink_pair_it != sinks_.end()) { + return &*sink_pair_it; + } + return nullptr; +} + +} // namespace rtc diff --git a/webrtc/media/base/videobroadcaster.h b/webrtc/media/base/videobroadcaster.h index f0009c92ac..63c22730c7 100644 --- a/webrtc/media/base/videobroadcaster.h +++ b/webrtc/media/base/videobroadcaster.h @@ -11,6 +11,50 @@ #ifndef WEBRTC_MEDIA_BASE_VIDEOBROADCASTER_H_ #define WEBRTC_MEDIA_BASE_VIDEOBROADCASTER_H_ -// TODO(perkj): Implement. +#include +#include + +#include "webrtc/base/thread_checker.h" +#include "webrtc/media/base/videoframe.h" +#include "webrtc/media/base/videosinkinterface.h" +#include "webrtc/media/base/videosourceinterface.h" + +namespace rtc { + +class VideoBroadcaster : public VideoSourceInterface, + public VideoSinkInterface { + public: + VideoBroadcaster(); + void AddOrUpdateSink(VideoSinkInterface* sink, + const VideoSinkWants& wants) override; + void RemoveSink(VideoSinkInterface* sink) override; + + // Returns true if the next frame will be delivered to at least one sink. + bool frame_wanted() const; + + // Returns VideoSinkWants a source is requested to fulfill. They are + // aggregated by all VideoSinkWants from all sinks. + VideoSinkWants wants() const; + + void OnFrame(const cricket::VideoFrame& frame) override; + + protected: + struct SinkPair { + SinkPair(VideoSinkInterface* sink, + VideoSinkWants wants) + : sink(sink), wants(wants) {} + VideoSinkInterface* sink; + VideoSinkWants wants; + }; + SinkPair* FindSinkPair(const VideoSinkInterface* sink); + + ThreadChecker thread_checker_; + + VideoSinkWants current_wants_; + + std::vector sinks_; +}; + +} // namespace rtc #endif // WEBRTC_MEDIA_BASE_VIDEOBROADCASTER_H_ diff --git a/webrtc/media/base/videocapturer.cc b/webrtc/media/base/videocapturer.cc index 5b0590480b..2d6a15e544 100644 --- a/webrtc/media/base/videocapturer.cc +++ b/webrtc/media/base/videocapturer.cc @@ -102,6 +102,10 @@ void VideoCapturer::Construct() { square_pixel_aspect_ratio_ = false; capture_state_ = CS_STOPPED; SignalFrameCaptured.connect(this, &VideoCapturer::OnFrameCaptured); + // TODO(perkj) SignalVideoFrame is used directly by Chrome remoting. + // Before that is refactored, SignalVideoFrame must forward frames to the + // |VideoBroadcaster|; + SignalVideoFrame.connect(this, &VideoCapturer::OnFrame); scaled_width_ = 0; scaled_height_ = 0; muted_ = false; @@ -226,16 +230,6 @@ bool VideoCapturer::MuteToBlackThenPause(bool muted) { return Pause(false); } -// Note that the last caller decides whether rotation should be applied if there -// are multiple send streams using the same camera. -bool VideoCapturer::SetApplyRotation(bool enable) { - apply_rotation_ = enable; - if (frame_factory_) { - frame_factory_->SetApplyRotation(apply_rotation_); - } - return true; -} - void VideoCapturer::SetSupportedFormats( const std::vector& formats) { supported_formats_ = formats; @@ -323,6 +317,25 @@ void VideoCapturer::GetStats(VariableInfo* adapt_drops_stats, frame_time_data_.Reset(); } +void VideoCapturer::RemoveSink( + rtc::VideoSinkInterface* sink) { + broadcaster_.RemoveSink(sink); +} + +void VideoCapturer::AddOrUpdateSink( + rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) { + broadcaster_.AddOrUpdateSink(sink, wants); + OnSinkWantsChanged(broadcaster_.wants()); +} + +void VideoCapturer::OnSinkWantsChanged(const rtc::VideoSinkWants& wants) { + apply_rotation_ = wants.rotation_applied; + if (frame_factory_) { + frame_factory_->SetApplyRotation(apply_rotation_); + } +} + void VideoCapturer::OnFrameCaptured(VideoCapturer*, const CapturedFrame* captured_frame) { if (muted_) { @@ -333,7 +346,7 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*, } } - if (SignalVideoFrame.is_empty()) { + if (!broadcaster_.frame_wanted()) { return; } @@ -517,10 +530,13 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*, adapted_frame->SetToBlack(); } SignalVideoFrame(this, adapted_frame.get()); - UpdateStats(captured_frame); } +void VideoCapturer::OnFrame(VideoCapturer* capturer, const VideoFrame* frame) { + broadcaster_.OnFrame(*frame); +} + void VideoCapturer::SetCaptureState(CaptureState state) { if (state == capture_state_) { // Don't trigger a state changed callback if the state hasn't changed. diff --git a/webrtc/media/base/videocapturer.h b/webrtc/media/base/videocapturer.h index 3b0d05e86e..0320034cad 100644 --- a/webrtc/media/base/videocapturer.h +++ b/webrtc/media/base/videocapturer.h @@ -19,6 +19,7 @@ #include "webrtc/base/basictypes.h" #include "webrtc/base/criticalsection.h" +#include "webrtc/media/base/videosourceinterface.h" #include "webrtc/base/messagehandler.h" #include "webrtc/base/rollingaccumulator.h" #include "webrtc/base/scoped_ptr.h" @@ -27,6 +28,7 @@ #include "webrtc/base/timing.h" #include "webrtc/media/base/mediachannel.h" #include "webrtc/media/base/videoadapter.h" +#include "webrtc/media/base/videobroadcaster.h" #include "webrtc/media/base/videocommon.h" #include "webrtc/media/base/videoframefactory.h" #include "webrtc/media/devices/devicemanager.h" @@ -73,7 +75,7 @@ struct CapturedFrame { // time with nanosecond units. uint32_t data_size; // number of bytes of the frame data - webrtc::VideoRotation rotation; // rotation in degrees of the frame. + webrtc::VideoRotation rotation; // rotation in degrees of the frame. void* data; // pointer to the frame data. This object allocates the // memory or points to an existing memory. @@ -108,9 +110,9 @@ struct CapturedFrame { // media engine thread). Hence, the VideoCapture subclasses dont need to be // thread safe. // -class VideoCapturer - : public sigslot::has_slots<>, - public rtc::MessageHandler { +class VideoCapturer : public sigslot::has_slots<>, + public rtc::MessageHandler, + public rtc::VideoSourceInterface { public: // All signals are marshalled to |thread| or the creating thread if // none is provided. @@ -197,11 +199,6 @@ class VideoCapturer return capture_state_; } - // Tells videocapturer whether to apply the pending rotation. By default, the - // rotation is applied and the generated frame is up right. When set to false, - // generated frames will carry the rotation information from - // SetCaptureRotation. Return value indicates whether this operation succeeds. - virtual bool SetApplyRotation(bool enable); virtual bool GetApplyRotation() { return apply_rotation_; } // Returns true if the capturer is screencasting. This can be used to @@ -240,10 +237,6 @@ class VideoCapturer // Signal the captured frame to downstream. sigslot::signal2 SignalFrameCaptured; - // Signal the captured and possibly adapted frame to downstream consumers - // such as the encoder. - sigslot::signal2 SignalVideoFrame; // If true, run video adaptation. By default, video adaptation is enabled // and users must call video_adapter()->OnOutputFormatRequest() @@ -269,10 +262,30 @@ class VideoCapturer VariableInfo* frame_time_stats, VideoFormat* last_captured_frame_format); + // Implements VideoSourceInterface + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) override; + void RemoveSink(rtc::VideoSinkInterface* sink) override; + protected: + // Signal the captured and possibly adapted frame to downstream consumers + // such as the encoder. + // TODO(perkj): Remove once it is not used by remoting in Chrome. + sigslot::signal2 SignalVideoFrame; + + // OnSinkWantsChanged can be overridden to change the default behavior + // when a sink changes its VideoSinkWants by calling AddOrUpdateSink. + virtual void OnSinkWantsChanged(const rtc::VideoSinkWants& wants); + // Callback attached to SignalFrameCaptured where SignalVideoFrames is called. void OnFrameCaptured(VideoCapturer* video_capturer, const CapturedFrame* captured_frame); + + // Callback attached to SignalVideoFrame. + // TODO(perkj): Remove once SignalVideoFrame is removed. + void OnFrame(VideoCapturer* capturer, const VideoFrame* frame); + void SetCaptureState(CaptureState state); // Marshals SignalStateChange onto thread_. @@ -344,6 +357,7 @@ class VideoCapturer bool muted_; int black_frame_count_down_; + rtc::VideoBroadcaster broadcaster_; bool enable_video_adapter_; CoordinatedVideoAdapter video_adapter_; diff --git a/webrtc/media/base/videocapturer_unittest.cc b/webrtc/media/base/videocapturer_unittest.cc index 76661cbaa7..f385d59551 100644 --- a/webrtc/media/base/videocapturer_unittest.cc +++ b/webrtc/media/base/videocapturer_unittest.cc @@ -35,29 +35,13 @@ class VideoCapturerTest public testing::Test { public: VideoCapturerTest() - : capture_state_(cricket::CS_STOPPED), - num_state_changes_(0), - video_frames_received_(0), - expects_rotation_applied_(true) { - capturer_.SignalVideoFrame.connect(this, &VideoCapturerTest::OnVideoFrame); + : capture_state_(cricket::CS_STOPPED), num_state_changes_(0) { capturer_.SignalStateChange.connect(this, &VideoCapturerTest::OnStateChange); - } - - void set_expected_compensation(bool compensation) { - expects_rotation_applied_ = compensation; + capturer_.AddOrUpdateSink(&renderer_, rtc::VideoSinkWants()); } protected: - void OnVideoFrame(cricket::VideoCapturer*, const cricket::VideoFrame* frame) { - ++video_frames_received_; - if (expects_rotation_applied_) { - EXPECT_EQ(webrtc::kVideoRotation_0, frame->GetVideoRotation()); - } else { - EXPECT_EQ(capturer_.GetRotation(), frame->GetVideoRotation()); - } - renderer_.RenderFrame(frame); - } void OnStateChange(cricket::VideoCapturer*, cricket::CaptureState capture_state) { capture_state_ = capture_state; @@ -65,14 +49,10 @@ class VideoCapturerTest } cricket::CaptureState capture_state() { return capture_state_; } int num_state_changes() { return num_state_changes_; } - int video_frames_received() const { - return video_frames_received_; - } cricket::FakeVideoCapturer capturer_; cricket::CaptureState capture_state_; int num_state_changes_; - int video_frames_received_; cricket::FakeVideoRenderer renderer_; bool expects_rotation_applied_; }; @@ -149,9 +129,9 @@ TEST_F(VideoCapturerTest, CameraOffOnMute) { cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420))); EXPECT_TRUE(capturer_.IsRunning()); - EXPECT_EQ(0, video_frames_received()); + EXPECT_EQ(0, renderer_.num_rendered_frames()); EXPECT_TRUE(capturer_.CaptureFrame()); - EXPECT_EQ(1, video_frames_received()); + EXPECT_EQ(1, renderer_.num_rendered_frames()); EXPECT_FALSE(capturer_.IsMuted()); // Mute the camera and expect black output frame. @@ -161,13 +141,13 @@ TEST_F(VideoCapturerTest, CameraOffOnMute) { EXPECT_TRUE(capturer_.CaptureFrame()); EXPECT_TRUE(renderer_.black_frame()); } - EXPECT_EQ(32, video_frames_received()); + EXPECT_EQ(32, renderer_.num_rendered_frames()); EXPECT_EQ_WAIT(cricket::CS_PAUSED, capturer_.capture_state(), kTimeout); // Verify that the camera is off. EXPECT_FALSE(capturer_.CaptureFrame()); - EXPECT_EQ(32, video_frames_received()); + EXPECT_EQ(32, renderer_.num_rendered_frames()); // Unmute the camera and expect non-black output frame. capturer_.MuteToBlackThenPause(false); @@ -176,7 +156,7 @@ TEST_F(VideoCapturerTest, CameraOffOnMute) { capturer_.capture_state(), kTimeout); EXPECT_TRUE(capturer_.CaptureFrame()); EXPECT_FALSE(renderer_.black_frame()); - EXPECT_EQ(33, video_frames_received()); + EXPECT_EQ(33, renderer_.num_rendered_frames()); } TEST_F(VideoCapturerTest, ScreencastScaledOddWidth) { @@ -203,7 +183,7 @@ TEST_F(VideoCapturerTest, ScreencastScaledOddWidth) { EXPECT_EQ(kHeight, renderer_.height()); } -TEST_F(VideoCapturerTest, TestRotationPending) { +TEST_F(VideoCapturerTest, TestRotationAppliedBySource) { int kWidth = 800; int kHeight = 400; int frame_count = 0; @@ -214,6 +194,7 @@ TEST_F(VideoCapturerTest, TestRotationPending) { cricket::FOURCC_I420)); capturer_.ResetSupportedFormats(formats); + // capturer_ should compensate rotation as default. capturer_.UpdateAspectRatio(400, 200); @@ -234,6 +215,7 @@ TEST_F(VideoCapturerTest, TestRotationPending) { // Swapped width and height EXPECT_EQ(kWidth, renderer_.height()); EXPECT_EQ(kHeight, renderer_.width()); + EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation()); capturer_.SetRotation(webrtc::kVideoRotation_270); EXPECT_TRUE(capturer_.CaptureFrame()); @@ -241,6 +223,7 @@ TEST_F(VideoCapturerTest, TestRotationPending) { // Swapped width and height EXPECT_EQ(kWidth, renderer_.height()); EXPECT_EQ(kHeight, renderer_.width()); + EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation()); capturer_.SetRotation(webrtc::kVideoRotation_180); EXPECT_TRUE(capturer_.CaptureFrame()); @@ -248,9 +231,10 @@ TEST_F(VideoCapturerTest, TestRotationPending) { // Back to normal width and height EXPECT_EQ(kWidth, renderer_.width()); EXPECT_EQ(kHeight, renderer_.height()); + EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation()); } -TEST_F(VideoCapturerTest, TestRotationApplied) { +TEST_F(VideoCapturerTest, TestRotationAppliedBySink) { int kWidth = 800; int kHeight = 400; @@ -260,10 +244,12 @@ TEST_F(VideoCapturerTest, TestRotationApplied) { cricket::FOURCC_I420)); capturer_.ResetSupportedFormats(formats); + rtc::VideoSinkWants wants; // capturer_ should not compensate rotation. - capturer_.SetApplyRotation(false); + wants.rotation_applied = false; + capturer_.AddOrUpdateSink(&renderer_, wants); + capturer_.UpdateAspectRatio(400, 200); - set_expected_compensation(false); EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( @@ -281,18 +267,64 @@ TEST_F(VideoCapturerTest, TestRotationApplied) { capturer_.SetRotation(webrtc::kVideoRotation_0); EXPECT_TRUE(capturer_.CaptureFrame()); EXPECT_EQ(++frame_count, renderer_.num_rendered_frames()); + EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation()); capturer_.SetRotation(webrtc::kVideoRotation_90); EXPECT_TRUE(capturer_.CaptureFrame()); EXPECT_EQ(++frame_count, renderer_.num_rendered_frames()); + EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation()); capturer_.SetRotation(webrtc::kVideoRotation_180); EXPECT_TRUE(capturer_.CaptureFrame()); EXPECT_EQ(++frame_count, renderer_.num_rendered_frames()); + EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation()); capturer_.SetRotation(webrtc::kVideoRotation_270); EXPECT_TRUE(capturer_.CaptureFrame()); EXPECT_EQ(++frame_count, renderer_.num_rendered_frames()); + EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation()); +} + +TEST_F(VideoCapturerTest, TestRotationAppliedBySourceWhenDifferentWants) { + int kWidth = 800; + int kHeight = 400; + + std::vector formats; + formats.push_back(cricket::VideoFormat(kWidth, kHeight, + cricket::VideoFormat::FpsToInterval(5), + cricket::FOURCC_I420)); + + capturer_.ResetSupportedFormats(formats); + rtc::VideoSinkWants wants; + // capturer_ should not compensate rotation. + wants.rotation_applied = false; + capturer_.AddOrUpdateSink(&renderer_, wants); + + capturer_.UpdateAspectRatio(400, 200); + + EXPECT_EQ(cricket::CS_RUNNING, + capturer_.Start(cricket::VideoFormat( + kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30), + cricket::FOURCC_I420))); + EXPECT_TRUE(capturer_.IsRunning()); + EXPECT_EQ(0, renderer_.num_rendered_frames()); + + int frame_count = 0; + capturer_.SetRotation(webrtc::kVideoRotation_90); + EXPECT_TRUE(capturer_.CaptureFrame()); + EXPECT_EQ(++frame_count, renderer_.num_rendered_frames()); + EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation()); + + // Add another sink that wants frames to be rotated. + cricket::FakeVideoRenderer renderer2; + wants.rotation_applied = true; + capturer_.AddOrUpdateSink(&renderer2, wants); + + EXPECT_TRUE(capturer_.CaptureFrame()); + EXPECT_EQ(++frame_count, renderer_.num_rendered_frames()); + EXPECT_EQ(1, renderer2.num_rendered_frames()); + EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation()); + EXPECT_EQ(webrtc::kVideoRotation_0, renderer2.rotation()); } TEST_F(VideoCapturerTest, ScreencastScaledSuperLarge) { @@ -715,25 +747,6 @@ TEST_F(VideoCapturerTest, TestRequest16x10_9) { EXPECT_EQ(360, best.height); } -// If HAVE_WEBRTC_VIDEO is not defined the video capturer will not be able to -// provide OnVideoFrame-callbacks since they require cricket::CapturedFrame to -// be decoded as a cricket::VideoFrame (i.e. an I420 frame). This functionality -// only exist if HAVE_WEBRTC_VIDEO is defined below. I420 frames are also a -// requirement for the VideoProcessors so they will not be called either. -#if defined(HAVE_WEBRTC_VIDEO) -TEST_F(VideoCapturerTest, VideoFrame) { - EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( - 640, - 480, - cricket::VideoFormat::FpsToInterval(30), - cricket::FOURCC_I420))); - EXPECT_TRUE(capturer_.IsRunning()); - EXPECT_EQ(0, video_frames_received()); - EXPECT_TRUE(capturer_.CaptureFrame()); - EXPECT_EQ(1, video_frames_received()); -} -#endif // HAVE_WEBRTC_VIDEO - bool HdFormatInList(const std::vector& formats) { for (std::vector::const_iterator found = formats.begin(); found != formats.end(); ++found) { diff --git a/webrtc/media/base/videoengine_unittest.h b/webrtc/media/base/videoengine_unittest.h index b7fbd4bd55..659e7e0a25 100644 --- a/webrtc/media/base/videoengine_unittest.h +++ b/webrtc/media/base/videoengine_unittest.h @@ -86,21 +86,6 @@ class VideoEngineOverride : public T { virtual ~VideoEngineOverride() { } bool is_camera_on() const { return T::GetVideoCapturer()->IsRunning(); } - void set_has_senders(bool has_senders) { - cricket::VideoCapturer* video_capturer = T::GetVideoCapturer(); - if (has_senders) { - video_capturer->SignalVideoFrame.connect(this, - &VideoEngineOverride::OnLocalFrame); - } else { - video_capturer->SignalVideoFrame.disconnect(this); - } - } - void OnLocalFrame(cricket::VideoCapturer*, - const cricket::VideoFrame*) { - } - void OnLocalFrameFormat(cricket::VideoCapturer*, - const cricket::VideoFormat*) { - } void TriggerMediaFrame(uint32_t ssrc, cricket::VideoFrame* frame, diff --git a/webrtc/media/base/videosinkinterface.h b/webrtc/media/base/videosinkinterface.h index 9b8ba31862..bb41bdb281 100644 --- a/webrtc/media/base/videosinkinterface.h +++ b/webrtc/media/base/videosinkinterface.h @@ -17,9 +17,8 @@ template class VideoSinkInterface { public: virtual void OnFrame(const VideoFrameT& frame) = 0; - protected: - ~VideoSinkInterface() {} + virtual ~VideoSinkInterface() {} }; } // namespace rtc diff --git a/webrtc/media/base/videosourceinterface.h b/webrtc/media/base/videosourceinterface.h new file mode 100644 index 0000000000..1462458543 --- /dev/null +++ b/webrtc/media/base/videosourceinterface.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 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. + */ + +#ifndef WEBRTC_MEDIA_BASE_VIDEOSOURCEINTERFACE_H_ +#define WEBRTC_MEDIA_BASE_VIDEOSOURCEINTERFACE_H_ + +#include "webrtc/media/base/videosinkinterface.h" +#include "webrtc/base/callback.h" + +namespace rtc { + +// VideoSinkWants is used for notifying the source of properties a video frame +// should have when it is delivered to a certain sink. +struct VideoSinkWants { + bool operator==(const VideoSinkWants& rh) const { + return rotation_applied == rh.rotation_applied; + } + bool operator!=(const VideoSinkWants& rh) const { return !operator==(rh); } + + // Tells the source whether the sink wants frames with rotation applied. + // By default, the rotation is applied by the source. + bool rotation_applied = true; +}; + +template +class VideoSourceInterface { + public: + virtual void AddOrUpdateSink(VideoSinkInterface* sink, + const VideoSinkWants& wants) = 0; + // RemoveSink must guarantee that at the time the method returns, + // there is no current and no future calls to VideoSinkInterface::OnFrame. + virtual void RemoveSink(VideoSinkInterface* sink) = 0; + + protected: + virtual ~VideoSourceInterface() {} +}; + +} // namespace rtc +#endif // WEBRTC_MEDIA_BASE_VIDEOSOURCEINTERFACE_H_ diff --git a/webrtc/media/engine/webrtcvideocapturer.cc b/webrtc/media/engine/webrtcvideocapturer.cc index 6dc5a11859..114556411c 100644 --- a/webrtc/media/engine/webrtcvideocapturer.cc +++ b/webrtc/media/engine/webrtcvideocapturer.cc @@ -14,7 +14,6 @@ #include #endif -#ifdef HAVE_WEBRTC_VIDEO #include "webrtc/base/arraysize.h" #include "webrtc/base/bind.h" #include "webrtc/base/checks.h" @@ -203,9 +202,6 @@ bool WebRtcVideoCapturer::Init(const Device& device) { SetId(device.id); SetSupportedFormats(supported); - // Ensure these 2 have the same value. - SetApplyRotation(module_->GetApplyRotation()); - return true; } @@ -243,7 +239,7 @@ bool WebRtcVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired, } return true; } -bool WebRtcVideoCapturer::SetApplyRotation(bool enable) { +void WebRtcVideoCapturer::OnSinkWantsChanged(const rtc::VideoSinkWants& wants) { // Can't take lock here as this will cause deadlock with // OnIncomingCapturedFrame. In fact, the whole method, including methods it // calls, can't take lock. @@ -253,13 +249,14 @@ bool WebRtcVideoCapturer::SetApplyRotation(bool enable) { webrtc::field_trial::FindFullName("WebRTC-CVO"); if (group_name == "Disabled") { - return true; + return; } - if (!VideoCapturer::SetApplyRotation(enable)) { - return false; - } - return module_->SetApplyRotation(enable); + VideoCapturer::OnSinkWantsChanged(wants); + bool result = module_->SetApplyRotation(wants.rotation_applied); + RTC_CHECK(result); + + return; } CaptureState WebRtcVideoCapturer::Start(const VideoFormat& capture_format) { @@ -427,5 +424,3 @@ WebRtcCapturedFrame::WebRtcCapturedFrame(const webrtc::VideoFrame& sample, } } // namespace cricket - -#endif // HAVE_WEBRTC_VIDEO diff --git a/webrtc/media/engine/webrtcvideocapturer.h b/webrtc/media/engine/webrtcvideocapturer.h index db9161b32b..15bc32caa8 100644 --- a/webrtc/media/engine/webrtcvideocapturer.h +++ b/webrtc/media/engine/webrtcvideocapturer.h @@ -11,8 +11,6 @@ #ifndef WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOCAPTURER_H_ #define WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOCAPTURER_H_ -#ifdef HAVE_WEBRTC_VIDEO - #include #include @@ -50,15 +48,15 @@ class WebRtcVideoCapturer : public VideoCapturer, bool Init(webrtc::VideoCaptureModule* module); // Override virtual methods of the parent class VideoCapturer. - virtual bool GetBestCaptureFormat(const VideoFormat& desired, - VideoFormat* best_format); - virtual CaptureState Start(const VideoFormat& capture_format); - virtual void Stop(); - virtual bool IsRunning(); - virtual bool IsScreencast() const { return false; } - virtual bool SetApplyRotation(bool enable); + bool GetBestCaptureFormat(const VideoFormat& desired, + VideoFormat* best_format) override; + CaptureState Start(const VideoFormat& capture_format) override; + void Stop() override; + bool IsRunning() override; + bool IsScreencast() const override { return false; } protected: + void OnSinkWantsChanged(const rtc::VideoSinkWants& wants) override; // Override virtual methods of the parent class VideoCapturer. virtual bool GetPreferredFourccs(std::vector* fourccs); @@ -95,5 +93,4 @@ struct WebRtcCapturedFrame : public CapturedFrame { } // namespace cricket -#endif // HAVE_WEBRTC_VIDEO -#endif // WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOCAPTURER_H_ +#endif // WEBRTC_MEDIA_WEBRTC_WEBRTCVIDEOCAPTURER_H_ diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc index 509c8a69ab..0dd8938dc3 100644 --- a/webrtc/media/engine/webrtcvideoengine2.cc +++ b/webrtc/media/engine/webrtcvideoengine2.cc @@ -8,7 +8,6 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifdef HAVE_WEBRTC_VIDEO #include "webrtc/media/engine/webrtcvideoengine2.h" #include @@ -960,7 +959,7 @@ bool WebRtcVideoChannel2::SetVideoSend(uint32_t ssrc, bool enable, bool WebRtcVideoChannel2::ValidateSendSsrcAvailability( const StreamParams& sp) const { - for (uint32_t ssrc: sp.ssrcs) { + for (uint32_t ssrc : sp.ssrcs) { if (send_ssrcs_.find(ssrc) != send_ssrcs_.end()) { LOG(LS_ERROR) << "Send stream with SSRC '" << ssrc << "' already exists."; return false; @@ -971,7 +970,7 @@ bool WebRtcVideoChannel2::ValidateSendSsrcAvailability( bool WebRtcVideoChannel2::ValidateReceiveSsrcAvailability( const StreamParams& sp) const { - for (uint32_t ssrc: sp.ssrcs) { + for (uint32_t ssrc : sp.ssrcs) { if (receive_ssrcs_.find(ssrc) != receive_ssrcs_.end()) { LOG(LS_ERROR) << "Receive stream with SSRC '" << ssrc << "' already exists."; @@ -1277,11 +1276,6 @@ bool WebRtcVideoChannel2::SetCapturer(uint32_t ssrc, VideoCapturer* capturer) { return false; } } - - if (capturer) { - capturer->SetApplyRotation(!ContainsHeaderExtension( - send_rtp_extensions_, kRtpVideoRotationHeaderExtension)); - } { rtc::CritScope lock(&capturer_crit_); capturers_[ssrc] = capturer; @@ -1547,12 +1541,11 @@ static void CreateBlackFrame(webrtc::VideoFrame* video_frame, video_frame->set_rotation(rotation); } -void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( - VideoCapturer* capturer, - const VideoFrame* frame) { - TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::InputFrame"); - webrtc::VideoFrame video_frame(frame->GetVideoFrameBuffer(), 0, 0, - frame->GetVideoRotation()); +void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame( + const VideoFrame& frame) { + TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::OnFrame"); + webrtc::VideoFrame video_frame(frame.GetVideoFrameBuffer(), 0, 0, + frame.GetVideoRotation()); rtc::CritScope cs(&lock_); if (stream_ == NULL) { // Frame input before send codecs are configured, dropping frame. @@ -1566,12 +1559,13 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( if (muted_) { // Create a black frame to transmit instead. - CreateBlackFrame(&video_frame, static_cast(frame->GetWidth()), - static_cast(frame->GetHeight()), - frame->GetVideoRotation()); + CreateBlackFrame(&video_frame, + static_cast(frame.GetWidth()), + static_cast(frame.GetHeight()), + video_frame.rotation()); } - int64_t frame_delta_ms = frame->GetTimeStamp() / rtc::kNumNanosecsPerMillisec; + int64_t frame_delta_ms = frame.GetTimeStamp() / rtc::kNumNanosecsPerMillisec; // frame->GetTimeStamp() is essentially a delta, align to webrtc time if (first_frame_timestamp_ms_ == 0) { first_frame_timestamp_ms_ = rtc::Time() - frame_delta_ms; @@ -1580,8 +1574,8 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( last_frame_timestamp_ms_ = first_frame_timestamp_ms_ + frame_delta_ms; video_frame.set_render_time_ms(last_frame_timestamp_ms_); // Reconfigure codec if necessary. - SetDimensions( - video_frame.width(), video_frame.height(), capturer->IsScreencast()); + SetDimensions(video_frame.width(), video_frame.height(), + capturer_->IsScreencast()); last_rotation_ = video_frame.rotation(); stream_->Input()->IncomingCapturedFrame(video_frame); @@ -1624,10 +1618,8 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer( } capturer_ = capturer; + capturer_->AddOrUpdateSink(this, sink_wants_); } - // Lock cannot be held while connecting the capturer to prevent lock-order - // violations. - capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame); return true; } @@ -1649,7 +1641,8 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() { capturer = capturer_; capturer_ = NULL; } - capturer->SignalVideoFrame.disconnect(this); + capturer->RemoveSink(this); + return true; } @@ -1786,9 +1779,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters( } if (params.rtp_header_extensions) { parameters_.config.rtp.extensions = *params.rtp_header_extensions; + sink_wants_.rotation_applied = !ContainsHeaderExtension( + *params.rtp_header_extensions, kRtpVideoRotationHeaderExtension); if (capturer_) { - capturer_->SetApplyRotation(!ContainsHeaderExtension( - *params.rtp_header_extensions, kRtpVideoRotationHeaderExtension)); + capturer_->AddOrUpdateSink(this, sink_wants_); } recreate_stream = true; } @@ -2496,5 +2490,3 @@ WebRtcVideoChannel2::MapCodecs(const std::vector& codecs) { } } // namespace cricket - -#endif // HAVE_WEBRTC_VIDEO diff --git a/webrtc/media/engine/webrtcvideoengine2.h b/webrtc/media/engine/webrtcvideoengine2.h index a8218324f8..16b7cc5157 100644 --- a/webrtc/media/engine/webrtcvideoengine2.h +++ b/webrtc/media/engine/webrtcvideoengine2.h @@ -12,6 +12,7 @@ #define WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOENGINE2_H_ #include +#include #include #include @@ -20,6 +21,7 @@ #include "webrtc/base/thread_annotations.h" #include "webrtc/base/thread_checker.h" #include "webrtc/media/base/videosinkinterface.h" +#include "webrtc/media/base/videosourceinterface.h" #include "webrtc/call.h" #include "webrtc/media/base/mediaengine.h" #include "webrtc/media/engine/webrtcvideochannelfactory.h" @@ -226,7 +228,8 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, // Wrapper for the sender part, this is where the capturer is connected and // frames are then converted from cricket frames to webrtc frames. - class WebRtcVideoSendStream : public sigslot::has_slots<> { + class WebRtcVideoSendStream + : public rtc::VideoSinkInterface { public: WebRtcVideoSendStream( webrtc::Call* call, @@ -238,13 +241,13 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, const rtc::Optional& codec_settings, const std::vector& rtp_extensions, const VideoSendParameters& send_params); - ~WebRtcVideoSendStream(); + virtual ~WebRtcVideoSendStream(); void SetOptions(const VideoOptions& options); // TODO(pbos): Move logic from SetOptions into this method. void SetSendParameters(const ChangedSendParameters& send_params); - void InputFrame(VideoCapturer* capturer, const VideoFrame* frame); + void OnFrame(const cricket::VideoFrame& frame) override; bool SetCapturer(VideoCapturer* capturer); void MuteStream(bool mute); bool DisconnectCapturer(); @@ -340,6 +343,7 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, const std::vector ssrcs_; const std::vector ssrc_groups_; webrtc::Call* const call_; + rtc::VideoSinkWants sink_wants_; WebRtcVideoEncoderFactory* const external_encoder_factory_ GUARDED_BY(lock_); diff --git a/webrtc/media/media.gyp b/webrtc/media/media.gyp index 5c460f8de7..e4960e16c9 100644 --- a/webrtc/media/media.gyp +++ b/webrtc/media/media.gyp @@ -35,8 +35,6 @@ 'base/audiorenderer.h', 'base/capturemanager.cc', 'base/capturemanager.h', - 'base/capturerenderadapter.cc', - 'base/capturerenderadapter.h', 'base/codec.cc', 'base/codec.h', 'base/constants.cc', @@ -64,6 +62,8 @@ 'base/turnutils.h', 'base/videoadapter.cc', 'base/videoadapter.h', + 'base/videobroadcaster.cc', + 'base/videobroadcaster.h', 'base/videocapturer.cc', 'base/videocapturer.h', 'base/videocapturerfactory.h', diff --git a/webrtc/pc/channelmanager.cc b/webrtc/pc/channelmanager.cc index c3e5893446..fe0564bbc2 100644 --- a/webrtc/pc/channelmanager.cc +++ b/webrtc/pc/channelmanager.cc @@ -86,7 +86,6 @@ void ChannelManager::Construct(MediaEngineInterface* me, main_thread_ = rtc::Thread::Current(); worker_thread_ = worker_thread; audio_output_volume_ = kNotSetOutputVolume; - local_renderer_ = NULL; capturing_ = false; enable_rtx_ = false; diff --git a/webrtc/pc/channelmanager.h b/webrtc/pc/channelmanager.h index a488d4f843..bd1bc2f469 100644 --- a/webrtc/pc/channelmanager.h +++ b/webrtc/pc/channelmanager.h @@ -214,7 +214,6 @@ class ChannelManager : public rtc::MessageHandler, DataChannels data_channels_; int audio_output_volume_; - VideoRenderer* local_renderer_; bool enable_rtx_; bool capturing_;