| // Copyright 2017 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 MEDIA_REMOTING_STREAM_PROVIDER_H_ | 
 | #define MEDIA_REMOTING_STREAM_PROVIDER_H_ | 
 |  | 
 | #include "base/callback_forward.h" | 
 | #include "base/containers/circular_deque.h" | 
 | #include "base/memory/scoped_refptr.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "base/sequenced_task_runner_helpers.h" | 
 | #include "base/single_thread_task_runner.h" | 
 | #include "media/base/audio_decoder_config.h" | 
 | #include "media/base/demuxer.h" | 
 | #include "media/base/demuxer_stream.h" | 
 | #include "media/base/video_decoder_config.h" | 
 | #include "media/mojo/mojom/remoting.mojom.h" | 
 | #include "mojo/public/cpp/bindings/receiver.h" | 
 | #include "mojo/public/cpp/bindings/remote.h" | 
 | #include "third_party/openscreen/src/cast/streaming/remoting.pb.h" | 
 |  | 
 | namespace base { | 
 | class SingleThreadTaskRunner; | 
 | }  // namespace base | 
 |  | 
 | namespace openscreen { | 
 | namespace cast { | 
 | class RpcMessenger; | 
 | } | 
 | }  // namespace openscreen | 
 |  | 
 | namespace media { | 
 |  | 
 | class MojoDecoderBufferReader; | 
 |  | 
 | namespace remoting { | 
 |  | 
 | class ReceiverController; | 
 |  | 
 | // The media stream provider for Media Remoting receiver. | 
 | class StreamProvider final : public Demuxer { | 
 |  public: | 
 |   StreamProvider( | 
 |       ReceiverController* receiver_controller, | 
 |       const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner); | 
 |  | 
 |   // Demuxer implementation. | 
 |   std::vector<DemuxerStream*> GetAllStreams() override; | 
 |   std::string GetDisplayName() const override; | 
 |   void Initialize(DemuxerHost* host, PipelineStatusCallback status_cb) override; | 
 |   void AbortPendingReads() override; | 
 |   void StartWaitingForSeek(base::TimeDelta seek_time) override; | 
 |   void CancelPendingSeek(base::TimeDelta seek_time) override; | 
 |   void Seek(base::TimeDelta time, PipelineStatusCallback status_cb) override; | 
 |   void Stop() override; | 
 |   base::TimeDelta GetStartTime() const override; | 
 |   base::Time GetTimelineOffset() const override; | 
 |   int64_t GetMemoryUsage() const override; | 
 |   absl::optional<container_names::MediaContainerName> GetContainerForMetrics() | 
 |       const override; | 
 |   void OnEnabledAudioTracksChanged(const std::vector<MediaTrack::Id>& track_ids, | 
 |                                    base::TimeDelta curr_time, | 
 |                                    TrackChangeCB change_completed_cb) override; | 
 |   void OnSelectedVideoTrackChanged(const std::vector<MediaTrack::Id>& track_ids, | 
 |                                    base::TimeDelta curr_time, | 
 |                                    TrackChangeCB change_completed_cb) override; | 
 |  | 
 |  protected: | 
 |   // Deletion is only allowed via Destroy(). | 
 |   ~StreamProvider() override; | 
 |  | 
 |  private: | 
 |   // An implementation of media::DemuxerStream on Media Remoting receiver. | 
 |   // Receives data from mojo data pipe, and returns one frame or/and status when | 
 |   // Read() is called. | 
 |   class MediaStream final : public DemuxerStream, | 
 |                             public mojom::RemotingDataStreamReceiver { | 
 |    public: | 
 |     using UniquePtr = | 
 |         std::unique_ptr<MediaStream, std::function<void(MediaStream*)>>; | 
 |  | 
 |     // MediaStream should be created on the main thread to be able to get unique | 
 |     // handle ID from |rpc_messenger_|. | 
 |     static void CreateOnMainThread( | 
 |         openscreen::cast::RpcMessenger* rpc_messenger, | 
 |         Type type, | 
 |         int32_t handle, | 
 |         const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, | 
 |         base::OnceCallback<void(MediaStream::UniquePtr)> callback); | 
 |  | 
 |     // In order to destroy members in the right thread, MediaStream has to use | 
 |     // DestructionHelper() to destroy itself. | 
 |     static void DestructionHelper(MediaStream* stream); | 
 |  | 
 |     MediaStream( | 
 |         openscreen::cast::RpcMessenger* rpc_messenger, | 
 |         Type type, | 
 |         int32_t remote_handle, | 
 |         const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner); | 
 |  | 
 |     // DemuxerStream implementation. | 
 |     void Read(ReadCB read_cb) override; | 
 |     AudioDecoderConfig audio_decoder_config() override; | 
 |     VideoDecoderConfig video_decoder_config() override; | 
 |     DemuxerStream::Type type() const override; | 
 |     Liveness liveness() const override; | 
 |     bool SupportsConfigChanges() override; | 
 |  | 
 |     void Initialize(base::OnceClosure init_done_cb); | 
 |  | 
 |     mojo::PendingRemote<mojom::RemotingDataStreamReceiver> | 
 |     BindNewPipeAndPassRemote() { | 
 |       return receiver_.BindNewPipeAndPassRemote(); | 
 |     } | 
 |  | 
 |    private: | 
 |     friend class base::DeleteHelper<MediaStream>;  // For using DeleteSoon(). | 
 |     // For testing. | 
 |     friend class StreamProviderTest; | 
 |  | 
 |     // Prevent from unique_ptr using ~MediaStream() to destroy MediaStream | 
 |     // instances. Use DestructionHelper() as the custom deleter with unique_ptr | 
 |     // to destroy MediaStream instances. | 
 |     ~MediaStream() override; | 
 |  | 
 |     void Destroy(); | 
 |  | 
 |     // Send RPC message on |main_task_runner_|. | 
 |     void SendRpcMessageOnMainThread( | 
 |         std::unique_ptr<openscreen::cast::RpcMessage> message); | 
 |  | 
 |     // mojom::RemotingDataStreamReceiver implementation. | 
 |     void InitializeDataPipe( | 
 |         mojo::ScopedDataPipeConsumerHandle data_pipe) override; | 
 |     void ReceiveFrame(uint32_t count, mojom::DecoderBufferPtr buffer) override; | 
 |     void FlushUntil(uint32_t count) override; | 
 |  | 
 |     // RPC messages handlers. | 
 |     void OnReceivedRpc(std::unique_ptr<openscreen::cast::RpcMessage> message); | 
 |     void OnInitializeCallback( | 
 |         std::unique_ptr<openscreen::cast::RpcMessage> message); | 
 |     void OnReadUntilCallback( | 
 |         std::unique_ptr<openscreen::cast::RpcMessage> message); | 
 |  | 
 |     // Issues the ReadUntil RPC message when read is pending and buffer is | 
 |     // empty. | 
 |     void SendReadUntil(); | 
 |  | 
 |     // Run |init_done_callback_| when MojoDecoderBufferReader is created and | 
 |     // received RPC_DS_INITIALIZE_CALLBACK | 
 |     void CompleteInitialize(); | 
 |  | 
 |     // Append a frame into |buffers_|. | 
 |     void AppendBuffer(uint32_t count, scoped_refptr<DecoderBuffer> buffer); | 
 |  | 
 |     // Run and reset the read callback. | 
 |     void CompleteRead(DemuxerStream::Status status); | 
 |  | 
 |     // Update the audio/video decoder config. When config changes in the mid | 
 |     // stream, the new config will be stored in |next_audio_decoder_config_|. | 
 |     // Old config will be dropped when all associated frames are consumed. | 
 |     void UpdateAudioConfig( | 
 |         const openscreen::cast::AudioDecoderConfig& audio_message); | 
 |     void UpdateVideoConfig( | 
 |         const openscreen::cast::VideoDecoderConfig& video_message); | 
 |  | 
 |     // Called when any error occurs. | 
 |     void OnError(const std::string& error); | 
 |  | 
 |     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 
 |     scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; | 
 |  | 
 |     openscreen::cast::RpcMessenger* const rpc_messenger_; | 
 |     const Type type_; | 
 |     const int remote_handle_; | 
 |     const int rpc_handle_; | 
 |  | 
 |     // Set when Initialize() is called. | 
 |     base::OnceClosure init_done_callback_; | 
 |  | 
 |     // The frame count of the frame to be returned on the next Read call. It | 
 |     // will be increased whenever a frame is read. It will be updated when | 
 |     // FlushUntil() is called. | 
 |     uint32_t current_frame_count_ = 0; | 
 |  | 
 |     // One plus the last frame count received over RTP. Used for continuity | 
 |     // check. | 
 |     uint32_t buffered_frame_count_ = 0; | 
 |  | 
 |     // The total number of frames received from the sender side. It will be used | 
 |     // as the base value for sending ReadUntil() to request more frames and be | 
 |     // updated in OnReadUntilCallback() which would get the message that | 
 |     // contains how many frames are sent. | 
 |     uint32_t total_received_frame_count_ = 0; | 
 |  | 
 |     // Indicates whether a ReadUntil RPC message was sent without receiving the | 
 |     // ReadUntilCallback message yet. | 
 |     bool read_until_sent_ = false; | 
 |  | 
 |     // Indicates whether RPC_DS_INITIALIZE_CALLBACK received. | 
 |     bool rpc_initialized_ = false; | 
 |  | 
 |     // Set when Read() is called. Run only once when read completes. | 
 |     ReadCB read_complete_callback_; | 
 |  | 
 |     // The frame data would be sent via Mojo IPC as MojoDecoderBuffer. When a | 
 |     // frame is sent to |this| from host by calling ReceiveFrame(), | 
 |     // |decoder_buffer_reader_| is used to read the frame date from data pipe. | 
 |     std::unique_ptr<MojoDecoderBufferReader> decoder_buffer_reader_; | 
 |  | 
 |     base::circular_deque<scoped_refptr<DecoderBuffer>> buffers_; | 
 |  | 
 |     // Current audio/video config. | 
 |     AudioDecoderConfig audio_decoder_config_; | 
 |     VideoDecoderConfig video_decoder_config_; | 
 |  | 
 |     // Stores the new audio/video config when config changes. | 
 |     AudioDecoderConfig next_audio_decoder_config_; | 
 |     VideoDecoderConfig next_video_decoder_config_; | 
 |  | 
 |     mojo::Receiver<mojom::RemotingDataStreamReceiver> receiver_{this}; | 
 |  | 
 |     base::WeakPtr<MediaStream> media_weak_this_; | 
 |     base::WeakPtrFactory<MediaStream> media_weak_factory_{this}; | 
 |   }; | 
 |  | 
 |   friend std::default_delete<StreamProvider>; | 
 |   friend class base::DeleteHelper<StreamProvider>;  // For using DeleteSoon(). | 
 |  | 
 |   // For testing. | 
 |   friend class StreamProviderTest; | 
 |  | 
 |   void Destroy(); | 
 |  | 
 |   // RPC messages handlers. | 
 |   void OnReceivedRpc(std::unique_ptr<openscreen::cast::RpcMessage> message); | 
 |   void OnAcquireDemuxer(std::unique_ptr<openscreen::cast::RpcMessage> message); | 
 |  | 
 |   // Called when audio/video stream is created and initialized. | 
 |   void InitializeDataPipe(); | 
 |   void OnAudioStreamCreated(MediaStream::UniquePtr stream); | 
 |   void OnVideoStreamCreated(MediaStream::UniquePtr stream); | 
 |   void OnAudioStreamInitialized(); | 
 |   void OnVideoStreamInitialized(); | 
 |   void CompleteInitialize(); | 
 |  | 
 |   scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 
 |   scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; | 
 |   ReceiverController* const receiver_controller_; | 
 |   openscreen::cast::RpcMessenger* const rpc_messenger_; | 
 |   MediaStream::UniquePtr audio_stream_; | 
 |   MediaStream::UniquePtr video_stream_; | 
 |   bool has_audio_{false}; | 
 |   bool has_video_{false}; | 
 |   bool audio_stream_initialized_{false}; | 
 |   bool video_stream_initialized_{false}; | 
 |  | 
 |   // Set when Initialize() is called, and will run when both video and audio | 
 |   // streams are initialized or error occurs. | 
 |   PipelineStatusCallback init_done_callback_; | 
 |  | 
 |   base::WeakPtr<StreamProvider> media_weak_this_; | 
 |   base::WeakPtrFactory<StreamProvider> media_weak_factory_{this}; | 
 | }; | 
 |  | 
 | }  // namespace remoting | 
 | }  // namespace media | 
 |  | 
 | namespace std { | 
 |  | 
 | // Specialize std::default_delete to call Destroy(). | 
 | template <> | 
 | struct default_delete<media::remoting::StreamProvider> { | 
 |   constexpr default_delete() = default; | 
 |  | 
 |   template <typename U, | 
 |             typename = typename std::enable_if<std::is_convertible< | 
 |                 U*, | 
 |                 media::remoting::StreamProvider*>::value>::type> | 
 |   explicit default_delete(const default_delete<U>& d) {} | 
 |  | 
 |   void operator()(media::remoting::StreamProvider* ptr) const; | 
 | }; | 
 |  | 
 | }  // namespace std | 
 |  | 
 | #endif  // MEDIA_REMOTING_STREAM_PROVIDER_H_ |