Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / cast / net / rtcp / rtcp_utility.cc
blob3cfb8ea704bb53697f4b5e1c9e1f987e9b442f42
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/rtcp/rtcp_utility.h"
7 #include "base/logging.h"
8 #include "media/cast/net/cast_transport_defines.h"
10 namespace media {
11 namespace cast {
13 RtcpParser::RtcpParser(uint32 local_ssrc, uint32 remote_ssrc) :
14 local_ssrc_(local_ssrc),
15 remote_ssrc_(remote_ssrc),
16 has_sender_report_(false),
17 has_last_report_(false),
18 has_cast_message_(false),
19 has_receiver_reference_time_report_(false) {
22 RtcpParser::~RtcpParser() {}
24 bool RtcpParser::Parse(base::BigEndianReader* reader) {
25 while (reader->remaining()) {
26 RtcpCommonHeader header;
27 if (!ParseCommonHeader(reader, &header))
28 return false;
30 base::StringPiece tmp;
31 if (!reader->ReadPiece(&tmp, header.length_in_octets - 4))
32 return false;
33 base::BigEndianReader chunk(tmp.data(), tmp.size());
35 switch (header.PT) {
36 case kPacketTypeSenderReport:
37 if (!ParseSR(&chunk, header))
38 return false;
39 break;
41 case kPacketTypeReceiverReport:
42 if (!ParseRR(&chunk, header))
43 return false;
44 break;
46 case kPacketTypeApplicationDefined:
47 if (!ParseApplicationDefined(&chunk, header))
48 return false;
49 break;
51 case kPacketTypePayloadSpecific:
52 if (!ParseFeedbackCommon(&chunk, header))
53 return false;
54 break;
56 case kPacketTypeXr:
57 if (!ParseExtendedReport(&chunk, header))
58 return false;
59 break;
62 return true;
65 bool RtcpParser::ParseCommonHeader(base::BigEndianReader* reader,
66 RtcpCommonHeader* parsed_header) {
67 // 0 1 2 3
68 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
69 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70 // |V=2|P| IC | PT | length |
71 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 // Common header for all Rtcp packets, 4 octets.
75 uint8 byte;
76 if (!reader->ReadU8(&byte))
77 return false;
78 parsed_header->V = byte >> 6;
79 parsed_header->P = ((byte & 0x20) == 0) ? false : true;
81 // Check if RTP version field == 2.
82 if (parsed_header->V != 2)
83 return false;
85 parsed_header->IC = byte & 0x1f;
86 if (!reader->ReadU8(&parsed_header->PT))
87 return false;
89 uint16 bytes;
90 if (!reader->ReadU16(&bytes))
91 return false;
93 parsed_header->length_in_octets = (static_cast<size_t>(bytes) + 1) * 4;
95 if (parsed_header->length_in_octets == 0)
96 return false;
98 return true;
101 bool RtcpParser::ParseSR(base::BigEndianReader* reader,
102 const RtcpCommonHeader& header) {
103 uint32 sender_ssrc;
104 if (!reader->ReadU32(&sender_ssrc))
105 return false;
107 if (sender_ssrc != remote_ssrc_)
108 return true;
110 uint32 tmp;
111 if (!reader->ReadU32(&sender_report_.ntp_seconds) ||
112 !reader->ReadU32(&sender_report_.ntp_fraction) ||
113 !reader->ReadU32(&sender_report_.rtp_timestamp) ||
114 !reader->ReadU32(&sender_report_.send_packet_count) ||
115 !reader->ReadU32(&tmp))
116 return false;
117 sender_report_.send_octet_count = tmp;
118 has_sender_report_ = true;
120 for (size_t block = 0; block < header.IC; block++)
121 if (!ParseReportBlock(reader))
122 return false;
124 return true;
127 bool RtcpParser::ParseRR(base::BigEndianReader* reader,
128 const RtcpCommonHeader& header) {
129 uint32 receiver_ssrc;
130 if (!reader->ReadU32(&receiver_ssrc))
131 return false;
133 if (receiver_ssrc != remote_ssrc_)
134 return true;
136 for (size_t block = 0; block < header.IC; block++)
137 if (!ParseReportBlock(reader))
138 return false;
140 return true;
143 bool RtcpParser::ParseReportBlock(base::BigEndianReader* reader) {
144 uint32 ssrc, last_report, delay;
145 if (!reader->ReadU32(&ssrc) ||
146 !reader->Skip(12) ||
147 !reader->ReadU32(&last_report) ||
148 !reader->ReadU32(&delay))
149 return false;
151 if (ssrc == local_ssrc_) {
152 last_report_ = last_report;
153 delay_since_last_report_ = delay;
154 has_last_report_ = true;
157 return true;
160 bool RtcpParser::ParseApplicationDefined(base::BigEndianReader* reader,
161 const RtcpCommonHeader& header) {
162 uint32 sender_ssrc;
163 uint32 name;
164 if (!reader->ReadU32(&sender_ssrc) ||
165 !reader->ReadU32(&name))
166 return false;
168 if (sender_ssrc != remote_ssrc_)
169 return true;
171 if (name != kCast)
172 return false;
174 switch (header.IC /* subtype */ ) {
175 case kReceiverLogSubtype:
176 if (!ParseCastReceiverLogFrameItem(reader))
177 return false;
178 break;
180 return true;
183 bool RtcpParser::ParseCastReceiverLogFrameItem(
184 base::BigEndianReader* reader) {
186 while (reader->remaining()) {
187 uint32 rtp_timestamp;
188 uint32 data;
189 if (!reader->ReadU32(&rtp_timestamp) ||
190 !reader->ReadU32(&data))
191 return false;
193 // We have 24 LSB of the event timestamp base on the wire.
194 base::TimeTicks event_timestamp_base = base::TimeTicks() +
195 base::TimeDelta::FromMilliseconds(data & 0xffffff);
197 size_t num_events = 1 + static_cast<uint8>(data >> 24);
199 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp);
200 for (size_t event = 0; event < num_events; event++) {
201 uint16 delay_delta_or_packet_id;
202 uint16 event_type_and_timestamp_delta;
203 if (!reader->ReadU16(&delay_delta_or_packet_id) ||
204 !reader->ReadU16(&event_type_and_timestamp_delta))
205 return false;
207 RtcpReceiverEventLogMessage event_log;
208 event_log.type = TranslateToLogEventFromWireFormat(
209 static_cast<uint8>(event_type_and_timestamp_delta >> 12));
210 event_log.event_timestamp =
211 event_timestamp_base +
212 base::TimeDelta::FromMilliseconds(
213 event_type_and_timestamp_delta & 0xfff);
214 if (event_log.type == PACKET_RECEIVED) {
215 event_log.packet_id = delay_delta_or_packet_id;
216 } else {
217 event_log.delay_delta = base::TimeDelta::FromMilliseconds(
218 static_cast<int16>(delay_delta_or_packet_id));
220 frame_log.event_log_messages_.push_back(event_log);
223 receiver_log_.push_back(frame_log);
226 return true;
229 // RFC 4585.
230 bool RtcpParser::ParseFeedbackCommon(base::BigEndianReader* reader,
231 const RtcpCommonHeader& header) {
232 // See RTC 4585 Section 6.4 for application specific feedback messages.
233 if (header.IC != 15) {
234 return true;
236 uint32 remote_ssrc;
237 uint32 media_ssrc;
238 if (!reader->ReadU32(&remote_ssrc) ||
239 !reader->ReadU32(&media_ssrc))
240 return false;
242 if (remote_ssrc != remote_ssrc_)
243 return true;
245 uint32 name;
246 if (!reader->ReadU32(&name))
247 return false;
249 if (name != kCast) {
250 return true;
253 cast_message_.media_ssrc = remote_ssrc;
255 uint8 last_frame_id;
256 uint8 number_of_lost_fields;
257 if (!reader->ReadU8(&last_frame_id) ||
258 !reader->ReadU8(&number_of_lost_fields) ||
259 !reader->ReadU16(&cast_message_.target_delay_ms))
260 return false;
262 // Please note, this frame_id is still only 8-bit!
263 cast_message_.ack_frame_id = last_frame_id;
265 for (size_t i = 0; i < number_of_lost_fields; i++) {
266 uint8 frame_id;
267 uint16 packet_id;
268 uint8 bitmask;
269 if (!reader->ReadU8(&frame_id) ||
270 !reader->ReadU16(&packet_id) ||
271 !reader->ReadU8(&bitmask))
272 return false;
273 cast_message_.missing_frames_and_packets[frame_id].insert(packet_id);
274 if (packet_id != kRtcpCastAllPacketsLost) {
275 while (bitmask) {
276 packet_id++;
277 if (bitmask & 1)
278 cast_message_.missing_frames_and_packets[frame_id].insert(packet_id);
279 bitmask >>= 1;
284 has_cast_message_ = true;
285 return true;
288 bool RtcpParser::ParseExtendedReport(base::BigEndianReader* reader,
289 const RtcpCommonHeader& header) {
290 uint32 remote_ssrc;
291 if (!reader->ReadU32(&remote_ssrc))
292 return false;
294 // Is it for us?
295 if (remote_ssrc != remote_ssrc_)
296 return true;
298 while (reader->remaining()) {
299 uint8 block_type;
300 uint16 block_length;
301 if (!reader->ReadU8(&block_type) ||
302 !reader->Skip(1) ||
303 !reader->ReadU16(&block_length))
304 return false;
306 switch (block_type) {
307 case 4: // RRTR. RFC3611 Section 4.4.
308 if (block_length != 2)
309 return false;
310 if (!ParseExtendedReportReceiverReferenceTimeReport(reader,
311 remote_ssrc))
312 return false;
313 break;
315 default:
316 // Skip unknown item.
317 if (!reader->Skip(block_length * 4))
318 return false;
322 return true;
325 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport(
326 base::BigEndianReader* reader,
327 uint32 remote_ssrc) {
328 receiver_reference_time_report_.remote_ssrc = remote_ssrc;
329 if(!reader->ReadU32(&receiver_reference_time_report_.ntp_seconds) ||
330 !reader->ReadU32(&receiver_reference_time_report_.ntp_fraction))
331 return false;
333 has_receiver_reference_time_report_ = true;
334 return true;
337 // Converts a log event type to an integer value.
338 // NOTE: We have only allocated 4 bits to represent the type of event over the
339 // wire. Therefore, this function can only return values from 0 to 15.
340 uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) {
341 switch (event) {
342 case FRAME_ACK_SENT:
343 return 11;
344 case FRAME_PLAYOUT:
345 return 12;
346 case FRAME_DECODED:
347 return 13;
348 case PACKET_RECEIVED:
349 return 14;
350 default:
351 return 0; // Not an interesting event.
355 CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
356 // TODO(imcheng): Remove the old mappings once they are no longer used.
357 switch (event) {
358 case 1: // AudioAckSent
359 case 5: // VideoAckSent
360 case 11: // Unified
361 return FRAME_ACK_SENT;
362 case 2: // AudioPlayoutDelay
363 case 7: // VideoRenderDelay
364 case 12: // Unified
365 return FRAME_PLAYOUT;
366 case 3: // AudioFrameDecoded
367 case 6: // VideoFrameDecoded
368 case 13: // Unified
369 return FRAME_DECODED;
370 case 4: // AudioPacketReceived
371 case 8: // VideoPacketReceived
372 case 14: // Unified
373 return PACKET_RECEIVED;
374 case 9: // DuplicateAudioPacketReceived
375 case 10: // DuplicateVideoPacketReceived
376 default:
377 // If the sender adds new log messages we will end up here until we add
378 // the new messages in the receiver.
379 VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
380 return UNKNOWN;
384 } // namespace cast
385 } // namespace media