diff options
Diffstat (limited to 'chromium/content/renderer/media/media_stream_video_track.cc')
-rw-r--r-- | chromium/content/renderer/media/media_stream_video_track.cc | 172 |
1 files changed, 150 insertions, 22 deletions
diff --git a/chromium/content/renderer/media/media_stream_video_track.cc b/chromium/content/renderer/media/media_stream_video_track.cc index 44962445161..0ad7159255d 100644 --- a/chromium/content/renderer/media/media_stream_video_track.cc +++ b/chromium/content/renderer/media/media_stream_video_track.cc @@ -4,44 +4,172 @@ #include "content/renderer/media/media_stream_video_track.h" -#include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h" +#include "base/bind.h" +#include "content/renderer/media/video_frame_deliverer.h" +#include "media/base/bind_to_current_loop.h" namespace content { -// 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_; +// Helper class used for delivering video frames to MediaStreamSinks on the +// IO-thread. +// Frames are delivered to an instance of this class from a +// MediaStreamVideoSource on the IO-thread to the method DeliverFrameOnIO. +// Frames are only delivered to the sinks if the track is enabled. +class MediaStreamVideoTrack::FrameDeliverer : public VideoFrameDeliverer { + public: + FrameDeliverer( + const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy, + bool enabled) + : VideoFrameDeliverer(io_message_loop_proxy), + enabled_(enabled) { } - MediaStreamVideoSink* sink_; + + // Add |sink| to receive state changes on the main render thread. + // Video frames will be delivered to |callback| on the IO thread. + void AddSink(MediaStreamVideoSink* sink, + const VideoCaptureDeliverFrameCB& callback) { + DCHECK(thread_checker().CalledOnValidThread()); + DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end()); + sinks_.push_back(sink); + AddCallback(sink, callback); + } + + void RemoveSink(MediaStreamVideoSink* sink) { + DCHECK(thread_checker().CalledOnValidThread()); + std::vector<MediaStreamVideoSink*>::iterator it = + std::find(sinks_.begin(), sinks_.end(), sink); + DCHECK(it != sinks_.end()); + sinks_.erase(it); + RemoveCallback(sink); + } + + void SetEnabled(bool enabled) { + DCHECK(thread_checker().CalledOnValidThread()); + io_message_loop()->PostTask( + FROM_HERE, + base::Bind(&MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO, + this, enabled)); + } + + virtual void DeliverFrameOnIO( + const scoped_refptr<media::VideoFrame>& frame, + const media::VideoCaptureFormat& format, + const base::TimeTicks& estimated_capture_time) OVERRIDE { + DCHECK(io_message_loop()->BelongsToCurrentThread()); + if (!enabled_) + return; + VideoFrameDeliverer::DeliverFrameOnIO(frame, format, + estimated_capture_time); + } + + const std::vector<MediaStreamVideoSink*>& sinks() const { return sinks_; } + + protected: + virtual ~FrameDeliverer() { + DCHECK(sinks_.empty()); + } + + void SetEnabledOnIO(bool enabled) { + DCHECK(io_message_loop()->BelongsToCurrentThread()); + enabled_ = enabled; + } + + private: + // The below members are used on the main render thread. + std::vector<MediaStreamVideoSink*> sinks_; + + // The below parameters are used on the IO-thread. + bool enabled_; + + DISALLOW_COPY_AND_ASSIGN(FrameDeliverer); }; -MediaStreamVideoTrack::MediaStreamVideoTrack(webrtc::VideoTrackInterface* track, - bool is_local_track) - : MediaStreamTrackExtraData(track, is_local_track), - video_track_(track) { +// static +blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack( + MediaStreamVideoSource* source, + const blink::WebMediaConstraints& constraints, + const MediaStreamVideoSource::ConstraintsCallback& callback, + bool enabled) { + blink::WebMediaStreamTrack track; + track.initialize(source->owner()); + track.setExtraData(new MediaStreamVideoTrack(source, + constraints, + callback, + enabled)); + return track; +} + +// static +MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack( + const blink::WebMediaStreamTrack& track) { + return static_cast<MediaStreamVideoTrack*>(track.extraData()); +} + +MediaStreamVideoTrack::MediaStreamVideoTrack( + MediaStreamVideoSource* source, + const blink::WebMediaConstraints& constraints, + const MediaStreamVideoSource::ConstraintsCallback& callback, + bool enabled) + : MediaStreamTrack(NULL, true), + frame_deliverer_( + new MediaStreamVideoTrack::FrameDeliverer(source->io_message_loop(), + enabled)), + constraints_(constraints), + source_(source) { + DCHECK(!constraints.isNull()); + source->AddTrack(this, + base::Bind( + &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO, + frame_deliverer_), + constraints, callback); } MediaStreamVideoTrack::~MediaStreamVideoTrack() { - DCHECK(sinks_.empty()); + DCHECK(thread_checker_.CalledOnValidThread()); + Stop(); + DVLOG(3) << "~MediaStreamVideoTrack()"; } -void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) { +void MediaStreamVideoTrack::AddSink( + MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(std::find_if(sinks_.begin(), sinks_.end(), - SinkWrapper(sink)) == sinks_.end()); - sinks_.push_back(new WebRtcVideoSinkAdapter(video_track_, sink)); + frame_deliverer_->AddSink(sink, callback); } void MediaStreamVideoTrack::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); + frame_deliverer_->RemoveSink(sink); +} + +void MediaStreamVideoTrack::SetEnabled(bool enabled) { + DCHECK(thread_checker_.CalledOnValidThread()); + MediaStreamTrack::SetEnabled(enabled); + + frame_deliverer_->SetEnabled(enabled); + const std::vector<MediaStreamVideoSink*>& sinks = frame_deliverer_->sinks(); + for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks.begin(); + it != sinks.end(); ++it) { + (*it)->OnEnabledChanged(enabled); + } +} + +void MediaStreamVideoTrack::Stop() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (source_) { + source_->RemoveTrack(this); + source_ = NULL; + } + OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded); +} + +void MediaStreamVideoTrack::OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) { + DCHECK(thread_checker_.CalledOnValidThread()); + const std::vector<MediaStreamVideoSink*>& sinks = frame_deliverer_->sinks(); + for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks.begin(); + it != sinks.end(); ++it) { + (*it)->OnReadyStateChanged(state); + } } } // namespace content |