Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / content / renderer / media / media_stream_video_track.cc
blob1da51c12d3d18632b02ef93c8bc466f4ba8e92cb
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 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 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());
175 // Wrap |black_frame_| so we get a fresh timestamp we can modify. Frames
176 // returned from this function may still be in use.
177 scoped_refptr<media::VideoFrame> wrapped_black_frame =
178 media::VideoFrame::WrapVideoFrame(
179 black_frame_, black_frame_->visible_rect(),
180 black_frame_->natural_size());
181 wrapped_black_frame->AddDestructionObserver(
182 base::Bind(&ReleaseOriginalFrame, black_frame_));
184 wrapped_black_frame->set_timestamp(reference_frame->timestamp());
185 return wrapped_black_frame;
188 // static
189 blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
190 MediaStreamVideoSource* source,
191 const blink::WebMediaConstraints& constraints,
192 const MediaStreamVideoSource::ConstraintsCallback& callback,
193 bool enabled) {
194 blink::WebMediaStreamTrack track;
195 track.initialize(source->owner());
196 track.setExtraData(new MediaStreamVideoTrack(source,
197 constraints,
198 callback,
199 enabled));
200 return track;
203 // static
204 MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack(
205 const blink::WebMediaStreamTrack& track) {
206 return static_cast<MediaStreamVideoTrack*>(track.extraData());
209 MediaStreamVideoTrack::MediaStreamVideoTrack(
210 MediaStreamVideoSource* source,
211 const blink::WebMediaConstraints& constraints,
212 const MediaStreamVideoSource::ConstraintsCallback& callback,
213 bool enabled)
214 : MediaStreamTrack(true),
215 frame_deliverer_(
216 new MediaStreamVideoTrack::FrameDeliverer(source->io_task_runner(),
217 enabled)),
218 constraints_(constraints),
219 source_(source) {
220 DCHECK(!constraints.isNull());
221 source->AddTrack(this,
222 base::Bind(
223 &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO,
224 frame_deliverer_),
225 constraints, callback);
228 MediaStreamVideoTrack::~MediaStreamVideoTrack() {
229 DCHECK(main_render_thread_checker_.CalledOnValidThread());
230 DCHECK(sinks_.empty());
231 Stop();
232 DVLOG(3) << "~MediaStreamVideoTrack()";
235 void MediaStreamVideoTrack::AddSink(
236 MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) {
237 DCHECK(main_render_thread_checker_.CalledOnValidThread());
238 DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
239 sinks_.push_back(sink);
240 frame_deliverer_->AddCallback(sink, callback);
243 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
244 DCHECK(main_render_thread_checker_.CalledOnValidThread());
245 std::vector<MediaStreamVideoSink*>::iterator it =
246 std::find(sinks_.begin(), sinks_.end(), sink);
247 DCHECK(it != sinks_.end());
248 sinks_.erase(it);
249 frame_deliverer_->RemoveCallback(sink);
252 void MediaStreamVideoTrack::SetEnabled(bool enabled) {
253 DCHECK(main_render_thread_checker_.CalledOnValidThread());
254 frame_deliverer_->SetEnabled(enabled);
255 for (auto* sink : sinks_)
256 sink->OnEnabledChanged(enabled);
259 void MediaStreamVideoTrack::Stop() {
260 DCHECK(main_render_thread_checker_.CalledOnValidThread());
261 if (source_) {
262 source_->RemoveTrack(this);
263 source_ = NULL;
265 OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
268 void MediaStreamVideoTrack::OnReadyStateChanged(
269 blink::WebMediaStreamSource::ReadyState state) {
270 DCHECK(main_render_thread_checker_.CalledOnValidThread());
271 for (auto* sink : sinks_)
272 sink->OnReadyStateChanged(state);
275 } // namespace content