xref: /aosp_15_r20/external/openscreen/cast/streaming/frame_collector.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/frame_collector.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <algorithm>
8*3f982cf4SFabien Sanglard #include <limits>
9*3f982cf4SFabien Sanglard #include <numeric>
10*3f982cf4SFabien Sanglard 
11*3f982cf4SFabien Sanglard #include "cast/streaming/frame_id.h"
12*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_defines.h"
13*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
14*3f982cf4SFabien Sanglard 
15*3f982cf4SFabien Sanglard namespace openscreen {
16*3f982cf4SFabien Sanglard namespace cast {
17*3f982cf4SFabien Sanglard 
18*3f982cf4SFabien Sanglard namespace {
19*3f982cf4SFabien Sanglard 
20*3f982cf4SFabien Sanglard // Integer constant representing that the number of packets is not yet known.
21*3f982cf4SFabien Sanglard constexpr int kUnknownNumberOfPackets = std::numeric_limits<int>::max();
22*3f982cf4SFabien Sanglard 
23*3f982cf4SFabien Sanglard }  // namespace
24*3f982cf4SFabien Sanglard 
FrameCollector()25*3f982cf4SFabien Sanglard FrameCollector::FrameCollector()
26*3f982cf4SFabien Sanglard     : num_missing_packets_(kUnknownNumberOfPackets) {}
27*3f982cf4SFabien Sanglard 
28*3f982cf4SFabien Sanglard FrameCollector::~FrameCollector() = default;
29*3f982cf4SFabien Sanglard 
CollectRtpPacket(const RtpPacketParser::ParseResult & part,std::vector<uint8_t> * buffer)30*3f982cf4SFabien Sanglard bool FrameCollector::CollectRtpPacket(const RtpPacketParser::ParseResult& part,
31*3f982cf4SFabien Sanglard                                       std::vector<uint8_t>* buffer) {
32*3f982cf4SFabien Sanglard   OSP_DCHECK(!frame_.frame_id.is_null());
33*3f982cf4SFabien Sanglard 
34*3f982cf4SFabien Sanglard   if (part.frame_id != frame_.frame_id) {
35*3f982cf4SFabien Sanglard     OSP_LOG_WARN
36*3f982cf4SFabien Sanglard         << "Ignoring potentially corrupt packet (frame ID mismatch). Expected: "
37*3f982cf4SFabien Sanglard         << frame_.frame_id << " Got: " << part.frame_id;
38*3f982cf4SFabien Sanglard     return false;
39*3f982cf4SFabien Sanglard   }
40*3f982cf4SFabien Sanglard 
41*3f982cf4SFabien Sanglard   const int frame_packet_count = static_cast<int>(part.max_packet_id) + 1;
42*3f982cf4SFabien Sanglard   if (num_missing_packets_ == kUnknownNumberOfPackets) {
43*3f982cf4SFabien Sanglard     // This is the first packet being processed for the frame.
44*3f982cf4SFabien Sanglard     num_missing_packets_ = frame_packet_count;
45*3f982cf4SFabien Sanglard     chunks_.resize(num_missing_packets_);
46*3f982cf4SFabien Sanglard   } else {
47*3f982cf4SFabien Sanglard     // Since this is not the first packet being processed, sanity-check that the
48*3f982cf4SFabien Sanglard     // "frame ID" and "max packet ID" are the expected values.
49*3f982cf4SFabien Sanglard     if (frame_packet_count != static_cast<int>(chunks_.size())) {
50*3f982cf4SFabien Sanglard       OSP_LOG_WARN << "Ignoring potentially corrupt packet (packet count "
51*3f982cf4SFabien Sanglard                       "mismatch). packet_count="
52*3f982cf4SFabien Sanglard                    << chunks_.size() << " is not equal to 1 + max_packet_id="
53*3f982cf4SFabien Sanglard                    << part.max_packet_id;
54*3f982cf4SFabien Sanglard       return false;
55*3f982cf4SFabien Sanglard     }
56*3f982cf4SFabien Sanglard   }
57*3f982cf4SFabien Sanglard 
58*3f982cf4SFabien Sanglard   // The packet ID must not be greater than the max packet ID.
59*3f982cf4SFabien Sanglard   if (part.packet_id >= chunks_.size()) {
60*3f982cf4SFabien Sanglard     OSP_LOG_WARN
61*3f982cf4SFabien Sanglard         << "Ignoring potentially corrupt packet having invalid packet ID "
62*3f982cf4SFabien Sanglard         << part.packet_id << " (should be less than " << chunks_.size() << ").";
63*3f982cf4SFabien Sanglard     return false;
64*3f982cf4SFabien Sanglard   }
65*3f982cf4SFabien Sanglard 
66*3f982cf4SFabien Sanglard   // Don't process duplicate packets.
67*3f982cf4SFabien Sanglard   if (chunks_[part.packet_id].has_data()) {
68*3f982cf4SFabien Sanglard     // Note: No logging here because this is a common occurrence that is not
69*3f982cf4SFabien Sanglard     // indicative of any problem in the system.
70*3f982cf4SFabien Sanglard     return true;
71*3f982cf4SFabien Sanglard   }
72*3f982cf4SFabien Sanglard 
73*3f982cf4SFabien Sanglard   // Populate metadata from packet 0 only, which is the only packet that must
74*3f982cf4SFabien Sanglard   // contain a complete set of values.
75*3f982cf4SFabien Sanglard   if (part.packet_id == FramePacketId{0}) {
76*3f982cf4SFabien Sanglard     if (part.is_key_frame) {
77*3f982cf4SFabien Sanglard       frame_.dependency = EncodedFrame::KEY_FRAME;
78*3f982cf4SFabien Sanglard     } else if (part.frame_id == part.referenced_frame_id) {
79*3f982cf4SFabien Sanglard       frame_.dependency = EncodedFrame::INDEPENDENTLY_DECODABLE;
80*3f982cf4SFabien Sanglard     } else {
81*3f982cf4SFabien Sanglard       frame_.dependency = EncodedFrame::DEPENDS_ON_ANOTHER;
82*3f982cf4SFabien Sanglard     }
83*3f982cf4SFabien Sanglard     frame_.referenced_frame_id = part.referenced_frame_id;
84*3f982cf4SFabien Sanglard     frame_.rtp_timestamp = part.rtp_timestamp;
85*3f982cf4SFabien Sanglard     frame_.new_playout_delay = part.new_playout_delay;
86*3f982cf4SFabien Sanglard   }
87*3f982cf4SFabien Sanglard 
88*3f982cf4SFabien Sanglard   // Take ownership of the contents of the |buffer| (no copy!), and record the
89*3f982cf4SFabien Sanglard   // region of the buffer containing the payload data. The payload region is
90*3f982cf4SFabien Sanglard   // usually all but the first few dozen bytes of the buffer.
91*3f982cf4SFabien Sanglard   PayloadChunk& chunk = chunks_[part.packet_id];
92*3f982cf4SFabien Sanglard   chunk.buffer.swap(*buffer);
93*3f982cf4SFabien Sanglard   chunk.payload = part.payload;
94*3f982cf4SFabien Sanglard   OSP_DCHECK_GE(chunk.payload.data(), chunk.buffer.data());
95*3f982cf4SFabien Sanglard   OSP_DCHECK_LE(chunk.payload.data() + chunk.payload.size(),
96*3f982cf4SFabien Sanglard                 chunk.buffer.data() + chunk.buffer.size());
97*3f982cf4SFabien Sanglard 
98*3f982cf4SFabien Sanglard   // Success!
99*3f982cf4SFabien Sanglard   --num_missing_packets_;
100*3f982cf4SFabien Sanglard   OSP_DCHECK_GE(num_missing_packets_, 0);
101*3f982cf4SFabien Sanglard   return true;
102*3f982cf4SFabien Sanglard }
103*3f982cf4SFabien Sanglard 
GetMissingPackets(std::vector<PacketNack> * nacks) const104*3f982cf4SFabien Sanglard void FrameCollector::GetMissingPackets(std::vector<PacketNack>* nacks) const {
105*3f982cf4SFabien Sanglard   OSP_DCHECK(!frame_.frame_id.is_null());
106*3f982cf4SFabien Sanglard 
107*3f982cf4SFabien Sanglard   if (num_missing_packets_ == 0) {
108*3f982cf4SFabien Sanglard     return;
109*3f982cf4SFabien Sanglard   }
110*3f982cf4SFabien Sanglard 
111*3f982cf4SFabien Sanglard   const int frame_packet_count = chunks_.size();
112*3f982cf4SFabien Sanglard   if (num_missing_packets_ >= frame_packet_count) {
113*3f982cf4SFabien Sanglard     nacks->push_back(PacketNack{frame_.frame_id, kAllPacketsLost});
114*3f982cf4SFabien Sanglard     return;
115*3f982cf4SFabien Sanglard   }
116*3f982cf4SFabien Sanglard 
117*3f982cf4SFabien Sanglard   for (int packet_id = 0; packet_id < frame_packet_count; ++packet_id) {
118*3f982cf4SFabien Sanglard     if (!chunks_[packet_id].has_data()) {
119*3f982cf4SFabien Sanglard       nacks->push_back(
120*3f982cf4SFabien Sanglard           PacketNack{frame_.frame_id, static_cast<FramePacketId>(packet_id)});
121*3f982cf4SFabien Sanglard     }
122*3f982cf4SFabien Sanglard   }
123*3f982cf4SFabien Sanglard }
124*3f982cf4SFabien Sanglard 
PeekAtAssembledFrame()125*3f982cf4SFabien Sanglard const EncryptedFrame& FrameCollector::PeekAtAssembledFrame() {
126*3f982cf4SFabien Sanglard   OSP_DCHECK_EQ(num_missing_packets_, 0);
127*3f982cf4SFabien Sanglard 
128*3f982cf4SFabien Sanglard   if (!frame_.data.data()) {
129*3f982cf4SFabien Sanglard     // Allocate the frame's payload buffer once, right-sized to the sum of all
130*3f982cf4SFabien Sanglard     // chunk sizes.
131*3f982cf4SFabien Sanglard     frame_.owned_data_.reserve(
132*3f982cf4SFabien Sanglard         std::accumulate(chunks_.cbegin(), chunks_.cend(), size_t{0},
133*3f982cf4SFabien Sanglard                         [](size_t num_bytes_so_far, const PayloadChunk& chunk) {
134*3f982cf4SFabien Sanglard                           return num_bytes_so_far + chunk.payload.size();
135*3f982cf4SFabien Sanglard                         }));
136*3f982cf4SFabien Sanglard     // Now, populate the frame's payload buffer with each chunk of data.
137*3f982cf4SFabien Sanglard     for (const PayloadChunk& chunk : chunks_) {
138*3f982cf4SFabien Sanglard       frame_.owned_data_.insert(frame_.owned_data_.end(), chunk.payload.begin(),
139*3f982cf4SFabien Sanglard                                 chunk.payload.end());
140*3f982cf4SFabien Sanglard     }
141*3f982cf4SFabien Sanglard     frame_.data = absl::Span<uint8_t>(frame_.owned_data_);
142*3f982cf4SFabien Sanglard   }
143*3f982cf4SFabien Sanglard 
144*3f982cf4SFabien Sanglard   return frame_;
145*3f982cf4SFabien Sanglard }
146*3f982cf4SFabien Sanglard 
Reset()147*3f982cf4SFabien Sanglard void FrameCollector::Reset() {
148*3f982cf4SFabien Sanglard   num_missing_packets_ = kUnknownNumberOfPackets;
149*3f982cf4SFabien Sanglard   frame_.frame_id = FrameId();
150*3f982cf4SFabien Sanglard   frame_.owned_data_.clear();
151*3f982cf4SFabien Sanglard   frame_.owned_data_.shrink_to_fit();
152*3f982cf4SFabien Sanglard   frame_.data = absl::Span<uint8_t>();
153*3f982cf4SFabien Sanglard   chunks_.clear();
154*3f982cf4SFabien Sanglard }
155*3f982cf4SFabien Sanglard 
156*3f982cf4SFabien Sanglard FrameCollector::PayloadChunk::PayloadChunk() = default;
157*3f982cf4SFabien Sanglard FrameCollector::PayloadChunk::~PayloadChunk() = default;
158*3f982cf4SFabien Sanglard 
159*3f982cf4SFabien Sanglard }  // namespace cast
160*3f982cf4SFabien Sanglard }  // namespace openscreen
161