OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "media/cast/rtcp/rtcp_utility.h" | |
6 | |
7 #include "base/big_endian.h" | |
8 #include "base/logging.h" | |
9 #include "media/cast/transport/cast_transport_defines.h" | |
10 | |
11 namespace media { | |
12 namespace cast { | |
13 | |
14 RtcpParser::RtcpParser(const uint8* rtcpData, size_t rtcpDataLength) | |
15 : rtcp_data_begin_(rtcpData), | |
16 rtcp_data_end_(rtcpData + rtcpDataLength), | |
17 valid_packet_(false), | |
18 rtcp_data_(rtcpData), | |
19 rtcp_block_end_(NULL), | |
20 state_(kStateTopLevel), | |
21 number_of_blocks_(0), | |
22 field_type_(kRtcpNotValidCode) { | |
23 memset(&field_, 0, sizeof(field_)); | |
24 Validate(); | |
25 } | |
26 | |
27 RtcpParser::~RtcpParser() {} | |
28 | |
29 RtcpFieldTypes RtcpParser::FieldType() const { return field_type_; } | |
30 | |
31 const RtcpField& RtcpParser::Field() const { return field_; } | |
32 | |
33 RtcpFieldTypes RtcpParser::Begin() { | |
34 rtcp_data_ = rtcp_data_begin_; | |
35 return Iterate(); | |
36 } | |
37 | |
38 RtcpFieldTypes RtcpParser::Iterate() { | |
39 // Reset packet type | |
40 field_type_ = kRtcpNotValidCode; | |
41 | |
42 if (!IsValid()) | |
43 return kRtcpNotValidCode; | |
44 | |
45 switch (state_) { | |
46 case kStateTopLevel: | |
47 IterateTopLevel(); | |
48 break; | |
49 case kStateReportBlock: | |
50 IterateReportBlockItem(); | |
51 break; | |
52 case kStateSdes: | |
53 IterateSdesItem(); | |
54 break; | |
55 case kStateBye: | |
56 IterateByeItem(); | |
57 break; | |
58 case kStateApplicationSpecificCastReceiverFrameLog: | |
59 IterateCastReceiverLogFrame(); | |
60 break; | |
61 case kStateApplicationSpecificCastReceiverEventLog: | |
62 IterateCastReceiverLogEvent(); | |
63 break; | |
64 case kStateExtendedReportBlock: | |
65 IterateExtendedReportItem(); | |
66 break; | |
67 case kStateExtendedReportDelaySinceLastReceiverReport: | |
68 IterateExtendedReportDelaySinceLastReceiverReportItem(); | |
69 break; | |
70 case kStateGenericRtpFeedbackNack: | |
71 IterateNackItem(); | |
72 break; | |
73 case kStatePayloadSpecificRpsi: | |
74 IterateRpsiItem(); | |
75 break; | |
76 case kStatePayloadSpecificFir: | |
77 IterateFirItem(); | |
78 break; | |
79 case kStatePayloadSpecificApplication: | |
80 IteratePayloadSpecificAppItem(); | |
81 break; | |
82 case kStatePayloadSpecificRemb: | |
83 IteratePayloadSpecificRembItem(); | |
84 break; | |
85 case kStatePayloadSpecificCast: | |
86 IteratePayloadSpecificCastItem(); | |
87 break; | |
88 case kStatePayloadSpecificCastNack: | |
89 IteratePayloadSpecificCastNackItem(); | |
90 break; | |
91 } | |
92 return field_type_; | |
93 } | |
94 | |
95 void RtcpParser::IterateTopLevel() { | |
96 for (;;) { | |
97 RtcpCommonHeader header; | |
98 | |
99 bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header); | |
100 if (!success) | |
101 return; | |
102 | |
103 rtcp_block_end_ = rtcp_data_ + header.length_in_octets; | |
104 | |
105 if (rtcp_block_end_ > rtcp_data_end_) | |
106 return; // Bad block! | |
107 | |
108 switch (header.PT) { | |
109 case transport::kPacketTypeSenderReport: | |
110 // number of Report blocks | |
111 number_of_blocks_ = header.IC; | |
112 ParseSR(); | |
113 return; | |
114 case transport::kPacketTypeReceiverReport: | |
115 // number of Report blocks | |
116 number_of_blocks_ = header.IC; | |
117 ParseRR(); | |
118 return; | |
119 case transport::kPacketTypeSdes: | |
120 // number of Sdes blocks | |
121 number_of_blocks_ = header.IC; | |
122 if (!ParseSdes()) { | |
123 break; // Nothing supported found, continue to next block! | |
124 } | |
125 return; | |
126 case transport::kPacketTypeBye: | |
127 number_of_blocks_ = header.IC; | |
128 if (!ParseBye()) { | |
129 // Nothing supported found, continue to next block! | |
130 break; | |
131 } | |
132 return; | |
133 case transport::kPacketTypeApplicationDefined: | |
134 if (!ParseApplicationDefined(header.IC)) { | |
135 // Nothing supported found, continue to next block! | |
136 break; | |
137 } | |
138 return; | |
139 case transport::kPacketTypeGenericRtpFeedback: // Fall through! | |
140 case transport::kPacketTypePayloadSpecific: | |
141 if (!ParseFeedBackCommon(header)) { | |
142 // Nothing supported found, continue to next block! | |
143 break; | |
144 } | |
145 return; | |
146 case transport::kPacketTypeXr: | |
147 if (!ParseExtendedReport()) { | |
148 break; // Nothing supported found, continue to next block! | |
149 } | |
150 return; | |
151 default: | |
152 // Not supported! Skip! | |
153 EndCurrentBlock(); | |
154 break; | |
155 } | |
156 } | |
157 } | |
158 | |
159 void RtcpParser::IterateReportBlockItem() { | |
160 bool success = ParseReportBlockItem(); | |
161 if (!success) | |
162 Iterate(); | |
163 } | |
164 | |
165 void RtcpParser::IterateSdesItem() { | |
166 bool success = ParseSdesItem(); | |
167 if (!success) | |
168 Iterate(); | |
169 } | |
170 | |
171 void RtcpParser::IterateByeItem() { | |
172 bool success = ParseByeItem(); | |
173 if (!success) | |
174 Iterate(); | |
175 } | |
176 | |
177 void RtcpParser::IterateExtendedReportItem() { | |
178 bool success = ParseExtendedReportItem(); | |
179 if (!success) | |
180 Iterate(); | |
181 } | |
182 | |
183 void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() { | |
184 bool success = ParseExtendedReportDelaySinceLastReceiverReport(); | |
185 if (!success) | |
186 Iterate(); | |
187 } | |
188 | |
189 void RtcpParser::IterateNackItem() { | |
190 bool success = ParseNackItem(); | |
191 if (!success) | |
192 Iterate(); | |
193 } | |
194 | |
195 void RtcpParser::IterateRpsiItem() { | |
196 bool success = ParseRpsiItem(); | |
197 if (!success) | |
198 Iterate(); | |
199 } | |
200 | |
201 void RtcpParser::IterateFirItem() { | |
202 bool success = ParseFirItem(); | |
203 if (!success) | |
204 Iterate(); | |
205 } | |
206 | |
207 void RtcpParser::IteratePayloadSpecificAppItem() { | |
208 bool success = ParsePayloadSpecificAppItem(); | |
209 if (!success) | |
210 Iterate(); | |
211 } | |
212 | |
213 void RtcpParser::IteratePayloadSpecificRembItem() { | |
214 bool success = ParsePayloadSpecificRembItem(); | |
215 if (!success) | |
216 Iterate(); | |
217 } | |
218 | |
219 void RtcpParser::IteratePayloadSpecificCastItem() { | |
220 bool success = ParsePayloadSpecificCastItem(); | |
221 if (!success) | |
222 Iterate(); | |
223 } | |
224 | |
225 void RtcpParser::IteratePayloadSpecificCastNackItem() { | |
226 bool success = ParsePayloadSpecificCastNackItem(); | |
227 if (!success) | |
228 Iterate(); | |
229 } | |
230 | |
231 void RtcpParser::IterateCastReceiverLogFrame() { | |
232 bool success = ParseCastReceiverLogFrameItem(); | |
233 if (!success) | |
234 Iterate(); | |
235 } | |
236 | |
237 void RtcpParser::IterateCastReceiverLogEvent() { | |
238 bool success = ParseCastReceiverLogEventItem(); | |
239 if (!success) | |
240 Iterate(); | |
241 } | |
242 | |
243 void RtcpParser::Validate() { | |
244 if (rtcp_data_ == NULL) | |
245 return; // NOT VALID | |
246 | |
247 RtcpCommonHeader header; | |
248 bool success = | |
249 RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header); | |
250 | |
251 if (!success) | |
252 return; // NOT VALID! | |
253 | |
254 valid_packet_ = true; | |
255 } | |
256 | |
257 bool RtcpParser::IsValid() const { return valid_packet_; } | |
258 | |
259 void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; } | |
260 | |
261 bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin, | |
262 const uint8* data_end, | |
263 RtcpCommonHeader* parsed_header) const { | |
264 if (!data_begin || !data_end) | |
265 return false; | |
266 | |
267 // 0 1 2 3 | |
268 // 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 | |
269 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
270 // |V=2|P| IC | PT | length | | |
271 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
272 // | |
273 // Common header for all Rtcp packets, 4 octets. | |
274 | |
275 if ((data_end - data_begin) < 4) | |
276 return false; | |
277 | |
278 parsed_header->V = data_begin[0] >> 6; | |
279 parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true; | |
280 parsed_header->IC = data_begin[0] & 0x1f; | |
281 parsed_header->PT = data_begin[1]; | |
282 | |
283 parsed_header->length_in_octets = | |
284 ((data_begin[2] << 8) + data_begin[3] + 1) * 4; | |
285 | |
286 if (parsed_header->length_in_octets == 0) | |
287 return false; | |
288 | |
289 // Check if RTP version field == 2. | |
290 if (parsed_header->V != 2) | |
291 return false; | |
292 | |
293 return true; | |
294 } | |
295 | |
296 bool RtcpParser::ParseRR() { | |
297 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
298 if (length < 8) | |
299 return false; | |
300 | |
301 field_type_ = kRtcpRrCode; | |
302 | |
303 base::BigEndianReader big_endian_reader( | |
304 reinterpret_cast<const char*>(rtcp_data_), length); | |
305 big_endian_reader.Skip(4); // Skip header | |
306 big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc); | |
307 field_.receiver_report.number_of_report_blocks = number_of_blocks_; | |
308 rtcp_data_ += 8; | |
309 | |
310 // State transition | |
311 state_ = kStateReportBlock; | |
312 return true; | |
313 } | |
314 | |
315 bool RtcpParser::ParseSR() { | |
316 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
317 if (length < 28) { | |
318 EndCurrentBlock(); | |
319 return false; | |
320 } | |
321 field_type_ = kRtcpSrCode; | |
322 | |
323 base::BigEndianReader big_endian_reader( | |
324 reinterpret_cast<const char*>(rtcp_data_), length); | |
325 big_endian_reader.Skip(4); // Skip header | |
326 big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc); | |
327 big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant); | |
328 big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant); | |
329 big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp); | |
330 big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count); | |
331 big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count); | |
332 field_.sender_report.number_of_report_blocks = number_of_blocks_; | |
333 rtcp_data_ += 28; | |
334 | |
335 if (number_of_blocks_ != 0) { | |
336 // State transition. | |
337 state_ = kStateReportBlock; | |
338 } else { | |
339 // Don't go to state report block item if 0 report blocks. | |
340 state_ = kStateTopLevel; | |
341 EndCurrentBlock(); | |
342 } | |
343 return true; | |
344 } | |
345 | |
346 bool RtcpParser::ParseReportBlockItem() { | |
347 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
348 if (length < 24 || number_of_blocks_ <= 0) { | |
349 state_ = kStateTopLevel; | |
350 EndCurrentBlock(); | |
351 return false; | |
352 } | |
353 | |
354 base::BigEndianReader big_endian_reader( | |
355 reinterpret_cast<const char*>(rtcp_data_), length); | |
356 big_endian_reader.ReadU32(&field_.report_block_item.ssrc); | |
357 big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost); | |
358 | |
359 uint8 temp_number_of_packets_lost; | |
360 big_endian_reader.ReadU8(&temp_number_of_packets_lost); | |
361 field_.report_block_item.cumulative_number_of_packets_lost = | |
362 temp_number_of_packets_lost << 16; | |
363 big_endian_reader.ReadU8(&temp_number_of_packets_lost); | |
364 field_.report_block_item.cumulative_number_of_packets_lost += | |
365 temp_number_of_packets_lost << 8; | |
366 big_endian_reader.ReadU8(&temp_number_of_packets_lost); | |
367 field_.report_block_item.cumulative_number_of_packets_lost += | |
368 temp_number_of_packets_lost; | |
369 | |
370 big_endian_reader.ReadU32( | |
371 &field_.report_block_item.extended_highest_sequence_number); | |
372 big_endian_reader.ReadU32(&field_.report_block_item.jitter); | |
373 big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report); | |
374 big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report); | |
375 rtcp_data_ += 24; | |
376 | |
377 number_of_blocks_--; | |
378 field_type_ = kRtcpReportBlockItemCode; | |
379 return true; | |
380 } | |
381 | |
382 bool RtcpParser::ParseSdes() { | |
383 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
384 | |
385 if (length < 8) { | |
386 state_ = kStateTopLevel; | |
387 EndCurrentBlock(); | |
388 return false; | |
389 } | |
390 rtcp_data_ += 4; // Skip header | |
391 | |
392 state_ = kStateSdes; | |
393 field_type_ = kRtcpSdesCode; | |
394 return true; | |
395 } | |
396 | |
397 bool RtcpParser::ParseSdesItem() { | |
398 if (number_of_blocks_ <= 0) { | |
399 state_ = kStateTopLevel; | |
400 EndCurrentBlock(); | |
401 return false; | |
402 } | |
403 number_of_blocks_--; | |
404 | |
405 // Find c_name item in a Sdes chunk. | |
406 while (rtcp_data_ < rtcp_block_end_) { | |
407 ptrdiff_t data_length = rtcp_block_end_ - rtcp_data_; | |
408 if (data_length < 4) { | |
409 state_ = kStateTopLevel; | |
410 EndCurrentBlock(); | |
411 return false; | |
412 } | |
413 | |
414 uint32 ssrc; | |
415 base::BigEndianReader big_endian_reader( | |
416 reinterpret_cast<const char*>(rtcp_data_), data_length); | |
417 big_endian_reader.ReadU32(&ssrc); | |
418 rtcp_data_ += 4; | |
419 | |
420 bool found_c_name = ParseSdesTypes(); | |
421 if (found_c_name) { | |
422 field_.c_name.sender_ssrc = ssrc; | |
423 return true; | |
424 } | |
425 } | |
426 state_ = kStateTopLevel; | |
427 EndCurrentBlock(); | |
428 return false; | |
429 } | |
430 | |
431 bool RtcpParser::ParseSdesTypes() { | |
432 // Only the c_name item is mandatory. RFC 3550 page 46. | |
433 bool found_c_name = false; | |
434 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
435 base::BigEndianReader big_endian_reader( | |
436 reinterpret_cast<const char*>(rtcp_data_), length); | |
437 | |
438 while (big_endian_reader.remaining() > 0) { | |
439 uint8 tag; | |
440 big_endian_reader.ReadU8(&tag); | |
441 | |
442 if (tag == 0) { | |
443 // End tag! 4 octet aligned. | |
444 rtcp_data_ = rtcp_block_end_; | |
445 return found_c_name; | |
446 } | |
447 | |
448 if (big_endian_reader.remaining() > 0) { | |
449 uint8 len; | |
450 big_endian_reader.ReadU8(&len); | |
451 | |
452 if (tag == 1) { // c_name. | |
453 // Sanity check. | |
454 if (big_endian_reader.remaining() < len) { | |
455 state_ = kStateTopLevel; | |
456 EndCurrentBlock(); | |
457 return false; | |
458 } | |
459 int i = 0; | |
460 for (; i < len; ++i) { | |
461 uint8 c; | |
462 big_endian_reader.ReadU8(&c); | |
463 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\')) { | |
464 // Illegal char. | |
465 state_ = kStateTopLevel; | |
466 EndCurrentBlock(); | |
467 return false; | |
468 } | |
469 field_.c_name.name[i] = c; | |
470 } | |
471 // Make sure we are null terminated. | |
472 field_.c_name.name[i] = 0; | |
473 field_type_ = kRtcpSdesChunkCode; | |
474 found_c_name = true; | |
475 } else { | |
476 big_endian_reader.Skip(len); | |
477 } | |
478 } | |
479 } | |
480 // No end tag found! | |
481 state_ = kStateTopLevel; | |
482 EndCurrentBlock(); | |
483 return false; | |
484 } | |
485 | |
486 bool RtcpParser::ParseBye() { | |
487 rtcp_data_ += 4; // Skip header. | |
488 state_ = kStateBye; | |
489 return ParseByeItem(); | |
490 } | |
491 | |
492 bool RtcpParser::ParseByeItem() { | |
493 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
494 if (length < 4 || number_of_blocks_ == 0) { | |
495 state_ = kStateTopLevel; | |
496 EndCurrentBlock(); | |
497 return false; | |
498 } | |
499 | |
500 field_type_ = kRtcpByeCode; | |
501 | |
502 base::BigEndianReader big_endian_reader( | |
503 reinterpret_cast<const char*>(rtcp_data_), length); | |
504 big_endian_reader.ReadU32(&field_.bye.sender_ssrc); | |
505 rtcp_data_ += 4; | |
506 | |
507 // We can have several CSRCs attached. | |
508 if (length >= 4 * number_of_blocks_) { | |
509 rtcp_data_ += (number_of_blocks_ - 1) * 4; | |
510 } | |
511 number_of_blocks_ = 0; | |
512 return true; | |
513 } | |
514 | |
515 bool RtcpParser::ParseApplicationDefined(uint8 subtype) { | |
516 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
517 if (length < 16 || subtype != kReceiverLogSubtype) { | |
518 state_ = kStateTopLevel; | |
519 EndCurrentBlock(); | |
520 return false; | |
521 } | |
522 | |
523 uint32 sender_ssrc; | |
524 uint32 name; | |
525 | |
526 base::BigEndianReader big_endian_reader( | |
527 reinterpret_cast<const char*>(rtcp_data_), length); | |
528 big_endian_reader.Skip(4); // Skip header. | |
529 big_endian_reader.ReadU32(&sender_ssrc); | |
530 big_endian_reader.ReadU32(&name); | |
531 | |
532 if (name != kCast) { | |
533 state_ = kStateTopLevel; | |
534 EndCurrentBlock(); | |
535 return false; | |
536 } | |
537 rtcp_data_ += 12; | |
538 switch (subtype) { | |
539 case kReceiverLogSubtype: | |
540 state_ = kStateApplicationSpecificCastReceiverFrameLog; | |
541 field_type_ = kRtcpApplicationSpecificCastReceiverLogCode; | |
542 field_.cast_receiver_log.sender_ssrc = sender_ssrc; | |
543 break; | |
544 default: | |
545 NOTREACHED(); | |
546 } | |
547 return true; | |
548 } | |
549 | |
550 bool RtcpParser::ParseCastReceiverLogFrameItem() { | |
551 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
552 if (length < 12) { | |
553 state_ = kStateTopLevel; | |
554 EndCurrentBlock(); | |
555 return false; | |
556 } | |
557 uint32 rtp_timestamp; | |
558 uint32 data; | |
559 base::BigEndianReader big_endian_reader( | |
560 reinterpret_cast<const char*>(rtcp_data_), length); | |
561 big_endian_reader.ReadU32(&rtp_timestamp); | |
562 big_endian_reader.ReadU32(&data); | |
563 | |
564 rtcp_data_ += 8; | |
565 | |
566 field_.cast_receiver_log.rtp_timestamp = rtp_timestamp; | |
567 // We have 24 LSB of the event timestamp base on the wire. | |
568 field_.cast_receiver_log.event_timestamp_base = data & 0xffffff; | |
569 | |
570 number_of_blocks_ = 1 + static_cast<uint8>(data >> 24); | |
571 state_ = kStateApplicationSpecificCastReceiverEventLog; | |
572 field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode; | |
573 return true; | |
574 } | |
575 | |
576 bool RtcpParser::ParseCastReceiverLogEventItem() { | |
577 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
578 if (length < 4) { | |
579 state_ = kStateTopLevel; | |
580 EndCurrentBlock(); | |
581 return false; | |
582 } | |
583 if (number_of_blocks_ == 0) { | |
584 // Continue parsing the next receiver frame event. | |
585 state_ = kStateApplicationSpecificCastReceiverFrameLog; | |
586 return false; | |
587 } | |
588 number_of_blocks_--; | |
589 | |
590 uint16 delay_delta_or_packet_id; | |
591 uint16 event_type_and_timestamp_delta; | |
592 base::BigEndianReader big_endian_reader( | |
593 reinterpret_cast<const char*>(rtcp_data_), length); | |
594 big_endian_reader.ReadU16(&delay_delta_or_packet_id); | |
595 big_endian_reader.ReadU16(&event_type_and_timestamp_delta); | |
596 | |
597 rtcp_data_ += 4; | |
598 | |
599 field_.cast_receiver_log.event = | |
600 static_cast<uint8>(event_type_and_timestamp_delta >> 12); | |
601 // delay_delta is in union'ed with packet_id. | |
602 field_.cast_receiver_log.delay_delta_or_packet_id.packet_id = | |
603 delay_delta_or_packet_id; | |
604 field_.cast_receiver_log.event_timestamp_delta = | |
605 event_type_and_timestamp_delta & 0xfff; | |
606 | |
607 field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode; | |
608 return true; | |
609 } | |
610 | |
611 bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) { | |
612 DCHECK((header.PT == transport::kPacketTypeGenericRtpFeedback) || | |
613 (header.PT == transport::kPacketTypePayloadSpecific)) | |
614 << "Invalid state"; | |
615 | |
616 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
617 | |
618 if (length < 12) { // 4 * 3, RFC4585 section 6.1 | |
619 EndCurrentBlock(); | |
620 return false; | |
621 } | |
622 | |
623 uint32 sender_ssrc; | |
624 uint32 media_ssrc; | |
625 base::BigEndianReader big_endian_reader( | |
626 reinterpret_cast<const char*>(rtcp_data_), length); | |
627 big_endian_reader.Skip(4); // Skip header. | |
628 big_endian_reader.ReadU32(&sender_ssrc); | |
629 big_endian_reader.ReadU32(&media_ssrc); | |
630 | |
631 rtcp_data_ += 12; | |
632 | |
633 if (header.PT == transport::kPacketTypeGenericRtpFeedback) { | |
634 // Transport layer feedback | |
635 switch (header.IC) { | |
636 case 1: | |
637 // Nack | |
638 field_type_ = kRtcpGenericRtpFeedbackNackCode; | |
639 field_.nack.sender_ssrc = sender_ssrc; | |
640 field_.nack.media_ssrc = media_ssrc; | |
641 state_ = kStateGenericRtpFeedbackNack; | |
642 return true; | |
643 case 2: | |
644 // Used to be ACK is this code point, which is removed conficts with | |
645 // http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00 | |
646 break; | |
647 case 3: | |
648 // Tmmbr | |
649 break; | |
650 case 4: | |
651 // Tmmbn | |
652 break; | |
653 case 5: | |
654 // RFC 6051 RTCP-sender_report-REQ Rapid Synchronisation of RTP Flows | |
655 // Trigger a new Rtcp sender_report | |
656 field_type_ = kRtcpGenericRtpFeedbackSrReqCode; | |
657 | |
658 // Note: No state transition, sender report REQ is empty! | |
659 return true; | |
660 default: | |
661 break; | |
662 } | |
663 EndCurrentBlock(); | |
664 return false; | |
665 | |
666 } else if (header.PT == transport::kPacketTypePayloadSpecific) { | |
667 // Payload specific feedback | |
668 switch (header.IC) { | |
669 case 1: | |
670 // PLI | |
671 field_type_ = kRtcpPayloadSpecificPliCode; | |
672 field_.pli.sender_ssrc = sender_ssrc; | |
673 field_.pli.media_ssrc = media_ssrc; | |
674 | |
675 // Note: No state transition, PLI FCI is empty! | |
676 return true; | |
677 case 2: | |
678 // Sli | |
679 break; | |
680 case 3: | |
681 field_type_ = kRtcpPayloadSpecificRpsiCode; | |
682 field_.rpsi.sender_ssrc = sender_ssrc; | |
683 field_.rpsi.media_ssrc = media_ssrc; | |
684 state_ = kStatePayloadSpecificRpsi; | |
685 return true; | |
686 case 4: | |
687 // fir | |
688 break; | |
689 case 15: | |
690 field_type_ = kRtcpPayloadSpecificAppCode; | |
691 field_.application_specific.sender_ssrc = sender_ssrc; | |
692 field_.application_specific.media_ssrc = media_ssrc; | |
693 state_ = kStatePayloadSpecificApplication; | |
694 return true; | |
695 default: | |
696 break; | |
697 } | |
698 | |
699 EndCurrentBlock(); | |
700 return false; | |
701 } else { | |
702 DCHECK(false) << "Invalid state"; | |
703 EndCurrentBlock(); | |
704 return false; | |
705 } | |
706 } | |
707 | |
708 bool RtcpParser::ParseRpsiItem() { | |
709 // RFC 4585 6.3.3. Reference Picture Selection Indication (rpsi) | |
710 /* | |
711 0 1 2 3 | |
712 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 | |
713 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
714 | PB |0| Payload Type| Native rpsi bit string | | |
715 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
716 | defined per codec ... | Padding (0) | | |
717 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
718 */ | |
719 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
720 | |
721 if (length < 4) { | |
722 state_ = kStateTopLevel; | |
723 EndCurrentBlock(); | |
724 return false; | |
725 } | |
726 if (length > 2 + kRtcpRpsiDataSize) { | |
727 state_ = kStateTopLevel; | |
728 EndCurrentBlock(); | |
729 return false; | |
730 } | |
731 | |
732 field_type_ = kRtcpPayloadSpecificRpsiCode; | |
733 | |
734 uint8 padding_bits; | |
735 base::BigEndianReader big_endian_reader( | |
736 reinterpret_cast<const char*>(rtcp_data_), length); | |
737 big_endian_reader.ReadU8(&padding_bits); | |
738 big_endian_reader.ReadU8(&field_.rpsi.payload_type); | |
739 big_endian_reader.ReadBytes(&field_.rpsi.native_bit_string, length - 2); | |
740 field_.rpsi.number_of_valid_bits = | |
741 static_cast<uint16>(length - 2) * 8 - padding_bits; | |
742 | |
743 rtcp_data_ += length; | |
744 return true; | |
745 } | |
746 | |
747 bool RtcpParser::ParseNackItem() { | |
748 // RFC 4585 6.2.1. Generic Nack | |
749 | |
750 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
751 if (length < 4) { | |
752 state_ = kStateTopLevel; | |
753 EndCurrentBlock(); | |
754 return false; | |
755 } | |
756 | |
757 field_type_ = kRtcpGenericRtpFeedbackNackItemCode; | |
758 | |
759 base::BigEndianReader big_endian_reader( | |
760 reinterpret_cast<const char*>(rtcp_data_), length); | |
761 big_endian_reader.ReadU16(&field_.nack_item.packet_id); | |
762 big_endian_reader.ReadU16(&field_.nack_item.bitmask); | |
763 rtcp_data_ += 4; | |
764 return true; | |
765 } | |
766 | |
767 bool RtcpParser::ParsePayloadSpecificAppItem() { | |
768 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
769 | |
770 if (length < 4) { | |
771 state_ = kStateTopLevel; | |
772 EndCurrentBlock(); | |
773 return false; | |
774 } | |
775 uint32 name; | |
776 base::BigEndianReader big_endian_reader( | |
777 reinterpret_cast<const char*>(rtcp_data_), length); | |
778 big_endian_reader.ReadU32(&name); | |
779 rtcp_data_ += 4; | |
780 | |
781 if (name == kRemb) { | |
782 field_type_ = kRtcpPayloadSpecificRembCode; | |
783 state_ = kStatePayloadSpecificRemb; | |
784 return true; | |
785 } else if (name == kCast) { | |
786 field_type_ = kRtcpPayloadSpecificCastCode; | |
787 state_ = kStatePayloadSpecificCast; | |
788 return true; | |
789 } | |
790 state_ = kStateTopLevel; | |
791 EndCurrentBlock(); | |
792 return false; | |
793 } | |
794 | |
795 bool RtcpParser::ParsePayloadSpecificRembItem() { | |
796 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
797 | |
798 if (length < 4) { | |
799 state_ = kStateTopLevel; | |
800 EndCurrentBlock(); | |
801 return false; | |
802 } | |
803 | |
804 base::BigEndianReader big_endian_reader( | |
805 reinterpret_cast<const char*>(rtcp_data_), length); | |
806 big_endian_reader.ReadU8(&field_.remb_item.number_of_ssrcs); | |
807 | |
808 uint8 byte_1; | |
809 uint8 byte_2; | |
810 uint8 byte_3; | |
811 big_endian_reader.ReadU8(&byte_1); | |
812 big_endian_reader.ReadU8(&byte_2); | |
813 big_endian_reader.ReadU8(&byte_3); | |
814 rtcp_data_ += 4; | |
815 | |
816 uint8 br_exp = (byte_1 >> 2) & 0x3F; | |
817 uint32 br_mantissa = ((byte_1 & 0x03) << 16) + (byte_2 << 8) + byte_3; | |
818 field_.remb_item.bitrate = (br_mantissa << br_exp); | |
819 | |
820 ptrdiff_t length_ssrcs = rtcp_block_end_ - rtcp_data_; | |
821 if (length_ssrcs < 4 * field_.remb_item.number_of_ssrcs) { | |
822 state_ = kStateTopLevel; | |
823 EndCurrentBlock(); | |
824 return false; | |
825 } | |
826 | |
827 field_type_ = kRtcpPayloadSpecificRembItemCode; | |
828 | |
829 for (int i = 0; i < field_.remb_item.number_of_ssrcs; i++) { | |
830 big_endian_reader.ReadU32(&field_.remb_item.ssrcs[i]); | |
831 } | |
832 return true; | |
833 } | |
834 | |
835 bool RtcpParser::ParsePayloadSpecificCastItem() { | |
836 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
837 if (length < 4) { | |
838 state_ = kStateTopLevel; | |
839 EndCurrentBlock(); | |
840 return false; | |
841 } | |
842 field_type_ = kRtcpPayloadSpecificCastCode; | |
843 | |
844 base::BigEndianReader big_endian_reader( | |
845 reinterpret_cast<const char*>(rtcp_data_), length); | |
846 big_endian_reader.ReadU8(&field_.cast_item.last_frame_id); | |
847 big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields); | |
848 big_endian_reader.ReadU16(&field_.cast_item.target_delay_ms); | |
849 | |
850 rtcp_data_ += 4; | |
851 | |
852 if (field_.cast_item.number_of_lost_fields != 0) { | |
853 // State transition | |
854 state_ = kStatePayloadSpecificCastNack; | |
855 } else { | |
856 // Don't go to state cast nack item if got 0 fields. | |
857 state_ = kStateTopLevel; | |
858 EndCurrentBlock(); | |
859 } | |
860 return true; | |
861 } | |
862 | |
863 bool RtcpParser::ParsePayloadSpecificCastNackItem() { | |
864 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
865 if (length < 4) { | |
866 state_ = kStateTopLevel; | |
867 EndCurrentBlock(); | |
868 return false; | |
869 } | |
870 field_type_ = kRtcpPayloadSpecificCastNackItemCode; | |
871 | |
872 base::BigEndianReader big_endian_reader( | |
873 reinterpret_cast<const char*>(rtcp_data_), length); | |
874 big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id); | |
875 big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id); | |
876 big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask); | |
877 | |
878 rtcp_data_ += 4; | |
879 return true; | |
880 } | |
881 | |
882 bool RtcpParser::ParseFirItem() { | |
883 // RFC 5104 4.3.1. Full Intra Request (fir) | |
884 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
885 | |
886 if (length < 8) { | |
887 state_ = kStateTopLevel; | |
888 EndCurrentBlock(); | |
889 return false; | |
890 } | |
891 field_type_ = kRtcpPayloadSpecificFirItemCode; | |
892 | |
893 base::BigEndianReader big_endian_reader( | |
894 reinterpret_cast<const char*>(rtcp_data_), length); | |
895 big_endian_reader.ReadU32(&field_.fir_item.ssrc); | |
896 big_endian_reader.ReadU8(&field_.fir_item.command_sequence_number); | |
897 | |
898 rtcp_data_ += 8; | |
899 return true; | |
900 } | |
901 | |
902 bool RtcpParser::ParseExtendedReport() { | |
903 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
904 if (length < 8) | |
905 return false; | |
906 | |
907 field_type_ = kRtcpXrCode; | |
908 | |
909 base::BigEndianReader big_endian_reader( | |
910 reinterpret_cast<const char*>(rtcp_data_), length); | |
911 big_endian_reader.Skip(4); // Skip header. | |
912 big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc); | |
913 | |
914 rtcp_data_ += 8; | |
915 | |
916 state_ = kStateExtendedReportBlock; | |
917 return true; | |
918 } | |
919 | |
920 bool RtcpParser::ParseExtendedReportItem() { | |
921 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
922 if (length < 4) { | |
923 state_ = kStateTopLevel; | |
924 EndCurrentBlock(); | |
925 return false; | |
926 } | |
927 | |
928 uint8 block_type; | |
929 uint16 block_length; | |
930 base::BigEndianReader big_endian_reader( | |
931 reinterpret_cast<const char*>(rtcp_data_), length); | |
932 big_endian_reader.ReadU8(&block_type); | |
933 big_endian_reader.Skip(1); // Ignore reserved. | |
934 big_endian_reader.ReadU16(&block_length); | |
935 | |
936 rtcp_data_ += 4; | |
937 | |
938 switch (block_type) { | |
939 case 4: | |
940 if (block_length != 2) { | |
941 // Invalid block length. | |
942 state_ = kStateTopLevel; | |
943 EndCurrentBlock(); | |
944 return false; | |
945 } | |
946 return ParseExtendedReportReceiverReferenceTimeReport(); | |
947 case 5: | |
948 if (block_length % 3 != 0) { | |
949 // Invalid block length. | |
950 state_ = kStateTopLevel; | |
951 EndCurrentBlock(); | |
952 return false; | |
953 } | |
954 if (block_length >= 3) { | |
955 number_of_blocks_ = block_length / 3; | |
956 state_ = kStateExtendedReportDelaySinceLastReceiverReport; | |
957 return ParseExtendedReportDelaySinceLastReceiverReport(); | |
958 } | |
959 return true; | |
960 default: | |
961 if (length < block_length * 4) { | |
962 state_ = kStateTopLevel; | |
963 EndCurrentBlock(); | |
964 return false; | |
965 } | |
966 field_type_ = kRtcpXrUnknownItemCode; | |
967 rtcp_data_ += block_length * 4; | |
968 return true; | |
969 } | |
970 } | |
971 | |
972 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() { | |
973 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
974 if (length < 8) { | |
975 state_ = kStateTopLevel; | |
976 EndCurrentBlock(); | |
977 return false; | |
978 } | |
979 | |
980 base::BigEndianReader big_endian_reader( | |
981 reinterpret_cast<const char*>(rtcp_data_), length); | |
982 big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant); | |
983 big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant); | |
984 | |
985 rtcp_data_ += 8; | |
986 | |
987 field_type_ = kRtcpXrRrtrCode; | |
988 return true; | |
989 } | |
990 | |
991 bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() { | |
992 ptrdiff_t length = rtcp_block_end_ - rtcp_data_; | |
993 if (length < 12) { | |
994 state_ = kStateTopLevel; | |
995 EndCurrentBlock(); | |
996 return false; | |
997 } | |
998 if (number_of_blocks_ == 0) { | |
999 // Continue parsing the extended report block. | |
1000 state_ = kStateExtendedReportBlock; | |
1001 return false; | |
1002 } | |
1003 | |
1004 base::BigEndianReader big_endian_reader( | |
1005 reinterpret_cast<const char*>(rtcp_data_), length); | |
1006 big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc); | |
1007 big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report); | |
1008 big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report); | |
1009 | |
1010 rtcp_data_ += 12; | |
1011 | |
1012 number_of_blocks_--; | |
1013 field_type_ = kRtcpXrDlrrCode; | |
1014 return true; | |
1015 } | |
1016 | |
1017 // Converts a log event type to an integer value. | |
1018 // NOTE: We have only allocated 4 bits to represent the type of event over the | |
1019 // wire. Therefore, this function can only return values from 0 to 15. | |
1020 uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) { | |
1021 switch (event) { | |
1022 case FRAME_ACK_SENT: | |
1023 return 11; | |
1024 case FRAME_PLAYOUT: | |
1025 return 12; | |
1026 case FRAME_DECODED: | |
1027 return 13; | |
1028 case PACKET_RECEIVED: | |
1029 return 14; | |
1030 default: | |
1031 return 0; // Not an interesting event. | |
1032 } | |
1033 } | |
1034 | |
1035 CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) { | |
1036 // TODO(imcheng): Remove the old mappings once they are no longer used. | |
1037 switch (event) { | |
1038 case 1: // AudioAckSent | |
1039 case 5: // VideoAckSent | |
1040 case 11: // Unified | |
1041 return FRAME_ACK_SENT; | |
1042 case 2: // AudioPlayoutDelay | |
1043 case 7: // VideoRenderDelay | |
1044 case 12: // Unified | |
1045 return FRAME_PLAYOUT; | |
1046 case 3: // AudioFrameDecoded | |
1047 case 6: // VideoFrameDecoded | |
1048 case 13: // Unified | |
1049 return FRAME_DECODED; | |
1050 case 4: // AudioPacketReceived | |
1051 case 8: // VideoPacketReceived | |
1052 case 14: // Unified | |
1053 return PACKET_RECEIVED; | |
1054 case 9: // DuplicateAudioPacketReceived | |
1055 case 10: // DuplicateVideoPacketReceived | |
1056 default: | |
1057 // If the sender adds new log messages we will end up here until we add | |
1058 // the new messages in the receiver. | |
1059 VLOG(1) << "Unexpected log message received: " << static_cast<int>(event); | |
1060 NOTREACHED(); | |
1061 return UNKNOWN; | |
1062 } | |
1063 } | |
1064 | |
1065 } // namespace cast | |
1066 } // namespace media | |
OLD | NEW |