1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cast/streaming/sender_report_parser.h" 6 7 #include "cast/streaming/packet_util.h" 8 #include "util/osp_logging.h" 9 10 namespace openscreen { 11 namespace cast { 12 13 SenderReportParser::SenderReportWithId::SenderReportWithId() = default; 14 SenderReportParser::SenderReportWithId::~SenderReportWithId() = default; 15 SenderReportParser(RtcpSession * session)16SenderReportParser::SenderReportParser(RtcpSession* session) 17 : session_(session) { 18 OSP_DCHECK(session_); 19 } 20 21 SenderReportParser::~SenderReportParser() = default; 22 23 absl::optional<SenderReportParser::SenderReportWithId> Parse(absl::Span<const uint8_t> buffer)24SenderReportParser::Parse(absl::Span<const uint8_t> buffer) { 25 absl::optional<SenderReportWithId> sender_report; 26 27 // The data contained in |buffer| can be a "compound packet," which means that 28 // it can be the concatenation of multiple RTCP packets. The loop here 29 // processes each one-by-one. 30 while (!buffer.empty()) { 31 const auto header = RtcpCommonHeader::Parse(buffer); 32 if (!header) { 33 return absl::nullopt; 34 } 35 buffer.remove_prefix(kRtcpCommonHeaderSize); 36 if (static_cast<int>(buffer.size()) < header->payload_size) { 37 return absl::nullopt; 38 } 39 auto chunk = buffer.subspan(0, header->payload_size); 40 buffer.remove_prefix(header->payload_size); 41 42 // Only process Sender Reports with a matching SSRC. 43 if (header->packet_type != RtcpPacketType::kSenderReport) { 44 continue; 45 } 46 if (header->payload_size < kRtcpSenderReportSize) { 47 return absl::nullopt; 48 } 49 if (ConsumeField<uint32_t>(&chunk) != session_->sender_ssrc()) { 50 continue; 51 } 52 SenderReportWithId& report = sender_report.emplace(); 53 const NtpTimestamp ntp_timestamp = ConsumeField<uint64_t>(&chunk); 54 report.report_id = ToStatusReportId(ntp_timestamp); 55 report.reference_time = 56 session_->ntp_converter().ToLocalTime(ntp_timestamp); 57 report.rtp_timestamp = 58 last_parsed_rtp_timestamp_.Expand(ConsumeField<uint32_t>(&chunk)); 59 report.send_packet_count = ConsumeField<uint32_t>(&chunk); 60 report.send_octet_count = ConsumeField<uint32_t>(&chunk); 61 report.report_block = RtcpReportBlock::ParseOne( 62 chunk, header->with.report_count, session_->receiver_ssrc()); 63 } 64 65 // At this point, the packet is known to be well-formed. Cache the 66 // most-recently parsed RTP timestamp value for bit-expansion in future 67 // parses. 68 if (sender_report) { 69 last_parsed_rtp_timestamp_ = sender_report->rtp_timestamp; 70 } 71 return sender_report; 72 } 73 74 } // namespace cast 75 } // namespace openscreen 76