xref: /aosp_15_r20/external/webrtc/modules/video_coding/nack_requester.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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_REQUESTER_H_
12 #define MODULES_VIDEO_CODING_NACK_REQUESTER_H_
13 
14 #include <stdint.h>
15 
16 #include <map>
17 #include <set>
18 #include <vector>
19 
20 #include "api/field_trials_view.h"
21 #include "api/sequence_checker.h"
22 #include "api/task_queue/pending_task_safety_flag.h"
23 #include "api/task_queue/task_queue_base.h"
24 #include "api/units/time_delta.h"
25 #include "api/units/timestamp.h"
26 #include "modules/include/module_common_types.h"
27 #include "modules/video_coding/histogram.h"
28 #include "rtc_base/numerics/sequence_number_util.h"
29 #include "rtc_base/task_utils/repeating_task.h"
30 #include "rtc_base/thread_annotations.h"
31 #include "system_wrappers/include/clock.h"
32 
33 namespace webrtc {
34 
35 class NackRequesterBase {
36  public:
37   virtual ~NackRequesterBase() = default;
38   virtual void ProcessNacks() = 0;
39 };
40 
41 class NackPeriodicProcessor {
42  public:
43   static constexpr TimeDelta kUpdateInterval = TimeDelta::Millis(20);
44   explicit NackPeriodicProcessor(TimeDelta update_interval = kUpdateInterval);
45   ~NackPeriodicProcessor();
46   void RegisterNackModule(NackRequesterBase* module);
47   void UnregisterNackModule(NackRequesterBase* module);
48 
49  private:
50   void ProcessNackModules() RTC_RUN_ON(sequence_);
51 
52   const TimeDelta update_interval_;
53   RepeatingTaskHandle repeating_task_ RTC_GUARDED_BY(sequence_);
54   std::vector<NackRequesterBase*> modules_ RTC_GUARDED_BY(sequence_);
55   RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_;
56 };
57 
58 class ScopedNackPeriodicProcessorRegistration {
59  public:
60   ScopedNackPeriodicProcessorRegistration(NackRequesterBase* module,
61                                           NackPeriodicProcessor* processor);
62   ~ScopedNackPeriodicProcessorRegistration();
63 
64  private:
65   NackRequesterBase* const module_;
66   NackPeriodicProcessor* const processor_;
67 };
68 
69 class NackRequester final : public NackRequesterBase {
70  public:
71   NackRequester(TaskQueueBase* current_queue,
72                 NackPeriodicProcessor* periodic_processor,
73                 Clock* clock,
74                 NackSender* nack_sender,
75                 KeyFrameRequestSender* keyframe_request_sender,
76                 const FieldTrialsView& field_trials);
77   ~NackRequester();
78 
79   void ProcessNacks() override;
80 
81   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);
86 
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              Timestamp created_at_time);
100 
101     uint16_t seq_num;
102     uint16_t send_at_seq_num;
103     Timestamp created_at_time;
104     Timestamp sent_at_time;
105     int retries;
106   };
107 
108   void AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end)
109       RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
110 
111   // Removes packets from the nack list until the next keyframe. Returns true
112   // if packets were removed.
113   bool RemovePacketsUntilKeyFrame()
114       RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
115   std::vector<uint16_t> GetNackBatch(NackFilterOptions options)
116       RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
117 
118   // Update the reordering distribution.
119   void UpdateReorderingStatistics(uint16_t seq_num)
120       RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
121 
122   // Returns how many packets we have to wait in order to receive the packet
123   // with probability `probabilty` or higher.
124   int WaitNumberOfPackets(float probability) const
125       RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
126 
127   TaskQueueBase* const worker_thread_;
128   Clock* const clock_;
129   NackSender* const nack_sender_;
130   KeyFrameRequestSender* const keyframe_request_sender_;
131 
132   // TODO(philipel): Some of the variables below are consistently used on a
133   // known thread (e.g. see `initialized_`). Those probably do not need
134   // synchronized access.
135   std::map<uint16_t, NackInfo, DescendingSeqNumComp<uint16_t>> nack_list_
136       RTC_GUARDED_BY(worker_thread_);
137   std::set<uint16_t, DescendingSeqNumComp<uint16_t>> keyframe_list_
138       RTC_GUARDED_BY(worker_thread_);
139   std::set<uint16_t, DescendingSeqNumComp<uint16_t>> recovered_list_
140       RTC_GUARDED_BY(worker_thread_);
141   video_coding::Histogram reordering_histogram_ RTC_GUARDED_BY(worker_thread_);
142   bool initialized_ RTC_GUARDED_BY(worker_thread_);
143   TimeDelta rtt_ RTC_GUARDED_BY(worker_thread_);
144   uint16_t newest_seq_num_ RTC_GUARDED_BY(worker_thread_);
145 
146   // Adds a delay before send nack on packet received.
147   const TimeDelta send_nack_delay_;
148 
149   ScopedNackPeriodicProcessorRegistration processor_registration_;
150 
151   // Used to signal destruction to potentially pending tasks.
152   ScopedTaskSafety task_safety_;
153 };
154 
155 }  // namespace webrtc
156 
157 #endif  // MODULES_VIDEO_CODING_NACK_REQUESTER_H_
158