blob: 23e9c70cbd68a89beaafd7480d3381d6d6924c01 [file] [log] [blame]
Åsa Persson062acd92021-08-16 09:33:13 +02001/*
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
17namespace webrtc {
18namespace {
19constexpr double kMinFramerate = 0.5;
20} // namespace
21
22FramerateController::FramerateController()
Åsa Persson59947d22021-08-26 12:04:27 +020023 : FramerateController(std::numeric_limits<double>::max()) {}
24
25FramerateController::FramerateController(double max_framerate)
26 : max_framerate_(max_framerate) {}
Åsa Persson062acd92021-08-16 09:33:13 +020027
28FramerateController::~FramerateController() {}
29
30void FramerateController::SetMaxFramerate(double max_framerate) {
31 max_framerate_ = max_framerate;
32}
33
Åsa Persson59947d22021-08-26 12:04:27 +020034double FramerateController::GetMaxFramerate() const {
35 return max_framerate_;
36}
37
Åsa Persson062acd92021-08-16 09:33:13 +020038bool 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
72void FramerateController::Reset() {
73 max_framerate_ = std::numeric_limits<double>::max();
74 next_frame_timestamp_ns_ = absl::nullopt;
75}
76
Åsa Persson59947d22021-08-26 12:04:27 +020077void 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
Åsa Persson062acd92021-08-16 09:33:13 +020088} // namespace webrtc