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 <limits> 14 15 #include "rtc_base/time_utils.h" 16 17 namespace webrtc { 18 namespace { 19 constexpr double kMinFramerate = 0.5; 20 } // namespace 21 FramerateController()22FramerateController::FramerateController() 23 : FramerateController(std::numeric_limits<double>::max()) {} 24 FramerateController(double max_framerate)25FramerateController::FramerateController(double max_framerate) 26 : max_framerate_(max_framerate) {} 27 ~FramerateController()28FramerateController::~FramerateController() {} 29 SetMaxFramerate(double max_framerate)30void FramerateController::SetMaxFramerate(double max_framerate) { 31 max_framerate_ = max_framerate; 32 } 33 GetMaxFramerate() const34double FramerateController::GetMaxFramerate() const { 35 return max_framerate_; 36 } 37 ShouldDropFrame(int64_t in_timestamp_ns)38bool FramerateController::ShouldDropFrame(int64_t in_timestamp_ns) { 39 if (max_framerate_ < kMinFramerate) 40 return true; 41 42 // If `max_framerate_` is not set (i.e. maxdouble), `frame_interval_ns` is 43 // rounded to 0. 44 int64_t frame_interval_ns = rtc::kNumNanosecsPerSec / max_framerate_; 45 if (frame_interval_ns <= 0) { 46 // Frame rate throttling not enabled. 47 return false; 48 } 49 50 if (next_frame_timestamp_ns_) { 51 // Time until next frame should be outputted. 52 const int64_t time_until_next_frame_ns = 53 (*next_frame_timestamp_ns_ - in_timestamp_ns); 54 // Continue if timestamp is within expected range. 55 if (std::abs(time_until_next_frame_ns) < 2 * frame_interval_ns) { 56 // Drop if a frame shouldn't be outputted yet. 57 if (time_until_next_frame_ns > 0) 58 return true; 59 // Time to output new frame. 60 *next_frame_timestamp_ns_ += frame_interval_ns; 61 return false; 62 } 63 } 64 65 // First timestamp received or timestamp is way outside expected range, so 66 // reset. Set first timestamp target to just half the interval to prefer 67 // keeping frames in case of jitter. 68 next_frame_timestamp_ns_ = in_timestamp_ns + frame_interval_ns / 2; 69 return false; 70 } 71 Reset()72void FramerateController::Reset() { 73 max_framerate_ = std::numeric_limits<double>::max(); 74 next_frame_timestamp_ns_ = absl::nullopt; 75 } 76 KeepFrame(int64_t in_timestamp_ns)77void FramerateController::KeepFrame(int64_t in_timestamp_ns) { 78 if (ShouldDropFrame(in_timestamp_ns)) { 79 if (max_framerate_ < kMinFramerate) 80 return; 81 82 int64_t frame_interval_ns = rtc::kNumNanosecsPerSec / max_framerate_; 83 if (next_frame_timestamp_ns_) 84 *next_frame_timestamp_ns_ += frame_interval_ns; 85 } 86 } 87 88 } // namespace webrtc 89