// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "cast/streaming/rtp_packet_parser.h" #include #include #include "cast/streaming/packet_util.h" #include "util/osp_logging.h" namespace openscreen { namespace cast { RtpPacketParser::RtpPacketParser(Ssrc sender_ssrc) : sender_ssrc_(sender_ssrc), highest_rtp_frame_id_(FrameId::first()) {} RtpPacketParser::~RtpPacketParser() = default; absl::optional RtpPacketParser::Parse( absl::Span buffer) { if (buffer.size() < kRtpPacketMinValidSize || ConsumeField(&buffer) != kRtpRequiredFirstByte) { return absl::nullopt; } // RTP header elements. // // Note: M (marker bit) is ignored here. Technically, according to the Cast // Streaming spec, it should only be set when PID == Max PID; but, let's be // lenient just in case some sender implementations don't adhere to this tiny, // subtle detail. const uint8_t payload_type = ConsumeField(&buffer) & kRtpPayloadTypeMask; if (!IsRtpPayloadType(payload_type)) { return absl::nullopt; } ParseResult result; result.payload_type = static_cast(payload_type); result.sequence_number = ConsumeField(&buffer); result.rtp_timestamp = last_parsed_rtp_timestamp_.Expand(ConsumeField(&buffer)); if (ConsumeField(&buffer) != sender_ssrc_) { return absl::nullopt; } // Cast-specific header elements. const uint8_t byte12 = ConsumeField(&buffer); result.is_key_frame = !!(byte12 & kRtpKeyFrameBitMask); const bool has_referenced_frame_id = !!(byte12 & kRtpHasReferenceFrameIdBitMask); const size_t num_cast_extensions = byte12 & kRtpExtensionCountMask; result.frame_id = highest_rtp_frame_id_.Expand(ConsumeField(&buffer)); result.packet_id = ConsumeField(&buffer); result.max_packet_id = ConsumeField(&buffer); if (result.max_packet_id == kAllPacketsLost) { return absl::nullopt; // Packet ID cannot be the special value. } if (result.packet_id > result.max_packet_id) { return absl::nullopt; } if (has_referenced_frame_id) { if (buffer.empty()) { return absl::nullopt; } result.referenced_frame_id = result.frame_id.Expand(ConsumeField(&buffer)); } else { // By default, if no reference frame ID was provided, the assumption is that // a key frame only references itself, while non-key frames reference only // their immediate predecessor. result.referenced_frame_id = result.is_key_frame ? result.frame_id : (result.frame_id - 1); } // Zero or more Cast extensions. for (size_t i = 0; i < num_cast_extensions; ++i) { if (buffer.size() < sizeof(uint16_t)) { return absl::nullopt; } const uint16_t type_and_size = ConsumeField(&buffer); const uint8_t type = type_and_size >> kNumExtensionDataSizeFieldBits; const size_t size = type_and_size & FieldBitmask(kNumExtensionDataSizeFieldBits); if (buffer.size() < size) { return absl::nullopt; } if (type == kAdaptiveLatencyRtpExtensionType) { if (size != sizeof(uint16_t)) { return absl::nullopt; } result.new_playout_delay = std::chrono::milliseconds(ReadBigEndian(buffer.data())); } buffer.remove_prefix(size); } // All remaining data in the packet is the payload. result.payload = buffer; // At this point, the packet is known to be well-formed. Track recent field // values for later parses, to bit-extend the truncated values found in future // packets. last_parsed_rtp_timestamp_ = result.rtp_timestamp; highest_rtp_frame_id_ = std::max(highest_rtp_frame_id_, result.frame_id); return result; } RtpPacketParser::ParseResult::ParseResult() = default; RtpPacketParser::ParseResult::~ParseResult() = default; } // namespace cast } // namespace openscreen