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/big_endian.h"
8 #include "base/logging.h"
9 #include "media/cast/net/cast_transport_defines.h"
14 RtcpParser::RtcpParser(const uint8* rtcpData, size_t rtcpDataLength)
15 : rtcp_data_begin_(rtcpData),
16 rtcp_data_end_(rtcpData + rtcpDataLength),
19 rtcp_block_end_(NULL),
20 state_(kStateTopLevel),
22 field_type_(kRtcpNotValidCode) {
23 memset(&field_, 0, sizeof(field_));
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_;
38 RtcpFieldTypes RtcpParser::Iterate() {
40 field_type_ = kRtcpNotValidCode;
43 return kRtcpNotValidCode;
49 case kStateReportBlock:
50 IterateReportBlockItem();
52 case kStateApplicationSpecificCastReceiverFrameLog:
53 IterateCastReceiverLogFrame();
55 case kStateApplicationSpecificCastReceiverEventLog:
56 IterateCastReceiverLogEvent();
58 case kStateExtendedReportBlock:
59 IterateExtendedReportItem();
61 case kStateExtendedReportDelaySinceLastReceiverReport:
62 IterateExtendedReportDelaySinceLastReceiverReportItem();
64 case kStatePayloadSpecificApplication:
65 IteratePayloadSpecificAppItem();
67 case kStatePayloadSpecificCast:
68 IteratePayloadSpecificCastItem();
70 case kStatePayloadSpecificCastNack:
71 IteratePayloadSpecificCastNackItem();
77 void RtcpParser::IterateTopLevel() {
79 RtcpCommonHeader header;
81 bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
85 rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
87 if (rtcp_block_end_ > rtcp_data_end_)
91 case kPacketTypeSenderReport:
92 // number of Report blocks
93 number_of_blocks_ = header.IC;
96 case kPacketTypeReceiverReport:
97 // number of Report blocks
98 number_of_blocks_ = header.IC;
101 case kPacketTypeApplicationDefined:
102 if (!ParseApplicationDefined(header.IC)) {
103 // Nothing supported found, continue to next block!
107 case kPacketTypeGenericRtpFeedback: // Fall through!
108 case kPacketTypePayloadSpecific:
109 if (!ParseFeedBackCommon(header)) {
110 // Nothing supported found, continue to next block!
115 if (!ParseExtendedReport()) {
116 break; // Nothing supported found, continue to next block!
120 // Not supported! Skip!
127 void RtcpParser::IterateReportBlockItem() {
128 bool success = ParseReportBlockItem();
133 void RtcpParser::IterateExtendedReportItem() {
134 bool success = ParseExtendedReportItem();
139 void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
140 bool success = ParseExtendedReportDelaySinceLastReceiverReport();
145 void RtcpParser::IteratePayloadSpecificAppItem() {
146 bool success = ParsePayloadSpecificAppItem();
151 void RtcpParser::IteratePayloadSpecificCastItem() {
152 bool success = ParsePayloadSpecificCastItem();
157 void RtcpParser::IteratePayloadSpecificCastNackItem() {
158 bool success = ParsePayloadSpecificCastNackItem();
163 void RtcpParser::IterateCastReceiverLogFrame() {
164 bool success = ParseCastReceiverLogFrameItem();
169 void RtcpParser::IterateCastReceiverLogEvent() {
170 bool success = ParseCastReceiverLogEventItem();
175 void RtcpParser::Validate() {
176 if (rtcp_data_ == NULL)
179 RtcpCommonHeader header;
181 RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header);
184 return; // NOT VALID!
186 valid_packet_ = true;
189 bool RtcpParser::IsValid() const { return valid_packet_; }
191 void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; }
193 bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
194 const uint8* data_end,
195 RtcpCommonHeader* parsed_header) const {
196 if (!data_begin || !data_end)
200 // 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
201 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202 // |V=2|P| IC | PT | length |
203 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205 // Common header for all Rtcp packets, 4 octets.
207 if ((data_end - data_begin) < 4)
210 parsed_header->V = data_begin[0] >> 6;
211 parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
212 parsed_header->IC = data_begin[0] & 0x1f;
213 parsed_header->PT = data_begin[1];
215 parsed_header->length_in_octets =
216 ((data_begin[2] << 8) + data_begin[3] + 1) * 4;
218 if (parsed_header->length_in_octets == 0)
221 // Check if RTP version field == 2.
222 if (parsed_header->V != 2)
228 bool RtcpParser::ParseRR() {
229 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
233 field_type_ = kRtcpRrCode;
235 base::BigEndianReader big_endian_reader(
236 reinterpret_cast<const char*>(rtcp_data_), length);
237 big_endian_reader.Skip(4); // Skip header
238 big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
239 field_.receiver_report.number_of_report_blocks = number_of_blocks_;
243 state_ = kStateReportBlock;
247 bool RtcpParser::ParseSR() {
248 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
253 field_type_ = kRtcpSrCode;
255 base::BigEndianReader big_endian_reader(
256 reinterpret_cast<const char*>(rtcp_data_), length);
257 big_endian_reader.Skip(4); // Skip header
258 big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
259 big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
260 big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant);
261 big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp);
262 big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count);
263 big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count);
264 field_.sender_report.number_of_report_blocks = number_of_blocks_;
267 if (number_of_blocks_ != 0) {
269 state_ = kStateReportBlock;
271 // Don't go to state report block item if 0 report blocks.
272 state_ = kStateTopLevel;
278 bool RtcpParser::ParseReportBlockItem() {
279 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
280 if (length < 24 || number_of_blocks_ <= 0) {
281 state_ = kStateTopLevel;
286 base::BigEndianReader big_endian_reader(
287 reinterpret_cast<const char*>(rtcp_data_), length);
288 big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
289 big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
291 uint8 temp_number_of_packets_lost;
292 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
293 field_.report_block_item.cumulative_number_of_packets_lost =
294 temp_number_of_packets_lost << 16;
295 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
296 field_.report_block_item.cumulative_number_of_packets_lost +=
297 temp_number_of_packets_lost << 8;
298 big_endian_reader.ReadU8(&temp_number_of_packets_lost);
299 field_.report_block_item.cumulative_number_of_packets_lost +=
300 temp_number_of_packets_lost;
302 big_endian_reader.ReadU32(
303 &field_.report_block_item.extended_highest_sequence_number);
304 big_endian_reader.ReadU32(&field_.report_block_item.jitter);
305 big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report);
306 big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report);
310 field_type_ = kRtcpReportBlockItemCode;
314 bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
315 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
316 if (length < 16 || subtype != kReceiverLogSubtype) {
317 state_ = kStateTopLevel;
325 base::BigEndianReader big_endian_reader(
326 reinterpret_cast<const char*>(rtcp_data_), length);
327 big_endian_reader.Skip(4); // Skip header.
328 big_endian_reader.ReadU32(&sender_ssrc);
329 big_endian_reader.ReadU32(&name);
332 state_ = kStateTopLevel;
338 case kReceiverLogSubtype:
339 state_ = kStateApplicationSpecificCastReceiverFrameLog;
340 field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
341 field_.cast_receiver_log.sender_ssrc = sender_ssrc;
349 bool RtcpParser::ParseCastReceiverLogFrameItem() {
350 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
352 state_ = kStateTopLevel;
356 uint32 rtp_timestamp;
358 base::BigEndianReader big_endian_reader(
359 reinterpret_cast<const char*>(rtcp_data_), length);
360 big_endian_reader.ReadU32(&rtp_timestamp);
361 big_endian_reader.ReadU32(&data);
365 field_.cast_receiver_log.rtp_timestamp = rtp_timestamp;
366 // We have 24 LSB of the event timestamp base on the wire.
367 field_.cast_receiver_log.event_timestamp_base = data & 0xffffff;
369 number_of_blocks_ = 1 + static_cast<uint8>(data >> 24);
370 state_ = kStateApplicationSpecificCastReceiverEventLog;
371 field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode;
375 bool RtcpParser::ParseCastReceiverLogEventItem() {
376 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
378 state_ = kStateTopLevel;
382 if (number_of_blocks_ == 0) {
383 // Continue parsing the next receiver frame event.
384 state_ = kStateApplicationSpecificCastReceiverFrameLog;
389 uint16 delay_delta_or_packet_id;
390 uint16 event_type_and_timestamp_delta;
391 base::BigEndianReader big_endian_reader(
392 reinterpret_cast<const char*>(rtcp_data_), length);
393 big_endian_reader.ReadU16(&delay_delta_or_packet_id);
394 big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
398 field_.cast_receiver_log.event =
399 static_cast<uint8>(event_type_and_timestamp_delta >> 12);
400 // delay_delta is in union'ed with packet_id.
401 field_.cast_receiver_log.delay_delta_or_packet_id.packet_id =
402 delay_delta_or_packet_id;
403 field_.cast_receiver_log.event_timestamp_delta =
404 event_type_and_timestamp_delta & 0xfff;
406 field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode;
410 bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
411 DCHECK((header.PT == kPacketTypeGenericRtpFeedback) ||
412 (header.PT == kPacketTypePayloadSpecific))
415 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
417 if (length < 12) { // 4 * 3, RFC4585 section 6.1
424 base::BigEndianReader big_endian_reader(
425 reinterpret_cast<const char*>(rtcp_data_), length);
426 big_endian_reader.Skip(4); // Skip header.
427 big_endian_reader.ReadU32(&sender_ssrc);
428 big_endian_reader.ReadU32(&media_ssrc);
432 if (header.PT == kPacketTypePayloadSpecific) {
433 // Payload specific feedback
448 field_type_ = kRtcpPayloadSpecificAppCode;
449 field_.application_specific.sender_ssrc = sender_ssrc;
450 field_.application_specific.media_ssrc = media_ssrc;
451 state_ = kStatePayloadSpecificApplication;
460 DCHECK(false) << "Invalid state";
466 bool RtcpParser::ParsePayloadSpecificAppItem() {
467 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
470 state_ = kStateTopLevel;
475 base::BigEndianReader big_endian_reader(
476 reinterpret_cast<const char*>(rtcp_data_), length);
477 big_endian_reader.ReadU32(&name);
481 field_type_ = kRtcpPayloadSpecificCastCode;
482 state_ = kStatePayloadSpecificCast;
485 state_ = kStateTopLevel;
490 bool RtcpParser::ParsePayloadSpecificCastItem() {
491 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
493 state_ = kStateTopLevel;
497 field_type_ = kRtcpPayloadSpecificCastCode;
499 base::BigEndianReader big_endian_reader(
500 reinterpret_cast<const char*>(rtcp_data_), length);
501 big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
502 big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
503 big_endian_reader.ReadU16(&field_.cast_item.target_delay_ms);
507 if (field_.cast_item.number_of_lost_fields != 0) {
509 state_ = kStatePayloadSpecificCastNack;
511 // Don't go to state cast nack item if got 0 fields.
512 state_ = kStateTopLevel;
518 bool RtcpParser::ParsePayloadSpecificCastNackItem() {
519 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
521 state_ = kStateTopLevel;
525 field_type_ = kRtcpPayloadSpecificCastNackItemCode;
527 base::BigEndianReader big_endian_reader(
528 reinterpret_cast<const char*>(rtcp_data_), length);
529 big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
530 big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
531 big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
537 bool RtcpParser::ParseExtendedReport() {
538 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
542 field_type_ = kRtcpXrCode;
544 base::BigEndianReader big_endian_reader(
545 reinterpret_cast<const char*>(rtcp_data_), length);
546 big_endian_reader.Skip(4); // Skip header.
547 big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
551 state_ = kStateExtendedReportBlock;
555 bool RtcpParser::ParseExtendedReportItem() {
556 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
558 state_ = kStateTopLevel;
565 base::BigEndianReader big_endian_reader(
566 reinterpret_cast<const char*>(rtcp_data_), length);
567 big_endian_reader.ReadU8(&block_type);
568 big_endian_reader.Skip(1); // Ignore reserved.
569 big_endian_reader.ReadU16(&block_length);
573 switch (block_type) {
574 case 4: // RRTR. RFC3611 Section 4.4.
575 if (block_length != 2) {
576 // Invalid block length.
577 state_ = kStateTopLevel;
581 return ParseExtendedReportReceiverReferenceTimeReport();
582 case 5: // DLRR. RFC3611 Section 4.5.
583 if (block_length % 3 != 0) {
584 // Invalid block length.
585 state_ = kStateTopLevel;
589 if (block_length >= 3) {
590 number_of_blocks_ = block_length / 3;
591 state_ = kStateExtendedReportDelaySinceLastReceiverReport;
592 return ParseExtendedReportDelaySinceLastReceiverReport();
596 if (length < block_length * 4) {
597 state_ = kStateTopLevel;
601 field_type_ = kRtcpXrUnknownItemCode;
602 rtcp_data_ += block_length * 4;
607 bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
608 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
610 state_ = kStateTopLevel;
615 base::BigEndianReader big_endian_reader(
616 reinterpret_cast<const char*>(rtcp_data_), length);
617 big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
618 big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
622 field_type_ = kRtcpXrRrtrCode;
626 bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
627 ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
629 state_ = kStateTopLevel;
633 if (number_of_blocks_ == 0) {
634 // Continue parsing the extended report block.
635 state_ = kStateExtendedReportBlock;
639 base::BigEndianReader big_endian_reader(
640 reinterpret_cast<const char*>(rtcp_data_), length);
641 big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
642 big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
643 big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
648 field_type_ = kRtcpXrDlrrCode;
652 // Converts a log event type to an integer value.
653 // NOTE: We have only allocated 4 bits to represent the type of event over the
654 // wire. Therefore, this function can only return values from 0 to 15.
655 uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) {
663 case PACKET_RECEIVED:
666 return 0; // Not an interesting event.
670 CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
671 // TODO(imcheng): Remove the old mappings once they are no longer used.
673 case 1: // AudioAckSent
674 case 5: // VideoAckSent
676 return FRAME_ACK_SENT;
677 case 2: // AudioPlayoutDelay
678 case 7: // VideoRenderDelay
680 return FRAME_PLAYOUT;
681 case 3: // AudioFrameDecoded
682 case 6: // VideoFrameDecoded
684 return FRAME_DECODED;
685 case 4: // AudioPacketReceived
686 case 8: // VideoPacketReceived
688 return PACKET_RECEIVED;
689 case 9: // DuplicateAudioPacketReceived
690 case 10: // DuplicateVideoPacketReceived
692 // If the sender adds new log messages we will end up here until we add
693 // the new messages in the receiver.
694 VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);