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.
5 #include "media/cast/net/rtp/rtp_parser.h"
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"
16 bool RtpParser::ParseSsrc(const uint8
* packet
,
19 base::BigEndianReader
big_endian_reader(
20 reinterpret_cast<const char*>(packet
), length
);
21 return big_endian_reader
.Skip(8) && big_endian_reader
.ReadU32(ssrc
);
24 RtpParser::RtpParser(uint32 expected_sender_ssrc
, uint8 expected_payload_type
)
25 : expected_sender_ssrc_(expected_sender_ssrc
),
26 expected_payload_type_(expected_payload_type
) {}
28 RtpParser::~RtpParser() {}
30 bool RtpParser::ParsePacket(const uint8
* packet
,
32 RtpCastHeader
* header
,
33 const uint8
** payload_data
,
34 size_t* payload_size
) {
40 if (length
< (kRtpHeaderLength
+ kCastHeaderLength
))
43 base::BigEndianReader
reader(reinterpret_cast<const char*>(packet
), length
);
45 // Parse the RTP header. See
46 // http://en.wikipedia.org/wiki/Real-time_Transport_Protocol for an
47 // explanation of the standard RTP packet header.
49 if (!reader
.ReadU8(&bits
))
51 const uint8 version
= bits
>> 6;
54 if (bits
& kRtpExtensionBitMask
)
55 return false; // We lack the implementation to skip over an extension.
56 if (!reader
.ReadU8(&bits
))
58 header
->marker
= !!(bits
& kRtpMarkerBitMask
);
59 header
->payload_type
= bits
& ~kRtpMarkerBitMask
;
60 if (header
->payload_type
!= expected_payload_type_
)
61 return false; // Punt: Unexpected payload type.
62 if (!reader
.ReadU16(&header
->sequence_number
) ||
63 !reader
.ReadU32(&header
->rtp_timestamp
) ||
64 !reader
.ReadU32(&header
->sender_ssrc
)) {
67 if (header
->sender_ssrc
!= expected_sender_ssrc_
)
68 return false; // Punt: Sender's SSRC does not match the expected one.
70 // Parse the Cast header. Note that, from the RTP protocol's perspective, the
71 // Cast header is part of the payload (and not meant to be an extension
73 if (!reader
.ReadU8(&bits
))
75 header
->is_key_frame
= !!(bits
& kCastKeyFrameBitMask
);
76 const bool includes_specific_frame_reference
=
77 !!(bits
& kCastReferenceFrameIdBitMask
);
78 uint8 truncated_frame_id
;
79 if (!reader
.ReadU8(&truncated_frame_id
) ||
80 !reader
.ReadU16(&header
->packet_id
) ||
81 !reader
.ReadU16(&header
->max_packet_id
)) {
84 // Sanity-check: Do the packet ID values make sense w.r.t. each other?
85 if (header
->max_packet_id
< header
->packet_id
)
87 uint8 truncated_reference_frame_id
;
88 if (!includes_specific_frame_reference
) {
89 // By default, a key frame only references itself; and non-key frames
90 // reference their direct predecessor.
91 truncated_reference_frame_id
= truncated_frame_id
;
92 if (!header
->is_key_frame
)
93 --truncated_reference_frame_id
;
94 } else if (!reader
.ReadU8(&truncated_reference_frame_id
)) {
98 for (int i
= 0; i
< (bits
& kCastExtensionCountmask
); i
++) {
100 if (!reader
.ReadU16(&type_and_size
))
102 base::StringPiece tmp
;
103 if (!reader
.ReadPiece(&tmp
, type_and_size
& 0x3ff))
105 base::BigEndianReader
chunk(tmp
.data(), tmp
.size());
106 switch (type_and_size
>> 10) {
107 case kCastRtpExtensionAdaptiveLatency
:
108 if (!chunk
.ReadU16(&header
->new_playout_delay_ms
))
114 // Only the lower 8 bits of the |frame_id| were serialized, so do some magic
115 // to restore the upper 24 bits.
117 // Note: The call to |frame_id_wrap_helper_| has side effects, so we must not
118 // call it until we know the entire deserialization will succeed.
120 frame_id_wrap_helper_
.MapTo32bitsFrameId(truncated_frame_id
);
121 // When the upper 24 bits are restored to |reference_frame_id|, make sure
122 // |reference_frame_id| will be strictly less than or equal to |frame_id|.
123 if (truncated_reference_frame_id
<= truncated_frame_id
)
124 header
->reference_frame_id
= header
->frame_id
& 0xffffff00;
126 header
->reference_frame_id
= (header
->frame_id
& 0xffffff00) - 0x00000100;
127 header
->reference_frame_id
|= truncated_reference_frame_id
;
129 // All remaining data in the packet is the payload.
130 *payload_data
= reinterpret_cast<const uint8
*>(reader
.ptr());
131 *payload_size
= reader
.remaining();