Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / media / webrtc / webrtc_video_track_adapter.cc
blobd3c2036c45f4f22f048b7bd9ceacbb242f3be433
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/webrtc_video_track_adapter.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/synchronization/lock.h"
9 #include "content/common/media/media_stream_options.h"
10 #include "content/renderer/media/media_stream_video_source.h"
11 #include "content/renderer/media/media_stream_video_track.h"
13 namespace {
15 bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints,
16 const blink::WebString& name) {
17 blink::WebString value_str;
18 return constraints.getMandatoryConstraintValue(name, value_str) ||
19 constraints.getOptionalConstraintValue(name, value_str);
22 } // anonymouse namespace
24 namespace content {
26 // Simple help class used for receiving video frames on the IO-thread from
27 // a MediaStreamVideoTrack and forward the frames to a
28 // WebRtcVideoCapturerAdapter on libjingle's worker thread.
29 // WebRtcVideoCapturerAdapter implements a video capturer for libjingle.
30 class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter
31 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> {
32 public:
33 WebRtcVideoSourceAdapter(
34 const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread,
35 const scoped_refptr<webrtc::VideoSourceInterface>& source,
36 WebRtcVideoCapturerAdapter* capture_adapter);
38 // WebRtcVideoTrackAdapter can be destroyed on the main render thread or
39 // libjingles worker thread since it posts video frames on that thread. But
40 // |video_source_| must be released on the main render thread before the
41 // PeerConnectionFactory has been destroyed. The only way to ensure that is
42 // to make sure |video_source_| is released when WebRtcVideoTrackAdapter() is
43 // destroyed.
44 void ReleaseSourceOnMainThread();
46 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
47 const base::TimeTicks& estimated_capture_time);
49 private:
50 void OnVideoFrameOnWorkerThread(
51 const scoped_refptr<media::VideoFrame>& frame);
52 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>;
53 virtual ~WebRtcVideoSourceAdapter();
55 scoped_refptr<base::MessageLoopProxy> render_thread_message_loop_;
57 // |render_thread_checker_| is bound to the main render thread.
58 base::ThreadChecker render_thread_checker_;
59 // Used to DCHECK that frames are called on the IO-thread.
60 base::ThreadChecker io_thread_checker_;
62 // Used for posting frames to libjingle's worker thread. Accessed on the
63 // IO-thread.
64 scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_;
66 scoped_refptr<webrtc::VideoSourceInterface> video_source_;
68 // Used to protect |capture_adapter_|. It is taken by libjingle's worker
69 // thread for each video frame that is delivered but only taken on the
70 // main render thread in ReleaseSourceOnMainThread() when
71 // the owning WebRtcVideoTrackAdapter is being destroyed.
72 base::Lock capture_adapter_stop_lock_;
73 // |capture_adapter_| is owned by |video_source_|
74 WebRtcVideoCapturerAdapter* capture_adapter_;
77 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
78 const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread,
79 const scoped_refptr<webrtc::VideoSourceInterface>& source,
80 WebRtcVideoCapturerAdapter* capture_adapter)
81 : render_thread_message_loop_(base::MessageLoopProxy::current()),
82 libjingle_worker_thread_(libjingle_worker_thread),
83 video_source_(source),
84 capture_adapter_(capture_adapter) {
85 io_thread_checker_.DetachFromThread();
88 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() {
89 DVLOG(3) << "~WebRtcVideoSourceAdapter()";
90 DCHECK(!capture_adapter_);
91 // This object can be destroyed on the main render thread or libjingles
92 // worker thread since it posts video frames on that thread. But
93 // |video_source_| must be released on the main render thread before the
94 // PeerConnectionFactory has been destroyed. The only way to ensure that is
95 // to make sure |video_source_| is released when WebRtcVideoTrackAdapter() is
96 // destroyed.
99 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::
100 ReleaseSourceOnMainThread() {
101 DCHECK(render_thread_checker_.CalledOnValidThread());
102 // Since frames are posted to the worker thread, this object might be deleted
103 // on that thread. However, since |video_source_| was created on the render
104 // thread, it should be released on the render thread.
105 base::AutoLock auto_lock(capture_adapter_stop_lock_);
106 // |video_source| owns |capture_adapter_|.
107 capture_adapter_ = NULL;
108 video_source_ = NULL;
111 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
112 const scoped_refptr<media::VideoFrame>& frame,
113 const base::TimeTicks& estimated_capture_time) {
114 DCHECK(io_thread_checker_.CalledOnValidThread());
115 libjingle_worker_thread_->PostTask(
116 FROM_HERE,
117 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread,
118 this,
119 frame));
122 void
123 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread(
124 const scoped_refptr<media::VideoFrame>& frame) {
125 DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
126 base::AutoLock auto_lock(capture_adapter_stop_lock_);
127 if (capture_adapter_)
128 capture_adapter_->OnFrameCaptured(frame);
131 WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter(
132 const blink::WebMediaStreamTrack& track,
133 PeerConnectionDependencyFactory* factory)
134 : web_track_(track) {
135 const blink::WebMediaConstraints& constraints =
136 MediaStreamVideoTrack::GetVideoTrack(track)->constraints();
138 bool is_screencast = ConstraintKeyExists(
139 constraints, base::UTF8ToUTF16(kMediaStreamSource));
140 WebRtcVideoCapturerAdapter* capture_adapter =
141 factory->CreateVideoCapturer(is_screencast);
143 // |video_source| owns |capture_adapter|
144 scoped_refptr<webrtc::VideoSourceInterface> video_source(
145 factory->CreateVideoSource(capture_adapter,
146 track.source().constraints()));
148 video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(),
149 video_source.get());
151 video_track_->set_enabled(web_track_.isEnabled());
153 source_adapter_ = new WebRtcVideoSourceAdapter(
154 factory->GetWebRtcWorkerThread(),
155 video_source,
156 capture_adapter);
158 AddToVideoTrack(
159 this,
160 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO,
161 source_adapter_),
162 web_track_);
164 DVLOG(3) << "WebRtcVideoTrackAdapter ctor() : is_screencast "
165 << is_screencast;
168 WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() {
169 DCHECK(thread_checker_.CalledOnValidThread());
170 DVLOG(3) << "WebRtcVideoTrackAdapter dtor().";
171 RemoveFromVideoTrack(this, web_track_);
172 source_adapter_->ReleaseSourceOnMainThread();
175 void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) {
176 DCHECK(thread_checker_.CalledOnValidThread());
177 video_track_->set_enabled(enabled);
180 } // namespace content