text: /*
   *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree. An additional intellectual property rights grant can be found
   *  in the file PATENTS.  All contributing project authors may
   *  be found in the AUTHORS file in the root of the source tree.
   */
  
  #include "webrtc/base/checks.h"
  #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
  #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
  
  #include <assert.h>
  #include <math.h>   // ceil
  #include <string.h> // memcpy
  
  #include "webrtc/base/checks.h"
  #include "webrtc/base/logging.h"
  #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
  
  namespace webrtc {
  
  namespace RTCPUtility {
  
  NackStats::NackStats()
      : max_sequence_number_(0),
        requests_(0),
        unique_requests_(0) {}
  
  NackStats::~NackStats() {}
  
  void NackStats::ReportRequest(uint16_t sequence_number) {
    if (requests_ == 0 ||
        webrtc::IsNewerSequenceNumber(sequence_number, max_sequence_number_)) {
      max_sequence_number_ =  sequence_number;
      ++unique_requests_;
    }
    ++requests_;
  }
  
  uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) {
    return (ntp_sec << 16) + (ntp_frac >> 16);
  }  // end RTCPUtility
  }
  
  // RTCPParserV2 : currently read only
  RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData,
                                          size_t rtcpDataLength,
                                          bool rtcpReducedSizeEnable)
      : _ptrRTCPDataBegin(rtcpData),
        _RTCPReducedSizeEnable(rtcpReducedSizeEnable),
        _ptrRTCPDataEnd(rtcpData + rtcpDataLength),
        _validPacket(false),
        _ptrRTCPData(rtcpData),
        _ptrRTCPBlockEnd(NULL),
        _state(ParseState::State_TopLevel),
        _numberOfBlocks(0),
        num_skipped_blocks_(0),
        _packetType(RTCPPacketTypes::kInvalid) {
    Validate();
  }
  
  RTCPUtility::RTCPParserV2::~RTCPParserV2() {
  }
  
  ptrdiff_t
  RTCPUtility::RTCPParserV2::LengthLeft() const
  {
      return (_ptrRTCPDataEnd- _ptrRTCPData);
  }
  
  RTCPUtility::RTCPPacketTypes
  RTCPUtility::RTCPParserV2::PacketType() const
  {
      return _packetType;
  }
  
  const RTCPUtility::RTCPPacket&
  RTCPUtility::RTCPParserV2::Packet() const
  {
      return _packet;
  }
  
  rtcp::RtcpPacket* RTCPUtility::RTCPParserV2::ReleaseRtcpPacket() {
    return rtcp_packet_.release();
  }
  RTCPUtility::RTCPPacketTypes
  RTCPUtility::RTCPParserV2::Begin()
  {
      _ptrRTCPData = _ptrRTCPDataBegin;
  
      return Iterate();
  }
  
  RTCPUtility::RTCPPacketTypes
  RTCPUtility::RTCPParserV2::Iterate()
  {
      // Reset packet type
    _packetType = RTCPPacketTypes::kInvalid;
  
      if (IsValid())
      {
          switch (_state)
          {
            case ParseState::State_TopLevel:
              IterateTopLevel();
              break;
            case ParseState::State_ReportBlockItem:
              IterateReportBlockItem();
              break;
            case ParseState::State_SDESChunk:
              IterateSDESChunk();
              break;
            case ParseState::State_BYEItem:
              IterateBYEItem();
              break;
            case ParseState::State_ExtendedJitterItem:
              IterateExtendedJitterItem();
              break;
            case ParseState::State_RTPFB_NACKItem:
              IterateNACKItem();
              break;
            case ParseState::State_RTPFB_TMMBRItem:
              IterateTMMBRItem();
              break;
            case ParseState::State_RTPFB_TMMBNItem:
              IterateTMMBNItem();
              break;
            case ParseState::State_PSFB_SLIItem:
              IterateSLIItem();
              break;
            case ParseState::State_PSFB_RPSIItem:
              IterateRPSIItem();
              break;
            case ParseState::State_PSFB_FIRItem:
              IterateFIRItem();
              break;
            case ParseState::State_PSFB_AppItem:
              IteratePsfbAppItem();
              break;
            case ParseState::State_PSFB_REMBItem:
              IteratePsfbREMBItem();
              break;
            case ParseState::State_XRItem:
              IterateXrItem();
              break;
            case ParseState::State_XR_DLLRItem:
              IterateXrDlrrItem();
              break;
            case ParseState::State_AppItem:
              IterateAppItem();
              break;
          default:
            RTC_NOTREACHED() << "Invalid state!";
              break;
          }
      }
      return _packetType;
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateTopLevel()
  {
      for (;;)
      {
        RtcpCommonHeader header;
        if (_ptrRTCPDataEnd <= _ptrRTCPData)
          return;
  
        if (!RtcpParseCommonHeader(_ptrRTCPData, _ptrRTCPDataEnd - _ptrRTCPData,
                                   &header)) {
              return;
          }
          _ptrRTCPBlockEnd = _ptrRTCPData + header.BlockSize();
          if (_ptrRTCPBlockEnd > _ptrRTCPDataEnd)
          {
            ++num_skipped_blocks_;
              return;
          }
  
          switch (header.packet_type) {
          case PT_SR:
          {
              // number of Report blocks
              _numberOfBlocks = header.count_or_format;
              ParseSR();
              return;
          }
          case PT_RR:
          {
              // number of Report blocks
              _numberOfBlocks = header.count_or_format;
              ParseRR();
              return;
          }
          case PT_SDES:
          {
              // number of SDES blocks
              _numberOfBlocks = header.count_or_format;
              const bool ok = ParseSDES();
              if (!ok)
              {
                  // Nothing supported found, continue to next block!
                  break;
              }
              return;
          }
          case PT_BYE:
          {
            _numberOfBlocks = header.count_or_format;
              const bool ok = ParseBYE();
              if (!ok)
              {
                  // Nothing supported found, continue to next block!
                  break;
              }
              return;
          }
          case PT_IJ:
          {
              // number of Report blocks
              _numberOfBlocks = header.count_or_format;
              ParseIJ();
              return;
          }
          case PT_RTPFB:
            FALLTHROUGH();
          case PT_PSFB:
          {
            if (!ParseFBCommon(header)) {
              // Nothing supported found, continue to next block!
              break;
            }
            return;
          }
          case PT_APP:
          {
              const bool ok = ParseAPP(header);
              if (!ok)
              {
                  // Nothing supported found, continue to next block!
                  break;
              }
              return;
          }
          case PT_XR:
          {
              const bool ok = ParseXr();
              if (!ok)
              {
                  // Nothing supported found, continue to next block!
                  break;
              }
              return;
          }
          default:
              // Not supported! Skip!
              ++num_skipped_blocks_;
              EndCurrentBlock();
              break;
          }
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateXrItem()
  {
      const bool success = ParseXrItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateXrDlrrItem()
  {
      const bool success = ParseXrDlrrItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateReportBlockItem()
  {
      const bool success = ParseReportBlockItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateSDESChunk()
  {
      const bool success = ParseSDESChunk();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateBYEItem()
  {
      const bool success = ParseBYEItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateExtendedJitterItem()
  {
      const bool success = ParseIJItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateNACKItem()
  {
      const bool success = ParseNACKItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateTMMBRItem()
  {
      const bool success = ParseTMMBRItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateTMMBNItem()
  {
      const bool success = ParseTMMBNItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateSLIItem()
  {
      const bool success = ParseSLIItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateRPSIItem()
  {
      const bool success = ParseRPSIItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateFIRItem()
  {
      const bool success = ParseFIRItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
  {
      const bool success = ParsePsfbAppItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
  {
      const bool success = ParsePsfbREMBItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::IterateAppItem()
  {
      const bool success = ParseAPPItem();
      if (!success)
      {
          Iterate();
      }
  }
  
  void
  RTCPUtility::RTCPParserV2::Validate()
  {
    if (_ptrRTCPData == nullptr)
      return;  // NOT VALID
  
    RtcpCommonHeader header;
    if (_ptrRTCPDataEnd <= _ptrRTCPDataBegin)
      return;  // NOT VALID
  
    if (!RtcpParseCommonHeader(_ptrRTCPDataBegin,
                               _ptrRTCPDataEnd - _ptrRTCPDataBegin, &header))
      return;  // NOT VALID!
  
      // * if (!reducedSize) : first packet must be RR or SR.
      //
      // * The padding bit (P) should be zero for the first packet of a
      //   compound RTCP packet because padding should only be applied,
      //   if it is needed, to the last packet. (NOT CHECKED!)
      //
      // * The length fields of the individual RTCP packets must add up
      //   to the overall length of the compound RTCP packet as
      //   received.  This is a fairly strong check. (NOT CHECKED!)
  
      if (!_RTCPReducedSizeEnable)
      {
        if ((header.packet_type != PT_SR) && (header.packet_type != PT_RR)) {
              return; // NOT VALID
          }
      }
  
      _validPacket = true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::IsValid() const
  {
      return _validPacket;
  }
  
  void
  RTCPUtility::RTCPParserV2::EndCurrentBlock()
  {
      _ptrRTCPData = _ptrRTCPBlockEnd;
  }
  
  //  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.
  
  bool RTCPUtility::RtcpParseCommonHeader(const uint8_t* packet,
                                          size_t size_bytes,
                                          RtcpCommonHeader* parsed_header) {
    RTC_DCHECK(parsed_header != nullptr);
    if (size_bytes < RtcpCommonHeader::kHeaderSizeBytes) {
      LOG(LS_WARNING) << "Too little data (" << size_bytes << " byte"
                      << (size_bytes != 1 ? "s" : "")
                      << ") remaining in buffer to parse RTCP header (4 bytes).";
      return false;
    }
  
    const uint8_t kRtcpVersion = 2;
    uint8_t version = packet[0] >> 6;
    if (version != kRtcpVersion) {
      LOG(LS_WARNING) << "Invalid RTCP header: Version must be "
                      << static_cast<int>(kRtcpVersion) << " but was "
                      << static_cast<int>(version);
      return false;
    }
  
    bool has_padding = (packet[0] & 0x20) != 0;
    uint8_t format = packet[0] & 0x1F;
    uint8_t packet_type = packet[1];
    size_t packet_size_words =
        ByteReader<uint16_t>::ReadBigEndian(&packet[2]) + 1;
  
    if (size_bytes < packet_size_words * 4) {
      LOG(LS_WARNING) << "Buffer too small (" << size_bytes
                      << " bytes) to fit an RtcpPacket of " << packet_size_words
                      << " 32bit words.";
      return false;
    }
  
    size_t payload_size = packet_size_words * 4;
    size_t padding_bytes = 0;
    if (has_padding) {
      if (payload_size <= RtcpCommonHeader::kHeaderSizeBytes) {
        LOG(LS_WARNING) << "Invalid RTCP header: Padding bit set but 0 payload "
                           "size specified.";
        return false;
      }
  
      padding_bytes = packet[payload_size - 1];
      if (RtcpCommonHeader::kHeaderSizeBytes + padding_bytes > payload_size) {
        LOG(LS_WARNING) << "Invalid RTCP header: Too many padding bytes ("
                        << padding_bytes << ") for a packet size of "
                        << payload_size << "bytes.";
        return false;
      }
      payload_size -= padding_bytes;
    }
    payload_size -= RtcpCommonHeader::kHeaderSizeBytes;
  
    parsed_header->version = kRtcpVersion;
    parsed_header->count_or_format = format;
    parsed_header->packet_type = packet_type;
    parsed_header->payload_size_bytes = payload_size;
    parsed_header->padding_bytes = padding_bytes;
  
    return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseRR()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 8)
      {
          return false;
      }
  
  
      _ptrRTCPData += 4; // Skip header
  
      _packetType = RTCPPacketTypes::kRr;
  
      _packet.RR.SenderSSRC = *_ptrRTCPData++ << 24;
      _packet.RR.SenderSSRC += *_ptrRTCPData++ << 16;
      _packet.RR.SenderSSRC += *_ptrRTCPData++ << 8;
      _packet.RR.SenderSSRC += *_ptrRTCPData++;
  
      _packet.RR.NumberOfReportBlocks = _numberOfBlocks;
  
      // State transition
      _state = ParseState::State_ReportBlockItem;
  
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseSR()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 28)
      {
          EndCurrentBlock();
          return false;
      }
  
      _ptrRTCPData += 4; // Skip header
  
      _packetType = RTCPPacketTypes::kSr;
  
      _packet.SR.SenderSSRC = *_ptrRTCPData++ << 24;
      _packet.SR.SenderSSRC += *_ptrRTCPData++ << 16;
      _packet.SR.SenderSSRC += *_ptrRTCPData++ << 8;
      _packet.SR.SenderSSRC += *_ptrRTCPData++;
  
      _packet.SR.NTPMostSignificant = *_ptrRTCPData++ << 24;
      _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 16;
      _packet.SR.NTPMostSignificant += *_ptrRTCPData++ << 8;
      _packet.SR.NTPMostSignificant += *_ptrRTCPData++;
  
      _packet.SR.NTPLeastSignificant = *_ptrRTCPData++ << 24;
      _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 16;
      _packet.SR.NTPLeastSignificant += *_ptrRTCPData++ << 8;
      _packet.SR.NTPLeastSignificant += *_ptrRTCPData++;
  
      _packet.SR.RTPTimestamp = *_ptrRTCPData++ << 24;
      _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 16;
      _packet.SR.RTPTimestamp += *_ptrRTCPData++ << 8;
      _packet.SR.RTPTimestamp += *_ptrRTCPData++;
  
      _packet.SR.SenderPacketCount = *_ptrRTCPData++ << 24;
      _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 16;
      _packet.SR.SenderPacketCount += *_ptrRTCPData++ << 8;
      _packet.SR.SenderPacketCount += *_ptrRTCPData++;
  
      _packet.SR.SenderOctetCount = *_ptrRTCPData++ << 24;
      _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 16;
      _packet.SR.SenderOctetCount += *_ptrRTCPData++ << 8;
      _packet.SR.SenderOctetCount += *_ptrRTCPData++;
  
      _packet.SR.NumberOfReportBlocks = _numberOfBlocks;
  
      // State transition
      if(_numberOfBlocks != 0)
      {
        _state = ParseState::State_ReportBlockItem;
      }else
      {
          // don't go to state report block item if 0 report blocks
        _state = ParseState::State_TopLevel;
          EndCurrentBlock();
      }
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseReportBlockItem()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 24 || _numberOfBlocks <= 0)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      _packet.ReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
      _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
      _packet.ReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
      _packet.ReportBlockItem.SSRC += *_ptrRTCPData++;
  
      _packet.ReportBlockItem.FractionLost = *_ptrRTCPData++;
  
      _packet.ReportBlockItem.CumulativeNumOfPacketsLost = *_ptrRTCPData++ << 16;
      _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++ << 8;
      _packet.ReportBlockItem.CumulativeNumOfPacketsLost += *_ptrRTCPData++;
  
      _packet.ReportBlockItem.ExtendedHighestSequenceNumber = *_ptrRTCPData++ << 24;
      _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 16;
      _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++ << 8;
      _packet.ReportBlockItem.ExtendedHighestSequenceNumber += *_ptrRTCPData++;
  
      _packet.ReportBlockItem.Jitter = *_ptrRTCPData++ << 24;
      _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 16;
      _packet.ReportBlockItem.Jitter += *_ptrRTCPData++ << 8;
      _packet.ReportBlockItem.Jitter += *_ptrRTCPData++;
  
      _packet.ReportBlockItem.LastSR = *_ptrRTCPData++ << 24;
      _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 16;
      _packet.ReportBlockItem.LastSR += *_ptrRTCPData++ << 8;
      _packet.ReportBlockItem.LastSR += *_ptrRTCPData++;
  
      _packet.ReportBlockItem.DelayLastSR = *_ptrRTCPData++ << 24;
      _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 16;
      _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++ << 8;
      _packet.ReportBlockItem.DelayLastSR += *_ptrRTCPData++;
  
      _numberOfBlocks--;
      _packetType = RTCPPacketTypes::kReportBlockItem;
      return true;
  }
  
  /* From RFC 5450: Transmission Time Offsets in RTP Streams.
        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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   hdr |V=2|P|    RC   |   PT=IJ=195   |             length            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      inter-arrival jitter                     |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       .                                                               .
       .                                                               .
       .                                                               .
       |                      inter-arrival jitter                     |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
  
  bool
  RTCPUtility::RTCPParserV2::ParseIJ()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 4)
      {
          return false;
      }
  
      _ptrRTCPData += 4; // Skip header
  
      _packetType = RTCPPacketTypes::kExtendedIj;
  
      // State transition
      _state = ParseState::State_ExtendedJitterItem;
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseIJItem()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 4 || _numberOfBlocks <= 0)
      {
        _state = ParseState::State_TopLevel;
          EndCurrentBlock();
          return false;
      }
  
      _packet.ExtendedJitterReportItem.Jitter = *_ptrRTCPData++ << 24;
      _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 16;
      _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++ << 8;
      _packet.ExtendedJitterReportItem.Jitter += *_ptrRTCPData++;
  
      _numberOfBlocks--;
      _packetType = RTCPPacketTypes::kExtendedIjItem;
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseSDES()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 8)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      _ptrRTCPData += 4; // Skip header
  
      _state = ParseState::State_SDESChunk;
      _packetType = RTCPPacketTypes::kSdes;
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseSDESChunk()
  {
      if(_numberOfBlocks <= 0)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      _numberOfBlocks--;
  
      // Find CName item in a SDES chunk.
      while (_ptrRTCPData < _ptrRTCPBlockEnd)
      {
          const ptrdiff_t dataLen = _ptrRTCPBlockEnd - _ptrRTCPData;
          if (dataLen < 4)
          {
            _state = ParseState::State_TopLevel;
  
              EndCurrentBlock();
              return false;
          }
  
          uint32_t SSRC = *_ptrRTCPData++ << 24;
          SSRC += *_ptrRTCPData++ << 16;
          SSRC += *_ptrRTCPData++ << 8;
          SSRC += *_ptrRTCPData++;
  
          const bool foundCname = ParseSDESItem();
          if (foundCname)
          {
              _packet.CName.SenderSSRC = SSRC; // Add SSRC
              return true;
          }
      }
      _state = ParseState::State_TopLevel;
  
      EndCurrentBlock();
      return false;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseSDESItem()
  {
      // Find CName
      // Only the CNAME item is mandatory. RFC 3550 page 46
      bool foundCName = false;
  
      size_t itemOctetsRead = 0;
      while (_ptrRTCPData < _ptrRTCPBlockEnd)
      {
          const uint8_t tag = *_ptrRTCPData++;
          ++itemOctetsRead;
  
          if (tag == 0)
          {
              // End tag! 4 oct aligned
              while ((itemOctetsRead++ % 4) != 0)
              {
                  ++_ptrRTCPData;
              }
              return foundCName;
          }
  
          if (_ptrRTCPData < _ptrRTCPBlockEnd)
          {
              const uint8_t len = *_ptrRTCPData++;
              ++itemOctetsRead;
  
              if (tag == 1)
              {
                  // CNAME
  
                  // Sanity
                  if ((_ptrRTCPData + len) >= _ptrRTCPBlockEnd)
                  {
                    _state = ParseState::State_TopLevel;
  
                      EndCurrentBlock();
                      return false;
                  }
                  uint8_t i = 0;
                  for (; i < len; ++i)
                  {
                      const uint8_t c = _ptrRTCPData[i];
                      if ((c < ' ') || (c > '{') || (c == '%') || (c == '\\'))
                      {
                          // Illegal char
                        _state = ParseState::State_TopLevel;
  
                          EndCurrentBlock();
                          return false;
                      }
                      _packet.CName.CName[i] = c;
                  }
                  // Make sure we are null terminated.
                  _packet.CName.CName[i] = 0;
                  _packetType = RTCPPacketTypes::kSdesChunk;
  
                  foundCName = true;
              }
              _ptrRTCPData += len;
              itemOctetsRead += len;
          }
      }
  
      // No end tag found!
      _state = ParseState::State_TopLevel;
  
      EndCurrentBlock();
      return false;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseBYE()
  {
      _ptrRTCPData += 4; // Skip header
  
      _state = ParseState::State_BYEItem;
  
      return ParseBYEItem();
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseBYEItem()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
      if (length < 4 || _numberOfBlocks == 0)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packetType = RTCPPacketTypes::kBye;
  
      _packet.BYE.SenderSSRC = *_ptrRTCPData++ << 24;
      _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 16;
      _packet.BYE.SenderSSRC += *_ptrRTCPData++ << 8;
      _packet.BYE.SenderSSRC += *_ptrRTCPData++;
  
      // we can have several CSRCs attached
  
      // sanity
      if(length >= 4*_numberOfBlocks)
      {
          _ptrRTCPData += (_numberOfBlocks -1)*4;
      }
      _numberOfBlocks = 0;
  
      return true;
  }
  /*
      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|reserved |   PT=XR=207   |             length            |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                              SSRC                             |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     :                         report blocks                         :
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
  bool RTCPUtility::RTCPParserV2::ParseXr()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
      if (length < 8)
      {
          EndCurrentBlock();
          return false;
      }
  
      _ptrRTCPData += 4; // Skip header
  
      _packet.XR.OriginatorSSRC = *_ptrRTCPData++ << 24;
      _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 16;
      _packet.XR.OriginatorSSRC += *_ptrRTCPData++ << 8;
      _packet.XR.OriginatorSSRC += *_ptrRTCPData++;
  
      _packetType = RTCPPacketTypes::kXrHeader;
      _state = ParseState::State_XRItem;
      return true;
  }
  
  /*  Extended report block format (RFC 3611).
      BT: block type.
      block length: length of report block in 32-bits words minus one (including
                    the header).
      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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      BT       | type-specific |         block length          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      :             type-specific block contents                      :
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
  bool RTCPUtility::RTCPParserV2::ParseXrItem() {
    const int kBlockHeaderLengthInBytes = 4;
    const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
    if (length < kBlockHeaderLengthInBytes) {
      _state = ParseState::State_TopLevel;
      EndCurrentBlock();
      return false;
    }
  
    uint8_t block_type = *_ptrRTCPData++;
    _ptrRTCPData++;  // Ignore reserved.
  
    uint16_t block_length_in_4bytes = *_ptrRTCPData++ << 8;
    block_length_in_4bytes += *_ptrRTCPData++;
  
    switch (block_type) {
      case kBtReceiverReferenceTime:
        return ParseXrReceiverReferenceTimeItem(block_length_in_4bytes);
      case kBtDlrr:
        return ParseXrDlrr(block_length_in_4bytes);
      case kBtVoipMetric:
        return ParseXrVoipMetricItem(block_length_in_4bytes);
      default:
        return ParseXrUnsupportedBlockType(block_length_in_4bytes);
    }
  }
  
  /*  Receiver Reference Time Report Block.
      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
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |     BT=4      |   reserved    |       block length = 2        |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |              NTP timestamp, most significant word             |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |             NTP timestamp, least significant word             |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
  bool RTCPUtility::RTCPParserV2::ParseXrReceiverReferenceTimeItem(
      int block_length_4bytes) {
    const int kBlockLengthIn4Bytes = 2;
    const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
    const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
    if (block_length_4bytes != kBlockLengthIn4Bytes ||
        length < kBlockLengthInBytes) {
      _state = ParseState::State_TopLevel;
      EndCurrentBlock();
      return false;
    }
  
    _packet.XRReceiverReferenceTimeItem.NTPMostSignificant = *_ptrRTCPData++<<24;
    _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<16;
    _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++<<8;
    _packet.XRReceiverReferenceTimeItem.NTPMostSignificant+= *_ptrRTCPData++;
  
    _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant = *_ptrRTCPData++<<24;
    _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<16;
    _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++<<8;
    _packet.XRReceiverReferenceTimeItem.NTPLeastSignificant+= *_ptrRTCPData++;
  
    _packetType = RTCPPacketTypes::kXrReceiverReferenceTime;
    _state = ParseState::State_XRItem;
    return true;
  }
  
  /*  DLRR Report Block.
      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
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |     BT=5      |   reserved    |         block length          |
     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     |                 SSRC_1 (SSRC of first receiver)               | sub-
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
     |                         last RR (LRR)                         |   1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                   delay since last RR (DLRR)                  |
     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     |                 SSRC_2 (SSRC of second receiver)              | sub-
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
     :                               ...                             :   2
     +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  */
  bool RTCPUtility::RTCPParserV2::ParseXrDlrr(int block_length_4bytes) {
    const int kSubBlockLengthIn4Bytes = 3;
    if (block_length_4bytes < 0 ||
        (block_length_4bytes % kSubBlockLengthIn4Bytes) != 0) {
      _state = ParseState::State_TopLevel;
      EndCurrentBlock();
      return false;
    }
    _packetType = RTCPPacketTypes::kXrDlrrReportBlock;
    _state = ParseState::State_XR_DLLRItem;
    _numberOfBlocks = block_length_4bytes / kSubBlockLengthIn4Bytes;
    return true;
  }
  
  bool RTCPUtility::RTCPParserV2::ParseXrDlrrItem() {
    if (_numberOfBlocks == 0) {
      _state = ParseState::State_XRItem;
      return false;
    }
    const int kSubBlockLengthInBytes = 12;
    const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
    if (length < kSubBlockLengthInBytes) {
      _state = ParseState::State_TopLevel;
      EndCurrentBlock();
      return false;
    }
  
    _packet.XRDLRRReportBlockItem.SSRC = *_ptrRTCPData++ << 24;
    _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 16;
    _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++ << 8;
    _packet.XRDLRRReportBlockItem.SSRC += *_ptrRTCPData++;
  
    _packet.XRDLRRReportBlockItem.LastRR = *_ptrRTCPData++ << 24;
    _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 16;
    _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++ << 8;
    _packet.XRDLRRReportBlockItem.LastRR += *_ptrRTCPData++;
  
    _packet.XRDLRRReportBlockItem.DelayLastRR = *_ptrRTCPData++ << 24;
    _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 16;
    _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++ << 8;
    _packet.XRDLRRReportBlockItem.DelayLastRR += *_ptrRTCPData++;
  
    _packetType = RTCPPacketTypes::kXrDlrrReportBlockItem;
    --_numberOfBlocks;
    _state = ParseState::State_XR_DLLRItem;
    return true;
  }
  /*  VoIP Metrics Report Block.
      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
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |     BT=7      |   reserved    |       block length = 8        |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        SSRC of source                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |   loss rate   | discard rate  | burst density |  gap density  |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |       burst duration          |         gap duration          |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |     round trip delay          |       end system delay        |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     | signal level  |  noise level  |     RERL      |     Gmin      |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |   R factor    | ext. R factor |    MOS-LQ     |    MOS-CQ     |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |   RX config   |   reserved    |          JB nominal           |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |          JB maximum           |          JB abs max           |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
  
  bool RTCPUtility::RTCPParserV2::ParseXrVoipMetricItem(int block_length_4bytes) {
    const int kBlockLengthIn4Bytes = 8;
    const int kBlockLengthInBytes = kBlockLengthIn4Bytes * 4;
    const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
    if (block_length_4bytes != kBlockLengthIn4Bytes ||
        length < kBlockLengthInBytes) {
      _state = ParseState::State_TopLevel;
      EndCurrentBlock();
      return false;
    }
  
    _packet.XRVOIPMetricItem.SSRC = *_ptrRTCPData++ << 24;
    _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 16;
    _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.SSRC += *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.lossRate = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.discardRate = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.burstDensity = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.gapDensity = *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.burstDuration = *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.burstDuration += *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.gapDuration = *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.gapDuration += *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.roundTripDelay = *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.roundTripDelay += *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.endSystemDelay = *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.endSystemDelay += *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.signalLevel = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.noiseLevel = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.RERL = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.Gmin = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.Rfactor = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.extRfactor = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.MOSLQ = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.MOSCQ = *_ptrRTCPData++;
    _packet.XRVOIPMetricItem.RXconfig = *_ptrRTCPData++;
    _ptrRTCPData++; // skip reserved
  
    _packet.XRVOIPMetricItem.JBnominal = *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.JBnominal += *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.JBmax = *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.JBmax += *_ptrRTCPData++;
  
    _packet.XRVOIPMetricItem.JBabsMax = *_ptrRTCPData++ << 8;
    _packet.XRVOIPMetricItem.JBabsMax += *_ptrRTCPData++;
  
    _packetType = RTCPPacketTypes::kXrVoipMetric;
    _state = ParseState::State_XRItem;
    return true;
  }
  
  bool RTCPUtility::RTCPParserV2::ParseXrUnsupportedBlockType(
      int block_length_4bytes) {
    const int32_t kBlockLengthInBytes = block_length_4bytes * 4;
    const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
    if (length < kBlockLengthInBytes) {
      _state = ParseState::State_TopLevel;
      EndCurrentBlock();
      return false;
    }
    // Skip block.
    _ptrRTCPData += kBlockLengthInBytes;
    _state = ParseState::State_XRItem;
    return false;
  }
  
  bool RTCPUtility::RTCPParserV2::ParseFBCommon(const RtcpCommonHeader& header) {
    RTC_CHECK((header.packet_type == PT_RTPFB) ||
              (header.packet_type == PT_PSFB));  // Parser logic check
  
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      // 4 * 3, RFC4585 section 6.1
      if (length < 12) {
        LOG(LS_WARNING)
            << "Invalid RTCP packet: Too little data (" << length
            << " bytes) left in buffer to parse a 12 byte RTPFB/PSFB message.";
          return false;
      }
  
      _ptrRTCPData += 4; // Skip RTCP header
  
      uint32_t senderSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
      _ptrRTCPData += 4;
  
      uint32_t mediaSSRC = ByteReader<uint32_t>::ReadBigEndian(_ptrRTCPData);
      _ptrRTCPData += 4;
  
      if (header.packet_type == PT_RTPFB) {
          // Transport layer feedback
  
          switch (header.count_or_format) {
          case 1:
          {
              // NACK
            _packetType = RTCPPacketTypes::kRtpfbNack;
              _packet.NACK.SenderSSRC = senderSSRC;
              _packet.NACK.MediaSSRC  = mediaSSRC;
  
              _state = ParseState::State_RTPFB_NACKItem;
  
              return true;
          }
          case 3:
          {
              // TMMBR
            _packetType = RTCPPacketTypes::kRtpfbTmmbr;
              _packet.TMMBR.SenderSSRC = senderSSRC;
              _packet.TMMBR.MediaSSRC  = mediaSSRC;
  
              _state = ParseState::State_RTPFB_TMMBRItem;
  
              return true;
          }
          case 4:
          {
              // TMMBN
            _packetType = RTCPPacketTypes::kRtpfbTmmbn;
              _packet.TMMBN.SenderSSRC = senderSSRC;
              _packet.TMMBN.MediaSSRC  = mediaSSRC;
  
              _state = ParseState::State_RTPFB_TMMBNItem;
  
              return true;
          }
          case 5:
           {
              // RTCP-SR-REQ Rapid Synchronisation of RTP Flows
              // draft-perkins-avt-rapid-rtp-sync-03.txt
              // trigger a new RTCP SR
            _packetType = RTCPPacketTypes::kRtpfbSrReq;
  
              // Note: No state transition, SR REQ is empty!
              return true;
          }
          case 15: {
            rtcp_packet_ =
                rtcp::TransportFeedback::ParseFrom(_ptrRTCPData - 12, length);
            // Since we parse the whole packet here, keep the TopLevel state and
            // just end the current block.
            EndCurrentBlock();
            if (rtcp_packet_.get()) {
              _packetType = RTCPPacketTypes::kTransportFeedback;
              return true;
            }
            break;
          }
          default:
              break;
          }
          // Unsupported RTPFB message. Skip and move to next block.
          ++num_skipped_blocks_;
          return false;
      } else if (header.packet_type == PT_PSFB) {
          // Payload specific feedback
          switch (header.count_or_format) {
          case 1:
              // PLI
            _packetType = RTCPPacketTypes::kPsfbPli;
              _packet.PLI.SenderSSRC = senderSSRC;
              _packet.PLI.MediaSSRC  = mediaSSRC;
  
              // Note: No state transition, PLI FCI is empty!
              return true;
          case 2:
              // SLI
            _packetType = RTCPPacketTypes::kPsfbSli;
              _packet.SLI.SenderSSRC = senderSSRC;
              _packet.SLI.MediaSSRC  = mediaSSRC;
  
              _state = ParseState::State_PSFB_SLIItem;
  
              return true;
          case 3:
            _packetType = RTCPPacketTypes::kPsfbRpsi;
              _packet.RPSI.SenderSSRC = senderSSRC;
              _packet.RPSI.MediaSSRC  = mediaSSRC;
  
              _state = ParseState::State_PSFB_RPSIItem;
              return true;
          case 4:
              // FIR
            _packetType = RTCPPacketTypes::kPsfbFir;
              _packet.FIR.SenderSSRC = senderSSRC;
              _packet.FIR.MediaSSRC  = mediaSSRC;
  
              _state = ParseState::State_PSFB_FIRItem;
              return true;
          case 15:
            _packetType = RTCPPacketTypes::kPsfbApp;
              _packet.PSFBAPP.SenderSSRC = senderSSRC;
              _packet.PSFBAPP.MediaSSRC  = mediaSSRC;
  
              _state = ParseState::State_PSFB_AppItem;
              return true;
          default:
              break;
          }
  
          return false;
      }
      else
      {
        RTC_NOTREACHED();
          return false;
      }
  }
  
  bool RTCPUtility::RTCPParserV2::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) |
      //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 4) {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      if (length > 2 + RTCP_RPSI_DATA_SIZE) {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packetType = RTCPPacketTypes::kPsfbRpsi;
  
      uint8_t padding_bits = *_ptrRTCPData++;
      _packet.RPSI.PayloadType = *_ptrRTCPData++;
  
      memcpy(_packet.RPSI.NativeBitString, _ptrRTCPData, length - 2);
      _ptrRTCPData += length - 2;
  
      _packet.RPSI.NumberOfValidBits =
          static_cast<uint16_t>(length - 2) * 8 - padding_bits;
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseNACKItem()
  {
      // RFC 4585 6.2.1. Generic NACK
  
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 4)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packetType = RTCPPacketTypes::kRtpfbNackItem;
  
      _packet.NACKItem.PacketID = *_ptrRTCPData++ << 8;
      _packet.NACKItem.PacketID += *_ptrRTCPData++;
  
      _packet.NACKItem.BitMask = *_ptrRTCPData++ << 8;
      _packet.NACKItem.BitMask += *_ptrRTCPData++;
  
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 4)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      if(*_ptrRTCPData++ != 'R')
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      if(*_ptrRTCPData++ != 'E')
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      if(*_ptrRTCPData++ != 'M')
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      if(*_ptrRTCPData++ != 'B')
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      _packetType = RTCPPacketTypes::kPsfbRemb;
      _state = ParseState::State_PSFB_REMBItem;
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 4)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packet.REMBItem.NumberOfSSRCs = *_ptrRTCPData++;
      const uint8_t brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
  
      uint32_t brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
      brMantissa += (_ptrRTCPData[1] << 8);
      brMantissa += (_ptrRTCPData[2]);
  
      _ptrRTCPData += 3; // Fwd read data
      _packet.REMBItem.BitRate = (brMantissa << brExp);
  
      const ptrdiff_t length_ssrcs = _ptrRTCPBlockEnd - _ptrRTCPData;
      if (length_ssrcs < 4 * _packet.REMBItem.NumberOfSSRCs)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packetType = RTCPPacketTypes::kPsfbRembItem;
  
      for (int i = 0; i < _packet.REMBItem.NumberOfSSRCs; i++)
      {
          _packet.REMBItem.SSRCs[i] = *_ptrRTCPData++ << 24;
          _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 16;
          _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++ << 8;
          _packet.REMBItem.SSRCs[i] += *_ptrRTCPData++;
      }
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseTMMBRItem()
  {
      // RFC 5104 4.2.1. Temporary Maximum Media Stream Bit Rate Request (TMMBR)
  
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 8)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packetType = RTCPPacketTypes::kRtpfbTmmbrItem;
  
      _packet.TMMBRItem.SSRC = *_ptrRTCPData++ << 24;
      _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 16;
      _packet.TMMBRItem.SSRC += *_ptrRTCPData++ << 8;
      _packet.TMMBRItem.SSRC += *_ptrRTCPData++;
  
      uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
  
      uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
      mxtbrMantissa += (_ptrRTCPData[1] << 7);
      mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
  
      uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
      measuredOH += _ptrRTCPData[3];
  
      _ptrRTCPData += 4; // Fwd read data
  
      _packet.TMMBRItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
      _packet.TMMBRItem.MeasuredOverhead     = measuredOH;
  
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseTMMBNItem()
  {
      // RFC 5104 4.2.2. Temporary Maximum Media Stream Bit Rate Notification (TMMBN)
  
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 8)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packetType = RTCPPacketTypes::kRtpfbTmmbnItem;
  
      _packet.TMMBNItem.SSRC = *_ptrRTCPData++ << 24;
      _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 16;
      _packet.TMMBNItem.SSRC += *_ptrRTCPData++ << 8;
      _packet.TMMBNItem.SSRC += *_ptrRTCPData++;
  
      uint8_t mxtbrExp = (_ptrRTCPData[0] >> 2) & 0x3F;
  
      uint32_t mxtbrMantissa = (_ptrRTCPData[0] & 0x03) << 15;
      mxtbrMantissa += (_ptrRTCPData[1] << 7);
      mxtbrMantissa += (_ptrRTCPData[2] >> 1) & 0x7F;
  
      uint32_t measuredOH = (_ptrRTCPData[2] & 0x01) << 8;
      measuredOH += _ptrRTCPData[3];
  
      _ptrRTCPData += 4; // Fwd read data
  
      _packet.TMMBNItem.MaxTotalMediaBitRate = ((mxtbrMantissa << mxtbrExp) / 1000);
      _packet.TMMBNItem.MeasuredOverhead     = measuredOH;
  
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseSLIItem()
  {
      // RFC 5104 6.3.2.  Slice Loss Indication (SLI)
      /*
      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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |            First        |        Number           | PictureID |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      */
  
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 4)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      _packetType = RTCPPacketTypes::kPsfbSliItem;
  
      uint32_t buffer;
      buffer = *_ptrRTCPData++ << 24;
      buffer += *_ptrRTCPData++ << 16;
      buffer += *_ptrRTCPData++ << 8;
      buffer += *_ptrRTCPData++;
  
      _packet.SLIItem.FirstMB = uint16_t((buffer>>19) & 0x1fff);
      _packet.SLIItem.NumberOfMB = uint16_t((buffer>>6) & 0x1fff);
      _packet.SLIItem.PictureId = uint8_t(buffer & 0x3f);
  
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseFIRItem()
  {
      // RFC 5104 4.3.1. Full Intra Request (FIR)
  
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 8)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
  
      _packetType = RTCPPacketTypes::kPsfbFirItem;
  
      _packet.FIRItem.SSRC = *_ptrRTCPData++ << 24;
      _packet.FIRItem.SSRC += *_ptrRTCPData++ << 16;
      _packet.FIRItem.SSRC += *_ptrRTCPData++ << 8;
      _packet.FIRItem.SSRC += *_ptrRTCPData++;
  
      _packet.FIRItem.CommandSequenceNumber = *_ptrRTCPData++;
      _ptrRTCPData += 3; // Skip "Reserved" bytes.
      return true;
  }
  
  bool RTCPUtility::RTCPParserV2::ParseAPP(const RtcpCommonHeader& header) {
      ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      if (length < 12) // 4 * 3, RFC 3550 6.7 APP: Application-Defined RTCP Packet
      {
          EndCurrentBlock();
          return false;
      }
  
      _ptrRTCPData += 4; // Skip RTCP header
  
      uint32_t senderSSRC = *_ptrRTCPData++ << 24;
      senderSSRC += *_ptrRTCPData++ << 16;
      senderSSRC += *_ptrRTCPData++ << 8;
      senderSSRC += *_ptrRTCPData++;
  
      uint32_t name = *_ptrRTCPData++ << 24;
      name += *_ptrRTCPData++ << 16;
      name += *_ptrRTCPData++ << 8;
      name += *_ptrRTCPData++;
  
      length  = _ptrRTCPBlockEnd - _ptrRTCPData;
  
      _packetType = RTCPPacketTypes::kApp;
  
      _packet.APP.SubType = header.count_or_format;
      _packet.APP.Name = name;
  
      _state = ParseState::State_AppItem;
      return true;
  }
  
  bool
  RTCPUtility::RTCPParserV2::ParseAPPItem()
  {
      const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
      if (length < 4)
      {
        _state = ParseState::State_TopLevel;
  
          EndCurrentBlock();
          return false;
      }
      _packetType = RTCPPacketTypes::kAppItem;
  
      if(length > kRtcpAppCode_DATA_SIZE)
      {
          memcpy(_packet.APP.Data, _ptrRTCPData, kRtcpAppCode_DATA_SIZE);
          _packet.APP.Size = kRtcpAppCode_DATA_SIZE;
          _ptrRTCPData += kRtcpAppCode_DATA_SIZE;
      }else
      {
          memcpy(_packet.APP.Data, _ptrRTCPData, length);
          _packet.APP.Size = (uint16_t)length;
          _ptrRTCPData += length;
      }
      return true;
  }
  
  size_t RTCPUtility::RTCPParserV2::NumSkippedBlocks() const {
    return num_skipped_blocks_;
  }
  
  RTCPUtility::RTCPPacketIterator::RTCPPacketIterator(uint8_t* rtcpData,
                                                      size_t rtcpDataLength)
      : _ptrBegin(rtcpData),
        _ptrEnd(rtcpData + rtcpDataLength),
        _ptrBlock(NULL) {
    memset(&_header, 0, sizeof(_header));
  }
  
  RTCPUtility::RTCPPacketIterator::~RTCPPacketIterator() {
  }
  
  const RTCPUtility::RtcpCommonHeader* RTCPUtility::RTCPPacketIterator::Begin() {
      _ptrBlock = _ptrBegin;
  
      return Iterate();
  }
  
  const RTCPUtility::RtcpCommonHeader*
  RTCPUtility::RTCPPacketIterator::Iterate() {
    if ((_ptrEnd <= _ptrBlock) ||
        !RtcpParseCommonHeader(_ptrBlock, _ptrEnd - _ptrBlock, &_header)) {
      _ptrBlock = nullptr;
      return nullptr;
    }
    _ptrBlock += _header.BlockSize();
  
    if (_ptrBlock > _ptrEnd) {
      _ptrBlock = nullptr;
      return nullptr;
    }
  
    return &_header;
  }
  
  const RTCPUtility::RtcpCommonHeader*
  RTCPUtility::RTCPPacketIterator::Current() {
      if (!_ptrBlock)
      {
          return NULL;
      }
  
      return &_header;
  }
  }  // namespace webrtc
  