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/media_stream_video_webrtc_sink.h" | 5 #include "content/renderer/media/webrtc/media_stream_video_webrtc_sink.h" |
6 | 6 |
7 #include "base/location.h" | 7 #include "base/location.h" |
8 #include "base/numerics/safe_conversions.h" | 8 #include "base/numerics/safe_conversions.h" |
9 #include "base/single_thread_task_runner.h" | 9 #include "base/single_thread_task_runner.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 | 52 |
53 // The default number of microseconds that should elapse since the last video | 53 // The default number of microseconds that should elapse since the last video |
54 // frame was received, before requesting a refresh frame. | 54 // frame was received, before requesting a refresh frame. |
55 const int64_t kDefaultRefreshIntervalMicros = | 55 const int64_t kDefaultRefreshIntervalMicros = |
56 base::Time::kMicrosecondsPerSecond; | 56 base::Time::kMicrosecondsPerSecond; |
57 | 57 |
58 // A lower-bound for the refresh interval. | 58 // A lower-bound for the refresh interval. |
59 const int64_t kLowerBoundRefreshIntervalMicros = | 59 const int64_t kLowerBoundRefreshIntervalMicros = |
60 base::Time::kMicrosecondsPerSecond / media::limits::kMaxFramesPerSecond; | 60 base::Time::kMicrosecondsPerSecond / media::limits::kMaxFramesPerSecond; |
61 | 61 |
62 webrtc::VideoTrackInterface::ContentHint TranslateContentHint( | |
63 blink::WebMediaStreamTrack::ContentHintType content_hint) { | |
64 switch (content_hint) { | |
65 case blink::WebMediaStreamTrack::ContentHintType::None: | |
66 return webrtc::VideoTrackInterface::ContentHint::kNone; | |
67 case blink::WebMediaStreamTrack::ContentHintType::AudioSpeech: | |
68 case blink::WebMediaStreamTrack::ContentHintType::AudioMusic: | |
69 NOTREACHED(); | |
mcasas
2016/12/19 19:32:05
Why are these hints causing a NOTREACHED() ?
IOW w
pbos
2016/12/19 19:42:09
They should never be settable on a video track. Th
| |
70 break; | |
71 case blink::WebMediaStreamTrack::ContentHintType::VideoFluid: | |
72 return webrtc::VideoTrackInterface::ContentHint::kFluid; | |
73 case blink::WebMediaStreamTrack::ContentHintType::VideoDetailed: | |
74 return webrtc::VideoTrackInterface::ContentHint::kDetailed; | |
75 } | |
76 NOTREACHED(); | |
77 return webrtc::VideoTrackInterface::ContentHint::kNone; | |
78 } | |
79 | |
62 } // namespace | 80 } // namespace |
63 | 81 |
64 // Simple help class used for receiving video frames on the IO-thread from a | 82 // Simple help class used for receiving video frames on the IO-thread from a |
65 // MediaStreamVideoTrack and forward the frames to a WebRtcVideoCapturerAdapter | 83 // MediaStreamVideoTrack and forward the frames to a WebRtcVideoCapturerAdapter |
66 // on libjingle's worker thread. WebRtcVideoCapturerAdapter implements a video | 84 // on libjingle's worker thread. WebRtcVideoCapturerAdapter implements a video |
67 // capturer for libjingle. | 85 // capturer for libjingle. |
68 class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter | 86 class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter |
69 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { | 87 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { |
70 public: | 88 public: |
71 WebRtcVideoSourceAdapter(const scoped_refptr<base::SingleThreadTaskRunner>& | 89 WebRtcVideoSourceAdapter(const scoped_refptr<base::SingleThreadTaskRunner>& |
72 libjingle_worker_thread, | 90 libjingle_worker_thread, |
73 const scoped_refptr<WebRtcVideoSource>& source, | 91 const scoped_refptr<WebRtcVideoSource>& source, |
74 base::TimeDelta refresh_interval, | 92 base::TimeDelta refresh_interval, |
75 const base::Closure& refresh_callback); | 93 const base::Closure& refresh_callback); |
76 | 94 |
77 // MediaStreamVideoWebRtcSink can be destroyed on the main render thread or | 95 // MediaStreamVideoWebRtcSink can be destroyed on the main render thread or |
78 // libjingles worker thread since it posts video frames on that thread. But | 96 // libjingles worker thread since it posts video frames on that thread. But |
79 // |video_source_| must be released on the main render thread before the | 97 // |video_source_| must be released on the main render thread before the |
80 // PeerConnectionFactory has been destroyed. The only way to ensure that is to | 98 // PeerConnectionFactory has been destroyed. The only way to ensure that is to |
81 // make sure |video_source_| is released when MediaStreamVideoWebRtcSink() is | 99 // make sure |video_source_| is released when MediaStreamVideoWebRtcSink() is |
82 // destroyed. | 100 // destroyed. |
83 void ReleaseSourceOnMainThread(); | 101 void ReleaseSourceOnMainThread(); |
84 | 102 |
103 void SetContentHint(blink::WebMediaStreamTrack::ContentHintType content_hint); | |
104 | |
85 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, | 105 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, |
86 base::TimeTicks estimated_capture_time); | 106 base::TimeTicks estimated_capture_time); |
87 | 107 |
88 private: | 108 private: |
109 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>; | |
110 | |
89 void OnVideoFrameOnWorkerThread( | 111 void OnVideoFrameOnWorkerThread( |
90 const scoped_refptr<media::VideoFrame>& frame); | 112 const scoped_refptr<media::VideoFrame>& frame); |
91 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>; | 113 |
114 void SetContentHintOnWorkerThread( | |
115 blink::WebMediaStreamTrack::ContentHintType content_hint); | |
116 | |
92 virtual ~WebRtcVideoSourceAdapter(); | 117 virtual ~WebRtcVideoSourceAdapter(); |
93 | 118 |
94 // Called whenever a video frame was just delivered on the IO thread. This | 119 // Called whenever a video frame was just delivered on the IO thread. This |
95 // restarts the delay period before the |refresh_timer_| will fire the next | 120 // restarts the delay period before the |refresh_timer_| will fire the next |
96 // time. | 121 // time. |
97 void ResetRefreshTimerOnMainThread(); | 122 void ResetRefreshTimerOnMainThread(); |
98 | 123 |
99 scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner_; | 124 scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner_; |
100 | 125 |
101 // |render_thread_checker_| is bound to the main render thread. | 126 // |render_thread_checker_| is bound to the main render thread. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 DVLOG(3) << "~WebRtcVideoSourceAdapter()"; | 179 DVLOG(3) << "~WebRtcVideoSourceAdapter()"; |
155 DCHECK(!capture_adapter_); | 180 DCHECK(!capture_adapter_); |
156 // This object can be destroyed on the main render thread or libjingles worker | 181 // This object can be destroyed on the main render thread or libjingles worker |
157 // thread since it posts video frames on that thread. But |video_source_| must | 182 // thread since it posts video frames on that thread. But |video_source_| must |
158 // be released on the main render thread before the PeerConnectionFactory has | 183 // be released on the main render thread before the PeerConnectionFactory has |
159 // been destroyed. The only way to ensure that is to make sure |video_source_| | 184 // been destroyed. The only way to ensure that is to make sure |video_source_| |
160 // is released when MediaStreamVideoWebRtcSink() is destroyed. | 185 // is released when MediaStreamVideoWebRtcSink() is destroyed. |
161 } | 186 } |
162 | 187 |
163 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter:: | 188 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter:: |
164 ResetRefreshTimerOnMainThread() { | 189 ResetRefreshTimerOnMainThread() { |
165 DCHECK(render_thread_checker_.CalledOnValidThread()); | 190 DCHECK(render_thread_checker_.CalledOnValidThread()); |
166 if (refresh_timer_.IsRunning()) | 191 if (refresh_timer_.IsRunning()) |
167 refresh_timer_.Reset(); | 192 refresh_timer_.Reset(); |
168 } | 193 } |
169 | 194 |
170 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter:: | 195 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter:: |
171 ReleaseSourceOnMainThread() { | 196 ReleaseSourceOnMainThread() { |
172 DCHECK(render_thread_checker_.CalledOnValidThread()); | 197 DCHECK(render_thread_checker_.CalledOnValidThread()); |
173 // Since frames are posted to the worker thread, this object might be deleted | 198 // Since frames are posted to the worker thread, this object might be deleted |
174 // on that thread. However, since |video_source_| was created on the render | 199 // on that thread. However, since |video_source_| was created on the render |
175 // thread, it should be released on the render thread. | 200 // thread, it should be released on the render thread. |
176 base::AutoLock auto_lock(capture_adapter_stop_lock_); | 201 base::AutoLock auto_lock(capture_adapter_stop_lock_); |
177 // |video_source| owns |capture_adapter_|. | 202 // |video_source| owns |capture_adapter_|. |
178 capture_adapter_ = NULL; | 203 capture_adapter_ = NULL; |
179 video_source_ = NULL; | 204 video_source_ = NULL; |
180 } | 205 } |
181 | 206 |
207 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::SetContentHint( | |
208 blink::WebMediaStreamTrack::ContentHintType content_hint) { | |
209 DCHECK(render_thread_checker_.CalledOnValidThread()); | |
210 libjingle_worker_thread_->PostTask( | |
211 FROM_HERE, | |
212 base::Bind(&WebRtcVideoSourceAdapter::SetContentHintOnWorkerThread, this, | |
213 content_hint)); | |
214 } | |
215 | |
216 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter:: | |
217 SetContentHintOnWorkerThread( | |
218 blink::WebMediaStreamTrack::ContentHintType content_hint) { | |
219 DCHECK(libjingle_worker_thread_->BelongsToCurrentThread()); | |
220 base::AutoLock auto_lock(capture_adapter_stop_lock_); | |
221 if (capture_adapter_) | |
222 capture_adapter_->SetContentHint(content_hint); | |
223 } | |
224 | |
182 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( | 225 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( |
183 const scoped_refptr<media::VideoFrame>& frame, | 226 const scoped_refptr<media::VideoFrame>& frame, |
184 base::TimeTicks estimated_capture_time) { | 227 base::TimeTicks estimated_capture_time) { |
185 DCHECK(io_thread_checker_.CalledOnValidThread()); | 228 DCHECK(io_thread_checker_.CalledOnValidThread()); |
186 render_thread_task_runner_->PostTask( | 229 render_thread_task_runner_->PostTask( |
187 FROM_HERE, | 230 FROM_HERE, |
188 base::Bind(&WebRtcVideoSourceAdapter::ResetRefreshTimerOnMainThread, | 231 base::Bind(&WebRtcVideoSourceAdapter::ResetRefreshTimerOnMainThread, |
189 this)); | 232 this)); |
190 libjingle_worker_thread_->PostTask( | 233 libjingle_worker_thread_->PostTask( |
191 FROM_HERE, | 234 FROM_HERE, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 if (refresh_interval.InMicroseconds() < kLowerBoundRefreshIntervalMicros) { | 303 if (refresh_interval.InMicroseconds() < kLowerBoundRefreshIntervalMicros) { |
261 refresh_interval = | 304 refresh_interval = |
262 base::TimeDelta::FromMicroseconds(kLowerBoundRefreshIntervalMicros); | 305 base::TimeDelta::FromMicroseconds(kLowerBoundRefreshIntervalMicros); |
263 } | 306 } |
264 } | 307 } |
265 | 308 |
266 // TODO(pbos): Consolidate WebRtcVideoCapturerAdapter into WebRtcVideoSource | 309 // TODO(pbos): Consolidate WebRtcVideoCapturerAdapter into WebRtcVideoSource |
267 // by removing the need for and dependency on a cricket::VideoCapturer. | 310 // by removing the need for and dependency on a cricket::VideoCapturer. |
268 video_source_ = scoped_refptr<WebRtcVideoSource>( | 311 video_source_ = scoped_refptr<WebRtcVideoSource>( |
269 new rtc::RefCountedObject<WebRtcVideoSource>( | 312 new rtc::RefCountedObject<WebRtcVideoSource>( |
270 new WebRtcVideoCapturerAdapter(is_screencast), is_screencast, | 313 new WebRtcVideoCapturerAdapter(is_screencast, track.contentHint()), |
271 needs_denoising)); | 314 is_screencast, needs_denoising)); |
272 | 315 |
273 // TODO(pbos): Consolidate the local video track with the source proxy and | 316 // TODO(pbos): Consolidate the local video track with the source proxy and |
274 // move into PeerConnectionDependencyFactory. This now separately holds on a | 317 // move into PeerConnectionDependencyFactory. This now separately holds on a |
275 // reference to the proxy object because | 318 // reference to the proxy object because |
276 // PeerConnectionFactory::CreateVideoTrack doesn't do reference counting. | 319 // PeerConnectionFactory::CreateVideoTrack doesn't do reference counting. |
277 video_source_proxy_ = | 320 video_source_proxy_ = |
278 factory->CreateVideoTrackSourceProxy(video_source_.get()); | 321 factory->CreateVideoTrackSourceProxy(video_source_.get()); |
279 video_track_ = factory->CreateLocalVideoTrack(track.id().utf8(), | 322 video_track_ = factory->CreateLocalVideoTrack(track.id().utf8(), |
280 video_source_proxy_.get()); | 323 video_source_proxy_.get()); |
281 | 324 |
325 video_track_->set_content_hint(TranslateContentHint(track.contentHint())); | |
mcasas
2016/12/19 19:32:05
Isn't this repeating what's done in l.313?
pbos
2016/12/19 19:42:09
Nope, l.313 is for the adapter.
| |
282 video_track_->set_enabled(track.isEnabled()); | 326 video_track_->set_enabled(track.isEnabled()); |
283 | 327 |
284 source_adapter_ = new WebRtcVideoSourceAdapter( | 328 source_adapter_ = new WebRtcVideoSourceAdapter( |
285 factory->GetWebRtcWorkerThread(), video_source_.get(), refresh_interval, | 329 factory->GetWebRtcWorkerThread(), video_source_.get(), refresh_interval, |
286 base::Bind(&MediaStreamVideoWebRtcSink::RequestRefreshFrame, | 330 base::Bind(&MediaStreamVideoWebRtcSink::RequestRefreshFrame, |
287 weak_factory_.GetWeakPtr())); | 331 weak_factory_.GetWeakPtr())); |
288 | 332 |
289 MediaStreamVideoSink::ConnectToTrack( | 333 MediaStreamVideoSink::ConnectToTrack( |
290 track, | 334 track, |
291 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_), | 335 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_), |
292 false); | 336 false); |
293 | 337 |
294 DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast " | 338 DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast " |
295 << is_screencast; | 339 << is_screencast; |
296 } | 340 } |
297 | 341 |
298 MediaStreamVideoWebRtcSink::~MediaStreamVideoWebRtcSink() { | 342 MediaStreamVideoWebRtcSink::~MediaStreamVideoWebRtcSink() { |
299 DCHECK(thread_checker_.CalledOnValidThread()); | 343 DCHECK(thread_checker_.CalledOnValidThread()); |
300 DVLOG(3) << "MediaStreamVideoWebRtcSink dtor()."; | 344 DVLOG(3) << "MediaStreamVideoWebRtcSink dtor()."; |
301 weak_factory_.InvalidateWeakPtrs(); | 345 weak_factory_.InvalidateWeakPtrs(); |
302 MediaStreamVideoSink::DisconnectFromTrack(); | 346 MediaStreamVideoSink::DisconnectFromTrack(); |
303 source_adapter_->ReleaseSourceOnMainThread(); | 347 source_adapter_->ReleaseSourceOnMainThread(); |
304 } | 348 } |
305 | 349 |
306 void MediaStreamVideoWebRtcSink::OnEnabledChanged(bool enabled) { | 350 void MediaStreamVideoWebRtcSink::OnEnabledChanged(bool enabled) { |
307 DCHECK(thread_checker_.CalledOnValidThread()); | 351 DCHECK(thread_checker_.CalledOnValidThread()); |
308 video_track_->set_enabled(enabled); | 352 video_track_->set_enabled(enabled); |
309 } | 353 } |
310 | 354 |
355 void MediaStreamVideoWebRtcSink::OnContentHintChanged( | |
356 blink::WebMediaStreamTrack::ContentHintType content_hint) { | |
357 DCHECK(thread_checker_.CalledOnValidThread()); | |
358 source_adapter_->SetContentHint(content_hint); | |
mcasas
2016/12/19 19:32:05
IIUC,WebRtcVideoCapturerAdapter::SetContentHint()
pbos
2016/12/19 19:42:09
We are on the renderer (signalling) thread here. S
| |
359 video_track_->set_content_hint(TranslateContentHint(content_hint)); | |
360 } | |
361 | |
311 void MediaStreamVideoWebRtcSink::RequestRefreshFrame() { | 362 void MediaStreamVideoWebRtcSink::RequestRefreshFrame() { |
312 DCHECK(thread_checker_.CalledOnValidThread()); | 363 DCHECK(thread_checker_.CalledOnValidThread()); |
313 content::RequestRefreshFrameFromVideoTrack(connected_track()); | 364 content::RequestRefreshFrameFromVideoTrack(connected_track()); |
314 } | 365 } |
315 | 366 |
316 rtc::Optional<bool> MediaStreamVideoWebRtcSink::SourceNeedsDenoisingForTesting() | 367 rtc::Optional<bool> MediaStreamVideoWebRtcSink::SourceNeedsDenoisingForTesting() |
317 const { | 368 const { |
318 return video_source_->needs_denoising(); | 369 return video_source_->needs_denoising(); |
319 } | 370 } |
320 | 371 |
321 } // namespace content | 372 } // namespace content |
OLD | NEW |