blob: a01fb7cd64bab73d0071679ec18e8132be4af49b [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"
Jonas Orelande02f9ee2022-03-25 12:43:14 +010022#include "api/webrtc_key_value_config.h"
Tommid3807da2020-05-22 17:36:36 +020023#include "modules/include/module_common_types.h"
24#include "modules/video_coding/histogram.h"
Tommid3807da2020-05-22 17:36:36 +020025#include "rtc_base/numerics/sequence_number_util.h"
Tommi63673fe2020-05-27 12:55:38 +020026#include "rtc_base/task_queue.h"
27#include "rtc_base/task_utils/pending_task_safety_flag.h"
28#include "rtc_base/task_utils/repeating_task.h"
Tommid3807da2020-05-22 17:36:36 +020029#include "rtc_base/thread_annotations.h"
30#include "system_wrappers/include/clock.h"
31
32namespace webrtc {
33
Markus Handell06a2bf02021-07-22 15:09:39 +020034class NackRequesterBase {
Markus Handell0e62f7a2021-07-20 13:32:02 +020035 public:
Markus Handell06a2bf02021-07-22 15:09:39 +020036 virtual ~NackRequesterBase() = default;
Markus Handell0e62f7a2021-07-20 13:32:02 +020037 virtual void ProcessNacks() = 0;
38};
39
40class NackPeriodicProcessor {
41 public:
42 static constexpr TimeDelta kUpdateInterval = TimeDelta::Millis(20);
43 explicit NackPeriodicProcessor(TimeDelta update_interval = kUpdateInterval);
44 ~NackPeriodicProcessor();
Markus Handell06a2bf02021-07-22 15:09:39 +020045 void RegisterNackModule(NackRequesterBase* module);
46 void UnregisterNackModule(NackRequesterBase* module);
Markus Handell0e62f7a2021-07-20 13:32:02 +020047
48 private:
49 void ProcessNackModules() RTC_RUN_ON(sequence_);
50
51 const TimeDelta update_interval_;
52 RepeatingTaskHandle repeating_task_ RTC_GUARDED_BY(sequence_);
Markus Handell06a2bf02021-07-22 15:09:39 +020053 std::vector<NackRequesterBase*> modules_ RTC_GUARDED_BY(sequence_);
Markus Handell0e62f7a2021-07-20 13:32:02 +020054 RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_;
55};
56
57class ScopedNackPeriodicProcessorRegistration {
58 public:
Markus Handell06a2bf02021-07-22 15:09:39 +020059 ScopedNackPeriodicProcessorRegistration(NackRequesterBase* module,
Markus Handell0e62f7a2021-07-20 13:32:02 +020060 NackPeriodicProcessor* processor);
61 ~ScopedNackPeriodicProcessorRegistration();
62
63 private:
Markus Handell06a2bf02021-07-22 15:09:39 +020064 NackRequesterBase* const module_;
Markus Handell0e62f7a2021-07-20 13:32:02 +020065 NackPeriodicProcessor* const processor_;
66};
67
Markus Handell06a2bf02021-07-22 15:09:39 +020068class NackRequester final : public NackRequesterBase {
Tommid3807da2020-05-22 17:36:36 +020069 public:
Markus Handell06a2bf02021-07-22 15:09:39 +020070 NackRequester(TaskQueueBase* current_queue,
71 NackPeriodicProcessor* periodic_processor,
72 Clock* clock,
73 NackSender* nack_sender,
Jonas Orelande02f9ee2022-03-25 12:43:14 +010074 KeyFrameRequestSender* keyframe_request_sender,
75 const WebRtcKeyValueConfig& field_trials);
Markus Handell06a2bf02021-07-22 15:09:39 +020076 ~NackRequester();
Tommid3807da2020-05-22 17:36:36 +020077
Markus Handell0e62f7a2021-07-20 13:32:02 +020078 void ProcessNacks() override;
79
Tommid3807da2020-05-22 17:36:36 +020080 int OnReceivedPacket(uint16_t seq_num, bool is_keyframe);
81 int OnReceivedPacket(uint16_t seq_num, bool is_keyframe, bool is_recovered);
82
83 void ClearUpTo(uint16_t seq_num);
84 void UpdateRtt(int64_t rtt_ms);
Tommid3807da2020-05-22 17:36:36 +020085
86 private:
87 // Which fields to consider when deciding which packet to nack in
88 // GetNackBatch.
89 enum NackFilterOptions { kSeqNumOnly, kTimeOnly, kSeqNumAndTime };
90
91 // This class holds the sequence number of the packet that is in the nack list
92 // as well as the meta data about when it should be nacked and how many times
93 // we have tried to nack this packet.
94 struct NackInfo {
95 NackInfo();
96 NackInfo(uint16_t seq_num,
97 uint16_t send_at_seq_num,
98 int64_t created_at_time);
99
100 uint16_t seq_num;
101 uint16_t send_at_seq_num;
102 int64_t created_at_time;
103 int64_t sent_at_time;
104 int retries;
105 };
106
107 struct BackoffSettings {
108 BackoffSettings(TimeDelta min_retry, TimeDelta max_rtt, double base);
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100109 static absl::optional<BackoffSettings> ParseFromFieldTrials(
110 const WebRtcKeyValueConfig& field_trials);
Tommid3807da2020-05-22 17:36:36 +0200111
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
Artem Titovdcd7fc72021-08-09 13:02:57 +0200135 // with probability `probabilty` or higher.
Tommid3807da2020-05-22 17:36:36 +0200136 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
Artem Titovdcd7fc72021-08-09 13:02:57 +0200145 // known thread (e.g. see `initialized_`). Those probably do not need
Tommid3807da2020-05-22 17:36:36 +0200146 // 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
Markus Handell06a2bf02021-07-22 15:09:39 +0200171#endif // MODULES_VIDEO_CODING_NACK_REQUESTER_H_