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