Commit 2ea50816 authored by Chandan Padhi's avatar Chandan Padhi Committed by Commit Bot

Implement InputDeviceInfo.getCapabilities() for video devices

Bug: 817769
Change-Id: I3f06b5f2360c570ff8c5b4bd800ca1014cc7d088
Reviewed-on: https://chromium-review.googlesource.com/956383
Commit-Queue: Chandan Padhi <c.padhi@samsung.com>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarRaymes Khoury <raymes@chromium.org>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543664}
parent 6a897c71
......@@ -33,17 +33,6 @@ namespace content {
namespace {
// Resolutions used if the source doesn't support capability enumeration.
struct {
int width;
int height;
} const kFallbackVideoResolutions[] = {{1920, 1080}, {1280, 720}, {960, 720},
{640, 480}, {640, 360}, {320, 240},
{320, 180}};
// Frame rates for sources with no support for capability enumeration.
const int kFallbackVideoFrameRates[] = {30, 60};
std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr>
ToVectorAudioInputDeviceCapabilitiesPtr(
const std::vector<blink::mojom::AudioInputDeviceCapabilities>&
......@@ -108,6 +97,7 @@ void MediaDevicesDispatcherHost::EnumerateDevices(
bool request_audio_input,
bool request_video_input,
bool request_audio_output,
bool request_video_input_capabilities,
EnumerateDevicesCallback client_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
......@@ -124,7 +114,8 @@ void MediaDevicesDispatcherHost::EnumerateDevices(
media_stream_manager_->media_devices_manager()->EnumerateDevices(
render_process_id_, render_frame_id_, group_id_salt_base_,
devices_to_enumerate, std::move(client_callback));
devices_to_enumerate, request_video_input_capabilities,
std::move(client_callback));
}
void MediaDevicesDispatcherHost::GetVideoInputCapabilities(
......@@ -233,7 +224,8 @@ void MediaDevicesDispatcherHost::FinalizeGetVideoInputCapabilities(
blink::mojom::VideoInputDeviceCapabilities::New();
capabilities->device_id = std::move(hmac_device_id);
capabilities->formats =
GetVideoInputFormats(descriptor.device_id, true /* try_in_use_first */);
media_stream_manager_->media_devices_manager()->GetVideoInputFormats(
descriptor.device_id, true /* try_in_use_first */);
capabilities->facing_mode = descriptor.facing;
#if defined(OS_ANDROID)
// On Android, the facing mode is not available in the |facing| field,
......@@ -296,53 +288,15 @@ void MediaDevicesDispatcherHost::FinalizeGetVideoInputDeviceFormats(
if (DoesMediaDeviceIDMatchHMAC(device_id_salt, security_origin, device_id,
descriptor.device_id)) {
std::move(client_callback)
.Run(GetVideoInputFormats(descriptor.device_id, try_in_use_first));
.Run(media_stream_manager_->media_devices_manager()
->GetVideoInputFormats(descriptor.device_id,
try_in_use_first));
return;
}
}
std::move(client_callback).Run(media::VideoCaptureFormats());
}
media::VideoCaptureFormats MediaDevicesDispatcherHost::GetVideoInputFormats(
const std::string& device_id,
bool try_in_use_first) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
media::VideoCaptureFormats formats;
if (try_in_use_first) {
base::Optional<media::VideoCaptureFormat> format =
media_stream_manager_->video_capture_manager()->GetDeviceFormatInUse(
MEDIA_DEVICE_VIDEO_CAPTURE, device_id);
if (format.has_value()) {
formats.push_back(format.value());
return formats;
}
}
media_stream_manager_->video_capture_manager()->GetDeviceSupportedFormats(
device_id, &formats);
// Remove formats that have zero resolution.
formats.erase(std::remove_if(formats.begin(), formats.end(),
[](const media::VideoCaptureFormat& format) {
return format.frame_size.GetArea() <= 0;
}),
formats.end());
// If the device does not report any valid format, use a fallback list of
// standard formats.
if (formats.empty()) {
for (const auto& resolution : kFallbackVideoResolutions) {
for (const auto frame_rate : kFallbackVideoFrameRates) {
formats.push_back(media::VideoCaptureFormat(
gfx::Size(resolution.width, resolution.height), frame_rate,
media::PIXEL_FORMAT_I420));
}
}
}
return formats;
}
struct MediaDevicesDispatcherHost::AudioInputCapabilitiesRequest {
std::string device_id_salt;
url::Origin security_origin;
......
......@@ -18,8 +18,6 @@
#include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h"
#include "url/origin.h"
using blink::mojom::MediaDeviceType;
namespace content {
class MediaStreamManager;
......@@ -41,6 +39,7 @@ class CONTENT_EXPORT MediaDevicesDispatcherHost
void EnumerateDevices(bool request_audio_input,
bool request_video_input,
bool request_audio_output,
bool request_video_input_capabilities,
EnumerateDevicesCallback client_callback) override;
void GetVideoInputCapabilities(
GetVideoInputCapabilitiesCallback client_callback) override;
......@@ -111,13 +110,6 @@ class CONTENT_EXPORT MediaDevicesDispatcherHost
const url::Origin& security_origin,
const media::VideoCaptureDeviceDescriptors& device_descriptors);
// Returns the supported video formats for the given |device_id|.
// If |try_in_use_first| is true and the device is being used, only the format
// in use is returned. Otherwise, all formats supported by the device are
// returned.
media::VideoCaptureFormats GetVideoInputFormats(const std::string& device_id,
bool try_in_use_first);
// The following const fields can be accessed on any thread.
const int render_process_id_;
const int render_frame_id_;
......
......@@ -37,6 +37,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
using blink::mojom::MediaDeviceType;
using testing::_;
using testing::SaveArg;
using testing::InvokeWithoutArgs;
......@@ -233,7 +234,9 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
protected:
void DevicesEnumerated(
const base::Closure& closure,
const std::vector<std::vector<MediaDeviceInfo>>& devices) {
const std::vector<std::vector<MediaDeviceInfo>>& devices,
std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities) {
enumerated_devices_ = devices;
closure.Run();
}
......@@ -248,6 +251,7 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
base::RunLoop run_loop;
host_->EnumerateDevices(
enumerate_audio_input, enumerate_video_input, enumerate_audio_output,
false,
base::BindOnce(&MediaDevicesDispatcherHostTest::DevicesEnumerated,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
......
......@@ -37,6 +37,17 @@ namespace content {
namespace {
// Resolutions used if the source doesn't support capability enumeration.
struct {
uint16_t width;
uint16_t height;
} const kFallbackVideoResolutions[] = {{1920, 1080}, {1280, 720}, {960, 720},
{640, 480}, {640, 360}, {320, 240},
{320, 180}};
// Frame rates for sources with no support for capability enumeration.
const uint16_t kFallbackVideoFrameRates[] = {30, 60};
// Private helper method to generate a string for the log message that lists the
// human readable names of |devices|.
std::string GetLogMessageString(MediaDeviceType device_type,
......@@ -258,6 +269,7 @@ void MediaDevicesManager::EnumerateDevices(
int render_frame_id,
const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
......@@ -268,7 +280,7 @@ void MediaDevicesManager::EnumerateDevices(
base::BindOnce(&MediaDevicesManager::CheckPermissionsForEnumerateDevices,
weak_factory_.GetWeakPtr(), render_process_id,
render_frame_id, group_id_salt_base, requested_types,
std::move(callback)));
request_video_input_capabilities, std::move(callback)));
}
uint32_t MediaDevicesManager::SubscribeDeviceChangeNotifications(
......@@ -387,6 +399,45 @@ void MediaDevicesManager::OnDevicesChanged(
}
}
media::VideoCaptureFormats MediaDevicesManager::GetVideoInputFormats(
const std::string& device_id,
bool try_in_use_first) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
media::VideoCaptureFormats formats;
if (try_in_use_first) {
base::Optional<media::VideoCaptureFormat> format =
video_capture_manager_->GetDeviceFormatInUse(MEDIA_DEVICE_VIDEO_CAPTURE,
device_id);
if (format.has_value()) {
formats.push_back(format.value());
return formats;
}
}
video_capture_manager_->GetDeviceSupportedFormats(device_id, &formats);
// Remove formats that have zero resolution.
formats.erase(std::remove_if(formats.begin(), formats.end(),
[](const media::VideoCaptureFormat& format) {
return format.frame_size.GetArea() <= 0;
}),
formats.end());
// If the device does not report any valid format, use a fallback list of
// standard formats.
if (formats.empty()) {
for (const auto& resolution : kFallbackVideoResolutions) {
for (const auto frame_rate : kFallbackVideoFrameRates) {
formats.push_back(media::VideoCaptureFormat(
gfx::Size(resolution.width, resolution.height), frame_rate,
media::PIXEL_FORMAT_I420));
}
}
}
return formats;
}
MediaDeviceInfoArray MediaDevicesManager::GetCachedDeviceInfo(
MediaDeviceType type) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
......@@ -411,6 +462,7 @@ void MediaDevicesManager::CheckPermissionsForEnumerateDevices(
int render_frame_id,
const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
const std::pair<std::string, url::Origin>& salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
......@@ -418,13 +470,15 @@ void MediaDevicesManager::CheckPermissionsForEnumerateDevices(
requested_types, render_process_id, render_frame_id,
base::BindOnce(&MediaDevicesManager::OnPermissionsCheckDone,
weak_factory_.GetWeakPtr(), group_id_salt_base,
requested_types, std::move(callback),
salt_and_origin.first, salt_and_origin.second));
requested_types, request_video_input_capabilities,
std::move(callback), salt_and_origin.first,
salt_and_origin.second));
}
void MediaDevicesManager::OnPermissionsCheckDone(
const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
const std::string& device_id_salt,
const url::Origin& security_origin,
......@@ -434,13 +488,15 @@ void MediaDevicesManager::OnPermissionsCheckDone(
requested_types,
base::BindRepeating(&MediaDevicesManager::OnDevicesEnumerated,
weak_factory_.GetWeakPtr(), group_id_salt_base,
requested_types, base::Passed(&callback),
device_id_salt, security_origin, has_permissions));
requested_types, request_video_input_capabilities,
base::Passed(&callback), device_id_salt,
security_origin, has_permissions));
}
void MediaDevicesManager::OnDevicesEnumerated(
const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
const std::string& device_id_salt,
const url::Origin& security_origin,
......@@ -448,6 +504,9 @@ void MediaDevicesManager::OnDevicesEnumerated(
const MediaDeviceEnumeration& enumeration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::string group_id_salt = group_id_salt_base + device_id_salt;
const bool video_input_capabilities_requested =
has_permissions[MEDIA_DEVICE_TYPE_VIDEO_INPUT] &&
request_video_input_capabilities;
MediaDeviceInfoArray video_device_infos =
enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT];
......@@ -461,16 +520,55 @@ void MediaDevicesManager::OnDevicesEnumerated(
if (!requested_types[i])
continue;
const MediaDeviceInfoArray& device_infos =
i == MEDIA_DEVICE_TYPE_VIDEO_INPUT ? video_device_infos
: enumeration[i];
for (const auto& device_info : device_infos) {
result[i].push_back(TranslateMediaDeviceInfo(
has_permissions[i], device_id_salt, group_id_salt, security_origin,
device_info));
if (i == MEDIA_DEVICE_TYPE_VIDEO_INPUT) {
for (const auto& device_info : video_device_infos) {
MediaDeviceInfo translated_device_info = TranslateMediaDeviceInfo(
has_permissions[i], device_id_salt, group_id_salt, security_origin,
device_info);
if (video_input_capabilities_requested)
translated_device_info.video_facing = device_info.video_facing;
result[i].push_back(translated_device_info);
}
} else {
for (const auto& device_info : enumeration[i]) {
result[i].push_back(TranslateMediaDeviceInfo(
has_permissions[i], device_id_salt, group_id_salt, security_origin,
device_info));
}
}
}
std::move(callback).Run(result);
std::move(callback).Run(
std::move(result),
video_input_capabilities_requested
? ComputeVideoInputCapabilities(result[MEDIA_DEVICE_TYPE_VIDEO_INPUT])
: std::vector<VideoInputDeviceCapabilitiesPtr>());
}
std::vector<VideoInputDeviceCapabilitiesPtr>
MediaDevicesManager::ComputeVideoInputCapabilities(
const MediaDeviceInfoArray& device_infos) {
std::vector<VideoInputDeviceCapabilitiesPtr> video_input_capabilities;
for (const auto& device_info : device_infos) {
VideoInputDeviceCapabilitiesPtr capabilities =
blink::mojom::VideoInputDeviceCapabilities::New();
capabilities->device_id = device_info.device_id;
capabilities->formats = GetVideoInputFormats(device_info.device_id,
false /* try_in_use_first */);
capabilities->facing_mode = device_info.video_facing;
#if defined(OS_ANDROID)
// On Android, the facing mode is not available in the |facing| field,
// but is available as part of the label.
// TODO(guidou): Remove this code once the |facing| field is supported
// on Android. See http://crbug.com/672856.
if (device_info.label.find("front") != std::string::npos)
capabilities->facing_mode = media::MEDIA_VIDEO_FACING_USER;
else if (device_info.label.find("back") != std::string::npos)
capabilities->facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
#endif
video_input_capabilities.push_back(std::move(capabilities));
}
return video_input_capabilities;
}
void MediaDevicesManager::DoEnumerateDevices(MediaDeviceType type) {
......
......@@ -21,8 +21,11 @@
#include "content/common/media/media_devices.h"
#include "media/audio/audio_device_description.h"
#include "media/capture/video/video_capture_device_descriptor.h"
#include "media/capture/video_capture_types.h"
#include "third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom.h"
using blink::mojom::VideoInputDeviceCapabilitiesPtr;
namespace media {
class AudioSystem;
}
......@@ -55,7 +58,8 @@ class CONTENT_EXPORT MediaDevicesManager
using EnumerationCallback =
base::Callback<void(const MediaDeviceEnumeration&)>;
using EnumerateDevicesCallback =
base::OnceCallback<void(const std::vector<MediaDeviceInfoArray>&)>;
base::OnceCallback<void(const std::vector<MediaDeviceInfoArray>&,
std::vector<VideoInputDeviceCapabilitiesPtr>)>;
MediaDevicesManager(
media::AudioSystem* audio_system,
......@@ -83,6 +87,7 @@ class CONTENT_EXPORT MediaDevicesManager
int render_frame_id,
const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback);
uint32_t SubscribeDeviceChangeNotifications(
......@@ -108,6 +113,13 @@ class CONTENT_EXPORT MediaDevicesManager
// changes.
void OnDevicesChanged(base::SystemMonitor::DeviceType device_type) override;
// Returns the supported video formats for the given |device_id|.
// If |try_in_use_first| is true and the device is being used, only the format
// in use is returned. Otherwise, all formats supported by the device are
// returned.
media::VideoCaptureFormats GetVideoInputFormats(const std::string& device_id,
bool try_in_use_first);
// TODO(guidou): Remove this function once content::GetMediaDeviceIDForHMAC
// is rewritten to receive devices via a callback.
// See http://crbug.com/648155.
......@@ -169,11 +181,13 @@ class CONTENT_EXPORT MediaDevicesManager
int render_frame_id,
const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
const std::pair<std::string, url::Origin>& salt_and_origin);
void OnPermissionsCheckDone(
const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
const std::string& device_id_salt,
const url::Origin& security_origin,
......@@ -181,12 +195,16 @@ class CONTENT_EXPORT MediaDevicesManager
void OnDevicesEnumerated(
const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
const std::string& device_id_salt,
const url::Origin& security_origin,
const MediaDevicesManager::BoolDeviceTypes& has_permissions,
const MediaDeviceEnumeration& enumeration);
std::vector<VideoInputDeviceCapabilitiesPtr> ComputeVideoInputCapabilities(
const MediaDeviceInfoArray& device_infos);
// Helpers to issue low-level device enumerations.
void DoEnumerateDevices(MediaDeviceType type);
void EnumerateAudioDevices(bool is_input);
......
......@@ -27,18 +27,6 @@
namespace content {
namespace {
media::VideoFacingMode GetVideoFacingMode(
const blink::WebMediaStreamTrack::FacingMode facing_mode) {
switch (facing_mode) {
case blink::WebMediaStreamTrack::FacingMode::kUser:
return media::MEDIA_VIDEO_FACING_USER;
case blink::WebMediaStreamTrack::FacingMode::kEnvironment:
return media::MEDIA_VIDEO_FACING_ENVIRONMENT;
default:
return media::MEDIA_VIDEO_FACING_NONE;
}
}
void RequestFailed(blink::WebApplyConstraintsRequest request,
const blink::WebString& constraint,
const blink::WebString& message) {
......@@ -257,10 +245,9 @@ VideoCaptureSettings ApplyConstraintsProcessor::SelectVideoSettings(
blink::mojom::VideoInputDeviceCapabilities::New();
device_capabilities->device_id =
current_request_.Track().Source().Id().Ascii();
device_capabilities->facing_mode = GetVideoFacingMode(
GetCurrentVideoSource()
? ToWebFacingMode(GetCurrentVideoSource()->device().video_facing)
: blink::WebMediaStreamTrack::FacingMode::kNone);
device_capabilities->facing_mode =
GetCurrentVideoSource() ? GetCurrentVideoSource()->device().video_facing
: media::MEDIA_VIDEO_FACING_NONE;
device_capabilities->formats = std::move(formats);
DCHECK(video_source_->GetCurrentCaptureParams());
......
......@@ -149,7 +149,6 @@ const char kFakeAudioInputDeviceId1[] = "fake_audio_input 1";
const char kFakeAudioInputDeviceId2[] = "fake_audio_input 2";
const char kFakeVideoInputDeviceId1[] = "fake_video_input 1";
const char kFakeVideoInputDeviceId2[] = "fake_video_input 2";
const char kFakeAudioOutputDeviceId1[] = "fake_audio_output 1";
class MockMediaDevicesDispatcherHost
: public blink::mojom::MediaDevicesDispatcherHost {
......@@ -158,25 +157,9 @@ class MockMediaDevicesDispatcherHost
void EnumerateDevices(bool request_audio_input,
bool request_video_input,
bool request_audio_output,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback) override {
std::vector<std::vector<MediaDeviceInfo>> result(NUM_MEDIA_DEVICE_TYPES);
if (request_audio_input) {
result[MEDIA_DEVICE_TYPE_AUDIO_INPUT].push_back(MediaDeviceInfo(
kFakeAudioInputDeviceId1, "Fake Audio Input 1", "fake_group 1"));
result[MEDIA_DEVICE_TYPE_AUDIO_INPUT].push_back(MediaDeviceInfo(
kFakeAudioInputDeviceId2, "Fake Audio Input 2", "fake_group 2"));
}
if (request_video_input) {
result[MEDIA_DEVICE_TYPE_VIDEO_INPUT].push_back(
MediaDeviceInfo(kFakeVideoInputDeviceId1, "Fake Video Input 1", ""));
result[MEDIA_DEVICE_TYPE_VIDEO_INPUT].push_back(
MediaDeviceInfo(kFakeVideoInputDeviceId2, "Fake Video Input 2", ""));
}
if (request_audio_output) {
result[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT].push_back(MediaDeviceInfo(
kFakeAudioOutputDeviceId1, "Fake Audio Input 1", "fake_group 1"));
}
std::move(callback).Run(result);
NOTREACHED();
}
void GetVideoInputCapabilities(
......
......@@ -109,6 +109,7 @@ void PepperMediaDeviceManager::EnumerateDevices(
CHECK(request_audio_input || request_video_input || request_audio_output);
GetMediaDevicesDispatcher()->EnumerateDevices(
request_audio_input, request_video_input, request_audio_output,
false /* request_video_input_capabilities */,
base::BindOnce(&PepperMediaDeviceManager::DevicesEnumerated, AsWeakPtr(),
callback, ToMediaDeviceType(type)));
#else
......@@ -277,7 +278,9 @@ void PepperMediaDeviceManager::OnDeviceOpened(int request_id,
void PepperMediaDeviceManager::DevicesEnumerated(
const DevicesCallback& client_callback,
MediaDeviceType type,
const std::vector<MediaDeviceInfoArray>& enumeration) {
const std::vector<MediaDeviceInfoArray>& enumeration,
std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities) {
client_callback.Run(FromMediaDeviceInfoArray(type, enumeration[type]));
}
......
......@@ -86,9 +86,12 @@ class PepperMediaDeviceManager
const std::string& label,
const MediaStreamDevice& device);
void DevicesEnumerated(const DevicesCallback& callback,
MediaDeviceType type,
const std::vector<MediaDeviceInfoArray>& enumeration);
void DevicesEnumerated(
const DevicesCallback& callback,
MediaDeviceType type,
const std::vector<MediaDeviceInfoArray>& enumeration,
std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities);
const mojom::MediaStreamDispatcherHostPtr& GetMediaStreamDispatcherHost();
MediaStreamDeviceObserver* GetMediaStreamDeviceObserver() const;
......
......@@ -34,6 +34,10 @@ promise_test(function() {
if (mediainfo.kind == "audioinput") {
assert_equals(typeof capabilities.echoCancellation, "object", "echoCancellation must be an object.");
}
if (mediainfo.kind == "videoinput") {
assert_equals(typeof capabilities.facingMode, "object", "facingMode must be an object.");
verifyVideoRangeProperties(capabilities);
}
} else if ( mediainfo.kind == "audiooutput" ) {
assert_true(mediainfo instanceof MediaDeviceInfo);
} else {
......@@ -42,6 +46,33 @@ promise_test(function() {
}
});
}, "mediaDevices.enumerateDevices() is present and working on navigator");
function verifyVideoRangeProperties(capabilities) {
if (capabilities.hasOwnProperty('width')) {
assert_equals(Object.keys(capabilities.width).length, 2);
assert_true(capabilities.width.hasOwnProperty('min'));
assert_true(capabilities.width.hasOwnProperty('max'));
assert_less_than_equal(capabilities.width.min, capabilities.width.max);
}
if (capabilities.hasOwnProperty('height')) {
assert_equals(Object.keys(capabilities.height).length, 2);
assert_true(capabilities.height.hasOwnProperty('min'));
assert_true(capabilities.height.hasOwnProperty('max'));
assert_less_than_equal(capabilities.height.min, capabilities.height.max);
}
if (capabilities.hasOwnProperty('aspectRatio')) {
assert_equals(Object.keys(capabilities.aspectRatio).length, 2);
assert_true(capabilities.aspectRatio.hasOwnProperty('min'));
assert_true(capabilities.aspectRatio.hasOwnProperty('max'));
assert_less_than_equal(capabilities.aspectRatio.min, capabilities.aspectRatio.max);
}
if (capabilities.hasOwnProperty('frameRate')) {
assert_equals(Object.keys(capabilities.frameRate).length, 2);
assert_true(capabilities.frameRate.hasOwnProperty('min'));
assert_true(capabilities.frameRate.hasOwnProperty('max'));
assert_less_than_equal(capabilities.frameRate.min, capabilities.frameRate.max);
}
}
</script>
</body>
</html>
......@@ -4,10 +4,34 @@
#include "modules/mediastream/InputDeviceInfo.h"
#include <algorithm>
#include "modules/mediastream/MediaTrackCapabilities.h"
namespace blink {
namespace {
// TODO(c.padhi): Merge this method with ToWebFacingMode() in
// media_stream_constraints_util_video_device.h, see https://crbug.com/821668.
WebMediaStreamTrack::FacingMode ToWebFacingMode(mojom::FacingMode facing_mode) {
switch (facing_mode) {
case mojom::FacingMode::NONE:
return WebMediaStreamTrack::FacingMode::kNone;
case mojom::FacingMode::USER:
return WebMediaStreamTrack::FacingMode::kUser;
case mojom::FacingMode::ENVIRONMENT:
return WebMediaStreamTrack::FacingMode::kEnvironment;
case mojom::FacingMode::LEFT:
return WebMediaStreamTrack::FacingMode::kLeft;
case mojom::FacingMode::RIGHT:
return WebMediaStreamTrack::FacingMode::kRight;
}
NOTREACHED();
return WebMediaStreamTrack::FacingMode::kNone;
}
} // namespace
InputDeviceInfo* InputDeviceInfo::Create(const String& device_id,
const String& label,
const String& group_id,
......@@ -21,12 +45,83 @@ InputDeviceInfo::InputDeviceInfo(const String& device_id,
MediaDeviceType device_type)
: MediaDeviceInfo(device_id, label, group_id, device_type) {}
void InputDeviceInfo::SetVideoInputCapabilities(
mojom::blink::VideoInputDeviceCapabilitiesPtr video_input_capabilities) {
DCHECK_EQ(deviceId(), video_input_capabilities->device_id);
// TODO(c.padhi): Merge the common logic below with
// ComputeCapabilitiesForVideoSource() in media_stream_constraints_util.h, see
// https://crbug.com/821668.
platform_capabilities_.facing_mode =
ToWebFacingMode(video_input_capabilities->facing_mode);
if (!video_input_capabilities->formats.IsEmpty()) {
int max_width = 1;
int max_height = 1;
float min_frame_rate = 1.0f;
float max_frame_rate = min_frame_rate;
for (const auto& format : video_input_capabilities->formats) {
max_width = std::max(max_width, format->frame_size.width);
max_height = std::max(max_height, format->frame_size.height);
max_frame_rate = std::max(max_frame_rate, format->frame_rate);
}
platform_capabilities_.width = {1, max_width};
platform_capabilities_.height = {1, max_height};
platform_capabilities_.aspect_ratio = {1.0 / max_height,
static_cast<double>(max_width)};
platform_capabilities_.frame_rate = {min_frame_rate, max_frame_rate};
}
}
void InputDeviceInfo::getCapabilities(MediaTrackCapabilities& capabilities) {
capabilities.setDeviceId(deviceId());
capabilities.setGroupId(groupId());
if (DeviceType() == MediaDeviceType::MEDIA_AUDIO_INPUT)
capabilities.setEchoCancellation({true, false});
if (DeviceType() == MediaDeviceType::MEDIA_VIDEO_INPUT) {
if (!platform_capabilities_.width.empty()) {
LongRange width;
width.setMin(platform_capabilities_.width[0]);
width.setMax(platform_capabilities_.width[1]);
capabilities.setWidth(width);
}
if (!platform_capabilities_.height.empty()) {
LongRange height;
height.setMin(platform_capabilities_.height[0]);
height.setMax(platform_capabilities_.height[1]);
capabilities.setHeight(height);
}
if (!platform_capabilities_.aspect_ratio.empty()) {
DoubleRange aspect_ratio;
aspect_ratio.setMin(platform_capabilities_.aspect_ratio[0]);
aspect_ratio.setMax(platform_capabilities_.aspect_ratio[1]);
capabilities.setAspectRatio(aspect_ratio);
}
if (!platform_capabilities_.frame_rate.empty()) {
DoubleRange frame_rate;
frame_rate.setMin(platform_capabilities_.frame_rate[0]);
frame_rate.setMax(platform_capabilities_.frame_rate[1]);
capabilities.setFrameRate(frame_rate);
}
Vector<String> facing_mode;
switch (platform_capabilities_.facing_mode) {
case WebMediaStreamTrack::FacingMode::kUser:
facing_mode.push_back("user");
break;
case WebMediaStreamTrack::FacingMode::kEnvironment:
facing_mode.push_back("environment");
break;
case WebMediaStreamTrack::FacingMode::kLeft:
facing_mode.push_back("left");
break;
case WebMediaStreamTrack::FacingMode::kRight:
facing_mode.push_back("right");
break;
case WebMediaStreamTrack::FacingMode::kNone:
break;
}
capabilities.setFacingMode(facing_mode);
}
}
} // namespace blink
......@@ -6,6 +6,7 @@
#define InputDeviceInfo_h
#include "modules/mediastream/MediaDeviceInfo.h"
#include "public/platform/WebMediaStreamSource.h"
namespace blink {
......@@ -20,6 +21,8 @@ class InputDeviceInfo final : public MediaDeviceInfo {
const String& group_id,
MediaDeviceType);
void SetVideoInputCapabilities(mojom::blink::VideoInputDeviceCapabilitiesPtr);
void getCapabilities(MediaTrackCapabilities&);
private:
......@@ -27,6 +30,8 @@ class InputDeviceInfo final : public MediaDeviceInfo {
const String& label,
const String& group_id,
MediaDeviceType);
WebMediaStreamSource::Capabilities platform_capabilities_;
};
} // namespace blink
......
......@@ -95,6 +95,7 @@ ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state) {
GetDispatcherHost(frame)->EnumerateDevices(
true /* audio input */, true /* video input */, true /* audio output */,
true /* request_video_input_capabilities */,
WTF::Bind(&MediaDevices::DevicesEnumerated, WrapPersistent(this),
WrapPersistent(resolver)));
return promise;
......@@ -252,7 +253,9 @@ void MediaDevices::Dispose() {
void MediaDevices::DevicesEnumerated(
ScriptPromiseResolver* resolver,
Vector<Vector<mojom::blink::MediaDeviceInfoPtr>> enumeration) {
Vector<Vector<mojom::blink::MediaDeviceInfoPtr>> enumeration,
Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities) {
if (!requests_.Contains(resolver))
return;
......@@ -266,16 +269,31 @@ void MediaDevices::DevicesEnumerated(
DCHECK_EQ(static_cast<size_t>(MediaDeviceType::NUM_MEDIA_DEVICE_TYPES),
enumeration.size());
if (!video_input_capabilities.IsEmpty()) {
DCHECK_EQ(
enumeration[static_cast<size_t>(MediaDeviceType::MEDIA_VIDEO_INPUT)]
.size(),
video_input_capabilities.size());
}
MediaDeviceInfoVector media_devices;
for (size_t i = 0;
i < static_cast<size_t>(MediaDeviceType::NUM_MEDIA_DEVICE_TYPES); ++i) {
for (const auto& device_info : enumeration[i]) {
for (size_t j = 0; j < enumeration[i].size(); ++j) {
MediaDeviceType device_type = static_cast<MediaDeviceType>(i);
mojom::blink::MediaDeviceInfoPtr device_info =
std::move(enumeration[i][j]);
if (device_type == MediaDeviceType::MEDIA_AUDIO_INPUT ||
device_type == MediaDeviceType::MEDIA_VIDEO_INPUT) {
media_devices.push_back(
InputDeviceInfo* input_device_info =
InputDeviceInfo::Create(device_info->device_id, device_info->label,
device_info->group_id, device_type));
device_info->group_id, device_type);
if (device_type == MediaDeviceType::MEDIA_VIDEO_INPUT &&
!video_input_capabilities.IsEmpty()) {
input_device_info->SetVideoInputCapabilities(
std::move(video_input_capabilities[j]));
}
media_devices.push_back(input_device_info);
} else {
media_devices.push_back(
MediaDeviceInfo::Create(device_info->device_id, device_info->label,
......
......@@ -101,7 +101,8 @@ class MODULES_EXPORT MediaDevices final
void StopObserving();
void Dispose();
void DevicesEnumerated(ScriptPromiseResolver*,
Vector<Vector<mojom::blink::MediaDeviceInfoPtr>>);
Vector<Vector<mojom::blink::MediaDeviceInfoPtr>>,
Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>);
void OnDispatcherHostConnectionError();
const mojom::blink::MediaDevicesDispatcherHostPtr& GetDispatcherHost(
LocalFrame*);
......
......@@ -31,9 +31,12 @@ class MockMediaDevicesDispatcherHost
void EnumerateDevices(bool request_audio_input,
bool request_video_input,
bool request_audio_output,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback) override {
Vector<Vector<MediaDeviceInfoPtr>> enumeration(
static_cast<size_t>(MediaDeviceType::NUM_MEDIA_DEVICE_TYPES));
Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities;
MediaDeviceInfoPtr device_info;
if (request_audio_input) {
device_info = mojom::blink::MediaDeviceInfo::New();
......@@ -64,6 +67,19 @@ class MockMediaDevicesDispatcherHost
device_info->group_id = "";
enumeration[static_cast<size_t>(MediaDeviceType::MEDIA_VIDEO_INPUT)]
.push_back(std::move(device_info));
if (request_video_input_capabilities) {
mojom::blink::VideoInputDeviceCapabilitiesPtr capabilities =
mojom::blink::VideoInputDeviceCapabilities::New();
capabilities->device_id = kFakeVideoInputDeviceId1;
capabilities->facing_mode = blink::mojom::FacingMode::NONE;
video_input_capabilities.push_back(std::move(capabilities));
capabilities = mojom::blink::VideoInputDeviceCapabilities::New();
capabilities->device_id = kFakeVideoInputDeviceId2;
capabilities->facing_mode = blink::mojom::FacingMode::USER;
video_input_capabilities.push_back(std::move(capabilities));
}
}
if (request_audio_output) {
device_info = mojom::blink::MediaDeviceInfo::New();
......@@ -73,7 +89,8 @@ class MockMediaDevicesDispatcherHost
enumeration[static_cast<size_t>(MediaDeviceType::MEDIA_AUDIO_OUTPUT)]
.push_back(std::move(device_info));
}
std::move(callback).Run(std::move(enumeration));
std::move(callback).Run(std::move(enumeration),
std::move(video_input_capabilities));
}
void GetVideoInputCapabilities(GetVideoInputCapabilitiesCallback) override {
......
......@@ -41,13 +41,15 @@ struct AudioInputDeviceCapabilities {
// enumeration requests and managing subscriptions for device-change
// notifications.
interface MediaDevicesDispatcherHost {
// The reply always contains NUM_MEDIA_DEVICE_TYPES elements.
// The result is indexed by device type as defined in
// content/common/media/media_devices.h.
// Each of the arrays in the reply always contains NUM_MEDIA_DEVICE_TYPES and
// MEDIA_VIDEO_INPUT elements respectively. |enumeration| is indexed by device
// type as defined in content/common/media/media_devices.h.
EnumerateDevices(bool request_audio_input,
bool request_video_input,
bool request_audio_output)
=> (array<array<MediaDeviceInfo>> enumeration);
bool request_audio_output,
bool request_video_input_capabilities)
=> (array<array<MediaDeviceInfo>> enumeration,
array<VideoInputDeviceCapabilities> video_input_device_capabilities);
// Returns a list of video devices and their capabilities.
// If there is a user-preferred device, it is the first in the result.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment