Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Unified Diff: webrtc/media/base/videoadapter.cc

Issue 2558243003: Reland of Add ability to scale to arbitrary factors (Closed)
Patch Set: Fix bug and add test Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/media/base/videoadapter.h ('k') | webrtc/media/base/videoadapter_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/media/base/videoadapter.cc
diff --git a/webrtc/media/base/videoadapter.cc b/webrtc/media/base/videoadapter.cc
index acb0e2c1a19888d758cd2d46893fca9e2b93a477..16d23193549e3e4aff9956cd0c234b7ef4bc1ae7 100644
--- a/webrtc/media/base/videoadapter.cc
+++ b/webrtc/media/base/videoadapter.cc
@@ -11,117 +11,72 @@
#include "webrtc/media/base/videoadapter.h"
#include <algorithm>
+#include <cmath>
#include <cstdlib>
#include <limits>
+#include "webrtc/base/arraysize.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/optional.h"
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/media/base/videocommon.h"
namespace {
-
struct Fraction {
int numerator;
int denominator;
};
-// Scale factors optimized for in libYUV that we accept.
-// Must be sorted in decreasing scale factors for FindScaleLargerThan to work.
-const Fraction kScaleFractions[] = {
- {1, 1},
- {3, 4},
- {1, 2},
- {3, 8},
- {1, 4},
- {3, 16},
-};
-
-// Round |valueToRound| to a multiple of |multiple|. Prefer rounding upwards,
-// but never more than |maxValue|.
-int roundUp(int valueToRound, int multiple, int maxValue) {
- const int roundedValue = (valueToRound + multiple - 1) / multiple * multiple;
- return roundedValue <= maxValue ? roundedValue
- : (maxValue / multiple * multiple);
-}
-
-Fraction FindScaleLessThanOrEqual(int input_num_pixels, int target_num_pixels) {
- float best_distance = std::numeric_limits<float>::max();
- Fraction best_scale = {0, 1}; // Default to 0 if nothing matches.
- for (const auto& fraction : kScaleFractions) {
- const float scale =
- fraction.numerator / static_cast<float>(fraction.denominator);
- float test_num_pixels = input_num_pixels * scale * scale;
- float diff = target_num_pixels - test_num_pixels;
- if (diff < 0) {
- continue;
- }
- if (diff < best_distance) {
- best_distance = diff;
- best_scale = fraction;
- if (best_distance == 0) { // Found exact match.
- break;
- }
- }
- }
- return best_scale;
+// Round |value_to_round| to a multiple of |multiple|. Prefer rounding upwards,
+// but never more than |max_value|.
+int roundUp(int value_to_round, int multiple, int max_value) {
+ const int rounded_value =
+ (value_to_round + multiple - 1) / multiple * multiple;
+ return rounded_value <= max_value ? rounded_value
+ : (max_value / multiple * multiple);
}
-Fraction FindScaleLargerThan(int input_num_pixels,
- int target_num_pixels,
- int* resulting_number_of_pixels) {
- float best_distance = std::numeric_limits<float>::max();
- Fraction best_scale = {1, 1}; // Default to unscaled if nothing matches.
- // Default to input number of pixels.
- float best_number_of_pixels = input_num_pixels;
- for (const auto& fraction : kScaleFractions) {
- const float scale =
- fraction.numerator / static_cast<float>(fraction.denominator);
- float test_num_pixels = input_num_pixels * scale * scale;
- float diff = test_num_pixels - target_num_pixels;
- if (diff <= 0) {
- break;
- }
- if (diff < best_distance) {
- best_distance = diff;
- best_scale = fraction;
- best_number_of_pixels = test_num_pixels;
+// Generates a scale factor that makes |input_num_pixels| smaller or
+// larger than |target_num_pixels|, depending on the value of |step_up|.
+Fraction FindScale(int input_num_pixels, int target_num_pixels, bool step_up) {
+ Fraction best_scale = Fraction{1, 1};
+ Fraction last_scale = Fraction{1, 1};
+ const float target_scale =
+ sqrt(target_num_pixels / static_cast<float>(input_num_pixels));
+ while (best_scale.numerator > (target_scale * best_scale.denominator)) {
+ last_scale = best_scale;
+ if (best_scale.numerator % 3 == 0 && best_scale.denominator % 2 == 0) {
+ // Multiply by 2/3
+ best_scale.numerator /= 3;
+ best_scale.denominator /= 2;
+ } else {
+ // Multiply by 3/4
+ best_scale.numerator *= 3;
+ best_scale.denominator *= 4;
}
}
-
- *resulting_number_of_pixels = static_cast<int>(best_number_of_pixels + .5f);
+ if (step_up)
+ return last_scale;
return best_scale;
}
-
-Fraction FindScale(int input_num_pixels,
- int max_pixel_count_step_up,
- int max_pixel_count) {
- // Try scale just above |max_pixel_count_step_up_|.
- if (max_pixel_count_step_up > 0) {
- int resulting_pixel_count;
- const Fraction scale = FindScaleLargerThan(
- input_num_pixels, max_pixel_count_step_up, &resulting_pixel_count);
- if (resulting_pixel_count <= max_pixel_count)
- return scale;
- }
- // Return largest scale below |max_pixel_count|.
- return FindScaleLessThanOrEqual(input_num_pixels, max_pixel_count);
-}
-
} // namespace
namespace cricket {
-VideoAdapter::VideoAdapter()
+VideoAdapter::VideoAdapter(int required_resolution_alignment)
: frames_in_(0),
frames_out_(0),
frames_scaled_(0),
adaption_changes_(0),
previous_width_(0),
previous_height_(0),
+ required_resolution_alignment_(required_resolution_alignment),
resolution_request_max_pixel_count_(std::numeric_limits<int>::max()),
resolution_request_max_pixel_count_step_up_(0) {}
+VideoAdapter::VideoAdapter() : VideoAdapter(1) {}
+
VideoAdapter::~VideoAdapter() {}
bool VideoAdapter::KeepFrame(int64_t in_timestamp_ns) {
@@ -165,10 +120,14 @@ bool VideoAdapter::AdaptFrameResolution(int in_width,
// The max output pixel count is the minimum of the requests from
// OnOutputFormatRequest and OnResolutionRequest.
+ const bool step_up = resolution_request_max_pixel_count_step_up_;
int max_pixel_count = resolution_request_max_pixel_count_;
if (requested_format_) {
+ // TODO(kthelgason): remove the - |step_up| hack when we change how
magjed_webrtc 2016/12/08 13:45:32 Explain also how this logic works, i.e. we are not
+ // resolution is requested from VideoSourceProxy.
max_pixel_count = std::min(
- max_pixel_count, requested_format_->width * requested_format_->height);
+ max_pixel_count,
+ requested_format_->width * requested_format_->height - step_up);
}
// Drop the input frame if necessary.
@@ -211,22 +170,25 @@ bool VideoAdapter::AdaptFrameResolution(int in_width,
*cropped_height =
std::min(in_height, static_cast<int>(in_width / requested_aspect));
}
-
- // Find best scale factor.
const Fraction scale =
- FindScale(*cropped_width * *cropped_height,
- resolution_request_max_pixel_count_step_up_, max_pixel_count);
-
+ FindScale(*cropped_width * *cropped_height, max_pixel_count, step_up);
// Adjust cropping slightly to get even integer output size and a perfect
- // scale factor.
- *cropped_width = roundUp(*cropped_width, scale.denominator, in_width);
- *cropped_height = roundUp(*cropped_height, scale.denominator, in_height);
+ // scale factor. Make sure the resulting dimensions are aligned correctly
+ // to be nice to hardware encoders.
+ *cropped_width =
+ roundUp(*cropped_width,
+ scale.denominator * required_resolution_alignment_, in_width);
+ *cropped_height =
+ roundUp(*cropped_height,
+ scale.denominator * required_resolution_alignment_, in_height);
RTC_DCHECK_EQ(0, *cropped_width % scale.denominator);
RTC_DCHECK_EQ(0, *cropped_height % scale.denominator);
// Calculate final output size.
*out_width = *cropped_width / scale.denominator * scale.numerator;
*out_height = *cropped_height / scale.denominator * scale.numerator;
+ RTC_DCHECK_EQ(0, *out_height % required_resolution_alignment_);
+ RTC_DCHECK_EQ(0, *out_height % required_resolution_alignment_);
++frames_out_;
if (scale.numerator != scale.denominator)
@@ -260,8 +222,8 @@ void VideoAdapter::OnResolutionRequest(
rtc::Optional<int> max_pixel_count,
rtc::Optional<int> max_pixel_count_step_up) {
rtc::CritScope cs(&critical_section_);
- resolution_request_max_pixel_count_ =
- max_pixel_count.value_or(std::numeric_limits<int>::max());
+ resolution_request_max_pixel_count_ = max_pixel_count.value_or(
+ max_pixel_count_step_up.value_or(std::numeric_limits<int>::max()));
resolution_request_max_pixel_count_step_up_ =
magjed_webrtc 2016/12/08 13:45:32 Store |scale_up| instead of |resolution_request_ma
max_pixel_count_step_up.value_or(0);
}
« no previous file with comments | « webrtc/media/base/videoadapter.h ('k') | webrtc/media/base/videoadapter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698