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 #include "media/cast/transport/cast_transport_defines.h"
     10 
     11 namespace {
     12 
     13 // A receiver frame event is identified by frame RTP timestamp, event timestamp
     14 // and event type.
     15 // A receiver packet event is identified by all of the above plus packet id.
     16 // The key format is as follows:
     17 // First uint64:
     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.
     22 // Second uint64:
     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;
     28   value1 <<= 16;
     29   value1 |= packet_id_or_zero;
     30   value1 <<= 32;
     31   value1 |= frame_rtp_timestamp;
     32   return std::make_pair(
     33       value1, static_cast<uint64>(event_timestamp.ToInternalValue()));
     34 }
     35 
     36 }  // namespace
     37 
     38 namespace media {
     39 namespace cast {
     40 
     41 RtcpReceiver::RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment,
     42                            RtcpSenderFeedback* sender_feedback,
     43                            RtcpReceiverFeedback* receiver_feedback,
     44                            RtcpRttFeedback* rtt_feedback,
     45                            uint32 local_ssrc)
     46     : ssrc_(local_ssrc),
     47       remote_ssrc_(0),
     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) {}
     53 
     54 RtcpReceiver::~RtcpReceiver() {}
     55 
     56 void RtcpReceiver::SetRemoteSSRC(uint32 ssrc) { remote_ssrc_ = ssrc; }
     57 
     58 void RtcpReceiver::SetCastReceiverEventHistorySize(size_t size) {
     59   receiver_event_history_size_ = size;
     60 }
     61 
     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
     66     // level packet.
     67     switch (field_type) {
     68       case kRtcpSrCode:
     69         HandleSenderReport(rtcp_parser);
     70         break;
     71       case kRtcpRrCode:
     72         HandleReceiverReport(rtcp_parser);
     73         break;
     74       case kRtcpSdesCode:
     75         HandleSDES(rtcp_parser);
     76         break;
     77       case kRtcpByeCode:
     78         HandleBYE(rtcp_parser);
     79         break;
     80       case kRtcpXrCode:
     81         HandleXr(rtcp_parser);
     82         break;
     83       case kRtcpGenericRtpFeedbackNackCode:
     84         HandleNACK(rtcp_parser);
     85         break;
     86       case kRtcpGenericRtpFeedbackSrReqCode:
     87         HandleSendReportRequest(rtcp_parser);
     88         break;
     89       case kRtcpPayloadSpecificPliCode:
     90         HandlePLI(rtcp_parser);
     91         break;
     92       case kRtcpPayloadSpecificRpsiCode:
     93         HandleRpsi(rtcp_parser);
     94         break;
     95       case kRtcpPayloadSpecificFirCode:
     96         HandleFIR(rtcp_parser);
     97         break;
     98       case kRtcpPayloadSpecificAppCode:
     99         HandlePayloadSpecificApp(rtcp_parser);
    100         break;
    101       case kRtcpApplicationSpecificCastReceiverLogCode:
    102         HandleApplicationSpecificCastReceiverLog(rtcp_parser);
    103         break;
    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";
    120         break;
    121     }
    122     field_type = rtcp_parser->FieldType();
    123   }
    124 }
    125 
    126 void RtcpReceiver::HandleSenderReport(RtcpParser* rtcp_parser) {
    127   RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
    128   const RtcpField& rtcp_field = rtcp_parser->Field();
    129 
    130   DCHECK(rtcp_field_type == kRtcpSrCode) << "Invalid state";
    131 
    132   // Synchronization source identifier for the originator of this SR packet.
    133   uint32 remote_ssrc = rtcp_field.sender_report.sender_ssrc;
    134 
    135   VLOG(2) << "Cast RTCP received SR from SSRC " << remote_ssrc;
    136 
    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);
    150     }
    151   }
    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();
    156   }
    157 }
    158 
    159 void RtcpReceiver::HandleReceiverReport(RtcpParser* rtcp_parser) {
    160   RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
    161   const RtcpField& rtcp_field = rtcp_parser->Field();
    162 
    163   DCHECK(rtcp_field_type == kRtcpRrCode) << "Invalid state";
    164 
    165   uint32 remote_ssrc = rtcp_field.receiver_report.sender_ssrc;
    166 
    167   VLOG(2) << "Cast RTCP received RR from SSRC " << remote_ssrc;
    168 
    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();
    173   }
    174 }
    175 
    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.
    181   //
    182   // We can calculate RTT if we send a send report and get a report block back.
    183 
    184   // |rtcp_field.ReportBlockItem.ssrc| is the ssrc identifier of the source to
    185   // which the information in this reception report block pertains.
    186 
    187   const RtcpFieldReportBlockItem& rb = rtcp_field->report_block_item;
    188 
    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.
    192     return;
    193   }
    194   VLOG(2) << "Cast RTCP received RB from SSRC " << remote_ssrc;
    195 
    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;
    206 
    207   if (rtt_feedback_) {
    208     rtt_feedback_->OnReceivedDelaySinceLastReport(
    209         rb.ssrc, rb.last_sender_report, rb.delay_last_sender_report);
    210   }
    211 }
    212 
    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();
    218   }
    219 }
    220 
    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;
    224 }
    225 
    226 void RtcpReceiver::HandleXr(RtcpParser* rtcp_parser) {
    227   RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
    228   const RtcpField& rtcp_field = rtcp_parser->Field();
    229 
    230   DCHECK(rtcp_field_type == kRtcpXrCode) << "Invalid state";
    231 
    232   uint32 remote_ssrc = rtcp_field.extended_report.sender_ssrc;
    233   rtcp_field_type = rtcp_parser->Iterate();
    234 
    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);
    242     }
    243     rtcp_field_type = rtcp_parser->Iterate();
    244   }
    245 }
    246 
    247 void RtcpReceiver::HandleRrtr(RtcpParser* rtcp_parser, uint32 remote_ssrc) {
    248   if (remote_ssrc_ != remote_ssrc) {
    249     // Not to us.
    250     return;
    251   }
    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;
    257 
    258   if (receiver_feedback_) {
    259     receiver_feedback_->OnReceiverReferenceTimeReport(remote_time_report);
    260   }
    261 }
    262 
    263 void RtcpReceiver::HandleDlrr(RtcpParser* rtcp_parser) {
    264   const RtcpField& rtcp_field = rtcp_parser->Field();
    265   if (remote_ssrc_ != rtcp_field.dlrr.receivers_ssrc) {
    266     // Not to us.
    267     return;
    268   }
    269   if (rtt_feedback_) {
    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);
    274   }
    275 }
    276 
    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.
    282     do {
    283       field_type = rtcp_parser->Iterate();
    284     } while (field_type == kRtcpGenericRtpFeedbackNackItemCode);
    285     return;
    286   }
    287   std::list<uint16> nackSequenceNumbers;
    288 
    289   RtcpFieldTypes field_type = rtcp_parser->Iterate();
    290   while (field_type == kRtcpGenericRtpFeedbackNackItemCode) {
    291     HandleNACKItem(&rtcp_field, &nackSequenceNumbers);
    292     field_type = rtcp_parser->Iterate();
    293   }
    294 }
    295 
    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);
    299 
    300   uint16 bitmask = rtcp_field->nack_item.bitmask;
    301   if (bitmask) {
    302     for (int i = 1; i <= 16; ++i) {
    303       if (bitmask & 1) {
    304         nack_sequence_numbers->push_back(rtcp_field->nack_item.packet_id + i);
    305       }
    306       bitmask = bitmask >> 1;
    307     }
    308   }
    309 }
    310 
    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;
    316   }
    317   rtcp_parser->Iterate();
    318 }
    319 
    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_;
    325   }
    326   rtcp_parser->Iterate();
    327 }
    328 
    329 void RtcpReceiver::HandleSendReportRequest(RtcpParser* rtcp_parser) {
    330   if (receiver_feedback_) {
    331     receiver_feedback_->OnReceivedSendReportRequest();
    332   }
    333   rtcp_parser->Iterate();
    334 }
    335 
    336 void RtcpReceiver::HandleRpsi(RtcpParser* rtcp_parser) {
    337   const RtcpField& rtcp_field = rtcp_parser->Field();
    338   if (rtcp_parser->Iterate() != kRtcpPayloadSpecificRpsiCode) {
    339     return;
    340   }
    341   if (rtcp_field.rpsi.number_of_valid_bits % 8 != 0) {
    342     // Continue
    343     return;
    344   }
    345   uint64 rpsi_picture_id = 0;
    346 
    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.
    352   }
    353   rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[bytes - 1] & 0x7f);
    354 
    355   VLOG(2) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id;
    356 }
    357 
    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;
    364     do {
    365       field_type = rtcp_parser->Iterate();
    366     } while (field_type == kRtcpPayloadSpecificRembCode ||
    367              field_type == kRtcpPayloadSpecificRembItemCode ||
    368              field_type == kRtcpPayloadSpecificCastCode ||
    369              field_type == kRtcpPayloadSpecificCastNackItemCode);
    370     return;
    371   }
    372 
    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();
    380       }
    381       break;
    382     case kRtcpPayloadSpecificCastCode:
    383       packet_type = rtcp_parser->Iterate();
    384       if (packet_type == kRtcpPayloadSpecificCastCode) {
    385         HandlePayloadSpecificCastItem(rtcp_parser);
    386       }
    387       break;
    388     default:
    389       return;
    390   }
    391 }
    392 
    393 void RtcpReceiver::HandlePayloadSpecificRembItem(RtcpParser* rtcp_parser) {
    394   const RtcpField& rtcp_field = rtcp_parser->Field();
    395 
    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;
    401       return;
    402     }
    403   }
    404 }
    405 
    406 void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
    407     RtcpParser* rtcp_parser) {
    408   const RtcpField& rtcp_field = rtcp_parser->Field();
    409 
    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;
    414     do {
    415       field_type = rtcp_parser->Iterate();
    416     } while (field_type == kRtcpApplicationSpecificCastReceiverLogFrameCode ||
    417              field_type == kRtcpApplicationSpecificCastReceiverLogEventCode);
    418     return;
    419   }
    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);
    425 
    426     field_type = rtcp_parser->Iterate();
    427     while (field_type == kRtcpApplicationSpecificCastReceiverLogEventCode) {
    428       HandleApplicationSpecificCastReceiverEventLog(
    429           rtcp_field.cast_receiver_log.rtp_timestamp,
    430           rtcp_parser,
    431           &frame_log.event_log_messages_);
    432       field_type = rtcp_parser->Iterate();
    433     }
    434 
    435     if (!frame_log.event_log_messages_.empty())
    436       receiver_log.push_back(frame_log);
    437   }
    438 
    439   if (receiver_feedback_ && !receiver_log.empty()) {
    440     receiver_feedback_->OnReceivedReceiverLog(receiver_log);
    441   }
    442 }
    443 
    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();
    449 
    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 =
    455       base::TimeTicks() +
    456       base::TimeDelta::FromMilliseconds(
    457           rtcp_field.cast_receiver_log.event_timestamp_base +
    458           rtcp_field.cast_receiver_log.event_timestamp_delta);
    459 
    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 =
    466       GetReceiverEventKey(
    467           frame_rtp_timestamp, event_timestamp, event, packet_id);
    468   if (receiver_event_key_set_.find(key) != receiver_event_key_set_.end()) {
    469     return;
    470   } else {
    471     receiver_event_key_set_.insert(key);
    472     receiver_event_key_queue_.push(key);
    473 
    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);
    478     }
    479   }
    480 
    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);
    489 }
    490 
    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;
    497 
    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();
    504   }
    505   if (sender_feedback_) {
    506     sender_feedback_->OnReceivedCastFeedback(cast_message);
    507   }
    508 }
    509 
    510 void RtcpReceiver::HandlePayloadSpecificCastNackItem(
    511     const RtcpField* rtcp_field,
    512     MissingFramesAndPacketsMap* missing_frames_and_packets) {
    513 
    514   MissingFramesAndPacketsMap::iterator frame_it =
    515       missing_frames_and_packets->find(rtcp_field->cast_nack_item.frame_id);
    516 
    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";
    525   }
    526   uint16 packet_id = rtcp_field->cast_nack_item.packet_id;
    527   frame_it->second.insert(packet_id);
    528 
    529   if (packet_id == kRtcpCastAllPacketsLost) {
    530     // Special case all packets in a frame is missing.
    531     return;
    532   }
    533   uint8 bitmask = rtcp_field->cast_nack_item.bitmask;
    534 
    535   if (bitmask) {
    536     for (int i = 1; i <= 8; ++i) {
    537       if (bitmask & 1) {
    538         frame_it->second.insert(packet_id + i);
    539       }
    540       bitmask = bitmask >> 1;
    541     }
    542   }
    543 }
    544 
    545 void RtcpReceiver::HandleFIR(RtcpParser* rtcp_parser) {
    546   const RtcpField& rtcp_field = rtcp_parser->Field();
    547 
    548   RtcpFieldTypes field_type = rtcp_parser->Iterate();
    549   while (field_type == kRtcpPayloadSpecificFirItemCode) {
    550     HandleFIRItem(&rtcp_field);
    551     field_type = rtcp_parser->Iterate();
    552   }
    553 }
    554 
    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)
    558     return;
    559 
    560   VLOG(2) << "Cast RTCP received FIR on our SSRC " << ssrc_;
    561 }
    562 
    563 }  // namespace cast
    564 }  // namespace media
    565