• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RtpParser(uint32 expected_sender_ssrc,uint8 expected_payload_type)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 
~RtpParser()25 RtpParser::~RtpParser() {}
26 
ParsePacket(const uint8 * packet,size_t length,RtpCastHeader * header,const uint8 ** payload_data,size_t * payload_size)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