blob: 431c4327db1ba3e7594cc8e3c4ac99ba260f1aeb [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_MIRRORING_SERVICE_REMOTING_SENDER_H_
#define COMPONENTS_MIRRORING_SERVICE_REMOTING_SENDER_H_
#include <memory>
#include "base/component_export.h"
#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "media/cast/sender/frame_sender.h"
#include "media/mojo/mojom/remoting.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
namespace base {
class TickClock;
} // namespace base
namespace media {
class DecoderBuffer;
} // namespace media
namespace media::cast {
class DecoderBufferReader;
} // namespace media::cast
namespace openscreen::cast {
class Sender;
} // namespace openscreen::cast
namespace mirroring {
// RTP sender for a single Cast Remoting RTP stream. The client calls Send() to
// instruct the sender to read from a Mojo data pipe and transmit the data using
// a CastTransport.
class COMPONENT_EXPORT(MIRRORING_SERVICE) RemotingSender final
: public media::mojom::RemotingDataStreamSender,
public media::cast::FrameSender::Client {
public:
// New way of instantiating using an openscreen::cast::Sender. Since the
// |Sender| instance is destroyed when renegotiation is complete, |this|
// is also invalid and should be immediately torn down.
RemotingSender(scoped_refptr<media::cast::CastEnvironment> cast_environment,
std::unique_ptr<openscreen::cast::Sender> sender,
const media::cast::FrameSenderConfig& config,
mojo::ScopedDataPipeConsumerHandle pipe,
mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
stream_sender,
base::OnceClosure error_callback);
RemotingSender(const RemotingSender&) = delete;
RemotingSender& operator=(const RemotingSender&) = delete;
~RemotingSender() override;
private:
// Ctor that takes a media::cast::FrameSender for unit tests.
// TODO(issues.chromium.org/329781397): Remove unnecessary wrapper objects in
// Chrome's implementation of the Cast sender.
RemotingSender(scoped_refptr<media::cast::CastEnvironment> cast_environment,
std::unique_ptr<media::cast::FrameSender> sender,
const media::cast::FrameSenderConfig& config,
mojo::ScopedDataPipeConsumerHandle pipe,
mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
stream_sender,
base::OnceClosure error_callback);
// Friend class for unit tests.
friend class RemotingSenderTest;
// Creates SenderEncodedFrames.
class SenderEncodedFrameFactory;
// media::mojom::RemotingDataStreamSender implementation.
void SendFrame(media::mojom::DecoderBufferPtr buffer,
SendFrameCallback callback) override;
void CancelInFlightData() override;
// FrameSender::Client overrides.
int GetNumberOfFramesInEncoder() const override;
base::TimeDelta GetEncoderBacklogDuration() const override;
void OnFrameCanceled(media::cast::FrameId frame_id) override;
// Sends out the frame to the receiver over network if |frame_sender_| has
// available space to handle it.
void TrySendFrame();
// Sets |next_frame_| once it has been read from the data pipe.
void OnFrameRead(scoped_refptr<media::DecoderBuffer> buffer);
// Called when |stream_sender_| is disconnected.
void OnRemotingDataStreamError();
// Clears the current frame and requests a new one be sent.
void ClearCurrentFrame();
// Returns true if OnRemotingDataStreamError was called.
bool HadError() const {
DCHECK_EQ(!decoder_buffer_reader_, !stream_sender_.is_bound());
return !decoder_buffer_reader_;
}
SEQUENCE_CHECKER(sequence_checker_);
// The backing frame sender implementation.
std::unique_ptr<media::cast::FrameSender> frame_sender_;
raw_ref<const base::TickClock> clock_;
// Callback that is run to notify when a fatal error occurs.
base::OnceClosure error_callback_;
// Reads media::DecoderBuffer instances and passes them to OnFrameRead().
std::unique_ptr<media::cast::DecoderBufferReader> decoder_buffer_reader_;
// Mojo receiver for this instance. Implementation at the other end of the
// message pipe uses the RemotingDataStreamSender remote to control when
// this RemotingSender consumes from |pipe_|.
mojo::Receiver<media::mojom::RemotingDataStreamSender> stream_sender_;
// Whether this is an audio sender (true) or a video sender (false).
const bool is_audio_;
// Responsible for creating encoded frames.
std::unique_ptr<SenderEncodedFrameFactory> frame_factory_;
// The next frame. Populated by call to OnFrameRead() when reading succeeded.
scoped_refptr<media::DecoderBuffer> next_frame_;
// To be called once a frame has been successfully read and this instance is
// ready to process a new one.
SendFrameCallback read_complete_cb_;
// Set to true if the first frame has not yet been sent, or if a
// CancelInFlightData() operation just completed. This causes TrySendFrame()
// to mark the next frame as the start of a new sequence.
bool flow_restart_pending_ = true;
// Number of EnqueueFrame() calls that have failed since the last successful
// call.
int consecutive_enqueue_frame_failure_count_ = 0;
// The next frame's ID. Before any frames are sent, this will be the ID of
// the first frame.
media::cast::FrameId next_frame_id_ = media::cast::FrameId::first();
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<RemotingSender> weak_factory_{this};
};
} // namespace mirroring
#endif // COMPONENTS_MIRRORING_SERVICE_REMOTING_SENDER_H_