Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / content / renderer / media / webrtc / media_stream_video_webrtc_sink.cc
blobf8ac666bf7fe7a8f0b97a7fc332d185635feb36b
1 // Copyright 2014 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/webrtc/media_stream_video_webrtc_sink.h"
7 #include "base/location.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/synchronization/lock.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/common/media/media_stream_options.h"
13 #include "content/renderer/media/media_stream_video_track.h"
14 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
16 namespace {
18 bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints,
19 const blink::WebString& name) {
20 blink::WebString value_str;
21 return constraints.getMandatoryConstraintValue(name, value_str) ||
22 constraints.getOptionalConstraintValue(name, value_str);
25 } // anonymouse namespace
27 namespace content {
29 // Simple help class used for receiving video frames on the IO-thread from a
30 // MediaStreamVideoTrack and forward the frames to a WebRtcVideoCapturerAdapter
31 // on libjingle's worker thread. WebRtcVideoCapturerAdapter implements a video
32 // capturer for libjingle.
33 class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter
34 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> {
35 public:
36 WebRtcVideoSourceAdapter(
37 const scoped_refptr<base::SingleThreadTaskRunner>&
38 libjingle_worker_thread,
39 const scoped_refptr<webrtc::VideoSourceInterface>& source,
40 WebRtcVideoCapturerAdapter* capture_adapter);
42 // MediaStreamVideoWebRtcSink can be destroyed on the main render thread or
43 // libjingles worker thread since it posts video frames on that thread. But
44 // |video_source_| must be released on the main render thread before the
45 // PeerConnectionFactory has been destroyed. The only way to ensure that is to
46 // make sure |video_source_| is released when MediaStreamVideoWebRtcSink() is
47 // destroyed.
48 void ReleaseSourceOnMainThread();
50 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
51 base::TimeTicks estimated_capture_time);
53 private:
54 void OnVideoFrameOnWorkerThread(
55 const scoped_refptr<media::VideoFrame>& frame);
56 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>;
57 virtual ~WebRtcVideoSourceAdapter();
59 scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner_;
61 // |render_thread_checker_| is bound to the main render thread.
62 base::ThreadChecker render_thread_checker_;
63 // Used to DCHECK that frames are called on the IO-thread.
64 base::ThreadChecker io_thread_checker_;
66 // Used for posting frames to libjingle's worker thread. Accessed on the
67 // IO-thread.
68 scoped_refptr<base::SingleThreadTaskRunner> libjingle_worker_thread_;
70 scoped_refptr<webrtc::VideoSourceInterface> video_source_;
72 // Used to protect |capture_adapter_|. It is taken by libjingle's worker
73 // thread for each video frame that is delivered but only taken on the
74 // main render thread in ReleaseSourceOnMainThread() when
75 // the owning MediaStreamVideoWebRtcSink is being destroyed.
76 base::Lock capture_adapter_stop_lock_;
77 // |capture_adapter_| is owned by |video_source_|
78 WebRtcVideoCapturerAdapter* capture_adapter_;
81 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
82 const scoped_refptr<base::SingleThreadTaskRunner>& libjingle_worker_thread,
83 const scoped_refptr<webrtc::VideoSourceInterface>& source,
84 WebRtcVideoCapturerAdapter* capture_adapter)
85 : render_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
86 libjingle_worker_thread_(libjingle_worker_thread),
87 video_source_(source),
88 capture_adapter_(capture_adapter) {
89 io_thread_checker_.DetachFromThread();
92 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
93 ~WebRtcVideoSourceAdapter() {
94 DVLOG(3) << "~WebRtcVideoSourceAdapter()";
95 DCHECK(!capture_adapter_);
96 // This object can be destroyed on the main render thread or libjingles worker
97 // thread since it posts video frames on that thread. But |video_source_| must
98 // be released on the main render thread before the PeerConnectionFactory has
99 // been destroyed. The only way to ensure that is to make sure |video_source_|
100 // is released when MediaStreamVideoWebRtcSink() is destroyed.
103 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
104 ReleaseSourceOnMainThread() {
105 DCHECK(render_thread_checker_.CalledOnValidThread());
106 // Since frames are posted to the worker thread, this object might be deleted
107 // on that thread. However, since |video_source_| was created on the render
108 // thread, it should be released on the render thread.
109 base::AutoLock auto_lock(capture_adapter_stop_lock_);
110 // |video_source| owns |capture_adapter_|.
111 capture_adapter_ = NULL;
112 video_source_ = NULL;
115 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
116 const scoped_refptr<media::VideoFrame>& frame,
117 base::TimeTicks estimated_capture_time) {
118 DCHECK(io_thread_checker_.CalledOnValidThread());
119 libjingle_worker_thread_->PostTask(
120 FROM_HERE,
121 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread,
122 this,
123 frame));
126 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
127 OnVideoFrameOnWorkerThread(const scoped_refptr<media::VideoFrame>& frame) {
128 DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
129 base::AutoLock auto_lock(capture_adapter_stop_lock_);
130 if (capture_adapter_)
131 capture_adapter_->OnFrameCaptured(frame);
134 MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
135 const blink::WebMediaStreamTrack& track,
136 PeerConnectionDependencyFactory* factory)
137 : web_track_(track) {
138 const blink::WebMediaConstraints& constraints =
139 MediaStreamVideoTrack::GetVideoTrack(track)->constraints();
141 bool is_screencast = ConstraintKeyExists(
142 constraints, base::UTF8ToUTF16(kMediaStreamSource));
143 WebRtcVideoCapturerAdapter* capture_adapter =
144 factory->CreateVideoCapturer(is_screencast);
146 // |video_source| owns |capture_adapter|
147 scoped_refptr<webrtc::VideoSourceInterface> video_source(
148 factory->CreateVideoSource(capture_adapter,
149 track.source().constraints()));
151 video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(),
152 video_source.get());
154 video_track_->set_enabled(web_track_.isEnabled());
156 source_adapter_ = new WebRtcVideoSourceAdapter(
157 factory->GetWebRtcWorkerThread(),
158 video_source,
159 capture_adapter);
161 AddToVideoTrack(
162 this,
163 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_),
164 web_track_);
166 DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast "
167 << is_screencast;
170 MediaStreamVideoWebRtcSink::~MediaStreamVideoWebRtcSink() {
171 DCHECK(thread_checker_.CalledOnValidThread());
172 DVLOG(3) << "MediaStreamVideoWebRtcSink dtor().";
173 RemoveFromVideoTrack(this, web_track_);
174 source_adapter_->ReleaseSourceOnMainThread();
177 void MediaStreamVideoWebRtcSink::OnEnabledChanged(bool enabled) {
178 DCHECK(thread_checker_.CalledOnValidThread());
179 video_track_->set_enabled(enabled);
182 } // namespace content