| Index: webrtc/media/base/videoadapter.cc
|
| diff --git a/webrtc/media/base/videoadapter.cc b/webrtc/media/base/videoadapter.cc
|
| index 660df8ad673e8f40668d8f150722cb21082073ee..9175ae8cb1558ec2400df6e84d80ab4831a1d895 100644
|
| --- a/webrtc/media/base/videoadapter.cc
|
| +++ b/webrtc/media/base/videoadapter.cc
|
| @@ -21,15 +21,16 @@
|
| #include "webrtc/base/optional.h"
|
| #include "webrtc/media/base/mediaconstants.h"
|
| #include "webrtc/media/base/videocommon.h"
|
| +#include "webrtc/media/base/videosourceinterface.h"
|
|
|
| namespace {
|
| struct Fraction {
|
| - int numerator;
|
| - int denominator;
|
| + uint32_t numerator;
|
| + uint32_t 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) {
|
| + uint32_t scale_pixel_count(uint32_t input_pixels) {
|
| return (numerator * numerator * input_pixels) / (denominator * denominator);
|
| }
|
| };
|
| @@ -45,7 +46,10 @@ int roundUp(int value_to_round, int multiple, int max_value) {
|
|
|
| // 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) {
|
| +Fraction FindScale(uint32_t input_pixels,
|
| + uint32_t target_pixels,
|
| + uint32_t max_pixels,
|
| + uint32_t min_pixels) {
|
| // This function only makes sense for a positive target.
|
| RTC_DCHECK_GT(target_pixels, 0);
|
| RTC_DCHECK_GT(max_pixels, 0);
|
| @@ -59,10 +63,12 @@ Fraction FindScale(int input_pixels, int target_pixels, int max_pixels) {
|
| Fraction best_scale = Fraction{1, 1};
|
| // The minimum (absolute) difference between the number of output pixels and
|
| // the target pixel count.
|
| - int min_pixel_diff = std::numeric_limits<int>::max();
|
| + uint32_t min_pixel_diff = std::numeric_limits<uint32_t>::max();
|
| 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);
|
| + min_pixel_diff = target_pixels > input_pixels
|
| + ? target_pixels - input_pixels
|
| + : input_pixels - target_pixels;
|
| }
|
|
|
| // Alternately scale down by 2/3 and 3/4. This results in fractions which are
|
| @@ -81,9 +87,15 @@ Fraction FindScale(int input_pixels, int target_pixels, int max_pixels) {
|
| current_scale.denominator *= 4;
|
| }
|
|
|
| - int output_pixels = current_scale.scale_pixel_count(input_pixels);
|
| + uint32_t output_pixels = current_scale.scale_pixel_count(input_pixels);
|
| + if (output_pixels < min_pixels) {
|
| + // Don't violate lower bound;
|
| + break;
|
| + }
|
| if (output_pixels <= max_pixels) {
|
| - int diff = std::abs(target_pixels - output_pixels);
|
| + uint32_t diff = target_pixels < output_pixels
|
| + ? output_pixels - target_pixels
|
| + : target_pixels - output_pixels;
|
| if (diff < min_pixel_diff) {
|
| min_pixel_diff = diff;
|
| best_scale = current_scale;
|
| @@ -104,9 +116,7 @@ VideoAdapter::VideoAdapter(int required_resolution_alignment)
|
| adaption_changes_(0),
|
| previous_width_(0),
|
| previous_height_(0),
|
| - required_resolution_alignment_(required_resolution_alignment),
|
| - resolution_request_target_pixel_count_(std::numeric_limits<int>::max()),
|
| - resolution_request_max_pixel_count_(std::numeric_limits<int>::max()) {}
|
| + required_resolution_alignment_(required_resolution_alignment) {}
|
|
|
| VideoAdapter::VideoAdapter() : VideoAdapter(1) {}
|
|
|
| @@ -114,21 +124,35 @@ VideoAdapter::~VideoAdapter() {}
|
|
|
| bool VideoAdapter::KeepFrame(int64_t in_timestamp_ns) {
|
| rtc::CritScope cs(&critical_section_);
|
| - if (!requested_format_ || requested_format_->interval == 0)
|
| +
|
| + int64_t frame_interval_ns = 0;
|
| + if (requested_format_ && requested_format_->interval)
|
| + frame_interval_ns = requested_format_->interval;
|
| + // TODO(sprang): Take target/min into consideration when implementing smoother
|
| + // frame dropping.
|
| + if (requested_framerate_fps_) {
|
| + frame_interval_ns = std::max<int64_t>(
|
| + frame_interval_ns,
|
| + rtc::kNumNanosecsPerSec / requested_framerate_fps_->max);
|
| + }
|
| +
|
| + if (frame_interval_ns <= 0) {
|
| + // Frame rate throttling not enabled.
|
| return true;
|
| + }
|
|
|
| if (next_frame_timestamp_ns_) {
|
| // Time until next frame should be outputted.
|
| const int64_t time_until_next_frame_ns =
|
| (*next_frame_timestamp_ns_ - in_timestamp_ns);
|
|
|
| - // Continue if timestamp is withing expected range.
|
| - if (std::abs(time_until_next_frame_ns) < 2 * requested_format_->interval) {
|
| + // Continue if timestamp is within expected range.
|
| + if (std::abs(time_until_next_frame_ns) < 2 * frame_interval_ns) {
|
| // Drop if a frame shouldn't be outputted yet.
|
| if (time_until_next_frame_ns > 0)
|
| return false;
|
| // Time to output new frame.
|
| - *next_frame_timestamp_ns_ += requested_format_->interval;
|
| + *next_frame_timestamp_ns_ += frame_interval_ns;
|
| return true;
|
| }
|
| }
|
| @@ -137,7 +161,7 @@ bool VideoAdapter::KeepFrame(int64_t in_timestamp_ns) {
|
| // reset. Set first timestamp target to just half the interval to prefer
|
| // keeping frames in case of jitter.
|
| next_frame_timestamp_ns_ =
|
| - rtc::Optional<int64_t>(in_timestamp_ns + requested_format_->interval / 2);
|
| + rtc::Optional<int64_t>(in_timestamp_ns + frame_interval_ns / 2);
|
| return true;
|
| }
|
|
|
| @@ -153,13 +177,19 @@ bool VideoAdapter::AdaptFrameResolution(int in_width,
|
|
|
| // The max output pixel count is the minimum of the requests from
|
| // OnOutputFormatRequest and OnResolutionRequest.
|
| - int max_pixel_count = resolution_request_max_pixel_count_;
|
| +
|
| + rtc::VideoSinkWants::Range requested_range =
|
| + requested_pixel_count_.value_or(rtc::VideoSinkWants::Range());
|
| + RTC_DCHECK_GE(requested_range.target, requested_range.min);
|
| + RTC_DCHECK_GE(requested_range.max, requested_range.target);
|
| + uint32_t max_pixel_count = requested_range.max;
|
| if (requested_format_) {
|
| max_pixel_count = std::min(
|
| - max_pixel_count, requested_format_->width * requested_format_->height);
|
| + max_pixel_count, static_cast<uint32_t>(requested_format_->width *
|
| + requested_format_->height));
|
| }
|
| - int target_pixel_count =
|
| - std::min(resolution_request_target_pixel_count_, max_pixel_count);
|
| + uint32_t target_pixel_count =
|
| + std::min(requested_range.target, max_pixel_count);
|
|
|
| // Drop the input frame if necessary.
|
| if (max_pixel_count <= 0 || !KeepFrame(in_timestamp_ns)) {
|
| @@ -201,8 +231,9 @@ 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),
|
| - target_pixel_count, max_pixel_count);
|
| + const Fraction scale =
|
| + FindScale((*cropped_width) * (*cropped_height), target_pixel_count,
|
| + max_pixel_count, requested_range.min);
|
| // 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.
|
| @@ -249,14 +280,12 @@ void VideoAdapter::OnOutputFormatRequest(const VideoFormat& format) {
|
| next_frame_timestamp_ns_ = rtc::Optional<int64_t>();
|
| }
|
|
|
| -void VideoAdapter::OnResolutionRequest(
|
| - const rtc::Optional<int>& target_pixel_count,
|
| - const rtc::Optional<int>& max_pixel_count) {
|
| +void VideoAdapter::OnResolutionFramerateRequest(
|
| + const rtc::Optional<rtc::VideoSinkWants::Range>& pixel_count,
|
| + const rtc::Optional<rtc::VideoSinkWants::Range>& framerate_fps) {
|
| rtc::CritScope cs(&critical_section_);
|
| - resolution_request_max_pixel_count_ =
|
| - max_pixel_count.value_or(std::numeric_limits<int>::max());
|
| - resolution_request_target_pixel_count_ =
|
| - target_pixel_count.value_or(resolution_request_max_pixel_count_);
|
| + requested_pixel_count_ = pixel_count;
|
| + requested_framerate_fps_ = framerate_fps;
|
| }
|
|
|
| } // namespace cricket
|
|
|