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}
diff --git a/webrtc/media/base/capturemanager.cc b/webrtc/media/base/capturemanager.cc
index 689b6d7..3628fb3 100644
--- a/webrtc/media/base/capturemanager.cc
+++ b/webrtc/media/base/capturemanager.cc
@@ -23,7 +23,7 @@
  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 @@
 
   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 @@
   };
   typedef std::vector<CaptureResolutionInfo> CaptureFormats;
 
-  explicit VideoCapturerState(CaptureRenderAdapter* adapter);
-
   rtc::ThreadChecker thread_checker_;
-  rtc::scoped_ptr<CaptureRenderAdapter> adapter_;
 
+  VideoCapturer* video_capturer_;
   int start_count_;
   CaptureFormats capture_formats_;
 };
@@ -66,17 +60,8 @@
   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 @@
   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 @@
   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::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 @@
   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 c4f1f69..93f8e18 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 @@
                                   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 f8d28f7..4eb738b 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<VideoFrame>* 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<VideoFrame>* 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 ea45768..4eb738b 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 <vector>
-
-#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<VideoFrame>* sink);
-  void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* 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<rtc::VideoSinkInterface<VideoFrame>*> 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 bc82cba..0854d0c 100644
--- a/webrtc/media/base/fakevideorenderer.h
+++ b/webrtc/media/base/fakevideorenderer.h
@@ -43,6 +43,7 @@
     ++num_rendered_frames_;
     width_ = static_cast<int>(frame->GetWidth());
     height_ = static_cast<int>(frame->GetHeight());
+    rotation_ = frame->GetVideoRotation();
     SignalRenderFrame(frame);
     return true;
   }
@@ -56,6 +57,10 @@
     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 @@
   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 a9f6eae..e369ee0 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<cricket::VideoFrame>* 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<cricket::VideoFrame>* 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<cricket::VideoFrame>* 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 f0009c9..63c2273 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 <utility>
+#include <vector>
+
+#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<cricket::VideoFrame>,
+                         public VideoSinkInterface<cricket::VideoFrame> {
+ public:
+  VideoBroadcaster();
+  void AddOrUpdateSink(VideoSinkInterface<cricket::VideoFrame>* sink,
+                       const VideoSinkWants& wants) override;
+  void RemoveSink(VideoSinkInterface<cricket::VideoFrame>* 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<cricket::VideoFrame>* sink,
+             VideoSinkWants wants)
+        : sink(sink), wants(wants) {}
+    VideoSinkInterface<cricket::VideoFrame>* sink;
+    VideoSinkWants wants;
+  };
+  SinkPair* FindSinkPair(const VideoSinkInterface<cricket::VideoFrame>* sink);
+
+  ThreadChecker thread_checker_;
+
+  VideoSinkWants current_wants_;
+
+  std::vector<SinkPair> sinks_;
+};
+
+}  // namespace rtc
 
 #endif  // WEBRTC_MEDIA_BASE_VIDEOBROADCASTER_H_
diff --git a/webrtc/media/base/videocapturer.cc b/webrtc/media/base/videocapturer.cc
index 5b05904..2d6a15e 100644
--- a/webrtc/media/base/videocapturer.cc
+++ b/webrtc/media/base/videocapturer.cc
@@ -102,6 +102,10 @@
   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 @@
   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<VideoFormat>& formats) {
   supported_formats_ = formats;
@@ -323,6 +317,25 @@
   frame_time_data_.Reset();
 }
 
+void VideoCapturer::RemoveSink(
+    rtc::VideoSinkInterface<cricket::VideoFrame>* sink) {
+  broadcaster_.RemoveSink(sink);
+}
+
+void VideoCapturer::AddOrUpdateSink(
+    rtc::VideoSinkInterface<cricket::VideoFrame>* 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 @@
     }
   }
 
-  if (SignalVideoFrame.is_empty()) {
+  if (!broadcaster_.frame_wanted()) {
     return;
   }
 
@@ -517,10 +530,13 @@
     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 3b0d05e..0320034 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 @@
                        // 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 @@
 //   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<cricket::VideoFrame> {
  public:
   // All signals are marshalled to |thread| or the creating thread if
   // none is provided.
@@ -197,11 +199,6 @@
     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 @@
   // Signal the captured frame to downstream.
   sigslot::signal2<VideoCapturer*, const CapturedFrame*,
                    sigslot::multi_threaded_local> SignalFrameCaptured;
-  // Signal the captured and possibly adapted frame to downstream consumers
-  // such as the encoder.
-  sigslot::signal2<VideoCapturer*, const VideoFrame*,
-                   sigslot::multi_threaded_local> SignalVideoFrame;
 
   // If true, run video adaptation. By default, video adaptation is enabled
   // and users must call video_adapter()->OnOutputFormatRequest()
@@ -269,10 +262,30 @@
                 VariableInfo<double>* frame_time_stats,
                 VideoFormat* last_captured_frame_format);
 
+  // Implements VideoSourceInterface
+  void AddOrUpdateSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
+                       const rtc::VideoSinkWants& wants) override;
+  void RemoveSink(rtc::VideoSinkInterface<cricket::VideoFrame>* 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<VideoCapturer*, const VideoFrame*,
+                    sigslot::multi_threaded_local> 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 @@
   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 76661cb..f385d59 100644
--- a/webrtc/media/base/videocapturer_unittest.cc
+++ b/webrtc/media/base/videocapturer_unittest.cc
@@ -35,29 +35,13 @@
       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 @@
   }
   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 @@
       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 @@
     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 @@
                  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 @@
   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 @@
                                          cricket::FOURCC_I420));
 
   capturer_.ResetSupportedFormats(formats);
+
   // capturer_ should compensate rotation as default.
   capturer_.UpdateAspectRatio(400, 200);
 
@@ -234,6 +215,7 @@
   // 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 @@
   // 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 @@
   // 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 @@
                                          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 @@
   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<cricket::VideoFormat> 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 @@
   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<cricket::VideoFormat>& formats) {
   for (std::vector<cricket::VideoFormat>::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 b7fbd4b..659e7e0 100644
--- a/webrtc/media/base/videoengine_unittest.h
+++ b/webrtc/media/base/videoengine_unittest.h
@@ -86,21 +86,6 @@
   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<T>::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 9b8ba31..bb41bdb 100644
--- a/webrtc/media/base/videosinkinterface.h
+++ b/webrtc/media/base/videosinkinterface.h
@@ -17,9 +17,8 @@
 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 0000000..1462458
--- /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 <typename VideoFrameT>
+class VideoSourceInterface {
+ public:
+  virtual void AddOrUpdateSink(VideoSinkInterface<VideoFrameT>* 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<VideoFrameT>* 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 6dc5a11..1145564 100644
--- a/webrtc/media/engine/webrtcvideocapturer.cc
+++ b/webrtc/media/engine/webrtcvideocapturer.cc
@@ -14,7 +14,6 @@
 #include <config.h>
 #endif
 
-#ifdef HAVE_WEBRTC_VIDEO
 #include "webrtc/base/arraysize.h"
 #include "webrtc/base/bind.h"
 #include "webrtc/base/checks.h"
@@ -203,9 +202,6 @@
   SetId(device.id);
   SetSupportedFormats(supported);
 
-  // Ensure these 2 have the same value.
-  SetApplyRotation(module_->GetApplyRotation());
-
   return true;
 }
 
@@ -243,7 +239,7 @@
   }
   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 @@
       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 @@
 }
 
 }  // namespace cricket
-
-#endif  // HAVE_WEBRTC_VIDEO
diff --git a/webrtc/media/engine/webrtcvideocapturer.h b/webrtc/media/engine/webrtcvideocapturer.h
index db9161b..15bc32c 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 <string>
 #include <vector>
 
@@ -50,15 +48,15 @@
   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<uint32_t>* fourccs);
 
@@ -95,5 +93,4 @@
 
 }  // 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 509c8a6..0dd8938 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 <algorithm>
@@ -960,7 +959,7 @@
 
 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::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 @@
       return false;
     }
   }
-
-  if (capturer) {
-    capturer->SetApplyRotation(!ContainsHeaderExtension(
-        send_rtp_extensions_, kRtpVideoRotationHeaderExtension));
-  }
   {
     rtc::CritScope lock(&capturer_crit_);
     capturers_[ssrc] = capturer;
@@ -1547,12 +1541,11 @@
   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 @@
 
   if (muted_) {
     // Create a black frame to transmit instead.
-    CreateBlackFrame(&video_frame, static_cast<int>(frame->GetWidth()),
-                     static_cast<int>(frame->GetHeight()),
-                     frame->GetVideoRotation());
+    CreateBlackFrame(&video_frame,
+                     static_cast<int>(frame.GetWidth()),
+                     static_cast<int>(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 @@
   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 @@
     }
 
     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 @@
     capturer = capturer_;
     capturer_ = NULL;
   }
-  capturer->SignalVideoFrame.disconnect(this);
+  capturer->RemoveSink(this);
+
   return true;
 }
 
@@ -1786,9 +1779,10 @@
   }
   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 @@
 }
 
 }  // namespace cricket
-
-#endif  // HAVE_WEBRTC_VIDEO
diff --git a/webrtc/media/engine/webrtcvideoengine2.h b/webrtc/media/engine/webrtcvideoengine2.h
index a821832..16b7cc5 100644
--- a/webrtc/media/engine/webrtcvideoengine2.h
+++ b/webrtc/media/engine/webrtcvideoengine2.h
@@ -12,6 +12,7 @@
 #define WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOENGINE2_H_
 
 #include <map>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -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 @@
 
   // 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<cricket::VideoFrame> {
    public:
     WebRtcVideoSendStream(
         webrtc::Call* call,
@@ -238,13 +241,13 @@
         const rtc::Optional<VideoCodecSettings>& codec_settings,
         const std::vector<webrtc::RtpExtension>& 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 @@
     const std::vector<uint32_t> ssrcs_;
     const std::vector<SsrcGroup> 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 5c460f8..e4960e1 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',