1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROMECAST_MEDIA_SERVICE_CAST_RENDERER_H_
6 #define CHROMECAST_MEDIA_SERVICE_CAST_RENDERER_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/memory/weak_ptr.h"
12 #include "base/no_destructor.h"
13 #include "base/optional.h"
14 #include "base/unguessable_token.h"
15 #include "chromecast/common/mojom/multiroom.mojom.h"
16 #include "chromecast/common/mojom/service_connector.mojom.h"
17 #include "chromecast/media/api/cma_backend_factory.h"
18 #include "chromecast/media/base/video_resolution_policy.h"
19 #include "chromecast/media/service/mojom/video_geometry_setter.mojom.h"
20 #include "media/base/renderer.h"
21 #include "media/base/waiting.h"
22 #include "media/mojo/mojom/cast_application_media_info_manager.mojom.h"
23 #include "media/mojo/mojom/frame_interface_factory.mojom.h"
24 #include "mojo/public/cpp/bindings/receiver.h"
25 #include "mojo/public/cpp/bindings/remote.h"
26 #include "ui/gfx/geometry/rect_f.h"
27 #include "ui/gfx/overlay_transform.h"
28 
29 namespace base {
30 class SingleThreadTaskRunner;
31 }  // namespace base
32 
33 namespace chromecast {
34 class TaskRunnerImpl;
35 
36 namespace media {
37 class BalancedMediaTaskRunnerFactory;
38 class CastCdmContext;
39 class MediaPipelineImpl;
40 class VideoGeometrySetterService;
41 class VideoModeSwitcher;
42 
43 class CastRenderer : public ::media::Renderer,
44                      public VideoResolutionPolicy::Observer,
45                      public mojom::VideoGeometryChangeClient {
46  public:
47   // |frame_interfaces| provides interfaces tied to RenderFrameHost.
48   CastRenderer(CmaBackendFactory* backend_factory,
49                const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
50                VideoModeSwitcher* video_mode_switcher,
51                VideoResolutionPolicy* video_resolution_policy,
52                const base::UnguessableToken& overlay_plane_id,
53                ::media::mojom::FrameInterfaceFactory* frame_interfaces);
54   ~CastRenderer() final;
55   // For CmaBackend implementation, CastRenderer must be connected to
56   // VideoGeometrySetterService.
57   void SetVideoGeometrySetterService(
58       VideoGeometrySetterService* video_geometry_setter_service);
59 
60   // ::media::Renderer implementation.
61   void Initialize(::media::MediaResource* media_resource,
62                   ::media::RendererClient* client,
63                   ::media::PipelineStatusCallback init_cb) final;
64   void SetCdm(::media::CdmContext* cdm_context,
65               CdmAttachedCB cdm_attached_cb) final;
66   void SetLatencyHint(base::Optional<base::TimeDelta> latency_hint) final;
67   void Flush(base::OnceClosure flush_cb) final;
68   void StartPlayingFrom(base::TimeDelta time) final;
69   void SetPlaybackRate(double playback_rate) final;
70   void SetVolume(float volume) final;
71   base::TimeDelta GetMediaTime() final;
72 
73   // VideoResolutionPolicy::Observer implementation.
74   void OnVideoResolutionPolicyChanged() override;
75 
76   // mojom::VideoGeometryChangeClient implementation.
77   void OnVideoGeometryChange(const gfx::RectF& rect_f,
78                              gfx::OverlayTransform transform) final;
79 
80   // TODO(guohuideng): For now we use a global callback to gain access to
81   // VideoPlaneController so CastRenderer can set the video geometry. We
82   // should separate the SetGeometry from VideoPlaneController and get rid
83   // of this callback. see b/79266094.
84   using OverlayCompositedCallback =
85       base::RepeatingCallback<void(const gfx::RectF&, gfx::OverlayTransform)>;
86   static void SetOverlayCompositedCallback(const OverlayCompositedCallback& cb);
87 
88  private:
89   enum Stream { STREAM_AUDIO, STREAM_VIDEO };
90   void OnSubscribeToVideoGeometryChange(::media::MediaResource* media_resource,
91                                         ::media::RendererClient* client);
92   void OnApplicationMediaInfoReceived(
93       ::media::MediaResource* media_resource,
94       ::media::RendererClient* client,
95       ::media::mojom::CastApplicationMediaInfoPtr application_media_info);
96   void OnGetMultiroomInfo(
97       ::media::MediaResource* media_resource,
98       ::media::RendererClient* client,
99       ::media::mojom::CastApplicationMediaInfoPtr application_media_info,
100       chromecast::mojom::MultiroomInfoPtr multiroom_info);
101   void OnError(::media::PipelineStatus status);
102   void OnEnded(Stream stream);
103   void OnStatisticsUpdate(const ::media::PipelineStatistics& stats);
104   void OnBufferingStateChange(::media::BufferingState state,
105                               ::media::BufferingStateChangeReason reason);
106   void OnWaiting(::media::WaitingReason reason);
107   void OnVideoNaturalSizeChange(const gfx::Size& size);
108   void OnVideoOpacityChange(bool opaque);
109   void CheckVideoResolutionPolicy();
110   void RunInitCallback(::media::PipelineStatus status);
111   void OnVideoInitializationFinished(::media::PipelineStatus status);
112 
113   CmaBackendFactory* const backend_factory_;
114   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
115   VideoModeSwitcher* video_mode_switcher_;
116   VideoResolutionPolicy* video_resolution_policy_;
117   base::UnguessableToken overlay_plane_id_;
118   mojo::Remote<chromecast::mojom::ServiceConnector> service_connector_;
119   ::media::mojom::FrameInterfaceFactory* frame_interfaces_;
120 
121   ::media::RendererClient* client_;
122   CastCdmContext* cast_cdm_context_;
123   scoped_refptr<BalancedMediaTaskRunnerFactory> media_task_runner_factory_;
124   std::unique_ptr<TaskRunnerImpl> backend_task_runner_;
125   std::unique_ptr<MediaPipelineImpl> pipeline_;
126   bool eos_[2];
127   gfx::Size video_res_;
128 
129   mojo::Remote<::media::mojom::CastApplicationMediaInfoManager>
130       application_media_info_manager_remote_;
131   VideoGeometrySetterService* video_geometry_setter_service_;
132   mojo::Remote<mojom::VideoGeometryChangeSubscriber>
133       video_geometry_change_subcriber_remote_;
134   mojo::Remote<chromecast::mojom::MultiroomManager> multiroom_manager_;
135   ::media::PipelineStatusCallback init_cb_;
136   mojo::Receiver<mojom::VideoGeometryChangeClient>
137       video_geometry_change_client_receiver_{this};
138 
GetOverlayCompositedCallback()139   static OverlayCompositedCallback& GetOverlayCompositedCallback() {
140     static base::NoDestructor<OverlayCompositedCallback>
141         g_overlay_composited_callback;
142     return *g_overlay_composited_callback;
143   }
144 
145   base::Optional<float> pending_volume_;
146 
147   base::WeakPtrFactory<CastRenderer> weak_factory_;
148   DISALLOW_COPY_AND_ASSIGN(CastRenderer);
149 };
150 
151 }  // namespace media
152 }  // namespace chromecast
153 
154 #endif  // CHROMECAST_MEDIA_SERVICE_CAST_RENDERER_H_
155