1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file. 4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/rtcp/rtcp_utility.h" 6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/logging.h" 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/cast_transport_defines.h" 9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace media { 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace cast { 12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)RtcpParser::RtcpParser(uint32 local_ssrc, uint32 remote_ssrc) : 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) local_ssrc_(local_ssrc), 1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) remote_ssrc_(remote_ssrc), 1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_sender_report_(false), 1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_last_report_(false), 1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_cast_message_(false), 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_receiver_reference_time_report_(false) { 20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)RtcpParser::~RtcpParser() {} 23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::Parse(base::BigEndianReader* reader) { 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (reader->remaining()) { 26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) RtcpCommonHeader header; 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseCommonHeader(reader, &header)) 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::StringPiece tmp; 3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadPiece(&tmp, header.length_in_octets - 4)) 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::BigEndianReader chunk(tmp.data(), tmp.size()); 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch (header.PT) { 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case kPacketTypeSenderReport: 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseSR(&chunk, header)) 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case kPacketTypeReceiverReport: 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseRR(&chunk, header)) 4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case kPacketTypeApplicationDefined: 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseApplicationDefined(&chunk, header)) 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case kPacketTypePayloadSpecific: 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseFeedbackCommon(&chunk, header)) 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case kPacketTypeXr: 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseExtendedReport(&chunk, header)) 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseCommonHeader(base::BigEndianReader* reader, 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) RtcpCommonHeader* parsed_header) { 67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 0 1 2 3 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 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 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // |V=2|P| IC | PT | length | 71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // 73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Common header for all Rtcp packets, 4 octets. 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint8 byte; 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU8(&byte)) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parsed_header->V = byte >> 6; 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parsed_header->P = ((byte & 0x20) == 0) ? false : true; 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Check if RTP version field == 2. 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (parsed_header->V != 2) 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parsed_header->IC = byte & 0x1f; 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU8(&parsed_header->PT)) 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint16 bytes; 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU16(&bytes)) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parsed_header->length_in_octets = (static_cast<size_t>(bytes) + 1) * 4; 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (parsed_header->length_in_octets == 0) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseSR(base::BigEndianReader* reader, 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const RtcpCommonHeader& header) { 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 sender_ssrc; 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&sender_ssrc)) 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (sender_ssrc != remote_ssrc_) 10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 tmp; 11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&sender_report_.ntp_seconds) || 11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&sender_report_.ntp_fraction) || 11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&sender_report_.rtp_timestamp) || 11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&sender_report_.send_packet_count) || 11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&tmp)) 11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) sender_report_.send_octet_count = tmp; 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_sender_report_ = true; 119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (size_t block = 0; block < header.IC; block++) 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseReportBlock(reader)) 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseRR(base::BigEndianReader* reader, 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const RtcpCommonHeader& header) { 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 receiver_ssrc; 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&receiver_ssrc)) 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (receiver_ssrc != remote_ssrc_) 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (size_t block = 0; block < header.IC; block++) 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseReportBlock(reader)) 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseReportBlock(base::BigEndianReader* reader) { 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 ssrc, last_report, delay; 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&ssrc) || 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->Skip(12) || 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&last_report) || 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&delay)) 149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (ssrc == local_ssrc_) { 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) last_report_ = last_report; 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) delay_since_last_report_ = delay; 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_last_report_ = true; 155424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseApplicationDefined(base::BigEndianReader* reader, 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const RtcpCommonHeader& header) { 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32 sender_ssrc; 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32 name; 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&sender_ssrc) || 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&name)) 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (sender_ssrc != remote_ssrc_) 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (name != kCast) 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) switch (header.IC /* subtype */ ) { 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case kReceiverLogSubtype: 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseCastReceiverLogFrameItem(reader)) 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseCastReceiverLogFrameItem( 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::BigEndianReader* reader) { 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (reader->remaining()) { 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 rtp_timestamp; 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 data; 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&rtp_timestamp) || 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&data)) 19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // We have 24 LSB of the event timestamp base on the wire. 19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::TimeTicks event_timestamp_base = base::TimeTicks() + 19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::TimeDelta::FromMilliseconds(data & 0xffffff); 196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t num_events = 1 + static_cast<uint8>(data >> 24); 198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); 20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (size_t event = 0; event < num_events; event++) { 20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint16 delay_delta_or_packet_id; 20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint16 event_type_and_timestamp_delta; 20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU16(&delay_delta_or_packet_id) || 20403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU16(&event_type_and_timestamp_delta)) 20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) RtcpReceiverEventLogMessage event_log; 20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) event_log.type = TranslateToLogEventFromWireFormat( 20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static_cast<uint8>(event_type_and_timestamp_delta >> 12)); 21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) event_log.event_timestamp = 21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) event_timestamp_base + 21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::TimeDelta::FromMilliseconds( 21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) event_type_and_timestamp_delta & 0xfff); 21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (event_log.type == PACKET_RECEIVED) { 21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) event_log.packet_id = delay_delta_or_packet_id; 21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) event_log.delay_delta = base::TimeDelta::FromMilliseconds( 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<int16>(delay_delta_or_packet_id)); 21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) frame_log.event_log_messages_.push_back(event_log); 221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_log_.push_back(frame_log); 224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// RFC 4585. 23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseFeedbackCommon(base::BigEndianReader* reader, 23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const RtcpCommonHeader& header) { 23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // See RTC 4585 Section 6.4 for application specific feedback messages. 23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (header.IC != 15) { 23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 remote_ssrc; 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 media_ssrc; 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&remote_ssrc) || 23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&media_ssrc)) 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (remote_ssrc != remote_ssrc_) 24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 name; 24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&name)) 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (name != kCast) { 25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 252424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_message_.media_ssrc = remote_ssrc; 254424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint8 last_frame_id; 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint8 number_of_lost_fields; 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU8(&last_frame_id) || 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU8(&number_of_lost_fields) || 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU16(&cast_message_.target_delay_ms)) 260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Please note, this frame_id is still only 8-bit! 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_message_.ack_frame_id = last_frame_id; 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (size_t i = 0; i < number_of_lost_fields; i++) { 26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint8 frame_id; 26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint16 packet_id; 26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint8 bitmask; 26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU8(&frame_id) || 27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU16(&packet_id) || 27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU8(&bitmask)) 27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_message_.missing_frames_and_packets[frame_id].insert(packet_id); 27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (packet_id != kRtcpCastAllPacketsLost) { 27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (bitmask) { 27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packet_id++; 27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (bitmask & 1) 27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cast_message_.missing_frames_and_packets[frame_id].insert(packet_id); 27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bitmask >>= 1; 280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_cast_message_ = true; 28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 28803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseExtendedReport(base::BigEndianReader* reader, 28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const RtcpCommonHeader& header) { 29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 remote_ssrc; 29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU32(&remote_ssrc)) 292424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Is it for us? 29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (remote_ssrc != remote_ssrc_) 29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (reader->remaining()) { 29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint8 block_type; 30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint16 block_length; 30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->ReadU8(&block_type) || 30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->Skip(1) || 30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU16(&block_length)) 30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 30603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) switch (block_type) { 30703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) case 4: // RRTR. RFC3611 Section 4.4. 30803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (block_length != 2) 30903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ParseExtendedReportReceiverReferenceTimeReport(reader, 31103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) remote_ssrc)) 31203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 31303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 31503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default: 31603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Skip unknown item. 31703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!reader->Skip(block_length * 4)) 31803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 31903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 32003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 321424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 322424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 32503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool RtcpParser::ParseExtendedReportReceiverReferenceTimeReport( 32603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::BigEndianReader* reader, 32703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 remote_ssrc) { 32803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_reference_time_report_.remote_ssrc = remote_ssrc; 32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if(!reader->ReadU32(&receiver_reference_time_report_.ntp_seconds) || 33003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) !reader->ReadU32(&receiver_reference_time_report_.ntp_fraction)) 331424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 332424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 33303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) has_receiver_reference_time_report_ = true; 334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Converts a log event type to an integer value. 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// NOTE: We have only allocated 4 bits to represent the type of event over the 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// wire. Therefore, this function can only return values from 0 to 15. 340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event) { 341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) switch (event) { 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case FRAME_ACK_SENT: 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 11; 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case FRAME_PLAYOUT: 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 12; 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case FRAME_DECODED: 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 13; 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PACKET_RECEIVED: 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 14; 350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) default: 351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return 0; // Not an interesting event. 352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event) { 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(imcheng): Remove the old mappings once they are no longer used. 357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) switch (event) { 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 1: // AudioAckSent 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 5: // VideoAckSent 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 11: // Unified 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return FRAME_ACK_SENT; 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 2: // AudioPlayoutDelay 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 7: // VideoRenderDelay 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 12: // Unified 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return FRAME_PLAYOUT; 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 3: // AudioFrameDecoded 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 6: // VideoFrameDecoded 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 13: // Unified 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return FRAME_DECODED; 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 4: // AudioPacketReceived 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 8: // VideoPacketReceived 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 14: // Unified 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return PACKET_RECEIVED; 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 9: // DuplicateAudioPacketReceived 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case 10: // DuplicateVideoPacketReceived 376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) default: 377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // If the sender adds new log messages we will end up here until we add 378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // the new messages in the receiver. 379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) VLOG(1) << "Unexpected log message received: " << static_cast<int>(event); 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return UNKNOWN; 381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 382010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 383010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 384424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace cast 385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace media 386