Chromium Code Reviews| Index: webrtc/media/base/videoadapter.cc |
| diff --git a/webrtc/media/base/videoadapter.cc b/webrtc/media/base/videoadapter.cc |
| index 8f7288dc590290fe40213b998b6a383b5a3147bc..3de76b1ff66a9229026f4c72baece658626764a5 100644 |
| --- a/webrtc/media/base/videoadapter.cc |
| +++ b/webrtc/media/base/videoadapter.cc |
| @@ -26,6 +26,12 @@ namespace { |
| struct Fraction { |
| int numerator; |
| int denominator; |
| + |
| + // Determines number of output pixels if both width and height of an input of |
| + // |input_pixels| pixels is scaled with the fraction numerator / denominator. |
| + int scale_pixel_count(int input_pixels) { |
| + return (numerator * numerator * input_pixels) / (denominator * denominator); |
| + } |
| }; |
| // Round |value_to_round| to a multiple of |multiple|. Prefer rounding upwards, |
| @@ -37,29 +43,49 @@ int roundUp(int value_to_round, int multiple, int max_value) { |
| : (max_value / multiple * multiple); |
| } |
| -// 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) { |
| +// Generates a scale factor that makes |input_pixels| close to |target_pixels|, |
| +// but no higher than |max_pixels|. |
| +Fraction FindScale(int input_pixels, int target_pixels, int max_pixels) { |
| // This function only makes sense for a positive target. |
| - RTC_DCHECK_GT(target_num_pixels, 0); |
| + RTC_DCHECK_GT(target_pixels, 0); |
| + RTC_DCHECK_GT(max_pixels, 0); |
| + RTC_DCHECK_GE(max_pixels, target_pixels); |
| + |
| + // Don't scale up original. |
| + if (target_pixels >= input_pixels) |
| + return Fraction{1, 1}; |
| + |
| + Fraction current_scale = Fraction{1, 1}; |
| 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; |
| + // The minimum (absolute) difference between the number of output pixels and |
| + // the target pixel count. |
| + int min_pixel_diff = input_pixels; |
| + if (input_pixels < max_pixels) { |
| + // Start condition for 1/1 case, if it is less than max. |
| + min_pixel_diff = std::abs(input_pixels - target_pixels); |
| + } |
| + while (current_scale.scale_pixel_count(input_pixels) > target_pixels) { |
| + if (current_scale.numerator % 3 == 0 && |
| + current_scale.denominator % 2 == 0) { |
| + // Multiply by 2/3. |
|
nisse-webrtc
2017/02/06 08:43:19
I think this logic deserves some explanation. But
sprang_webrtc
2017/02/06 10:34:02
I'll add a brief comment. But yes, it was not imme
|
| + current_scale.numerator /= 3; |
| + current_scale.denominator /= 2; |
| } else { |
| - // Multiply by 3/4 |
| - best_scale.numerator *= 3; |
| - best_scale.denominator *= 4; |
| + // Multiply by 3/4. |
| + current_scale.numerator *= 3; |
| + current_scale.denominator *= 4; |
| + } |
| + |
| + int output_pixels = current_scale.scale_pixel_count(input_pixels); |
| + if (output_pixels <= max_pixels) { |
| + int diff = std::abs(target_pixels - output_pixels); |
| + if (diff < min_pixel_diff) { |
| + min_pixel_diff = diff; |
| + best_scale = current_scale; |
| + } |
| } |
| } |
| - if (step_up) |
| - return last_scale; |
| + |
| return best_scale; |
| } |
| } // namespace |
| @@ -74,8 +100,8 @@ VideoAdapter::VideoAdapter(int required_resolution_alignment) |
| previous_width_(0), |
| previous_height_(0), |
| required_resolution_alignment_(required_resolution_alignment), |
| - resolution_request_max_pixel_count_(std::numeric_limits<int>::max()), |
| - step_up_(false) {} |
| + resolution_request_target_pixel_count_(std::numeric_limits<int>::max()), |
| + resolution_request_max_pixel_count_(std::numeric_limits<int>::max()) {} |
| VideoAdapter::VideoAdapter() : VideoAdapter(1) {} |
| @@ -129,9 +155,10 @@ bool VideoAdapter::AdaptFrameResolution(int in_width, |
| // This is required because we must not scale above the requested |
| // format so we subtract one when scaling up. |
| max_pixel_count = std::min( |
| - max_pixel_count, requested_format_->width * requested_format_->height - |
| - static_cast<int>(step_up_)); |
| + max_pixel_count, requested_format_->width * requested_format_->height); |
| } |
| + int target_pixel_count = |
| + std::min(resolution_request_target_pixel_count_, max_pixel_count); |
| // Drop the input frame if necessary. |
| if (max_pixel_count <= 0 || !KeepFrame(in_timestamp_ns)) { |
| @@ -173,8 +200,8 @@ bool VideoAdapter::AdaptFrameResolution(int in_width, |
| *cropped_height = |
| std::min(in_height, static_cast<int>(in_width / requested_aspect)); |
| } |
| - const Fraction scale = |
| - FindScale(*cropped_width * *cropped_height, max_pixel_count, step_up_); |
| + const Fraction scale = FindScale((*cropped_width) * (*cropped_height), |
| + target_pixel_count, max_pixel_count); |
| // Adjust cropping slightly to get even integer output size and a perfect |
| // scale factor. Make sure the resulting dimensions are aligned correctly |
| // to be nice to hardware encoders. |
| @@ -221,13 +248,13 @@ void VideoAdapter::OnOutputFormatRequest(const VideoFormat& format) { |
| next_frame_timestamp_ns_ = rtc::Optional<int64_t>(); |
| } |
| -void VideoAdapter::OnResolutionRequest( |
| - rtc::Optional<int> max_pixel_count, |
| - rtc::Optional<int> max_pixel_count_step_up) { |
| +void VideoAdapter::OnResolutionRequest(rtc::Optional<int> target_pixel_count, |
| + rtc::Optional<int> max_pixel_count) { |
| rtc::CritScope cs(&critical_section_); |
| - resolution_request_max_pixel_count_ = max_pixel_count.value_or( |
| - max_pixel_count_step_up.value_or(std::numeric_limits<int>::max())); |
| - step_up_ = static_cast<bool>(max_pixel_count_step_up); |
| + resolution_request_target_pixel_count_ = |
| + target_pixel_count.value_or(std::numeric_limits<int>::max()); |
|
nisse-webrtc
2017/02/06 08:43:18
You could swap order, and make max_pixel_count the
sprang_webrtc
2017/02/06 10:34:02
Done.
|
| + resolution_request_max_pixel_count_ = |
| + max_pixel_count.value_or(resolution_request_target_pixel_count_); |
| } |
| } // namespace cricket |