blob: 46d904b7a43cdd6f56d5769db7bee6c261a98f84 [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
Markus Handell06a2bf02021-07-22 15:09:39 +020011#ifndef MODULES_VIDEO_CODING_NACK_REQUESTER_H_
12#define MODULES_VIDEO_CODING_NACK_REQUESTER_H_
Tommid3807da2020-05-22 17:36:36 +020013
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 Handell06a2bf02021-07-22 15:09:39 +020033class NackRequesterBase {
Markus Handell0e62f7a2021-07-20 13:32:02 +020034 public:
Markus Handell06a2bf02021-07-22 15:09:39 +020035 virtual ~NackRequesterBase() = default;
Markus Handell0e62f7a2021-07-20 13:32:02 +020036 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();
Markus Handell06a2bf02021-07-22 15:09:39 +020044 void RegisterNackModule(NackRequesterBase* module);
45 void UnregisterNackModule(NackRequesterBase* module);
Markus Handell0e62f7a2021-07-20 13:32:02 +020046
47 private:
48 void ProcessNackModules() RTC_RUN_ON(sequence_);
49
50 const TimeDelta update_interval_;
51 RepeatingTaskHandle repeating_task_ RTC_GUARDED_BY(sequence_);
Markus Handell06a2bf02021-07-22 15:09:39 +020052 std::vector<NackRequesterBase*> modules_ RTC_GUARDED_BY(sequence_);
Markus Handell0e62f7a2021-07-20 13:32:02 +020053 RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_;
54};
55
56class ScopedNackPeriodicProcessorRegistration {
57 public:
Markus Handell06a2bf02021-07-22 15:09:39 +020058 ScopedNackPeriodicProcessorRegistration(NackRequesterBase* module,
Markus Handell0e62f7a2021-07-20 13:32:02 +020059 NackPeriodicProcessor* processor);
60 ~ScopedNackPeriodicProcessorRegistration();
61
62 private:
Markus Handell06a2bf02021-07-22 15:09:39 +020063 NackRequesterBase* const module_;
Markus Handell0e62f7a2021-07-20 13:32:02 +020064 NackPeriodicProcessor* const processor_;
65};
66
Markus Handell06a2bf02021-07-22 15:09:39 +020067class NackRequester final : public NackRequesterBase {
Tommid3807da2020-05-22 17:36:36 +020068 public:
Markus Handell06a2bf02021-07-22 15:09:39 +020069 NackRequester(TaskQueueBase* current_queue,
70 NackPeriodicProcessor* periodic_processor,
71 Clock* clock,
72 NackSender* nack_sender,
73 KeyFrameRequestSender* keyframe_request_sender);
74 ~NackRequester();
Tommid3807da2020-05-22 17:36:36 +020075
Markus Handell0e62f7a2021-07-20 13:32:02 +020076 void ProcessNacks() override;
77
Tommid3807da2020-05-22 17:36:36 +020078 int OnReceivedPacket(uint16_t seq_num, bool is_keyframe);
79 int OnReceivedPacket(uint16_t seq_num, bool is_keyframe, bool is_recovered);
80
81 void ClearUpTo(uint16_t seq_num);
82 void UpdateRtt(int64_t rtt_ms);
Tommid3807da2020-05-22 17:36:36 +020083
84 private:
85 // Which fields to consider when deciding which packet to nack in
86 // GetNackBatch.
87 enum NackFilterOptions { kSeqNumOnly, kTimeOnly, kSeqNumAndTime };
88
89 // This class holds the sequence number of the packet that is in the nack list
90 // as well as the meta data about when it should be nacked and how many times
91 // we have tried to nack this packet.
92 struct NackInfo {
93 NackInfo();
94 NackInfo(uint16_t seq_num,
95 uint16_t send_at_seq_num,
96 int64_t created_at_time);
97
98 uint16_t seq_num;
99 uint16_t send_at_seq_num;
100 int64_t created_at_time;
101 int64_t sent_at_time;
102 int retries;
103 };
104
105 struct BackoffSettings {
106 BackoffSettings(TimeDelta min_retry, TimeDelta max_rtt, double base);
107 static absl::optional<BackoffSettings> ParseFromFieldTrials();
108
109 // Min time between nacks.
110 const TimeDelta min_retry_interval;
111 // Upper bound on link-delay considered for exponential backoff.
112 const TimeDelta max_rtt;
113 // Base for the exponential backoff.
114 const double base;
115 };
116
117 void AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end)
Tommi63673fe2020-05-27 12:55:38 +0200118 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200119
120 // Removes packets from the nack list until the next keyframe. Returns true
121 // if packets were removed.
Tommi63673fe2020-05-27 12:55:38 +0200122 bool RemovePacketsUntilKeyFrame()
123 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200124 std::vector<uint16_t> GetNackBatch(NackFilterOptions options)
Tommi63673fe2020-05-27 12:55:38 +0200125 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200126
127 // Update the reordering distribution.
128 void UpdateReorderingStatistics(uint16_t seq_num)
Tommi63673fe2020-05-27 12:55:38 +0200129 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200130
131 // Returns how many packets we have to wait in order to receive the packet
Artem Titovdcd7fc72021-08-09 13:02:57 +0200132 // with probability `probabilty` or higher.
Tommid3807da2020-05-22 17:36:36 +0200133 int WaitNumberOfPackets(float probability) const
Tommi63673fe2020-05-27 12:55:38 +0200134 RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200135
Tommi63673fe2020-05-27 12:55:38 +0200136 TaskQueueBase* const worker_thread_;
Tommid3807da2020-05-22 17:36:36 +0200137 Clock* const clock_;
138 NackSender* const nack_sender_;
139 KeyFrameRequestSender* const keyframe_request_sender_;
140
141 // TODO(philipel): Some of the variables below are consistently used on a
Artem Titovdcd7fc72021-08-09 13:02:57 +0200142 // known thread (e.g. see `initialized_`). Those probably do not need
Tommid3807da2020-05-22 17:36:36 +0200143 // synchronized access.
144 std::map<uint16_t, NackInfo, DescendingSeqNumComp<uint16_t>> nack_list_
Tommi63673fe2020-05-27 12:55:38 +0200145 RTC_GUARDED_BY(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200146 std::set<uint16_t, DescendingSeqNumComp<uint16_t>> keyframe_list_
Tommi63673fe2020-05-27 12:55:38 +0200147 RTC_GUARDED_BY(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200148 std::set<uint16_t, DescendingSeqNumComp<uint16_t>> recovered_list_
Tommi63673fe2020-05-27 12:55:38 +0200149 RTC_GUARDED_BY(worker_thread_);
150 video_coding::Histogram reordering_histogram_ RTC_GUARDED_BY(worker_thread_);
151 bool initialized_ RTC_GUARDED_BY(worker_thread_);
152 int64_t rtt_ms_ RTC_GUARDED_BY(worker_thread_);
153 uint16_t newest_seq_num_ RTC_GUARDED_BY(worker_thread_);
Tommid3807da2020-05-22 17:36:36 +0200154
155 // Adds a delay before send nack on packet received.
156 const int64_t send_nack_delay_ms_;
157
158 const absl::optional<BackoffSettings> backoff_settings_;
Tommi63673fe2020-05-27 12:55:38 +0200159
Markus Handell0e62f7a2021-07-20 13:32:02 +0200160 ScopedNackPeriodicProcessorRegistration processor_registration_;
161
Tommi63673fe2020-05-27 12:55:38 +0200162 // Used to signal destruction to potentially pending tasks.
163 ScopedTaskSafety task_safety_;
Tommid3807da2020-05-22 17:36:36 +0200164};
165
166} // namespace webrtc
167
Markus Handell06a2bf02021-07-22 15:09:39 +0200168#endif // MODULES_VIDEO_CODING_NACK_REQUESTER_H_