Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / renderer / media / media_stream_video_track.cc
blob1fc2df2463adab51606d8d5d2d4628a1f141221b
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.
5 #include "content/renderer/media/media_stream_video_track.h"
7 #include <utility>
9 #include "base/bind.h"
11 namespace content {
13 namespace {
14 void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) {
15 // |callback| will be deleted when this exits.
17 } // namespace
19 // MediaStreamVideoTrack::FrameDeliverer is a helper class used for registering
20 // VideoCaptureDeliverFrameCB on the main render thread to receive video frames
21 // on the IO-thread.
22 // Frames are only delivered to the sinks if the track is enabled. If the track
23 // is disabled, a black frame is instead forwarded to the sinks at the same
24 // frame rate.
25 class MediaStreamVideoTrack::FrameDeliverer
26 : public base::RefCountedThreadSafe<FrameDeliverer> {
27 public:
28 FrameDeliverer(
29 const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
30 bool enabled);
32 void SetEnabled(bool enabled);
34 // Add |callback| to receive video frames on the IO-thread.
35 // Must be called on the main render thread.
36 void AddCallback(void* id, const VideoCaptureDeliverFrameCB& callback);
38 // Removes |callback| associated with |id| from receiving video frames if |id|
39 // has been added. It is ok to call RemoveCallback even if the |id| has not
40 // been added. Note that the added callback will be reset on the main thread.
41 // Must be called on the main render thread.
42 void RemoveCallback(void* id);
44 // Triggers all registered callbacks with |frame|, |format| and
45 // |estimated_capture_time| as parameters. Must be called on the IO-thread.
46 void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
47 const media::VideoCaptureFormat& format,
48 const base::TimeTicks& estimated_capture_time);
50 private:
51 friend class base::RefCountedThreadSafe<FrameDeliverer>;
52 virtual ~FrameDeliverer();
53 void AddCallbackOnIO(void* id, const VideoCaptureDeliverFrameCB& callback);
54 void RemoveCallbackOnIO(
55 void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop);
57 void SetEnabledOnIO(bool enabled);
58 // Returns |black_frame_| where the size and time stamp is set to the same as
59 // as in |reference_frame|.
60 const scoped_refptr<media::VideoFrame>& GetBlackFrame(
61 const scoped_refptr<media::VideoFrame>& reference_frame);
63 // Used to DCHECK that AddCallback and RemoveCallback are called on the main
64 // render thread.
65 base::ThreadChecker thread_checker_;
66 scoped_refptr<base::MessageLoopProxy> io_message_loop_;
68 bool enabled_;
69 scoped_refptr<media::VideoFrame> black_frame_;
71 typedef std::pair<void*, VideoCaptureDeliverFrameCB> VideoIdCallbackPair;
72 std::vector<VideoIdCallbackPair> callbacks_;
74 DISALLOW_COPY_AND_ASSIGN(FrameDeliverer);
77 MediaStreamVideoTrack::FrameDeliverer::FrameDeliverer(
78 const scoped_refptr<base::MessageLoopProxy>& io_message_loop, bool enabled)
79 : io_message_loop_(io_message_loop),
80 enabled_(enabled) {
81 DCHECK(io_message_loop_.get());
84 MediaStreamVideoTrack::FrameDeliverer::~FrameDeliverer() {
85 DCHECK(callbacks_.empty());
88 void MediaStreamVideoTrack::FrameDeliverer::AddCallback(
89 void* id,
90 const VideoCaptureDeliverFrameCB& callback) {
91 DCHECK(thread_checker_.CalledOnValidThread());
92 io_message_loop_->PostTask(
93 FROM_HERE,
94 base::Bind(&FrameDeliverer::AddCallbackOnIO,
95 this, id, callback));
98 void MediaStreamVideoTrack::FrameDeliverer::AddCallbackOnIO(
99 void* id,
100 const VideoCaptureDeliverFrameCB& callback) {
101 DCHECK(io_message_loop_->BelongsToCurrentThread());
102 callbacks_.push_back(std::make_pair(id, callback));
105 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallback(void* id) {
106 DCHECK(thread_checker_.CalledOnValidThread());
107 io_message_loop_->PostTask(
108 FROM_HERE,
109 base::Bind(&FrameDeliverer::RemoveCallbackOnIO,
110 this, id, base::MessageLoopProxy::current()));
113 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallbackOnIO(
114 void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop) {
115 DCHECK(io_message_loop_->BelongsToCurrentThread());
116 std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
117 for (; it != callbacks_.end(); ++it) {
118 if (it->first == id) {
119 // Callback is copied to heap and then deleted on the target thread.
120 scoped_ptr<VideoCaptureDeliverFrameCB> callback;
121 callback.reset(new VideoCaptureDeliverFrameCB(it->second));
122 callbacks_.erase(it);
123 message_loop->PostTask(
124 FROM_HERE, base::Bind(&ResetCallback, base::Passed(&callback)));
125 return;
130 void MediaStreamVideoTrack::FrameDeliverer::SetEnabled(bool enabled) {
131 DCHECK(thread_checker_.CalledOnValidThread());
132 io_message_loop_->PostTask(
133 FROM_HERE,
134 base::Bind(&FrameDeliverer::SetEnabledOnIO,
135 this, enabled));
138 void MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO(bool enabled) {
139 DCHECK(io_message_loop_->BelongsToCurrentThread());
140 enabled_ = enabled;
141 if (enabled_)
142 black_frame_ = NULL;
145 void MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO(
146 const scoped_refptr<media::VideoFrame>& frame,
147 const media::VideoCaptureFormat& format,
148 const base::TimeTicks& estimated_capture_time) {
149 DCHECK(io_message_loop_->BelongsToCurrentThread());
150 const scoped_refptr<media::VideoFrame>& video_frame =
151 enabled_ ? frame : GetBlackFrame(frame);
153 for (std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
154 it != callbacks_.end(); ++it) {
155 it->second.Run(video_frame, format, estimated_capture_time);
159 const scoped_refptr<media::VideoFrame>&
160 MediaStreamVideoTrack::FrameDeliverer::GetBlackFrame(
161 const scoped_refptr<media::VideoFrame>& reference_frame) {
162 DCHECK(io_message_loop_->BelongsToCurrentThread());
163 if (!black_frame_.get() ||
164 black_frame_->natural_size() != reference_frame->natural_size())
165 black_frame_ =
166 media::VideoFrame::CreateBlackFrame(reference_frame->natural_size());
168 black_frame_->set_timestamp(reference_frame->timestamp());
169 return black_frame_;
172 // static
173 blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
174 MediaStreamVideoSource* source,
175 const blink::WebMediaConstraints& constraints,
176 const MediaStreamVideoSource::ConstraintsCallback& callback,
177 bool enabled) {
178 blink::WebMediaStreamTrack track;
179 track.initialize(source->owner());
180 track.setExtraData(new MediaStreamVideoTrack(source,
181 constraints,
182 callback,
183 enabled));
184 return track;
187 // static
188 MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack(
189 const blink::WebMediaStreamTrack& track) {
190 return static_cast<MediaStreamVideoTrack*>(track.extraData());
193 MediaStreamVideoTrack::MediaStreamVideoTrack(
194 MediaStreamVideoSource* source,
195 const blink::WebMediaConstraints& constraints,
196 const MediaStreamVideoSource::ConstraintsCallback& callback,
197 bool enabled)
198 : MediaStreamTrack(NULL, true),
199 frame_deliverer_(
200 new MediaStreamVideoTrack::FrameDeliverer(source->io_message_loop(),
201 enabled)),
202 constraints_(constraints),
203 source_(source) {
204 DCHECK(!constraints.isNull());
205 source->AddTrack(this,
206 base::Bind(
207 &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO,
208 frame_deliverer_),
209 constraints, callback);
212 MediaStreamVideoTrack::~MediaStreamVideoTrack() {
213 DCHECK(thread_checker_.CalledOnValidThread());
214 DCHECK(sinks_.empty());
215 Stop();
216 DVLOG(3) << "~MediaStreamVideoTrack()";
219 void MediaStreamVideoTrack::AddSink(
220 MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) {
221 DCHECK(thread_checker_.CalledOnValidThread());
222 DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
223 sinks_.push_back(sink);
224 frame_deliverer_->AddCallback(sink, callback);
227 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
228 DCHECK(thread_checker_.CalledOnValidThread());
229 std::vector<MediaStreamVideoSink*>::iterator it =
230 std::find(sinks_.begin(), sinks_.end(), sink);
231 DCHECK(it != sinks_.end());
232 sinks_.erase(it);
233 frame_deliverer_->RemoveCallback(sink);
236 void MediaStreamVideoTrack::SetEnabled(bool enabled) {
237 DCHECK(thread_checker_.CalledOnValidThread());
238 MediaStreamTrack::SetEnabled(enabled);
240 frame_deliverer_->SetEnabled(enabled);
241 for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks_.begin();
242 it != sinks_.end(); ++it) {
243 (*it)->OnEnabledChanged(enabled);
247 void MediaStreamVideoTrack::Stop() {
248 DCHECK(thread_checker_.CalledOnValidThread());
249 if (source_) {
250 source_->RemoveTrack(this);
251 source_ = NULL;
253 OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
256 void MediaStreamVideoTrack::OnReadyStateChanged(
257 blink::WebMediaStreamSource::ReadyState state) {
258 DCHECK(thread_checker_.CalledOnValidThread());
259 for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks_.begin();
260 it != sinks_.end(); ++it) {
261 (*it)->OnReadyStateChanged(state);
265 void MediaStreamVideoTrack::SetMutedState(bool muted_state) {
266 DCHECK(thread_checker_.CalledOnValidThread());
267 muted_state_ = muted_state;
270 bool MediaStreamVideoTrack::GetMutedState(void) const {
271 DCHECK(thread_checker_.CalledOnValidThread());
272 return muted_state_;
275 } // namespace content