blob: 4f1ea530289accf7d60cb2b59e0f53959ca6d24c [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/capture/capture_resolution_chooser.h"
#include "media/base/limits.h"
#include "media/base/video_util.h"
namespace media {
namespace {
// Compute the minimum frame size from the given |max_frame_size| and
// |resolution_change_policy|.
gfx::Size ComputeMinimumCaptureSize(
const gfx::Size& max_frame_size,
ResolutionChangePolicy resolution_change_policy) {
switch (resolution_change_policy) {
case RESOLUTION_POLICY_FIXED_RESOLUTION:
return max_frame_size;
case RESOLUTION_POLICY_FIXED_ASPECT_RATIO: {
// TODO(miu): This is a place-holder until "min constraints" are plumbed-
// in from the MediaStream framework. http://crbug.com/473336
const int kMinLines = 180;
if (max_frame_size.height() <= kMinLines)
return max_frame_size;
const gfx::Size result(
kMinLines * max_frame_size.width() / max_frame_size.height(),
kMinLines);
if (result.width() <= 0 || result.width() > limits::kMaxDimension)
return max_frame_size;
return result;
}
case RESOLUTION_POLICY_ANY_WITHIN_LIMIT:
return gfx::Size(1, 1);
}
NOTREACHED();
return gfx::Size(1, 1);
}
// Returns |size|, unless it exceeds |max_size| or is under |min_size|. When
// the bounds are exceeded, computes and returns an alternate size of similar
// aspect ratio that is within the bounds.
gfx::Size ComputeBoundedCaptureSize(const gfx::Size& size,
const gfx::Size& min_size,
const gfx::Size& max_size) {
if (size.width() > max_size.width() || size.height() > max_size.height()) {
gfx::Size result = ScaleSizeToFitWithinTarget(size, max_size);
result.SetToMax(min_size);
return result;
} else if (size.width() < min_size.width() ||
size.height() < min_size.height()) {
gfx::Size result = ScaleSizeToEncompassTarget(size, min_size);
result.SetToMin(max_size);
return result;
} else {
return size;
}
}
} // namespace
CaptureResolutionChooser::CaptureResolutionChooser(
const gfx::Size& max_frame_size,
ResolutionChangePolicy resolution_change_policy)
: max_frame_size_(max_frame_size),
min_frame_size_(ComputeMinimumCaptureSize(max_frame_size,
resolution_change_policy)),
resolution_change_policy_(resolution_change_policy),
constrained_size_(max_frame_size) {
DCHECK_LT(0, max_frame_size_.width());
DCHECK_LT(0, max_frame_size_.height());
DCHECK_LE(min_frame_size_.width(), max_frame_size_.width());
DCHECK_LE(min_frame_size_.height(), max_frame_size_.height());
DCHECK_LE(resolution_change_policy_, RESOLUTION_POLICY_LAST);
RecomputeCaptureSize();
}
CaptureResolutionChooser::~CaptureResolutionChooser() {}
void CaptureResolutionChooser::SetSourceSize(const gfx::Size& source_size) {
if (source_size.IsEmpty())
return;
switch (resolution_change_policy_) {
case RESOLUTION_POLICY_FIXED_RESOLUTION:
// Source size changes do not affect the frame resolution. Frame
// resolution is always fixed to |max_frame_size_|.
break;
case RESOLUTION_POLICY_FIXED_ASPECT_RATIO:
constrained_size_ = ComputeBoundedCaptureSize(
PadToMatchAspectRatio(source_size, max_frame_size_),
min_frame_size_,
max_frame_size_);
RecomputeCaptureSize();
break;
case RESOLUTION_POLICY_ANY_WITHIN_LIMIT:
constrained_size_ = ComputeBoundedCaptureSize(
source_size, min_frame_size_, max_frame_size_);
RecomputeCaptureSize();
break;
}
}
void CaptureResolutionChooser::RecomputeCaptureSize() {
// TODO(miu): An upcoming change will introduce the ability to find the best
// capture resolution, given the current capabilities of the system.
// http://crbug.com/156767
capture_size_ = constrained_size_;
}
} // namespace media