Home | History | Annotate | Download | only in rtcp
      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.
      4 
      5 #include "media/cast/rtcp/rtcp_receiver.h"
      6 
      7 #include "base/logging.h"
      8 #include "media/cast/rtcp/rtcp_utility.h"
      9 
     10 namespace {
     11 
     12 media::cast::CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
     13   switch (event) {
     14     case 1:
     15       return media::cast::kAckSent;
     16     case 2:
     17       return media::cast::kAudioPlayoutDelay;
     18     case 3:
     19       return media::cast::kAudioFrameDecoded;
     20     case 4:
     21       return media::cast::kVideoFrameDecoded;
     22     case 5:
     23       return media::cast::kVideoRenderDelay;
     24     case 6:
     25       return media::cast::kPacketReceived;
     26     default:
     27       // If the sender adds new log messages we will end up here until we add
     28       // the new messages in the receiver.
     29       VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
     30       NOTREACHED();
     31       return media::cast::kUnknown;
     32   }
     33 }
     34 
     35 media::cast::RtcpSenderFrameStatus TranslateToFrameStatusFromWireFormat(
     36     uint8 status) {
     37   switch (status) {
     38     case 0:
     39       return media::cast::kRtcpSenderFrameStatusUnknown;
     40     case 1:
     41       return media::cast::kRtcpSenderFrameStatusDroppedByEncoder;
     42     case 2:
     43       return media::cast::kRtcpSenderFrameStatusDroppedByFlowControl;
     44     case 3:
     45       return media::cast::kRtcpSenderFrameStatusSentToNetwork;
     46     default:
     47       // If the sender adds new log messages we will end up here until we add
     48       // the new messages in the receiver.
     49       NOTREACHED();
     50       VLOG(1) << "Unexpected status received: " << static_cast<int>(status);
     51       return media::cast::kRtcpSenderFrameStatusUnknown;
     52   }
     53 }
     54 
     55 }  // namespace
     56 
     57 namespace media {
     58 namespace cast {
     59 
     60 RtcpReceiver::RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment,
     61                            RtcpSenderFeedback* sender_feedback,
     62                            RtcpReceiverFeedback* receiver_feedback,
     63                            RtcpRttFeedback* rtt_feedback,
     64                            uint32 local_ssrc)
     65     : ssrc_(local_ssrc),
     66       remote_ssrc_(0),
     67       sender_feedback_(sender_feedback),
     68       receiver_feedback_(receiver_feedback),
     69       rtt_feedback_(rtt_feedback),
     70       cast_environment_(cast_environment) {}
     71 
     72 RtcpReceiver::~RtcpReceiver() {}
     73 
     74 void RtcpReceiver::SetRemoteSSRC(uint32 ssrc) {
     75   remote_ssrc_ = ssrc;
     76 }
     77 
     78 void RtcpReceiver::IncomingRtcpPacket(RtcpParser* rtcp_parser) {
     79   RtcpFieldTypes field_type = rtcp_parser->Begin();
     80   while (field_type != kRtcpNotValidCode) {
     81     // Each "case" is responsible for iterate the parser to the next top
     82     // level packet.
     83     switch (field_type) {
     84       case kRtcpSrCode:
     85         HandleSenderReport(rtcp_parser);
     86         break;
     87       case kRtcpRrCode:
     88         HandleReceiverReport(rtcp_parser);
     89         break;
     90       case kRtcpSdesCode:
     91         HandleSDES(rtcp_parser);
     92         break;
     93       case kRtcpByeCode:
     94         HandleBYE(rtcp_parser);
     95         break;
     96       case kRtcpXrCode:
     97         HandleXr(rtcp_parser);
     98         break;
     99       case kRtcpGenericRtpFeedbackNackCode:
    100         HandleNACK(rtcp_parser);
    101         break;
    102       case kRtcpGenericRtpFeedbackSrReqCode:
    103         HandleSendReportRequest(rtcp_parser);
    104         break;
    105       case kRtcpPayloadSpecificPliCode:
    106         HandlePLI(rtcp_parser);
    107         break;
    108       case kRtcpPayloadSpecificRpsiCode:
    109         HandleRpsi(rtcp_parser);
    110         break;
    111       case kRtcpPayloadSpecificFirCode:
    112         HandleFIR(rtcp_parser);
    113         break;
    114       case kRtcpPayloadSpecificAppCode:
    115         HandlePayloadSpecificApp(rtcp_parser);
    116         break;
    117       case kRtcpApplicationSpecificCastReceiverLogCode:
    118         HandleApplicationSpecificCastReceiverLog(rtcp_parser);
    119         break;
    120       case kRtcpApplicationSpecificCastSenderLogCode:
    121         HandleApplicationSpecificCastSenderLog(rtcp_parser);
    122         break;
    123       case kRtcpPayloadSpecificRembCode:
    124       case kRtcpPayloadSpecificRembItemCode:
    125       case kRtcpPayloadSpecificCastCode:
    126       case kRtcpPayloadSpecificCastNackItemCode:
    127       case kRtcpApplicationSpecificCastReceiverLogFrameCode:
    128       case kRtcpApplicationSpecificCastReceiverLogEventCode:
    129       case kRtcpNotValidCode:
    130       case kRtcpReportBlockItemCode:
    131       case kRtcpSdesChunkCode:
    132       case kRtcpGenericRtpFeedbackNackItemCode:
    133       case kRtcpPayloadSpecificFirItemCode:
    134       case kRtcpXrRrtrCode:
    135       case kRtcpXrDlrrCode:
    136       case kRtcpXrUnknownItemCode:
    137         rtcp_parser->Iterate();
    138         NOTREACHED() << "Invalid state";
    139         break;
    140     }
    141     field_type = rtcp_parser->FieldType();
    142   }
    143 }
    144 
    145 void RtcpReceiver::HandleSenderReport(RtcpParser* rtcp_parser) {
    146   RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
    147   const RtcpField& rtcp_field = rtcp_parser->Field();
    148 
    149   DCHECK(rtcp_field_type == kRtcpSrCode) << "Invalid state";
    150 
    151   // Synchronization source identifier for the originator of this SR packet.
    152   uint32 remote_ssrc = rtcp_field.sender_report.sender_ssrc;
    153 
    154   VLOG(1) << "Cast RTCP received SR from SSRC " << remote_ssrc;
    155 
    156   if (remote_ssrc_ == remote_ssrc) {
    157     RtcpSenderInfo remote_sender_info;
    158     remote_sender_info.ntp_seconds =
    159         rtcp_field.sender_report.ntp_most_significant;
    160     remote_sender_info.ntp_fraction =
    161         rtcp_field.sender_report.ntp_least_significant;
    162     remote_sender_info.rtp_timestamp =
    163         rtcp_field.sender_report.rtp_timestamp;
    164     remote_sender_info.send_packet_count =
    165         rtcp_field.sender_report.sender_packet_count;
    166     remote_sender_info.send_octet_count =
    167         rtcp_field.sender_report.sender_octet_count;
    168     if (receiver_feedback_) {
    169       receiver_feedback_->OnReceivedSenderReport(remote_sender_info);
    170     }
    171   }
    172   rtcp_field_type = rtcp_parser->Iterate();
    173   while (rtcp_field_type == kRtcpReportBlockItemCode) {
    174     HandleReportBlock(&rtcp_field, remote_ssrc);
    175     rtcp_field_type = rtcp_parser->Iterate();
    176   }
    177 }
    178 
    179 void RtcpReceiver::HandleReceiverReport(RtcpParser* rtcp_parser) {
    180   RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
    181   const RtcpField& rtcp_field = rtcp_parser->Field();
    182 
    183   DCHECK(rtcp_field_type == kRtcpRrCode) << "Invalid state";
    184 
    185   uint32 remote_ssrc = rtcp_field.receiver_report.sender_ssrc;
    186 
    187   VLOG(1) << "Cast RTCP received RR from SSRC " << remote_ssrc;
    188 
    189   rtcp_field_type = rtcp_parser->Iterate();
    190   while (rtcp_field_type == kRtcpReportBlockItemCode) {
    191     HandleReportBlock(&rtcp_field, remote_ssrc);
    192     rtcp_field_type = rtcp_parser->Iterate();
    193   }
    194 }
    195 
    196 void RtcpReceiver::HandleReportBlock(const RtcpField* rtcp_field,
    197                                      uint32 remote_ssrc) {
    198   // This will be called once per report block in the Rtcp packet.
    199   // We filter out all report blocks that are not for us.
    200   // Each packet has max 31 RR blocks.
    201   //
    202   // We can calculate RTT if we send a send report and get a report block back.
    203 
    204   // |rtcp_field.ReportBlockItem.ssrc| is the ssrc identifier of the source to
    205   // which the information in this reception report block pertains.
    206 
    207   const RtcpFieldReportBlockItem& rb = rtcp_field->report_block_item;
    208 
    209   // Filter out all report blocks that are not for us.
    210   if (rb.ssrc != ssrc_) {
    211     // This block is not for us ignore it.
    212     return;
    213   }
    214   VLOG(1) << "Cast RTCP received RB from SSRC " << remote_ssrc;
    215   cast_environment_->Logging()->InsertGenericEvent(kPacketLoss,
    216                                                    rb.fraction_lost);
    217   cast_environment_->Logging()->InsertGenericEvent(kJitterMs,
    218                                                    rb.jitter);
    219 
    220   RtcpReportBlock report_block;
    221   report_block.remote_ssrc = remote_ssrc;
    222   report_block.media_ssrc = rb.ssrc;
    223   report_block.fraction_lost = rb.fraction_lost;
    224   report_block.cumulative_lost = rb.cumulative_number_of_packets_lost;
    225   report_block.extended_high_sequence_number =
    226       rb.extended_highest_sequence_number;
    227   report_block.jitter = rb.jitter;
    228   report_block.last_sr = rb.last_sender_report;
    229   report_block.delay_since_last_sr = rb.delay_last_sender_report;
    230 
    231   if (rtt_feedback_) {
    232     rtt_feedback_->OnReceivedDelaySinceLastReport(rb.ssrc,
    233                                                   rb.last_sender_report,
    234                                                   rb.delay_last_sender_report);
    235   }
    236 }
    237 
    238 void RtcpReceiver::HandleSDES(RtcpParser* rtcp_parser) {
    239   RtcpFieldTypes field_type = rtcp_parser->Iterate();
    240   while (field_type == kRtcpSdesChunkCode) {
    241     HandleSDESChunk(rtcp_parser);
    242     field_type = rtcp_parser->Iterate();
    243   }
    244 }
    245 
    246 void RtcpReceiver::HandleSDESChunk(RtcpParser* rtcp_parser) {
    247   const RtcpField& rtcp_field = rtcp_parser->Field();
    248   VLOG(1) << "Cast RTCP received SDES with cname " << rtcp_field.c_name.name;
    249 }
    250 
    251 void RtcpReceiver::HandleXr(RtcpParser* rtcp_parser) {
    252   RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
    253   const RtcpField& rtcp_field = rtcp_parser->Field();
    254 
    255   DCHECK(rtcp_field_type == kRtcpXrCode) << "Invalid state";
    256 
    257   uint32 remote_ssrc = rtcp_field.extended_report.sender_ssrc;
    258   rtcp_field_type = rtcp_parser->Iterate();
    259 
    260   while (rtcp_field_type == kRtcpXrDlrrCode ||
    261          rtcp_field_type == kRtcpXrRrtrCode ||
    262          rtcp_field_type == kRtcpXrUnknownItemCode) {
    263     if (rtcp_field_type == kRtcpXrRrtrCode) {
    264       HandleRrtr(rtcp_parser, remote_ssrc);
    265     } else if (rtcp_field_type == kRtcpXrDlrrCode) {
    266       HandleDlrr(rtcp_parser);
    267     }
    268     rtcp_field_type = rtcp_parser->Iterate();
    269   }
    270 }
    271 
    272 void RtcpReceiver::HandleRrtr(RtcpParser* rtcp_parser, uint32 remote_ssrc) {
    273   if (remote_ssrc_ != remote_ssrc) {
    274     // Not to us.
    275     return;
    276   }
    277   const RtcpField& rtcp_field = rtcp_parser->Field();
    278   RtcpReceiverReferenceTimeReport remote_time_report;
    279   remote_time_report.remote_ssrc = remote_ssrc;
    280   remote_time_report.ntp_seconds = rtcp_field.rrtr.ntp_most_significant;
    281   remote_time_report.ntp_fraction = rtcp_field.rrtr.ntp_least_significant;
    282 
    283   if (receiver_feedback_) {
    284     receiver_feedback_->OnReceiverReferenceTimeReport(remote_time_report);
    285   }
    286 }
    287 
    288 void RtcpReceiver::HandleDlrr(RtcpParser* rtcp_parser) {
    289   const RtcpField& rtcp_field = rtcp_parser->Field();
    290   if (remote_ssrc_ != rtcp_field.dlrr.receivers_ssrc) {
    291     // Not to us.
    292     return;
    293   }
    294   if (rtt_feedback_) {
    295     rtt_feedback_->OnReceivedDelaySinceLastReport(
    296         rtcp_field.dlrr.receivers_ssrc,
    297         rtcp_field.dlrr.last_receiver_report,
    298         rtcp_field.dlrr.delay_last_receiver_report);
    299   }
    300 }
    301 
    302 void RtcpReceiver::HandleNACK(RtcpParser* rtcp_parser) {
    303   const RtcpField& rtcp_field = rtcp_parser->Field();
    304   if (ssrc_ != rtcp_field.nack.media_ssrc) {
    305     RtcpFieldTypes field_type;
    306     // Message not to us. Iterate until we have passed this message.
    307     do {
    308       field_type = rtcp_parser->Iterate();
    309     } while (field_type == kRtcpGenericRtpFeedbackNackItemCode);
    310     return;
    311   }
    312   std::list<uint16> nackSequenceNumbers;
    313 
    314   RtcpFieldTypes field_type = rtcp_parser->Iterate();
    315   while (field_type == kRtcpGenericRtpFeedbackNackItemCode) {
    316     HandleNACKItem(&rtcp_field, &nackSequenceNumbers);
    317     field_type = rtcp_parser->Iterate();
    318   }
    319 }
    320 
    321 void RtcpReceiver::HandleNACKItem(const RtcpField* rtcp_field,
    322                                   std::list<uint16>* nack_sequence_numbers) {
    323   nack_sequence_numbers->push_back(rtcp_field->nack_item.packet_id);
    324 
    325   uint16 bitmask = rtcp_field->nack_item.bitmask;
    326   if (bitmask) {
    327     for (int i = 1; i <= 16; ++i) {
    328       if (bitmask & 1) {
    329         nack_sequence_numbers->push_back(rtcp_field->nack_item.packet_id + i);
    330       }
    331       bitmask = bitmask >> 1;
    332     }
    333   }
    334 }
    335 
    336 void RtcpReceiver::HandleBYE(RtcpParser* rtcp_parser) {
    337   const RtcpField& rtcp_field = rtcp_parser->Field();
    338   uint32 remote_ssrc = rtcp_field.bye.sender_ssrc;
    339   if (remote_ssrc_ == remote_ssrc) {
    340     VLOG(1) << "Cast RTCP received BYE from SSRC " << remote_ssrc;
    341   }
    342   rtcp_parser->Iterate();
    343 }
    344 
    345 void RtcpReceiver::HandlePLI(RtcpParser* rtcp_parser) {
    346   const RtcpField& rtcp_field = rtcp_parser->Field();
    347   if (ssrc_ == rtcp_field.pli.media_ssrc) {
    348     // Received a signal that we need to send a new key frame.
    349     VLOG(1) << "Cast RTCP received PLI on our SSRC " << ssrc_;
    350   }
    351   rtcp_parser->Iterate();
    352 }
    353 
    354 void RtcpReceiver::HandleSendReportRequest(RtcpParser* rtcp_parser) {
    355   if (receiver_feedback_) {
    356     receiver_feedback_->OnReceivedSendReportRequest();
    357   }
    358   rtcp_parser->Iterate();
    359 }
    360 
    361 void RtcpReceiver::HandleRpsi(RtcpParser* rtcp_parser) {
    362   const RtcpField& rtcp_field = rtcp_parser->Field();
    363   if (rtcp_parser->Iterate() != kRtcpPayloadSpecificRpsiCode) {
    364     return;
    365   }
    366   if (rtcp_field.rpsi.number_of_valid_bits % 8 != 0) {
    367     // Continue
    368     return;
    369   }
    370   uint64 rpsi_picture_id = 0;
    371 
    372   // Convert native_bit_string to rpsi_picture_id
    373   uint8 bytes = rtcp_field.rpsi.number_of_valid_bits / 8;
    374   for (uint8 n = 0; n < (bytes - 1); ++n) {
    375     rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[n] & 0x7f);
    376     rpsi_picture_id <<= 7;  // Prepare next.
    377   }
    378   rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[bytes - 1] & 0x7f);
    379 
    380   VLOG(1) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id;
    381 }
    382 
    383 void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser* rtcp_parser) {
    384   const RtcpField& rtcp_field = rtcp_parser->Field();
    385   uint32 remote_ssrc = rtcp_field.application_specific.sender_ssrc;
    386   if (remote_ssrc_ != remote_ssrc) {
    387     // Message not to us. Iterate until we have passed this message.
    388     RtcpFieldTypes field_type;
    389     do {
    390       field_type = rtcp_parser->Iterate();
    391     } while (field_type == kRtcpPayloadSpecificRembCode ||
    392              field_type == kRtcpPayloadSpecificRembItemCode ||
    393              field_type == kRtcpPayloadSpecificCastCode ||
    394              field_type == kRtcpPayloadSpecificCastNackItemCode);
    395     return;
    396   }
    397 
    398   RtcpFieldTypes packet_type = rtcp_parser->Iterate();
    399   switch (packet_type) {
    400     case kRtcpPayloadSpecificRembCode:
    401       packet_type = rtcp_parser->Iterate();
    402       if (packet_type == kRtcpPayloadSpecificRembItemCode) {
    403         HandlePayloadSpecificRembItem(rtcp_parser);
    404         rtcp_parser->Iterate();
    405       }
    406       break;
    407     case kRtcpPayloadSpecificCastCode:
    408       packet_type = rtcp_parser->Iterate();
    409       if (packet_type == kRtcpPayloadSpecificCastCode) {
    410         HandlePayloadSpecificCastItem(rtcp_parser);
    411       }
    412       break;
    413     default:
    414       return;
    415   }
    416 }
    417 
    418 void RtcpReceiver::HandlePayloadSpecificRembItem(RtcpParser* rtcp_parser) {
    419   const RtcpField& rtcp_field = rtcp_parser->Field();
    420 
    421   for (int i = 0; i < rtcp_field.remb_item.number_of_ssrcs; ++i) {
    422     if (rtcp_field.remb_item.ssrcs[i] == ssrc_) {
    423       // Found matching ssrc.
    424       VLOG(1) << "Cast RTCP received REMB with received_bitrate "
    425               << rtcp_field.remb_item.bitrate;
    426       return;
    427     }
    428   }
    429 }
    430 
    431 void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
    432     RtcpParser* rtcp_parser) {
    433   const RtcpField& rtcp_field = rtcp_parser->Field();
    434 
    435   uint32 remote_ssrc = rtcp_field.cast_receiver_log.sender_ssrc;
    436   if (remote_ssrc_ != remote_ssrc) {
    437     // Message not to us. Iterate until we have passed this message.
    438     RtcpFieldTypes field_type;
    439     do {
    440       field_type = rtcp_parser->Iterate();
    441     } while (field_type == kRtcpApplicationSpecificCastReceiverLogFrameCode ||
    442              field_type == kRtcpApplicationSpecificCastReceiverLogEventCode);
    443     return;
    444   }
    445   RtcpReceiverLogMessage receiver_log;
    446   RtcpFieldTypes field_type = rtcp_parser->Iterate();
    447   while (field_type == kRtcpApplicationSpecificCastReceiverLogFrameCode) {
    448     RtcpReceiverFrameLogMessage frame_log(
    449         rtcp_field.cast_receiver_log.rtp_timestamp);
    450 
    451     field_type = rtcp_parser->Iterate();
    452     while (field_type == kRtcpApplicationSpecificCastReceiverLogEventCode) {
    453       HandleApplicationSpecificCastReceiverEventLog(rtcp_parser,
    454           &frame_log.event_log_messages_);
    455       field_type = rtcp_parser->Iterate();
    456     }
    457     receiver_log.push_back(frame_log);
    458   }
    459 
    460   if (receiver_feedback_ && !receiver_log.empty()) {
    461     receiver_feedback_->OnReceivedReceiverLog(receiver_log);
    462   }
    463 }
    464 
    465 void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
    466     RtcpParser* rtcp_parser,
    467     RtcpReceiverEventLogMessages* event_log_messages) {
    468   const RtcpField& rtcp_field = rtcp_parser->Field();
    469 
    470   RtcpReceiverEventLogMessage event_log;
    471   event_log.type = TranslateToLogEventFromWireFormat(
    472       rtcp_field.cast_receiver_log.event);
    473   event_log.event_timestamp = base::TimeTicks() +
    474       base::TimeDelta::FromMilliseconds(
    475           rtcp_field.cast_receiver_log.event_timestamp_base +
    476           rtcp_field.cast_receiver_log.event_timestamp_delta);
    477   event_log.delay_delta = base::TimeDelta::FromMilliseconds(
    478       rtcp_field.cast_receiver_log.delay_delta_or_packet_id);
    479   event_log.packet_id =
    480       rtcp_field.cast_receiver_log.delay_delta_or_packet_id;
    481   event_log_messages->push_back(event_log);
    482 }
    483 
    484 void RtcpReceiver::HandleApplicationSpecificCastSenderLog(
    485     RtcpParser* rtcp_parser) {
    486   const RtcpField& rtcp_field = rtcp_parser->Field();
    487   uint32 remote_ssrc = rtcp_field.cast_sender_log.sender_ssrc;
    488 
    489   if (remote_ssrc_ != remote_ssrc) {
    490     RtcpFieldTypes field_type;
    491     // Message not to us. Iterate until we have passed this message.
    492     do {
    493       field_type = rtcp_parser->Iterate();
    494     } while (field_type == kRtcpApplicationSpecificCastSenderLogCode);
    495     return;
    496   }
    497   RtcpSenderLogMessage sender_log;
    498 
    499   RtcpFieldTypes field_type = rtcp_parser->Iterate();
    500   while (field_type == kRtcpApplicationSpecificCastSenderLogCode) {
    501     const RtcpField& rtcp_field = rtcp_parser->Field();
    502     RtcpSenderFrameLogMessage frame_log;
    503     frame_log.frame_status =
    504         TranslateToFrameStatusFromWireFormat(rtcp_field.cast_sender_log.status);
    505     frame_log.rtp_timestamp = rtcp_field.cast_sender_log.rtp_timestamp;
    506     sender_log.push_back(frame_log);
    507     field_type = rtcp_parser->Iterate();
    508   }
    509   if (receiver_feedback_) {
    510     receiver_feedback_->OnReceivedSenderLog(sender_log);
    511   }
    512 }
    513 
    514 void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser* rtcp_parser) {
    515   const RtcpField& rtcp_field = rtcp_parser->Field();
    516   RtcpCastMessage cast_message(remote_ssrc_);
    517   cast_message.ack_frame_id_ = ack_frame_id_wrap_helper_.MapTo32bitsFrameId(
    518       rtcp_field.cast_item.last_frame_id);
    519 
    520   RtcpFieldTypes packet_type = rtcp_parser->Iterate();
    521   while (packet_type == kRtcpPayloadSpecificCastNackItemCode) {
    522     const RtcpField& rtcp_field = rtcp_parser->Field();
    523     HandlePayloadSpecificCastNackItem(
    524         &rtcp_field, &cast_message.missing_frames_and_packets_);
    525     packet_type = rtcp_parser->Iterate();
    526   }
    527   if (sender_feedback_) {
    528     sender_feedback_->OnReceivedCastFeedback(cast_message);
    529   }
    530 }
    531 
    532 void RtcpReceiver::HandlePayloadSpecificCastNackItem(
    533     const RtcpField* rtcp_field,
    534     MissingFramesAndPacketsMap* missing_frames_and_packets) {
    535 
    536   MissingFramesAndPacketsMap::iterator frame_it =
    537       missing_frames_and_packets->find(rtcp_field->cast_nack_item.frame_id);
    538 
    539   if (frame_it == missing_frames_and_packets->end()) {
    540     // First missing packet in a frame.
    541     PacketIdSet empty_set;
    542     std::pair<MissingFramesAndPacketsMap::iterator, bool> ret =
    543         missing_frames_and_packets->insert(std::pair<uint8, PacketIdSet>(
    544             rtcp_field->cast_nack_item.frame_id, empty_set));
    545     frame_it = ret.first;
    546     DCHECK(frame_it != missing_frames_and_packets->end()) << "Invalid state";
    547   }
    548   if (rtcp_field->cast_nack_item.packet_id == kRtcpCastAllPacketsLost) {
    549     // Special case all packets in a frame is missing.
    550     return;
    551   }
    552   uint16 packet_id = rtcp_field->cast_nack_item.packet_id;
    553   uint8 bitmask = rtcp_field->cast_nack_item.bitmask;
    554 
    555   frame_it->second.insert(packet_id);
    556 
    557   if (bitmask) {
    558     for (int i = 1; i <= 8; ++i) {
    559       if (bitmask & 1) {
    560         frame_it->second.insert(packet_id + i);
    561       }
    562       bitmask = bitmask >> 1;
    563     }
    564   }
    565 }
    566 
    567 void RtcpReceiver::HandleFIR(RtcpParser* rtcp_parser) {
    568   const RtcpField& rtcp_field = rtcp_parser->Field();
    569 
    570   RtcpFieldTypes field_type = rtcp_parser->Iterate();
    571   while (field_type == kRtcpPayloadSpecificFirItemCode) {
    572     HandleFIRItem(&rtcp_field);
    573     field_type = rtcp_parser->Iterate();
    574   }
    575 }
    576 
    577 void RtcpReceiver::HandleFIRItem(const RtcpField* rtcp_field) {
    578   // Is it our sender that is requested to generate a new keyframe.
    579   if (ssrc_ != rtcp_field->fir_item.ssrc) return;
    580 
    581   VLOG(1) << "Cast RTCP received FIR on our SSRC " << ssrc_;
    582 }
    583 
    584 }  // namespace cast
    585 }  // namespace media
    586