Chromium Code Reviews| 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" |
| 11 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
| 12 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 13 #include "base/timer/timer.h" | 13 #include "base/timer/timer.h" |
| 14 #include "content/common/media/media_stream_options.h" | 14 #include "content/common/media/media_stream_options.h" |
| 15 #include "content/public/renderer/media_stream_utils.h" | 15 #include "content/public/renderer/media_stream_utils.h" |
| 16 #include "content/renderer/media/media_stream_constraints_util.h" | 16 #include "content/renderer/media/media_stream_constraints_util.h" |
| 17 #include "content/renderer/media/media_stream_video_track.h" | 17 #include "content/renderer/media/media_stream_video_track.h" |
| 18 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" | 18 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" |
| 19 #include "media/base/limits.h" | 19 #include "media/base/limits.h" |
| 20 #include "third_party/webrtc/api/videosourceproxy.h" | |
| 21 #include "third_party/webrtc/api/videotracksource.h" | |
| 20 | 22 |
| 21 namespace content { | 23 namespace content { |
| 22 | 24 |
| 25 class MediaStreamVideoWebRtcSink::WebRtcVideoSource | |
| 26 : public webrtc::VideoTrackSource { | |
| 27 public: | |
| 28 WebRtcVideoSource(WebRtcVideoCapturerAdapter* capture_adapter, | |
| 29 bool is_screencast, | |
| 30 rtc::Optional<bool> needs_denoising) | |
| 31 : VideoTrackSource(capture_adapter, false), | |
| 32 capture_adapter_(capture_adapter), | |
| 33 is_screencast_(is_screencast), | |
| 34 needs_denoising_(needs_denoising) {} | |
| 35 | |
| 36 WebRtcVideoCapturerAdapter* capture_adapter() const { | |
| 37 return capture_adapter_.get(); | |
| 38 } | |
| 39 | |
| 40 bool is_screencast() const override { return is_screencast_; } | |
| 41 rtc::Optional<bool> needs_denoising() const override { | |
| 42 return needs_denoising_; | |
| 43 } | |
| 44 | |
| 45 private: | |
| 46 std::unique_ptr<WebRtcVideoCapturerAdapter> const capture_adapter_; | |
| 47 const bool is_screencast_; | |
| 48 const rtc::Optional<bool> needs_denoising_; | |
| 49 }; | |
| 50 | |
| 23 namespace { | 51 namespace { |
| 24 | 52 |
| 25 // 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 |
| 26 // frame was received, before requesting a refresh frame. | 54 // frame was received, before requesting a refresh frame. |
| 27 const int64_t kDefaultRefreshIntervalMicros = | 55 const int64_t kDefaultRefreshIntervalMicros = |
| 28 base::Time::kMicrosecondsPerSecond; | 56 base::Time::kMicrosecondsPerSecond; |
| 29 | 57 |
| 30 // A lower-bound for the refresh interval. | 58 // A lower-bound for the refresh interval. |
| 31 const int64_t kLowerBoundRefreshIntervalMicros = | 59 const int64_t kLowerBoundRefreshIntervalMicros = |
| 32 base::Time::kMicrosecondsPerSecond / media::limits::kMaxFramesPerSecond; | 60 base::Time::kMicrosecondsPerSecond / media::limits::kMaxFramesPerSecond; |
| 33 | 61 |
| 34 } // namespace | 62 } // namespace |
| 35 | 63 |
| 36 // Simple help class used for receiving video frames on the IO-thread from a | 64 // Simple help class used for receiving video frames on the IO-thread from a |
| 37 // MediaStreamVideoTrack and forward the frames to a WebRtcVideoCapturerAdapter | 65 // MediaStreamVideoTrack and forward the frames to a WebRtcVideoCapturerAdapter |
| 38 // on libjingle's worker thread. WebRtcVideoCapturerAdapter implements a video | 66 // on libjingle's worker thread. WebRtcVideoCapturerAdapter implements a video |
| 39 // capturer for libjingle. | 67 // capturer for libjingle. |
| 40 class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter | 68 class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter |
| 41 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { | 69 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { |
| 42 public: | 70 public: |
| 43 WebRtcVideoSourceAdapter( | 71 WebRtcVideoSourceAdapter(const scoped_refptr<base::SingleThreadTaskRunner>& |
| 44 const scoped_refptr<base::SingleThreadTaskRunner>& | 72 libjingle_worker_thread, |
| 45 libjingle_worker_thread, | 73 const scoped_refptr<WebRtcVideoSource>& source, |
| 46 const scoped_refptr<webrtc::VideoTrackSourceInterface>& source, | 74 base::TimeDelta refresh_interval, |
| 47 WebRtcVideoCapturerAdapter* capture_adapter, | 75 const base::Closure& refresh_callback); |
| 48 base::TimeDelta refresh_interval, | |
| 49 const base::Closure& refresh_callback); | |
| 50 | 76 |
| 51 // MediaStreamVideoWebRtcSink can be destroyed on the main render thread or | 77 // MediaStreamVideoWebRtcSink can be destroyed on the main render thread or |
| 52 // libjingles worker thread since it posts video frames on that thread. But | 78 // libjingles worker thread since it posts video frames on that thread. But |
| 53 // |video_source_| must be released on the main render thread before the | 79 // |video_source_| must be released on the main render thread before the |
| 54 // PeerConnectionFactory has been destroyed. The only way to ensure that is to | 80 // PeerConnectionFactory has been destroyed. The only way to ensure that is to |
| 55 // make sure |video_source_| is released when MediaStreamVideoWebRtcSink() is | 81 // make sure |video_source_| is released when MediaStreamVideoWebRtcSink() is |
| 56 // destroyed. | 82 // destroyed. |
| 57 void ReleaseSourceOnMainThread(); | 83 void ReleaseSourceOnMainThread(); |
| 58 | 84 |
| 59 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, | 85 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 101 // remote clients that join a distributed session receive a first video frame | 127 // remote clients that join a distributed session receive a first video frame |
| 102 // in a timely manner. Second, it will allow WebRTC's internal bandwidth | 128 // in a timely manner. Second, it will allow WebRTC's internal bandwidth |
| 103 // estimation logic to maintain a more optimal state, since sending a video | 129 // estimation logic to maintain a more optimal state, since sending a video |
| 104 // frame will "prime it." Third, it allows lossy encoders to clean up | 130 // frame will "prime it." Third, it allows lossy encoders to clean up |
| 105 // artifacts in a still image. http://crbug.com/486274 | 131 // artifacts in a still image. http://crbug.com/486274 |
| 106 base::RepeatingTimer refresh_timer_; | 132 base::RepeatingTimer refresh_timer_; |
| 107 }; | 133 }; |
| 108 | 134 |
| 109 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( | 135 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( |
| 110 const scoped_refptr<base::SingleThreadTaskRunner>& libjingle_worker_thread, | 136 const scoped_refptr<base::SingleThreadTaskRunner>& libjingle_worker_thread, |
| 111 const scoped_refptr<webrtc::VideoTrackSourceInterface>& source, | 137 const scoped_refptr<WebRtcVideoSource>& source, |
| 112 WebRtcVideoCapturerAdapter* capture_adapter, | |
| 113 base::TimeDelta refresh_interval, | 138 base::TimeDelta refresh_interval, |
| 114 const base::Closure& refresh_callback) | 139 const base::Closure& refresh_callback) |
| 115 : render_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 140 : render_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 116 libjingle_worker_thread_(libjingle_worker_thread), | 141 libjingle_worker_thread_(libjingle_worker_thread), |
| 117 video_source_(source), | 142 video_source_(source), |
| 118 capture_adapter_(capture_adapter) { | 143 capture_adapter_(source->capture_adapter()) { |
| 119 io_thread_checker_.DetachFromThread(); | 144 io_thread_checker_.DetachFromThread(); |
| 120 if (!refresh_interval.is_zero()) { | 145 if (!refresh_interval.is_zero()) { |
| 121 VLOG(1) << "Starting frame refresh timer with interval " | 146 VLOG(1) << "Starting frame refresh timer with interval " |
| 122 << refresh_interval.InMillisecondsF() << " ms."; | 147 << refresh_interval.InMillisecondsF() << " ms."; |
| 123 refresh_timer_.Start(FROM_HERE, refresh_interval, refresh_callback); | 148 refresh_timer_.Start(FROM_HERE, refresh_interval, refresh_callback); |
| 124 } | 149 } |
| 125 } | 150 } |
| 126 | 151 |
| 127 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter:: | 152 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter:: |
| 128 ~WebRtcVideoSourceAdapter() { | 153 ~WebRtcVideoSourceAdapter() { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 : weak_factory_(this) { | 208 : weak_factory_(this) { |
| 184 const blink::WebMediaConstraints& constraints = | 209 const blink::WebMediaConstraints& constraints = |
| 185 MediaStreamVideoTrack::GetVideoTrack(track)->constraints(); | 210 MediaStreamVideoTrack::GetVideoTrack(track)->constraints(); |
| 186 | 211 |
| 187 // Check for presence of mediaStreamSource constraint. The value is ignored. | 212 // Check for presence of mediaStreamSource constraint. The value is ignored. |
| 188 std::string value; | 213 std::string value; |
| 189 bool is_screencast = GetConstraintValueAsString( | 214 bool is_screencast = GetConstraintValueAsString( |
| 190 constraints, &blink::WebMediaTrackConstraintSet::mediaStreamSource, | 215 constraints, &blink::WebMediaTrackConstraintSet::mediaStreamSource, |
| 191 &value); | 216 &value); |
| 192 | 217 |
| 218 // Extract denoising preference, if no value is set this currently falls back | |
| 219 // to a codec-specific default inside webrtc, hence the tri-state of {on, off | |
| 220 // unset}. | |
| 221 // TODO(pbos): Add tests that make sure that googNoiseReduction has properly | |
|
perkj_chrome
2016/09/26 07:09:04
This class is currently tested in rtc_peer_connect
pbos
2016/09/26 17:11:44
Would like to do it in a follow-up, won't close th
| |
| 222 // propagated from getUserMedia down to a VideoTrackSource. | |
| 223 rtc::Optional<bool> needs_denoising; | |
| 224 bool denoising_value; | |
| 225 if (GetConstraintValueAsBoolean( | |
| 226 constraints, &blink::WebMediaTrackConstraintSet::googNoiseReduction, | |
| 227 &denoising_value)) { | |
| 228 needs_denoising = rtc::Optional<bool>(denoising_value); | |
|
nisse-chromium (ooo August 14)
2016/09/26 06:51:01
Maybe move this logic closer to where needs_denois
pbos
2016/09/26 17:11:44
Done this way to keep constraint extraction in one
| |
| 229 } | |
| 230 | |
| 193 // Enable automatic frame refreshes for the screen capture sources, which will | 231 // Enable automatic frame refreshes for the screen capture sources, which will |
| 194 // stop producing frames whenever screen content is not changing. Check the | 232 // stop producing frames whenever screen content is not changing. Check the |
| 195 // frameRate constraint to determine the rate of refreshes. If a minimum | 233 // frameRate constraint to determine the rate of refreshes. If a minimum |
| 196 // frameRate is provided, use that. Otherwise, use the maximum frameRate if it | 234 // frameRate is provided, use that. Otherwise, use the maximum frameRate if it |
| 197 // happens to be less than the default. | 235 // happens to be less than the default. |
| 198 base::TimeDelta refresh_interval = base::TimeDelta::FromMicroseconds(0); | 236 base::TimeDelta refresh_interval = base::TimeDelta::FromMicroseconds(0); |
| 199 if (is_screencast) { | 237 if (is_screencast) { |
| 200 // Start with the default refresh interval, and refine based on constraints. | 238 // Start with the default refresh interval, and refine based on constraints. |
| 201 refresh_interval = | 239 refresh_interval = |
| 202 base::TimeDelta::FromMicroseconds(kDefaultRefreshIntervalMicros); | 240 base::TimeDelta::FromMicroseconds(kDefaultRefreshIntervalMicros); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 217 base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>( | 255 base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>( |
| 218 base::Time::kMicrosecondsPerSecond / value)); | 256 base::Time::kMicrosecondsPerSecond / value)); |
| 219 refresh_interval = std::max(refresh_interval, alternate_refresh_interval); | 257 refresh_interval = std::max(refresh_interval, alternate_refresh_interval); |
| 220 } | 258 } |
| 221 if (refresh_interval.InMicroseconds() < kLowerBoundRefreshIntervalMicros) { | 259 if (refresh_interval.InMicroseconds() < kLowerBoundRefreshIntervalMicros) { |
| 222 refresh_interval = | 260 refresh_interval = |
| 223 base::TimeDelta::FromMicroseconds(kLowerBoundRefreshIntervalMicros); | 261 base::TimeDelta::FromMicroseconds(kLowerBoundRefreshIntervalMicros); |
| 224 } | 262 } |
| 225 } | 263 } |
| 226 | 264 |
| 227 WebRtcVideoCapturerAdapter* capture_adapter = | 265 // TODO(pbos): Consolidate WebRtcVideoCapturerAdapter into WebRtcVideoSource |
| 228 factory->CreateVideoCapturer(is_screencast); | 266 // by removing the need for and dependency on a cricket::VideoCapturer. |
| 267 video_source_ = scoped_refptr<WebRtcVideoSource>( | |
| 268 new rtc::RefCountedObject<WebRtcVideoSource>( | |
| 269 new WebRtcVideoCapturerAdapter(is_screencast), is_screencast, | |
| 270 needs_denoising)); | |
| 229 | 271 |
| 230 // |video_source| owns |capture_adapter| | 272 // TODO(pbos): Consolidate the local video track with the source proxy and |
| 231 scoped_refptr<webrtc::VideoTrackSourceInterface> video_source( | 273 // move into PeerConnectionDependencyFactory. This now separately holds on a |
| 232 factory->CreateVideoSource(capture_adapter)); | 274 // reference to the proxy object because |
| 233 | 275 // PeerConnectionFactory::CreateVideoTrack doesn't do reference counting. |
| 276 video_source_proxy_ = | |
| 277 factory->CreateVideoTrackSourceProxy(video_source_.get()); | |
| 234 video_track_ = factory->CreateLocalVideoTrack(track.id().utf8(), | 278 video_track_ = factory->CreateLocalVideoTrack(track.id().utf8(), |
| 235 video_source.get()); | 279 video_source_proxy_.get()); |
| 236 | 280 |
| 237 video_track_->set_enabled(track.isEnabled()); | 281 video_track_->set_enabled(track.isEnabled()); |
| 238 | 282 |
| 239 source_adapter_ = new WebRtcVideoSourceAdapter( | 283 source_adapter_ = new WebRtcVideoSourceAdapter( |
| 240 factory->GetWebRtcWorkerThread(), | 284 factory->GetWebRtcWorkerThread(), video_source_.get(), refresh_interval, |
| 241 video_source, | |
| 242 capture_adapter, | |
| 243 refresh_interval, | |
| 244 base::Bind(&MediaStreamVideoWebRtcSink::RequestRefreshFrame, | 285 base::Bind(&MediaStreamVideoWebRtcSink::RequestRefreshFrame, |
| 245 weak_factory_.GetWeakPtr())); | 286 weak_factory_.GetWeakPtr())); |
| 246 | 287 |
| 247 MediaStreamVideoSink::ConnectToTrack( | 288 MediaStreamVideoSink::ConnectToTrack( |
| 248 track, | 289 track, |
| 249 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_), | 290 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_), |
| 250 false); | 291 false); |
| 251 | 292 |
| 252 DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast " | 293 DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast " |
| 253 << is_screencast; | 294 << is_screencast; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 265 DCHECK(thread_checker_.CalledOnValidThread()); | 306 DCHECK(thread_checker_.CalledOnValidThread()); |
| 266 video_track_->set_enabled(enabled); | 307 video_track_->set_enabled(enabled); |
| 267 } | 308 } |
| 268 | 309 |
| 269 void MediaStreamVideoWebRtcSink::RequestRefreshFrame() { | 310 void MediaStreamVideoWebRtcSink::RequestRefreshFrame() { |
| 270 DCHECK(thread_checker_.CalledOnValidThread()); | 311 DCHECK(thread_checker_.CalledOnValidThread()); |
| 271 content::RequestRefreshFrameFromVideoTrack(connected_track()); | 312 content::RequestRefreshFrameFromVideoTrack(connected_track()); |
| 272 } | 313 } |
| 273 | 314 |
| 274 } // namespace content | 315 } // namespace content |
| OLD | NEW |