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

Unified Diff: media/cast/rtcp/rtcp_utility.cc

Issue 388663003: Cast: Reshuffle files under media/cast (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: missing includes Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/cast/rtcp/rtcp_utility.h ('k') | media/cast/rtcp/test_rtcp_packet_builder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/cast/rtcp/rtcp_utility.cc
diff --git a/media/cast/rtcp/rtcp_utility.cc b/media/cast/rtcp/rtcp_utility.cc
deleted file mode 100644
index e29f82e9cf93d0a8f41fc28c3b5239848cef51a4..0000000000000000000000000000000000000000
--- a/media/cast/rtcp/rtcp_utility.cc
+++ /dev/null
@@ -1,1066 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/cast/rtcp/rtcp_utility.h"
-
-#include "base/big_endian.h"
-#include "base/logging.h"
-#include "media/cast/transport/cast_transport_defines.h"
-
-namespace media {
-namespace cast {
-
-RtcpParser::RtcpParser(const uint8* rtcpData, size_t rtcpDataLength)
- : rtcp_data_begin_(rtcpData),
- rtcp_data_end_(rtcpData + rtcpDataLength),
- valid_packet_(false),
- rtcp_data_(rtcpData),
- rtcp_block_end_(NULL),
- state_(kStateTopLevel),
- number_of_blocks_(0),
- field_type_(kRtcpNotValidCode) {
- memset(&field_, 0, sizeof(field_));
- Validate();
-}
-
-RtcpParser::~RtcpParser() {}
-
-RtcpFieldTypes RtcpParser::FieldType() const { return field_type_; }
-
-const RtcpField& RtcpParser::Field() const { return field_; }
-
-RtcpFieldTypes RtcpParser::Begin() {
- rtcp_data_ = rtcp_data_begin_;
- return Iterate();
-}
-
-RtcpFieldTypes RtcpParser::Iterate() {
- // Reset packet type
- field_type_ = kRtcpNotValidCode;
-
- if (!IsValid())
- return kRtcpNotValidCode;
-
- switch (state_) {
- case kStateTopLevel:
- IterateTopLevel();
- break;
- case kStateReportBlock:
- IterateReportBlockItem();
- break;
- case kStateSdes:
- IterateSdesItem();
- break;
- case kStateBye:
- IterateByeItem();
- break;
- case kStateApplicationSpecificCastReceiverFrameLog:
- IterateCastReceiverLogFrame();
- break;
- case kStateApplicationSpecificCastReceiverEventLog:
- IterateCastReceiverLogEvent();
- break;
- case kStateExtendedReportBlock:
- IterateExtendedReportItem();
- break;
- case kStateExtendedReportDelaySinceLastReceiverReport:
- IterateExtendedReportDelaySinceLastReceiverReportItem();
- break;
- case kStateGenericRtpFeedbackNack:
- IterateNackItem();
- break;
- case kStatePayloadSpecificRpsi:
- IterateRpsiItem();
- break;
- case kStatePayloadSpecificFir:
- IterateFirItem();
- break;
- case kStatePayloadSpecificApplication:
- IteratePayloadSpecificAppItem();
- break;
- case kStatePayloadSpecificRemb:
- IteratePayloadSpecificRembItem();
- break;
- case kStatePayloadSpecificCast:
- IteratePayloadSpecificCastItem();
- break;
- case kStatePayloadSpecificCastNack:
- IteratePayloadSpecificCastNackItem();
- break;
- }
- return field_type_;
-}
-
-void RtcpParser::IterateTopLevel() {
- for (;;) {
- RtcpCommonHeader header;
-
- bool success = RtcpParseCommonHeader(rtcp_data_, rtcp_data_end_, &header);
- if (!success)
- return;
-
- rtcp_block_end_ = rtcp_data_ + header.length_in_octets;
-
- if (rtcp_block_end_ > rtcp_data_end_)
- return; // Bad block!
-
- switch (header.PT) {
- case transport::kPacketTypeSenderReport:
- // number of Report blocks
- number_of_blocks_ = header.IC;
- ParseSR();
- return;
- case transport::kPacketTypeReceiverReport:
- // number of Report blocks
- number_of_blocks_ = header.IC;
- ParseRR();
- return;
- case transport::kPacketTypeSdes:
- // number of Sdes blocks
- number_of_blocks_ = header.IC;
- if (!ParseSdes()) {
- break; // Nothing supported found, continue to next block!
- }
- return;
- case transport::kPacketTypeBye:
- number_of_blocks_ = header.IC;
- if (!ParseBye()) {
- // Nothing supported found, continue to next block!
- break;
- }
- return;
- case transport::kPacketTypeApplicationDefined:
- if (!ParseApplicationDefined(header.IC)) {
- // Nothing supported found, continue to next block!
- break;
- }
- return;
- case transport::kPacketTypeGenericRtpFeedback: // Fall through!
- case transport::kPacketTypePayloadSpecific:
- if (!ParseFeedBackCommon(header)) {
- // Nothing supported found, continue to next block!
- break;
- }
- return;
- case transport::kPacketTypeXr:
- if (!ParseExtendedReport()) {
- break; // Nothing supported found, continue to next block!
- }
- return;
- default:
- // Not supported! Skip!
- EndCurrentBlock();
- break;
- }
- }
-}
-
-void RtcpParser::IterateReportBlockItem() {
- bool success = ParseReportBlockItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateSdesItem() {
- bool success = ParseSdesItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateByeItem() {
- bool success = ParseByeItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateExtendedReportItem() {
- bool success = ParseExtendedReportItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateExtendedReportDelaySinceLastReceiverReportItem() {
- bool success = ParseExtendedReportDelaySinceLastReceiverReport();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateNackItem() {
- bool success = ParseNackItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateRpsiItem() {
- bool success = ParseRpsiItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateFirItem() {
- bool success = ParseFirItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IteratePayloadSpecificAppItem() {
- bool success = ParsePayloadSpecificAppItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IteratePayloadSpecificRembItem() {
- bool success = ParsePayloadSpecificRembItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IteratePayloadSpecificCastItem() {
- bool success = ParsePayloadSpecificCastItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IteratePayloadSpecificCastNackItem() {
- bool success = ParsePayloadSpecificCastNackItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateCastReceiverLogFrame() {
- bool success = ParseCastReceiverLogFrameItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::IterateCastReceiverLogEvent() {
- bool success = ParseCastReceiverLogEventItem();
- if (!success)
- Iterate();
-}
-
-void RtcpParser::Validate() {
- if (rtcp_data_ == NULL)
- return; // NOT VALID
-
- RtcpCommonHeader header;
- bool success =
- RtcpParseCommonHeader(rtcp_data_begin_, rtcp_data_end_, &header);
-
- if (!success)
- return; // NOT VALID!
-
- valid_packet_ = true;
-}
-
-bool RtcpParser::IsValid() const { return valid_packet_; }
-
-void RtcpParser::EndCurrentBlock() { rtcp_data_ = rtcp_block_end_; }
-
-bool RtcpParser::RtcpParseCommonHeader(const uint8* data_begin,
- const uint8* data_end,
- RtcpCommonHeader* parsed_header) const {
- if (!data_begin || !data_end)
- return false;
-
- // 0 1 2 3
- // 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
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // |V=2|P| IC | PT | length |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- //
- // Common header for all Rtcp packets, 4 octets.
-
- if ((data_end - data_begin) < 4)
- return false;
-
- parsed_header->V = data_begin[0] >> 6;
- parsed_header->P = ((data_begin[0] & 0x20) == 0) ? false : true;
- parsed_header->IC = data_begin[0] & 0x1f;
- parsed_header->PT = data_begin[1];
-
- parsed_header->length_in_octets =
- ((data_begin[2] << 8) + data_begin[3] + 1) * 4;
-
- if (parsed_header->length_in_octets == 0)
- return false;
-
- // Check if RTP version field == 2.
- if (parsed_header->V != 2)
- return false;
-
- return true;
-}
-
-bool RtcpParser::ParseRR() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 8)
- return false;
-
- field_type_ = kRtcpRrCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.Skip(4); // Skip header
- big_endian_reader.ReadU32(&field_.receiver_report.sender_ssrc);
- field_.receiver_report.number_of_report_blocks = number_of_blocks_;
- rtcp_data_ += 8;
-
- // State transition
- state_ = kStateReportBlock;
- return true;
-}
-
-bool RtcpParser::ParseSR() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 28) {
- EndCurrentBlock();
- return false;
- }
- field_type_ = kRtcpSrCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.Skip(4); // Skip header
- big_endian_reader.ReadU32(&field_.sender_report.sender_ssrc);
- big_endian_reader.ReadU32(&field_.sender_report.ntp_most_significant);
- big_endian_reader.ReadU32(&field_.sender_report.ntp_least_significant);
- big_endian_reader.ReadU32(&field_.sender_report.rtp_timestamp);
- big_endian_reader.ReadU32(&field_.sender_report.sender_packet_count);
- big_endian_reader.ReadU32(&field_.sender_report.sender_octet_count);
- field_.sender_report.number_of_report_blocks = number_of_blocks_;
- rtcp_data_ += 28;
-
- if (number_of_blocks_ != 0) {
- // State transition.
- state_ = kStateReportBlock;
- } else {
- // Don't go to state report block item if 0 report blocks.
- state_ = kStateTopLevel;
- EndCurrentBlock();
- }
- return true;
-}
-
-bool RtcpParser::ParseReportBlockItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 24 || number_of_blocks_ <= 0) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU32(&field_.report_block_item.ssrc);
- big_endian_reader.ReadU8(&field_.report_block_item.fraction_lost);
-
- uint8 temp_number_of_packets_lost;
- big_endian_reader.ReadU8(&temp_number_of_packets_lost);
- field_.report_block_item.cumulative_number_of_packets_lost =
- temp_number_of_packets_lost << 16;
- big_endian_reader.ReadU8(&temp_number_of_packets_lost);
- field_.report_block_item.cumulative_number_of_packets_lost +=
- temp_number_of_packets_lost << 8;
- big_endian_reader.ReadU8(&temp_number_of_packets_lost);
- field_.report_block_item.cumulative_number_of_packets_lost +=
- temp_number_of_packets_lost;
-
- big_endian_reader.ReadU32(
- &field_.report_block_item.extended_highest_sequence_number);
- big_endian_reader.ReadU32(&field_.report_block_item.jitter);
- big_endian_reader.ReadU32(&field_.report_block_item.last_sender_report);
- big_endian_reader.ReadU32(&field_.report_block_item.delay_last_sender_report);
- rtcp_data_ += 24;
-
- number_of_blocks_--;
- field_type_ = kRtcpReportBlockItemCode;
- return true;
-}
-
-bool RtcpParser::ParseSdes() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
-
- if (length < 8) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- rtcp_data_ += 4; // Skip header
-
- state_ = kStateSdes;
- field_type_ = kRtcpSdesCode;
- return true;
-}
-
-bool RtcpParser::ParseSdesItem() {
- if (number_of_blocks_ <= 0) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- number_of_blocks_--;
-
- // Find c_name item in a Sdes chunk.
- while (rtcp_data_ < rtcp_block_end_) {
- ptrdiff_t data_length = rtcp_block_end_ - rtcp_data_;
- if (data_length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- uint32 ssrc;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), data_length);
- big_endian_reader.ReadU32(&ssrc);
- rtcp_data_ += 4;
-
- bool found_c_name = ParseSdesTypes();
- if (found_c_name) {
- field_.c_name.sender_ssrc = ssrc;
- return true;
- }
- }
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
-}
-
-bool RtcpParser::ParseSdesTypes() {
- // Only the c_name item is mandatory. RFC 3550 page 46.
- bool found_c_name = false;
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
-
- while (big_endian_reader.remaining() > 0) {
- uint8 tag;
- big_endian_reader.ReadU8(&tag);
-
- if (tag == 0) {
- // End tag! 4 octet aligned.
- rtcp_data_ = rtcp_block_end_;
- return found_c_name;
- }
-
- if (big_endian_reader.remaining() > 0) {
- uint8 len;
- big_endian_reader.ReadU8(&len);
-
- if (tag == 1) { // c_name.
- // Sanity check.
- if (big_endian_reader.remaining() < len) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- int i = 0;
- for (; i < len; ++i) {
- uint8 c;
- big_endian_reader.ReadU8(&c);
- if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\')) {
- // Illegal char.
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- field_.c_name.name[i] = c;
- }
- // Make sure we are null terminated.
- field_.c_name.name[i] = 0;
- field_type_ = kRtcpSdesChunkCode;
- found_c_name = true;
- } else {
- big_endian_reader.Skip(len);
- }
- }
- }
- // No end tag found!
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
-}
-
-bool RtcpParser::ParseBye() {
- rtcp_data_ += 4; // Skip header.
- state_ = kStateBye;
- return ParseByeItem();
-}
-
-bool RtcpParser::ParseByeItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 4 || number_of_blocks_ == 0) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- field_type_ = kRtcpByeCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU32(&field_.bye.sender_ssrc);
- rtcp_data_ += 4;
-
- // We can have several CSRCs attached.
- if (length >= 4 * number_of_blocks_) {
- rtcp_data_ += (number_of_blocks_ - 1) * 4;
- }
- number_of_blocks_ = 0;
- return true;
-}
-
-bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 16 || subtype != kReceiverLogSubtype) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- uint32 sender_ssrc;
- uint32 name;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.Skip(4); // Skip header.
- big_endian_reader.ReadU32(&sender_ssrc);
- big_endian_reader.ReadU32(&name);
-
- if (name != kCast) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- rtcp_data_ += 12;
- switch (subtype) {
- case kReceiverLogSubtype:
- state_ = kStateApplicationSpecificCastReceiverFrameLog;
- field_type_ = kRtcpApplicationSpecificCastReceiverLogCode;
- field_.cast_receiver_log.sender_ssrc = sender_ssrc;
- break;
- default:
- NOTREACHED();
- }
- return true;
-}
-
-bool RtcpParser::ParseCastReceiverLogFrameItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 12) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- uint32 rtp_timestamp;
- uint32 data;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU32(&rtp_timestamp);
- big_endian_reader.ReadU32(&data);
-
- rtcp_data_ += 8;
-
- field_.cast_receiver_log.rtp_timestamp = rtp_timestamp;
- // We have 24 LSB of the event timestamp base on the wire.
- field_.cast_receiver_log.event_timestamp_base = data & 0xffffff;
-
- number_of_blocks_ = 1 + static_cast<uint8>(data >> 24);
- state_ = kStateApplicationSpecificCastReceiverEventLog;
- field_type_ = kRtcpApplicationSpecificCastReceiverLogFrameCode;
- return true;
-}
-
-bool RtcpParser::ParseCastReceiverLogEventItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- if (number_of_blocks_ == 0) {
- // Continue parsing the next receiver frame event.
- state_ = kStateApplicationSpecificCastReceiverFrameLog;
- return false;
- }
- number_of_blocks_--;
-
- uint16 delay_delta_or_packet_id;
- uint16 event_type_and_timestamp_delta;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU16(&delay_delta_or_packet_id);
- big_endian_reader.ReadU16(&event_type_and_timestamp_delta);
-
- rtcp_data_ += 4;
-
- field_.cast_receiver_log.event =
- static_cast<uint8>(event_type_and_timestamp_delta >> 12);
- // delay_delta is in union'ed with packet_id.
- field_.cast_receiver_log.delay_delta_or_packet_id.packet_id =
- delay_delta_or_packet_id;
- field_.cast_receiver_log.event_timestamp_delta =
- event_type_and_timestamp_delta & 0xfff;
-
- field_type_ = kRtcpApplicationSpecificCastReceiverLogEventCode;
- return true;
-}
-
-bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
- DCHECK((header.PT == transport::kPacketTypeGenericRtpFeedback) ||
- (header.PT == transport::kPacketTypePayloadSpecific))
- << "Invalid state";
-
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
-
- if (length < 12) { // 4 * 3, RFC4585 section 6.1
- EndCurrentBlock();
- return false;
- }
-
- uint32 sender_ssrc;
- uint32 media_ssrc;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.Skip(4); // Skip header.
- big_endian_reader.ReadU32(&sender_ssrc);
- big_endian_reader.ReadU32(&media_ssrc);
-
- rtcp_data_ += 12;
-
- if (header.PT == transport::kPacketTypeGenericRtpFeedback) {
- // Transport layer feedback
- switch (header.IC) {
- case 1:
- // Nack
- field_type_ = kRtcpGenericRtpFeedbackNackCode;
- field_.nack.sender_ssrc = sender_ssrc;
- field_.nack.media_ssrc = media_ssrc;
- state_ = kStateGenericRtpFeedbackNack;
- return true;
- case 2:
- // Used to be ACK is this code point, which is removed conficts with
- // http://tools.ietf.org/html/draft-levin-avt-rtcp-burst-00
- break;
- case 3:
- // Tmmbr
- break;
- case 4:
- // Tmmbn
- break;
- case 5:
- // RFC 6051 RTCP-sender_report-REQ Rapid Synchronisation of RTP Flows
- // Trigger a new Rtcp sender_report
- field_type_ = kRtcpGenericRtpFeedbackSrReqCode;
-
- // Note: No state transition, sender report REQ is empty!
- return true;
- default:
- break;
- }
- EndCurrentBlock();
- return false;
-
- } else if (header.PT == transport::kPacketTypePayloadSpecific) {
- // Payload specific feedback
- switch (header.IC) {
- case 1:
- // PLI
- field_type_ = kRtcpPayloadSpecificPliCode;
- field_.pli.sender_ssrc = sender_ssrc;
- field_.pli.media_ssrc = media_ssrc;
-
- // Note: No state transition, PLI FCI is empty!
- return true;
- case 2:
- // Sli
- break;
- case 3:
- field_type_ = kRtcpPayloadSpecificRpsiCode;
- field_.rpsi.sender_ssrc = sender_ssrc;
- field_.rpsi.media_ssrc = media_ssrc;
- state_ = kStatePayloadSpecificRpsi;
- return true;
- case 4:
- // fir
- break;
- case 15:
- field_type_ = kRtcpPayloadSpecificAppCode;
- field_.application_specific.sender_ssrc = sender_ssrc;
- field_.application_specific.media_ssrc = media_ssrc;
- state_ = kStatePayloadSpecificApplication;
- return true;
- default:
- break;
- }
-
- EndCurrentBlock();
- return false;
- } else {
- DCHECK(false) << "Invalid state";
- EndCurrentBlock();
- return false;
- }
-}
-
-bool RtcpParser::ParseRpsiItem() {
- // RFC 4585 6.3.3. Reference Picture Selection Indication (rpsi)
- /*
- 0 1 2 3
- 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
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | PB |0| Payload Type| Native rpsi bit string |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | defined per codec ... | Padding (0) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
-
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- if (length > 2 + kRtcpRpsiDataSize) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- field_type_ = kRtcpPayloadSpecificRpsiCode;
-
- uint8 padding_bits;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU8(&padding_bits);
- big_endian_reader.ReadU8(&field_.rpsi.payload_type);
- big_endian_reader.ReadBytes(&field_.rpsi.native_bit_string, length - 2);
- field_.rpsi.number_of_valid_bits =
- static_cast<uint16>(length - 2) * 8 - padding_bits;
-
- rtcp_data_ += length;
- return true;
-}
-
-bool RtcpParser::ParseNackItem() {
- // RFC 4585 6.2.1. Generic Nack
-
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- field_type_ = kRtcpGenericRtpFeedbackNackItemCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU16(&field_.nack_item.packet_id);
- big_endian_reader.ReadU16(&field_.nack_item.bitmask);
- rtcp_data_ += 4;
- return true;
-}
-
-bool RtcpParser::ParsePayloadSpecificAppItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
-
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- uint32 name;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU32(&name);
- rtcp_data_ += 4;
-
- if (name == kRemb) {
- field_type_ = kRtcpPayloadSpecificRembCode;
- state_ = kStatePayloadSpecificRemb;
- return true;
- } else if (name == kCast) {
- field_type_ = kRtcpPayloadSpecificCastCode;
- state_ = kStatePayloadSpecificCast;
- return true;
- }
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
-}
-
-bool RtcpParser::ParsePayloadSpecificRembItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
-
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU8(&field_.remb_item.number_of_ssrcs);
-
- uint8 byte_1;
- uint8 byte_2;
- uint8 byte_3;
- big_endian_reader.ReadU8(&byte_1);
- big_endian_reader.ReadU8(&byte_2);
- big_endian_reader.ReadU8(&byte_3);
- rtcp_data_ += 4;
-
- uint8 br_exp = (byte_1 >> 2) & 0x3F;
- uint32 br_mantissa = ((byte_1 & 0x03) << 16) + (byte_2 << 8) + byte_3;
- field_.remb_item.bitrate = (br_mantissa << br_exp);
-
- ptrdiff_t length_ssrcs = rtcp_block_end_ - rtcp_data_;
- if (length_ssrcs < 4 * field_.remb_item.number_of_ssrcs) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- field_type_ = kRtcpPayloadSpecificRembItemCode;
-
- for (int i = 0; i < field_.remb_item.number_of_ssrcs; i++) {
- big_endian_reader.ReadU32(&field_.remb_item.ssrcs[i]);
- }
- return true;
-}
-
-bool RtcpParser::ParsePayloadSpecificCastItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- field_type_ = kRtcpPayloadSpecificCastCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU8(&field_.cast_item.last_frame_id);
- big_endian_reader.ReadU8(&field_.cast_item.number_of_lost_fields);
- big_endian_reader.ReadU16(&field_.cast_item.target_delay_ms);
-
- rtcp_data_ += 4;
-
- if (field_.cast_item.number_of_lost_fields != 0) {
- // State transition
- state_ = kStatePayloadSpecificCastNack;
- } else {
- // Don't go to state cast nack item if got 0 fields.
- state_ = kStateTopLevel;
- EndCurrentBlock();
- }
- return true;
-}
-
-bool RtcpParser::ParsePayloadSpecificCastNackItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- field_type_ = kRtcpPayloadSpecificCastNackItemCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU8(&field_.cast_nack_item.frame_id);
- big_endian_reader.ReadU16(&field_.cast_nack_item.packet_id);
- big_endian_reader.ReadU8(&field_.cast_nack_item.bitmask);
-
- rtcp_data_ += 4;
- return true;
-}
-
-bool RtcpParser::ParseFirItem() {
- // RFC 5104 4.3.1. Full Intra Request (fir)
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
-
- if (length < 8) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- field_type_ = kRtcpPayloadSpecificFirItemCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU32(&field_.fir_item.ssrc);
- big_endian_reader.ReadU8(&field_.fir_item.command_sequence_number);
-
- rtcp_data_ += 8;
- return true;
-}
-
-bool RtcpParser::ParseExtendedReport() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 8)
- return false;
-
- field_type_ = kRtcpXrCode;
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.Skip(4); // Skip header.
- big_endian_reader.ReadU32(&field_.extended_report.sender_ssrc);
-
- rtcp_data_ += 8;
-
- state_ = kStateExtendedReportBlock;
- return true;
-}
-
-bool RtcpParser::ParseExtendedReportItem() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- uint8 block_type;
- uint16 block_length;
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU8(&block_type);
- big_endian_reader.Skip(1); // Ignore reserved.
- big_endian_reader.ReadU16(&block_length);
-
- rtcp_data_ += 4;
-
- switch (block_type) {
- case 4:
- if (block_length != 2) {
- // Invalid block length.
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- return ParseExtendedReportReceiverReferenceTimeReport();
- case 5:
- if (block_length % 3 != 0) {
- // Invalid block length.
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- if (block_length >= 3) {
- number_of_blocks_ = block_length / 3;
- state_ = kStateExtendedReportDelaySinceLastReceiverReport;
- return ParseExtendedReportDelaySinceLastReceiverReport();
- }
- return true;
- default:
- if (length < block_length * 4) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- field_type_ = kRtcpXrUnknownItemCode;
- rtcp_data_ += block_length * 4;
- return true;
- }
-}
-
-bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 8) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU32(&field_.rrtr.ntp_most_significant);
- big_endian_reader.ReadU32(&field_.rrtr.ntp_least_significant);
-
- rtcp_data_ += 8;
-
- field_type_ = kRtcpXrRrtrCode;
- return true;
-}
-
-bool RtcpParser::ParseExtendedReportDelaySinceLastReceiverReport() {
- ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
- if (length < 12) {
- state_ = kStateTopLevel;
- EndCurrentBlock();
- return false;
- }
- if (number_of_blocks_ == 0) {
- // Continue parsing the extended report block.
- state_ = kStateExtendedReportBlock;
- return false;
- }
-
- base::BigEndianReader big_endian_reader(
- reinterpret_cast<const char*>(rtcp_data_), length);
- big_endian_reader.ReadU32(&field_.dlrr.receivers_ssrc);
- big_endian_reader.ReadU32(&field_.dlrr.last_receiver_report);
- big_endian_reader.ReadU32(&field_.dlrr.delay_last_receiver_report);
-
- rtcp_data_ += 12;
-
- number_of_blocks_--;
- field_type_ = kRtcpXrDlrrCode;
- return true;
-}
-
-// Converts a log event type to an integer value.
-// NOTE: We have only allocated 4 bits to represent the type of event over the
-// wire. Therefore, this function can only return values from 0 to 15.
-uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) {
- switch (event) {
- case FRAME_ACK_SENT:
- return 11;
- case FRAME_PLAYOUT:
- return 12;
- case FRAME_DECODED:
- return 13;
- case PACKET_RECEIVED:
- return 14;
- default:
- return 0; // Not an interesting event.
- }
-}
-
-CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) {
- // TODO(imcheng): Remove the old mappings once they are no longer used.
- switch (event) {
- case 1: // AudioAckSent
- case 5: // VideoAckSent
- case 11: // Unified
- return FRAME_ACK_SENT;
- case 2: // AudioPlayoutDelay
- case 7: // VideoRenderDelay
- case 12: // Unified
- return FRAME_PLAYOUT;
- case 3: // AudioFrameDecoded
- case 6: // VideoFrameDecoded
- case 13: // Unified
- return FRAME_DECODED;
- case 4: // AudioPacketReceived
- case 8: // VideoPacketReceived
- case 14: // Unified
- return PACKET_RECEIVED;
- case 9: // DuplicateAudioPacketReceived
- case 10: // DuplicateVideoPacketReceived
- default:
- // If the sender adds new log messages we will end up here until we add
- // the new messages in the receiver.
- VLOG(1) << "Unexpected log message received: " << static_cast<int>(event);
- NOTREACHED();
- return UNKNOWN;
- }
-}
-
-} // namespace cast
-} // namespace media
« no previous file with comments | « media/cast/rtcp/rtcp_utility.h ('k') | media/cast/rtcp/test_rtcp_packet_builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698