Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / webrtc / webrtc_video_track_adapter.cc
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.
4
5 #include "content/renderer/media/webrtc/webrtc_video_track_adapter.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/common/media/media_stream_options.h"
9 #include "content/renderer/media/media_stream_video_source.h"
10 #include "content/renderer/media/media_stream_video_track.h"
11
12 namespace {
13
14 bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints,
15                          const blink::WebString& name) {
16   blink::WebString value_str;
17   return constraints.getMandatoryConstraintValue(name, value_str) ||
18       constraints.getOptionalConstraintValue(name, value_str);
19 }
20
21 // Used to make sure |source| is released on the main render thread.
22 void ReleaseWebRtcSourceOnMainRenderThread(
23     webrtc::VideoSourceInterface* source) {
24   source->Release();
25 }
26
27 }  // anonymouse namespace
28
29 namespace content {
30
31 // Simple help class used for receiving video frames on the IO-thread from
32 // a MediaStreamVideoTrack and forward the frames to a
33 // WebRtcVideoCapturerAdapter on libjingle's worker thread.
34 // WebRtcVideoCapturerAdapter implements a video capturer for libjingle.
35 class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter
36     : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> {
37  public:
38   WebRtcVideoSourceAdapter(
39       const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread,
40       const scoped_refptr<webrtc::VideoSourceInterface>& source,
41       WebRtcVideoCapturerAdapter* capture_adapter);
42
43   void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
44                         const media::VideoCaptureFormat& format);
45
46  private:
47   void OnVideoFrameOnWorkerThread(const scoped_refptr<media::VideoFrame>& frame,
48                                   const media::VideoCaptureFormat& format);
49   friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>;
50   virtual ~WebRtcVideoSourceAdapter();
51
52   scoped_refptr<base::MessageLoopProxy> render_thread_message_loop_;
53
54   // Used to DCHECK that frames are called on the IO-thread.
55   base::ThreadChecker io_thread_checker_;
56
57   // Used for posting frames to libjingle's worker thread. Accessed on the
58   // IO-thread.
59   scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_;
60
61   scoped_refptr<webrtc::VideoSourceInterface> video_source_;
62   // |capture_adapter_| is owned by |video_source_|
63   WebRtcVideoCapturerAdapter* capture_adapter_;
64 };
65
66 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
67     const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread,
68     const scoped_refptr<webrtc::VideoSourceInterface>& source,
69     WebRtcVideoCapturerAdapter* capture_adapter)
70     : render_thread_message_loop_(base::MessageLoopProxy::current()),
71       libjingle_worker_thread_(libjingle_worker_thread),
72       video_source_(source),
73       capture_adapter_(capture_adapter) {
74   io_thread_checker_.DetachFromThread();
75 }
76
77 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() {
78   // Since frames are posted to the worker thread, this object might be deleted
79   // on that thread. However, since |video_source_| was created on the render
80   // thread, it should be released on the render thread.
81   if (!render_thread_message_loop_->BelongsToCurrentThread()) {
82     webrtc::VideoSourceInterface* source = video_source_.get();
83     source->AddRef();
84     video_source_ = NULL;
85     render_thread_message_loop_->PostTask(
86         FROM_HERE,
87         base::Bind(&ReleaseWebRtcSourceOnMainRenderThread,
88                    base::Unretained(source)));
89   }
90 }
91
92 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
93     const scoped_refptr<media::VideoFrame>& frame,
94     const media::VideoCaptureFormat& format) {
95   DCHECK(io_thread_checker_.CalledOnValidThread());
96   libjingle_worker_thread_->PostTask(
97       FROM_HERE,
98       base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread,
99                  this, frame, format));
100 }
101
102 void
103 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread(
104     const scoped_refptr<media::VideoFrame>& frame,
105     const media::VideoCaptureFormat& format) {
106   DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
107   capture_adapter_->OnFrameCaptured(frame);
108 }
109
110 WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter(
111     const blink::WebMediaStreamTrack& track,
112     MediaStreamDependencyFactory* factory)
113     : web_track_(track) {
114   const blink::WebMediaConstraints& constraints =
115       MediaStreamVideoTrack::GetVideoTrack(track)->constraints();
116
117   bool is_screencast = ConstraintKeyExists(
118       constraints, base::UTF8ToUTF16(kMediaStreamSource));
119   WebRtcVideoCapturerAdapter* capture_adapter =
120       factory->CreateVideoCapturer(is_screencast);
121
122   // |video_source| owns |capture_adapter|
123   scoped_refptr<webrtc::VideoSourceInterface> video_source(
124       factory->CreateVideoSource(capture_adapter,
125                                  track.source().constraints()));
126
127   video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(),
128                                                 video_source.get());
129
130   video_track_->set_enabled(web_track_.isEnabled());
131
132   source_adapter_ = new WebRtcVideoSourceAdapter(
133       factory->GetWebRtcWorkerThread(),
134       video_source,
135       capture_adapter);
136
137   AddToVideoTrack(
138       this,
139       base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO,
140                  source_adapter_),
141       web_track_);
142
143   DVLOG(3) << "WebRtcVideoTrackAdapter ctor() : is_screencast "
144            << is_screencast;
145 }
146
147 WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() {
148   DCHECK(thread_checker_.CalledOnValidThread());
149   DVLOG(3) << "WebRtcVideoTrackAdapter dtor().";
150   RemoveFromVideoTrack(this, web_track_);
151 }
152
153 void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) {
154   DCHECK(thread_checker_.CalledOnValidThread());
155   video_track_->set_enabled(enabled);
156 }
157
158 }  // namespace content