Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / cast / net / rtp / rtp_parser.cc
blobbb6c2c0ebd8224f5f7fc8fd5b3bcf4a61e076fd8
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"
12 namespace media {
13 namespace cast {
15 // static
16 bool RtpParser::ParseSsrc(const uint8* packet,
17 size_t length,
18 uint32* ssrc) {
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,
31 size_t length,
32 RtpCastHeader* header,
33 const uint8** payload_data,
34 size_t* payload_size) {
35 DCHECK(packet);
36 DCHECK(header);
37 DCHECK(payload_data);
38 DCHECK(payload_size);
40 if (length < (kRtpHeaderLength + kCastHeaderLength))
41 return false;
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.
48 uint8 bits;
49 if (!reader.ReadU8(&bits))
50 return false;
51 const uint8 version = bits >> 6;
52 if (version != 2)
53 return false;
54 if (bits & kRtpExtensionBitMask)
55 return false; // We lack the implementation to skip over an extension.
56 if (!reader.ReadU8(&bits))
57 return false;
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)) {
65 return false;
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
72 // header).
73 if (!reader.ReadU8(&bits))
74 return false;
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)) {
82 return false;
84 // Sanity-check: Do the packet ID values make sense w.r.t. each other?
85 if (header->max_packet_id < header->packet_id)
86 return false;
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)) {
95 return false;
98 for (int i = 0; i < (bits & kCastExtensionCountmask); i++) {
99 uint16 type_and_size;
100 if (!reader.ReadU16(&type_and_size))
101 return false;
102 base::StringPiece tmp;
103 if (!reader.ReadPiece(&tmp, type_and_size & 0x3ff))
104 return false;
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))
109 return false;
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.
119 header->frame_id =
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;
125 else
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();
133 return true;
136 } // namespace cast
137 } // namespace media