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