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