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.
5 #include "media/cast/net/rtcp/receiver_rtcp_event_subscriber.h"
12 ReceiverRtcpEventSubscriber::ReceiverRtcpEventSubscriber(
13 const size_t max_size_to_retain
, EventMediaType type
)
14 : max_size_to_retain_(
15 max_size_to_retain
* (kResendDelay
* kNumResends
+ 1)),
18 DCHECK(max_size_to_retain_
> 0u);
19 DCHECK(type_
== AUDIO_EVENT
|| type_
== VIDEO_EVENT
);
20 for (size_t i
= 0; i
< kNumResends
; i
++) {
25 ReceiverRtcpEventSubscriber::~ReceiverRtcpEventSubscriber() {
26 DCHECK(thread_checker_
.CalledOnValidThread());
29 void ReceiverRtcpEventSubscriber::OnReceiveFrameEvent(
30 const FrameEvent
& frame_event
) {
31 DCHECK(thread_checker_
.CalledOnValidThread());
33 if (ShouldProcessEvent(frame_event
.type
, frame_event
.media_type
)) {
35 switch (frame_event
.type
) {
37 rtcp_event
.delay_delta
= frame_event
.delay_delta
;
40 rtcp_event
.type
= frame_event
.type
;
41 rtcp_event
.timestamp
= frame_event
.timestamp
;
42 rtcp_events_
.push_back(
43 std::make_pair(frame_event
.rtp_timestamp
, rtcp_event
));
50 TruncateMapIfNeeded();
53 void ReceiverRtcpEventSubscriber::OnReceivePacketEvent(
54 const PacketEvent
& packet_event
) {
55 DCHECK(thread_checker_
.CalledOnValidThread());
57 if (ShouldProcessEvent(packet_event
.type
, packet_event
.media_type
)) {
59 if (packet_event
.type
== PACKET_RECEIVED
) {
60 rtcp_event
.type
= packet_event
.type
;
61 rtcp_event
.timestamp
= packet_event
.timestamp
;
62 rtcp_event
.packet_id
= packet_event
.packet_id
;
63 rtcp_events_
.push_back(
64 std::make_pair(packet_event
.rtp_timestamp
, rtcp_event
));
68 TruncateMapIfNeeded();
71 struct CompareByFirst
{
72 bool operator()(const std::pair
<RtpTimestamp
, RtcpEvent
>& a
,
73 const std::pair
<RtpTimestamp
, RtcpEvent
>& b
) {
74 return a
.first
< b
.first
;
78 void ReceiverRtcpEventSubscriber::GetRtcpEventsWithRedundancy(
79 RtcpEvents
* rtcp_events
) {
80 DCHECK(thread_checker_
.CalledOnValidThread());
83 uint64 event_level
= rtcp_events_
.size() + popped_events_
;
84 event_levels_for_past_frames_
.push_back(event_level
);
86 for (size_t i
= 0; i
< kNumResends
; i
++) {
87 size_t resend_delay
= kResendDelay
* i
;
88 if (event_levels_for_past_frames_
.size() < resend_delay
+ 1)
91 uint64 send_limit
= event_levels_for_past_frames_
[
92 event_levels_for_past_frames_
.size() - 1 - resend_delay
];
94 if (send_ptrs_
[i
] < popped_events_
) {
95 send_ptrs_
[i
] = popped_events_
;
98 while (send_ptrs_
[i
] < send_limit
&&
99 rtcp_events
->size() < kMaxEventsPerRTCP
) {
100 rtcp_events
->push_back(rtcp_events_
[send_ptrs_
[i
] - popped_events_
]);
103 send_limit
= send_ptrs_
[i
];
106 if (event_levels_for_past_frames_
.size() > kResendDelay
* (kNumResends
+ 1)) {
107 while (popped_events_
< event_levels_for_past_frames_
[0]) {
108 rtcp_events_
.pop_front();
111 event_levels_for_past_frames_
.pop_front();
114 std::sort(rtcp_events
->begin(), rtcp_events
->end(), CompareByFirst());
117 void ReceiverRtcpEventSubscriber::TruncateMapIfNeeded() {
118 // If map size has exceeded |max_size_to_retain_|, remove entry with
119 // the smallest RTP timestamp.
120 if (rtcp_events_
.size() > max_size_to_retain_
) {
121 DVLOG(3) << "RTCP event map exceeded size limit; "
122 << "removing oldest entry";
123 // This is fine since we only insert elements one at a time.
124 rtcp_events_
.pop_front();
128 DCHECK(rtcp_events_
.size() <= max_size_to_retain_
);
131 bool ReceiverRtcpEventSubscriber::ShouldProcessEvent(
132 CastLoggingEvent event_type
, EventMediaType event_media_type
) {
133 return type_
== event_media_type
&&
134 (event_type
== FRAME_ACK_SENT
|| event_type
== FRAME_DECODED
||
135 event_type
== FRAME_PLAYOUT
|| event_type
== PACKET_RECEIVED
);