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/rtp_packet_parser.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "cast/streaming/packet_util.h"
11 #include "util/osp_logging.h"
12
13 namespace openscreen {
14 namespace cast {
15
RtpPacketParser(Ssrc sender_ssrc)16 RtpPacketParser::RtpPacketParser(Ssrc sender_ssrc)
17 : sender_ssrc_(sender_ssrc), highest_rtp_frame_id_(FrameId::first()) {}
18
19 RtpPacketParser::~RtpPacketParser() = default;
20
Parse(absl::Span<const uint8_t> buffer)21 absl::optional<RtpPacketParser::ParseResult> RtpPacketParser::Parse(
22 absl::Span<const uint8_t> buffer) {
23 if (buffer.size() < kRtpPacketMinValidSize ||
24 ConsumeField<uint8_t>(&buffer) != kRtpRequiredFirstByte) {
25 return absl::nullopt;
26 }
27
28 // RTP header elements.
29 //
30 // Note: M (marker bit) is ignored here. Technically, according to the Cast
31 // Streaming spec, it should only be set when PID == Max PID; but, let's be
32 // lenient just in case some sender implementations don't adhere to this tiny,
33 // subtle detail.
34 const uint8_t payload_type =
35 ConsumeField<uint8_t>(&buffer) & kRtpPayloadTypeMask;
36 if (!IsRtpPayloadType(payload_type)) {
37 return absl::nullopt;
38 }
39 ParseResult result;
40 result.payload_type = static_cast<RtpPayloadType>(payload_type);
41 result.sequence_number = ConsumeField<uint16_t>(&buffer);
42 result.rtp_timestamp =
43 last_parsed_rtp_timestamp_.Expand(ConsumeField<uint32_t>(&buffer));
44 if (ConsumeField<uint32_t>(&buffer) != sender_ssrc_) {
45 return absl::nullopt;
46 }
47
48 // Cast-specific header elements.
49 const uint8_t byte12 = ConsumeField<uint8_t>(&buffer);
50 result.is_key_frame = !!(byte12 & kRtpKeyFrameBitMask);
51 const bool has_referenced_frame_id =
52 !!(byte12 & kRtpHasReferenceFrameIdBitMask);
53 const size_t num_cast_extensions = byte12 & kRtpExtensionCountMask;
54 result.frame_id =
55 highest_rtp_frame_id_.Expand(ConsumeField<uint8_t>(&buffer));
56 result.packet_id = ConsumeField<uint16_t>(&buffer);
57 result.max_packet_id = ConsumeField<uint16_t>(&buffer);
58 if (result.max_packet_id == kAllPacketsLost) {
59 return absl::nullopt; // Packet ID cannot be the special value.
60 }
61 if (result.packet_id > result.max_packet_id) {
62 return absl::nullopt;
63 }
64 if (has_referenced_frame_id) {
65 if (buffer.empty()) {
66 return absl::nullopt;
67 }
68 result.referenced_frame_id =
69 result.frame_id.Expand(ConsumeField<uint8_t>(&buffer));
70 } else {
71 // By default, if no reference frame ID was provided, the assumption is that
72 // a key frame only references itself, while non-key frames reference only
73 // their immediate predecessor.
74 result.referenced_frame_id =
75 result.is_key_frame ? result.frame_id : (result.frame_id - 1);
76 }
77
78 // Zero or more Cast extensions.
79 for (size_t i = 0; i < num_cast_extensions; ++i) {
80 if (buffer.size() < sizeof(uint16_t)) {
81 return absl::nullopt;
82 }
83 const uint16_t type_and_size = ConsumeField<uint16_t>(&buffer);
84 const uint8_t type = type_and_size >> kNumExtensionDataSizeFieldBits;
85 const size_t size =
86 type_and_size & FieldBitmask<uint16_t>(kNumExtensionDataSizeFieldBits);
87 if (buffer.size() < size) {
88 return absl::nullopt;
89 }
90 if (type == kAdaptiveLatencyRtpExtensionType) {
91 if (size != sizeof(uint16_t)) {
92 return absl::nullopt;
93 }
94 result.new_playout_delay =
95 std::chrono::milliseconds(ReadBigEndian<uint16_t>(buffer.data()));
96 }
97 buffer.remove_prefix(size);
98 }
99
100 // All remaining data in the packet is the payload.
101 result.payload = buffer;
102
103 // At this point, the packet is known to be well-formed. Track recent field
104 // values for later parses, to bit-extend the truncated values found in future
105 // packets.
106 last_parsed_rtp_timestamp_ = result.rtp_timestamp;
107 highest_rtp_frame_id_ = std::max(highest_rtp_frame_id_, result.frame_id);
108
109 return result;
110 }
111
112 RtpPacketParser::ParseResult::ParseResult() = default;
113 RtpPacketParser::ParseResult::~ParseResult() = default;
114
115 } // namespace cast
116 } // namespace openscreen
117