blob: f1f212c94fa76f67a040dbb1e0489e185e7b80f8 [file] [log] [blame]
Tommid3807da2020-05-22 17:36:36 +02001/*
2 * Copyright (c) 2016 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#ifndef MODULES_VIDEO_CODING_NACK_MODULE2_H_
12#define MODULES_VIDEO_CODING_NACK_MODULE2_H_
13
14#include <stdint.h>
15
16#include <map>
17#include <set>
18#include <vector>
19
Artem Titovd15a5752021-02-10 14:31:24 +010020#include "api/sequence_checker.h"
Tommid3807da2020-05-22 17:36:36 +020021#include "api/units/time_delta.h"
Tommid3807da2020-05-22 17:36:36 +020022#include "modules/include/module_common_types.h"
23#include "modules/video_coding/histogram.h"
Tommid3807da2020-05-22 17:36:36 +020024#include "rtc_base/numerics/sequence_number_util.h"
Tommi63673fe2020-05-27 12:55:38 +020025#include "rtc_base/task_queue.h"
26#include "rtc_base/task_utils/pending_task_safety_flag.h"
27#include "rtc_base/task_utils/repeating_task.h"
Tommid3807da2020-05-22 17:36:36 +020028#include "rtc_base/thread_annotations.h"
29#include "system_wrappers/include/clock.h"
30
31namespace webrtc {
32
Markus Handell0e62f7a2021-07-20 13:32:02 +020033class NackModuleBase {
34 public:
35 virtual ~NackModuleBase() = default;
36 virtual void ProcessNacks() = 0;
37};
38
39class NackPeriodicProcessor {
40 public:
41 static constexpr TimeDelta kUpdateInterval = TimeDelta::Millis(20);
42 explicit NackPeriodicProcessor(TimeDelta update_interval = kUpdateInterval);
43 ~NackPeriodicProcessor();
44 void RegisterNackModule(NackModuleBase* module);
45 void UnregisterNackModule(NackModuleBase* module);
46
47 private:
48 void ProcessNackModules() RTC_RUN_ON(sequence_);
49
50 const TimeDelta update_interval_;
51 RepeatingTaskHandle repeating_task_ RTC_GUARDED_BY(sequence_);
52 std::vector<NackModuleBase*> modules_ RTC_GUARDED_BY(sequence_);
53 RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_;
54};
55
56class ScopedNackPeriodicProcessorRegistration {
57 public:
58 ScopedNackPeriodicProcessorRegistration(NackModuleBase* module,
59 NackPeriodicProcessor* processor);
60 ~ScopedNackPeriodicProcessorRegistration();
61
62 private:
63 NackModuleBase* const module_;
64 NackPeriodicProcessor* const processor_;
65};
66
Tommi63673fe2020-05-27 12:55:38 +020067// TODO(bugs.webrtc.org/11594): This class no longer implements the Module
68// interface and therefore "NackModule" may not be a descriptive name anymore.
69// Consider renaming to e.g. NackTracker or NackRequester.
Markus Handell0e62f7a2021-07-20 13:32:02 +020070class NackModule2 final : public NackModuleBase {
Tommid3807da2020-05-22 17:36:36 +020071 public:
Tommi63673fe2020-05-27 12:55:38 +020072 NackModule2(TaskQueueBase* current_queue,
Markus Handell0e62f7a2021-07-20 13:32:02 +020073 NackPeriodicProcessor* periodic_processor,
Tommi63673fe2020-05-27 12:55:38 +020074 Clock* clock,
Tommid3807da2020-05-22 17:36:36 +020075 NackSender* nack_sender,
Markus Handell0e62f7a2021-07-20 13:32:02 +020076 KeyFrameRequestSender* keyframe_request_sender);
Tommi63673fe2020-05-27 12:55:38 +020077 ~NackModule2();
Tommid3807da2020-05-22 17:36:36 +020078
Markus Handell0e62f7a2021-07-20 13:32:02 +020079 void ProcessNacks() override;
80
Tommid3807da2020-05-22 17:36:36 +020081 int OnReceivedPacket(uint16_t seq_num, bool is_keyframe);
82 int OnReceivedPacket(uint16_t seq_num, bool is_keyframe, bool is_recovered);
83
84 void ClearUpTo(uint16_t seq_num);
85 void UpdateRtt(int64_t rtt_ms);
Tommid3807da2020-05-22 17:36:36 +020086
87 private:
88 // Which fields to consider when deciding which packet to nack in
89 // GetNackBatch.
90 enum NackFilterOptions { kSeqNumOnly, kTimeOnly, kSeqNumAndTime };
91
92 // This class holds the sequence number of the packet that is in the nack list
93 // as well as the meta data about when it should be nacked and how many times
94 // we have tried to nack this packet.
95 struct NackInfo {
96 NackInfo();
97 NackInfo(uint16_t seq_num,
98 uint16_t send_at_seq_num,
99 int64_t created_at_time);
100
101 uint16_t seq_num;
102 uint16_t send_at_seq_num;
103 int64_t created_at_time;
104 int64_t sent_at_time;
105 int retries;
106 };
107
108 struct BackoffSettings {
109 BackoffSettings(TimeDelta min_retry, TimeDelta max_rtt, double base);
110 static absl::optional<BackoffSettings> ParseFromFieldTrials();
111
112 // Min time between nacks.
113 const TimeDelta min_retry_interval;
114 // Upper bound on link-delay considered for exponential backoff.
115 const TimeDelta max_rtt;
116 // Base for the exponential backoff.
117 const double base;
118 };
119
120 void AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end)
Tommi63673fe2020-05-27 12:55:38 +0200121 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200122
123 // Removes packets from the nack list until the next keyframe. Returns true
124 // if packets were removed.
Tommi63673fe2020-05-27 12:55:38 +0200125 bool RemovePacketsUntilKeyFrame()
126 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200127 std::vector<uint16_t> GetNackBatch(NackFilterOptions options)
Tommi63673fe2020-05-27 12:55:38 +0200128 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200129
130 // Update the reordering distribution.
131 void UpdateReorderingStatistics(uint16_t seq_num)
Tommi63673fe2020-05-27 12:55:38 +0200132 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200133
134 // Returns how many packets we have to wait in order to receive the packet
135 // with probability |probabilty| or higher.
136 int WaitNumberOfPackets(float probability) const
Tommi63673fe2020-05-27 12:55:38 +0200137 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200138
Tommi63673fe2020-05-27 12:55:38 +0200139 TaskQueueBase* const worker_thread_;
Tommid3807da2020-05-22 17:36:36 +0200140 Clock* const clock_;
141 NackSender* const nack_sender_;
142 KeyFrameRequestSender* const keyframe_request_sender_;
143
144 // TODO(philipel): Some of the variables below are consistently used on a
145 // known thread (e.g. see |initialized_|). Those probably do not need
146 // synchronized access.
147 std::map<uint16_t, NackInfo, DescendingSeqNumComp<uint16_t>> nack_list_
Tommi63673fe2020-05-27 12:55:38 +0200148 RTC_GUARDED_BY(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200149 std::set<uint16_t, DescendingSeqNumComp<uint16_t>> keyframe_list_
Tommi63673fe2020-05-27 12:55:38 +0200150 RTC_GUARDED_BY(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200151 std::set<uint16_t, DescendingSeqNumComp<uint16_t>> recovered_list_
Tommi63673fe2020-05-27 12:55:38 +0200152 RTC_GUARDED_BY(worker_thread_);
153 video_coding::Histogram reordering_histogram_ RTC_GUARDED_BY(worker_thread_);
154 bool initialized_ RTC_GUARDED_BY(worker_thread_);
155 int64_t rtt_ms_ RTC_GUARDED_BY(worker_thread_);
156 uint16_t newest_seq_num_ RTC_GUARDED_BY(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200157
158 // Adds a delay before send nack on packet received.
159 const int64_t send_nack_delay_ms_;
160
161 const absl::optional<BackoffSettings> backoff_settings_;
Tommi63673fe2020-05-27 12:55:38 +0200162
Markus Handell0e62f7a2021-07-20 13:32:02 +0200163 ScopedNackPeriodicProcessorRegistration processor_registration_;
164
Tommi63673fe2020-05-27 12:55:38 +0200165 // Used to signal destruction to potentially pending tasks.
166 ScopedTaskSafety task_safety_;
Tommid3807da2020-05-22 17:36:36 +0200167};
168
169} // namespace webrtc
170
171#endif // MODULES_VIDEO_CODING_NACK_MODULE2_H_