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 #ifndef CAST_STREAMING_FRAME_COLLECTOR_H_ 6 #define CAST_STREAMING_FRAME_COLLECTOR_H_ 7 8 #include <vector> 9 10 #include "absl/types/span.h" 11 #include "cast/streaming/frame_crypto.h" 12 #include "cast/streaming/frame_id.h" 13 #include "cast/streaming/rtcp_common.h" 14 #include "cast/streaming/rtp_packet_parser.h" 15 16 namespace openscreen { 17 namespace cast { 18 19 // Used by a Receiver to collect the parts of a frame, track what is 20 // missing/complete, and assemble a complete frame. 21 class FrameCollector { 22 public: 23 FrameCollector(); 24 ~FrameCollector(); 25 26 // Sets the ID of the current frame being collected. This must be called after 27 // each Reset(), and before any of the other methods. set_frame_id(FrameId frame_id)28 void set_frame_id(FrameId frame_id) { frame_.frame_id = frame_id; } 29 30 // Examine the parsed packet, representing part of the whole frame, and 31 // collect any data/metadata from it that helps complete the frame. Returns 32 // false if the |part| contained invalid data. On success, this method takes 33 // the data contained within the |buffer|, into which |part.payload| is 34 // pointing, in lieu of copying the data. 35 [[nodiscard]] bool CollectRtpPacket(const RtpPacketParser::ParseResult& part, 36 std::vector<uint8_t>* buffer); 37 38 // Returns true if the frame data collection is complete and the frame can be 39 // assembled. is_complete()40 bool is_complete() const { return num_missing_packets_ == 0; } 41 42 // Appends zero or more elements to |nacks| representing which packets are not 43 // yet collected. If all packets for the frame are missing, this appends a 44 // single element containing the special kAllPacketsLost packet ID. Otherwise, 45 // one element is appended for each missing packet, in increasing order of 46 // packet ID. 47 void GetMissingPackets(std::vector<PacketNack>* nacks) const; 48 49 // Returns a read-only reference to the completely-collected frame, assembling 50 // it if necessary. The caller should reset the FrameCollector (see Reset() 51 // below) to free-up memory once it has finished reading from the returned 52 // frame. 53 // 54 // Precondition: is_complete() must return true before this method can be 55 // called. 56 const EncryptedFrame& PeekAtAssembledFrame(); 57 58 // Resets the FrameCollector back to its initial state, freeing-up memory. 59 void Reset(); 60 61 private: 62 struct PayloadChunk { 63 std::vector<uint8_t> buffer; 64 absl::Span<const uint8_t> payload; // Once set, is within |buffer.data()|. 65 66 PayloadChunk(); 67 ~PayloadChunk(); 68 has_dataPayloadChunk69 bool has_data() const { return !!payload.data(); } 70 }; 71 72 // Storage for frame metadata and data. Once the frame has been completely 73 // collected and assembled, |frame_.data| is set to non-null, and this is 74 // exposed externally (read-only). 75 EncryptedFrame frame_; 76 77 // The number of packets needed to complete the frame, or the maximum int if 78 // this is not yet known. 79 int num_missing_packets_; 80 81 // The chunks of payload data being collected, where element indices 82 // correspond 1:1 with packet IDs. When the first part is collected, this is 83 // resized to match the total number of packets being expected. 84 std::vector<PayloadChunk> chunks_; 85 }; 86 87 } // namespace cast 88 } // namespace openscreen 89 90 #endif // CAST_STREAMING_FRAME_COLLECTOR_H_ 91