blob: 79a42e98ba4089e8f642400c7befc611ab361390 [file] [log] [blame]
// 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 <algorithm>
#include <utility>
#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::ParseResult> RtpPacketParser::Parse(
absl::Span<const uint8_t> buffer) {
if (buffer.size() < kRtpPacketMinValidSize ||
ConsumeField<uint8_t>(&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<uint8_t>(&buffer) & kRtpPayloadTypeMask;
if (!IsRtpPayloadType(payload_type)) {
return absl::nullopt;
}
ParseResult result;
result.payload_type = static_cast<RtpPayloadType>(payload_type);
result.sequence_number = ConsumeField<uint16_t>(&buffer);
result.rtp_timestamp =
last_parsed_rtp_timestamp_.Expand(ConsumeField<uint32_t>(&buffer));
if (ConsumeField<uint32_t>(&buffer) != sender_ssrc_) {
return absl::nullopt;
}
// Cast-specific header elements.
const uint8_t byte12 = ConsumeField<uint8_t>(&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<uint8_t>(&buffer));
result.packet_id = ConsumeField<uint16_t>(&buffer);
result.max_packet_id = ConsumeField<uint16_t>(&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<uint8_t>(&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<uint16_t>(&buffer);
const uint8_t type = type_and_size >> kNumExtensionDataSizeFieldBits;
const size_t size =
type_and_size & FieldBitmask<uint16_t>(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<uint16_t>(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