blob: ca68ab31b0b17497150c7ca6748db9a7cae1878e [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.
#ifndef CAST_STREAMING_FRAME_COLLECTOR_H_
#define CAST_STREAMING_FRAME_COLLECTOR_H_
#include <vector>
#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<uint8_t>* 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<PacketNack>* 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<uint8_t> buffer;
absl::Span<const uint8_t> 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<PayloadChunk> chunks_;
};
} // namespace cast
} // namespace openscreen
#endif // CAST_STREAMING_FRAME_COLLECTOR_H_