Remove Unused AsTextButtonBorder RTTI helper.
[chromium-blink-merge.git] / media / cast / rtcp / rtcp_utility.cc
blob08063bfcc4158b1106a04d0a0fca37b43688e393
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/rtcp/rtcp_utility.h"
7 #include "base/logging.h"
8 #include "media/cast/transport/cast_transport_defines.h"
9 #include "net/base/big_endian.h"
11 namespace media {
12 namespace cast {
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();
27 RtcpParser::~RtcpParser() {}
29 RtcpFieldTypes RtcpParser::FieldType() const { return field_type_; }
31 const RtcpField& RtcpParser::Field() const { return field_; }
33 RtcpFieldTypes RtcpParser::Begin() {
34 rtcp_data_ = rtcp_data_begin_;
35 return Iterate();
38 RtcpFieldTypes RtcpParser::Iterate() {
39 // Reset packet type
40 field_type_ = kRtcpNotValidCode;
42 if (!IsValid())
43 return kRtcpNotValidCode;
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 kStateApplicationSpecificCastSenderLog:
65 IterateCastSenderLog();
66 break;
67 case kStateExtendedReportBlock:
68 IterateExtendedReportItem();
69 break;
70 case kStateExtendedReportDelaySinceLastReceiverReport:
71 IterateExtendedReportDelaySinceLastReceiverReportItem();
72 break;
73 case kStateGenericRtpFeedbackNack:
74 IterateNackItem();
75 break;
76 case kStatePayloadSpecificRpsi:
77 IterateRpsiItem();
78 break;
79 case kStatePayloadSpecificFir:
80 IterateFirItem();
81 break;
82 case kStatePayloadSpecificApplication:
83 IteratePayloadSpecificAppItem();
84 break;
85 case kStatePayloadSpecificRemb:
86 IteratePayloadSpecificRembItem();
87 break;
88 case kStatePayloadSpecificCast:
89 IteratePayloadSpecificCastItem();
90 break;
91 case kStatePayloadSpecificCastNack:
92 IteratePayloadSpecificCastNackItem();
93 break;
95 return field_type_;
98 void RtcpParser::IterateTopLevel() {
99 for (;;) {
100 RtcpCommonHeader header;
102 bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
103 if (!success)
104 return;
106 rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
108 if (rtcp_block_end_ > rtcp_data_end_)
109 return; // Bad block!
111 switch (header.PT) {
112 case transport::kPacketTypeSenderReport:
113 // number of Report blocks
114 number_of_blocks_ = header.IC;
115 ParseSR();
116 return;
117 case transport::kPacketTypeReceiverReport:
118 // number of Report blocks
119 number_of_blocks_ = header.IC;
120 ParseRR();
121 return;
122 case transport::kPacketTypeSdes:
123 // number of Sdes blocks
124 number_of_blocks_ = header.IC;
125 if (!ParseSdes()) {
126 break; // Nothing supported found, continue to next block!
128 return;
129 case transport::kPacketTypeBye:
130 number_of_blocks_ = header.IC;
131 if (!ParseBye()) {
132 // Nothing supported found, continue to next block!
133 break;
135 return;
136 case transport::kPacketTypeApplicationDefined:
137 if (!ParseApplicationDefined(header.IC)) {
138 // Nothing supported found, continue to next block!
139 break;
141 return;
142 case transport::kPacketTypeGenericRtpFeedback: // Fall through!
143 case transport::kPacketTypePayloadSpecific:
144 if (!ParseFeedBackCommon(header)) {
145 // Nothing supported found, continue to next block!
146 break;
148 return;
149 case transport::kPacketTypeXr:
150 if (!ParseExtendedReport()) {
151 break; // Nothing supported found, continue to next block!
153 return;
154 default:
155 // Not supported! Skip!
156 EndCurrentBlock();
157 break;
162 void RtcpParser::IterateReportBlockItem() {
163 bool success = ParseReportBlockItem();
164 if (!success)
165 Iterate();
168 void RtcpParser::IterateSdesItem() {
169 bool success = ParseSdesItem();
170 if (!success)
171 Iterate();
174 void RtcpParser::IterateByeItem() {
175 bool success = ParseByeItem();
176 if (!success)
177 Iterate();
180 void RtcpParser::IterateExtendedReportItem() {
181 bool success = ParseExtendedReportItem();
182 if (!success)
183 Iterate();
186 void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
187 bool success = ParseExtendedReportDelaySinceLastReceiverReport();
188 if (!success)
189 Iterate();
192 void RtcpParser::IterateNackItem() {
193 bool success = ParseNackItem();
194 if (!success)
195 Iterate();
198 void RtcpParser::IterateRpsiItem() {
199 bool success = ParseRpsiItem();
200 if (!success)
201 Iterate();
204 void RtcpParser::IterateFirItem() {
205 bool success = ParseFirItem();
206 if (!success)
207 Iterate();
210 void RtcpParser::IteratePayloadSpecificAppItem() {
211 bool success = ParsePayloadSpecificAppItem();
212 if (!success)
213 Iterate();
216 void RtcpParser::IteratePayloadSpecificRembItem() {
217 bool success = ParsePayloadSpecificRembItem();
218 if (!success)
219 Iterate();
222 void RtcpParser::IteratePayloadSpecificCastItem() {
223 bool success = ParsePayloadSpecificCastItem();
224 if (!success)
225 Iterate();
228 void RtcpParser::IteratePayloadSpecificCastNackItem() {
229 bool success = ParsePayloadSpecificCastNackItem();
230 if (!success)
231 Iterate();
234 void RtcpParser::IterateCastReceiverLogFrame() {
235 bool success = ParseCastReceiverLogFrameItem();
236 if (!success)
237 Iterate();
240 void RtcpParser::IterateCastReceiverLogEvent() {
241 bool success = ParseCastReceiverLogEventItem();
242 if (!success)
243 Iterate();
246 void RtcpParser::IterateCastSenderLog() {
247 bool success = ParseCastSenderLogItem();
248 if (!success)
249 Iterate();
252 void RtcpParser::Validate() {
253 if (rtcp_data_ == NULL)
254 return; // NOT VALID
256 RtcpCommonHeader header;
257 bool success =
258 RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header);
260 if (!success)
261 return; // NOT VALID!
263 valid_packet_ = true;
266 bool RtcpParser::IsValid() const { return valid_packet_; }
268 void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; }
270 bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
271 const uint8* data_end,
272 RtcpCommonHeader* parsed_header) const {
273 if (!data_begin || !data_end)
274 return false;
276 // 0 1 2 3
277 // 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
278 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279 // |V=2|P| IC | PT | length |
280 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
282 // Common header for all Rtcp packets, 4 octets.
284 if ((data_end - data_begin) < 4)
285 return false;
287 parsed_header->V = data_begin[0] >> 6;
288 parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
289 parsed_header->IC = data_begin[0] & 0x1f;
290 parsed_header->PT = data_begin[1];
292 parsed_header->length_in_octets =
293 ((data_begin[2] << 8) + data_begin[3] + 1) * 4;
295 if (parsed_header->length_in_octets == 0)
296 return false;
298 // Check if RTP version field == 2.
299 if (parsed_header->V != 2)
300 return false;
302 return true;
305 bool RtcpParser::ParseRR() {
306 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
307 if (length < 8)
308 return false;
310 field_type_ = kRtcpRrCode;
312 net::BigEndianReader big_endian_reader(rtcp_data_, length);
313 big_endian_reader.Skip(4); // Skip header
314 big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
315 field_.receiver_report.number_of_report_blocks = number_of_blocks_;
316 rtcp_data_ += 8;
318 // State transition
319 state_ = kStateReportBlock;
320 return true;
323 bool RtcpParser::ParseSR() {
324 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
325 if (length < 28) {
326 EndCurrentBlock();
327 return false;
329 field_type_ = kRtcpSrCode;
331 net::BigEndianReader big_endian_reader(rtcp_data_, length);
332 big_endian_reader.Skip(4); // Skip header
333 big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
334 big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
335 big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant);
336 big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp);
337 big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count);
338 big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count);
339 field_.sender_report.number_of_report_blocks = number_of_blocks_;
340 rtcp_data_ += 28;
342 if (number_of_blocks_ != 0) {
343 // State transition.
344 state_ = kStateReportBlock;
345 } else {
346 // Don't go to state report block item if 0 report blocks.
347 state_ = kStateTopLevel;
348 EndCurrentBlock();
350 return true;
353 bool RtcpParser::ParseReportBlockItem() {
354 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
355 if (length < 24 || number_of_blocks_ <= 0) {
356 state_ = kStateTopLevel;
357 EndCurrentBlock();
358 return false;
361 net::BigEndianReader big_endian_reader(rtcp_data_, length);
362 big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
363 big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
365 uint8 temp_number_of_packets_lost;
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 << 16;
369 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
370 field_.report_block_item.cumulative_number_of_packets_lost +=
371 temp_number_of_packets_lost << 8;
372 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
373 field_.report_block_item.cumulative_number_of_packets_lost +=
374 temp_number_of_packets_lost;
376 big_endian_reader.ReadU32(
377 &field_.report_block_item.extended_highest_sequence_number);
378 big_endian_reader.ReadU32(&field_.report_block_item.jitter);
379 big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report);
380 big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report);
381 rtcp_data_ += 24;
383 number_of_blocks_--;
384 field_type_ = kRtcpReportBlockItemCode;
385 return true;
388 bool RtcpParser::ParseSdes() {
389 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
391 if (length < 8) {
392 state_ = kStateTopLevel;
393 EndCurrentBlock();
394 return false;
396 rtcp_data_ += 4; // Skip header
398 state_ = kStateSdes;
399 field_type_ = kRtcpSdesCode;
400 return true;
403 bool RtcpParser::ParseSdesItem() {
404 if (number_of_blocks_ <= 0) {
405 state_ = kStateTopLevel;
406 EndCurrentBlock();
407 return false;
409 number_of_blocks_--;
411 // Find c_name item in a Sdes chunk.
412 while (rtcp_data_ < rtcp_block_end_) {
413 ptrdiff_t data_length = rtcp_block_end_ - rtcp_data_;
414 if (data_length < 4) {
415 state_ = kStateTopLevel;
416 EndCurrentBlock();
417 return false;
420 uint32 ssrc;
421 net::BigEndianReader big_endian_reader(rtcp_data_, data_length);
422 big_endian_reader.ReadU32(&ssrc);
423 rtcp_data_ += 4;
425 bool found_c_name = ParseSdesTypes();
426 if (found_c_name) {
427 field_.c_name.sender_ssrc = ssrc;
428 return true;
431 state_ = kStateTopLevel;
432 EndCurrentBlock();
433 return false;
436 bool RtcpParser::ParseSdesTypes() {
437 // Only the c_name item is mandatory. RFC 3550 page 46.
438 bool found_c_name = false;
439 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
440 net::BigEndianReader big_endian_reader(rtcp_data_, length);
442 while (big_endian_reader.remaining() > 0) {
443 uint8 tag;
444 big_endian_reader.ReadU8(&tag);
446 if (tag == 0) {
447 // End tag! 4 octet aligned.
448 rtcp_data_ = rtcp_block_end_;
449 return found_c_name;
452 if (big_endian_reader.remaining() > 0) {
453 uint8 len;
454 big_endian_reader.ReadU8(&len);
456 if (tag == 1) { // c_name.
457 // Sanity check.
458 if (big_endian_reader.remaining() < len) {
459 state_ = kStateTopLevel;
460 EndCurrentBlock();
461 return false;
463 int i = 0;
464 for (; i < len; ++i) {
465 uint8 c;
466 big_endian_reader.ReadU8(&c);
467 if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\')) {
468 // Illegal char.
469 state_ = kStateTopLevel;
470 EndCurrentBlock();
471 return false;
473 field_.c_name.name[i] = c;
475 // Make sure we are null terminated.
476 field_.c_name.name[i] = 0;
477 field_type_ = kRtcpSdesChunkCode;
478 found_c_name = true;
479 } else {
480 big_endian_reader.Skip(len);
484 // No end tag found!
485 state_ = kStateTopLevel;
486 EndCurrentBlock();
487 return false;
490 bool RtcpParser::ParseBye() {
491 rtcp_data_ += 4; // Skip header.
492 state_ = kStateBye;
493 return ParseByeItem();
496 bool RtcpParser::ParseByeItem() {
497 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
498 if (length < 4 || number_of_blocks_ == 0) {
499 state_ = kStateTopLevel;
500 EndCurrentBlock();
501 return false;
504 field_type_ = kRtcpByeCode;
506 net::BigEndianReader big_endian_reader(rtcp_data_, length);
507 big_endian_reader.ReadU32(&field_.bye.sender_ssrc);
508 rtcp_data_ += 4;
510 // We can have several CSRCs attached.
511 if (length >= 4 * number_of_blocks_) {
512 rtcp_data_ += (number_of_blocks_ - 1) * 4;
514 number_of_blocks_ = 0;
515 return true;
518 bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
519 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
520 if (length < 16 ||
521 !(subtype == kSenderLogSubtype || subtype == kReceiverLogSubtype)) {
522 state_ = kStateTopLevel;
523 EndCurrentBlock();
524 return false;
527 uint32 sender_ssrc;
528 uint32 name;
530 net::BigEndianReader big_endian_reader(rtcp_data_, length);
531 big_endian_reader.Skip(4); // Skip header.
532 big_endian_reader.ReadU32(&sender_ssrc);
533 big_endian_reader.ReadU32(&name);
535 if (name != kCast) {
536 state_ = kStateTopLevel;
537 EndCurrentBlock();
538 return false;
540 rtcp_data_ += 12;
541 switch (subtype) {
542 case kSenderLogSubtype:
543 state_ = kStateApplicationSpecificCastSenderLog;
544 field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
545 field_.cast_sender_log.sender_ssrc = sender_ssrc;
546 break;
547 case kReceiverLogSubtype:
548 state_ = kStateApplicationSpecificCastReceiverFrameLog;
549 field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
550 field_.cast_receiver_log.sender_ssrc = sender_ssrc;
551 break;
552 default:
553 NOTREACHED();
555 return true;
558 bool RtcpParser::ParseCastReceiverLogFrameItem() {
559 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
560 if (length < 12) {
561 state_ = kStateTopLevel;
562 EndCurrentBlock();
563 return false;
565 uint32 rtp_timestamp;
566 uint32 data;
567 net::BigEndianReader big_endian_reader(rtcp_data_, length);
568 big_endian_reader.ReadU32(&rtp_timestamp);
569 big_endian_reader.ReadU32(&data);
571 rtcp_data_ += 8;
573 field_.cast_receiver_log.rtp_timestamp = rtp_timestamp;
574 // We have 24 LSB of the event timestamp base on the wire.
575 field_.cast_receiver_log.event_timestamp_base = data & 0xffffff;
577 number_of_blocks_ = 1 + static_cast<uint8>(data >> 24);
578 state_ = kStateApplicationSpecificCastReceiverEventLog;
579 field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode;
580 return true;
583 bool RtcpParser::ParseCastReceiverLogEventItem() {
584 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
585 if (length < 4) {
586 state_ = kStateTopLevel;
587 EndCurrentBlock();
588 return false;
590 if (number_of_blocks_ == 0) {
591 // Continue parsing the next receiver frame event.
592 state_ = kStateApplicationSpecificCastReceiverFrameLog;
593 return false;
595 number_of_blocks_--;
597 uint16 delay_delta_or_packet_id;
598 uint16 event_type_and_timestamp_delta;
599 net::BigEndianReader big_endian_reader(rtcp_data_, length);
600 big_endian_reader.ReadU16(&delay_delta_or_packet_id);
601 big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
603 rtcp_data_ += 4;
605 field_.cast_receiver_log.event =
606 static_cast<uint8>(event_type_and_timestamp_delta >> 12);
607 field_.cast_receiver_log.delay_delta_or_packet_id = delay_delta_or_packet_id;
608 field_.cast_receiver_log.event_timestamp_delta =
609 event_type_and_timestamp_delta & 0xfff;
611 field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode;
612 return true;
615 bool RtcpParser::ParseCastSenderLogItem() {
616 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
618 if (length < 4) {
619 state_ = kStateTopLevel;
620 EndCurrentBlock();
621 return false;
623 uint32 data;
624 net::BigEndianReader big_endian_reader(rtcp_data_, length);
625 big_endian_reader.ReadU32(&data);
627 rtcp_data_ += 4;
629 field_.cast_sender_log.status = static_cast<uint8>(data >> 24);
630 // We have 24 LSB of the RTP timestamp on the wire.
631 field_.cast_sender_log.rtp_timestamp = data & 0xffffff;
632 field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
633 return true;
636 bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
637 DCHECK((header.PT == transport::kPacketTypeGenericRtpFeedback) ||
638 (header.PT == transport::kPacketTypePayloadSpecific))
639 << "Invalid state";
641 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
643 if (length < 12) { // 4 * 3, RFC4585 section 6.1
644 EndCurrentBlock();
645 return false;
648 uint32 sender_ssrc;
649 uint32 media_ssrc;
650 net::BigEndianReader big_endian_reader(rtcp_data_, length);
651 big_endian_reader.Skip(4); // Skip header.
652 big_endian_reader.ReadU32(&sender_ssrc);
653 big_endian_reader.ReadU32(&media_ssrc);
655 rtcp_data_ += 12;
657 if (header.PT == transport::kPacketTypeGenericRtpFeedback) {
658 // Transport layer feedback
659 switch (header.IC) {
660 case 1:
661 // Nack
662 field_type_ = kRtcpGenericRtpFeedbackNackCode;
663 field_.nack.sender_ssrc = sender_ssrc;
664 field_.nack.media_ssrc = media_ssrc;
665 state_ = kStateGenericRtpFeedbackNack;
666 return true;
667 case 2:
668 // Used to be ACK is this code point, which is removed conficts with
669 // http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
670 break;
671 case 3:
672 // Tmmbr
673 break;
674 case 4:
675 // Tmmbn
676 break;
677 case 5:
678 // RFC 6051 RTCP-sender_report-REQ Rapid Synchronisation of RTP Flows
679 // Trigger a new Rtcp sender_report
680 field_type_ = kRtcpGenericRtpFeedbackSrReqCode;
682 // Note: No state transition, sender report REQ is empty!
683 return true;
684 default:
685 break;
687 EndCurrentBlock();
688 return false;
690 } else if (header.PT == transport::kPacketTypePayloadSpecific) {
691 // Payload specific feedback
692 switch (header.IC) {
693 case 1:
694 // PLI
695 field_type_ = kRtcpPayloadSpecificPliCode;
696 field_.pli.sender_ssrc = sender_ssrc;
697 field_.pli.media_ssrc = media_ssrc;
699 // Note: No state transition, PLI FCI is empty!
700 return true;
701 case 2:
702 // Sli
703 break;
704 case 3:
705 field_type_ = kRtcpPayloadSpecificRpsiCode;
706 field_.rpsi.sender_ssrc = sender_ssrc;
707 field_.rpsi.media_ssrc = media_ssrc;
708 state_ = kStatePayloadSpecificRpsi;
709 return true;
710 case 4:
711 // fir
712 break;
713 case 15:
714 field_type_ = kRtcpPayloadSpecificAppCode;
715 field_.application_specific.sender_ssrc = sender_ssrc;
716 field_.application_specific.media_ssrc = media_ssrc;
717 state_ = kStatePayloadSpecificApplication;
718 return true;
719 default:
720 break;
723 EndCurrentBlock();
724 return false;
725 } else {
726 DCHECK(false) << "Invalid state";
727 EndCurrentBlock();
728 return false;
732 bool RtcpParser::ParseRpsiItem() {
733 // RFC 4585 6.3.3. Reference Picture Selection Indication (rpsi)
735 0 1 2 3
736 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
737 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
738 | PB |0| Payload Type| Native rpsi bit string |
739 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
740 | defined per codec ... | Padding (0) |
741 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
743 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
745 if (length < 4) {
746 state_ = kStateTopLevel;
747 EndCurrentBlock();
748 return false;
750 if (length > 2 + kRtcpRpsiDataSize) {
751 state_ = kStateTopLevel;
752 EndCurrentBlock();
753 return false;
756 field_type_ = kRtcpPayloadSpecificRpsiCode;
758 uint8 padding_bits;
759 net::BigEndianReader big_endian_reader(rtcp_data_, length);
760 big_endian_reader.ReadU8(&padding_bits);
761 big_endian_reader.ReadU8(&field_.rpsi.payload_type);
762 big_endian_reader.ReadBytes(&field_.rpsi.native_bit_string, length - 2);
763 field_.rpsi.number_of_valid_bits =
764 static_cast<uint16>(length - 2) * 8 - padding_bits;
766 rtcp_data_ += length;
767 return true;
770 bool RtcpParser::ParseNackItem() {
771 // RFC 4585 6.2.1. Generic Nack
773 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
774 if (length < 4) {
775 state_ = kStateTopLevel;
776 EndCurrentBlock();
777 return false;
780 field_type_ = kRtcpGenericRtpFeedbackNackItemCode;
782 net::BigEndianReader big_endian_reader(rtcp_data_, length);
783 big_endian_reader.ReadU16(&field_.nack_item.packet_id);
784 big_endian_reader.ReadU16(&field_.nack_item.bitmask);
785 rtcp_data_ += 4;
786 return true;
789 bool RtcpParser::ParsePayloadSpecificAppItem() {
790 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
792 if (length < 4) {
793 state_ = kStateTopLevel;
794 EndCurrentBlock();
795 return false;
797 uint32 name;
798 net::BigEndianReader big_endian_reader(rtcp_data_, length);
799 big_endian_reader.ReadU32(&name);
800 rtcp_data_ += 4;
802 if (name == kRemb) {
803 field_type_ = kRtcpPayloadSpecificRembCode;
804 state_ = kStatePayloadSpecificRemb;
805 return true;
806 } else if (name == kCast) {
807 field_type_ = kRtcpPayloadSpecificCastCode;
808 state_ = kStatePayloadSpecificCast;
809 return true;
811 state_ = kStateTopLevel;
812 EndCurrentBlock();
813 return false;
816 bool RtcpParser::ParsePayloadSpecificRembItem() {
817 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
819 if (length < 4) {
820 state_ = kStateTopLevel;
821 EndCurrentBlock();
822 return false;
825 net::BigEndianReader big_endian_reader(rtcp_data_, length);
826 big_endian_reader.ReadU8(&field_.remb_item.number_of_ssrcs);
828 uint8 byte_1;
829 uint8 byte_2;
830 uint8 byte_3;
831 big_endian_reader.ReadU8(&byte_1);
832 big_endian_reader.ReadU8(&byte_2);
833 big_endian_reader.ReadU8(&byte_3);
834 rtcp_data_ += 4;
836 uint8 br_exp = (byte_1 >> 2) & 0x3F;
837 uint32 br_mantissa = ((byte_1 & 0x03) << 16) + (byte_2 << 8) + byte_3;
838 field_.remb_item.bitrate = (br_mantissa << br_exp);
840 ptrdiff_t length_ssrcs = rtcp_block_end_ - rtcp_data_;
841 if (length_ssrcs < 4 * field_.remb_item.number_of_ssrcs) {
842 state_ = kStateTopLevel;
843 EndCurrentBlock();
844 return false;
847 field_type_ = kRtcpPayloadSpecificRembItemCode;
849 for (int i = 0; i < field_.remb_item.number_of_ssrcs; i++) {
850 big_endian_reader.ReadU32(&field_.remb_item.ssrcs[i]);
852 return true;
855 bool RtcpParser::ParsePayloadSpecificCastItem() {
856 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
857 if (length < 4) {
858 state_ = kStateTopLevel;
859 EndCurrentBlock();
860 return false;
862 field_type_ = kRtcpPayloadSpecificCastCode;
864 net::BigEndianReader big_endian_reader(rtcp_data_, length);
865 big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
866 big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
868 rtcp_data_ += 4;
870 if (field_.cast_item.number_of_lost_fields != 0) {
871 // State transition
872 state_ = kStatePayloadSpecificCastNack;
873 } else {
874 // Don't go to state cast nack item if got 0 fields.
875 state_ = kStateTopLevel;
876 EndCurrentBlock();
878 return true;
881 bool RtcpParser::ParsePayloadSpecificCastNackItem() {
882 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
883 if (length < 4) {
884 state_ = kStateTopLevel;
885 EndCurrentBlock();
886 return false;
888 field_type_ = kRtcpPayloadSpecificCastNackItemCode;
890 net::BigEndianReader big_endian_reader(rtcp_data_, length);
891 big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
892 big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
893 big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
895 rtcp_data_ += 4;
896 return true;
899 bool RtcpParser::ParseFirItem() {
900 // RFC 5104 4.3.1. Full Intra Request (fir)
901 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
903 if (length < 8) {
904 state_ = kStateTopLevel;
905 EndCurrentBlock();
906 return false;
908 field_type_ = kRtcpPayloadSpecificFirItemCode;
910 net::BigEndianReader big_endian_reader(rtcp_data_, length);
911 big_endian_reader.ReadU32(&field_.fir_item.ssrc);
912 big_endian_reader.ReadU8(&field_.fir_item.command_sequence_number);
914 rtcp_data_ += 8;
915 return true;
918 bool RtcpParser::ParseExtendedReport() {
919 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
920 if (length < 8)
921 return false;
923 field_type_ = kRtcpXrCode;
925 net::BigEndianReader big_endian_reader(rtcp_data_, length);
926 big_endian_reader.Skip(4); // Skip header.
927 big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
929 rtcp_data_ += 8;
931 state_ = kStateExtendedReportBlock;
932 return true;
935 bool RtcpParser::ParseExtendedReportItem() {
936 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
937 if (length < 4) {
938 state_ = kStateTopLevel;
939 EndCurrentBlock();
940 return false;
943 uint8 block_type;
944 uint16 block_length;
945 net::BigEndianReader big_endian_reader(rtcp_data_, length);
946 big_endian_reader.ReadU8(&block_type);
947 big_endian_reader.Skip(1); // Ignore reserved.
948 big_endian_reader.ReadU16(&block_length);
950 rtcp_data_ += 4;
952 switch (block_type) {
953 case 4:
954 if (block_length != 2) {
955 // Invalid block length.
956 state_ = kStateTopLevel;
957 EndCurrentBlock();
958 return false;
960 return ParseExtendedReportReceiverReferenceTimeReport();
961 case 5:
962 if (block_length % 3 != 0) {
963 // Invalid block length.
964 state_ = kStateTopLevel;
965 EndCurrentBlock();
966 return false;
968 if (block_length >= 3) {
969 number_of_blocks_ = block_length / 3;
970 state_ = kStateExtendedReportDelaySinceLastReceiverReport;
971 return ParseExtendedReportDelaySinceLastReceiverReport();
973 return true;
974 default:
975 if (length < block_length * 4) {
976 state_ = kStateTopLevel;
977 EndCurrentBlock();
978 return false;
980 field_type_ = kRtcpXrUnknownItemCode;
981 rtcp_data_ += block_length * 4;
982 return true;
986 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
987 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
988 if (length < 8) {
989 state_ = kStateTopLevel;
990 EndCurrentBlock();
991 return false;
994 net::BigEndianReader big_endian_reader(rtcp_data_, length);
995 big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
996 big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
998 rtcp_data_ += 8;
1000 field_type_ = kRtcpXrRrtrCode;
1001 return true;
1004 bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
1005 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
1006 if (length < 12) {
1007 state_ = kStateTopLevel;
1008 EndCurrentBlock();
1009 return false;
1011 if (number_of_blocks_ == 0) {
1012 // Continue parsing the extended report block.
1013 state_ = kStateExtendedReportBlock;
1014 return false;
1017 net::BigEndianReader big_endian_reader(rtcp_data_, length);
1018 big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
1019 big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
1020 big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
1022 rtcp_data_ += 12;
1024 number_of_blocks_--;
1025 field_type_ = kRtcpXrDlrrCode;
1026 return true;
1029 } // namespace cast
1030 } // namespace media