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

Make rescaling optional for VideoTrackAdapter

This CL:
1. Makes the former |max_width|, |max_height| parameters in
VideoTrackAdapterSettings a single optional gfx::Size |target_size|.

2. Changes VideoTrackAdapter so that if no |target_size| is specified
in VideoTrackAdapterSettings, no rescaling will occur.

3. Changes VideoTrackAdapterSettings to a class to increase encapsulation.

4. CalculateTargetSize() is renamed to CalculateDesiredSize() and it now
returns a bool indicating if it was possible to compute a desired size.
If not, it means the input frame should not be rendered.
Currently this is limited to frames of invalid size (greater than the system
limit), but it will be expanded in follow-up work to detect frames that
violate constraints and should cause the overconstrained event to be fired.

These changes are in anticipation of support for the resizeMode constrainable
property and the overconstrained event.

Bug: 854980
Change-Id: I688d0a655a9ac31995d99b710f955123a8894654
Reviewed-on: https://chromium-review.googlesource.com/c/1286140
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600926}
parent eb4f089e
......@@ -126,10 +126,14 @@ VideoCaptureSettings::VideoCaptureSettings(
max_frame_rate_(max_frame_rate) {
DCHECK(!min_frame_rate ||
*min_frame_rate_ <= capture_params.requested_format.frame_rate);
DCHECK_LE(track_adapter_settings.max_width,
capture_params.requested_format.frame_size.width());
DCHECK_LE(track_adapter_settings.max_height,
capture_params.requested_format.frame_size.height());
// TODO(crbug.com/854980): Update these DCHECKS to allow for unspecified
// target size.
DCHECK(track_adapter_settings.target_size() &&
track_adapter_settings.target_size()->width() <=
capture_params.requested_format.frame_size.width());
DCHECK(track_adapter_settings_.target_size() &&
track_adapter_settings_.target_size()->height() <=
capture_params.requested_format.frame_size.height());
}
VideoCaptureSettings::VideoCaptureSettings(const VideoCaptureSettings& other) =
......@@ -287,7 +291,7 @@ VideoTrackAdapterSettings SelectVideoTrackAdapterSettings(
track_max_frame_rate = 0.0;
return VideoTrackAdapterSettings(
track_max_width, track_max_height, track_min_aspect_ratio,
gfx::Size(track_max_width, track_max_height), track_min_aspect_ratio,
track_max_aspect_ratio, track_max_frame_rate);
}
......
......@@ -405,11 +405,11 @@ void MediaStreamVideoSource::UpdateTrackSettings(
// Calculate resulting frame size if the source delivers frames
// according to the current format. Note: Format may change later.
gfx::Size desired_size;
VideoTrackAdapter::CalculateTargetSize(false /* is_rotated */,
GetCurrentFormat()->frame_size,
adapter_settings, &desired_size);
VideoTrackAdapter::CalculateDesiredSize(false /* is_rotated */,
GetCurrentFormat()->frame_size,
adapter_settings, &desired_size);
track->SetTargetSizeAndFrameRate(desired_size.width(), desired_size.height(),
adapter_settings.max_frame_rate);
adapter_settings.max_frame_rate());
}
MediaStreamVideoSource::PendingTrackInfo::PendingTrackInfo(
......
......@@ -31,7 +31,7 @@ namespace content {
class MediaStreamVideoTrack;
class VideoTrackAdapter;
struct VideoTrackAdapterSettings;
class VideoTrackAdapterSettings;
// MediaStreamVideoSource is an interface used for sending video frames to a
// MediaStreamVideoTrack.
......
......@@ -107,8 +107,7 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
double frame_rate,
bool detect_rotation = false) {
blink::WebMediaStreamTrack track = CreateTrack(
"123",
VideoTrackAdapterSettings(width, height, 0.0, HUGE_VAL, frame_rate),
"123", VideoTrackAdapterSettings(gfx::Size(width, height), frame_rate),
base::Optional<bool>(), false, 0.0);
EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
......@@ -200,12 +199,11 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
CreateTrackAndStartSource(expected_width1, expected_height1,
MediaStreamVideoSource::kDefaultFrameRate);
blink::WebMediaStreamTrack track2 =
CreateTrack("dummy",
VideoTrackAdapterSettings(
expected_width2, expected_height2, 0.0, HUGE_VAL,
MediaStreamVideoSource::kDefaultFrameRate),
base::Optional<bool>(), false, 0.0);
blink::WebMediaStreamTrack track2 = CreateTrack(
"dummy",
VideoTrackAdapterSettings(gfx::Size(expected_width2, expected_height2),
MediaStreamVideoSource::kDefaultFrameRate),
base::Optional<bool>(), false, 0.0);
MockMediaStreamVideoSink sink1;
sink1.ConnectToTrack(track1);
......@@ -463,7 +461,7 @@ TEST_F(MediaStreamVideoSourceTest, ReconfigureTrack) {
EXPECT_EQ(settings.aspect_ratio, 640.0 / 480.0);
source()->ReconfigureTrack(
native_track, VideoTrackAdapterSettings(630, 470, 0, HUGE_VAL, 30.0));
native_track, VideoTrackAdapterSettings(gfx::Size(630, 470), 30.0));
native_track->GetSettings(settings);
EXPECT_EQ(settings.width, 630);
EXPECT_EQ(settings.height, 470);
......@@ -500,7 +498,7 @@ TEST_F(MediaStreamVideoSourceTest, ReconfigureStoppedTrack) {
blink::WebMediaStreamSource::kReadyStateEnded);
source()->ReconfigureTrack(
native_track, VideoTrackAdapterSettings(630, 470, 0, HUGE_VAL, 30.0));
native_track, VideoTrackAdapterSettings(gfx::Size(630, 470), 30.0));
blink::WebMediaStreamTrack::Settings stopped_settings;
native_track->GetSettings(stopped_settings);
EXPECT_EQ(stopped_settings.width, -1);
......
......@@ -21,7 +21,7 @@
namespace content {
struct VideoTrackAdapterSettings;
class VideoTrackAdapterSettings;
// MediaStreamVideoTrack is a video specific representation of a
// blink::WebMediaStreamTrack in content. It is owned by the blink object
......
......@@ -4,6 +4,8 @@
#include <stdint.h>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
......@@ -308,8 +310,9 @@ TEST_F(MediaStreamVideoTrackTest, GetSettingsWithAdjustment) {
const int kAdjustedWidth = 600;
const int kAdjustedHeight = 400;
const double kAdjustedFrameRate = 20.0;
VideoTrackAdapterSettings adapter_settings(kAdjustedWidth, kAdjustedHeight,
0.0, 10000.0, kAdjustedFrameRate);
VideoTrackAdapterSettings adapter_settings(
gfx::Size(kAdjustedWidth, kAdjustedHeight), 0.0, 10000.0,
kAdjustedFrameRate);
blink::WebMediaStreamTrack track = CreateTrackWithSettings(adapter_settings);
MediaStreamVideoTrack* const native_track =
MediaStreamVideoTrack::GetVideoTrack(track);
......
......@@ -12,7 +12,7 @@
namespace content {
struct VideoTrackAdapterSettings;
class VideoTrackAdapterSettings;
// This class encapsulates creation of a Blink MediaStream having inside the
// necessary Blink and Chromium, track and source. The Chrome Video source is
......
......@@ -889,14 +889,16 @@ TEST_F(UserMediaClientImplTest, DefaultConstraintsPropagate) {
const VideoTrackAdapterSettings& track_settings =
video_capture_settings.track_adapter_settings();
EXPECT_EQ(track_settings.max_width, MediaStreamVideoSource::kDefaultWidth);
EXPECT_EQ(track_settings.max_height, MediaStreamVideoSource::kDefaultHeight);
EXPECT_EQ(track_settings.min_aspect_ratio,
EXPECT_EQ(track_settings.target_width(),
MediaStreamVideoSource::kDefaultWidth);
EXPECT_EQ(track_settings.target_height(),
MediaStreamVideoSource::kDefaultHeight);
EXPECT_EQ(track_settings.min_aspect_ratio(),
1.0 / MediaStreamVideoSource::kDefaultHeight);
EXPECT_EQ(track_settings.max_aspect_ratio,
EXPECT_EQ(track_settings.max_aspect_ratio(),
MediaStreamVideoSource::kDefaultWidth);
// 0.0 is the default max_frame_rate and it indicates no frame-rate adjustment
EXPECT_EQ(track_settings.max_frame_rate, 0.0);
EXPECT_EQ(track_settings.max_frame_rate(), 0.0);
}
TEST_F(UserMediaClientImplTest, DefaultTabCapturePropagate) {
......@@ -949,12 +951,12 @@ TEST_F(UserMediaClientImplTest, DefaultTabCapturePropagate) {
const VideoTrackAdapterSettings& track_settings =
video_capture_settings.track_adapter_settings();
EXPECT_EQ(track_settings.max_width, kDefaultScreenCastWidth);
EXPECT_EQ(track_settings.max_height, kDefaultScreenCastHeight);
EXPECT_EQ(track_settings.min_aspect_ratio, 1.0 / kMaxScreenCastDimension);
EXPECT_EQ(track_settings.max_aspect_ratio, kMaxScreenCastDimension);
EXPECT_EQ(track_settings.target_width(), kDefaultScreenCastWidth);
EXPECT_EQ(track_settings.target_height(), kDefaultScreenCastHeight);
EXPECT_EQ(track_settings.min_aspect_ratio(), 1.0 / kMaxScreenCastDimension);
EXPECT_EQ(track_settings.max_aspect_ratio(), kMaxScreenCastDimension);
// 0.0 is the default max_frame_rate and it indicates no frame-rate adjustment
EXPECT_EQ(track_settings.max_frame_rate, 0.0);
EXPECT_EQ(track_settings.max_frame_rate(), 0.0);
}
TEST_F(UserMediaClientImplTest, DefaultDesktopCapturePropagate) {
......@@ -1008,12 +1010,12 @@ TEST_F(UserMediaClientImplTest, DefaultDesktopCapturePropagate) {
const VideoTrackAdapterSettings& track_settings =
video_capture_settings.track_adapter_settings();
EXPECT_EQ(track_settings.max_width, kDefaultScreenCastWidth);
EXPECT_EQ(track_settings.max_height, kDefaultScreenCastHeight);
EXPECT_EQ(track_settings.min_aspect_ratio, 1.0 / kMaxScreenCastDimension);
EXPECT_EQ(track_settings.max_aspect_ratio, kMaxScreenCastDimension);
EXPECT_EQ(track_settings.target_width(), kDefaultScreenCastWidth);
EXPECT_EQ(track_settings.target_height(), kDefaultScreenCastHeight);
EXPECT_EQ(track_settings.min_aspect_ratio(), 1.0 / kMaxScreenCastDimension);
EXPECT_EQ(track_settings.max_aspect_ratio(), kMaxScreenCastDimension);
// 0.0 is the default max_frame_rate and it indicates no frame-rate adjustment
EXPECT_EQ(track_settings.max_frame_rate, 0.0);
EXPECT_EQ(track_settings.max_frame_rate(), 0.0);
}
TEST_F(UserMediaClientImplTest, NonDefaultAudioConstraintsPropagate) {
......
......@@ -20,10 +20,19 @@
namespace content {
struct CONTENT_EXPORT VideoTrackAdapterSettings {
class CONTENT_EXPORT VideoTrackAdapterSettings {
public:
// Creates a VideoTrackAdapterSettings with no target resolution or frame rate
// and without any constraints on the resolution.
VideoTrackAdapterSettings();
VideoTrackAdapterSettings(int max_width,
int max_height,
// Creates a VideoTrackAdapterSettings with a given target resolution and
// and frame rate, and without any constraints on the resolution.
VideoTrackAdapterSettings(const gfx::Size& target_size,
double max_frame_rate);
// Creates a VideoTrackAdapterSettings with the specified resolution, frame
// rate and resolution constraints. If |target_size| is null, it means that
// no video processing is desired.
VideoTrackAdapterSettings(base::Optional<gfx::Size> target_size,
double min_aspect_ratio,
double max_aspect_ratio,
double max_frame_rate);
......@@ -31,14 +40,30 @@ struct CONTENT_EXPORT VideoTrackAdapterSettings {
VideoTrackAdapterSettings& operator=(const VideoTrackAdapterSettings& other);
bool operator==(const VideoTrackAdapterSettings& other) const;
int max_width;
int max_height;
double min_aspect_ratio;
double max_aspect_ratio;
// A |max_frame_rate| of zero is used to signal that no frame-rate adjustment
// is necessary.
const base::Optional<gfx::Size>& target_size() const { return target_size_; }
int target_width() const {
DCHECK(target_size_);
return target_size_->width();
}
int target_height() const {
DCHECK(target_size_);
return target_size_->height();
}
double min_aspect_ratio() const { return min_aspect_ratio_; }
double max_aspect_ratio() const { return max_aspect_ratio_; }
double max_frame_rate() const { return max_frame_rate_; }
void set_max_frame_rate(double max_frame_rate) {
max_frame_rate_ = max_frame_rate;
}
private:
base::Optional<gfx::Size> target_size_;
double min_aspect_ratio_;
double max_aspect_ratio_;
// A |max_frame_rate| of zero is used to signal that no frame-rate
// adjustment is necessary.
// TODO(guidou): Change this to base::Optional. http://crbug.com/734528
double max_frame_rate;
double max_frame_rate_;
};
// VideoTrackAdapter is a helper class used by MediaStreamVideoSource used for
......@@ -91,7 +116,10 @@ class VideoTrackAdapter
void SetSourceFrameSize(const gfx::Size& source_frame_size);
// Exported for testing.
CONTENT_EXPORT static void CalculateTargetSize(
// Returns true if |desired_size| is updated successfully, false otherwise.
// |desired_size| is not updated |settings| has rescaling disabled and
// |input_size| is invalid.
CONTENT_EXPORT static bool CalculateDesiredSize(
bool is_rotated,
const gfx::Size& input_size,
const VideoTrackAdapterSettings& settings,
......
......@@ -30,41 +30,41 @@ TEST(VideoTrackAdapterTest, ZeroInputArea) {
kLargeDimension > kMaxWidth && kLargeDimension > kMaxHeight,
"kLargeDimension must be greater than kMaxWidth and kMaxHeight");
const VideoTrackAdapterSettings kVideoTrackAdapterSettings(
kMaxWidth, kMaxHeight, 0.1 /* min_aspect_ratio */,
gfx::Size(kMaxWidth, kMaxHeight), 0.1 /* min_aspect_ratio */,
2.0 /* max_aspect_ratio */, 0.0 /* max_frame_rate */);
const bool kIsRotatedValues[] = {true, false};
for (bool is_rotated : kIsRotatedValues) {
gfx::Size desired_size;
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
is_rotated, gfx::Size(0, 0), kVideoTrackAdapterSettings, &desired_size);
EXPECT_EQ(desired_size.width(), 0);
EXPECT_EQ(desired_size.height(), 0);
// Zero width.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
is_rotated, gfx::Size(0, kSmallDimension), kVideoTrackAdapterSettings,
&desired_size);
EXPECT_EQ(desired_size.width(), 0);
EXPECT_EQ(desired_size.height(), kSmallDimension);
// Zero height.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
is_rotated, gfx::Size(kSmallDimension, 0), kVideoTrackAdapterSettings,
&desired_size);
EXPECT_EQ(desired_size.width(), kSmallDimension);
EXPECT_EQ(desired_size.height(), 0);
// Requires "cropping" of height.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
is_rotated, gfx::Size(0, kLargeDimension), kVideoTrackAdapterSettings,
&desired_size);
EXPECT_EQ(desired_size.width(), 0);
EXPECT_EQ(desired_size.height(), is_rotated ? kMaxWidth : kMaxHeight);
// Requires "cropping" of width.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
is_rotated, gfx::Size(kLargeDimension, 0), kVideoTrackAdapterSettings,
&desired_size);
EXPECT_EQ(desired_size.width(), is_rotated ? kMaxHeight : kMaxWidth);
......@@ -90,60 +90,57 @@ TEST(VideoTrackAdapterTest, ZeroOutputArea) {
gfx::Size desired_size;
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(0 /* max_width */, 0 /* max_height */,
kMinAspectRatio, kMaxAspectRatio,
0.0 /* max_frame_rate */),
VideoTrackAdapterSettings(gfx::Size(0, 0), kMinAspectRatio,
kMaxAspectRatio, 0.0 /* max_frame_rate */),
&desired_size);
EXPECT_EQ(desired_size.width(), 0);
EXPECT_EQ(desired_size.height(), 0);
// Width is cropped to zero.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(
0 /* max_width */, kLargeMaxDimension /* max_height */,
kMinAspectRatio, kMaxAspectRatio, 0.0 /* max_frame_rate */),
VideoTrackAdapterSettings(gfx::Size(0, kLargeMaxDimension), 0.0,
HUGE_VAL, // kMinAspectRatio, kMaxAspectRatio,
0.0 /* max_frame_rate */),
&desired_size);
EXPECT_EQ(desired_size.width(), 0);
EXPECT_EQ(desired_size.height(), kInputHeight);
// Requires "cropping" of width and height.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(
0 /* max_width */, kSmallMaxDimension /* max_height */,
kMinAspectRatio, kMaxAspectRatio, 0.0 /* max_frame_rate */),
VideoTrackAdapterSettings(gfx::Size(0, kSmallMaxDimension),
kMinAspectRatio, kMaxAspectRatio,
0.0 /* max_frame_rate */),
&desired_size);
EXPECT_EQ(desired_size.width(), 0);
EXPECT_EQ(desired_size.height(), kSmallMaxDimension);
// Height is cropped to zero.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(kLargeMaxDimension /* max_width */,
0 /* max_height */, kMinAspectRatio,
kMaxAspectRatio, 0.0 /* max_frame_rate */),
VideoTrackAdapterSettings(gfx::Size(kLargeMaxDimension, 0),
kMinAspectRatio, kMaxAspectRatio,
0.0 /* max_frame_rate */),
&desired_size);
EXPECT_EQ(desired_size.width(), kInputWidth);
EXPECT_EQ(desired_size.height(), 0);
// Requires "cropping" of width and height.
VideoTrackAdapter::CalculateTargetSize(
VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(kSmallMaxDimension /* max_width */,
0 /* max_height */, kMinAspectRatio,
kMaxAspectRatio, 0.0 /* max_frame_rate */),
VideoTrackAdapterSettings(
gfx::Size(kSmallMaxDimension /* max_width */, 0 /* max_height */),
kMinAspectRatio, kMaxAspectRatio, 0.0 /* max_frame_rate */),
&desired_size);
EXPECT_EQ(desired_size.width(), kSmallMaxDimension);
EXPECT_EQ(desired_size.height(), 0);
}
// Test that large frame sizes are clamped to the maximum supported dimension.
TEST(VideoTrackAdapterTest, ClampToMaxDimension) {
const double kMinAspectRatio = 0.0;
const double kMaxAspectRatio = HUGE_VAL;
// Test that large frames are handled correctly.
TEST(VideoTrackAdapterTest, LargeFrames) {
const int kInputWidth = std::numeric_limits<int>::max();
const int kInputHeight = std::numeric_limits<int>::max();
const int kMaxWidth = std::numeric_limits<int>::max();
......@@ -151,13 +148,44 @@ TEST(VideoTrackAdapterTest, ClampToMaxDimension) {
gfx::Size desired_size;
VideoTrackAdapter::CalculateTargetSize(
// If a target size is provided in VideoTrackAdapterSettings, rescaling is
// allowed and frames must be clamped to the maximum allowed size, even if the
// target exceeds the system maximum.
bool success = VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(kMaxWidth, kMaxHeight, kMinAspectRatio,
kMaxAspectRatio, 0.0 /* max_frame_rate */),
VideoTrackAdapterSettings(gfx::Size(kMaxWidth, kMaxHeight),
0.0 /* max_frame_rate */),
&desired_size);
EXPECT_TRUE(success);
EXPECT_EQ(desired_size.width(), media::limits::kMaxDimension);
EXPECT_EQ(desired_size.height(), media::limits::kMaxDimension);
// If no target size is provided in VideoTrackAdapterSettings, rescaling is
// disabled and |desired_size| is left unmodified.
desired_size.set_width(0);
desired_size.set_height(0);
success = VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(), &desired_size);
EXPECT_FALSE(success);
EXPECT_EQ(desired_size.width(), 0);
EXPECT_EQ(desired_size.height(), 0);
}
// Test that regular frames are not rescaled if settings do not specify a target
// resolution.
TEST(VideoTrackAdapterTest, NoRescaling) {
const int kInputWidth = 640;
const int kInputHeight = 480;
// No target size,
gfx::Size desired_size;
bool success = VideoTrackAdapter::CalculateDesiredSize(
false /* is_rotated */, gfx::Size(kInputWidth, kInputHeight),
VideoTrackAdapterSettings(), &desired_size);
EXPECT_TRUE(success);
EXPECT_EQ(desired_size.width(), kInputWidth);
EXPECT_EQ(desired_size.height(), kInputHeight);
}
} // namespace content
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