Home | History | Annotate | Download | only in rtp
      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/rtp/rtp_parser.h"
      6 
      7 #include "base/big_endian.h"
      8 #include "base/logging.h"
      9 #include "media/cast/cast_defines.h"
     10 #include "media/cast/net/rtp/rtp_defines.h"
     11 
     12 namespace media {
     13 namespace cast {
     14 
     15 RtpParser::RtpParser(uint32 expected_sender_ssrc, uint8 expected_payload_type)
     16     : expected_sender_ssrc_(expected_sender_ssrc),
     17       expected_payload_type_(expected_payload_type) {}
     18 
     19 RtpParser::~RtpParser() {}
     20 
     21 bool RtpParser::ParsePacket(const uint8* packet,
     22                             size_t length,
     23                             RtpCastHeader* header,
     24                             const uint8** payload_data,
     25                             size_t* payload_size) {
     26   DCHECK(packet);
     27   DCHECK(header);
     28   DCHECK(payload_data);
     29   DCHECK(payload_size);
     30 
     31   if (length < (kRtpHeaderLength + kCastHeaderLength))
     32     return false;
     33 
     34   base::BigEndianReader reader(reinterpret_cast<const char*>(packet), length);
     35 
     36   // Parse the RTP header.  See
     37   // http://en.wikipedia.org/wiki/Real-time_Transport_Protocol for an
     38   // explanation of the standard RTP packet header.
     39   uint8 bits;
     40   if (!reader.ReadU8(&bits))
     41     return false;
     42   const uint8 version = bits >> 6;
     43   if (version != 2)
     44     return false;
     45   if (bits & kRtpExtensionBitMask)
     46     return false;  // We lack the implementation to skip over an extension.
     47   if (!reader.ReadU8(&bits))
     48     return false;
     49   header->marker = !!(bits & kRtpMarkerBitMask);
     50   header->payload_type = bits & ~kRtpMarkerBitMask;
     51   if (header->payload_type != expected_payload_type_)
     52     return false;  // Punt: Unexpected payload type.
     53   if (!reader.ReadU16(&header->sequence_number) ||
     54       !reader.ReadU32(&header->rtp_timestamp) ||
     55       !reader.ReadU32(&header->sender_ssrc)) {
     56     return false;
     57   }
     58   if (header->sender_ssrc != expected_sender_ssrc_)
     59     return false;  // Punt: Sender's SSRC does not match the expected one.
     60 
     61   // Parse the Cast header.  Note that, from the RTP protocol's perspective, the
     62   // Cast header is part of the payload (and not meant to be an extension
     63   // header).
     64   if (!reader.ReadU8(&bits))
     65     return false;
     66   header->is_key_frame = !!(bits & kCastKeyFrameBitMask);
     67   const bool includes_specific_frame_reference =
     68       !!(bits & kCastReferenceFrameIdBitMask);
     69   uint8 truncated_frame_id;
     70   if (!reader.ReadU8(&truncated_frame_id) ||
     71       !reader.ReadU16(&header->packet_id) ||
     72       !reader.ReadU16(&header->max_packet_id)) {
     73     return false;
     74   }
     75   // Sanity-check: Do the packet ID values make sense w.r.t. each other?
     76   if (header->max_packet_id < header->packet_id)
     77     return false;
     78   uint8 truncated_reference_frame_id;
     79   if (!includes_specific_frame_reference) {
     80     // By default, a key frame only references itself; and non-key frames
     81     // reference their direct predecessor.
     82     truncated_reference_frame_id = truncated_frame_id;
     83     if (!header->is_key_frame)
     84       --truncated_reference_frame_id;
     85   } else if (!reader.ReadU8(&truncated_reference_frame_id)) {
     86     return false;
     87   }
     88 
     89   for (int i = 0; i < (bits & kCastExtensionCountmask); i++) {
     90     uint16 type_and_size;
     91     if (!reader.ReadU16(&type_and_size))
     92       return false;
     93     base::StringPiece tmp;
     94     if (!reader.ReadPiece(&tmp, type_and_size & 0x3ff))
     95       return false;
     96     base::BigEndianReader chunk(tmp.data(), tmp.size());
     97     switch (type_and_size >> 10) {
     98       case kCastRtpExtensionAdaptiveLatency:
     99         if (!chunk.ReadU16(&header->new_playout_delay_ms))
    100           return false;
    101 
    102     }
    103   }
    104 
    105   // Only the lower 8 bits of the |frame_id| were serialized, so do some magic
    106   // to restore the upper 24 bits.
    107   //
    108   // Note: The call to |frame_id_wrap_helper_| has side effects, so we must not
    109   // call it until we know the entire deserialization will succeed.
    110   header->frame_id =
    111       frame_id_wrap_helper_.MapTo32bitsFrameId(truncated_frame_id);
    112   // When the upper 24 bits are restored to |reference_frame_id|, make sure
    113   // |reference_frame_id| will be strictly less than or equal to |frame_id|.
    114   if (truncated_reference_frame_id <= truncated_frame_id)
    115     header->reference_frame_id = header->frame_id & 0xffffff00;
    116   else
    117     header->reference_frame_id = (header->frame_id & 0xffffff00) - 0x00000100;
    118   header->reference_frame_id |= truncated_reference_frame_id;
    119 
    120   // All remaining data in the packet is the payload.
    121   *payload_data = reinterpret_cast<const uint8*>(reader.ptr());
    122   *payload_size = reader.remaining();
    123 
    124   return true;
    125 }
    126 
    127 }  // namespace cast
    128 }  // namespace media
    129