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 |