Commit f349e11b authored by Guido Urdaneta's avatar Guido Urdaneta Committed by Commit Bot

Add support for resizeMode in MediaStreamTrack.getSettings()

This CL exposes the current resizeMode setting to the Web Platform.
As of this CL, the resizeMode is 'none' if the track resolution
corresponds to the native resolution of the video source, without any
resolution adjustment. It is 'crop-and-rescale' if rescaling is
necessary.

The resizeMode currently cannot be set explicitly with getUserMedia() or
applyConstraints(), but this functionality will be added in a follow-up
CL.

Drive-by: Add separate WPT tests for all getSettings() properties.

Intent to Ship:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/V2srjdzRCXE

Bug: 854980
Change-Id: Id4c683e6b2f228b17cf2354cb7fc589ca9e593a6
Reviewed-on: https://chromium-review.googlesource.com/c/1307448
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Reviewed-by: default avatarPhilip Jägenstedt <foolip@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604562}
parent 7523c4b7
......@@ -382,6 +382,11 @@ void MediaStreamVideoTrack::GetSettings(
settings.video_kind = GetVideoKindForFormat(*format);
}
settings.facing_mode = ToWebFacingMode(source_->device().video_facing);
settings.resize_mode = blink::WebString::FromASCII(
std::string(adapter_settings().target_size()
? blink::WebMediaStreamTrack::kResizeModeRescale
: blink::WebMediaStreamTrack::kResizeModeNone));
const base::Optional<CameraCalibration> calibration =
source_->device().camera_calibration;
if (calibration) {
......
......@@ -71,40 +71,146 @@
var stream = await navigator.mediaDevices.getUserMedia(constraints);
assert_equals(stream.getTracks()[0].getSettings().groupId,
device.groupId);
assert_true(device.groupId.length > 0);
assert_greater_than(device.groupId.length, 0);
}
});
}, 'groupId is correctly reported by getSettings() for all devices');
promise_test(t => {
return navigator.mediaDevices.getUserMedia({audio: true}).then(stream => {
let settings = stream.getAudioTracks()[0].getSettings();
assert_equals(typeof(settings.deviceId), "string",
"deviceId should exist and it should be a string.");
assert_equals(typeof(settings.groupId), "string",
"groupId should exist and it should be a string.");
assert_equals(typeof(settings.volume), "number",
"volume should exist and it should be a number.");
assert_true(settings.volume >= 0.0 && settings.volume <= 1.0,
"volume should be a number in the range [0.0, 1.0].");
assert_equals(typeof(settings.sampleRate), "number",
"sampleRate should exist and it should be a number.");
assert_true(settings.sampleRate > 0, "sampleRate should be positive.");
assert_equals(typeof(settings.sampleSize), "number",
"sampleSize should exist and it should be a number.");
assert_true(settings.sampleSize > 0, "sampleSize should be positive.");
assert_equals(typeof(settings.echoCancellation), "boolean",
"echoCancellation should exist and it should be a boolean.");
assert_equals(typeof(settings.autoGainControl), "boolean",
"autoGainControl should exist and it should be a boolean.");
assert_equals(typeof(settings.noiseSuppression), "boolean",
"noiseSuppression should exist and it should be a boolean.");
assert_equals(typeof(settings.latency), "number",
"latency should exist and it should be a number.");
assert_true(settings.latency >= 0, "latency should not be negative.");
assert_equals(typeof(settings.channelCount), "number",
"channelCount should exist and it should be a number.");
assert_true(settings.channelCount > 0, "channelCount should be positive.");
});
}, 'audio properties are reported by getSettings()');
async function createAudioStreamAndGetSettings(t) {
const stream = await navigator.mediaDevices.getUserMedia({audio: true});
t.add_cleanup(() => stream.getAudioTracks()[0].stop());
return stream.getAudioTracks()[0].getSettings();
}
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.deviceId), "string",
"deviceId should exist and it should be a string.");
}, 'deviceId is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.groupId), "string",
"groupId should exist and it should be a string.");
}, 'groupId is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.volume), "number",
"volume should exist and it should be a number.");
assert_between_inclusive(settings.volume, 0.0, 1.0);
}, 'volume is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.sampleRate), "number",
"sampleRate should exist and it should be a number.");
assert_greater_than(settings.sampleRate, 0);
}, 'sampleRate is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.sampleSize), "number",
"sampleSize should exist and it should be a number.");
assert_greater_than(settings.sampleSize, 0);
}, 'sampleSize is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.echoCancellation), "boolean",
"echoCancellation should exist and it should be a boolean.");
}, 'echoCancellation is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.autoGainControl), "boolean",
"autoGainControl should exist and it should be a boolean.");
}, 'autoGainControl is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.noiseSuppression), "boolean",
"noiseSuppression should exist and it should be a boolean.");
}, 'noiseSuppression is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.latency), "number",
"latency should exist and it should be a number.");
assert_greater_than_equal(settings.latency,0);
}, 'latency is reported by getSettings() for getUserMedia() audio tracks');
promise_test(async t => {
const settings = await createAudioStreamAndGetSettings(t);
assert_equals(typeof(settings.channelCount), "number",
"channelCount should exist and it should be a number.");
assert_greater_than(settings.channelCount, 0);
}, 'channelCount is reported by getSettings() for getUserMedia() audio tracks');
async function createVideoStreamAndGetSettings(t) {
const stream = await navigator.mediaDevices.getUserMedia({video: true});
t.add_cleanup(() => stream.getVideoTracks()[0].stop());
return stream.getVideoTracks()[0].getSettings();
}
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
assert_equals(typeof(settings.deviceId), "string",
"deviceId should exist and it should be a string.");
}, 'deviceId is reported by getSettings() for getUserMedia() video tracks');
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
assert_equals(typeof(settings.groupId), "string",
"groupId should exist and it should be a string.");
}, 'groupId is reported by getSettings() for getUserMedia() video tracks');
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
assert_equals(typeof(settings.width), "number",
"width should exist and it should be a number.");
assert_true(Number.isInteger(settings.width), "width should be an integer.");
assert_greater_than_equal(settings.width, 0);
}, 'width is reported by getSettings() for getUserMedia() video tracks');
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
assert_equals(typeof(settings.height), "number",
"height should exist and it should be a number.");
assert_true(Number.isInteger(settings.height), "height should be an integer.");
assert_greater_than_equal(settings.height, 0);
}, 'height is reported by getSettings() for getUserMedia() video tracks');
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
assert_equals(typeof(settings.aspectRatio), "number",
"aspectRatio should exist and it should be a number.");
assert_greater_than_equal(settings.aspectRatio, 0);
}, 'aspectRatio is reported by getSettings() for getUserMedia() video tracks');
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
assert_equals(typeof(settings.frameRate), "number",
"frameRate should exist and it should be a number.");
assert_greater_than_equal(settings.frameRate, 0);
}, 'frameRate is reported by getSettings() for getUserMedia() video tracks');
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
// facingMode not treated as mandatory because not all platforms provide
// this information.
if (settings.facingMode) {
assert_equals(typeof(settings.facingMode), "string",
"If facingMode is provided it should be a string.");
assert_in_array(settings.facingMode,
['user', 'environment', 'left', 'right']);
}
}, 'facingMode is reported by getSettings() for getUserMedia() video tracks');
promise_test(async t => {
const settings = await createVideoStreamAndGetSettings(t);
assert_equals(typeof(settings.resizeMode), "string",
"resizeMode should exist and it should be a string.");
assert_in_array(settings.resizeMode, ['none', 'crop-and-scale']);
}, 'resizeMode is reported by getSettings() for getUserMedia() video tracks');
</script>
......@@ -55,6 +55,8 @@ promise_test(function() {
assert_true('aspectRatio' in settings,
'Aspect ratio missing: ' + JSON.stringify(settings));
assert_equals(settings.width / settings.height, settings.aspectRatio);
assert_in_array(settings.resizeMode, [ "none", "crop-and-scale" ],
'Invalid resizeMode: ' + JSON.stringify(settings));
});
}, 'A video track returns the expected variables');
......
......@@ -51,6 +51,9 @@ class WebMediaStreamTrack {
};
enum class CursorCaptureType { kNever, kAlways, kMotion };
BLINK_PLATFORM_EXPORT static const char kResizeModeNone[];
BLINK_PLATFORM_EXPORT static const char kResizeModeRescale[];
struct Settings {
bool HasFrameRate() const { return frame_rate >= 0.0; }
bool HasWidth() const { return width >= 0; }
......@@ -76,6 +79,7 @@ class WebMediaStreamTrack {
WebString device_id;
WebString group_id;
FacingMode facing_mode = FacingMode::kNone;
WebString resize_mode;
base::Optional<bool> echo_cancellation;
base::Optional<bool> auto_gain_control;
base::Optional<bool> noise_supression;
......
......@@ -480,6 +480,8 @@ MediaTrackSettings* MediaStreamTrack::getSettings() const {
break;
}
}
if (!platform_settings.resize_mode.IsNull())
settings->setResizeMode(platform_settings.resize_mode);
if (platform_settings.echo_cancellation)
settings->setEchoCancellation(*platform_settings.echo_cancellation);
......
......@@ -10,6 +10,7 @@ dictionary MediaTrackSettings {
double aspectRatio;
double frameRate;
DOMString facingMode;
DOMString resizeMode;
double volume;
long sampleRate;
long sampleSize;
......
......@@ -57,6 +57,9 @@ class TrackDataContainer : public MediaStreamComponent::TrackData {
} // namespace
const char WebMediaStreamTrack::kResizeModeNone[] = "none";
const char WebMediaStreamTrack::kResizeModeRescale[] = "crop-and-scale";
WebMediaStreamTrack::WebMediaStreamTrack(
MediaStreamComponent* media_stream_component)
: private_(media_stream_component) {}
......
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