framerate_controller.cc (2792B)
1 /* 2 * Copyright 2021 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "common_video/framerate_controller.h" 12 13 #include <cstdint> 14 #include <cstdlib> 15 #include <limits> 16 #include <optional> 17 18 #include "rtc_base/time_utils.h" 19 20 namespace webrtc { 21 namespace { 22 constexpr double kMinFramerate = 0.5; 23 } // namespace 24 25 FramerateController::FramerateController() 26 : FramerateController(std::numeric_limits<double>::max()) {} 27 28 FramerateController::FramerateController(double max_framerate) 29 : max_framerate_(max_framerate) {} 30 31 FramerateController::~FramerateController() {} 32 33 void FramerateController::SetMaxFramerate(double max_framerate) { 34 max_framerate_ = max_framerate; 35 } 36 37 double FramerateController::GetMaxFramerate() const { 38 return max_framerate_; 39 } 40 41 bool FramerateController::ShouldDropFrame(int64_t in_timestamp_ns) { 42 if (max_framerate_ < kMinFramerate) 43 return true; 44 45 // If `max_framerate_` is not set (i.e. maxdouble), `frame_interval_ns` is 46 // rounded to 0. 47 int64_t frame_interval_ns = kNumNanosecsPerSec / max_framerate_; 48 if (frame_interval_ns <= 0) { 49 // Frame rate throttling not enabled. 50 return false; 51 } 52 53 if (next_frame_timestamp_ns_) { 54 // Time until next frame should be outputted. 55 const int64_t time_until_next_frame_ns = 56 (*next_frame_timestamp_ns_ - in_timestamp_ns); 57 // Continue if timestamp is within expected range. 58 if (std::abs(time_until_next_frame_ns) < 2 * frame_interval_ns) { 59 // Drop if a frame shouldn't be outputted yet. 60 if (time_until_next_frame_ns > 0) 61 return true; 62 // Time to output new frame. 63 *next_frame_timestamp_ns_ += frame_interval_ns; 64 return false; 65 } 66 } 67 68 // First timestamp received or timestamp is way outside expected range, so 69 // reset. Set first timestamp target to just half the interval to prefer 70 // keeping frames in case of jitter. 71 next_frame_timestamp_ns_ = in_timestamp_ns + frame_interval_ns / 2; 72 return false; 73 } 74 75 void FramerateController::Reset() { 76 max_framerate_ = std::numeric_limits<double>::max(); 77 next_frame_timestamp_ns_ = std::nullopt; 78 } 79 80 void FramerateController::KeepFrame(int64_t in_timestamp_ns) { 81 if (ShouldDropFrame(in_timestamp_ns)) { 82 if (max_framerate_ < kMinFramerate) 83 return; 84 85 int64_t frame_interval_ns = kNumNanosecsPerSec / max_framerate_; 86 if (next_frame_timestamp_ns_) 87 *next_frame_timestamp_ns_ += frame_interval_ns; 88 } 89 } 90 91 } // namespace webrtc