1 // Copyright 2013 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/rtcp_receiver.h"
7 #include "base/logging.h"
8 #include "media/cast/rtcp/rtcp_utility.h"
9 #include "media/cast/transport/cast_transport_defines.h"
13 // A receiver frame event is identified by frame RTP timestamp, event timestamp
15 // A receiver packet event is identified by all of the above plus packet id.
16 // The key format is as follows:
18 // bits 0-11: zeroes (unused).
19 // bits 12-15: event type ID.
20 // bits 16-31: packet ID if packet event, 0 otherwise.
21 // bits 32-63: RTP timestamp.
23 // bits 0-63: event TimeTicks internal value.
24 std::pair
<uint64
, uint64
> GetReceiverEventKey(
25 uint32 frame_rtp_timestamp
, const base::TimeTicks
& event_timestamp
,
26 uint8 event_type
, uint16 packet_id_or_zero
) {
27 uint64 value1
= event_type
;
29 value1
|= packet_id_or_zero
;
31 value1
|= frame_rtp_timestamp
;
32 return std::make_pair(
33 value1
, static_cast<uint64
>(event_timestamp
.ToInternalValue()));
41 RtcpReceiver::RtcpReceiver(scoped_refptr
<CastEnvironment
> cast_environment
,
42 RtcpSenderFeedback
* sender_feedback
,
43 RtcpReceiverFeedback
* receiver_feedback
,
44 RtcpRttFeedback
* rtt_feedback
,
48 sender_feedback_(sender_feedback
),
49 receiver_feedback_(receiver_feedback
),
50 rtt_feedback_(rtt_feedback
),
51 cast_environment_(cast_environment
),
52 receiver_event_history_size_(0) {}
54 RtcpReceiver::~RtcpReceiver() {}
56 void RtcpReceiver::SetRemoteSSRC(uint32 ssrc
) { remote_ssrc_
= ssrc
; }
58 void RtcpReceiver::SetCastReceiverEventHistorySize(size_t size
) {
59 receiver_event_history_size_
= size
;
62 void RtcpReceiver::IncomingRtcpPacket(RtcpParser
* rtcp_parser
) {
63 RtcpFieldTypes field_type
= rtcp_parser
->Begin();
64 while (field_type
!= kRtcpNotValidCode
) {
65 // Each "case" is responsible for iterate the parser to the next top
69 HandleSenderReport(rtcp_parser
);
72 HandleReceiverReport(rtcp_parser
);
75 HandleSDES(rtcp_parser
);
78 HandleBYE(rtcp_parser
);
81 HandleXr(rtcp_parser
);
83 case kRtcpGenericRtpFeedbackNackCode
:
84 HandleNACK(rtcp_parser
);
86 case kRtcpGenericRtpFeedbackSrReqCode
:
87 HandleSendReportRequest(rtcp_parser
);
89 case kRtcpPayloadSpecificPliCode
:
90 HandlePLI(rtcp_parser
);
92 case kRtcpPayloadSpecificRpsiCode
:
93 HandleRpsi(rtcp_parser
);
95 case kRtcpPayloadSpecificFirCode
:
96 HandleFIR(rtcp_parser
);
98 case kRtcpPayloadSpecificAppCode
:
99 HandlePayloadSpecificApp(rtcp_parser
);
101 case kRtcpApplicationSpecificCastReceiverLogCode
:
102 HandleApplicationSpecificCastReceiverLog(rtcp_parser
);
104 case kRtcpPayloadSpecificRembCode
:
105 case kRtcpPayloadSpecificRembItemCode
:
106 case kRtcpPayloadSpecificCastCode
:
107 case kRtcpPayloadSpecificCastNackItemCode
:
108 case kRtcpApplicationSpecificCastReceiverLogFrameCode
:
109 case kRtcpApplicationSpecificCastReceiverLogEventCode
:
110 case kRtcpNotValidCode
:
111 case kRtcpReportBlockItemCode
:
112 case kRtcpSdesChunkCode
:
113 case kRtcpGenericRtpFeedbackNackItemCode
:
114 case kRtcpPayloadSpecificFirItemCode
:
115 case kRtcpXrRrtrCode
:
116 case kRtcpXrDlrrCode
:
117 case kRtcpXrUnknownItemCode
:
118 rtcp_parser
->Iterate();
119 NOTREACHED() << "Invalid state";
122 field_type
= rtcp_parser
->FieldType();
126 void RtcpReceiver::HandleSenderReport(RtcpParser
* rtcp_parser
) {
127 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
128 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
130 DCHECK(rtcp_field_type
== kRtcpSrCode
) << "Invalid state";
132 // Synchronization source identifier for the originator of this SR packet.
133 uint32 remote_ssrc
= rtcp_field
.sender_report
.sender_ssrc
;
135 VLOG(2) << "Cast RTCP received SR from SSRC " << remote_ssrc
;
137 if (remote_ssrc_
== remote_ssrc
) {
138 transport::RtcpSenderInfo remote_sender_info
;
139 remote_sender_info
.ntp_seconds
=
140 rtcp_field
.sender_report
.ntp_most_significant
;
141 remote_sender_info
.ntp_fraction
=
142 rtcp_field
.sender_report
.ntp_least_significant
;
143 remote_sender_info
.rtp_timestamp
= rtcp_field
.sender_report
.rtp_timestamp
;
144 remote_sender_info
.send_packet_count
=
145 rtcp_field
.sender_report
.sender_packet_count
;
146 remote_sender_info
.send_octet_count
=
147 rtcp_field
.sender_report
.sender_octet_count
;
148 if (receiver_feedback_
) {
149 receiver_feedback_
->OnReceivedSenderReport(remote_sender_info
);
152 rtcp_field_type
= rtcp_parser
->Iterate();
153 while (rtcp_field_type
== kRtcpReportBlockItemCode
) {
154 HandleReportBlock(&rtcp_field
, remote_ssrc
);
155 rtcp_field_type
= rtcp_parser
->Iterate();
159 void RtcpReceiver::HandleReceiverReport(RtcpParser
* rtcp_parser
) {
160 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
161 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
163 DCHECK(rtcp_field_type
== kRtcpRrCode
) << "Invalid state";
165 uint32 remote_ssrc
= rtcp_field
.receiver_report
.sender_ssrc
;
167 VLOG(2) << "Cast RTCP received RR from SSRC " << remote_ssrc
;
169 rtcp_field_type
= rtcp_parser
->Iterate();
170 while (rtcp_field_type
== kRtcpReportBlockItemCode
) {
171 HandleReportBlock(&rtcp_field
, remote_ssrc
);
172 rtcp_field_type
= rtcp_parser
->Iterate();
176 void RtcpReceiver::HandleReportBlock(const RtcpField
* rtcp_field
,
177 uint32 remote_ssrc
) {
178 // This will be called once per report block in the Rtcp packet.
179 // We filter out all report blocks that are not for us.
180 // Each packet has max 31 RR blocks.
182 // We can calculate RTT if we send a send report and get a report block back.
184 // |rtcp_field.ReportBlockItem.ssrc| is the ssrc identifier of the source to
185 // which the information in this reception report block pertains.
187 const RtcpFieldReportBlockItem
& rb
= rtcp_field
->report_block_item
;
189 // Filter out all report blocks that are not for us.
190 if (rb
.ssrc
!= ssrc_
) {
191 // This block is not for us ignore it.
194 VLOG(2) << "Cast RTCP received RB from SSRC " << remote_ssrc
;
196 transport::RtcpReportBlock report_block
;
197 report_block
.remote_ssrc
= remote_ssrc
;
198 report_block
.media_ssrc
= rb
.ssrc
;
199 report_block
.fraction_lost
= rb
.fraction_lost
;
200 report_block
.cumulative_lost
= rb
.cumulative_number_of_packets_lost
;
201 report_block
.extended_high_sequence_number
=
202 rb
.extended_highest_sequence_number
;
203 report_block
.jitter
= rb
.jitter
;
204 report_block
.last_sr
= rb
.last_sender_report
;
205 report_block
.delay_since_last_sr
= rb
.delay_last_sender_report
;
208 rtt_feedback_
->OnReceivedDelaySinceLastReport(
209 rb
.ssrc
, rb
.last_sender_report
, rb
.delay_last_sender_report
);
213 void RtcpReceiver::HandleSDES(RtcpParser
* rtcp_parser
) {
214 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
215 while (field_type
== kRtcpSdesChunkCode
) {
216 HandleSDESChunk(rtcp_parser
);
217 field_type
= rtcp_parser
->Iterate();
221 void RtcpReceiver::HandleSDESChunk(RtcpParser
* rtcp_parser
) {
222 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
223 VLOG(2) << "Cast RTCP received SDES with cname " << rtcp_field
.c_name
.name
;
226 void RtcpReceiver::HandleXr(RtcpParser
* rtcp_parser
) {
227 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
228 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
230 DCHECK(rtcp_field_type
== kRtcpXrCode
) << "Invalid state";
232 uint32 remote_ssrc
= rtcp_field
.extended_report
.sender_ssrc
;
233 rtcp_field_type
= rtcp_parser
->Iterate();
235 while (rtcp_field_type
== kRtcpXrDlrrCode
||
236 rtcp_field_type
== kRtcpXrRrtrCode
||
237 rtcp_field_type
== kRtcpXrUnknownItemCode
) {
238 if (rtcp_field_type
== kRtcpXrRrtrCode
) {
239 HandleRrtr(rtcp_parser
, remote_ssrc
);
240 } else if (rtcp_field_type
== kRtcpXrDlrrCode
) {
241 HandleDlrr(rtcp_parser
);
243 rtcp_field_type
= rtcp_parser
->Iterate();
247 void RtcpReceiver::HandleRrtr(RtcpParser
* rtcp_parser
, uint32 remote_ssrc
) {
248 if (remote_ssrc_
!= remote_ssrc
) {
252 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
253 RtcpReceiverReferenceTimeReport remote_time_report
;
254 remote_time_report
.remote_ssrc
= remote_ssrc
;
255 remote_time_report
.ntp_seconds
= rtcp_field
.rrtr
.ntp_most_significant
;
256 remote_time_report
.ntp_fraction
= rtcp_field
.rrtr
.ntp_least_significant
;
258 if (receiver_feedback_
) {
259 receiver_feedback_
->OnReceiverReferenceTimeReport(remote_time_report
);
263 void RtcpReceiver::HandleDlrr(RtcpParser
* rtcp_parser
) {
264 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
265 if (remote_ssrc_
!= rtcp_field
.dlrr
.receivers_ssrc
) {
270 rtt_feedback_
->OnReceivedDelaySinceLastReport(
271 rtcp_field
.dlrr
.receivers_ssrc
,
272 rtcp_field
.dlrr
.last_receiver_report
,
273 rtcp_field
.dlrr
.delay_last_receiver_report
);
277 void RtcpReceiver::HandleNACK(RtcpParser
* rtcp_parser
) {
278 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
279 if (ssrc_
!= rtcp_field
.nack
.media_ssrc
) {
280 RtcpFieldTypes field_type
;
281 // Message not to us. Iterate until we have passed this message.
283 field_type
= rtcp_parser
->Iterate();
284 } while (field_type
== kRtcpGenericRtpFeedbackNackItemCode
);
287 std::list
<uint16
> nackSequenceNumbers
;
289 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
290 while (field_type
== kRtcpGenericRtpFeedbackNackItemCode
) {
291 HandleNACKItem(&rtcp_field
, &nackSequenceNumbers
);
292 field_type
= rtcp_parser
->Iterate();
296 void RtcpReceiver::HandleNACKItem(const RtcpField
* rtcp_field
,
297 std::list
<uint16
>* nack_sequence_numbers
) {
298 nack_sequence_numbers
->push_back(rtcp_field
->nack_item
.packet_id
);
300 uint16 bitmask
= rtcp_field
->nack_item
.bitmask
;
302 for (int i
= 1; i
<= 16; ++i
) {
304 nack_sequence_numbers
->push_back(rtcp_field
->nack_item
.packet_id
+ i
);
306 bitmask
= bitmask
>> 1;
311 void RtcpReceiver::HandleBYE(RtcpParser
* rtcp_parser
) {
312 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
313 uint32 remote_ssrc
= rtcp_field
.bye
.sender_ssrc
;
314 if (remote_ssrc_
== remote_ssrc
) {
315 VLOG(2) << "Cast RTCP received BYE from SSRC " << remote_ssrc
;
317 rtcp_parser
->Iterate();
320 void RtcpReceiver::HandlePLI(RtcpParser
* rtcp_parser
) {
321 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
322 if (ssrc_
== rtcp_field
.pli
.media_ssrc
) {
323 // Received a signal that we need to send a new key frame.
324 VLOG(2) << "Cast RTCP received PLI on our SSRC " << ssrc_
;
326 rtcp_parser
->Iterate();
329 void RtcpReceiver::HandleSendReportRequest(RtcpParser
* rtcp_parser
) {
330 if (receiver_feedback_
) {
331 receiver_feedback_
->OnReceivedSendReportRequest();
333 rtcp_parser
->Iterate();
336 void RtcpReceiver::HandleRpsi(RtcpParser
* rtcp_parser
) {
337 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
338 if (rtcp_parser
->Iterate() != kRtcpPayloadSpecificRpsiCode
) {
341 if (rtcp_field
.rpsi
.number_of_valid_bits
% 8 != 0) {
345 uint64 rpsi_picture_id
= 0;
347 // Convert native_bit_string to rpsi_picture_id
348 uint8 bytes
= rtcp_field
.rpsi
.number_of_valid_bits
/ 8;
349 for (uint8 n
= 0; n
< (bytes
- 1); ++n
) {
350 rpsi_picture_id
+= (rtcp_field
.rpsi
.native_bit_string
[n
] & 0x7f);
351 rpsi_picture_id
<<= 7; // Prepare next.
353 rpsi_picture_id
+= (rtcp_field
.rpsi
.native_bit_string
[bytes
- 1] & 0x7f);
355 VLOG(2) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id
;
358 void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser
* rtcp_parser
) {
359 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
360 uint32 remote_ssrc
= rtcp_field
.application_specific
.sender_ssrc
;
361 if (remote_ssrc_
!= remote_ssrc
) {
362 // Message not to us. Iterate until we have passed this message.
363 RtcpFieldTypes field_type
;
365 field_type
= rtcp_parser
->Iterate();
366 } while (field_type
== kRtcpPayloadSpecificRembCode
||
367 field_type
== kRtcpPayloadSpecificRembItemCode
||
368 field_type
== kRtcpPayloadSpecificCastCode
||
369 field_type
== kRtcpPayloadSpecificCastNackItemCode
);
373 RtcpFieldTypes packet_type
= rtcp_parser
->Iterate();
374 switch (packet_type
) {
375 case kRtcpPayloadSpecificRembCode
:
376 packet_type
= rtcp_parser
->Iterate();
377 if (packet_type
== kRtcpPayloadSpecificRembItemCode
) {
378 HandlePayloadSpecificRembItem(rtcp_parser
);
379 rtcp_parser
->Iterate();
382 case kRtcpPayloadSpecificCastCode
:
383 packet_type
= rtcp_parser
->Iterate();
384 if (packet_type
== kRtcpPayloadSpecificCastCode
) {
385 HandlePayloadSpecificCastItem(rtcp_parser
);
393 void RtcpReceiver::HandlePayloadSpecificRembItem(RtcpParser
* rtcp_parser
) {
394 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
396 for (int i
= 0; i
< rtcp_field
.remb_item
.number_of_ssrcs
; ++i
) {
397 if (rtcp_field
.remb_item
.ssrcs
[i
] == ssrc_
) {
398 // Found matching ssrc.
399 VLOG(2) << "Cast RTCP received REMB with received_bitrate "
400 << rtcp_field
.remb_item
.bitrate
;
406 void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
407 RtcpParser
* rtcp_parser
) {
408 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
410 uint32 remote_ssrc
= rtcp_field
.cast_receiver_log
.sender_ssrc
;
411 if (remote_ssrc_
!= remote_ssrc
) {
412 // Message not to us. Iterate until we have passed this message.
413 RtcpFieldTypes field_type
;
415 field_type
= rtcp_parser
->Iterate();
416 } while (field_type
== kRtcpApplicationSpecificCastReceiverLogFrameCode
||
417 field_type
== kRtcpApplicationSpecificCastReceiverLogEventCode
);
420 RtcpReceiverLogMessage receiver_log
;
421 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
422 while (field_type
== kRtcpApplicationSpecificCastReceiverLogFrameCode
) {
423 RtcpReceiverFrameLogMessage
frame_log(
424 rtcp_field
.cast_receiver_log
.rtp_timestamp
);
426 field_type
= rtcp_parser
->Iterate();
427 while (field_type
== kRtcpApplicationSpecificCastReceiverLogEventCode
) {
428 HandleApplicationSpecificCastReceiverEventLog(
429 rtcp_field
.cast_receiver_log
.rtp_timestamp
,
431 &frame_log
.event_log_messages_
);
432 field_type
= rtcp_parser
->Iterate();
435 if (!frame_log
.event_log_messages_
.empty())
436 receiver_log
.push_back(frame_log
);
439 if (receiver_feedback_
&& !receiver_log
.empty()) {
440 receiver_feedback_
->OnReceivedReceiverLog(receiver_log
);
444 void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
445 uint32 frame_rtp_timestamp
,
446 RtcpParser
* rtcp_parser
,
447 RtcpReceiverEventLogMessages
* event_log_messages
) {
448 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
450 const uint8 event
= rtcp_field
.cast_receiver_log
.event
;
451 const CastLoggingEvent event_type
= TranslateToLogEventFromWireFormat(event
);
452 uint16 packet_id
= event_type
== PACKET_RECEIVED
?
453 rtcp_field
.cast_receiver_log
.delay_delta_or_packet_id
.packet_id
: 0;
454 const base::TimeTicks event_timestamp
=
456 base::TimeDelta::FromMilliseconds(
457 rtcp_field
.cast_receiver_log
.event_timestamp_base
+
458 rtcp_field
.cast_receiver_log
.event_timestamp_delta
);
460 // The following code checks to see if we have already seen this event.
461 // The algorithm works by maintaining a sliding window of events. We have
462 // a queue and a set of events. We enqueue every new event and insert it
463 // into the set. When the queue becomes too big we remove the oldest event
464 // from both the queue and the set.
465 ReceiverEventKey key
=
467 frame_rtp_timestamp
, event_timestamp
, event
, packet_id
);
468 if (receiver_event_key_set_
.find(key
) != receiver_event_key_set_
.end()) {
471 receiver_event_key_set_
.insert(key
);
472 receiver_event_key_queue_
.push(key
);
474 if (receiver_event_key_queue_
.size() > receiver_event_history_size_
) {
475 const ReceiverEventKey oldest_key
= receiver_event_key_queue_
.front();
476 receiver_event_key_queue_
.pop();
477 receiver_event_key_set_
.erase(oldest_key
);
481 RtcpReceiverEventLogMessage event_log
;
482 event_log
.type
= event_type
;
483 event_log
.event_timestamp
= event_timestamp
;
484 event_log
.delay_delta
= base::TimeDelta::FromMilliseconds(
485 rtcp_field
.cast_receiver_log
.delay_delta_or_packet_id
.delay_delta
);
486 event_log
.packet_id
=
487 rtcp_field
.cast_receiver_log
.delay_delta_or_packet_id
.packet_id
;
488 event_log_messages
->push_back(event_log
);
491 void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser
* rtcp_parser
) {
492 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
493 RtcpCastMessage
cast_message(remote_ssrc_
);
494 cast_message
.ack_frame_id_
= ack_frame_id_wrap_helper_
.MapTo32bitsFrameId(
495 rtcp_field
.cast_item
.last_frame_id
);
496 cast_message
.target_delay_ms_
= rtcp_field
.cast_item
.target_delay_ms
;
498 RtcpFieldTypes packet_type
= rtcp_parser
->Iterate();
499 while (packet_type
== kRtcpPayloadSpecificCastNackItemCode
) {
500 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
501 HandlePayloadSpecificCastNackItem(
502 &rtcp_field
, &cast_message
.missing_frames_and_packets_
);
503 packet_type
= rtcp_parser
->Iterate();
505 if (sender_feedback_
) {
506 sender_feedback_
->OnReceivedCastFeedback(cast_message
);
510 void RtcpReceiver::HandlePayloadSpecificCastNackItem(
511 const RtcpField
* rtcp_field
,
512 MissingFramesAndPacketsMap
* missing_frames_and_packets
) {
514 MissingFramesAndPacketsMap::iterator frame_it
=
515 missing_frames_and_packets
->find(rtcp_field
->cast_nack_item
.frame_id
);
517 if (frame_it
== missing_frames_and_packets
->end()) {
518 // First missing packet in a frame.
519 PacketIdSet empty_set
;
520 std::pair
<MissingFramesAndPacketsMap::iterator
, bool> ret
=
521 missing_frames_and_packets
->insert(std::pair
<uint8
, PacketIdSet
>(
522 rtcp_field
->cast_nack_item
.frame_id
, empty_set
));
523 frame_it
= ret
.first
;
524 DCHECK(frame_it
!= missing_frames_and_packets
->end()) << "Invalid state";
526 uint16 packet_id
= rtcp_field
->cast_nack_item
.packet_id
;
527 frame_it
->second
.insert(packet_id
);
529 if (packet_id
== kRtcpCastAllPacketsLost
) {
530 // Special case all packets in a frame is missing.
533 uint8 bitmask
= rtcp_field
->cast_nack_item
.bitmask
;
536 for (int i
= 1; i
<= 8; ++i
) {
538 frame_it
->second
.insert(packet_id
+ i
);
540 bitmask
= bitmask
>> 1;
545 void RtcpReceiver::HandleFIR(RtcpParser
* rtcp_parser
) {
546 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
548 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
549 while (field_type
== kRtcpPayloadSpecificFirItemCode
) {
550 HandleFIRItem(&rtcp_field
);
551 field_type
= rtcp_parser
->Iterate();
555 void RtcpReceiver::HandleFIRItem(const RtcpField
* rtcp_field
) {
556 // Is it our sender that is requested to generate a new keyframe.
557 if (ssrc_
!= rtcp_field
->fir_item
.ssrc
)
560 VLOG(2) << "Cast RTCP received FIR on our SSRC " << ssrc_
;