rtc_event_processor.h (6503B)
1 /* 2 * Copyright (c) 2018 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 LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_ 12 #define LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_ 13 14 #include <stdint.h> 15 16 #include <functional> 17 #include <memory> 18 #include <optional> 19 #include <type_traits> 20 #include <vector> 21 22 #include "logging/rtc_event_log/rtc_event_log_parser.h" 23 #include "logging/rtc_event_log/rtc_event_processor_order.h" 24 #include "rtc_base/checks.h" 25 26 namespace webrtc { 27 28 // This file contains helper class used to process the elements of two or more 29 // sorted lists in timestamp order. The effect is the same as doing a merge step 30 // in the merge-sort algorithm but without copying the elements or modifying the 31 // lists. 32 33 namespace event_processor_impl { 34 // Interface to allow "merging" lists of different types. ProcessNext() 35 // processes the next unprocessed element in the list. IsEmpty() checks if all 36 // elements have been processed. GetNextTime returns the timestamp of the next 37 // unprocessed element. 38 class ProcessableEventListInterface { 39 public: 40 virtual ~ProcessableEventListInterface() = default; 41 virtual void ProcessNext() = 0; 42 virtual bool IsEmpty() const = 0; 43 virtual int64_t GetNextTime() const = 0; 44 virtual int GetTypeOrder() const = 0; 45 virtual std::optional<uint16_t> GetTransportSeqNum() const = 0; 46 virtual int GetInsertionOrder() const = 0; 47 }; 48 49 // ProcessableEventList encapsulates a list of events and a function that will 50 // be applied to each element of the list. 51 template <typename Iterator, typename T> 52 class ProcessableEventList : public ProcessableEventListInterface { 53 public: 54 ProcessableEventList(Iterator begin, 55 Iterator end, 56 std::function<void(const T&)> f, 57 int type_order, 58 std::function<std::optional<uint16_t>(const T&)> 59 transport_seq_num_accessor, 60 int insertion_order) 61 : begin_(begin), 62 end_(end), 63 f_(f), 64 type_order_(type_order), 65 transport_seq_num_accessor_(transport_seq_num_accessor), 66 insertion_order_(insertion_order) {} 67 68 void ProcessNext() override { 69 RTC_DCHECK(!IsEmpty()); 70 f_(*begin_); 71 ++begin_; 72 } 73 74 bool IsEmpty() const override { return begin_ == end_; } 75 76 int64_t GetNextTime() const override { 77 RTC_DCHECK(!IsEmpty()); 78 return begin_->log_time_us(); 79 } 80 81 int GetTypeOrder() const override { return type_order_; } 82 83 std::optional<uint16_t> GetTransportSeqNum() const override { 84 RTC_DCHECK(!IsEmpty()); 85 return transport_seq_num_accessor_(*begin_); 86 } 87 88 int GetInsertionOrder() const override { return insertion_order_; } 89 90 private: 91 Iterator begin_; 92 Iterator end_; 93 std::function<void(const T&)> f_; 94 int type_order_; 95 std::function<std::optional<uint16_t>(const T&)> transport_seq_num_accessor_; 96 int insertion_order_; 97 }; 98 99 } // namespace event_processor_impl 100 101 // Helper class used to "merge" two or more lists of ordered RtcEventLog events 102 // so that they can be treated as a single ordered list. Since the individual 103 // lists may have different types, we need to access the lists via pointers to 104 // the common base class. 105 // 106 // Usage example: 107 // ParsedRtcEventLogNew log; 108 // auto incoming_handler = [] (LoggedRtcpPacketIncoming elem) { ... }; 109 // auto outgoing_handler = [] (LoggedRtcpPacketOutgoing elem) { ... }; 110 // 111 // RtcEventProcessor processor; 112 // processor.AddEvents(log.incoming_rtcp_packets(), 113 // incoming_handler); 114 // processor.AddEvents(log.outgoing_rtcp_packets(), 115 // outgoing_handler); 116 // processor.ProcessEventsInOrder(); 117 class RtcEventProcessor { 118 public: 119 RtcEventProcessor(); 120 ~RtcEventProcessor(); 121 // The elements of each list is processed in the index order. To process all 122 // elements in all lists in timestamp order, each list needs to be sorted in 123 // timestamp order prior to insertion. 124 // N.B. `iterable` is not owned by RtcEventProcessor. The caller must ensure 125 // that the iterable outlives RtcEventProcessor and it must not be modified 126 // until processing has finished. 127 template <typename Iterable> 128 void AddEvents( 129 const Iterable& iterable, 130 std::function<void(const typename Iterable::value_type&)> handler) { 131 using ValueType = 132 typename std::remove_const<typename Iterable::value_type>::type; 133 AddEvents(iterable, handler, TieBreaker<ValueType>::type_order, 134 TieBreaker<ValueType>::transport_seq_num_accessor, 135 num_insertions_); 136 } 137 138 template <typename Iterable> 139 void AddEvents( 140 const Iterable& iterable, 141 std::function<void(const typename Iterable::value_type&)> handler, 142 PacketDirection direction) { 143 using ValueType = 144 typename std::remove_const<typename Iterable::value_type>::type; 145 AddEvents(iterable, handler, TieBreaker<ValueType>::type_order(direction), 146 TieBreaker<ValueType>::transport_seq_num_accessor, 147 num_insertions_); 148 } 149 150 template <typename Iterable> 151 void AddEvents( 152 const Iterable& iterable, 153 std::function<void(const typename Iterable::value_type&)> handler, 154 int type_order, 155 std::function<std::optional<uint16_t>( 156 const typename Iterable::value_type&)> transport_seq_num_accessor, 157 int insertion_order) { 158 if (iterable.begin() == iterable.end()) 159 return; 160 num_insertions_++; 161 event_lists_.push_back( 162 std::make_unique<event_processor_impl::ProcessableEventList< 163 typename Iterable::const_iterator, typename Iterable::value_type>>( 164 iterable.begin(), iterable.end(), handler, type_order, 165 transport_seq_num_accessor, insertion_order)); 166 } 167 168 void ProcessEventsInOrder(); 169 170 private: 171 using ListPtrType = 172 std::unique_ptr<event_processor_impl::ProcessableEventListInterface>; 173 // Comparison function to make `event_lists_` into a min heap. 174 static bool Cmp(const ListPtrType& a, const ListPtrType& b); 175 176 std::vector<ListPtrType> event_lists_; 177 int num_insertions_ = 0; 178 }; 179 180 } // namespace webrtc 181 182 #endif // LOGGING_RTC_EVENT_LOG_RTC_EVENT_PROCESSOR_H_