| /* |
| * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef MODULES_RTP_RTCP_SOURCE_SOURCE_TRACKER_H_ |
| #define MODULES_RTP_RTCP_SOURCE_SOURCE_TRACKER_H_ |
| |
| #include <cstdint> |
| #include <list> |
| #include <unordered_map> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/types/optional.h" |
| #include "api/rtp_packet_infos.h" |
| #include "api/task_queue/pending_task_safety_flag.h" |
| #include "api/task_queue/task_queue_base.h" |
| #include "api/transport/rtp/rtp_source.h" |
| #include "api/units/time_delta.h" |
| #include "api/units/timestamp.h" |
| #include "rtc_base/time_utils.h" |
| #include "system_wrappers/include/clock.h" |
| |
| namespace webrtc { |
| |
| // |
| // Tracker for `RTCRtpContributingSource` and `RTCRtpSynchronizationSource`: |
| // - https://w3c.github.io/webrtc-pc/#dom-rtcrtpcontributingsource |
| // - https://w3c.github.io/webrtc-pc/#dom-rtcrtpsynchronizationsource |
| // |
| class SourceTracker { |
| public: |
| // Amount of time before the entry associated with an update is removed. See: |
| // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources |
| static constexpr TimeDelta kTimeout = TimeDelta::Seconds(10); |
| |
| explicit SourceTracker(Clock* clock); |
| |
| SourceTracker(const SourceTracker& other) = delete; |
| SourceTracker(SourceTracker&& other) = delete; |
| SourceTracker& operator=(const SourceTracker& other) = delete; |
| SourceTracker& operator=(SourceTracker&& other) = delete; |
| |
| // Updates the source entries when a frame is delivered to the |
| // RTCRtpReceiver's MediaStreamTrack. |
| void OnFrameDelivered(RtpPacketInfos packet_infos); |
| |
| // Returns an `RtpSource` for each unique SSRC and CSRC identifier updated in |
| // the last `kTimeoutMs` milliseconds. Entries appear in reverse chronological |
| // order (i.e. with the most recently updated entries appearing first). |
| std::vector<RtpSource> GetSources() const; |
| |
| private: |
| struct SourceKey { |
| SourceKey(RtpSourceType source_type, uint32_t source) |
| : source_type(source_type), source(source) {} |
| |
| // Type of `source`. |
| RtpSourceType source_type; |
| |
| // CSRC or SSRC identifier of the contributing or synchronization source. |
| uint32_t source; |
| }; |
| |
| struct SourceKeyComparator { |
| bool operator()(const SourceKey& lhs, const SourceKey& rhs) const { |
| return (lhs.source_type == rhs.source_type) && (lhs.source == rhs.source); |
| } |
| }; |
| |
| struct SourceKeyHasher { |
| size_t operator()(const SourceKey& value) const { |
| return static_cast<size_t>(value.source_type) + |
| static_cast<size_t>(value.source) * 11076425802534262905ULL; |
| } |
| }; |
| |
| struct SourceEntry { |
| // Timestamp indicating the most recent time a frame from an RTP packet, |
| // originating from this source, was delivered to the RTCRtpReceiver's |
| // MediaStreamTrack. Its reference clock is the outer class's `clock_`. |
| Timestamp timestamp = Timestamp::MinusInfinity(); |
| |
| // Audio level from an RFC 6464 or RFC 6465 header extension received with |
| // the most recent packet used to assemble the frame associated with |
| // `timestamp`. May be absent. Only relevant for audio receivers. See the |
| // specs for `RTCRtpContributingSource` for more info. |
| absl::optional<uint8_t> audio_level; |
| |
| // Absolute capture time header extension received or interpolated from the |
| // most recent packet used to assemble the frame. For more info see |
| // https://webrtc.org/experiments/rtp-hdrext/abs-capture-time/ |
| absl::optional<AbsoluteCaptureTime> absolute_capture_time; |
| |
| // Clock offset between the local clock and the capturer's clock. |
| // Do not confuse with `AbsoluteCaptureTime::estimated_capture_clock_offset` |
| // which instead represents the clock offset between a remote sender and the |
| // capturer. The following holds: |
| // Capture's NTP Clock = Local NTP Clock + Local-Capture Clock Offset |
| absl::optional<TimeDelta> local_capture_clock_offset; |
| |
| // RTP timestamp of the most recent packet used to assemble the frame |
| // associated with `timestamp`. |
| uint32_t rtp_timestamp = 0; |
| }; |
| |
| using SourceList = std::list<std::pair<const SourceKey, SourceEntry>>; |
| using SourceMap = std::unordered_map<SourceKey, |
| SourceList::iterator, |
| SourceKeyHasher, |
| SourceKeyComparator>; |
| |
| void OnFrameDeliveredInternal(Timestamp now, |
| const RtpPacketInfos& packet_infos) |
| RTC_RUN_ON(worker_thread_); |
| |
| // Updates an entry by creating it (if it didn't previously exist) and moving |
| // it to the front of the list. Returns a reference to the entry. |
| SourceEntry& UpdateEntry(const SourceKey& key) RTC_RUN_ON(worker_thread_); |
| |
| // Removes entries that have timed out. Marked as "const" so that we can do |
| // pruning in getters. |
| void PruneEntries(Timestamp now) const RTC_RUN_ON(worker_thread_); |
| |
| TaskQueueBase* const worker_thread_; |
| Clock* const clock_; |
| |
| // Entries are stored in reverse chronological order (i.e. with the most |
| // recently updated entries appearing first). Mutability is needed for timeout |
| // pruning in const functions. |
| mutable SourceList list_ RTC_GUARDED_BY(worker_thread_); |
| mutable SourceMap map_ RTC_GUARDED_BY(worker_thread_); |
| ScopedTaskSafety worker_safety_; |
| }; |
| |
| } // namespace webrtc |
| |
| #endif // MODULES_RTP_RTCP_SOURCE_SOURCE_TRACKER_H_ |