| OLD | NEW |
| (Empty) |
| 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 | |
| OLD | NEW |