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/rtcp/receiver_rtcp_event_subscriber.h"
12 ReceiverRtcpEventSubscriber::ReceiverRtcpEventSubscriber(
13 const size_t max_size_to_retain
, Type type
)
14 : max_size_to_retain_(max_size_to_retain
), type_(type
) {
15 DCHECK(max_size_to_retain_
> 0u);
16 DCHECK(type_
== kAudioEventSubscriber
|| type_
== kVideoEventSubscriber
);
19 ReceiverRtcpEventSubscriber::~ReceiverRtcpEventSubscriber() {
20 DCHECK(thread_checker_
.CalledOnValidThread());
23 void ReceiverRtcpEventSubscriber::OnReceiveFrameEvent(
24 const FrameEvent
& frame_event
) {
25 DCHECK(thread_checker_
.CalledOnValidThread());
27 if (ShouldProcessEvent(frame_event
.type
)) {
29 switch (frame_event
.type
) {
30 case kAudioPlayoutDelay
:
31 case kVideoRenderDelay
:
32 rtcp_event
.delay_delta
= frame_event
.delay_delta
;
33 case kAudioFrameDecoded
:
34 case kVideoFrameDecoded
:
35 // TODO(imcheng): This doesn't seem correct because kAudioAckSent and
36 // kVideoAckSent logged as generic events in AudioReceiver /
37 // VideoReceiver. (crbug.com/339590)
40 rtcp_event
.type
= frame_event
.type
;
41 rtcp_event
.timestamp
= frame_event
.timestamp
;
43 std::make_pair(frame_event
.rtp_timestamp
, rtcp_event
));
50 TruncateMapIfNeeded();
52 DCHECK(rtcp_events_
.size() <= max_size_to_retain_
);
55 void ReceiverRtcpEventSubscriber::OnReceivePacketEvent(
56 const PacketEvent
& packet_event
) {
57 DCHECK(thread_checker_
.CalledOnValidThread());
59 if (ShouldProcessEvent(packet_event
.type
)) {
61 if (packet_event
.type
== kAudioPacketReceived
||
62 packet_event
.type
== kVideoPacketReceived
) {
63 rtcp_event
.type
= packet_event
.type
;
64 rtcp_event
.timestamp
= packet_event
.timestamp
;
65 rtcp_event
.packet_id
= packet_event
.packet_id
;
67 std::make_pair(packet_event
.rtp_timestamp
, rtcp_event
));
71 TruncateMapIfNeeded();
73 DCHECK(rtcp_events_
.size() <= max_size_to_retain_
);
76 void ReceiverRtcpEventSubscriber::OnReceiveGenericEvent(
77 const GenericEvent
& generic_event
) {
78 DCHECK(thread_checker_
.CalledOnValidThread());
79 // Do nothing as RTP receiver is not interested in generic events for RTCP.
82 void ReceiverRtcpEventSubscriber::GetReceiverLogMessageAndReset(
83 RtcpReceiverLogMessage
* receiver_log
) {
84 DCHECK(thread_checker_
.CalledOnValidThread());
86 receiver_log
->clear();
88 typedef std::multimap
<RtpTimestamp
, RtcpEvent
> RtcpEventMultiMap
;
89 RtcpEventMultiMap::const_iterator it
= rtcp_events_
.begin();
90 while (it
!= rtcp_events_
.end()) {
91 // On each iteration, process all entries that have the same key (RTP
92 // timestamp) within the multimap, and generate a
93 // RtcpReceiverFrameLogMessage from them.
94 RtpTimestamp rtp_timestamp
= it
->first
;
95 RtcpReceiverFrameLogMessage
frame_log(rtp_timestamp
);
97 RtcpReceiverEventLogMessage event_log_message
;
98 event_log_message
.type
= it
->second
.type
;
99 event_log_message
.event_timestamp
= it
->second
.timestamp
;
100 event_log_message
.delay_delta
= it
->second
.delay_delta
;
101 event_log_message
.packet_id
= it
->second
.packet_id
;
102 frame_log
.event_log_messages_
.push_back(event_log_message
);
104 } while (it
!= rtcp_events_
.end() && it
->first
== rtp_timestamp
);
106 receiver_log
->push_back(frame_log
);
109 rtcp_events_
.clear();
112 void ReceiverRtcpEventSubscriber::TruncateMapIfNeeded() {
113 // If map size has exceeded |max_size_to_retain_|, remove entry with
114 // the smallest RTP timestamp.
115 if (rtcp_events_
.size() > max_size_to_retain_
) {
116 DVLOG(2) << "RTCP event map exceeded size limit; "
117 << "removing oldest entry";
118 // This is fine since we only insert elements one at a time.
119 rtcp_events_
.erase(rtcp_events_
.begin());
123 bool ReceiverRtcpEventSubscriber::ShouldProcessEvent(
124 CastLoggingEvent event_type
) {
125 if (type_
== kAudioEventSubscriber
) {
126 return event_type
== kAudioPlayoutDelay
||
127 event_type
== kAudioFrameDecoded
|| event_type
== kAudioAckSent
||
128 event_type
== kAudioPacketReceived
;
129 } else if (type_
== kVideoEventSubscriber
) {
130 return event_type
== kVideoRenderDelay
||
131 event_type
== kVideoFrameDecoded
|| event_type
== kVideoAckSent
||
132 event_type
== kVideoPacketReceived
;