// 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. #ifndef CAST_STREAMING_FRAME_COLLECTOR_H_ #define CAST_STREAMING_FRAME_COLLECTOR_H_ #include #include "absl/types/span.h" #include "cast/streaming/frame_crypto.h" #include "cast/streaming/frame_id.h" #include "cast/streaming/rtcp_common.h" #include "cast/streaming/rtp_packet_parser.h" namespace openscreen { namespace cast { // Used by a Receiver to collect the parts of a frame, track what is // missing/complete, and assemble a complete frame. class FrameCollector { public: FrameCollector(); ~FrameCollector(); // Sets the ID of the current frame being collected. This must be called after // each Reset(), and before any of the other methods. void set_frame_id(FrameId frame_id) { frame_.frame_id = frame_id; } // Examine the parsed packet, representing part of the whole frame, and // collect any data/metadata from it that helps complete the frame. Returns // false if the |part| contained invalid data. On success, this method takes // the data contained within the |buffer|, into which |part.payload| is // pointing, in lieu of copying the data. [[nodiscard]] bool CollectRtpPacket(const RtpPacketParser::ParseResult& part, std::vector* buffer); // Returns true if the frame data collection is complete and the frame can be // assembled. bool is_complete() const { return num_missing_packets_ == 0; } // Appends zero or more elements to |nacks| representing which packets are not // yet collected. If all packets for the frame are missing, this appends a // single element containing the special kAllPacketsLost packet ID. Otherwise, // one element is appended for each missing packet, in increasing order of // packet ID. void GetMissingPackets(std::vector* nacks) const; // Returns a read-only reference to the completely-collected frame, assembling // it if necessary. The caller should reset the FrameCollector (see Reset() // below) to free-up memory once it has finished reading from the returned // frame. // // Precondition: is_complete() must return true before this method can be // called. const EncryptedFrame& PeekAtAssembledFrame(); // Resets the FrameCollector back to its initial state, freeing-up memory. void Reset(); private: struct PayloadChunk { std::vector buffer; absl::Span payload; // Once set, is within |buffer.data()|. PayloadChunk(); ~PayloadChunk(); bool has_data() const { return !!payload.data(); } }; // Storage for frame metadata and data. Once the frame has been completely // collected and assembled, |frame_.data| is set to non-null, and this is // exposed externally (read-only). EncryptedFrame frame_; // The number of packets needed to complete the frame, or the maximum int if // this is not yet known. int num_missing_packets_; // The chunks of payload data being collected, where element indices // correspond 1:1 with packet IDs. When the first part is collected, this is // resized to match the total number of packets being expected. std::vector chunks_; }; } // namespace cast } // namespace openscreen #endif // CAST_STREAMING_FRAME_COLLECTOR_H_