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