• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()22 FramerateController::FramerateController()
23     : FramerateController(std::numeric_limits<double>::max()) {}
24 
FramerateController(double max_framerate)25 FramerateController::FramerateController(double max_framerate)
26     : max_framerate_(max_framerate) {}
27 
~FramerateController()28 FramerateController::~FramerateController() {}
29 
SetMaxFramerate(double max_framerate)30 void FramerateController::SetMaxFramerate(double max_framerate) {
31   max_framerate_ = max_framerate;
32 }
33 
GetMaxFramerate() const34 double FramerateController::GetMaxFramerate() const {
35   return max_framerate_;
36 }
37 
ShouldDropFrame(int64_t in_timestamp_ns)38 bool 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()72 void 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)77 void 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