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"
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;
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
) {}
25 RtpParser::~RtpParser() {}
27 bool RtpParser::ParsePacket(const uint8
* packet
,
29 RtpCastHeader
* header
,
30 const uint8
** payload_data
,
31 size_t* payload_size
) {
37 if (length
< (kRtpHeaderLength
+ kCastHeaderLength
))
40 base::BigEndianReader
reader(reinterpret_cast<const char*>(packet
), length
);
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.
46 if (!reader
.ReadU8(&bits
))
48 const uint8 version
= bits
>> 6;
51 if (bits
& kRtpExtensionBitMask
)
52 return false; // We lack the implementation to skip over an extension.
53 if (!reader
.ReadU8(&bits
))
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
)) {
64 if (header
->sender_ssrc
!= expected_sender_ssrc_
)
65 return false; // Punt: Sender's SSRC does not match the expected one.
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
70 if (!reader
.ReadU8(&bits
))
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
)) {
81 // Sanity-check: Do the packet ID values make sense w.r.t. each other?
82 if (header
->max_packet_id
< header
->packet_id
)
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
)) {
95 // Only the lower 8 bits of the |frame_id| were serialized, so do some magic
96 // to restore the upper 24 bits.
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.
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;
107 header
->reference_frame_id
= (header
->frame_id
& 0xffffff00) - 0x00000100;
108 header
->reference_frame_id
|= truncated_reference_frame_id
;
110 // All remaining data in the packet is the payload.
111 *payload_data
= reinterpret_cast<const uint8
*>(reader
.ptr());
112 *payload_size
= reader
.remaining();