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