diff options
author | vrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-09 21:16:52 +0000 |
---|---|---|
committer | vrk@chromium.org <vrk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-09 21:16:52 +0000 |
commit | c6d743ef45ab10d0e014dd07b81de10a9aaa3e0c (patch) | |
tree | 9b3f3ea6407dd07ae3bb1cdbbed129e3f528283b /content/renderer/media | |
parent | 23bb07d9ff721a6a716294f2d54b5af3493557c2 (diff) | |
download | chromium_src-c6d743ef45ab10d0e014dd07b81de10a9aaa3e0c.zip chromium_src-c6d743ef45ab10d0e014dd07b81de10a9aaa3e0c.tar.gz chromium_src-c6d743ef45ab10d0e014dd07b81de10a9aaa3e0c.tar.bz2 |
Revert 262050 "Implement a source for remote video tracks."
> Implement a source for remote video tracks.
> 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.
>
> BUG=334243
>
> Review URL: https://codereview.chromium.org/201583003
This caused remote video to appear unexpectedly zoomed and cropped.
BUG=334243,361770
TBR=perkj@chromium.org
Review URL: https://codereview.chromium.org/231963002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262819 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer/media')
17 files changed, 365 insertions, 566 deletions
diff --git a/content/renderer/media/media_stream_center.cc b/content/renderer/media/media_stream_center.cc index e568567..dea0f92a 100644 --- a/content/renderer/media/media_stream_center.cc +++ b/content/renderer/media/media_stream_center.cc @@ -52,7 +52,12 @@ void CreateNativeVideoMediaStreamTrack( DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo); MediaStreamVideoSource* native_source = MediaStreamVideoSource::GetVideoSource(source); - DCHECK(native_source); + if (!native_source) { + // TODO(perkj): Implement support for sources from + // remote MediaStreams. + NOTIMPLEMENTED(); + return; + } 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 70f3d06..fef5308 100644 --- a/content/renderer/media/media_stream_dependency_factory.cc +++ b/content/renderer/media/media_stream_dependency_factory.cc @@ -678,20 +678,24 @@ MediaStreamDependencyFactory::CreateAudioCapturer( GetWebRtcAudioDevice()); } -void MediaStreamDependencyFactory::AddNativeAudioTrackToBlinkTrack( +void MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack( 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; - DVLOG(1) << "AddNativeTrackToBlinkTrack() audio"; - track.setExtraData( - new MediaStreamTrack( - static_cast<webrtc::AudioTrackInterface*>(native_track), - is_local_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)); + } } bool MediaStreamDependencyFactory::OnControlMessageReceived( diff --git a/content/renderer/media/media_stream_dependency_factory.h b/content/renderer/media/media_stream_dependency_factory.h index 5986abb..accac97 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 AddNativeAudioTrackToBlinkTrack( + static void AddNativeTrackToBlinkTrack( 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 51da6bb..6091726 100644 --- a/content/renderer/media/media_stream_video_source.cc +++ b/content/renderer/media/media_stream_video_source.cc @@ -308,6 +308,7 @@ 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 af33b4e..b080a47 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. - virtual webrtc::VideoSourceInterface* GetAdapter(); + 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() const { return state_; } + State state() { 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 8d4b83d..3cf98cd 100644 --- a/content/renderer/media/media_stream_video_track.cc +++ b/content/renderer/media/media_stream_video_track.cc @@ -5,6 +5,7 @@ #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 { @@ -41,12 +42,18 @@ MediaStreamVideoTrack::MediaStreamVideoTrack( enabled_(enabled), source_(source), factory_(factory) { - source->AddTrack(this, constraints, callback); + // 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); } MediaStreamVideoTrack::~MediaStreamVideoTrack() { DCHECK(sinks_.empty()); - source_->RemoveTrack(this); + // 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); } void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) { @@ -109,4 +116,43 @@ 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 07307ae..16c0a91 100644 --- a/content/renderer/media/media_stream_video_track.h +++ b/content/renderer/media/media_stream_video_track.h @@ -22,6 +22,7 @@ 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 @@ -86,6 +87,26 @@ 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 d07cb3a..1441d32 100644 --- a/content/renderer/media/mock_media_stream_dependency_factory.cc +++ b/content/renderer/media/mock_media_stream_dependency_factory.cc @@ -283,64 +283,60 @@ int MockVideoSource::GetFrameNum() const { return static_cast<MockRtcVideoCapturer*>(capturer_.get())->GetFrameNum(); } -MockWebRtcVideoTrack::MockWebRtcVideoTrack( - std::string id, - webrtc::VideoSourceInterface* source) +MockLocalVideoTrack::MockLocalVideoTrack(std::string id, + webrtc::VideoSourceInterface* source) : enabled_(false), id_(id), state_(MediaStreamTrackInterface::kLive), source_(source), - observer_(NULL), - renderer_(NULL) { + observer_(NULL) { } -MockWebRtcVideoTrack::~MockWebRtcVideoTrack() {} +MockLocalVideoTrack::~MockLocalVideoTrack() {} -void MockWebRtcVideoTrack::AddRenderer(VideoRendererInterface* renderer) { - DCHECK(!renderer_); - renderer_ = renderer; +void MockLocalVideoTrack::AddRenderer(VideoRendererInterface* renderer) { + NOTIMPLEMENTED(); } -void MockWebRtcVideoTrack::RemoveRenderer(VideoRendererInterface* renderer) { - DCHECK_EQ(renderer_, renderer); - renderer_ = NULL; +void MockLocalVideoTrack::RemoveRenderer(VideoRendererInterface* renderer) { + NOTIMPLEMENTED(); } -std::string MockWebRtcVideoTrack::kind() const { +std::string MockLocalVideoTrack::kind() const { NOTIMPLEMENTED(); return std::string(); } -std::string MockWebRtcVideoTrack::id() const { return id_; } +std::string MockLocalVideoTrack::id() const { return id_; } -bool MockWebRtcVideoTrack::enabled() const { return enabled_; } +bool MockLocalVideoTrack::enabled() const { return enabled_; } -MockWebRtcVideoTrack::TrackState MockWebRtcVideoTrack::state() const { +MockLocalVideoTrack::TrackState MockLocalVideoTrack::state() const { return state_; } -bool MockWebRtcVideoTrack::set_enabled(bool enable) { +bool MockLocalVideoTrack::set_enabled(bool enable) { enabled_ = enable; return true; } -bool MockWebRtcVideoTrack::set_state(TrackState new_state) { +bool MockLocalVideoTrack::set_state(TrackState new_state) { state_ = new_state; if (observer_) observer_->OnChanged(); return true; } -void MockWebRtcVideoTrack::RegisterObserver(ObserverInterface* observer) { +void MockLocalVideoTrack::RegisterObserver(ObserverInterface* observer) { observer_ = observer; } -void MockWebRtcVideoTrack::UnregisterObserver(ObserverInterface* observer) { +void MockLocalVideoTrack::UnregisterObserver(ObserverInterface* observer) { DCHECK(observer_ == observer); observer_ = NULL; } -VideoSourceInterface* MockWebRtcVideoTrack::GetSource() const { +VideoSourceInterface* MockLocalVideoTrack::GetSource() const { return source_.get(); } @@ -484,7 +480,7 @@ MockMediaStreamDependencyFactory::CreateLocalVideoTrack( const std::string& id, webrtc::VideoSourceInterface* source) { scoped_refptr<webrtc::VideoTrackInterface> track( - new talk_base::RefCountedObject<MockWebRtcVideoTrack>( + new talk_base::RefCountedObject<MockLocalVideoTrack>( id, source)); return track; } @@ -497,8 +493,7 @@ MockMediaStreamDependencyFactory::CreateLocalVideoTrack( new talk_base::RefCountedObject<MockVideoSource>(); source->SetVideoCapturer(capturer); - return - new talk_base::RefCountedObject<MockWebRtcVideoTrack>(id, source.get()); + return new talk_base::RefCountedObject<MockLocalVideoTrack>(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 a2cce87..05cd5c7 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 MockWebRtcVideoTrack : public webrtc::VideoTrackInterface { +class MockLocalVideoTrack : public webrtc::VideoTrackInterface { public: - MockWebRtcVideoTrack(std::string id, + MockLocalVideoTrack(std::string id, webrtc::VideoSourceInterface* source); virtual void AddRenderer(webrtc::VideoRendererInterface* renderer) OVERRIDE; virtual void RemoveRenderer( @@ -122,7 +122,7 @@ class MockWebRtcVideoTrack : public webrtc::VideoTrackInterface { virtual webrtc::VideoSourceInterface* GetSource() const OVERRIDE; protected: - virtual ~MockWebRtcVideoTrack(); + virtual ~MockLocalVideoTrack(); private: bool enabled_; @@ -130,7 +130,6 @@ class MockWebRtcVideoTrack : 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 1510607b..66bdb60 100644 --- a/content/renderer/media/remote_media_stream_impl.cc +++ b/content/renderer/media/remote_media_stream_impl.cc @@ -10,131 +10,86 @@ #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 { -namespace { - -void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track, - blink::WebMediaStreamTrack* webkit_track, - blink::WebMediaStreamSource::Type type) { - blink::WebMediaStreamSource webkit_source; - blink::WebString webkit_track_id(base::UTF8ToUTF16(track->id())); - - webkit_source.initialize(webkit_track_id, type, webkit_track_id); - webkit_track->initialize(webkit_track_id, webkit_source); - - 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); - } -} - -} // 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 { +// 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: - RemoteMediaStreamTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track, - const blink::WebMediaStreamTrack& webkit_track) - : webrtc_track_(webrtc_track), - webkit_track_(webkit_track) { - } - - virtual ~RemoteMediaStreamTrackAdapter() { - } + RemoteMediaStreamTrackObserver( + webrtc::MediaStreamTrackInterface* webrtc_track, + const blink::WebMediaStreamTrack& webkit_track); + virtual ~RemoteMediaStreamTrackObserver(); - webrtc::MediaStreamTrackInterface* observed_track() { + 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_; - bool sent_ended_message_; - DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackAdapter); + DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver); }; -static content::RemoteMediaStreamTrackAdapter* FindTrackObserver( - webrtc::MediaStreamTrackInterface* track, - const ScopedVector<content::RemoteMediaStreamTrackAdapter>& observers) { - ScopedVector<content::RemoteMediaStreamTrackAdapter>::const_iterator it = +} // namespace content + +namespace { + +void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track, + blink::WebMediaStreamTrack* webkit_track, + blink::WebMediaStreamSource::Type type) { + blink::WebMediaStreamSource webkit_source; + blink::WebString webkit_track_id(base::UTF8ToUTF16(track->id())); + + 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); +} + +content::RemoteMediaStreamTrackObserver* FindTrackObserver( + webrtc::MediaStreamTrackInterface* track, + const ScopedVector<content::RemoteMediaStreamTrackObserver>& observers) { + ScopedVector<content::RemoteMediaStreamTrackObserver>::const_iterator it = observers.begin(); for (; it != observers.end(); ++it) { - if ((*it)->observed_track() == track) + if ((*it)->observered_track() == track) return *it; } return NULL; } -// 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(); - - private: - // webrtc::ObserverInterface implementation. - virtual void OnChanged() OVERRIDE; - - webrtc::MediaStreamTrackInterface::TrackState state_; +} // namespace anonymous - DISALLOW_COPY_AND_ASSIGN(RemoteAudioMediaStreamTrackAdapter); -}; +namespace content { -RemoteAudioMediaStreamTrackAdapter::RemoteAudioMediaStreamTrackAdapter( +RemoteMediaStreamTrackObserver::RemoteMediaStreamTrackObserver( webrtc::MediaStreamTrackInterface* webrtc_track, const blink::WebMediaStreamTrack& webkit_track) - : RemoteMediaStreamTrackAdapter(webrtc_track, webkit_track), - state_(observed_track()->state()) { - observed_track()->RegisterObserver(this); + : state_(webrtc_track->state()), + webrtc_track_(webrtc_track), + webkit_track_(webkit_track) { + webrtc_track->RegisterObserver(this); } -RemoteAudioMediaStreamTrackAdapter::~RemoteAudioMediaStreamTrackAdapter() { - observed_track()->UnregisterObserver(this); +RemoteMediaStreamTrackObserver::~RemoteMediaStreamTrackObserver() { + webrtc_track_->UnregisterObserver(this); } -void RemoteAudioMediaStreamTrackAdapter::OnChanged() { +void RemoteMediaStreamTrackObserver::OnChanged() { DCHECK(CalledOnValidThread()); - webrtc::MediaStreamTrackInterface::TrackState state = - observed_track()->state(); + webrtc::MediaStreamTrackInterface::TrackState state = webrtc_track_->state(); if (state == state_) return; @@ -145,11 +100,11 @@ void RemoteAudioMediaStreamTrackAdapter::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: @@ -176,8 +131,8 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl( InitializeWebkitTrack(audio_track, &webkit_audio_tracks[i], blink::WebMediaStreamSource::TypeAudio); audio_track_observers_.push_back( - new RemoteAudioMediaStreamTrackAdapter(audio_track, - webkit_audio_tracks[i])); + new RemoteMediaStreamTrackObserver(audio_track, + webkit_audio_tracks[i])); } // Initialize WebKit video tracks. @@ -191,8 +146,8 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl( InitializeWebkitTrack(video_track, &webkit_video_tracks[i], blink::WebMediaStreamSource::TypeVideo); video_track_observers_.push_back( - new RemoteMediaStreamTrackAdapter(video_track, - webkit_video_tracks[i])); + new RemoteMediaStreamTrackObserver(video_track, + webkit_video_tracks[i])); } webkit_stream_.initialize(base::UTF8ToUTF16(webrtc_stream->label()), @@ -206,10 +161,10 @@ RemoteMediaStreamImpl::~RemoteMediaStreamImpl() { void RemoteMediaStreamImpl::OnChanged() { // Find removed audio tracks. - ScopedVector<RemoteMediaStreamTrackAdapter>::iterator audio_it = + ScopedVector<RemoteMediaStreamTrackObserver>::iterator audio_it = audio_track_observers_.begin(); while (audio_it != audio_track_observers_.end()) { - std::string track_id = (*audio_it)->observed_track()->id(); + std::string track_id = (*audio_it)->observered_track()->id(); if (webrtc_stream_->FindAudioTrack(track_id) == NULL) { webkit_stream_.removeTrack((*audio_it)->webkit_track()); audio_it = audio_track_observers_.erase(audio_it); @@ -219,10 +174,10 @@ void RemoteMediaStreamImpl::OnChanged() { } // Find removed video tracks. - ScopedVector<RemoteMediaStreamTrackAdapter>::iterator video_it = + ScopedVector<RemoteMediaStreamTrackObserver>::iterator video_it = video_track_observers_.begin(); while (video_it != video_track_observers_.end()) { - std::string track_id = (*video_it)->observed_track()->id(); + std::string track_id = (*video_it)->observered_track()->id(); if (webrtc_stream_->FindVideoTrack(track_id) == NULL) { webkit_stream_.removeTrack((*video_it)->webkit_track()); video_it = video_track_observers_.erase(video_it); @@ -241,7 +196,7 @@ void RemoteMediaStreamImpl::OnChanged() { InitializeWebkitTrack(*it, &new_track, blink::WebMediaStreamSource::TypeAudio); audio_track_observers_.push_back( - new RemoteAudioMediaStreamTrackAdapter(*it, new_track)); + new RemoteMediaStreamTrackObserver(*it, new_track)); webkit_stream_.addTrack(new_track); } } @@ -256,7 +211,7 @@ void RemoteMediaStreamImpl::OnChanged() { InitializeWebkitTrack(*it, &new_track, blink::WebMediaStreamSource::TypeVideo); video_track_observers_.push_back( - new RemoteMediaStreamTrackAdapter(*it, new_track)); + new RemoteMediaStreamTrackObserver(*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 6b1554a..3263ed4 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 RemoteMediaStreamTrackAdapter; +class RemoteMediaStreamTrackObserver; // 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<RemoteMediaStreamTrackAdapter> video_track_observers_; - ScopedVector<RemoteMediaStreamTrackAdapter> audio_track_observers_; + ScopedVector<RemoteMediaStreamTrackObserver> audio_track_observers_; + ScopedVector<RemoteMediaStreamTrackObserver> video_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 17cf4e8..c2b21dc 100644 --- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc +++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc @@ -288,7 +288,6 @@ 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_; @@ -740,24 +739,17 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) { pc_handler_->OnAddStream(remote_stream.get()); const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream(); - { - // 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()); - } + 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()); @@ -777,23 +769,17 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) { pc_handler_->OnAddStream(remote_stream.get()); const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream(); - { - // 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()); - } + 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 deleted file mode 100644 index 50468af..0000000 --- a/content/renderer/media/webrtc/media_stream_remote_video_source.cc +++ /dev/null @@ -1,157 +0,0 @@ -// 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 deleted file mode 100644 index 2d5be61..0000000 --- a/content/renderer/media/webrtc/media_stream_remote_video_source.h +++ /dev/null @@ -1,74 +0,0 @@ -// 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 deleted file mode 100644 index 068320f..0000000 --- a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc +++ /dev/null @@ -1,160 +0,0 @@ -// 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 new file mode 100644 index 0000000..587ecfe --- /dev/null +++ b/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc @@ -0,0 +1,118 @@ +// 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 new file mode 100644 index 0000000..2f75a95 --- /dev/null +++ b/content/renderer/media/webrtc/webrtc_video_sink_adapter.h @@ -0,0 +1,60 @@ +// 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_ |