Make USB permissions work in the new permission message system
[chromium-blink-merge.git] / content / renderer / media / media_stream_video_track.cc
blob4403260538a83c673614aa4936335a8ac7fbe0c4
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"
10 #include "base/location.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
15 namespace content {
17 namespace {
18 void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) {
19 // |callback| will be deleted when this exits.
22 // Empty method used for keeping a reference to the original media::VideoFrame.
23 // The reference to |frame| is kept in the closure that calls this method.
24 void ReleaseOriginalFrame(const scoped_refptr<media::VideoFrame>& frame) {
27 } // namespace
29 // MediaStreamVideoTrack::FrameDeliverer is a helper class used for registering
30 // VideoCaptureDeliverFrameCB on the main render thread to receive video frames
31 // on the IO-thread.
32 // Frames are only delivered to the sinks if the track is enabled. If the track
33 // is disabled, a black frame is instead forwarded to the sinks at the same
34 // frame rate.
35 class MediaStreamVideoTrack::FrameDeliverer
36 : public base::RefCountedThreadSafe<FrameDeliverer> {
37 public:
38 typedef MediaStreamVideoSink* VideoSinkId;
40 FrameDeliverer(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
41 bool enabled);
43 void SetEnabled(bool enabled);
45 // Add |callback| to receive video frames on the IO-thread.
46 // Must be called on the main render thread.
47 void AddCallback(VideoSinkId id, const VideoCaptureDeliverFrameCB& callback);
49 // Removes |callback| associated with |id| from receiving video frames if |id|
50 // has been added. It is ok to call RemoveCallback even if the |id| has not
51 // been added. Note that the added callback will be reset on the main thread.
52 // Must be called on the main render thread.
53 void RemoveCallback(VideoSinkId id);
55 // Triggers all registered callbacks with |frame|, |format| and
56 // |estimated_capture_time| as parameters. Must be called on the IO-thread.
57 void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
58 const base::TimeTicks& estimated_capture_time);
60 private:
61 friend class base::RefCountedThreadSafe<FrameDeliverer>;
62 virtual ~FrameDeliverer();
63 void AddCallbackOnIO(VideoSinkId id,
64 const VideoCaptureDeliverFrameCB& callback);
65 void RemoveCallbackOnIO(
66 VideoSinkId id,
67 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
69 void SetEnabledOnIO(bool enabled);
70 // Returns a black frame where the size and time stamp is set to the same as
71 // as in |reference_frame|.
72 scoped_refptr<media::VideoFrame> GetBlackFrame(
73 const scoped_refptr<media::VideoFrame>& reference_frame);
75 // Used to DCHECK that AddCallback and RemoveCallback are called on the main
76 // Render Thread.
77 base::ThreadChecker main_render_thread_checker_;
78 const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
80 bool enabled_;
81 scoped_refptr<media::VideoFrame> black_frame_;
83 typedef std::pair<VideoSinkId, VideoCaptureDeliverFrameCB>
84 VideoIdCallbackPair;
85 std::vector<VideoIdCallbackPair> callbacks_;
87 DISALLOW_COPY_AND_ASSIGN(FrameDeliverer);
90 MediaStreamVideoTrack::FrameDeliverer::FrameDeliverer(
91 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
92 bool enabled)
93 : io_task_runner_(io_task_runner), enabled_(enabled) {
94 DCHECK(io_task_runner_.get());
97 MediaStreamVideoTrack::FrameDeliverer::~FrameDeliverer() {
98 DCHECK(callbacks_.empty());
101 void MediaStreamVideoTrack::FrameDeliverer::AddCallback(
102 VideoSinkId id,
103 const VideoCaptureDeliverFrameCB& callback) {
104 DCHECK(main_render_thread_checker_.CalledOnValidThread());
105 io_task_runner_->PostTask(
106 FROM_HERE,
107 base::Bind(&FrameDeliverer::AddCallbackOnIO, this, id, callback));
110 void MediaStreamVideoTrack::FrameDeliverer::AddCallbackOnIO(
111 VideoSinkId id,
112 const VideoCaptureDeliverFrameCB& callback) {
113 DCHECK(io_task_runner_->BelongsToCurrentThread());
114 callbacks_.push_back(std::make_pair(id, callback));
117 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallback(VideoSinkId id) {
118 DCHECK(main_render_thread_checker_.CalledOnValidThread());
119 io_task_runner_->PostTask(
120 FROM_HERE, base::Bind(&FrameDeliverer::RemoveCallbackOnIO, this, id,
121 base::ThreadTaskRunnerHandle::Get()));
124 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallbackOnIO(
125 VideoSinkId id,
126 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
127 DCHECK(io_task_runner_->BelongsToCurrentThread());
128 std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
129 for (; it != callbacks_.end(); ++it) {
130 if (it->first == id) {
131 // Callback is copied to heap and then deleted on the target thread.
132 scoped_ptr<VideoCaptureDeliverFrameCB> callback;
133 callback.reset(new VideoCaptureDeliverFrameCB(it->second));
134 callbacks_.erase(it);
135 task_runner->PostTask(
136 FROM_HERE, base::Bind(&ResetCallback, base::Passed(&callback)));
137 return;
142 void MediaStreamVideoTrack::FrameDeliverer::SetEnabled(bool enabled) {
143 DCHECK(main_render_thread_checker_.CalledOnValidThread());
144 io_task_runner_->PostTask(
145 FROM_HERE, base::Bind(&FrameDeliverer::SetEnabledOnIO, this, enabled));
148 void MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO(bool enabled) {
149 DCHECK(io_task_runner_->BelongsToCurrentThread());
150 enabled_ = enabled;
151 if (enabled_)
152 black_frame_ = NULL;
155 void MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO(
156 const scoped_refptr<media::VideoFrame>& frame,
157 const base::TimeTicks& estimated_capture_time) {
158 DCHECK(io_task_runner_->BelongsToCurrentThread());
159 const scoped_refptr<media::VideoFrame>& video_frame =
160 enabled_ ? frame : GetBlackFrame(frame);
161 for (const auto& entry : callbacks_)
162 entry.second.Run(video_frame, estimated_capture_time);
165 scoped_refptr<media::VideoFrame>
166 MediaStreamVideoTrack::FrameDeliverer::GetBlackFrame(
167 const scoped_refptr<media::VideoFrame>& reference_frame) {
168 DCHECK(io_task_runner_->BelongsToCurrentThread());
169 if (!black_frame_.get() ||
170 black_frame_->natural_size() != reference_frame->natural_size())
171 black_frame_ =
172 media::VideoFrame::CreateBlackFrame(reference_frame->natural_size());
174 // Wrap |black_frame_| so we get a fresh timestamp we can modify. Frames
175 // returned from this function may still be in use.
176 scoped_refptr<media::VideoFrame> wrapped_black_frame =
177 media::VideoFrame::WrapVideoFrame(
178 black_frame_, black_frame_->visible_rect(),
179 black_frame_->natural_size());
180 wrapped_black_frame->AddDestructionObserver(
181 base::Bind(&ReleaseOriginalFrame, black_frame_));
183 wrapped_black_frame->set_timestamp(reference_frame->timestamp());
184 return wrapped_black_frame;
187 // static
188 blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
189 MediaStreamVideoSource* source,
190 const blink::WebMediaConstraints& constraints,
191 const MediaStreamVideoSource::ConstraintsCallback& callback,
192 bool enabled) {
193 blink::WebMediaStreamTrack track;
194 track.initialize(source->owner());
195 track.setExtraData(new MediaStreamVideoTrack(source,
196 constraints,
197 callback,
198 enabled));
199 return track;
202 // static
203 MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack(
204 const blink::WebMediaStreamTrack& track) {
205 return static_cast<MediaStreamVideoTrack*>(track.extraData());
208 MediaStreamVideoTrack::MediaStreamVideoTrack(
209 MediaStreamVideoSource* source,
210 const blink::WebMediaConstraints& constraints,
211 const MediaStreamVideoSource::ConstraintsCallback& callback,
212 bool enabled)
213 : MediaStreamTrack(true),
214 frame_deliverer_(
215 new MediaStreamVideoTrack::FrameDeliverer(source->io_task_runner(),
216 enabled)),
217 constraints_(constraints),
218 source_(source) {
219 DCHECK(!constraints.isNull());
220 source->AddTrack(this,
221 base::Bind(
222 &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO,
223 frame_deliverer_),
224 constraints, callback);
227 MediaStreamVideoTrack::~MediaStreamVideoTrack() {
228 DCHECK(main_render_thread_checker_.CalledOnValidThread());
229 DCHECK(sinks_.empty());
230 Stop();
231 DVLOG(3) << "~MediaStreamVideoTrack()";
234 void MediaStreamVideoTrack::AddSink(
235 MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) {
236 DCHECK(main_render_thread_checker_.CalledOnValidThread());
237 DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
238 sinks_.push_back(sink);
239 frame_deliverer_->AddCallback(sink, callback);
242 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
243 DCHECK(main_render_thread_checker_.CalledOnValidThread());
244 std::vector<MediaStreamVideoSink*>::iterator it =
245 std::find(sinks_.begin(), sinks_.end(), sink);
246 DCHECK(it != sinks_.end());
247 sinks_.erase(it);
248 frame_deliverer_->RemoveCallback(sink);
251 void MediaStreamVideoTrack::SetEnabled(bool enabled) {
252 DCHECK(main_render_thread_checker_.CalledOnValidThread());
253 frame_deliverer_->SetEnabled(enabled);
254 for (auto* sink : sinks_)
255 sink->OnEnabledChanged(enabled);
258 void MediaStreamVideoTrack::Stop() {
259 DCHECK(main_render_thread_checker_.CalledOnValidThread());
260 if (source_) {
261 source_->RemoveTrack(this);
262 source_ = NULL;
264 OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
267 void MediaStreamVideoTrack::OnReadyStateChanged(
268 blink::WebMediaStreamSource::ReadyState state) {
269 DCHECK(main_render_thread_checker_.CalledOnValidThread());
270 for (auto* sink : sinks_)
271 sink->OnReadyStateChanged(state);
274 } // namespace content