1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Worker #ifndef MODULES_VIDEO_CODING_NACK_REQUESTER_H_ 12*d9f75844SAndroid Build Coastguard Worker #define MODULES_VIDEO_CODING_NACK_REQUESTER_H_ 13*d9f75844SAndroid Build Coastguard Worker 14*d9f75844SAndroid Build Coastguard Worker #include <stdint.h> 15*d9f75844SAndroid Build Coastguard Worker 16*d9f75844SAndroid Build Coastguard Worker #include <map> 17*d9f75844SAndroid Build Coastguard Worker #include <set> 18*d9f75844SAndroid Build Coastguard Worker #include <vector> 19*d9f75844SAndroid Build Coastguard Worker 20*d9f75844SAndroid Build Coastguard Worker #include "api/field_trials_view.h" 21*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h" 22*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/pending_task_safety_flag.h" 23*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h" 24*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h" 25*d9f75844SAndroid Build Coastguard Worker #include "api/units/timestamp.h" 26*d9f75844SAndroid Build Coastguard Worker #include "modules/include/module_common_types.h" 27*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/histogram.h" 28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/sequence_number_util.h" 29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/task_utils/repeating_task.h" 30*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread_annotations.h" 31*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/clock.h" 32*d9f75844SAndroid Build Coastguard Worker 33*d9f75844SAndroid Build Coastguard Worker namespace webrtc { 34*d9f75844SAndroid Build Coastguard Worker 35*d9f75844SAndroid Build Coastguard Worker class NackRequesterBase { 36*d9f75844SAndroid Build Coastguard Worker public: 37*d9f75844SAndroid Build Coastguard Worker virtual ~NackRequesterBase() = default; 38*d9f75844SAndroid Build Coastguard Worker virtual void ProcessNacks() = 0; 39*d9f75844SAndroid Build Coastguard Worker }; 40*d9f75844SAndroid Build Coastguard Worker 41*d9f75844SAndroid Build Coastguard Worker class NackPeriodicProcessor { 42*d9f75844SAndroid Build Coastguard Worker public: 43*d9f75844SAndroid Build Coastguard Worker static constexpr TimeDelta kUpdateInterval = TimeDelta::Millis(20); 44*d9f75844SAndroid Build Coastguard Worker explicit NackPeriodicProcessor(TimeDelta update_interval = kUpdateInterval); 45*d9f75844SAndroid Build Coastguard Worker ~NackPeriodicProcessor(); 46*d9f75844SAndroid Build Coastguard Worker void RegisterNackModule(NackRequesterBase* module); 47*d9f75844SAndroid Build Coastguard Worker void UnregisterNackModule(NackRequesterBase* module); 48*d9f75844SAndroid Build Coastguard Worker 49*d9f75844SAndroid Build Coastguard Worker private: 50*d9f75844SAndroid Build Coastguard Worker void ProcessNackModules() RTC_RUN_ON(sequence_); 51*d9f75844SAndroid Build Coastguard Worker 52*d9f75844SAndroid Build Coastguard Worker const TimeDelta update_interval_; 53*d9f75844SAndroid Build Coastguard Worker RepeatingTaskHandle repeating_task_ RTC_GUARDED_BY(sequence_); 54*d9f75844SAndroid Build Coastguard Worker std::vector<NackRequesterBase*> modules_ RTC_GUARDED_BY(sequence_); 55*d9f75844SAndroid Build Coastguard Worker RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_; 56*d9f75844SAndroid Build Coastguard Worker }; 57*d9f75844SAndroid Build Coastguard Worker 58*d9f75844SAndroid Build Coastguard Worker class ScopedNackPeriodicProcessorRegistration { 59*d9f75844SAndroid Build Coastguard Worker public: 60*d9f75844SAndroid Build Coastguard Worker ScopedNackPeriodicProcessorRegistration(NackRequesterBase* module, 61*d9f75844SAndroid Build Coastguard Worker NackPeriodicProcessor* processor); 62*d9f75844SAndroid Build Coastguard Worker ~ScopedNackPeriodicProcessorRegistration(); 63*d9f75844SAndroid Build Coastguard Worker 64*d9f75844SAndroid Build Coastguard Worker private: 65*d9f75844SAndroid Build Coastguard Worker NackRequesterBase* const module_; 66*d9f75844SAndroid Build Coastguard Worker NackPeriodicProcessor* const processor_; 67*d9f75844SAndroid Build Coastguard Worker }; 68*d9f75844SAndroid Build Coastguard Worker 69*d9f75844SAndroid Build Coastguard Worker class NackRequester final : public NackRequesterBase { 70*d9f75844SAndroid Build Coastguard Worker public: 71*d9f75844SAndroid Build Coastguard Worker NackRequester(TaskQueueBase* current_queue, 72*d9f75844SAndroid Build Coastguard Worker NackPeriodicProcessor* periodic_processor, 73*d9f75844SAndroid Build Coastguard Worker Clock* clock, 74*d9f75844SAndroid Build Coastguard Worker NackSender* nack_sender, 75*d9f75844SAndroid Build Coastguard Worker KeyFrameRequestSender* keyframe_request_sender, 76*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& field_trials); 77*d9f75844SAndroid Build Coastguard Worker ~NackRequester(); 78*d9f75844SAndroid Build Coastguard Worker 79*d9f75844SAndroid Build Coastguard Worker void ProcessNacks() override; 80*d9f75844SAndroid Build Coastguard Worker 81*d9f75844SAndroid Build Coastguard Worker int OnReceivedPacket(uint16_t seq_num, bool is_keyframe); 82*d9f75844SAndroid Build Coastguard Worker int OnReceivedPacket(uint16_t seq_num, bool is_keyframe, bool is_recovered); 83*d9f75844SAndroid Build Coastguard Worker 84*d9f75844SAndroid Build Coastguard Worker void ClearUpTo(uint16_t seq_num); 85*d9f75844SAndroid Build Coastguard Worker void UpdateRtt(int64_t rtt_ms); 86*d9f75844SAndroid Build Coastguard Worker 87*d9f75844SAndroid Build Coastguard Worker private: 88*d9f75844SAndroid Build Coastguard Worker // Which fields to consider when deciding which packet to nack in 89*d9f75844SAndroid Build Coastguard Worker // GetNackBatch. 90*d9f75844SAndroid Build Coastguard Worker enum NackFilterOptions { kSeqNumOnly, kTimeOnly, kSeqNumAndTime }; 91*d9f75844SAndroid Build Coastguard Worker 92*d9f75844SAndroid Build Coastguard Worker // This class holds the sequence number of the packet that is in the nack list 93*d9f75844SAndroid Build Coastguard Worker // as well as the meta data about when it should be nacked and how many times 94*d9f75844SAndroid Build Coastguard Worker // we have tried to nack this packet. 95*d9f75844SAndroid Build Coastguard Worker struct NackInfo { 96*d9f75844SAndroid Build Coastguard Worker NackInfo(); 97*d9f75844SAndroid Build Coastguard Worker NackInfo(uint16_t seq_num, 98*d9f75844SAndroid Build Coastguard Worker uint16_t send_at_seq_num, 99*d9f75844SAndroid Build Coastguard Worker Timestamp created_at_time); 100*d9f75844SAndroid Build Coastguard Worker 101*d9f75844SAndroid Build Coastguard Worker uint16_t seq_num; 102*d9f75844SAndroid Build Coastguard Worker uint16_t send_at_seq_num; 103*d9f75844SAndroid Build Coastguard Worker Timestamp created_at_time; 104*d9f75844SAndroid Build Coastguard Worker Timestamp sent_at_time; 105*d9f75844SAndroid Build Coastguard Worker int retries; 106*d9f75844SAndroid Build Coastguard Worker }; 107*d9f75844SAndroid Build Coastguard Worker 108*d9f75844SAndroid Build Coastguard Worker void AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end) 109*d9f75844SAndroid Build Coastguard Worker RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); 110*d9f75844SAndroid Build Coastguard Worker 111*d9f75844SAndroid Build Coastguard Worker // Removes packets from the nack list until the next keyframe. Returns true 112*d9f75844SAndroid Build Coastguard Worker // if packets were removed. 113*d9f75844SAndroid Build Coastguard Worker bool RemovePacketsUntilKeyFrame() 114*d9f75844SAndroid Build Coastguard Worker RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); 115*d9f75844SAndroid Build Coastguard Worker std::vector<uint16_t> GetNackBatch(NackFilterOptions options) 116*d9f75844SAndroid Build Coastguard Worker RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); 117*d9f75844SAndroid Build Coastguard Worker 118*d9f75844SAndroid Build Coastguard Worker // Update the reordering distribution. 119*d9f75844SAndroid Build Coastguard Worker void UpdateReorderingStatistics(uint16_t seq_num) 120*d9f75844SAndroid Build Coastguard Worker RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); 121*d9f75844SAndroid Build Coastguard Worker 122*d9f75844SAndroid Build Coastguard Worker // Returns how many packets we have to wait in order to receive the packet 123*d9f75844SAndroid Build Coastguard Worker // with probability `probabilty` or higher. 124*d9f75844SAndroid Build Coastguard Worker int WaitNumberOfPackets(float probability) const 125*d9f75844SAndroid Build Coastguard Worker RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); 126*d9f75844SAndroid Build Coastguard Worker 127*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* const worker_thread_; 128*d9f75844SAndroid Build Coastguard Worker Clock* const clock_; 129*d9f75844SAndroid Build Coastguard Worker NackSender* const nack_sender_; 130*d9f75844SAndroid Build Coastguard Worker KeyFrameRequestSender* const keyframe_request_sender_; 131*d9f75844SAndroid Build Coastguard Worker 132*d9f75844SAndroid Build Coastguard Worker // TODO(philipel): Some of the variables below are consistently used on a 133*d9f75844SAndroid Build Coastguard Worker // known thread (e.g. see `initialized_`). Those probably do not need 134*d9f75844SAndroid Build Coastguard Worker // synchronized access. 135*d9f75844SAndroid Build Coastguard Worker std::map<uint16_t, NackInfo, DescendingSeqNumComp<uint16_t>> nack_list_ 136*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(worker_thread_); 137*d9f75844SAndroid Build Coastguard Worker std::set<uint16_t, DescendingSeqNumComp<uint16_t>> keyframe_list_ 138*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(worker_thread_); 139*d9f75844SAndroid Build Coastguard Worker std::set<uint16_t, DescendingSeqNumComp<uint16_t>> recovered_list_ 140*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(worker_thread_); 141*d9f75844SAndroid Build Coastguard Worker video_coding::Histogram reordering_histogram_ RTC_GUARDED_BY(worker_thread_); 142*d9f75844SAndroid Build Coastguard Worker bool initialized_ RTC_GUARDED_BY(worker_thread_); 143*d9f75844SAndroid Build Coastguard Worker TimeDelta rtt_ RTC_GUARDED_BY(worker_thread_); 144*d9f75844SAndroid Build Coastguard Worker uint16_t newest_seq_num_ RTC_GUARDED_BY(worker_thread_); 145*d9f75844SAndroid Build Coastguard Worker 146*d9f75844SAndroid Build Coastguard Worker // Adds a delay before send nack on packet received. 147*d9f75844SAndroid Build Coastguard Worker const TimeDelta send_nack_delay_; 148*d9f75844SAndroid Build Coastguard Worker 149*d9f75844SAndroid Build Coastguard Worker ScopedNackPeriodicProcessorRegistration processor_registration_; 150*d9f75844SAndroid Build Coastguard Worker 151*d9f75844SAndroid Build Coastguard Worker // Used to signal destruction to potentially pending tasks. 152*d9f75844SAndroid Build Coastguard Worker ScopedTaskSafety task_safety_; 153*d9f75844SAndroid Build Coastguard Worker }; 154*d9f75844SAndroid Build Coastguard Worker 155*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc 156*d9f75844SAndroid Build Coastguard Worker 157*d9f75844SAndroid Build Coastguard Worker #endif // MODULES_VIDEO_CODING_NACK_REQUESTER_H_ 158