summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/content_renderer.gypi4
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/renderer/media/media_stream_center.cc7
-rw-r--r--content/renderer/media/media_stream_dependency_factory.cc20
-rw-r--r--content/renderer/media/media_stream_dependency_factory.h2
-rw-r--r--content/renderer/media/media_stream_video_source.cc1
-rw-r--r--content/renderer/media/media_stream_video_source.h4
-rw-r--r--content/renderer/media/media_stream_video_track.cc50
-rw-r--r--content/renderer/media/media_stream_video_track.h21
-rw-r--r--content/renderer/media/mock_media_stream_dependency_factory.cc43
-rw-r--r--content/renderer/media/mock_media_stream_dependency_factory.h7
-rw-r--r--content/renderer/media/remote_media_stream_impl.cc163
-rw-r--r--content/renderer/media/remote_media_stream_impl.h6
-rw-r--r--content/renderer/media/rtc_peer_connection_handler_unittest.cc38
-rw-r--r--content/renderer/media/webrtc/media_stream_remote_video_source.cc157
-rw-r--r--content/renderer/media/webrtc/media_stream_remote_video_source.h74
-rw-r--r--content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc160
-rw-r--r--content/renderer/media/webrtc/webrtc_video_sink_adapter.cc118
-rw-r--r--content/renderer/media/webrtc/webrtc_video_sink_adapter.h60
19 files changed, 569 insertions, 367 deletions
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 45dd77c..7250d83 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -690,6 +690,8 @@
'renderer/media/video_source_handler.h',
'renderer/media/webaudio_capturer_source.cc',
'renderer/media/webaudio_capturer_source.h',
+ 'renderer/media/webrtc/media_stream_remote_video_source.cc',
+ 'renderer/media/webrtc/media_stream_remote_video_source.h',
'renderer/media/webrtc/media_stream_track_metrics.cc',
'renderer/media/webrtc/media_stream_track_metrics.h',
'renderer/media/webrtc/video_destination_handler.cc',
@@ -700,8 +702,6 @@
'renderer/media/webrtc/webrtc_local_audio_track_adapter.h',
'renderer/media/webrtc/webrtc_video_capturer_adapter.cc',
'renderer/media/webrtc/webrtc_video_capturer_adapter.h',
- 'renderer/media/webrtc/webrtc_video_sink_adapter.cc',
- 'renderer/media/webrtc/webrtc_video_sink_adapter.h',
'renderer/media/webrtc_audio_capturer.cc',
'renderer/media/webrtc_audio_capturer.h',
'renderer/media/webrtc_audio_device_impl.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 0d9efcc..d21aadf0 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -727,6 +727,7 @@
'renderer/media/rtc_peer_connection_handler_unittest.cc',
'renderer/media/rtc_video_decoder_unittest.cc',
'renderer/media/video_source_handler_unittest.cc',
+ 'renderer/media/webrtc/media_stream_remote_video_source_unittest.cc',
'renderer/media/webrtc/media_stream_track_metrics_unittest.cc',
'renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc',
'renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc',
diff --git a/content/renderer/media/media_stream_center.cc b/content/renderer/media/media_stream_center.cc
index 3318fbd..d7279c7 100644
--- a/content/renderer/media/media_stream_center.cc
+++ b/content/renderer/media/media_stream_center.cc
@@ -52,12 +52,7 @@ void CreateNativeVideoMediaStreamTrack(
DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo);
MediaStreamVideoSource* native_source =
MediaStreamVideoSource::GetVideoSource(source);
- if (!native_source) {
- // TODO(perkj): Implement support for sources from
- // remote MediaStreams.
- NOTIMPLEMENTED();
- return;
- }
+ DCHECK(native_source);
blink::WebMediaStreamTrack writable_track(track);
writable_track.setExtraData(
new MediaStreamVideoTrack(native_source, source.constraints(),
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index fef5308..70f3d06 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -678,24 +678,20 @@ MediaStreamDependencyFactory::CreateAudioCapturer(
GetWebRtcAudioDevice());
}
-void MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack(
+void MediaStreamDependencyFactory::AddNativeAudioTrackToBlinkTrack(
webrtc::MediaStreamTrackInterface* native_track,
const blink::WebMediaStreamTrack& webkit_track,
bool is_local_track) {
DCHECK(!webkit_track.isNull() && !webkit_track.extraData());
+ DCHECK_EQ(blink::WebMediaStreamSource::TypeAudio,
+ webkit_track.source().type());
blink::WebMediaStreamTrack track = webkit_track;
- if (track.source().type() == blink::WebMediaStreamSource::TypeVideo) {
- DVLOG(1) << "AddNativeTrackToBlinkTrack() video";
- track.setExtraData(new WebRtcMediaStreamVideoTrack(
- static_cast<webrtc::VideoTrackInterface*>(native_track)));
- } else {
- DVLOG(1) << "AddNativeTrackToBlinkTrack() audio";
- track.setExtraData(
- new MediaStreamTrack(
- static_cast<webrtc::AudioTrackInterface*>(native_track),
- is_local_track));
- }
+ DVLOG(1) << "AddNativeTrackToBlinkTrack() audio";
+ track.setExtraData(
+ new MediaStreamTrack(
+ static_cast<webrtc::AudioTrackInterface*>(native_track),
+ is_local_track));
}
bool MediaStreamDependencyFactory::OnControlMessageReceived(
diff --git a/content/renderer/media/media_stream_dependency_factory.h b/content/renderer/media/media_stream_dependency_factory.h
index accac97..5986abb 100644
--- a/content/renderer/media/media_stream_dependency_factory.h
+++ b/content/renderer/media/media_stream_dependency_factory.h
@@ -136,7 +136,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
WebRtcAudioDeviceImpl* GetWebRtcAudioDevice();
- static void AddNativeTrackToBlinkTrack(
+ static void AddNativeAudioTrackToBlinkTrack(
webrtc::MediaStreamTrackInterface* native_track,
const blink::WebMediaStreamTrack& webkit_track,
bool is_local_track);
diff --git a/content/renderer/media/media_stream_video_source.cc b/content/renderer/media/media_stream_video_source.cc
index 6091726..51da6bb 100644
--- a/content/renderer/media/media_stream_video_source.cc
+++ b/content/renderer/media/media_stream_video_source.cc
@@ -308,7 +308,6 @@ MediaStreamVideoSource::MediaStreamVideoSource(
: state_(NEW),
factory_(factory),
capture_adapter_(NULL) {
- DCHECK(factory_);
}
MediaStreamVideoSource::~MediaStreamVideoSource() {
diff --git a/content/renderer/media/media_stream_video_source.h b/content/renderer/media/media_stream_video_source.h
index b080a47..af33b4e 100644
--- a/content/renderer/media/media_stream_video_source.h
+++ b/content/renderer/media/media_stream_video_source.h
@@ -64,7 +64,7 @@ class CONTENT_EXPORT MediaStreamVideoSource
// interface of this class.
// This creates a VideoSourceInterface implementation if it does not already
// exist.
- webrtc::VideoSourceInterface* GetAdapter();
+ virtual webrtc::VideoSourceInterface* GetAdapter();
// Return true if |name| is a constraint supported by MediaStreamVideoSource.
static bool IsConstraintSupported(const std::string& name);
@@ -130,7 +130,7 @@ class CONTENT_EXPORT MediaStreamVideoSource
STARTED,
ENDED
};
- State state() { return state_; }
+ State state() const { return state_; }
private:
// Creates a webrtc::VideoSourceInterface used by libjingle.
diff --git a/content/renderer/media/media_stream_video_track.cc b/content/renderer/media/media_stream_video_track.cc
index 3cf98cd..8d4b83d 100644
--- a/content/renderer/media/media_stream_video_track.cc
+++ b/content/renderer/media/media_stream_video_track.cc
@@ -5,7 +5,6 @@
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
-#include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h"
namespace content {
@@ -42,18 +41,12 @@ MediaStreamVideoTrack::MediaStreamVideoTrack(
enabled_(enabled),
source_(source),
factory_(factory) {
- // TODO(perkj): source can be NULL if this is actually a remote video track.
- // Remove as soon as we only have one implementation of video tracks.
- if (source)
- source->AddTrack(this, constraints, callback);
+ source->AddTrack(this, constraints, callback);
}
MediaStreamVideoTrack::~MediaStreamVideoTrack() {
DCHECK(sinks_.empty());
- // TODO(perkj): source can be NULL if this is actually a remote video track.
- // Remove as soon as we only have one implementation of video tracks.
- if (source_)
- source_->RemoveTrack(this);
+ source_->RemoveTrack(this);
}
void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) {
@@ -116,43 +109,4 @@ void MediaStreamVideoTrack::OnReadyStateChanged(
}
}
-// Wrapper which allows to use std::find_if() when adding and removing
-// sinks to/from |sinks_|.
-struct SinkWrapper {
- explicit SinkWrapper(MediaStreamVideoSink* sink) : sink_(sink) {}
- bool operator()(
- const WebRtcVideoSinkAdapter* owner) {
- return owner->sink() == sink_;
- }
- MediaStreamVideoSink* sink_;
-};
-
-WebRtcMediaStreamVideoTrack::WebRtcMediaStreamVideoTrack(
- webrtc::VideoTrackInterface* track)
- : MediaStreamVideoTrack(NULL,
- blink::WebMediaConstraints(),
- MediaStreamVideoSource::ConstraintsCallback(),
- track->enabled(),
- NULL) {
- track_ = track;
-}
-
-WebRtcMediaStreamVideoTrack::~WebRtcMediaStreamVideoTrack() {
-}
-
-void WebRtcMediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(std::find_if(sinks_.begin(), sinks_.end(),
- SinkWrapper(sink)) == sinks_.end());
- sinks_.push_back(new WebRtcVideoSinkAdapter(GetVideoAdapter(), sink));
-}
-
-void WebRtcMediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ScopedVector<WebRtcVideoSinkAdapter>::iterator it =
- std::find_if(sinks_.begin(), sinks_.end(), SinkWrapper(sink));
- DCHECK(it != sinks_.end());
- sinks_.erase(it);
-}
-
} // namespace content
diff --git a/content/renderer/media/media_stream_video_track.h b/content/renderer/media/media_stream_video_track.h
index 16c0a91..07307ae 100644
--- a/content/renderer/media/media_stream_video_track.h
+++ b/content/renderer/media/media_stream_video_track.h
@@ -22,7 +22,6 @@ class VideoTrackInterface;
namespace content {
class MediaStreamDependencyFactory;
-class WebRtcVideoSinkAdapter;
// MediaStreamVideoTrack is a video specific representation of a
// blink::WebMediaStreamTrack in content. It is owned by the blink object
@@ -87,26 +86,6 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoTrack);
};
-// WebRtcMediaStreamVideoTrack is a content representation of a video track.
-// received on a PeerConnection.
-// TODO(perkj): Replace WebRtcMediaStreamVideoTrack with a remote
-// MediaStreamVideoSource class so that all tracks are MediaStreamVideoTracks
-// and new tracks can be cloned from the original remote video track.
-// crbug/334243.
-class CONTENT_EXPORT WebRtcMediaStreamVideoTrack
- : public MediaStreamVideoTrack {
- public:
- explicit WebRtcMediaStreamVideoTrack(webrtc::VideoTrackInterface* track);
- virtual ~WebRtcMediaStreamVideoTrack();
- virtual void AddSink(MediaStreamVideoSink* sink) OVERRIDE;
- virtual void RemoveSink(MediaStreamVideoSink* sink) OVERRIDE;
-
- private:
- ScopedVector<WebRtcVideoSinkAdapter> sinks_;
-
- DISALLOW_COPY_AND_ASSIGN(WebRtcMediaStreamVideoTrack);
-};
-
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.cc b/content/renderer/media/mock_media_stream_dependency_factory.cc
index 1441d32..d07cb3a 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.cc
+++ b/content/renderer/media/mock_media_stream_dependency_factory.cc
@@ -283,60 +283,64 @@ int MockVideoSource::GetFrameNum() const {
return static_cast<MockRtcVideoCapturer*>(capturer_.get())->GetFrameNum();
}
-MockLocalVideoTrack::MockLocalVideoTrack(std::string id,
- webrtc::VideoSourceInterface* source)
+MockWebRtcVideoTrack::MockWebRtcVideoTrack(
+ std::string id,
+ webrtc::VideoSourceInterface* source)
: enabled_(false),
id_(id),
state_(MediaStreamTrackInterface::kLive),
source_(source),
- observer_(NULL) {
+ observer_(NULL),
+ renderer_(NULL) {
}
-MockLocalVideoTrack::~MockLocalVideoTrack() {}
+MockWebRtcVideoTrack::~MockWebRtcVideoTrack() {}
-void MockLocalVideoTrack::AddRenderer(VideoRendererInterface* renderer) {
- NOTIMPLEMENTED();
+void MockWebRtcVideoTrack::AddRenderer(VideoRendererInterface* renderer) {
+ DCHECK(!renderer_);
+ renderer_ = renderer;
}
-void MockLocalVideoTrack::RemoveRenderer(VideoRendererInterface* renderer) {
- NOTIMPLEMENTED();
+void MockWebRtcVideoTrack::RemoveRenderer(VideoRendererInterface* renderer) {
+ DCHECK_EQ(renderer_, renderer);
+ renderer_ = NULL;
}
-std::string MockLocalVideoTrack::kind() const {
+std::string MockWebRtcVideoTrack::kind() const {
NOTIMPLEMENTED();
return std::string();
}
-std::string MockLocalVideoTrack::id() const { return id_; }
+std::string MockWebRtcVideoTrack::id() const { return id_; }
-bool MockLocalVideoTrack::enabled() const { return enabled_; }
+bool MockWebRtcVideoTrack::enabled() const { return enabled_; }
-MockLocalVideoTrack::TrackState MockLocalVideoTrack::state() const {
+MockWebRtcVideoTrack::TrackState MockWebRtcVideoTrack::state() const {
return state_;
}
-bool MockLocalVideoTrack::set_enabled(bool enable) {
+bool MockWebRtcVideoTrack::set_enabled(bool enable) {
enabled_ = enable;
return true;
}
-bool MockLocalVideoTrack::set_state(TrackState new_state) {
+bool MockWebRtcVideoTrack::set_state(TrackState new_state) {
state_ = new_state;
if (observer_)
observer_->OnChanged();
return true;
}
-void MockLocalVideoTrack::RegisterObserver(ObserverInterface* observer) {
+void MockWebRtcVideoTrack::RegisterObserver(ObserverInterface* observer) {
observer_ = observer;
}
-void MockLocalVideoTrack::UnregisterObserver(ObserverInterface* observer) {
+void MockWebRtcVideoTrack::UnregisterObserver(ObserverInterface* observer) {
DCHECK(observer_ == observer);
observer_ = NULL;
}
-VideoSourceInterface* MockLocalVideoTrack::GetSource() const {
+VideoSourceInterface* MockWebRtcVideoTrack::GetSource() const {
return source_.get();
}
@@ -480,7 +484,7 @@ MockMediaStreamDependencyFactory::CreateLocalVideoTrack(
const std::string& id,
webrtc::VideoSourceInterface* source) {
scoped_refptr<webrtc::VideoTrackInterface> track(
- new talk_base::RefCountedObject<MockLocalVideoTrack>(
+ new talk_base::RefCountedObject<MockWebRtcVideoTrack>(
id, source));
return track;
}
@@ -493,7 +497,8 @@ MockMediaStreamDependencyFactory::CreateLocalVideoTrack(
new talk_base::RefCountedObject<MockVideoSource>();
source->SetVideoCapturer(capturer);
- return new talk_base::RefCountedObject<MockLocalVideoTrack>(id, source.get());
+ return
+ new talk_base::RefCountedObject<MockWebRtcVideoTrack>(id, source.get());
}
SessionDescriptionInterface*
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.h b/content/renderer/media/mock_media_stream_dependency_factory.h
index 05cd5c7..a2cce87 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.h
+++ b/content/renderer/media/mock_media_stream_dependency_factory.h
@@ -104,9 +104,9 @@ class MockAudioSource : public webrtc::AudioSourceInterface {
webrtc::MediaConstraintsInterface::Constraints mandatory_constraints_;
};
-class MockLocalVideoTrack : public webrtc::VideoTrackInterface {
+class MockWebRtcVideoTrack : public webrtc::VideoTrackInterface {
public:
- MockLocalVideoTrack(std::string id,
+ MockWebRtcVideoTrack(std::string id,
webrtc::VideoSourceInterface* source);
virtual void AddRenderer(webrtc::VideoRendererInterface* renderer) OVERRIDE;
virtual void RemoveRenderer(
@@ -122,7 +122,7 @@ class MockLocalVideoTrack : public webrtc::VideoTrackInterface {
virtual webrtc::VideoSourceInterface* GetSource() const OVERRIDE;
protected:
- virtual ~MockLocalVideoTrack();
+ virtual ~MockWebRtcVideoTrack();
private:
bool enabled_;
@@ -130,6 +130,7 @@ class MockLocalVideoTrack : public webrtc::VideoTrackInterface {
TrackState state_;
scoped_refptr<webrtc::VideoSourceInterface> source_;
webrtc::ObserverInterface* observer_;
+ webrtc::VideoRendererInterface* renderer_;
};
class MockMediaStream : public webrtc::MediaStreamInterface {
diff --git a/content/renderer/media/remote_media_stream_impl.cc b/content/renderer/media/remote_media_stream_impl.cc
index 66bdb60..1510607b 100644
--- a/content/renderer/media/remote_media_stream_impl.cc
+++ b/content/renderer/media/remote_media_stream_impl.cc
@@ -10,39 +10,13 @@
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/webrtc/media_stream_remote_video_source.h"
+#include "content/renderer/render_thread_impl.h"
#include "third_party/WebKit/public/platform/WebString.h"
namespace content {
-// RemoteMediaStreamTrackObserver is responsible for listening on change
-// notification on a remote webrtc MediaStreamTrack and notify WebKit.
-class RemoteMediaStreamTrackObserver
- : NON_EXPORTED_BASE(public webrtc::ObserverInterface),
- NON_EXPORTED_BASE(public base::NonThreadSafe) {
- public:
- RemoteMediaStreamTrackObserver(
- webrtc::MediaStreamTrackInterface* webrtc_track,
- const blink::WebMediaStreamTrack& webkit_track);
- virtual ~RemoteMediaStreamTrackObserver();
-
- webrtc::MediaStreamTrackInterface* observered_track() {
- return webrtc_track_.get();
- }
- const blink::WebMediaStreamTrack& webkit_track() { return webkit_track_; }
-
- private:
- // webrtc::ObserverInterface implementation.
- virtual void OnChanged() OVERRIDE;
-
- webrtc::MediaStreamTrackInterface::TrackState state_;
- scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
- blink::WebMediaStreamTrack webkit_track_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver);
-};
-
-} // namespace content
-
namespace {
void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track,
@@ -53,43 +27,114 @@ void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track,
webkit_source.initialize(webkit_track_id, type, webkit_track_id);
webkit_track->initialize(webkit_track_id, webkit_source);
- content::MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack(
- track, *webkit_track, false);
+
+ MediaStreamDependencyFactory* factory = NULL;
+ // RenderThreadImpl::current() may be NULL in unit tests.
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ if (render_thread)
+ factory = render_thread->GetMediaStreamDependencyFactory();
+
+ if (type == blink::WebMediaStreamSource::TypeVideo) {
+ MediaStreamRemoteVideoSource* video_source =
+ new MediaStreamRemoteVideoSource(
+ static_cast<webrtc::VideoTrackInterface*>(track));
+ webkit_source.setExtraData(video_source);
+ // Initial constraints must be provided to a MediaStreamVideoTrack. But
+ // no constraints are available initially on a remote video track.
+ blink::WebMediaConstraints constraints;
+ constraints.initialize();
+ webkit_track->setExtraData(
+ new MediaStreamVideoTrack(video_source, constraints,
+ MediaStreamVideoSource::ConstraintsCallback(),
+ track->enabled(), factory));
+ } else {
+ DCHECK(type == blink::WebMediaStreamSource::TypeAudio);
+ content::MediaStreamDependencyFactory::AddNativeAudioTrackToBlinkTrack(
+ track, *webkit_track, false);
+ }
}
-content::RemoteMediaStreamTrackObserver* FindTrackObserver(
- webrtc::MediaStreamTrackInterface* track,
- const ScopedVector<content::RemoteMediaStreamTrackObserver>& observers) {
- ScopedVector<content::RemoteMediaStreamTrackObserver>::const_iterator it =
+} // namespace
+
+// Base class used for mapping between webrtc and blink MediaStream tracks.
+// An instance of a RemoteMediaStreamTrackAdapter is stored in
+// RemoteMediaStreamImpl per remote audio and video track.
+class RemoteMediaStreamTrackAdapter {
+ public:
+ RemoteMediaStreamTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track,
+ const blink::WebMediaStreamTrack& webkit_track)
+ : webrtc_track_(webrtc_track),
+ webkit_track_(webkit_track) {
+ }
+
+ virtual ~RemoteMediaStreamTrackAdapter() {
+ }
+
+ webrtc::MediaStreamTrackInterface* observed_track() {
+ return webrtc_track_.get();
+ }
+
+ const blink::WebMediaStreamTrack& webkit_track() { return webkit_track_; }
+
+ private:
+ scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
+ blink::WebMediaStreamTrack webkit_track_;
+ bool sent_ended_message_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackAdapter);
+};
+
+static content::RemoteMediaStreamTrackAdapter* FindTrackObserver(
+ webrtc::MediaStreamTrackInterface* track,
+ const ScopedVector<content::RemoteMediaStreamTrackAdapter>& observers) {
+ ScopedVector<content::RemoteMediaStreamTrackAdapter>::const_iterator it =
observers.begin();
for (; it != observers.end(); ++it) {
- if ((*it)->observered_track() == track)
+ if ((*it)->observed_track() == track)
return *it;
}
return NULL;
}
-} // namespace anonymous
+// RemoteAudioMediaStreamTrackAdapter is responsible for listening on state
+// change notifications on a remote webrtc audio MediaStreamTracks and notify
+// WebKit.
+class RemoteAudioMediaStreamTrackAdapter
+ : public RemoteMediaStreamTrackAdapter,
+ public webrtc::ObserverInterface,
+ public base::NonThreadSafe {
+ public:
+ RemoteAudioMediaStreamTrackAdapter(
+ webrtc::MediaStreamTrackInterface* webrtc_track,
+ const blink::WebMediaStreamTrack& webkit_track);
+ virtual ~RemoteAudioMediaStreamTrackAdapter();
-namespace content {
+ private:
+ // webrtc::ObserverInterface implementation.
+ virtual void OnChanged() OVERRIDE;
+
+ webrtc::MediaStreamTrackInterface::TrackState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoteAudioMediaStreamTrackAdapter);
+};
-RemoteMediaStreamTrackObserver::RemoteMediaStreamTrackObserver(
+RemoteAudioMediaStreamTrackAdapter::RemoteAudioMediaStreamTrackAdapter(
webrtc::MediaStreamTrackInterface* webrtc_track,
const blink::WebMediaStreamTrack& webkit_track)
- : state_(webrtc_track->state()),
- webrtc_track_(webrtc_track),
- webkit_track_(webkit_track) {
- webrtc_track->RegisterObserver(this);
+ : RemoteMediaStreamTrackAdapter(webrtc_track, webkit_track),
+ state_(observed_track()->state()) {
+ observed_track()->RegisterObserver(this);
}
-RemoteMediaStreamTrackObserver::~RemoteMediaStreamTrackObserver() {
- webrtc_track_->UnregisterObserver(this);
+RemoteAudioMediaStreamTrackAdapter::~RemoteAudioMediaStreamTrackAdapter() {
+ observed_track()->UnregisterObserver(this);
}
-void RemoteMediaStreamTrackObserver::OnChanged() {
+void RemoteAudioMediaStreamTrackAdapter::OnChanged() {
DCHECK(CalledOnValidThread());
- webrtc::MediaStreamTrackInterface::TrackState state = webrtc_track_->state();
+ webrtc::MediaStreamTrackInterface::TrackState state =
+ observed_track()->state();
if (state == state_)
return;
@@ -100,11 +145,11 @@ void RemoteMediaStreamTrackObserver::OnChanged() {
// WebMediaStreamSource::ReadyState.
break;
case webrtc::MediaStreamTrackInterface::kLive:
- webkit_track_.source().setReadyState(
+ webkit_track().source().setReadyState(
blink::WebMediaStreamSource::ReadyStateLive);
break;
case webrtc::MediaStreamTrackInterface::kEnded:
- webkit_track_.source().setReadyState(
+ webkit_track().source().setReadyState(
blink::WebMediaStreamSource::ReadyStateEnded);
break;
default:
@@ -131,8 +176,8 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl(
InitializeWebkitTrack(audio_track, &webkit_audio_tracks[i],
blink::WebMediaStreamSource::TypeAudio);
audio_track_observers_.push_back(
- new RemoteMediaStreamTrackObserver(audio_track,
- webkit_audio_tracks[i]));
+ new RemoteAudioMediaStreamTrackAdapter(audio_track,
+ webkit_audio_tracks[i]));
}
// Initialize WebKit video tracks.
@@ -146,8 +191,8 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl(
InitializeWebkitTrack(video_track, &webkit_video_tracks[i],
blink::WebMediaStreamSource::TypeVideo);
video_track_observers_.push_back(
- new RemoteMediaStreamTrackObserver(video_track,
- webkit_video_tracks[i]));
+ new RemoteMediaStreamTrackAdapter(video_track,
+ webkit_video_tracks[i]));
}
webkit_stream_.initialize(base::UTF8ToUTF16(webrtc_stream->label()),
@@ -161,10 +206,10 @@ RemoteMediaStreamImpl::~RemoteMediaStreamImpl() {
void RemoteMediaStreamImpl::OnChanged() {
// Find removed audio tracks.
- ScopedVector<RemoteMediaStreamTrackObserver>::iterator audio_it =
+ ScopedVector<RemoteMediaStreamTrackAdapter>::iterator audio_it =
audio_track_observers_.begin();
while (audio_it != audio_track_observers_.end()) {
- std::string track_id = (*audio_it)->observered_track()->id();
+ std::string track_id = (*audio_it)->observed_track()->id();
if (webrtc_stream_->FindAudioTrack(track_id) == NULL) {
webkit_stream_.removeTrack((*audio_it)->webkit_track());
audio_it = audio_track_observers_.erase(audio_it);
@@ -174,10 +219,10 @@ void RemoteMediaStreamImpl::OnChanged() {
}
// Find removed video tracks.
- ScopedVector<RemoteMediaStreamTrackObserver>::iterator video_it =
+ ScopedVector<RemoteMediaStreamTrackAdapter>::iterator video_it =
video_track_observers_.begin();
while (video_it != video_track_observers_.end()) {
- std::string track_id = (*video_it)->observered_track()->id();
+ std::string track_id = (*video_it)->observed_track()->id();
if (webrtc_stream_->FindVideoTrack(track_id) == NULL) {
webkit_stream_.removeTrack((*video_it)->webkit_track());
video_it = video_track_observers_.erase(video_it);
@@ -196,7 +241,7 @@ void RemoteMediaStreamImpl::OnChanged() {
InitializeWebkitTrack(*it, &new_track,
blink::WebMediaStreamSource::TypeAudio);
audio_track_observers_.push_back(
- new RemoteMediaStreamTrackObserver(*it, new_track));
+ new RemoteAudioMediaStreamTrackAdapter(*it, new_track));
webkit_stream_.addTrack(new_track);
}
}
@@ -211,7 +256,7 @@ void RemoteMediaStreamImpl::OnChanged() {
InitializeWebkitTrack(*it, &new_track,
blink::WebMediaStreamSource::TypeVideo);
video_track_observers_.push_back(
- new RemoteMediaStreamTrackObserver(*it, new_track));
+ new RemoteMediaStreamTrackAdapter(*it, new_track));
webkit_stream_.addTrack(new_track);
}
}
diff --git a/content/renderer/media/remote_media_stream_impl.h b/content/renderer/media/remote_media_stream_impl.h
index 3263ed4..6b1554a 100644
--- a/content/renderer/media/remote_media_stream_impl.h
+++ b/content/renderer/media/remote_media_stream_impl.h
@@ -18,7 +18,7 @@
namespace content {
-class RemoteMediaStreamTrackObserver;
+class RemoteMediaStreamTrackAdapter;
// RemoteMediaStreamImpl serves as a container and glue between remote webrtc
// MediaStreams and WebKit MediaStreams. For each remote MediaStream received
@@ -39,8 +39,8 @@ class CONTENT_EXPORT RemoteMediaStreamImpl
virtual void OnChanged() OVERRIDE;
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_;
- ScopedVector<RemoteMediaStreamTrackObserver> audio_track_observers_;
- ScopedVector<RemoteMediaStreamTrackObserver> video_track_observers_;
+ ScopedVector<RemoteMediaStreamTrackAdapter> video_track_observers_;
+ ScopedVector<RemoteMediaStreamTrackAdapter> audio_track_observers_;
blink::WebMediaStream webkit_stream_;
DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamImpl);
diff --git a/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index c2b21dc..17cf4e8 100644
--- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -288,6 +288,7 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
return stream;
}
+ base::MessageLoop message_loop_;
scoped_ptr<MockWebRTCPeerConnectionHandlerClient> mock_client_;
scoped_ptr<MockMediaStreamDependencyFactory> mock_dependency_factory_;
scoped_ptr<NiceMock<MockPeerConnectionTracker> > mock_tracker_;
@@ -739,17 +740,24 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
pc_handler_->OnAddStream(remote_stream.get());
const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
- blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
- webkit_stream.audioTracks(audio_tracks);
- EXPECT_EQ(1u, audio_tracks.size());
+ {
+ // Test in a small scope so that |audio_tracks| don't hold on to destroyed
+ // source later.
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ webkit_stream.audioTracks(audio_tracks);
+ EXPECT_EQ(1u, audio_tracks.size());
+ }
// Remove the Webrtc audio track from the Webrtc MediaStream.
scoped_refptr<webrtc::AudioTrackInterface> webrtc_track =
remote_stream->GetAudioTracks()[0].get();
remote_stream->RemoveTrack(webrtc_track.get());
- blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1;
- webkit_stream.audioTracks(modified_audio_tracks1);
- EXPECT_EQ(0u, modified_audio_tracks1.size());
+
+ {
+ blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1;
+ webkit_stream.audioTracks(modified_audio_tracks1);
+ EXPECT_EQ(0u, modified_audio_tracks1.size());
+ }
// Add the WebRtc audio track again.
remote_stream->AddTrack(webrtc_track.get());
@@ -769,17 +777,23 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
pc_handler_->OnAddStream(remote_stream.get());
const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
- webkit_stream.videoTracks(video_tracks);
- EXPECT_EQ(1u, video_tracks.size());
+ {
+ // Test in a small scope so that |video_tracks| don't hold on to destroyed
+ // source later.
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ webkit_stream.videoTracks(video_tracks);
+ EXPECT_EQ(1u, video_tracks.size());
+ }
// Remove the Webrtc video track from the Webrtc MediaStream.
scoped_refptr<webrtc::VideoTrackInterface> webrtc_track =
remote_stream->GetVideoTracks()[0].get();
remote_stream->RemoveTrack(webrtc_track.get());
- blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1;
- webkit_stream.videoTracks(modified_video_tracks1);
- EXPECT_EQ(0u, modified_video_tracks1.size());
+ {
+ blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1;
+ webkit_stream.videoTracks(modified_video_tracks1);
+ EXPECT_EQ(0u, modified_video_tracks1.size());
+ }
// Add the WebRtc video track again.
remote_stream->AddTrack(webrtc_track.get());
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
new file mode 100644
index 0000000..50468af
--- /dev/null
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -0,0 +1,157 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc/media_stream_remote_video_source.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "content/renderer/media/native_handle_impl.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_util.h"
+#include "third_party/libjingle/source/talk/media/base/videoframe.h"
+
+namespace content {
+
+MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource(
+ webrtc::VideoTrackInterface* remote_track)
+ : MediaStreamVideoSource(NULL),
+ message_loop_proxy_(base::MessageLoopProxy::current()),
+ remote_track_(remote_track),
+ last_state_(remote_track_->state()),
+ first_frame_received_(false) {
+ remote_track_->AddRenderer(this);
+ remote_track_->RegisterObserver(this);
+}
+
+MediaStreamRemoteVideoSource::~MediaStreamRemoteVideoSource() {
+ StopSourceImpl();
+}
+
+void MediaStreamRemoteVideoSource::GetCurrentSupportedFormats(
+ int max_requested_width,
+ int max_requested_height) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ if (format_.IsValid()) {
+ media::VideoCaptureFormats formats;
+ formats.push_back(format_);
+ OnSupportedFormats(formats);
+ }
+}
+
+void MediaStreamRemoteVideoSource::StartSourceImpl(
+ const media::VideoCaptureParams& params) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ OnStartDone(true);
+}
+
+void MediaStreamRemoteVideoSource::StopSourceImpl() {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ remote_track_->RemoveRenderer(this);
+ remote_track_->UnregisterObserver(this);
+}
+
+webrtc::VideoSourceInterface* MediaStreamRemoteVideoSource::GetAdapter() {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ return remote_track_->GetSource();
+}
+
+void MediaStreamRemoteVideoSource::SetSize(int width, int height) {
+}
+
+void MediaStreamRemoteVideoSource::RenderFrame(
+ const cricket::VideoFrame* frame) {
+ base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(
+ frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec);
+
+ scoped_refptr<media::VideoFrame> video_frame;
+ if (frame->GetNativeHandle() != NULL) {
+ NativeHandleImpl* handle =
+ static_cast<NativeHandleImpl*>(frame->GetNativeHandle());
+ video_frame = static_cast<media::VideoFrame*>(handle->GetHandle());
+ video_frame->SetTimestamp(timestamp);
+ } else {
+ gfx::Size size(frame->GetWidth(), frame->GetHeight());
+ video_frame = frame_pool_.CreateFrame(
+ media::VideoFrame::I420, size, gfx::Rect(size), size, timestamp);
+
+ // Non-square pixels are unsupported.
+ DCHECK_EQ(frame->GetPixelWidth(), 1u);
+ DCHECK_EQ(frame->GetPixelHeight(), 1u);
+
+ int y_rows = frame->GetHeight();
+ int uv_rows = frame->GetChromaHeight();
+ CopyYPlane(
+ frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get());
+ CopyUPlane(
+ frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get());
+ CopyVPlane(
+ frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get());
+ }
+
+ if (!first_frame_received_) {
+ first_frame_received_ = true;
+ media::VideoPixelFormat pixel_format = (
+ video_frame->format() == media::VideoFrame::I420) ?
+ media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_TEXTURE;
+ media::VideoCaptureFormat format(
+ gfx::Size(video_frame->natural_size().width(),
+ video_frame->natural_size().height()),
+ MediaStreamVideoSource::kDefaultFrameRate,
+ pixel_format);
+ message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaStreamRemoteVideoSource::FrameFormatOnMainThread,
+ AsWeakPtr(), format));
+ }
+
+ // TODO(perkj): Consider delivering the frame on whatever thread the frame is
+ // delivered on once crbug/335327 is fixed.
+ message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaStreamRemoteVideoSource::DoRenderFrameOnMainThread,
+ AsWeakPtr(), video_frame));
+}
+
+void MediaStreamRemoteVideoSource::OnChanged() {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ webrtc::MediaStreamTrackInterface::TrackState state = remote_track_->state();
+ if (state != last_state_) {
+ last_state_ = state;
+ switch (state) {
+ case webrtc::MediaStreamTrackInterface::kInitializing:
+ // Ignore the kInitializing state since there is no match in
+ // WebMediaStreamSource::ReadyState.
+ break;
+ case webrtc::MediaStreamTrackInterface::kLive:
+ SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
+ break;
+ case webrtc::MediaStreamTrackInterface::kEnded:
+ SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+void MediaStreamRemoteVideoSource::FrameFormatOnMainThread(
+ const media::VideoCaptureFormat& format) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ format_ = format;
+ if (state() == RETRIEVING_CAPABILITIES) {
+ media::VideoCaptureFormats formats;
+ formats.push_back(format);
+ OnSupportedFormats(formats);
+ }
+}
+
+void MediaStreamRemoteVideoSource::DoRenderFrameOnMainThread(
+ scoped_refptr<media::VideoFrame> video_frame) {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ if (state() == STARTED)
+ DeliverVideoFrame(video_frame);
+}
+
+} // namespace content
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.h b/content/renderer/media/webrtc/media_stream_remote_video_source.h
new file mode 100644
index 0000000..2d5be61
--- /dev/null
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source.h
@@ -0,0 +1,74 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_REMOTE_VIDEO_SOURCE_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_REMOTE_VIDEO_SOURCE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "content/renderer/media/media_stream_video_source.h"
+#include "media/base/video_frame_pool.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+
+namespace content {
+
+// MediaStreamRemoteVideoSource implements the MediaStreamVideoSource interface
+// for video tracks received on a PeerConnection. The purpose of the class is
+// to make sure there is no difference between a video track where the source is
+// a local source and a video track where the source is a remote video track.
+class CONTENT_EXPORT MediaStreamRemoteVideoSource
+ : public MediaStreamVideoSource,
+ NON_EXPORTED_BASE(public webrtc::VideoRendererInterface),
+ NON_EXPORTED_BASE(public webrtc::ObserverInterface),
+ public base::SupportsWeakPtr<MediaStreamRemoteVideoSource> {
+ public:
+ explicit MediaStreamRemoteVideoSource(
+ webrtc::VideoTrackInterface* remote_track);
+ virtual ~MediaStreamRemoteVideoSource();
+
+ protected:
+ // Implements MediaStreamVideoSource.
+ virtual void GetCurrentSupportedFormats(
+ int max_requested_width,
+ int max_requested_height) OVERRIDE;
+
+ virtual void StartSourceImpl(
+ const media::VideoCaptureParams& params) OVERRIDE;
+
+ virtual void StopSourceImpl() OVERRIDE;
+
+ virtual webrtc::VideoSourceInterface* GetAdapter() OVERRIDE;
+
+ // Implements webrtc::VideoRendererInterface used for receiving video frames
+ // from the PeerConnection video track. May be called on
+ // a different thread.
+ virtual void SetSize(int width, int height) OVERRIDE;
+ virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE;
+
+ // webrtc::ObserverInterface implementation.
+ virtual void OnChanged() OVERRIDE;
+
+ private:
+ void FrameFormatOnMainThread(const media::VideoCaptureFormat& format);
+ void DoRenderFrameOnMainThread(scoped_refptr<media::VideoFrame> video_frame);
+
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+ scoped_refptr<webrtc::VideoTrackInterface> remote_track_;
+ webrtc::MediaStreamTrackInterface::TrackState last_state_;
+
+ // |first_frame_received_| and |frame_pool_| are only accessed on whatever
+ // thread webrtc::VideoRendererInterface::RenderFrame is called on.
+ bool first_frame_received_;
+ media::VideoFramePool frame_pool_;
+
+ // |format_| is the format currently received by this source.
+ media::VideoCaptureFormat format_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamRemoteVideoSource);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_REMOTE_VIDEO_SOURCE_H_
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
new file mode 100644
index 0000000..068320f
--- /dev/null
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/renderer/media_stream_video_sink.h"
+#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+#include "content/renderer/media/webrtc/media_stream_remote_video_source.h"
+#include "media/base/video_frame.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
+
+namespace content {
+
+class MockVideoSink : public MediaStreamVideoSink {
+ public:
+ MockVideoSink()
+ : number_of_frames_(0),
+ state_(blink::WebMediaStreamSource::ReadyStateLive) {
+ }
+
+ virtual void OnVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame) OVERRIDE {
+ ++number_of_frames_;
+ }
+
+ virtual void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) OVERRIDE {
+ state_ = state;
+ }
+
+ int number_of_frames() const { return number_of_frames_; }
+ blink::WebMediaStreamSource::ReadyState state() const { return state_; }
+
+ private:
+ int number_of_frames_;
+ blink::WebMediaStreamSource::ReadyState state_;
+};
+
+class MediaStreamRemoteVideoSourceUnderTest
+ : public MediaStreamRemoteVideoSource {
+ public:
+ MediaStreamRemoteVideoSourceUnderTest(webrtc::VideoTrackInterface* track)
+ : MediaStreamRemoteVideoSource(track) {
+ }
+ using MediaStreamRemoteVideoSource::RenderFrame;
+};
+
+class MediaStreamRemoteVideoSourceTest
+ : public ::testing::Test {
+ public:
+ MediaStreamRemoteVideoSourceTest()
+ : mock_factory_(new MockMediaStreamDependencyFactory()),
+ webrtc_video_track_(
+ mock_factory_->CreateLocalVideoTrack(
+ "test",
+ static_cast<cricket::VideoCapturer*>(NULL))),
+ remote_source_(
+ new MediaStreamRemoteVideoSourceUnderTest(webrtc_video_track_)),
+ number_of_successful_constraints_applied_(0),
+ number_of_failed_constraints_applied_(0) {
+ webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
+ blink::WebMediaStreamSource::TypeVideo,
+ base::UTF8ToUTF16("dummy_source_name"));
+ webkit_source_.setExtraData(remote_source_);
+ }
+ virtual ~MediaStreamRemoteVideoSourceTest() {}
+
+ MediaStreamRemoteVideoSourceUnderTest* source() {
+ return remote_source_;
+ }
+
+ MediaStreamVideoTrack* CreateTrack() {
+ bool enabled = true;
+ blink::WebMediaConstraints constraints;
+ constraints.initialize();
+ MediaStreamDependencyFactory* factory = NULL;
+ return new MediaStreamVideoTrack(
+ source(),
+ constraints,
+ base::Bind(
+ &MediaStreamRemoteVideoSourceTest::OnConstraintsApplied,
+ base::Unretained(this)),
+ enabled, factory);
+ }
+
+ int NumberOfSuccessConstraintsCallbacks() const {
+ return number_of_successful_constraints_applied_;
+ }
+
+ int NumberOfFailedConstraintsCallbacks() const {
+ return number_of_failed_constraints_applied_;
+ }
+
+ void StopWebRtcTrack() {
+ static_cast<MockWebRtcVideoTrack*>(webrtc_video_track_.get())->set_state(
+ webrtc::MediaStreamTrackInterface::kEnded);
+ }
+
+ base::MessageLoop* message_loop() { return &message_loop_; }
+
+ const blink::WebMediaStreamSource& webkit_source() const {
+ return webkit_source_;
+ }
+
+ private:
+ void OnConstraintsApplied(MediaStreamSource* source, bool success) {
+ ASSERT_EQ(source, remote_source_);
+ if (success)
+ ++number_of_successful_constraints_applied_;
+ else
+ ++number_of_failed_constraints_applied_;
+ }
+
+ base::MessageLoop message_loop_;
+ scoped_ptr<MockMediaStreamDependencyFactory> mock_factory_;
+ scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track_;
+ // |remote_source_| is owned by |webkit_source_|.
+ MediaStreamRemoteVideoSourceUnderTest* remote_source_;
+ blink::WebMediaStreamSource webkit_source_;
+ int number_of_successful_constraints_applied_;
+ int number_of_failed_constraints_applied_;
+};
+
+TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
+ scoped_ptr<MediaStreamVideoTrack> track(CreateTrack());
+ EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
+
+ MockVideoSink sink;
+ track->AddSink(&sink);
+
+ cricket::WebRtcVideoFrame webrtc_frame;
+ webrtc_frame.InitToBlack(320, 240, 1, 1, 0, 1);
+ source()->RenderFrame(&webrtc_frame);
+ message_loop()->RunUntilIdle();
+
+ EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
+ EXPECT_EQ(1, sink.number_of_frames());
+ track->RemoveSink(&sink);
+}
+
+TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
+ scoped_ptr<MediaStreamVideoTrack> track(CreateTrack());
+
+ MockVideoSink sink;
+ track->AddSink(&sink);
+
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink.state());
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
+ webkit_source().readyState());
+ StopWebRtcTrack();
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
+ webkit_source().readyState());
+ EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink.state());
+
+ track->RemoveSink(&sink);
+}
+
+} // namespace content
diff --git a/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc b/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc
deleted file mode 100644
index 587ecfe..0000000
--- a/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "content/renderer/media/native_handle_impl.h"
-#include "media/base/video_frame.h"
-#include "media/base/video_util.h"
-#include "third_party/libjingle/source/talk/media/base/videoframe.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
-#include "ui/gfx/size.h"
-
-using media::CopyYPlane;
-using media::CopyUPlane;
-using media::CopyVPlane;
-
-namespace content {
-
-WebRtcVideoSinkAdapter::WebRtcVideoSinkAdapter(
- webrtc::VideoTrackInterface* video_track,
- MediaStreamVideoSink* sink)
- : message_loop_proxy_(base::MessageLoopProxy::current()),
- sink_(sink),
- video_track_(video_track),
- state_(video_track->state()),
- track_enabled_(video_track->enabled()) {
- DCHECK(sink);
- video_track_->AddRenderer(this);
- video_track_->RegisterObserver(this);
- DVLOG(1) << "WebRtcVideoSinkAdapter";
-}
-
-WebRtcVideoSinkAdapter::~WebRtcVideoSinkAdapter() {
- video_track_->RemoveRenderer(this);
- video_track_->UnregisterObserver(this);
- DVLOG(1) << "~WebRtcVideoSinkAdapter";
-}
-
-void WebRtcVideoSinkAdapter::SetSize(int width, int height) {
-}
-
-void WebRtcVideoSinkAdapter::RenderFrame(const cricket::VideoFrame* frame) {
- base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(
- frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec);
-
- scoped_refptr<media::VideoFrame> video_frame;
- if (frame->GetNativeHandle() != NULL) {
- NativeHandleImpl* handle =
- static_cast<NativeHandleImpl*>(frame->GetNativeHandle());
- video_frame = static_cast<media::VideoFrame*>(handle->GetHandle());
- video_frame->SetTimestamp(timestamp);
- } else {
- gfx::Size size(frame->GetWidth(), frame->GetHeight());
- video_frame = media::VideoFrame::CreateFrame(
- media::VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
-
- // Aspect ratio unsupported; DCHECK when there are non-square pixels.
- DCHECK_EQ(frame->GetPixelWidth(), 1u);
- DCHECK_EQ(frame->GetPixelHeight(), 1u);
-
- int y_rows = frame->GetHeight();
- int uv_rows = frame->GetChromaHeight();
- CopyYPlane(
- frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get());
- CopyUPlane(
- frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get());
- CopyVPlane(
- frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get());
- }
-
- message_loop_proxy_->PostTask(
- FROM_HERE, base::Bind(&WebRtcVideoSinkAdapter::DoRenderFrameOnMainThread,
- AsWeakPtr(), video_frame));
-}
-
-void WebRtcVideoSinkAdapter::OnChanged() {
- DCHECK(message_loop_proxy_->BelongsToCurrentThread());
-
- // TODO(perkj): OnChanged belongs to the base class of WebRtcVideoSinkAdapter
- // common for both webrtc audio and video.
- webrtc::MediaStreamTrackInterface::TrackState state = video_track_->state();
- if (state != state_) {
- state_ = state;
- switch (state) {
- case webrtc::MediaStreamTrackInterface::kInitializing:
- // Ignore the kInitializing state since there is no match in
- // WebMediaStreamSource::ReadyState.
- break;
- case webrtc::MediaStreamTrackInterface::kLive:
- sink_->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive);
- break;
- case webrtc::MediaStreamTrackInterface::kEnded:
- sink_->OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyStateEnded);
- break;
- default:
- NOTREACHED();
- break;
- }
- }
- if (track_enabled_ != video_track_->enabled()) {
- track_enabled_ = video_track_->enabled();
- sink_->OnEnabledChanged(track_enabled_);
- }
-}
-
-void WebRtcVideoSinkAdapter::DoRenderFrameOnMainThread(
- scoped_refptr<media::VideoFrame> video_frame) {
- DCHECK(message_loop_proxy_->BelongsToCurrentThread());
- sink_->OnVideoFrame(video_frame);
-}
-
-} // namespace content
diff --git a/content/renderer/media/webrtc/webrtc_video_sink_adapter.h b/content/renderer/media/webrtc/webrtc_video_sink_adapter.h
deleted file mode 100644
index 2f75a95..0000000
--- a/content/renderer/media/webrtc/webrtc_video_sink_adapter.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_
-
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "content/public/renderer/media_stream_video_sink.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace content {
-
-// WebRtcVideoSinkAdapter acts as the middle man between a
-// webrtc:::VideoTrackInterface and a content::MediaStreamVideoSink.
-// It is responsible for translating video data from a libjingle video type
-// to a chrome video type.
-class CONTENT_EXPORT WebRtcVideoSinkAdapter
- : NON_EXPORTED_BASE(public webrtc::VideoRendererInterface),
- NON_EXPORTED_BASE(public webrtc::ObserverInterface),
- public base::SupportsWeakPtr<WebRtcVideoSinkAdapter> {
- public:
- WebRtcVideoSinkAdapter(webrtc::VideoTrackInterface* video_track,
- MediaStreamVideoSink* sink);
- virtual ~WebRtcVideoSinkAdapter();
-
- MediaStreamVideoSink* sink() const { return sink_; }
-
- protected:
- // webrtc::VideoRendererInterface implementation. May be called on
- // a different thread.
- virtual void SetSize(int width, int height) OVERRIDE;
- virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE;
-
- // webrtc::ObserverInterface implementation.
- // TODO(perkj): OnChanged should be implemented on a common base class used
- // for both WebRtc Audio and Video tracks.
- virtual void OnChanged() OVERRIDE;
-
- private:
- void DoRenderFrameOnMainThread(scoped_refptr<media::VideoFrame> video_frame);
-
- scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
- MediaStreamVideoSink* sink_;
- // The video track the renderer is connected to.
- scoped_refptr<webrtc::VideoTrackInterface> video_track_;
- webrtc::MediaStreamTrackInterface::TrackState state_;
- bool track_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(WebRtcVideoSinkAdapter);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_