blob: c74bb3ec0102d1d6709ec8a3167aa245b40db82b [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_COMPOUND_RTCP_PARSER_H_
#define CAST_STREAMING_COMPOUND_RTCP_PARSER_H_
#include <chrono>
#include <vector>
#include "absl/types/optional.h"
#include "absl/types/span.h"
#include "cast/streaming/frame_id.h"
#include "cast/streaming/rtcp_common.h"
#include "cast/streaming/rtp_defines.h"
namespace openscreen {
namespace cast {
class RtcpSession;
// Parses compound RTCP packets from a Receiver, invoking client callbacks when
// information of interest to a Sender (in the current process) is encountered.
class CompoundRtcpParser {
public:
// Callback interface used while parsing RTCP packets of interest to a Sender.
// The implementation must take into account:
//
// 1. Some/All of the data could be stale, as it only reflects the state of
// the Receiver at the time the packet was generated. A significant
// amount of time may have passed, depending on how long it took the
// packet to reach this local instance over the network.
// 2. The data shouldn't necessarily be trusted blindly: Some may be
// inconsistent (e.g., the same frame being ACKed and NACKed; or a frame
// that has not been sent yet is being NACKed). While that would indicate
// a badly-behaving Receiver, the Sender should be robust to such things.
class Client {
public:
Client();
virtual ~Client();
// Called when a Receiver Reference Time Report has been parsed.
virtual void OnReceiverReferenceTimeAdvanced(
Clock::time_point reference_time);
// Called when a Receiver Report with a Report Block has been parsed.
virtual void OnReceiverReport(const RtcpReportBlock& receiver_report);
// Called when the Receiver has encountered an unrecoverable error in
// decoding the data. The Sender should provide a key frame as soon as
// possible.
virtual void OnReceiverIndicatesPictureLoss();
// Called when the Receiver indicates that all of the packets for all frames
// up to and including |frame_id| have been successfully received (or
// otherwise do not need to be re-transmitted). The |playout_delay| is the
// Receiver's current end-to-end target playout delay setting, which should
// reflect any changes the Sender has made by using the "Cast Adaptive
// Latency Extension" in RTP packets.
virtual void OnReceiverCheckpoint(FrameId frame_id,
std::chrono::milliseconds playout_delay);
// Called to indicate the Receiver has successfully received all of the
// packets for each of the given |acks|. The argument's elements are in
// monotonically increasing order.
virtual void OnReceiverHasFrames(std::vector<FrameId> acks);
// Called to indicate the Receiver is missing certain specific packets for
// certain specific frames. Any elements where the packet_id is
// kAllPacketsLost indicates that all the packets are missing for a frame.
// The argument's elements are in monotonically increasing order.
virtual void OnReceiverIsMissingPackets(std::vector<PacketNack> nacks);
};
// |session| and |client| must be non-null and must outlive the
// CompoundRtcpParser instance.
CompoundRtcpParser(RtcpSession* session, Client* client);
~CompoundRtcpParser();
// Parses the packet, invoking the Client callback methods when appropriate.
// Returns true if the |packet| was well-formed, or false if it was corrupt.
// Note that none of the Client callback methods will be invoked until a
// packet is known to be well-formed.
//
// |max_feedback_frame_id| is the maximum-valued FrameId that could possibly
// be ACKnowledged by the Receiver, if there is Cast Feedback in the |packet|.
// This is needed for expanding truncated frame IDs correctly.
bool Parse(absl::Span<const uint8_t> packet, FrameId max_feedback_frame_id);
private:
// These return true if the input was well-formed, and false if it was
// invalid/corrupt. The true/false value does NOT indicate whether the data
// contained within was ignored. Output arguments are only modified if the
// input contained the relevant field(s).
bool ParseReceiverReport(absl::Span<const uint8_t> in,
int num_report_blocks,
absl::optional<RtcpReportBlock>* receiver_report);
bool ParseFeedback(absl::Span<const uint8_t> in,
FrameId max_feedback_frame_id,
FrameId* checkpoint_frame_id,
std::chrono::milliseconds* target_playout_delay,
std::vector<FrameId>* received_frames,
std::vector<PacketNack>* packet_nacks);
bool ParseExtendedReports(absl::Span<const uint8_t> in,
Clock::time_point* receiver_reference_time);
bool ParsePictureLossIndicator(absl::Span<const uint8_t> in,
bool* picture_loss_indicator);
RtcpSession* const session_;
Client* const client_;
// Tracks the latest timestamp seen from any Receiver Reference Time Report,
// and uses this to ignore stale RTCP packets that arrived out-of-order and/or
// late from the network.
Clock::time_point latest_receiver_timestamp_;
};
} // namespace cast
} // namespace openscreen
#endif // CAST_STREAMING_COMPOUND_RTCP_PARSER_H_