Index: webrtc/media/base/videoadapter.cc |
diff --git a/webrtc/media/base/videoadapter.cc b/webrtc/media/base/videoadapter.cc |
index 9c3837c5729bc4b48531689c36ed2e0a9206afc7..e1f506f10b0eec15e66930959d40df9a1d6c94f4 100644 |
--- a/webrtc/media/base/videoadapter.cc |
+++ b/webrtc/media/base/videoadapter.cc |
@@ -11,6 +11,7 @@ |
#include "webrtc/media/base/videoadapter.h" |
#include <algorithm> |
+#include <cstdlib> |
#include <limits> |
#include "webrtc/base/checks.h" |
@@ -118,22 +119,43 @@ VideoAdapter::VideoAdapter() |
adaption_changes_(0), |
previous_width_(0), |
previous_height_(0), |
- input_interval_(0), |
- interval_next_frame_(0), |
resolution_request_max_pixel_count_(std::numeric_limits<int>::max()), |
resolution_request_max_pixel_count_step_up_(0) {} |
VideoAdapter::~VideoAdapter() {} |
-void VideoAdapter::SetExpectedInputFrameInterval(int64_t interval) { |
- // TODO(perkj): Consider measuring input frame rate instead. |
- // Frame rate typically varies depending on lighting. |
+bool VideoAdapter::KeepFrame(int64_t in_timestamp_ns) { |
rtc::CritScope cs(&critical_section_); |
- input_interval_ = interval; |
+ if (!requested_format_ || requested_format_->interval == 0) |
+ 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) { |
+ // 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; |
+ return true; |
+ } |
+ } |
+ |
+ // First timestamp received or timestamp is way outside expected range, so |
+ // 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); |
+ return true; |
} |
void VideoAdapter::AdaptFrameResolution(int in_width, |
int in_height, |
+ int64_t in_timestamp_ns, |
int* cropped_width, |
int* cropped_height, |
int* out_width, |
@@ -150,25 +172,7 @@ void VideoAdapter::AdaptFrameResolution(int in_width, |
} |
// Drop the input frame if necessary. |
- bool should_drop = false; |
- if (max_pixel_count == 0) { |
- // Drop all frames as the output format is 0x0. |
- should_drop = true; |
- } else if (requested_format_ && requested_format_->interval > 0) { |
- // Drop some frames based on input fps and output fps. |
- // Normally output fps is less than input fps. |
- interval_next_frame_ += input_interval_; |
- if (interval_next_frame_ >= requested_format_->interval) { |
- interval_next_frame_ -= requested_format_->interval; |
- // Reset |interval_next_frame_| if it accumulates too much to avoid |
- // "catching up" behaviour. |
- if (interval_next_frame_ >= requested_format_->interval) |
- interval_next_frame_ = 0; |
- } else { |
- should_drop = true; |
- } |
- } |
- if (should_drop) { |
+ if (max_pixel_count == 0 || !KeepFrame(in_timestamp_ns)) { |
// Show VAdapt log every 90 frames dropped. (3 seconds) |
if ((frames_in_ - frames_out_) % 90 == 0) { |
// TODO(fbarchard): Reduce to LS_VERBOSE when adapter info is not needed |
@@ -179,7 +183,7 @@ void VideoAdapter::AdaptFrameResolution(int in_width, |
<< " Changes: " << adaption_changes_ |
<< " Input: " << in_width |
<< "x" << in_height |
- << " i" << input_interval_ |
+ << " timestamp: " << in_timestamp_ns |
<< " Output: i" |
<< (requested_format_ ? requested_format_->interval : 0); |
} |
@@ -238,7 +242,7 @@ void VideoAdapter::AdaptFrameResolution(int in_width, |
LOG(LS_INFO) << "Frame size changed: scaled " << frames_scaled_ << " / out " |
<< frames_out_ << " / in " << frames_in_ |
<< " Changes: " << adaption_changes_ << " Input: " << in_width |
- << "x" << in_height << " i" << input_interval_ |
+ << "x" << in_height |
<< " Scale: " << scale.numerator << "/" << scale.denominator |
<< " Output: " << *out_width << "x" << *out_height << " i" |
<< (requested_format_ ? requested_format_->interval : 0); |
@@ -251,7 +255,7 @@ void VideoAdapter::AdaptFrameResolution(int in_width, |
void VideoAdapter::OnOutputFormatRequest(const VideoFormat& format) { |
rtc::CritScope cs(&critical_section_); |
requested_format_ = rtc::Optional<VideoFormat>(format); |
- interval_next_frame_ = 0; |
+ next_frame_timestamp_ns_ = rtc::Optional<int64_t>(); |
} |
void VideoAdapter::OnResolutionRequest( |