OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/webrtc/webrtc_video_track_adapter.h" | 5 #include "content/renderer/media/webrtc/webrtc_video_track_adapter.h" |
6 | 6 |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "content/common/media/media_stream_options.h" | 8 #include "content/common/media/media_stream_options.h" |
9 #include "content/renderer/media/media_stream_video_source.h" | 9 #include "content/renderer/media/media_stream_video_source.h" |
10 #include "content/renderer/media/media_stream_video_track.h" | 10 #include "content/renderer/media/media_stream_video_track.h" |
11 | 11 |
12 namespace { | 12 namespace { |
13 | 13 |
14 bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints, | 14 bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints, |
15 const blink::WebString& name) { | 15 const blink::WebString& name) { |
16 blink::WebString value_str; | 16 blink::WebString value_str; |
17 return constraints.getMandatoryConstraintValue(name, value_str) || | 17 return constraints.getMandatoryConstraintValue(name, value_str) || |
18 constraints.getOptionalConstraintValue(name, value_str); | 18 constraints.getOptionalConstraintValue(name, value_str); |
19 } | 19 } |
20 | 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 | |
21 } // anonymouse namespace | 27 } // anonymouse namespace |
22 | 28 |
23 namespace content { | 29 namespace content { |
24 | 30 |
25 // Simple help class used for receiving video frames on the IO-thread from | 31 // Simple help class used for receiving video frames on the IO-thread from |
26 // a MediaStreamVideoTrack and forward the frames to a | 32 // a MediaStreamVideoTrack and forward the frames to a |
27 // WebRtcVideoCapturerAdapter that implements a video capturer for libjingle. | 33 // WebRtcVideoCapturerAdapter that implements a video capturer for libjingle. |
28 class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter | 34 class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter |
29 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { | 35 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { |
30 public: | 36 public: |
31 WebRtcVideoSourceAdapter( | 37 WebRtcVideoSourceAdapter( |
38 const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread, | |
32 const scoped_refptr<webrtc::VideoSourceInterface>& source, | 39 const scoped_refptr<webrtc::VideoSourceInterface>& source, |
33 WebRtcVideoCapturerAdapter* capture_adapter); | 40 WebRtcVideoCapturerAdapter* capture_adapter); |
34 | 41 |
35 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, | 42 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, |
36 const media::VideoCaptureFormat& format); | 43 const media::VideoCaptureFormat& format); |
37 | 44 |
38 private: | 45 private: |
46 void OnVideoFrameOnWt(const scoped_refptr<media::VideoFrame>& frame, | |
tommi (sloooow) - chröme
2014/05/12 14:20:41
OnVideoFrameOnWorkerThread
perkj_chrome
2014/05/12 15:39:51
Done.
| |
47 const media::VideoCaptureFormat& format); | |
39 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>; | 48 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>; |
40 virtual ~WebRtcVideoSourceAdapter(); | 49 virtual ~WebRtcVideoSourceAdapter(); |
41 | 50 |
51 scoped_refptr<base::MessageLoopProxy> render_thread_message_loop_; | |
52 | |
42 // Used to DCHECK that frames are called on the IO-thread. | 53 // Used to DCHECK that frames are called on the IO-thread. |
43 base::ThreadChecker io_thread_checker_; | 54 base::ThreadChecker io_thread_checker_; |
55 | |
56 // Used for posting frames to libjingles worker thread. Accessed on the | |
tommi (sloooow) - chröme
2014/05/12 14:20:41
libjingle's
perkj_chrome
2014/05/12 15:39:51
Done.
| |
57 // IO-thread. | |
58 scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_; | |
59 | |
44 scoped_refptr<webrtc::VideoSourceInterface> video_source_; | 60 scoped_refptr<webrtc::VideoSourceInterface> video_source_; |
45 // |capture_adapter_| is owned by |video_source_| | 61 // |capture_adapter_| is owned by |video_source_| |
46 WebRtcVideoCapturerAdapter* capture_adapter_; | 62 WebRtcVideoCapturerAdapter* capture_adapter_; |
47 }; | 63 }; |
48 | 64 |
49 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( | 65 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( |
66 const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread, | |
50 const scoped_refptr<webrtc::VideoSourceInterface>& source, | 67 const scoped_refptr<webrtc::VideoSourceInterface>& source, |
51 WebRtcVideoCapturerAdapter* capture_adapter) | 68 WebRtcVideoCapturerAdapter* capture_adapter) |
52 : video_source_(source), | 69 : render_thread_message_loop_(base::MessageLoopProxy::current()), |
70 libjingle_worker_thread_(libjingle_worker_thread), | |
71 video_source_(source), | |
53 capture_adapter_(capture_adapter) { | 72 capture_adapter_(capture_adapter) { |
54 io_thread_checker_.DetachFromThread(); | 73 io_thread_checker_.DetachFromThread(); |
55 } | 74 } |
56 | 75 |
57 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() { | 76 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() { |
77 // Since frames are posted to the worker thread, this object might be deleted | |
78 // on that thread. However, since |video_source_| was created on the render | |
79 // thread, we should release our reference on the render thread. This is not | |
tommi (sloooow) - chröme
2014/05/12 14:20:41
nit: s/should/must
| |
80 // strictly necessary since both the main render thread and the worker thread | |
81 // implements libjingle's thread Send method. | |
tommi (sloooow) - chröme
2014/05/12 14:20:41
nit: implement
(no s)
After reading why this isn'
perkj_chrome
2014/05/12 15:39:51
ok- I removed the whole comment instead since we d
| |
82 if (!render_thread_message_loop_->BelongsToCurrentThread()) { | |
tommi (sloooow) - chröme
2014/05/12 14:20:41
I think that if at all possible to avoid this, we
perkj_chrome
2014/05/12 15:39:51
Suggestions? We have 3 - threads here. Render thre
| |
83 webrtc::VideoSourceInterface* source = video_source_.get(); | |
84 source->AddRef(); | |
85 video_source_ = NULL; | |
86 render_thread_message_loop_->PostTask( | |
87 FROM_HERE, | |
88 base::Bind(&ReleaseWebRtcSourceOnMainRenderThread, | |
89 base::Unretained(source))); | |
90 } | |
58 } | 91 } |
59 | 92 |
60 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( | 93 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( |
61 const scoped_refptr<media::VideoFrame>& frame, | 94 const scoped_refptr<media::VideoFrame>& frame, |
62 const media::VideoCaptureFormat& format) { | 95 const media::VideoCaptureFormat& format) { |
63 DCHECK(io_thread_checker_.CalledOnValidThread()); | 96 DCHECK(io_thread_checker_.CalledOnValidThread()); |
97 libjingle_worker_thread_->PostTask( | |
perkj_chrome
2014/05/12 15:39:51
This is what might cause WebRtcVideoTrackAdapter::
| |
98 FROM_HERE, | |
99 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnWt, | |
100 this, frame, format)); | |
101 } | |
102 | |
103 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWt( | |
104 const scoped_refptr<media::VideoFrame>& frame, | |
105 const media::VideoCaptureFormat& format) { | |
106 DCHECK(libjingle_worker_thread_->BelongsToCurrentThread()); | |
64 capture_adapter_->OnFrameCaptured(frame); | 107 capture_adapter_->OnFrameCaptured(frame); |
65 } | 108 } |
66 | 109 |
67 WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter( | 110 WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter( |
68 const blink::WebMediaStreamTrack& track, | 111 const blink::WebMediaStreamTrack& track, |
69 MediaStreamDependencyFactory* factory) | 112 MediaStreamDependencyFactory* factory) |
70 : web_track_(track) { | 113 : web_track_(track) { |
71 const blink::WebMediaConstraints& constraints = | 114 const blink::WebMediaConstraints& constraints = |
72 MediaStreamVideoTrack::GetVideoTrack(track)->constraints(); | 115 MediaStreamVideoTrack::GetVideoTrack(track)->constraints(); |
73 | 116 |
74 bool is_screencast = ConstraintKeyExists( | 117 bool is_screencast = ConstraintKeyExists( |
75 constraints, base::UTF8ToUTF16(kMediaStreamSource)); | 118 constraints, base::UTF8ToUTF16(kMediaStreamSource)); |
76 WebRtcVideoCapturerAdapter* capture_adapter = | 119 WebRtcVideoCapturerAdapter* capture_adapter = |
77 factory->CreateVideoCapturer(is_screencast); | 120 factory->CreateVideoCapturer(is_screencast); |
78 | 121 |
79 // |video_source| owns |capture_adapter| | 122 // |video_source| owns |capture_adapter| |
80 scoped_refptr<webrtc::VideoSourceInterface> video_source( | 123 scoped_refptr<webrtc::VideoSourceInterface> video_source( |
81 factory->CreateVideoSource(capture_adapter, | 124 factory->CreateVideoSource(capture_adapter, |
82 track.source().constraints())); | 125 track.source().constraints())); |
83 | 126 |
84 video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(), | 127 video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(), |
85 video_source.get()); | 128 video_source.get()); |
86 | 129 |
87 video_track_->set_enabled(web_track_.isEnabled()); | 130 video_track_->set_enabled(web_track_.isEnabled()); |
88 | 131 |
89 source_adapter_ = new WebRtcVideoSourceAdapter(video_source, | 132 source_adapter_ = new WebRtcVideoSourceAdapter( |
90 capture_adapter); | 133 factory->worker_thread_proxy(), |
134 video_source, | |
135 capture_adapter); | |
91 | 136 |
92 AddToVideoTrack( | 137 AddToVideoTrack( |
93 this, | 138 this, |
94 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, | 139 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, |
95 source_adapter_), | 140 source_adapter_), |
96 web_track_); | 141 web_track_); |
97 | 142 |
98 DVLOG(3) << "WebRtcVideoTrackAdapter ctor() : is_screencast " | 143 DVLOG(3) << "WebRtcVideoTrackAdapter ctor() : is_screencast " |
99 << is_screencast; | 144 << is_screencast; |
100 } | 145 } |
101 | 146 |
102 WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() { | 147 WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() { |
103 DCHECK(thread_checker_.CalledOnValidThread()); | 148 DCHECK(thread_checker_.CalledOnValidThread()); |
104 DVLOG(3) << "WebRtcVideoTrackAdapter dtor()."; | 149 DVLOG(3) << "WebRtcVideoTrackAdapter dtor()."; |
105 RemoveFromVideoTrack(this, web_track_); | 150 RemoveFromVideoTrack(this, web_track_); |
106 } | 151 } |
107 | 152 |
108 void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) { | 153 void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) { |
109 DCHECK(thread_checker_.CalledOnValidThread()); | 154 DCHECK(thread_checker_.CalledOnValidThread()); |
110 video_track_->set_enabled(enabled); | 155 video_track_->set_enabled(enabled); |
111 } | 156 } |
112 | 157 |
113 } // namespace content | 158 } // namespace content |
OLD | NEW |