| Index: media/cast/rtcp/rtcp_utility.cc
|
| diff --git a/media/cast/rtcp/rtcp_utility.cc b/media/cast/rtcp/rtcp_utility.cc
|
| index 4f9d2ec76936ea6d0e2d79f6d5dd0a53310d40b7..daeaa8aaceb8b1071d7716109c436701c78aeac2 100644
|
| --- a/media/cast/rtcp/rtcp_utility.cc
|
| +++ b/media/cast/rtcp/rtcp_utility.cc
|
| @@ -56,6 +56,15 @@ RtcpFieldTypes RtcpParser::Iterate() {
|
| case kStateBye:
|
| IterateByeItem();
|
| break;
|
| + case kStateApplicationSpecificCastReceiverFrameLog:
|
| + IterateCastReceiverLogFrame();
|
| + break;
|
| + case kStateApplicationSpecificCastReceiverEventLog:
|
| + IterateCastReceiverLogEvent();
|
| + break;
|
| + case kStateApplicationSpecificCastSenderLog:
|
| + IterateCastSenderLog();
|
| + break;
|
| case kStateExtendedReportBlock:
|
| IterateExtendedReportItem();
|
| break;
|
| @@ -123,6 +132,12 @@ void RtcpParser::IterateTopLevel() {
|
| break;
|
| }
|
| return;
|
| + case kPacketTypeApplicationDefined:
|
| + if (!ParseApplicationDefined(header.IC)) {
|
| + // Nothing supported found, continue to next block!
|
| + break;
|
| + }
|
| + return;
|
| case kPacketTypeGenericRtpFeedback: // Fall through!
|
| case kPacketTypePayloadSpecific:
|
| if (!ParseFeedBackCommon(header)) {
|
| @@ -203,6 +218,21 @@ void RtcpParser::IteratePayloadSpecificCastNackItem() {
|
| if (!success) Iterate();
|
| }
|
|
|
| +void RtcpParser::IterateCastReceiverLogFrame() {
|
| + bool success = ParseCastReceiverLogFrameItem();
|
| + if (!success) Iterate();
|
| +}
|
| +
|
| +void RtcpParser::IterateCastReceiverLogEvent() {
|
| + bool success = ParseCastReceiverLogEventItem();
|
| + if (!success) Iterate();
|
| +}
|
| +
|
| +void RtcpParser::IterateCastSenderLog() {
|
| + bool success = ParseCastSenderLogItem();
|
| + if (!success) Iterate();
|
| +}
|
| +
|
| void RtcpParser::Validate() {
|
| if (rtcp_data_ == NULL) return; // NOT VALID
|
|
|
| @@ -466,6 +496,124 @@ bool RtcpParser::ParseByeItem() {
|
| return true;
|
| }
|
|
|
| +bool RtcpParser::ParseApplicationDefined(uint8 subtype) {
|
| + ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
|
| + if (length < 16 ||
|
| + !(subtype == kSenderLogSubtype || subtype == kReceiverLogSubtype)) {
|
| + state_ = kStateTopLevel;
|
| + EndCurrentBlock();
|
| + return false;
|
| + }
|
| +
|
| + uint32 sender_ssrc;
|
| + uint32 name;
|
| +
|
| + net::BigEndianReader big_endian_reader(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 kSenderLogSubtype:
|
| + state_ = kStateApplicationSpecificCastSenderLog;
|
| + field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
|
| + field_.cast_sender_log.sender_ssrc = sender_ssrc;
|
| + break;
|
| + 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;
|
| + net::BigEndianReader big_endian_reader(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;
|
| + net::BigEndianReader big_endian_reader(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);
|
| + field_.cast_receiver_log.delay_delta_or_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::ParseCastSenderLogItem() {
|
| + ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
|
| +
|
| + if (length < 4) {
|
| + state_ = kStateTopLevel;
|
| + EndCurrentBlock();
|
| + return false;
|
| + }
|
| + uint32 data;
|
| + net::BigEndianReader big_endian_reader(rtcp_data_, length);
|
| + big_endian_reader.ReadU32(&data);
|
| +
|
| + rtcp_data_ += 4;
|
| +
|
| + field_.cast_sender_log.status = static_cast<uint8>(data >> 24);
|
| + // We have 24 LSB of the RTP timestamp on the wire.
|
| + field_.cast_sender_log.rtp_timestamp = data & 0xffffff;
|
| + field_type_ = kRtcpApplicationSpecificCastSenderLogCode;
|
| + return true;
|
| +}
|
| +
|
| bool RtcpParser::ParseFeedBackCommon(const RtcpCommonHeader& header) {
|
| DCHECK((header.PT == kPacketTypeGenericRtpFeedback) ||
|
| (header.PT == kPacketTypePayloadSpecific)) << "Invalid state";
|
| @@ -686,7 +834,6 @@ bool RtcpParser::ParsePayloadSpecificRembItem() {
|
|
|
| bool RtcpParser::ParsePayloadSpecificCastItem() {
|
| ptrdiff_t length = rtcp_block_end_ - rtcp_data_;
|
| -
|
| if (length < 4) {
|
| state_ = kStateTopLevel;
|
| EndCurrentBlock();
|
|
|