Home | History | Annotate | Download | only in rtcp
      1 // Copyright 2014 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/net/rtcp/rtcp_utility.h"
      6 
      7 #include "base/logging.h"
      8 #include "media/cast/net/cast_transport_defines.h"
      9 
     10 namespace media {
     11 namespace cast {
     12 
     13 RtcpParser::RtcpParser(uint32 local_ssrc, uint32 remote_ssrc) :
     14     local_ssrc_(local_ssrc),
     15     remote_ssrc_(remote_ssrc),
     16     has_sender_report_(false),
     17     has_last_report_(false),
     18     has_cast_message_(false),
     19     has_receiver_reference_time_report_(false) {
     20 }
     21 
     22 RtcpParser::~RtcpParser() {}
     23 
     24 bool RtcpParser::Parse(base::BigEndianReader* reader) {
     25   while (reader->remaining()) {
     26     RtcpCommonHeader header;
     27     if (!ParseCommonHeader(reader, &header))
     28       return false;
     29 
     30     base::StringPiece tmp;
     31     if (!reader->ReadPiece(&tmp, header.length_in_octets - 4))
     32       return false;
     33     base::BigEndianReader chunk(tmp.data(), tmp.size());
     34 
     35     switch (header.PT) {
     36       case kPacketTypeSenderReport:
     37         if (!ParseSR(&chunk, header))
     38           return false;
     39         break;
     40 
     41       case kPacketTypeReceiverReport:
     42         if (!ParseRR(&chunk, header))
     43           return false;
     44         break;
     45 
     46       case kPacketTypeApplicationDefined:
     47         if (!ParseApplicationDefined(&chunk, header))
     48           return false;
     49         break;
     50 
     51       case kPacketTypePayloadSpecific:
     52         if (!ParseFeedbackCommon(&chunk, header))
     53           return false;
     54         break;
     55 
     56       case kPacketTypeXr:
     57         if (!ParseExtendedReport(&chunk, header))
     58           return false;
     59         break;
     60     }
     61   }
     62   return true;
     63 }
     64 
     65 bool RtcpParser::ParseCommonHeader(base::BigEndianReader* reader,
     66                                    RtcpCommonHeader* parsed_header) {
     67   //  0                   1                   2                   3
     68   //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     69   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     70   // |V=2|P|    IC   |      PT       |             length            |
     71   // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     72   //
     73   // Common header for all Rtcp packets, 4 octets.
     74 
     75   uint8 byte;
     76   if (!reader->ReadU8(&byte))
     77     return false;
     78   parsed_header->V = byte >> 6;
     79   parsed_header->P = ((byte & 0x20) == 0) ? false : true;
     80 
     81   // Check if RTP version field == 2.
     82   if (parsed_header->V != 2)
     83     return false;
     84 
     85   parsed_header->IC = byte & 0x1f;
     86   if (!reader->ReadU8(&parsed_header->PT))
     87     return false;
     88 
     89   uint16 bytes;
     90   if (!reader->ReadU16(&bytes))
     91     return false;
     92 
     93   parsed_header->length_in_octets = (static_cast<size_t>(bytes) + 1) * 4;
     94 
     95   if (parsed_header->length_in_octets == 0)
     96     return false;
     97 
     98   return true;
     99 }
    100 
    101 bool RtcpParser::ParseSR(base::BigEndianReader* reader,
    102                          const RtcpCommonHeader& header) {
    103   uint32 sender_ssrc;
    104   if (!reader->ReadU32(&sender_ssrc))
    105     return false;
    106 
    107   if (sender_ssrc != remote_ssrc_)
    108     return true;
    109 
    110   uint32 tmp;
    111   if (!reader->ReadU32(&sender_report_.ntp_seconds) ||
    112       !reader->ReadU32(&sender_report_.ntp_fraction) ||
    113       !reader->ReadU32(&sender_report_.rtp_timestamp) ||
    114       !reader->ReadU32(&sender_report_.send_packet_count) ||
    115       !reader->ReadU32(&tmp))
    116     return false;
    117   sender_report_.send_octet_count = tmp;
    118   has_sender_report_ = true;
    119 
    120   for (size_t block = 0; block < header.IC; block++)
    121     if (!ParseReportBlock(reader))
    122       return false;
    123 
    124   return true;
    125 }
    126 
    127 bool RtcpParser::ParseRR(base::BigEndianReader* reader,
    128                          const RtcpCommonHeader& header) {
    129   uint32 receiver_ssrc;
    130   if (!reader->ReadU32(&receiver_ssrc))
    131     return false;
    132 
    133   if (receiver_ssrc != remote_ssrc_)
    134     return true;
    135 
    136   for (size_t block = 0; block < header.IC; block++)
    137     if (!ParseReportBlock(reader))
    138       return false;
    139 
    140   return true;
    141 }
    142 
    143 bool RtcpParser::ParseReportBlock(base::BigEndianReader* reader) {
    144   uint32 ssrc, last_report, delay;
    145   if (!reader->ReadU32(&ssrc) ||
    146       !reader->Skip(12) ||
    147       !reader->ReadU32(&last_report) ||
    148       !reader->ReadU32(&delay))
    149     return false;
    150 
    151   if (ssrc == local_ssrc_) {
    152     last_report_ = last_report;
    153     delay_since_last_report_ = delay;
    154     has_last_report_ = true;
    155   }
    156 
    157   return true;
    158 }
    159 
    160 bool RtcpParser::ParseApplicationDefined(base::BigEndianReader* reader,
    161                                          const RtcpCommonHeader& header) {
    162   uint32 sender_ssrc;
    163   uint32 name;
    164   if (!reader->ReadU32(&sender_ssrc) ||
    165       !reader->ReadU32(&name))
    166     return false;
    167 
    168   if (sender_ssrc != remote_ssrc_)
    169     return true;
    170 
    171   if (name != kCast)
    172     return false;
    173 
    174   switch (header.IC /* subtype */ ) {
    175     case kReceiverLogSubtype:
    176       if (!ParseCastReceiverLogFrameItem(reader))
    177         return false;
    178       break;
    179   }
    180   return true;
    181 }
    182 
    183 bool RtcpParser::ParseCastReceiverLogFrameItem(
    184     base::BigEndianReader* reader) {
    185 
    186   while (reader->remaining()) {
    187     uint32 rtp_timestamp;
    188     uint32 data;
    189     if (!reader->ReadU32(&rtp_timestamp) ||
    190         !reader->ReadU32(&data))
    191       return false;
    192 
    193     // We have 24 LSB of the event timestamp base on the wire.
    194     base::TimeTicks event_timestamp_base = base::TimeTicks() +
    195         base::TimeDelta::FromMilliseconds(data & 0xffffff);
    196 
    197     size_t num_events = 1 + static_cast<uint8>(data >> 24);
    198 
    199     RtcpReceiverFrameLogMessage frame_log(rtp_timestamp);
    200     for (size_t event = 0; event < num_events; event++) {
    201       uint16 delay_delta_or_packet_id;
    202       uint16 event_type_and_timestamp_delta;
    203       if (!reader->ReadU16(&delay_delta_or_packet_id) ||
    204           !reader->ReadU16(&event_type_and_timestamp_delta))
    205         return false;
    206 
    207       RtcpReceiverEventLogMessage event_log;
    208       event_log.type = TranslateToLogEventFromWireFormat(
    209           static_cast<uint8>(event_type_and_timestamp_delta >> 12));
    210       event_log.event_timestamp =
    211           event_timestamp_base +
    212           base::TimeDelta::FromMilliseconds(
    213               event_type_and_timestamp_delta & 0xfff);
    214       if (event_log.type == PACKET_RECEIVED) {
    215         event_log.packet_id = delay_delta_or_packet_id;
    216       } else {
    217         event_log.delay_delta = base::TimeDelta::FromMilliseconds(
    218             static_cast<int16>(delay_delta_or_packet_id));
    219       }
    220       frame_log.event_log_messages_.push_back(event_log);
    221     }
    222 
    223     receiver_log_.push_back(frame_log);
    224   }
    225 
    226   return true;
    227 }
    228 
    229 // RFC 4585.
    230 bool RtcpParser::ParseFeedbackCommon(base::BigEndianReader* reader,
    231                                      const RtcpCommonHeader& header) {
    232   // See RTC 4585 Section 6.4 for application specific feedback messages.
    233   if (header.IC != 15) {
    234     return true;
    235   }
    236   uint32 remote_ssrc;
    237   uint32 media_ssrc;
    238   if (!reader->ReadU32(&remote_ssrc) ||
    239       !reader->ReadU32(&media_ssrc))
    240     return false;
    241 
    242   if (remote_ssrc != remote_ssrc_)
    243     return true;
    244 
    245   uint32 name;
    246   if (!reader->ReadU32(&name))
    247     return false;
    248 
    249   if (name != kCast) {
    250     return true;
    251   }
    252 
    253   cast_message_.media_ssrc = remote_ssrc;
    254 
    255   uint8 last_frame_id;
    256   uint8 number_of_lost_fields;
    257   if (!reader->ReadU8(&last_frame_id) ||
    258       !reader->ReadU8(&number_of_lost_fields) ||
    259       !reader->ReadU16(&cast_message_.target_delay_ms))
    260     return false;
    261 
    262   // Please note, this frame_id is still only 8-bit!
    263   cast_message_.ack_frame_id = last_frame_id;
    264 
    265   for (size_t i = 0; i < number_of_lost_fields; i++) {
    266     uint8 frame_id;
    267     uint16 packet_id;
    268     uint8 bitmask;
    269     if (!reader->ReadU8(&frame_id) ||
    270         !reader->ReadU16(&packet_id) ||
    271         !reader->ReadU8(&bitmask))
    272       return false;
    273     cast_message_.missing_frames_and_packets[frame_id].insert(packet_id);
    274     if (packet_id != kRtcpCastAllPacketsLost) {
    275       while (bitmask) {
    276         packet_id++;
    277         if (bitmask & 1)
    278           cast_message_.missing_frames_and_packets[frame_id].insert(packet_id);
    279         bitmask >>= 1;
    280       }
    281     }
    282   }
    283 
    284   has_cast_message_ = true;
    285   return true;
    286 }
    287 
    288 bool RtcpParser::ParseExtendedReport(base::BigEndianReader* reader,
    289                                      const RtcpCommonHeader& header) {
    290   uint32 remote_ssrc;
    291   if (!reader->ReadU32(&remote_ssrc))
    292     return false;
    293 
    294   // Is it for us?
    295   if (remote_ssrc != remote_ssrc_)
    296     return true;
    297 
    298   while (reader->remaining()) {
    299     uint8 block_type;
    300     uint16 block_length;
    301     if (!reader->ReadU8(&block_type) ||
    302         !reader->Skip(1) ||
    303         !reader->ReadU16(&block_length))
    304       return false;
    305 
    306     switch (block_type) {
    307       case 4:  // RRTR. RFC3611 Section 4.4.
    308         if (block_length != 2)
    309           return false;
    310         if (!ParseExtendedReportReceiverReferenceTimeReport(reader,
    311                                                             remote_ssrc))
    312           return false;
    313         break;
    314 
    315       default:
    316         // Skip unknown item.
    317         if (!reader->Skip(block_length * 4))
    318           return false;
    319     }
    320   }
    321 
    322   return true;
    323 }
    324 
    325 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport(
    326     base::BigEndianReader* reader,
    327     uint32 remote_ssrc) {
    328   receiver_reference_time_report_.remote_ssrc = remote_ssrc;
    329   if(!reader->ReadU32(&receiver_reference_time_report_.ntp_seconds) ||
    330      !reader->ReadU32(&receiver_reference_time_report_.ntp_fraction))
    331     return false;
    332 
    333   has_receiver_reference_time_report_ = true;
    334   return true;
    335 }
    336 
    337 // Converts a log event type to an integer value.
    338 // NOTE: We have only allocated 4 bits to represent the type of event over the
    339 // wire. Therefore, this function can only return values from 0 to 15.
    340 uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) {
    341   switch (event) {
    342     case FRAME_ACK_SENT:
    343       return 11;
    344     case FRAME_PLAYOUT:
    345       return 12;
    346     case FRAME_DECODED:
    347       return 13;
    348     case PACKET_RECEIVED:
    349       return 14;
    350     default:
    351       return 0;  // Not an interesting event.
    352   }
    353 }
    354 
    355 CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
    356   // TODO(imcheng): Remove the old mappings once they are no longer used.
    357   switch (event) {
    358     case 1:  // AudioAckSent
    359     case 5:  // VideoAckSent
    360     case 11:  // Unified
    361       return FRAME_ACK_SENT;
    362     case 2:  // AudioPlayoutDelay
    363     case 7:  // VideoRenderDelay
    364     case 12:  // Unified
    365       return FRAME_PLAYOUT;
    366     case 3:  // AudioFrameDecoded
    367     case 6:  // VideoFrameDecoded
    368     case 13:  // Unified
    369       return FRAME_DECODED;
    370     case 4:  // AudioPacketReceived
    371     case 8:  // VideoPacketReceived
    372     case 14:  // Unified
    373       return PACKET_RECEIVED;
    374     case 9:  // DuplicateAudioPacketReceived
    375     case 10:  // DuplicateVideoPacketReceived
    376     default:
    377       // If the sender adds new log messages we will end up here until we add
    378       // the new messages in the receiver.
    379       VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
    380       return UNKNOWN;
    381   }
    382 }
    383 
    384 }  // namespace cast
    385 }  // namespace media
    386