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 |