aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Keane <rwkeane@google.com>2021-05-05 17:20:41 -0700
committerCommit Bot <commit-bot@chromium.org>2021-05-10 23:40:03 +0000
commit655e5480afbd232c73a1ea33b23dddc40eb12f01 (patch)
tree5e6209f745abe061f82a37515556ea9141cf9baf
parent37e21e8e06746c3106ff4c22ca8e41d29ffc27d6 (diff)
downloadopenscreen-655e5480afbd232c73a1ea33b23dddc40eb12f01.tar.gz
Create Base Class for Receiver
This class defines a base class for the //cast/streaming/receiver class. It is necessary to allow for unit testing of classes which require a Receiver type. Change-Id: I7a462ec64d83b41beb6e4a6d31098dc85f521fa2 Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2876289 Reviewed-by: Jordan Bayles <jophba@chromium.org> Commit-Queue: Ryan Keane <rwkeane@google.com>
-rw-r--r--cast/streaming/BUILD.gn2
-rw-r--r--cast/streaming/receiver.cc12
-rw-r--r--cast/streaming/receiver.h78
-rw-r--r--cast/streaming/receiver_base.cc17
-rw-r--r--cast/streaming/receiver_base.h108
5 files changed, 154 insertions, 63 deletions
diff --git a/cast/streaming/BUILD.gn b/cast/streaming/BUILD.gn
index 013073cc..85867a95 100644
--- a/cast/streaming/BUILD.gn
+++ b/cast/streaming/BUILD.gn
@@ -111,6 +111,8 @@ source_set("receiver") {
"packet_receive_stats_tracker.h",
"receiver.cc",
"receiver.h",
+ "receiver_base.cc",
+ "receiver_base.h",
"receiver_packet_router.cc",
"receiver_packet_router.h",
"receiver_session.cc",
diff --git a/cast/streaming/receiver.cc b/cast/streaming/receiver.cc
index 271904f5..ee2b0bc5 100644
--- a/cast/streaming/receiver.cc
+++ b/cast/streaming/receiver.cc
@@ -61,6 +61,16 @@ Receiver::~Receiver() {
packet_router_->OnReceiverDestroyed(rtcp_session_.sender_ssrc());
}
+const SessionConfig& Receiver::config() const {
+ return config_;
+}
+int Receiver::rtp_timebase() const {
+ return rtp_timebase_;
+}
+Ssrc Receiver::ssrc() const {
+ return rtcp_session_.receiver_ssrc();
+}
+
void Receiver::SetConsumer(Consumer* consumer) {
consumer_ = consumer;
ScheduleFrameReadyCheck();
@@ -465,8 +475,6 @@ void Receiver::ScheduleFrameReadyCheck(Clock::time_point when) {
when);
}
-Receiver::Consumer::~Consumer() = default;
-
Receiver::PendingFrame::PendingFrame() = default;
Receiver::PendingFrame::~PendingFrame() = default;
diff --git a/cast/streaming/receiver.h b/cast/streaming/receiver.h
index 66edb7d5..d7fd1c80 100644
--- a/cast/streaming/receiver.h
+++ b/cast/streaming/receiver.h
@@ -21,6 +21,7 @@
#include "cast/streaming/frame_collector.h"
#include "cast/streaming/frame_id.h"
#include "cast/streaming/packet_receive_stats_tracker.h"
+#include "cast/streaming/receiver_base.h"
#include "cast/streaming/rtcp_common.h"
#include "cast/streaming/rtcp_session.h"
#include "cast/streaming/rtp_packet_parser.h"
@@ -103,20 +104,9 @@ class ReceiverPacketRouter;
// 3. Last Frame Consumed: The FrameId of last frame consumed (see
// ConsumeNextFrame()). Once a frame is consumed, all internal resources
// related to the frame can be freed and/or re-used for later frames.
-class Receiver {
+class Receiver : public ReceiverBase {
public:
- class Consumer {
- public:
- virtual ~Consumer();
-
- // Called whenever one or more frames have become ready for consumption. The
- // |next_frame_buffer_size| argument is identical to the result of calling
- // AdvanceToNextFrame(), and so the Consumer only needs to prepare a buffer
- // and call ConsumeNextFrame(). It may then call AdvanceToNextFrame() to
- // check whether there are any more frames ready, but this is not mandatory.
- // See usage example in class-level comments.
- virtual void OnFramesReady(int next_frame_buffer_size) = 0;
- };
+ using ReceiverBase::Consumer;
// Constructs a Receiver that attaches to the given |environment| and
// |packet_router|. The config contains the settings that were
@@ -126,52 +116,17 @@ class Receiver {
Receiver(Environment* environment,
ReceiverPacketRouter* packet_router,
SessionConfig config);
- ~Receiver();
-
- const SessionConfig& config() const { return config_; }
- int rtp_timebase() const { return rtp_timebase_; }
- Ssrc ssrc() const { return rtcp_session_.receiver_ssrc(); }
-
- // Set the Consumer receiving notifications when new frames are ready for
- // consumption. Frames received before this method is called will remain in
- // the queue indefinitely.
- void SetConsumer(Consumer* consumer);
-
- // Sets how much time the consumer will need to decode/buffer/render/etc., and
- // otherwise fully process a frame for on-time playback. This information is
- // used by the Receiver to decide whether to skip past frames that have
- // arrived too late. This method can be called repeatedly to make adjustments
- // based on changing environmental conditions.
- //
- // Default setting: kDefaultPlayerProcessingTime
- void SetPlayerProcessingTime(Clock::duration needed_time);
-
- // Propagates a "picture loss indicator" notification to the Sender,
- // requesting a key frame so that decode/playout can recover. It is safe to
- // call this redundantly. The Receiver will clear the picture loss condition
- // automatically, once a key frame is received (i.e., before
- // ConsumeNextFrame() is called to access it).
- void RequestKeyFrame();
-
- // Advances to the next frame ready for consumption. This may skip-over
- // incomplete frames that will not play out on-time; but only if there are
- // completed frames further down the queue that have no dependency
- // relationship with them (e.g., key frames).
- //
- // This method returns kNoFramesReady if there is not currently a frame ready
- // for consumption. The caller should wait for a Consumer::OnFramesReady()
- // notification before trying again. Otherwise, the number of bytes of encoded
- // data is returned, and the caller should use this to ensure the buffer it
- // passes to ConsumeNextFrame() is large enough.
- int AdvanceToNextFrame();
-
- // Returns the next frame, both metadata and payload data. The Consumer calls
- // this method after being notified via OnFramesReady(), and it can also call
- // this whenever AdvanceToNextFrame() indicates another frame is ready.
- // |buffer| must point to a sufficiently-sized buffer that will be populated
- // with the frame's payload data. Upon return |frame->data| will be set to the
- // portion of the buffer that was populated.
- EncodedFrame ConsumeNextFrame(absl::Span<uint8_t> buffer);
+ ~Receiver() override;
+
+ // ReceiverBase overrides.
+ const SessionConfig& config() const override;
+ int rtp_timebase() const override;
+ Ssrc ssrc() const override;
+ void SetConsumer(Consumer* consumer) override;
+ void SetPlayerProcessingTime(Clock::duration needed_time) override;
+ void RequestKeyFrame() override;
+ int AdvanceToNextFrame() override;
+ EncodedFrame ConsumeNextFrame(absl::Span<uint8_t> buffer) override;
// Allows setting picture loss indication for testing. In production, this
// should be done using the config.
@@ -180,11 +135,12 @@ class Receiver {
}
// The default "player processing time" amount. See SetPlayerProcessingTime().
- static constexpr std::chrono::milliseconds kDefaultPlayerProcessingTime{5};
+ static constexpr std::chrono::milliseconds kDefaultPlayerProcessingTime =
+ ReceiverBase::kDefaultPlayerProcessingTime;
// Returned by AdvanceToNextFrame() when there are no frames currently ready
// for consumption.
- static constexpr int kNoFramesReady = -1;
+ static constexpr int kNoFramesReady = ReceiverBase::kNoFramesReady;
protected:
friend class ReceiverPacketRouter;
diff --git a/cast/streaming/receiver_base.cc b/cast/streaming/receiver_base.cc
new file mode 100644
index 00000000..dd0067df
--- /dev/null
+++ b/cast/streaming/receiver_base.cc
@@ -0,0 +1,17 @@
+// Copyright 2021 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.
+
+#include "cast/streaming/receiver_base.h"
+
+namespace openscreen {
+namespace cast {
+
+ReceiverBase::Consumer::~Consumer() = default;
+
+ReceiverBase::ReceiverBase() = default;
+
+ReceiverBase::~ReceiverBase() = default;
+
+} // namespace cast
+} // namespace openscreen
diff --git a/cast/streaming/receiver_base.h b/cast/streaming/receiver_base.h
new file mode 100644
index 00000000..0ad3ff86
--- /dev/null
+++ b/cast/streaming/receiver_base.h
@@ -0,0 +1,108 @@
+// Copyright 2021 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_RECEIVER_BASE_H_
+#define CAST_STREAMING_RECEIVER_BASE_H_
+
+#include <chrono>
+
+#include "absl/types/span.h"
+#include "cast/streaming/encoded_frame.h"
+#include "cast/streaming/session_config.h"
+#include "cast/streaming/ssrc.h"
+#include "platform/api/time.h"
+
+namespace openscreen {
+namespace cast {
+
+// The Cast Streaming Receiver, a peer corresponding to some Cast Streaming
+// Sender at the other end of a network link.
+//
+// Cast Streaming is a transport protocol which divides up the frames for one
+// media stream (e.g., audio or video) into multiple RTP packets containing an
+// encrypted payload. The Receiver is the peer responsible for collecting the
+// RTP packets, decrypting the payload, and re-assembling a frame that can be
+// passed to a decoder and played out.
+//
+// A Sender ↔ Receiver pair is used to transport each media stream. Typically,
+// there are two pairs in a normal system, one for the audio stream and one for
+// video stream. A local player is responsible for synchronizing the playout of
+// the frames of each stream to achieve lip-sync. See the discussion in
+// encoded_frame.h for how the |reference_time| and |rtp_timestamp| of the
+// EncodedFrames are used to achieve this.
+class ReceiverBase {
+ public:
+ class Consumer {
+ public:
+ virtual ~Consumer();
+
+ // Called whenever one or more frames have become ready for consumption. The
+ // |next_frame_buffer_size| argument is identical to the result of calling
+ // AdvanceToNextFrame(), and so the Consumer only needs to prepare a buffer
+ // and call ConsumeNextFrame(). It may then call AdvanceToNextFrame() to
+ // check whether there are any more frames ready, but this is not mandatory.
+ // See usage example in class-level comments.
+ virtual void OnFramesReady(int next_frame_buffer_size) = 0;
+ };
+
+ ReceiverBase();
+ virtual ~ReceiverBase();
+
+ virtual const SessionConfig& config() const = 0;
+ virtual int rtp_timebase() const = 0;
+ virtual Ssrc ssrc() const = 0;
+
+ // Set the Consumer receiving notifications when new frames are ready for
+ // consumption. Frames received before this method is called will remain in
+ // the queue indefinitely.
+ virtual void SetConsumer(Consumer* consumer) = 0;
+
+ // Sets how much time the consumer will need to decode/buffer/render/etc., and
+ // otherwise fully process a frame for on-time playback. This information is
+ // used by the Receiver to decide whether to skip past frames that have
+ // arrived too late. This method can be called repeatedly to make adjustments
+ // based on changing environmental conditions.
+ //
+ // Default setting: kDefaultPlayerProcessingTime
+ virtual void SetPlayerProcessingTime(Clock::duration needed_time) = 0;
+
+ // Propagates a "picture loss indicator" notification to the Sender,
+ // requesting a key frame so that decode/playout can recover. It is safe to
+ // call this redundantly. The Receiver will clear the picture loss condition
+ // automatically, once a key frame is received (i.e., before
+ // ConsumeNextFrame() is called to access it).
+ virtual void RequestKeyFrame() = 0;
+
+ // Advances to the next frame ready for consumption. This may skip-over
+ // incomplete frames that will not play out on-time; but only if there are
+ // completed frames further down the queue that have no dependency
+ // relationship with them (e.g., key frames).
+ //
+ // This method returns kNoFramesReady if there is not currently a frame ready
+ // for consumption. The caller should wait for a Consumer::OnFramesReady()
+ // notification before trying again. Otherwise, the number of bytes of encoded
+ // data is returned, and the caller should use this to ensure the buffer it
+ // passes to ConsumeNextFrame() is large enough.
+ virtual int AdvanceToNextFrame() = 0;
+
+ // Returns the next frame, both metadata and payload data. The Consumer calls
+ // this method after being notified via OnFramesReady(), and it can also call
+ // this whenever AdvanceToNextFrame() indicates another frame is ready.
+ // |buffer| must point to a sufficiently-sized buffer that will be populated
+ // with the frame's payload data. Upon return |frame->data| will be set to the
+ // portion of the buffer that was populated.
+ virtual EncodedFrame ConsumeNextFrame(absl::Span<uint8_t> buffer) = 0;
+
+ // The default "player processing time" amount. See SetPlayerProcessingTime().
+ static constexpr std::chrono::milliseconds kDefaultPlayerProcessingTime{5};
+
+ // Returned by AdvanceToNextFrame() when there are no frames currently ready
+ // for consumption.
+ static constexpr int kNoFramesReady = -1;
+};
+
+#endif // CAST_STREAMING_RECEIVER_BASE_H_
+
+} // namespace cast
+} // namespace openscreen