summaryrefslogtreecommitdiff
path: root/media/cast/rtcp/rtcp_utility.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/cast/rtcp/rtcp_utility.cc')
-rw-r--r--media/cast/rtcp/rtcp_utility.cc149
1 files changed, 148 insertions, 1 deletions
diff --git a/media/cast/rtcp/rtcp_utility.cc b/media/cast/rtcp/rtcp_utility.cc
index 4f9d2ec769..daeaa8aace 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();