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.
5 #include "media/cast/rtp_receiver/rtp_parser/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/rtp_receiver/rtp_receiver.h"
15 static const size_t kRtpHeaderLength
= 12;
16 static const size_t kCastHeaderLength
= 7;
17 static const uint8 kRtpExtensionBitMask
= 0x10;
18 static const uint8 kRtpMarkerBitMask
= 0x80;
19 static const uint8 kCastKeyFrameBitMask
= 0x80;
20 static const uint8 kCastReferenceFrameIdBitMask
= 0x40;
22 RtpParser::RtpParser(uint32 expected_sender_ssrc
, uint8 expected_payload_type
)
23 : expected_sender_ssrc_(expected_sender_ssrc
),
24 expected_payload_type_(expected_payload_type
) {}
26 RtpParser::~RtpParser() {}
28 bool RtpParser::ParsePacket(const uint8
* packet
,
30 RtpCastHeader
* header
,
31 const uint8
** payload_data
,
32 size_t* payload_size
) {
38 if (length
< (kRtpHeaderLength
+ kCastHeaderLength
))
41 base::BigEndianReader
reader(reinterpret_cast<const char*>(packet
), length
);
43 // Parse the RTP header. See
44 // http://en.wikipedia.org/wiki/Real-time_Transport_Protocol for an
45 // explanation of the standard RTP packet header.
47 if (!reader
.ReadU8(&bits
))
49 const uint8 version
= bits
>> 6;
52 if (bits
& kRtpExtensionBitMask
)
53 return false; // We lack the implementation to skip over an extension.
54 if (!reader
.ReadU8(&bits
))
56 header
->marker
= !!(bits
& kRtpMarkerBitMask
);
57 header
->payload_type
= bits
& ~kRtpMarkerBitMask
;
58 if (header
->payload_type
!= expected_payload_type_
)
59 return false; // Punt: Unexpected payload type.
60 if (!reader
.ReadU16(&header
->sequence_number
) ||
61 !reader
.ReadU32(&header
->rtp_timestamp
) ||
62 !reader
.ReadU32(&header
->sender_ssrc
)) {
65 if (header
->sender_ssrc
!= expected_sender_ssrc_
)
66 return false; // Punt: Sender's SSRC does not match the expected one.
68 // Parse the Cast header. Note that, from the RTP protocol's perspective, the
69 // Cast header is part of the payload (and not meant to be an extension
71 if (!reader
.ReadU8(&bits
))
73 header
->is_key_frame
= !!(bits
& kCastKeyFrameBitMask
);
74 const bool includes_specific_frame_reference
=
75 !!(bits
& kCastReferenceFrameIdBitMask
);
76 uint8 truncated_frame_id
;
77 if (!reader
.ReadU8(&truncated_frame_id
) ||
78 !reader
.ReadU16(&header
->packet_id
) ||
79 !reader
.ReadU16(&header
->max_packet_id
)) {
82 // Sanity-check: Do the packet ID values make sense w.r.t. each other?
83 if (header
->max_packet_id
< header
->packet_id
)
85 uint8 truncated_reference_frame_id
;
86 if (!includes_specific_frame_reference
) {
87 // By default, a key frame only references itself; and non-key frames
88 // reference their direct predecessor.
89 truncated_reference_frame_id
= truncated_frame_id
;
90 if (!header
->is_key_frame
)
91 --truncated_reference_frame_id
;
92 } else if (!reader
.ReadU8(&truncated_reference_frame_id
)) {
96 // Only the lower 8 bits of the |frame_id| were serialized, so do some magic
97 // to restore the upper 24 bits.
99 // Note: The call to |frame_id_wrap_helper_| has side effects, so we must not
100 // call it until we know the entire deserialization will succeed.
102 frame_id_wrap_helper_
.MapTo32bitsFrameId(truncated_frame_id
);
103 // When the upper 24 bits are restored to |reference_frame_id|, make sure
104 // |reference_frame_id| will be strictly less than or equal to |frame_id|.
105 if (truncated_reference_frame_id
<= truncated_frame_id
)
106 header
->reference_frame_id
= header
->frame_id
& 0xffffff00;
108 header
->reference_frame_id
= (header
->frame_id
& 0xffffff00) - 0x00000100;
109 header
->reference_frame_id
|= truncated_reference_frame_id
;
111 // All remaining data in the packet is the payload.
112 *payload_data
= reinterpret_cast<const uint8
*>(reader
.ptr());
113 *payload_size
= reader
.remaining();