OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/net/rtp/rtp_parser.h" | 5 #include "media/cast/net/rtp/rtp_parser.h" |
6 | 6 |
7 #include "base/big_endian.h" | 7 #include "base/big_endian.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "media/cast/constants.h" | 9 #include "media/cast/constants.h" |
10 #include "media/cast/net/rtp/rtp_defines.h" | 10 #include "media/cast/net/rtp/rtp_defines.h" |
11 | 11 |
12 namespace media { | 12 namespace media { |
13 namespace cast { | 13 namespace cast { |
14 | 14 |
15 // static | 15 // static |
16 bool RtpParser::ParseSsrc(const uint8* packet, | 16 bool RtpParser::ParseSsrc(const uint8_t* packet, |
17 size_t length, | 17 size_t length, |
18 uint32* ssrc) { | 18 uint32_t* ssrc) { |
19 base::BigEndianReader big_endian_reader( | 19 base::BigEndianReader big_endian_reader( |
20 reinterpret_cast<const char*>(packet), length); | 20 reinterpret_cast<const char*>(packet), length); |
21 return big_endian_reader.Skip(8) && big_endian_reader.ReadU32(ssrc); | 21 return big_endian_reader.Skip(8) && big_endian_reader.ReadU32(ssrc); |
22 } | 22 } |
23 | 23 |
24 RtpParser::RtpParser(uint32 expected_sender_ssrc, uint8 expected_payload_type) | 24 RtpParser::RtpParser(uint32_t expected_sender_ssrc, |
| 25 uint8_t expected_payload_type) |
25 : expected_sender_ssrc_(expected_sender_ssrc), | 26 : expected_sender_ssrc_(expected_sender_ssrc), |
26 expected_payload_type_(expected_payload_type), | 27 expected_payload_type_(expected_payload_type), |
27 frame_id_wrap_helper_(kFirstFrameId - 1) {} | 28 frame_id_wrap_helper_(kFirstFrameId - 1) {} |
28 | 29 |
29 RtpParser::~RtpParser() {} | 30 RtpParser::~RtpParser() {} |
30 | 31 |
31 bool RtpParser::ParsePacket(const uint8* packet, | 32 bool RtpParser::ParsePacket(const uint8_t* packet, |
32 size_t length, | 33 size_t length, |
33 RtpCastHeader* header, | 34 RtpCastHeader* header, |
34 const uint8** payload_data, | 35 const uint8_t** payload_data, |
35 size_t* payload_size) { | 36 size_t* payload_size) { |
36 DCHECK(packet); | 37 DCHECK(packet); |
37 DCHECK(header); | 38 DCHECK(header); |
38 DCHECK(payload_data); | 39 DCHECK(payload_data); |
39 DCHECK(payload_size); | 40 DCHECK(payload_size); |
40 | 41 |
41 if (length < (kRtpHeaderLength + kCastHeaderLength)) | 42 if (length < (kRtpHeaderLength + kCastHeaderLength)) |
42 return false; | 43 return false; |
43 | 44 |
44 base::BigEndianReader reader(reinterpret_cast<const char*>(packet), length); | 45 base::BigEndianReader reader(reinterpret_cast<const char*>(packet), length); |
45 | 46 |
46 // Parse the RTP header. See | 47 // Parse the RTP header. See |
47 // http://en.wikipedia.org/wiki/Real-time_Transport_Protocol for an | 48 // http://en.wikipedia.org/wiki/Real-time_Transport_Protocol for an |
48 // explanation of the standard RTP packet header. | 49 // explanation of the standard RTP packet header. |
49 uint8 bits; | 50 uint8_t bits; |
50 if (!reader.ReadU8(&bits)) | 51 if (!reader.ReadU8(&bits)) |
51 return false; | 52 return false; |
52 const uint8 version = bits >> 6; | 53 const uint8_t version = bits >> 6; |
53 if (version != 2) | 54 if (version != 2) |
54 return false; | 55 return false; |
55 header->num_csrcs = bits & kRtpNumCsrcsMask; | 56 header->num_csrcs = bits & kRtpNumCsrcsMask; |
56 if (bits & kRtpExtensionBitMask) | 57 if (bits & kRtpExtensionBitMask) |
57 return false; // We lack the implementation to skip over an extension. | 58 return false; // We lack the implementation to skip over an extension. |
58 if (!reader.ReadU8(&bits)) | 59 if (!reader.ReadU8(&bits)) |
59 return false; | 60 return false; |
60 header->marker = !!(bits & kRtpMarkerBitMask); | 61 header->marker = !!(bits & kRtpMarkerBitMask); |
61 header->payload_type = bits & ~kRtpMarkerBitMask; | 62 header->payload_type = bits & ~kRtpMarkerBitMask; |
62 if (header->payload_type != expected_payload_type_) | 63 if (header->payload_type != expected_payload_type_) |
63 return false; // Punt: Unexpected payload type. | 64 return false; // Punt: Unexpected payload type. |
64 if (!reader.ReadU16(&header->sequence_number) || | 65 if (!reader.ReadU16(&header->sequence_number) || |
65 !reader.ReadU32(&header->rtp_timestamp) || | 66 !reader.ReadU32(&header->rtp_timestamp) || |
66 !reader.ReadU32(&header->sender_ssrc)) { | 67 !reader.ReadU32(&header->sender_ssrc)) { |
67 return false; | 68 return false; |
68 } | 69 } |
69 if (header->sender_ssrc != expected_sender_ssrc_) | 70 if (header->sender_ssrc != expected_sender_ssrc_) |
70 return false; // Punt: Sender's SSRC does not match the expected one. | 71 return false; // Punt: Sender's SSRC does not match the expected one. |
71 | 72 |
72 // Parse the Cast header. Note that, from the RTP protocol's perspective, the | 73 // Parse the Cast header. Note that, from the RTP protocol's perspective, the |
73 // Cast header is part of the payload (and not meant to be an extension | 74 // Cast header is part of the payload (and not meant to be an extension |
74 // header). | 75 // header). |
75 if (!reader.ReadU8(&bits)) | 76 if (!reader.ReadU8(&bits)) |
76 return false; | 77 return false; |
77 header->is_key_frame = !!(bits & kCastKeyFrameBitMask); | 78 header->is_key_frame = !!(bits & kCastKeyFrameBitMask); |
78 header->is_reference = !!(bits & kCastReferenceFrameIdBitMask); | 79 header->is_reference = !!(bits & kCastReferenceFrameIdBitMask); |
79 uint8 truncated_frame_id; | 80 uint8_t truncated_frame_id; |
80 if (!reader.ReadU8(&truncated_frame_id) || | 81 if (!reader.ReadU8(&truncated_frame_id) || |
81 !reader.ReadU16(&header->packet_id) || | 82 !reader.ReadU16(&header->packet_id) || |
82 !reader.ReadU16(&header->max_packet_id)) { | 83 !reader.ReadU16(&header->max_packet_id)) { |
83 return false; | 84 return false; |
84 } | 85 } |
85 // Sanity-check: Do the packet ID values make sense w.r.t. each other? | 86 // Sanity-check: Do the packet ID values make sense w.r.t. each other? |
86 if (header->max_packet_id < header->packet_id) | 87 if (header->max_packet_id < header->packet_id) |
87 return false; | 88 return false; |
88 uint8 truncated_reference_frame_id; | 89 uint8_t truncated_reference_frame_id; |
89 if (!header->is_reference) { | 90 if (!header->is_reference) { |
90 // By default, a key frame only references itself; and non-key frames | 91 // By default, a key frame only references itself; and non-key frames |
91 // reference their direct predecessor. | 92 // reference their direct predecessor. |
92 truncated_reference_frame_id = truncated_frame_id; | 93 truncated_reference_frame_id = truncated_frame_id; |
93 if (!header->is_key_frame) | 94 if (!header->is_key_frame) |
94 --truncated_reference_frame_id; | 95 --truncated_reference_frame_id; |
95 } else if (!reader.ReadU8(&truncated_reference_frame_id)) { | 96 } else if (!reader.ReadU8(&truncated_reference_frame_id)) { |
96 return false; | 97 return false; |
97 } | 98 } |
98 | 99 |
99 header->num_extensions = bits & kCastExtensionCountmask; | 100 header->num_extensions = bits & kCastExtensionCountmask; |
100 for (int i = 0; i < header->num_extensions; i++) { | 101 for (int i = 0; i < header->num_extensions; i++) { |
101 uint16 type_and_size; | 102 uint16_t type_and_size; |
102 if (!reader.ReadU16(&type_and_size)) | 103 if (!reader.ReadU16(&type_and_size)) |
103 return false; | 104 return false; |
104 base::StringPiece tmp; | 105 base::StringPiece tmp; |
105 if (!reader.ReadPiece(&tmp, type_and_size & 0x3ff)) | 106 if (!reader.ReadPiece(&tmp, type_and_size & 0x3ff)) |
106 return false; | 107 return false; |
107 base::BigEndianReader chunk(tmp.data(), tmp.size()); | 108 base::BigEndianReader chunk(tmp.data(), tmp.size()); |
108 switch (type_and_size >> 10) { | 109 switch (type_and_size >> 10) { |
109 case kCastRtpExtensionAdaptiveLatency: | 110 case kCastRtpExtensionAdaptiveLatency: |
110 if (!chunk.ReadU16(&header->new_playout_delay_ms)) | 111 if (!chunk.ReadU16(&header->new_playout_delay_ms)) |
111 return false; | 112 return false; |
112 } | 113 } |
113 } | 114 } |
114 | 115 |
115 // Only the lower 8 bits of the |frame_id| were serialized, so do some magic | 116 // Only the lower 8 bits of the |frame_id| were serialized, so do some magic |
116 // to restore the upper 24 bits. | 117 // to restore the upper 24 bits. |
117 // | 118 // |
118 // Note: The call to |frame_id_wrap_helper_| has side effects, so we must not | 119 // Note: The call to |frame_id_wrap_helper_| has side effects, so we must not |
119 // call it until we know the entire deserialization will succeed. | 120 // call it until we know the entire deserialization will succeed. |
120 header->frame_id = | 121 header->frame_id = |
121 frame_id_wrap_helper_.MapTo32bitsFrameId(truncated_frame_id); | 122 frame_id_wrap_helper_.MapTo32bitsFrameId(truncated_frame_id); |
122 // When the upper 24 bits are restored to |reference_frame_id|, make sure | 123 // When the upper 24 bits are restored to |reference_frame_id|, make sure |
123 // |reference_frame_id| will be strictly less than or equal to |frame_id|. | 124 // |reference_frame_id| will be strictly less than or equal to |frame_id|. |
124 if (truncated_reference_frame_id <= truncated_frame_id) | 125 if (truncated_reference_frame_id <= truncated_frame_id) |
125 header->reference_frame_id = header->frame_id & 0xffffff00; | 126 header->reference_frame_id = header->frame_id & 0xffffff00; |
126 else | 127 else |
127 header->reference_frame_id = (header->frame_id & 0xffffff00) - 0x00000100; | 128 header->reference_frame_id = (header->frame_id & 0xffffff00) - 0x00000100; |
128 header->reference_frame_id |= truncated_reference_frame_id; | 129 header->reference_frame_id |= truncated_reference_frame_id; |
129 | 130 |
130 // All remaining data in the packet is the payload. | 131 // All remaining data in the packet is the payload. |
131 *payload_data = reinterpret_cast<const uint8*>(reader.ptr()); | 132 *payload_data = reinterpret_cast<const uint8_t*>(reader.ptr()); |
132 *payload_size = reader.remaining(); | 133 *payload_size = reader.remaining(); |
133 | 134 |
134 return true; | 135 return true; |
135 } | 136 } |
136 | 137 |
137 } // namespace cast | 138 } // namespace cast |
138 } // namespace media | 139 } // namespace media |
OLD | NEW |