Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: media/cast/rtp_receiver/rtp_parser/rtp_parser.cc

Issue 250363002: [Cast] Clean-up RtpCastHeader and RtpParser, removing the last WebRTC dependency. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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/rtp_receiver/rtp_parser/rtp_parser.h" 5 #include "media/cast/rtp_receiver/rtp_parser/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/cast_defines.h" 9 #include "media/cast/cast_defines.h"
10 #include "media/cast/rtp_receiver/rtp_receiver.h" 10 #include "media/cast/rtp_receiver/rtp_receiver.h"
11 11
12 namespace media { 12 namespace media {
13 namespace cast { 13 namespace cast {
14 14
15 static const size_t kRtpCommonHeaderLength = 12; 15 static const size_t kRtpHeaderLength = 12;
16 static const size_t kRtpCastHeaderLength = 7; 16 static const size_t kCastHeaderLength = 7;
17 static const uint8 kRtpExtensionBitMask = 0x10;
18 static const uint8 kRtpMarkerBitMask = 0x80;
17 static const uint8 kCastKeyFrameBitMask = 0x80; 19 static const uint8 kCastKeyFrameBitMask = 0x80;
18 static const uint8 kCastReferenceFrameIdBitMask = 0x40; 20 static const uint8 kCastReferenceFrameIdBitMask = 0x40;
19 21
20 RtpParser::RtpParser(const RtpParserConfig parser_config) 22 RtpParser::RtpParser(uint32 expected_sender_ssrc, uint8 expected_payload_type)
21 : parser_config_(parser_config) {} 23 : expected_sender_ssrc_(expected_sender_ssrc),
24 expected_payload_type_(expected_payload_type) {}
22 25
23 RtpParser::~RtpParser() {} 26 RtpParser::~RtpParser() {}
24 27
25 bool RtpParser::ParsePacket(const uint8* packet, 28 bool RtpParser::ParsePacket(const uint8* packet,
miu 2014/04/23 23:41:58 I consolidated all the ParseXXX() methods into one
26 size_t length, 29 size_t length,
27 RtpCastHeader* rtp_header) { 30 RtpCastHeader* header,
28 if (length == 0) 31 const uint8** payload_data,
32 size_t* payload_size) {
33 DCHECK(packet);
34 DCHECK(header);
35 DCHECK(payload_data);
36 DCHECK(payload_size);
37
38 if (length < (kRtpHeaderLength + kCastHeaderLength))
29 return false; 39 return false;
30 // Get RTP general header. 40
31 if (!ParseCommon(packet, length, rtp_header)) 41 base::BigEndianReader reader(reinterpret_cast<const char*>(packet), length);
42
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.
46 uint8 bits;
47 if (!reader.ReadU8(&bits))
32 return false; 48 return false;
33 if (rtp_header->webrtc.header.payloadType == parser_config_.payload_type && 49 const uint8 version = bits >> 6;
34 rtp_header->webrtc.header.ssrc == parser_config_.ssrc) {
35 return ParseCast(packet + kRtpCommonHeaderLength,
36 length - kRtpCommonHeaderLength,
37 rtp_header);
38 }
39 // Not a valid payload type / ssrc combination.
40 return false;
41 }
42
43 bool RtpParser::ParseCommon(const uint8* packet,
44 size_t length,
45 RtpCastHeader* rtp_header) {
46 if (length < kRtpCommonHeaderLength)
47 return false;
48 uint8 version = packet[0] >> 6;
49 if (version != 2) 50 if (version != 2)
50 return false; 51 return false;
51 uint8 cc = packet[0] & 0x0f; 52 if (bits & kRtpExtensionBitMask)
52 bool marker = ((packet[1] & 0x80) != 0); 53 return false; // We lack the implementation to skip over an extension.
53 int payload_type = packet[1] & 0x7f; 54 if (!reader.ReadU8(&bits))
55 return false;
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)) {
63 return false;
64 }
65 if (header->sender_ssrc != expected_sender_ssrc_)
66 return false; // Punt: Sender's SSRC does not match the expected one.
54 67
55 uint16 sequence_number; 68 // Parse the Cast header. Note that, from the RTP protocol's perspective, the
56 uint32 rtp_timestamp, ssrc; 69 // Cast header is part of the payload (and not meant to be an extension
57 base::BigEndianReader big_endian_reader( 70 // header).
58 reinterpret_cast<const char*>(packet + 2), 10); 71 if (!reader.ReadU8(&bits))
59 big_endian_reader.ReadU16(&sequence_number); 72 return false;
60 big_endian_reader.ReadU32(&rtp_timestamp); 73 header->is_key_frame = !!(bits & kCastKeyFrameBitMask);
61 big_endian_reader.ReadU32(&ssrc); 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)) {
80 return false;
81 }
82 // Sanity-check: Do the packet ID values make sense w.r.t. each other?
83 if (header->max_packet_id < header->packet_id)
84 return false;
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)) {
93 return false;
94 }
62 95
63 if (ssrc != parser_config_.ssrc) 96 // Only the lower 8 bits of the |frame_id| were serialized, so do some magic
64 return false; 97 // to restore the upper 24 bits.
98 //
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.
101 header->frame_id =
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;
107 else
108 header->reference_frame_id = (header->frame_id & 0xffffff00) - 0x00000100;
109 header->reference_frame_id |= truncated_reference_frame_id;
65 110
66 rtp_header->webrtc.header.markerBit = marker; 111 // All remaining data in the packet is the payload.
67 rtp_header->webrtc.header.payloadType = payload_type; 112 *payload_data = reinterpret_cast<const uint8*>(reader.ptr());
68 rtp_header->webrtc.header.sequenceNumber = sequence_number; 113 *payload_size = reader.remaining();
69 rtp_header->webrtc.header.timestamp = rtp_timestamp;
70 rtp_header->webrtc.header.ssrc = ssrc;
71 rtp_header->webrtc.header.numCSRCs = cc;
72 114
73 uint8 csrc_octs = cc * 4;
74 rtp_header->webrtc.type.Audio.numEnergy = rtp_header->webrtc.header.numCSRCs;
75 rtp_header->webrtc.header.headerLength = kRtpCommonHeaderLength + csrc_octs;
76 rtp_header->webrtc.type.Audio.isCNG = false;
77 rtp_header->webrtc.type.Audio.channel = parser_config_.audio_channels;
78 // TODO(pwestin): look at x bit and skip data.
79 return true; 115 return true;
80 } 116 }
81 117
82 bool RtpParser::ParseCast(const uint8* packet,
83 size_t length,
84 RtpCastHeader* rtp_header) {
85 if (length < kRtpCastHeaderLength)
86 return false;
87
88 // Extract header.
89 const uint8* data_ptr = packet;
90 size_t data_length = length;
91 rtp_header->is_key_frame = !!(data_ptr[0] & kCastKeyFrameBitMask);
92 rtp_header->is_reference = !!(data_ptr[0] & kCastReferenceFrameIdBitMask);
93 rtp_header->frame_id = frame_id_wrap_helper_.MapTo32bitsFrameId(data_ptr[1]);
94
95 base::BigEndianReader big_endian_reader(
96 reinterpret_cast<const char*>(data_ptr + 2), 4);
97 big_endian_reader.ReadU16(&rtp_header->packet_id);
98 big_endian_reader.ReadU16(&rtp_header->max_packet_id);
99
100 if (rtp_header->is_reference) {
101 rtp_header->reference_frame_id =
102 reference_frame_id_wrap_helper_.MapTo32bitsFrameId(data_ptr[6]);
103 data_ptr += kRtpCastHeaderLength;
104 data_length -= kRtpCastHeaderLength;
105 } else {
106 data_ptr += kRtpCastHeaderLength - 1;
107 data_length -= kRtpCastHeaderLength - 1;
108 }
109
110 if (rtp_header->max_packet_id < rtp_header->packet_id)
111 return false;
112
113 OnReceivedPayloadData(data_ptr, data_length, *rtp_header);
114 return true;
115 }
116
117 } // namespace cast 118 } // namespace cast
118 } // namespace media 119 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698