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/media_stream_video_capturer_source.h" | 5 #include "content/renderer/media/media_stream_video_capturer_source.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "content/public/common/media_stream_request.h" |
| 11 #include "content/renderer/media/media_stream_constraints_util.h" |
10 #include "content/renderer/media/video_capture_impl_manager.h" | 12 #include "content/renderer/media/video_capture_impl_manager.h" |
11 #include "content/renderer/render_thread_impl.h" | 13 #include "content/renderer/render_thread_impl.h" |
12 #include "media/base/bind_to_current_loop.h" | 14 #include "media/base/bind_to_current_loop.h" |
| 15 #include "media/base/limits.h" |
13 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
14 | 17 |
| 18 namespace content { |
| 19 |
15 namespace { | 20 namespace { |
16 | 21 |
17 // Resolutions used if the source doesn't support capability enumeration. | 22 // Resolutions used if the source doesn't support capability enumeration. |
18 struct { | 23 struct { |
19 int width; | 24 int width; |
20 int height; | 25 int height; |
21 } const kVideoResolutions[] = {{1920, 1080}, | 26 } const kVideoResolutions[] = {{1920, 1080}, |
22 {1280, 720}, | 27 {1280, 720}, |
23 {960, 720}, | 28 {960, 720}, |
24 {640, 480}, | 29 {640, 480}, |
25 {640, 360}, | 30 {640, 360}, |
26 {320, 240}, | 31 {320, 240}, |
27 {320, 180}}; | 32 {320, 180}}; |
28 | 33 |
29 // Frame rates for sources with no support for capability enumeration. | 34 // Frame rates for sources with no support for capability enumeration. |
30 const int kVideoFrameRates[] = {30, 60}; | 35 const int kVideoFrameRates[] = {30, 60}; |
31 | 36 |
32 // Hard upper-bound frame rate for tab/desktop capture. | 37 // Hard upper-bound frame rate for tab/desktop capture. |
33 const double kMaxScreenCastFrameRate = 120.0; | 38 const double kMaxScreenCastFrameRate = 120.0; |
34 | 39 |
| 40 // Returns true if the value for width or height is reasonable. |
| 41 bool DimensionValueIsValid(int x) { |
| 42 return x > 0 && x <= media::limits::kMaxDimension; |
| 43 } |
| 44 |
| 45 // Returns true if the value for frame rate is reasonable. |
| 46 bool FrameRateValueIsValid(double frame_rate) { |
| 47 return (frame_rate > (1.0 / 60.0)) && // Lower-bound: One frame per minute. |
| 48 (frame_rate <= media::limits::kMaxFramesPerSecond); |
| 49 } |
| 50 |
| 51 // Returns true if the aspect ratio of |a| and |b| are equivalent to two |
| 52 // significant digits. |
| 53 bool AreNearlyEquivalentInAspectRatio(const gfx::Size& a, const gfx::Size& b) { |
| 54 DCHECK(!a.IsEmpty()); |
| 55 DCHECK(!b.IsEmpty()); |
| 56 const int aspect_ratio_a = (100 * a.width()) / a.height(); |
| 57 const int aspect_ratio_b = (100 * b.width()) / b.height(); |
| 58 return aspect_ratio_a == aspect_ratio_b; |
| 59 } |
| 60 |
| 61 // Interprets the properties in |constraints| to override values in |params| and |
| 62 // determine the resolution change policy. |
| 63 void SetScreenCastParamsFromConstraints( |
| 64 const blink::WebMediaConstraints& constraints, |
| 65 MediaStreamType type, |
| 66 media::VideoCaptureParams* params) { |
| 67 // The default resolution change policies for tab versus desktop capture are |
| 68 // the way they are for legacy reasons. |
| 69 if (type == MEDIA_TAB_VIDEO_CAPTURE) { |
| 70 params->resolution_change_policy = |
| 71 media::RESOLUTION_POLICY_FIXED_RESOLUTION; |
| 72 } else if (type == MEDIA_DESKTOP_VIDEO_CAPTURE) { |
| 73 params->resolution_change_policy = |
| 74 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT; |
| 75 } else { |
| 76 NOTREACHED(); |
| 77 } |
| 78 |
| 79 // If the maximum frame resolution was provided in the constraints, use it if |
| 80 // either: 1) none has been set yet; or 2) the maximum specificed is smaller |
| 81 // than the current setting. |
| 82 int width = 0; |
| 83 int height = 0; |
| 84 gfx::Size desired_max_frame_size; |
| 85 if (GetConstraintValueAsInteger(constraints, |
| 86 MediaStreamVideoSource::kMaxWidth, |
| 87 &width) && |
| 88 GetConstraintValueAsInteger(constraints, |
| 89 MediaStreamVideoSource::kMaxHeight, |
| 90 &height) && |
| 91 DimensionValueIsValid(width) && |
| 92 DimensionValueIsValid(height)) { |
| 93 desired_max_frame_size.SetSize(width, height); |
| 94 if (params->requested_format.frame_size.IsEmpty() || |
| 95 desired_max_frame_size.width() < |
| 96 params->requested_format.frame_size.width() || |
| 97 desired_max_frame_size.height() < |
| 98 params->requested_format.frame_size.height()) { |
| 99 params->requested_format.frame_size = desired_max_frame_size; |
| 100 } |
| 101 } |
| 102 |
| 103 // Set the default frame resolution if none was provided. |
| 104 if (params->requested_format.frame_size.IsEmpty()) { |
| 105 params->requested_format.frame_size.SetSize( |
| 106 MediaStreamVideoSource::kDefaultWidth, |
| 107 MediaStreamVideoSource::kDefaultHeight); |
| 108 } |
| 109 |
| 110 // If the maximum frame rate was provided, use it if either: 1) none has been |
| 111 // set yet; or 2) the maximum specificed is smaller than the current setting. |
| 112 double frame_rate = 0.0; |
| 113 if (GetConstraintValueAsDouble(constraints, |
| 114 MediaStreamVideoSource::kMaxFrameRate, |
| 115 &frame_rate) && |
| 116 FrameRateValueIsValid(frame_rate)) { |
| 117 if (params->requested_format.frame_rate <= 0.0f || |
| 118 frame_rate < params->requested_format.frame_rate) { |
| 119 params->requested_format.frame_rate = frame_rate; |
| 120 } |
| 121 } |
| 122 |
| 123 // Set the default frame rate if none was provided. |
| 124 if (params->requested_format.frame_rate <= 0.0f) { |
| 125 params->requested_format.frame_rate = |
| 126 MediaStreamVideoSource::kDefaultFrameRate; |
| 127 } |
| 128 |
| 129 // If the minimum frame resolution was provided, compare it to the maximum |
| 130 // frame resolution to determine the intended resolution change policy. |
| 131 if (!desired_max_frame_size.IsEmpty() && |
| 132 GetConstraintValueAsInteger(constraints, |
| 133 MediaStreamVideoSource::kMinWidth, |
| 134 &width) && |
| 135 GetConstraintValueAsInteger(constraints, |
| 136 MediaStreamVideoSource::kMinHeight, |
| 137 &height) && |
| 138 width <= desired_max_frame_size.width() && |
| 139 height <= desired_max_frame_size.height()) { |
| 140 if (width == desired_max_frame_size.width() && |
| 141 height == desired_max_frame_size.height()) { |
| 142 // Constraints explicitly require a single frame resolution. |
| 143 params->resolution_change_policy = |
| 144 media::RESOLUTION_POLICY_FIXED_RESOLUTION; |
| 145 } else if (DimensionValueIsValid(width) && |
| 146 DimensionValueIsValid(height) && |
| 147 AreNearlyEquivalentInAspectRatio(gfx::Size(width, height), |
| 148 desired_max_frame_size)) { |
| 149 // Constraints only mention a single aspect ratio. |
| 150 params->resolution_change_policy = |
| 151 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO; |
| 152 } else { |
| 153 // Constraints specify a minimum resolution that is smaller than the |
| 154 // maximum resolution and has a different aspect ratio (possibly even |
| 155 // 0x0). This indicates any frame resolution and aspect ratio is |
| 156 // acceptable. |
| 157 params->resolution_change_policy = |
| 158 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT; |
| 159 } |
| 160 } |
| 161 |
| 162 DVLOG(1) << "SetScreenCastParamsFromConstraints: " |
| 163 << params->requested_format.ToString() |
| 164 << " with resolution change policy " |
| 165 << params->resolution_change_policy; |
| 166 } |
| 167 |
35 } // namespace | 168 } // namespace |
36 | 169 |
37 namespace content { | |
38 | |
39 VideoCapturerDelegate::VideoCapturerDelegate( | 170 VideoCapturerDelegate::VideoCapturerDelegate( |
40 const StreamDeviceInfo& device_info) | 171 const StreamDeviceInfo& device_info) |
41 : session_id_(device_info.session_id), | 172 : session_id_(device_info.session_id), |
42 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE || | 173 is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE || |
43 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE), | 174 device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE), |
44 weak_factory_(this) { | 175 weak_factory_(this) { |
45 DVLOG(3) << "VideoCapturerDelegate::ctor"; | 176 DVLOG(3) << "VideoCapturerDelegate::ctor"; |
46 | 177 |
47 // NULL in unit test. | 178 // NULL in unit test. |
48 if (RenderThreadImpl::current()) { | 179 if (RenderThreadImpl::current()) { |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 const VideoCaptureDeviceFormatsCB& callback) { | 370 const VideoCaptureDeviceFormatsCB& callback) { |
240 delegate_->GetCurrentSupportedFormats( | 371 delegate_->GetCurrentSupportedFormats( |
241 max_requested_width, | 372 max_requested_width, |
242 max_requested_height, | 373 max_requested_height, |
243 max_requested_frame_rate, | 374 max_requested_frame_rate, |
244 callback); | 375 callback); |
245 } | 376 } |
246 | 377 |
247 void MediaStreamVideoCapturerSource::StartSourceImpl( | 378 void MediaStreamVideoCapturerSource::StartSourceImpl( |
248 const media::VideoCaptureFormat& format, | 379 const media::VideoCaptureFormat& format, |
| 380 const blink::WebMediaConstraints& constraints, |
249 const VideoCaptureDeliverFrameCB& frame_callback) { | 381 const VideoCaptureDeliverFrameCB& frame_callback) { |
250 media::VideoCaptureParams new_params; | 382 media::VideoCaptureParams new_params; |
251 new_params.requested_format = format; | 383 new_params.requested_format = format; |
252 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE || | 384 if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE || |
253 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { | 385 device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { |
254 new_params.resolution_change_policy = | 386 SetScreenCastParamsFromConstraints( |
255 media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT; | 387 constraints, device_info().device.type, &new_params); |
256 } | 388 } |
257 delegate_->StartCapture( | 389 delegate_->StartCapture( |
258 new_params, | 390 new_params, |
259 frame_callback, | 391 frame_callback, |
260 RenderThreadImpl::current() ? | 392 RenderThreadImpl::current() ? |
261 RenderThreadImpl::current()->GetIOMessageLoopProxy() : | 393 RenderThreadImpl::current()->GetIOMessageLoopProxy() : |
262 nullptr, | 394 nullptr, |
263 base::Bind(&MediaStreamVideoCapturerSource::OnStarted, | 395 base::Bind(&MediaStreamVideoCapturerSource::OnStarted, |
264 base::Unretained(this))); | 396 base::Unretained(this))); |
265 } | 397 } |
266 | 398 |
267 void MediaStreamVideoCapturerSource::StopSourceImpl() { | 399 void MediaStreamVideoCapturerSource::StopSourceImpl() { |
268 delegate_->StopCapture(); | 400 delegate_->StopCapture(); |
269 } | 401 } |
270 | 402 |
271 void MediaStreamVideoCapturerSource::OnStarted(bool result) { | 403 void MediaStreamVideoCapturerSource::OnStarted(bool result) { |
272 OnStartDone(result ? MEDIA_DEVICE_OK : MEDIA_DEVICE_TRACK_START_FAILURE); | 404 OnStartDone(result ? MEDIA_DEVICE_OK : MEDIA_DEVICE_TRACK_START_FAILURE); |
273 } | 405 } |
274 | 406 |
275 } // namespace content | 407 } // namespace content |
OLD | NEW |