Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / media_stream_video_track.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/media/media_stream_video_track.h"
6
7 #include "base/bind.h"
8 #include "content/renderer/media/video_frame_deliverer.h"
9 #include "media/base/bind_to_current_loop.h"
10
11 namespace content {
12
13 // Helper class used for delivering video frames to MediaStreamSinks on the
14 // IO-thread.
15 // Frames are delivered to an instance of this class from a
16 // MediaStreamVideoSource on the IO-thread to the method DeliverFrameOnIO.
17 // Frames are only delivered to the sinks if the track is enabled.
18 class MediaStreamVideoTrack::FrameDeliverer : public VideoFrameDeliverer {
19  public:
20   FrameDeliverer(
21       const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
22       bool enabled)
23       : VideoFrameDeliverer(io_message_loop_proxy),
24         enabled_(enabled) {
25   }
26
27   // Add |sink| to receive state changes on the main render thread.
28   // Video frames will be delivered to |callback| on the IO thread.
29   void AddSink(MediaStreamVideoSink* sink,
30                const VideoCaptureDeliverFrameCB& callback) {
31     DCHECK(thread_checker().CalledOnValidThread());
32     DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
33     sinks_.push_back(sink);
34     AddCallback(sink, callback);
35   }
36
37   void RemoveSink(MediaStreamVideoSink* sink) {
38     DCHECK(thread_checker().CalledOnValidThread());
39     std::vector<MediaStreamVideoSink*>::iterator it =
40         std::find(sinks_.begin(), sinks_.end(), sink);
41     DCHECK(it != sinks_.end());
42     sinks_.erase(it);
43     RemoveCallback(sink);
44   }
45
46   void SetEnabled(bool enabled) {
47     DCHECK(thread_checker().CalledOnValidThread());
48     io_message_loop()->PostTask(
49         FROM_HERE,
50         base::Bind(&MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO,
51                    this, enabled));
52   }
53
54   virtual void DeliverFrameOnIO(
55       const scoped_refptr<media::VideoFrame>& frame,
56       const media::VideoCaptureFormat& format) OVERRIDE {
57     DCHECK(io_message_loop()->BelongsToCurrentThread());
58     if (!enabled_)
59       return;
60     VideoFrameDeliverer::DeliverFrameOnIO(frame, format);
61   }
62
63   const std::vector<MediaStreamVideoSink*>& sinks() const { return sinks_; }
64
65  protected:
66   virtual ~FrameDeliverer() {
67     DCHECK(sinks_.empty());
68   }
69
70   void SetEnabledOnIO(bool enabled) {
71     DCHECK(io_message_loop()->BelongsToCurrentThread());
72     enabled_ = enabled;
73   }
74
75  private:
76   // The below members are used on the main render thread.
77   std::vector<MediaStreamVideoSink*> sinks_;
78
79   // The below parameters are used on the IO-thread.
80   bool enabled_;
81
82   DISALLOW_COPY_AND_ASSIGN(FrameDeliverer);
83 };
84
85 // static
86 blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
87     MediaStreamVideoSource* source,
88     const blink::WebMediaConstraints& constraints,
89     const MediaStreamVideoSource::ConstraintsCallback& callback,
90     bool enabled) {
91   blink::WebMediaStreamTrack track;
92   track.initialize(source->owner());
93   track.setExtraData(new MediaStreamVideoTrack(source,
94                                                constraints,
95                                                callback,
96                                                enabled));
97   return track;
98 }
99
100 // static
101 MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack(
102      const blink::WebMediaStreamTrack& track) {
103   return static_cast<MediaStreamVideoTrack*>(track.extraData());
104 }
105
106 MediaStreamVideoTrack::MediaStreamVideoTrack(
107     MediaStreamVideoSource* source,
108     const blink::WebMediaConstraints& constraints,
109     const MediaStreamVideoSource::ConstraintsCallback& callback,
110     bool enabled)
111     : MediaStreamTrack(NULL, true),
112       frame_deliverer_(
113           new MediaStreamVideoTrack::FrameDeliverer(source->io_message_loop(),
114                                                     enabled)),
115       constraints_(constraints),
116       source_(source) {
117   source->AddTrack(this,
118                    base::Bind(
119                        &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO,
120                        frame_deliverer_),
121                    constraints, callback);
122 }
123
124 MediaStreamVideoTrack::~MediaStreamVideoTrack() {
125   Stop();
126   DVLOG(3) << "~MediaStreamVideoTrack()";
127 }
128
129 void MediaStreamVideoTrack::AddSink(
130     MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) {
131   DCHECK(thread_checker_.CalledOnValidThread());
132   frame_deliverer_->AddSink(sink, callback);
133 }
134
135 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
136   DCHECK(thread_checker_.CalledOnValidThread());
137   frame_deliverer_->RemoveSink(sink);
138 }
139
140 void MediaStreamVideoTrack::SetEnabled(bool enabled) {
141   DCHECK(thread_checker_.CalledOnValidThread());
142   MediaStreamTrack::SetEnabled(enabled);
143
144   frame_deliverer_->SetEnabled(enabled);
145   const std::vector<MediaStreamVideoSink*>& sinks = frame_deliverer_->sinks();
146   for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks.begin();
147        it != sinks.end(); ++it) {
148     (*it)->OnEnabledChanged(enabled);
149   }
150 }
151
152 void MediaStreamVideoTrack::Stop() {
153   DCHECK(thread_checker_.CalledOnValidThread());
154   if (source_) {
155     source_->RemoveTrack(this);
156     source_ = NULL;
157   }
158   OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
159 }
160
161 void MediaStreamVideoTrack::OnReadyStateChanged(
162     blink::WebMediaStreamSource::ReadyState state) {
163   DCHECK(thread_checker_.CalledOnValidThread());
164   const std::vector<MediaStreamVideoSink*>& sinks = frame_deliverer_->sinks();
165   for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks.begin();
166        it != sinks.end(); ++it) {
167     (*it)->OnReadyStateChanged(state);
168   }
169 }
170
171 }  // namespace content