1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/cast/net/rtcp/receiver_rtcp_event_subscriber.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 namespace media {
11 namespace cast {
12
ReceiverRtcpEventSubscriber(const size_t max_size_to_retain,EventMediaType type)13 ReceiverRtcpEventSubscriber::ReceiverRtcpEventSubscriber(
14 const size_t max_size_to_retain, EventMediaType type)
15 : max_size_to_retain_(
16 max_size_to_retain * (kResendDelay * kNumResends + 1)),
17 type_(type),
18 popped_events_(0) {
19 DCHECK(max_size_to_retain_ > 0u);
20 DCHECK(type_ == AUDIO_EVENT || type_ == VIDEO_EVENT);
21 for (size_t i = 0; i < kNumResends; i++) {
22 send_ptrs_[i] = 0;
23 }
24 }
25
~ReceiverRtcpEventSubscriber()26 ReceiverRtcpEventSubscriber::~ReceiverRtcpEventSubscriber() {
27 DCHECK(thread_checker_.CalledOnValidThread());
28 }
29
OnReceiveFrameEvent(const FrameEvent & frame_event)30 void ReceiverRtcpEventSubscriber::OnReceiveFrameEvent(
31 const FrameEvent& frame_event) {
32 DCHECK(thread_checker_.CalledOnValidThread());
33
34 if (ShouldProcessEvent(frame_event.type, frame_event.media_type)) {
35 RtcpEvent rtcp_event;
36 switch (frame_event.type) {
37 case FRAME_PLAYOUT:
38 rtcp_event.delay_delta = frame_event.delay_delta;
39 FALLTHROUGH;
40 case FRAME_ACK_SENT:
41 case FRAME_DECODED:
42 rtcp_event.type = frame_event.type;
43 rtcp_event.timestamp = frame_event.timestamp;
44 rtcp_events_.push_back(
45 std::make_pair(frame_event.rtp_timestamp, rtcp_event));
46 break;
47 default:
48 break;
49 }
50 }
51
52 TruncateMapIfNeeded();
53 }
54
OnReceivePacketEvent(const PacketEvent & packet_event)55 void ReceiverRtcpEventSubscriber::OnReceivePacketEvent(
56 const PacketEvent& packet_event) {
57 DCHECK(thread_checker_.CalledOnValidThread());
58
59 if (ShouldProcessEvent(packet_event.type, packet_event.media_type)) {
60 RtcpEvent rtcp_event;
61 if (packet_event.type == PACKET_RECEIVED) {
62 rtcp_event.type = packet_event.type;
63 rtcp_event.timestamp = packet_event.timestamp;
64 rtcp_event.packet_id = packet_event.packet_id;
65 rtcp_events_.push_back(
66 std::make_pair(packet_event.rtp_timestamp, rtcp_event));
67 }
68 }
69
70 TruncateMapIfNeeded();
71 }
72
73 struct CompareByFirst {
operator ()media::cast::CompareByFirst74 bool operator()(const std::pair<RtpTimeTicks, RtcpEvent>& a,
75 const std::pair<RtpTimeTicks, RtcpEvent>& b) {
76 return a.first < b.first;
77 }
78 };
79
GetRtcpEventsWithRedundancy(RtcpEvents * rtcp_events)80 void ReceiverRtcpEventSubscriber::GetRtcpEventsWithRedundancy(
81 RtcpEvents* rtcp_events) {
82 DCHECK(thread_checker_.CalledOnValidThread());
83 DCHECK(rtcp_events);
84
85 uint64_t event_level = rtcp_events_.size() + popped_events_;
86 event_levels_for_past_frames_.push_back(event_level);
87
88 for (size_t i = 0; i < kNumResends; i++) {
89 size_t resend_delay = kResendDelay * i;
90 if (event_levels_for_past_frames_.size() < resend_delay + 1)
91 break;
92
93 uint64_t send_limit =
94 event_levels_for_past_frames_[event_levels_for_past_frames_.size() - 1 -
95 resend_delay];
96
97 if (send_ptrs_[i] < popped_events_) {
98 send_ptrs_[i] = popped_events_;
99 }
100
101 while (send_ptrs_[i] < send_limit &&
102 rtcp_events->size() < kMaxEventsPerRTCP) {
103 rtcp_events->push_back(rtcp_events_[send_ptrs_[i] - popped_events_]);
104 send_ptrs_[i]++;
105 }
106 send_limit = send_ptrs_[i];
107 }
108
109 if (event_levels_for_past_frames_.size() > kResendDelay * (kNumResends + 1)) {
110 while (popped_events_ < event_levels_for_past_frames_[0]) {
111 rtcp_events_.pop_front();
112 popped_events_++;
113 }
114 event_levels_for_past_frames_.pop_front();
115 }
116
117 std::sort(rtcp_events->begin(), rtcp_events->end(), CompareByFirst());
118 }
119
TruncateMapIfNeeded()120 void ReceiverRtcpEventSubscriber::TruncateMapIfNeeded() {
121 // If map size has exceeded |max_size_to_retain_|, remove entry with
122 // the smallest RTP timestamp.
123 if (rtcp_events_.size() > max_size_to_retain_) {
124 DVLOG(3) << "RTCP event map exceeded size limit; "
125 << "removing oldest entry";
126 // This is fine since we only insert elements one at a time.
127 rtcp_events_.pop_front();
128 popped_events_++;
129 }
130
131 DCHECK(rtcp_events_.size() <= max_size_to_retain_);
132 }
133
ShouldProcessEvent(CastLoggingEvent event_type,EventMediaType event_media_type)134 bool ReceiverRtcpEventSubscriber::ShouldProcessEvent(
135 CastLoggingEvent event_type, EventMediaType event_media_type) {
136 return type_ == event_media_type &&
137 (event_type == FRAME_ACK_SENT || event_type == FRAME_DECODED ||
138 event_type == FRAME_PLAYOUT || event_type == PACKET_RECEIVED);
139 }
140
141 } // namespace cast
142 } // namespace media
143