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::kAudioAckSent
;
18 return media::cast::kAudioPlayoutDelay
;
20 return media::cast::kAudioFrameDecoded
;
22 return media::cast::kAudioPacketReceived
;
24 return media::cast::kVideoAckSent
;
26 return media::cast::kVideoFrameDecoded
;
28 return media::cast::kVideoRenderDelay
;
30 return media::cast::kVideoPacketReceived
;
32 return media::cast::kDuplicatePacketReceived
;
34 // If the sender adds new log messages we will end up here until we add
35 // the new messages in the receiver.
36 VLOG(1) << "Unexpected log message received: " << static_cast<int>(event
);
38 return media::cast::kUnknown
;
42 media::cast::transport::RtcpSenderFrameStatus
43 TranslateToFrameStatusFromWireFormat(uint8 status
) {
46 return media::cast::transport::kRtcpSenderFrameStatusUnknown
;
48 return media::cast::transport::kRtcpSenderFrameStatusDroppedByEncoder
;
50 return media::cast::transport::kRtcpSenderFrameStatusDroppedByFlowControl
;
52 return media::cast::transport::kRtcpSenderFrameStatusSentToNetwork
;
54 // If the sender adds new log messages we will end up here until we add
55 // the new messages in the receiver.
57 VLOG(1) << "Unexpected status received: " << static_cast<int>(status
);
58 return media::cast::transport::kRtcpSenderFrameStatusUnknown
;
67 RtcpReceiver::RtcpReceiver(scoped_refptr
<CastEnvironment
> cast_environment
,
68 RtcpSenderFeedback
* sender_feedback
,
69 RtcpReceiverFeedback
* receiver_feedback
,
70 RtcpRttFeedback
* rtt_feedback
,
74 sender_feedback_(sender_feedback
),
75 receiver_feedback_(receiver_feedback
),
76 rtt_feedback_(rtt_feedback
),
77 cast_environment_(cast_environment
) {}
79 RtcpReceiver::~RtcpReceiver() {}
81 void RtcpReceiver::SetRemoteSSRC(uint32 ssrc
) { remote_ssrc_
= ssrc
; }
83 void RtcpReceiver::IncomingRtcpPacket(RtcpParser
* rtcp_parser
) {
84 RtcpFieldTypes field_type
= rtcp_parser
->Begin();
85 while (field_type
!= kRtcpNotValidCode
) {
86 // Each "case" is responsible for iterate the parser to the next top
90 HandleSenderReport(rtcp_parser
);
93 HandleReceiverReport(rtcp_parser
);
96 HandleSDES(rtcp_parser
);
99 HandleBYE(rtcp_parser
);
102 HandleXr(rtcp_parser
);
104 case kRtcpGenericRtpFeedbackNackCode
:
105 HandleNACK(rtcp_parser
);
107 case kRtcpGenericRtpFeedbackSrReqCode
:
108 HandleSendReportRequest(rtcp_parser
);
110 case kRtcpPayloadSpecificPliCode
:
111 HandlePLI(rtcp_parser
);
113 case kRtcpPayloadSpecificRpsiCode
:
114 HandleRpsi(rtcp_parser
);
116 case kRtcpPayloadSpecificFirCode
:
117 HandleFIR(rtcp_parser
);
119 case kRtcpPayloadSpecificAppCode
:
120 HandlePayloadSpecificApp(rtcp_parser
);
122 case kRtcpApplicationSpecificCastReceiverLogCode
:
123 HandleApplicationSpecificCastReceiverLog(rtcp_parser
);
125 case kRtcpApplicationSpecificCastSenderLogCode
:
126 HandleApplicationSpecificCastSenderLog(rtcp_parser
);
128 case kRtcpPayloadSpecificRembCode
:
129 case kRtcpPayloadSpecificRembItemCode
:
130 case kRtcpPayloadSpecificCastCode
:
131 case kRtcpPayloadSpecificCastNackItemCode
:
132 case kRtcpApplicationSpecificCastReceiverLogFrameCode
:
133 case kRtcpApplicationSpecificCastReceiverLogEventCode
:
134 case kRtcpNotValidCode
:
135 case kRtcpReportBlockItemCode
:
136 case kRtcpSdesChunkCode
:
137 case kRtcpGenericRtpFeedbackNackItemCode
:
138 case kRtcpPayloadSpecificFirItemCode
:
139 case kRtcpXrRrtrCode
:
140 case kRtcpXrDlrrCode
:
141 case kRtcpXrUnknownItemCode
:
142 rtcp_parser
->Iterate();
143 NOTREACHED() << "Invalid state";
146 field_type
= rtcp_parser
->FieldType();
150 void RtcpReceiver::HandleSenderReport(RtcpParser
* rtcp_parser
) {
151 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
152 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
154 DCHECK(rtcp_field_type
== kRtcpSrCode
) << "Invalid state";
156 // Synchronization source identifier for the originator of this SR packet.
157 uint32 remote_ssrc
= rtcp_field
.sender_report
.sender_ssrc
;
159 VLOG(1) << "Cast RTCP received SR from SSRC " << remote_ssrc
;
161 if (remote_ssrc_
== remote_ssrc
) {
162 transport::RtcpSenderInfo remote_sender_info
;
163 remote_sender_info
.ntp_seconds
=
164 rtcp_field
.sender_report
.ntp_most_significant
;
165 remote_sender_info
.ntp_fraction
=
166 rtcp_field
.sender_report
.ntp_least_significant
;
167 remote_sender_info
.rtp_timestamp
= rtcp_field
.sender_report
.rtp_timestamp
;
168 remote_sender_info
.send_packet_count
=
169 rtcp_field
.sender_report
.sender_packet_count
;
170 remote_sender_info
.send_octet_count
=
171 rtcp_field
.sender_report
.sender_octet_count
;
172 if (receiver_feedback_
) {
173 receiver_feedback_
->OnReceivedSenderReport(remote_sender_info
);
176 rtcp_field_type
= rtcp_parser
->Iterate();
177 while (rtcp_field_type
== kRtcpReportBlockItemCode
) {
178 HandleReportBlock(&rtcp_field
, remote_ssrc
);
179 rtcp_field_type
= rtcp_parser
->Iterate();
183 void RtcpReceiver::HandleReceiverReport(RtcpParser
* rtcp_parser
) {
184 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
185 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
187 DCHECK(rtcp_field_type
== kRtcpRrCode
) << "Invalid state";
189 uint32 remote_ssrc
= rtcp_field
.receiver_report
.sender_ssrc
;
191 VLOG(1) << "Cast RTCP received RR from SSRC " << remote_ssrc
;
193 rtcp_field_type
= rtcp_parser
->Iterate();
194 while (rtcp_field_type
== kRtcpReportBlockItemCode
) {
195 HandleReportBlock(&rtcp_field
, remote_ssrc
);
196 rtcp_field_type
= rtcp_parser
->Iterate();
200 void RtcpReceiver::HandleReportBlock(const RtcpField
* rtcp_field
,
201 uint32 remote_ssrc
) {
202 // This will be called once per report block in the Rtcp packet.
203 // We filter out all report blocks that are not for us.
204 // Each packet has max 31 RR blocks.
206 // We can calculate RTT if we send a send report and get a report block back.
208 // |rtcp_field.ReportBlockItem.ssrc| is the ssrc identifier of the source to
209 // which the information in this reception report block pertains.
211 const RtcpFieldReportBlockItem
& rb
= rtcp_field
->report_block_item
;
213 // Filter out all report blocks that are not for us.
214 if (rb
.ssrc
!= ssrc_
) {
215 // This block is not for us ignore it.
218 VLOG(1) << "Cast RTCP received RB from SSRC " << remote_ssrc
;
219 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
220 cast_environment_
->Logging()->InsertGenericEvent(
221 now
, kPacketLoss
, rb
.fraction_lost
);
222 cast_environment_
->Logging()->InsertGenericEvent(now
, kJitterMs
, rb
.jitter
);
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(
237 rb
.ssrc
, rb
.last_sender_report
, rb
.delay_last_sender_report
);
241 void RtcpReceiver::HandleSDES(RtcpParser
* rtcp_parser
) {
242 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
243 while (field_type
== kRtcpSdesChunkCode
) {
244 HandleSDESChunk(rtcp_parser
);
245 field_type
= rtcp_parser
->Iterate();
249 void RtcpReceiver::HandleSDESChunk(RtcpParser
* rtcp_parser
) {
250 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
251 VLOG(1) << "Cast RTCP received SDES with cname " << rtcp_field
.c_name
.name
;
254 void RtcpReceiver::HandleXr(RtcpParser
* rtcp_parser
) {
255 RtcpFieldTypes rtcp_field_type
= rtcp_parser
->FieldType();
256 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
258 DCHECK(rtcp_field_type
== kRtcpXrCode
) << "Invalid state";
260 uint32 remote_ssrc
= rtcp_field
.extended_report
.sender_ssrc
;
261 rtcp_field_type
= rtcp_parser
->Iterate();
263 while (rtcp_field_type
== kRtcpXrDlrrCode
||
264 rtcp_field_type
== kRtcpXrRrtrCode
||
265 rtcp_field_type
== kRtcpXrUnknownItemCode
) {
266 if (rtcp_field_type
== kRtcpXrRrtrCode
) {
267 HandleRrtr(rtcp_parser
, remote_ssrc
);
268 } else if (rtcp_field_type
== kRtcpXrDlrrCode
) {
269 HandleDlrr(rtcp_parser
);
271 rtcp_field_type
= rtcp_parser
->Iterate();
275 void RtcpReceiver::HandleRrtr(RtcpParser
* rtcp_parser
, uint32 remote_ssrc
) {
276 if (remote_ssrc_
!= remote_ssrc
) {
280 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
281 RtcpReceiverReferenceTimeReport remote_time_report
;
282 remote_time_report
.remote_ssrc
= remote_ssrc
;
283 remote_time_report
.ntp_seconds
= rtcp_field
.rrtr
.ntp_most_significant
;
284 remote_time_report
.ntp_fraction
= rtcp_field
.rrtr
.ntp_least_significant
;
286 if (receiver_feedback_
) {
287 receiver_feedback_
->OnReceiverReferenceTimeReport(remote_time_report
);
291 void RtcpReceiver::HandleDlrr(RtcpParser
* rtcp_parser
) {
292 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
293 if (remote_ssrc_
!= rtcp_field
.dlrr
.receivers_ssrc
) {
298 rtt_feedback_
->OnReceivedDelaySinceLastReport(
299 rtcp_field
.dlrr
.receivers_ssrc
,
300 rtcp_field
.dlrr
.last_receiver_report
,
301 rtcp_field
.dlrr
.delay_last_receiver_report
);
305 void RtcpReceiver::HandleNACK(RtcpParser
* rtcp_parser
) {
306 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
307 if (ssrc_
!= rtcp_field
.nack
.media_ssrc
) {
308 RtcpFieldTypes field_type
;
309 // Message not to us. Iterate until we have passed this message.
311 field_type
= rtcp_parser
->Iterate();
312 } while (field_type
== kRtcpGenericRtpFeedbackNackItemCode
);
315 std::list
<uint16
> nackSequenceNumbers
;
317 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
318 while (field_type
== kRtcpGenericRtpFeedbackNackItemCode
) {
319 HandleNACKItem(&rtcp_field
, &nackSequenceNumbers
);
320 field_type
= rtcp_parser
->Iterate();
324 void RtcpReceiver::HandleNACKItem(const RtcpField
* rtcp_field
,
325 std::list
<uint16
>* nack_sequence_numbers
) {
326 nack_sequence_numbers
->push_back(rtcp_field
->nack_item
.packet_id
);
328 uint16 bitmask
= rtcp_field
->nack_item
.bitmask
;
330 for (int i
= 1; i
<= 16; ++i
) {
332 nack_sequence_numbers
->push_back(rtcp_field
->nack_item
.packet_id
+ i
);
334 bitmask
= bitmask
>> 1;
339 void RtcpReceiver::HandleBYE(RtcpParser
* rtcp_parser
) {
340 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
341 uint32 remote_ssrc
= rtcp_field
.bye
.sender_ssrc
;
342 if (remote_ssrc_
== remote_ssrc
) {
343 VLOG(1) << "Cast RTCP received BYE from SSRC " << remote_ssrc
;
345 rtcp_parser
->Iterate();
348 void RtcpReceiver::HandlePLI(RtcpParser
* rtcp_parser
) {
349 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
350 if (ssrc_
== rtcp_field
.pli
.media_ssrc
) {
351 // Received a signal that we need to send a new key frame.
352 VLOG(1) << "Cast RTCP received PLI on our SSRC " << ssrc_
;
354 rtcp_parser
->Iterate();
357 void RtcpReceiver::HandleSendReportRequest(RtcpParser
* rtcp_parser
) {
358 if (receiver_feedback_
) {
359 receiver_feedback_
->OnReceivedSendReportRequest();
361 rtcp_parser
->Iterate();
364 void RtcpReceiver::HandleRpsi(RtcpParser
* rtcp_parser
) {
365 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
366 if (rtcp_parser
->Iterate() != kRtcpPayloadSpecificRpsiCode
) {
369 if (rtcp_field
.rpsi
.number_of_valid_bits
% 8 != 0) {
373 uint64 rpsi_picture_id
= 0;
375 // Convert native_bit_string to rpsi_picture_id
376 uint8 bytes
= rtcp_field
.rpsi
.number_of_valid_bits
/ 8;
377 for (uint8 n
= 0; n
< (bytes
- 1); ++n
) {
378 rpsi_picture_id
+= (rtcp_field
.rpsi
.native_bit_string
[n
] & 0x7f);
379 rpsi_picture_id
<<= 7; // Prepare next.
381 rpsi_picture_id
+= (rtcp_field
.rpsi
.native_bit_string
[bytes
- 1] & 0x7f);
383 VLOG(1) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id
;
386 void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser
* rtcp_parser
) {
387 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
388 uint32 remote_ssrc
= rtcp_field
.application_specific
.sender_ssrc
;
389 if (remote_ssrc_
!= remote_ssrc
) {
390 // Message not to us. Iterate until we have passed this message.
391 RtcpFieldTypes field_type
;
393 field_type
= rtcp_parser
->Iterate();
394 } while (field_type
== kRtcpPayloadSpecificRembCode
||
395 field_type
== kRtcpPayloadSpecificRembItemCode
||
396 field_type
== kRtcpPayloadSpecificCastCode
||
397 field_type
== kRtcpPayloadSpecificCastNackItemCode
);
401 RtcpFieldTypes packet_type
= rtcp_parser
->Iterate();
402 switch (packet_type
) {
403 case kRtcpPayloadSpecificRembCode
:
404 packet_type
= rtcp_parser
->Iterate();
405 if (packet_type
== kRtcpPayloadSpecificRembItemCode
) {
406 HandlePayloadSpecificRembItem(rtcp_parser
);
407 rtcp_parser
->Iterate();
410 case kRtcpPayloadSpecificCastCode
:
411 packet_type
= rtcp_parser
->Iterate();
412 if (packet_type
== kRtcpPayloadSpecificCastCode
) {
413 HandlePayloadSpecificCastItem(rtcp_parser
);
421 void RtcpReceiver::HandlePayloadSpecificRembItem(RtcpParser
* rtcp_parser
) {
422 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
424 for (int i
= 0; i
< rtcp_field
.remb_item
.number_of_ssrcs
; ++i
) {
425 if (rtcp_field
.remb_item
.ssrcs
[i
] == ssrc_
) {
426 // Found matching ssrc.
427 VLOG(1) << "Cast RTCP received REMB with received_bitrate "
428 << rtcp_field
.remb_item
.bitrate
;
434 void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
435 RtcpParser
* rtcp_parser
) {
436 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
438 uint32 remote_ssrc
= rtcp_field
.cast_receiver_log
.sender_ssrc
;
439 if (remote_ssrc_
!= remote_ssrc
) {
440 // Message not to us. Iterate until we have passed this message.
441 RtcpFieldTypes field_type
;
443 field_type
= rtcp_parser
->Iterate();
444 } while (field_type
== kRtcpApplicationSpecificCastReceiverLogFrameCode
||
445 field_type
== kRtcpApplicationSpecificCastReceiverLogEventCode
);
448 RtcpReceiverLogMessage receiver_log
;
449 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
450 while (field_type
== kRtcpApplicationSpecificCastReceiverLogFrameCode
) {
451 RtcpReceiverFrameLogMessage
frame_log(
452 rtcp_field
.cast_receiver_log
.rtp_timestamp
);
454 field_type
= rtcp_parser
->Iterate();
455 while (field_type
== kRtcpApplicationSpecificCastReceiverLogEventCode
) {
456 HandleApplicationSpecificCastReceiverEventLog(
457 rtcp_parser
, &frame_log
.event_log_messages_
);
458 field_type
= rtcp_parser
->Iterate();
460 receiver_log
.push_back(frame_log
);
463 if (receiver_feedback_
&& !receiver_log
.empty()) {
464 receiver_feedback_
->OnReceivedReceiverLog(receiver_log
);
468 void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
469 RtcpParser
* rtcp_parser
,
470 RtcpReceiverEventLogMessages
* event_log_messages
) {
471 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
473 RtcpReceiverEventLogMessage event_log
;
475 TranslateToLogEventFromWireFormat(rtcp_field
.cast_receiver_log
.event
);
476 event_log
.event_timestamp
=
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
= rtcp_field
.cast_receiver_log
.delay_delta_or_packet_id
;
484 event_log_messages
->push_back(event_log
);
487 void RtcpReceiver::HandleApplicationSpecificCastSenderLog(
488 RtcpParser
* rtcp_parser
) {
489 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
490 uint32 remote_ssrc
= rtcp_field
.cast_sender_log
.sender_ssrc
;
492 if (remote_ssrc_
!= remote_ssrc
) {
493 RtcpFieldTypes field_type
;
494 // Message not to us. Iterate until we have passed this message.
496 field_type
= rtcp_parser
->Iterate();
497 } while (field_type
== kRtcpApplicationSpecificCastSenderLogCode
);
500 transport::RtcpSenderLogMessage sender_log
;
502 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
503 while (field_type
== kRtcpApplicationSpecificCastSenderLogCode
) {
504 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
505 transport::RtcpSenderFrameLogMessage frame_log
;
506 frame_log
.frame_status
=
507 TranslateToFrameStatusFromWireFormat(rtcp_field
.cast_sender_log
.status
);
508 frame_log
.rtp_timestamp
= rtcp_field
.cast_sender_log
.rtp_timestamp
;
509 sender_log
.push_back(frame_log
);
510 field_type
= rtcp_parser
->Iterate();
512 if (receiver_feedback_
) {
513 receiver_feedback_
->OnReceivedSenderLog(sender_log
);
517 void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser
* rtcp_parser
) {
518 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
519 RtcpCastMessage
cast_message(remote_ssrc_
);
520 cast_message
.ack_frame_id_
= ack_frame_id_wrap_helper_
.MapTo32bitsFrameId(
521 rtcp_field
.cast_item
.last_frame_id
);
523 RtcpFieldTypes packet_type
= rtcp_parser
->Iterate();
524 while (packet_type
== kRtcpPayloadSpecificCastNackItemCode
) {
525 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
526 HandlePayloadSpecificCastNackItem(
527 &rtcp_field
, &cast_message
.missing_frames_and_packets_
);
528 packet_type
= rtcp_parser
->Iterate();
530 if (sender_feedback_
) {
531 sender_feedback_
->OnReceivedCastFeedback(cast_message
);
535 void RtcpReceiver::HandlePayloadSpecificCastNackItem(
536 const RtcpField
* rtcp_field
,
537 MissingFramesAndPacketsMap
* missing_frames_and_packets
) {
539 MissingFramesAndPacketsMap::iterator frame_it
=
540 missing_frames_and_packets
->find(rtcp_field
->cast_nack_item
.frame_id
);
542 if (frame_it
== missing_frames_and_packets
->end()) {
543 // First missing packet in a frame.
544 PacketIdSet empty_set
;
545 std::pair
<MissingFramesAndPacketsMap::iterator
, bool> ret
=
546 missing_frames_and_packets
->insert(std::pair
<uint8
, PacketIdSet
>(
547 rtcp_field
->cast_nack_item
.frame_id
, empty_set
));
548 frame_it
= ret
.first
;
549 DCHECK(frame_it
!= missing_frames_and_packets
->end()) << "Invalid state";
551 if (rtcp_field
->cast_nack_item
.packet_id
== kRtcpCastAllPacketsLost
) {
552 // Special case all packets in a frame is missing.
555 uint16 packet_id
= rtcp_field
->cast_nack_item
.packet_id
;
556 uint8 bitmask
= rtcp_field
->cast_nack_item
.bitmask
;
558 frame_it
->second
.insert(packet_id
);
561 for (int i
= 1; i
<= 8; ++i
) {
563 frame_it
->second
.insert(packet_id
+ i
);
565 bitmask
= bitmask
>> 1;
570 void RtcpReceiver::HandleFIR(RtcpParser
* rtcp_parser
) {
571 const RtcpField
& rtcp_field
= rtcp_parser
->Field();
573 RtcpFieldTypes field_type
= rtcp_parser
->Iterate();
574 while (field_type
== kRtcpPayloadSpecificFirItemCode
) {
575 HandleFIRItem(&rtcp_field
);
576 field_type
= rtcp_parser
->Iterate();
580 void RtcpReceiver::HandleFIRItem(const RtcpField
* rtcp_field
) {
581 // Is it our sender that is requested to generate a new keyframe.
582 if (ssrc_
!= rtcp_field
->fir_item
.ssrc
)
585 VLOG(1) << "Cast RTCP received FIR on our SSRC " << ssrc_
;