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 media::cast::CastLoggingEvent
TranslateToLogEventFromWireFormat(uint8 event
) {
16 return media::cast::kAckSent
;
18 return media::cast::kAudioPlayoutDelay
;
20 return media::cast::kAudioFrameDecoded
;
22 return media::cast::kVideoFrameDecoded
;
24 return media::cast::kVideoRenderDelay
;
26 return media::cast::kPacketReceived
;
28 return media::cast::kDuplicatePacketReceived
;
30 // If the sender adds new log messages we will end up here until we add
31 // the new messages in the receiver.
32 VLOG(1) << "Unexpected log message received: " << static_cast<int>(event
);
34 return media::cast::kUnknown
;
38 media::cast::transport::RtcpSenderFrameStatus
39 TranslateToFrameStatusFromWireFormat(uint8 status
) {
42 return media::cast::transport::kRtcpSenderFrameStatusUnknown
;
44 return media::cast::transport::kRtcpSenderFrameStatusDroppedByEncoder
;
46 return media::cast::transport::kRtcpSenderFrameStatusDroppedByFlowControl
;
48 return media::cast::transport::kRtcpSenderFrameStatusSentToNetwork
;
50 // If the sender adds new log messages we will end up here until we add
51 // the new messages in the receiver.
53 VLOG(1) << "Unexpected status received: " << static_cast<int>(status
);
54 return media::cast::transport::kRtcpSenderFrameStatusUnknown
;
63 RtcpReceiver::RtcpReceiver(scoped_refptr
<CastEnvironment
> cast_environment
,
64 RtcpSenderFeedback
* sender_feedback
,
65 RtcpReceiverFeedback
* receiver_feedback
,
66 RtcpRttFeedback
* rtt_feedback
,
70 sender_feedback_(sender_feedback
),
71 receiver_feedback_(receiver_feedback
),
72 rtt_feedback_(rtt_feedback
),
73 cast_environment_(cast_environment
) {}
75 RtcpReceiver::~RtcpReceiver() {}
77 void RtcpReceiver::SetRemoteSSRC(uint32 ssrc
) {
81 void RtcpReceiver::IncomingRtcpPacket(RtcpParser
* rtcp_parser
) {
82 RtcpFieldTypes field_type
= rtcp_parser
->Begin();
83 while (field_type
!= kRtcpNotValidCode
) {
84 // Each "case" is responsible for iterate the parser to the next top
88 HandleSenderReport(rtcp_parser
);
91 HandleReceiverReport(rtcp_parser
);
94 HandleSDES(rtcp_parser
);
97 HandleBYE(rtcp_parser
);
100 HandleXr(rtcp_parser
);
102 case kRtcpGenericRtpFeedbackNackCode
:
103 HandleNACK(rtcp_parser
);
105 case kRtcpGenericRtpFeedbackSrReqCode
:
106 HandleSendReportRequest(rtcp_parser
);
108 case kRtcpPayloadSpecificPliCode
:
109 HandlePLI(rtcp_parser
);
111 case kRtcpPayloadSpecificRpsiCode
:
112 HandleRpsi(rtcp_parser
);
114 case kRtcpPayloadSpecificFirCode
:
115 HandleFIR(rtcp_parser
);
117 case kRtcpPayloadSpecificAppCode
:
118 HandlePayloadSpecificApp(rtcp_parser
);
120 case kRtcpApplicationSpecificCastReceiverLogCode
:
121 HandleApplicationSpecificCastReceiverLog(rtcp_parser
);
123 case kRtcpApplicationSpecificCastSenderLogCode
:
124 HandleApplicationSpecificCastSenderLog(rtcp_parser
);
126 case kRtcpPayloadSpecificRembCode
:
127 case kRtcpPayloadSpecificRembItemCode
:
128 case kRtcpPayloadSpecificCastCode
:
129 case kRtcpPayloadSpecificCastNackItemCode
:
130 case kRtcpApplicationSpecificCastReceiverLogFrameCode
:
131 case kRtcpApplicationSpecificCastReceiverLogEventCode
:
132 case kRtcpNotValidCode
:
133 case kRtcpReportBlockItemCode
:
134 case kRtcpSdesChunkCode
:
135 case kRtcpGenericRtpFeedbackNackItemCode
:
136 case kRtcpPayloadSpecificFirItemCode
:
137 case kRtcpXrRrtrCode
:
138 case kRtcpXrDlrrCode
:
139 case kRtcpXrUnknownItemCode
:
140 rtcp_parser
->Iterate();
141 NOTREACHED() << "Invalid state";
144 field_type
= rtcp_parser
->FieldType();
148 void RtcpReceiver::HandleSenderReport(RtcpParser
* rtcp_parser
) {
149 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
150 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
152 DCHECK(rtcp_field_type
== kRtcpSrCode
) << "Invalid state";
154 // Synchronization source identifier for the originator of this SR packet.
155 uint32 remote_ssrc
= rtcp_field
.sender_report
.sender_ssrc
;
157 VLOG(1) << "Cast RTCP received SR from SSRC " << remote_ssrc
;
159 if (remote_ssrc_
== remote_ssrc
) {
160 transport::RtcpSenderInfo remote_sender_info
;
161 remote_sender_info
.ntp_seconds
=
162 rtcp_field
.sender_report
.ntp_most_significant
;
163 remote_sender_info
.ntp_fraction
=
164 rtcp_field
.sender_report
.ntp_least_significant
;
165 remote_sender_info
.rtp_timestamp
=
166 rtcp_field
.sender_report
.rtp_timestamp
;
167 remote_sender_info
.send_packet_count
=
168 rtcp_field
.sender_report
.sender_packet_count
;
169 remote_sender_info
.send_octet_count
=
170 rtcp_field
.sender_report
.sender_octet_count
;
171 if (receiver_feedback_
) {
172 receiver_feedback_
->OnReceivedSenderReport(remote_sender_info
);
175 rtcp_field_type
= rtcp_parser
->Iterate();
176 while (rtcp_field_type
== kRtcpReportBlockItemCode
) {
177 HandleReportBlock(&rtcp_field
, remote_ssrc
);
178 rtcp_field_type
= rtcp_parser
->Iterate();
182 void RtcpReceiver::HandleReceiverReport(RtcpParser
* rtcp_parser
) {
183 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
184 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
186 DCHECK(rtcp_field_type
== kRtcpRrCode
) << "Invalid state";
188 uint32 remote_ssrc
= rtcp_field
.receiver_report
.sender_ssrc
;
190 VLOG(1) << "Cast RTCP received RR from SSRC " << remote_ssrc
;
192 rtcp_field_type
= rtcp_parser
->Iterate();
193 while (rtcp_field_type
== kRtcpReportBlockItemCode
) {
194 HandleReportBlock(&rtcp_field
, remote_ssrc
);
195 rtcp_field_type
= rtcp_parser
->Iterate();
199 void RtcpReceiver::HandleReportBlock(const RtcpField
* rtcp_field
,
200 uint32 remote_ssrc
) {
201 // This will be called once per report block in the Rtcp packet.
202 // We filter out all report blocks that are not for us.
203 // Each packet has max 31 RR blocks.
205 // We can calculate RTT if we send a send report and get a report block back.
207 // |rtcp_field.ReportBlockItem.ssrc| is the ssrc identifier of the source to
208 // which the information in this reception report block pertains.
210 const RtcpFieldReportBlockItem
& rb
= rtcp_field
->report_block_item
;
212 // Filter out all report blocks that are not for us.
213 if (rb
.ssrc
!= ssrc_
) {
214 // This block is not for us ignore it.
217 VLOG(1) << "Cast RTCP received RB from SSRC " << remote_ssrc
;
218 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
219 cast_environment_
->Logging()->InsertGenericEvent(now
, kPacketLoss
,
221 cast_environment_
->Logging()->InsertGenericEvent(now
, kJitterMs
,
224 transport::RtcpReportBlock report_block
;
225 report_block
.remote_ssrc
= remote_ssrc
;
226 report_block
.media_ssrc
= rb
.ssrc
;
227 report_block
.fraction_lost
= rb
.fraction_lost
;
228 report_block
.cumulative_lost
= rb
.cumulative_number_of_packets_lost
;
229 report_block
.extended_high_sequence_number
=
230 rb
.extended_highest_sequence_number
;
231 report_block
.jitter
= rb
.jitter
;
232 report_block
.last_sr
= rb
.last_sender_report
;
233 report_block
.delay_since_last_sr
= rb
.delay_last_sender_report
;
236 rtt_feedback_
->OnReceivedDelaySinceLastReport(rb
.ssrc
,
237 rb
.last_sender_report
,
238 rb
.delay_last_sender_report
);
242 void RtcpReceiver::HandleSDES(RtcpParser
* rtcp_parser
) {
243 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
244 while (field_type
== kRtcpSdesChunkCode
) {
245 HandleSDESChunk(rtcp_parser
);
246 field_type
= rtcp_parser
->Iterate();
250 void RtcpReceiver::HandleSDESChunk(RtcpParser
* rtcp_parser
) {
251 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
252 VLOG(1) << "Cast RTCP received SDES with cname " << rtcp_field
.c_name
.name
;
255 void RtcpReceiver::HandleXr(RtcpParser
* rtcp_parser
) {
256 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
257 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
259 DCHECK(rtcp_field_type
== kRtcpXrCode
) << "Invalid state";
261 uint32 remote_ssrc
= rtcp_field
.extended_report
.sender_ssrc
;
262 rtcp_field_type
= rtcp_parser
->Iterate();
264 while (rtcp_field_type
== kRtcpXrDlrrCode
||
265 rtcp_field_type
== kRtcpXrRrtrCode
||
266 rtcp_field_type
== kRtcpXrUnknownItemCode
) {
267 if (rtcp_field_type
== kRtcpXrRrtrCode
) {
268 HandleRrtr(rtcp_parser
, remote_ssrc
);
269 } else if (rtcp_field_type
== kRtcpXrDlrrCode
) {
270 HandleDlrr(rtcp_parser
);
272 rtcp_field_type
= rtcp_parser
->Iterate();
276 void RtcpReceiver::HandleRrtr(RtcpParser
* rtcp_parser
, uint32 remote_ssrc
) {
277 if (remote_ssrc_
!= remote_ssrc
) {
281 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
282 RtcpReceiverReferenceTimeReport remote_time_report
;
283 remote_time_report
.remote_ssrc
= remote_ssrc
;
284 remote_time_report
.ntp_seconds
= rtcp_field
.rrtr
.ntp_most_significant
;
285 remote_time_report
.ntp_fraction
= rtcp_field
.rrtr
.ntp_least_significant
;
287 if (receiver_feedback_
) {
288 receiver_feedback_
->OnReceiverReferenceTimeReport(remote_time_report
);
292 void RtcpReceiver::HandleDlrr(RtcpParser
* rtcp_parser
) {
293 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
294 if (remote_ssrc_
!= rtcp_field
.dlrr
.receivers_ssrc
) {
299 rtt_feedback_
->OnReceivedDelaySinceLastReport(
300 rtcp_field
.dlrr
.receivers_ssrc
,
301 rtcp_field
.dlrr
.last_receiver_report
,
302 rtcp_field
.dlrr
.delay_last_receiver_report
);
306 void RtcpReceiver::HandleNACK(RtcpParser
* rtcp_parser
) {
307 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
308 if (ssrc_
!= rtcp_field
.nack
.media_ssrc
) {
309 RtcpFieldTypes field_type
;
310 // Message not to us. Iterate until we have passed this message.
312 field_type
= rtcp_parser
->Iterate();
313 } while (field_type
== kRtcpGenericRtpFeedbackNackItemCode
);
316 std::list
<uint16
> nackSequenceNumbers
;
318 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
319 while (field_type
== kRtcpGenericRtpFeedbackNackItemCode
) {
320 HandleNACKItem(&rtcp_field
, &nackSequenceNumbers
);
321 field_type
= rtcp_parser
->Iterate();
325 void RtcpReceiver::HandleNACKItem(const RtcpField
* rtcp_field
,
326 std::list
<uint16
>* nack_sequence_numbers
) {
327 nack_sequence_numbers
->push_back(rtcp_field
->nack_item
.packet_id
);
329 uint16 bitmask
= rtcp_field
->nack_item
.bitmask
;
331 for (int i
= 1; i
<= 16; ++i
) {
333 nack_sequence_numbers
->push_back(rtcp_field
->nack_item
.packet_id
+ i
);
335 bitmask
= bitmask
>> 1;
340 void RtcpReceiver::HandleBYE(RtcpParser
* rtcp_parser
) {
341 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
342 uint32 remote_ssrc
= rtcp_field
.bye
.sender_ssrc
;
343 if (remote_ssrc_
== remote_ssrc
) {
344 VLOG(1) << "Cast RTCP received BYE from SSRC " << remote_ssrc
;
346 rtcp_parser
->Iterate();
349 void RtcpReceiver::HandlePLI(RtcpParser
* rtcp_parser
) {
350 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
351 if (ssrc_
== rtcp_field
.pli
.media_ssrc
) {
352 // Received a signal that we need to send a new key frame.
353 VLOG(1) << "Cast RTCP received PLI on our SSRC " << ssrc_
;
355 rtcp_parser
->Iterate();
358 void RtcpReceiver::HandleSendReportRequest(RtcpParser
* rtcp_parser
) {
359 if (receiver_feedback_
) {
360 receiver_feedback_
->OnReceivedSendReportRequest();
362 rtcp_parser
->Iterate();
365 void RtcpReceiver::HandleRpsi(RtcpParser
* rtcp_parser
) {
366 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
367 if (rtcp_parser
->Iterate() != kRtcpPayloadSpecificRpsiCode
) {
370 if (rtcp_field
.rpsi
.number_of_valid_bits
% 8 != 0) {
374 uint64 rpsi_picture_id
= 0;
376 // Convert native_bit_string to rpsi_picture_id
377 uint8 bytes
= rtcp_field
.rpsi
.number_of_valid_bits
/ 8;
378 for (uint8 n
= 0; n
< (bytes
- 1); ++n
) {
379 rpsi_picture_id
+= (rtcp_field
.rpsi
.native_bit_string
[n
] & 0x7f);
380 rpsi_picture_id
<<= 7; // Prepare next.
382 rpsi_picture_id
+= (rtcp_field
.rpsi
.native_bit_string
[bytes
- 1] & 0x7f);
384 VLOG(1) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id
;
387 void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser
* rtcp_parser
) {
388 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
389 uint32 remote_ssrc
= rtcp_field
.application_specific
.sender_ssrc
;
390 if (remote_ssrc_
!= remote_ssrc
) {
391 // Message not to us. Iterate until we have passed this message.
392 RtcpFieldTypes field_type
;
394 field_type
= rtcp_parser
->Iterate();
395 } while (field_type
== kRtcpPayloadSpecificRembCode
||
396 field_type
== kRtcpPayloadSpecificRembItemCode
||
397 field_type
== kRtcpPayloadSpecificCastCode
||
398 field_type
== kRtcpPayloadSpecificCastNackItemCode
);
402 RtcpFieldTypes packet_type
= rtcp_parser
->Iterate();
403 switch (packet_type
) {
404 case kRtcpPayloadSpecificRembCode
:
405 packet_type
= rtcp_parser
->Iterate();
406 if (packet_type
== kRtcpPayloadSpecificRembItemCode
) {
407 HandlePayloadSpecificRembItem(rtcp_parser
);
408 rtcp_parser
->Iterate();
411 case kRtcpPayloadSpecificCastCode
:
412 packet_type
= rtcp_parser
->Iterate();
413 if (packet_type
== kRtcpPayloadSpecificCastCode
) {
414 HandlePayloadSpecificCastItem(rtcp_parser
);
422 void RtcpReceiver::HandlePayloadSpecificRembItem(RtcpParser
* rtcp_parser
) {
423 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
425 for (int i
= 0; i
< rtcp_field
.remb_item
.number_of_ssrcs
; ++i
) {
426 if (rtcp_field
.remb_item
.ssrcs
[i
] == ssrc_
) {
427 // Found matching ssrc.
428 VLOG(1) << "Cast RTCP received REMB with received_bitrate "
429 << rtcp_field
.remb_item
.bitrate
;
435 void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
436 RtcpParser
* rtcp_parser
) {
437 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
439 uint32 remote_ssrc
= rtcp_field
.cast_receiver_log
.sender_ssrc
;
440 if (remote_ssrc_
!= remote_ssrc
) {
441 // Message not to us. Iterate until we have passed this message.
442 RtcpFieldTypes field_type
;
444 field_type
= rtcp_parser
->Iterate();
445 } while (field_type
== kRtcpApplicationSpecificCastReceiverLogFrameCode
||
446 field_type
== kRtcpApplicationSpecificCastReceiverLogEventCode
);
449 RtcpReceiverLogMessage receiver_log
;
450 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
451 while (field_type
== kRtcpApplicationSpecificCastReceiverLogFrameCode
) {
452 RtcpReceiverFrameLogMessage
frame_log(
453 rtcp_field
.cast_receiver_log
.rtp_timestamp
);
455 field_type
= rtcp_parser
->Iterate();
456 while (field_type
== kRtcpApplicationSpecificCastReceiverLogEventCode
) {
457 HandleApplicationSpecificCastReceiverEventLog(rtcp_parser
,
458 &frame_log
.event_log_messages_
);
459 field_type
= rtcp_parser
->Iterate();
461 receiver_log
.push_back(frame_log
);
464 if (receiver_feedback_
&& !receiver_log
.empty()) {
465 receiver_feedback_
->OnReceivedReceiverLog(receiver_log
);
469 void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
470 RtcpParser
* rtcp_parser
,
471 RtcpReceiverEventLogMessages
* event_log_messages
) {
472 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
474 RtcpReceiverEventLogMessage event_log
;
475 event_log
.type
= TranslateToLogEventFromWireFormat(
476 rtcp_field
.cast_receiver_log
.event
);
477 event_log
.event_timestamp
= base::TimeTicks() +
478 base::TimeDelta::FromMilliseconds(
479 rtcp_field
.cast_receiver_log
.event_timestamp_base
+
480 rtcp_field
.cast_receiver_log
.event_timestamp_delta
);
481 event_log
.delay_delta
= base::TimeDelta::FromMilliseconds(
482 rtcp_field
.cast_receiver_log
.delay_delta_or_packet_id
);
483 event_log
.packet_id
=
484 rtcp_field
.cast_receiver_log
.delay_delta_or_packet_id
;
485 event_log_messages
->push_back(event_log
);
488 void RtcpReceiver::HandleApplicationSpecificCastSenderLog(
489 RtcpParser
* rtcp_parser
) {
490 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
491 uint32 remote_ssrc
= rtcp_field
.cast_sender_log
.sender_ssrc
;
493 if (remote_ssrc_
!= remote_ssrc
) {
494 RtcpFieldTypes field_type
;
495 // Message not to us. Iterate until we have passed this message.
497 field_type
= rtcp_parser
->Iterate();
498 } while (field_type
== kRtcpApplicationSpecificCastSenderLogCode
);
501 transport::RtcpSenderLogMessage sender_log
;
503 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
504 while (field_type
== kRtcpApplicationSpecificCastSenderLogCode
) {
505 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
506 transport::RtcpSenderFrameLogMessage frame_log
;
507 frame_log
.frame_status
=
508 TranslateToFrameStatusFromWireFormat(rtcp_field
.cast_sender_log
.status
);
509 frame_log
.rtp_timestamp
= rtcp_field
.cast_sender_log
.rtp_timestamp
;
510 sender_log
.push_back(frame_log
);
511 field_type
= rtcp_parser
->Iterate();
513 if (receiver_feedback_
) {
514 receiver_feedback_
->OnReceivedSenderLog(sender_log
);
518 void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser
* rtcp_parser
) {
519 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
520 RtcpCastMessage
cast_message(remote_ssrc_
);
521 cast_message
.ack_frame_id_
= ack_frame_id_wrap_helper_
.MapTo32bitsFrameId(
522 rtcp_field
.cast_item
.last_frame_id
);
524 RtcpFieldTypes packet_type
= rtcp_parser
->Iterate();
525 while (packet_type
== kRtcpPayloadSpecificCastNackItemCode
) {
526 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
527 HandlePayloadSpecificCastNackItem(
528 &rtcp_field
, &cast_message
.missing_frames_and_packets_
);
529 packet_type
= rtcp_parser
->Iterate();
531 if (sender_feedback_
) {
532 sender_feedback_
->OnReceivedCastFeedback(cast_message
);
536 void RtcpReceiver::HandlePayloadSpecificCastNackItem(
537 const RtcpField
* rtcp_field
,
538 MissingFramesAndPacketsMap
* missing_frames_and_packets
) {
540 MissingFramesAndPacketsMap::iterator frame_it
=
541 missing_frames_and_packets
->find(rtcp_field
->cast_nack_item
.frame_id
);
543 if (frame_it
== missing_frames_and_packets
->end()) {
544 // First missing packet in a frame.
545 PacketIdSet empty_set
;
546 std::pair
<MissingFramesAndPacketsMap::iterator
, bool> ret
=
547 missing_frames_and_packets
->insert(std::pair
<uint8
, PacketIdSet
>(
548 rtcp_field
->cast_nack_item
.frame_id
, empty_set
));
549 frame_it
= ret
.first
;
550 DCHECK(frame_it
!= missing_frames_and_packets
->end()) << "Invalid state";
552 if (rtcp_field
->cast_nack_item
.packet_id
== kRtcpCastAllPacketsLost
) {
553 // Special case all packets in a frame is missing.
556 uint16 packet_id
= rtcp_field
->cast_nack_item
.packet_id
;
557 uint8 bitmask
= rtcp_field
->cast_nack_item
.bitmask
;
559 frame_it
->second
.insert(packet_id
);
562 for (int i
= 1; i
<= 8; ++i
) {
564 frame_it
->second
.insert(packet_id
+ i
);
566 bitmask
= bitmask
>> 1;
571 void RtcpReceiver::HandleFIR(RtcpParser
* rtcp_parser
) {
572 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
574 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
575 while (field_type
== kRtcpPayloadSpecificFirItemCode
) {
576 HandleFIRItem(&rtcp_field
);
577 field_type
= rtcp_parser
->Iterate();
581 void RtcpReceiver::HandleFIRItem(const RtcpField
* rtcp_field
) {
582 // Is it our sender that is requested to generate a new keyframe.
583 if (ssrc_
!= rtcp_field
->fir_item
.ssrc
) return;
585 VLOG(1) << "Cast RTCP received FIR on our SSRC " << ssrc_
;