1 // Copyright 2015 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 THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_WEBMEDIAPLAYER_MS_COMPOSITOR_H_ 6 #define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_WEBMEDIAPLAYER_MS_COMPOSITOR_H_ 7 8 #include <stddef.h> 9 10 #include <map> 11 #include <memory> 12 #include <vector> 13 14 #include "base/memory/weak_ptr.h" 15 #include "base/optional.h" 16 #include "base/synchronization/lock.h" 17 #include "base/threading/thread_checker.h" 18 #include "cc/layers/surface_layer.h" 19 #include "cc/layers/video_frame_provider.h" 20 #include "media/base/media_util.h" 21 #include "third_party/blink/public/platform/web_media_player.h" 22 #include "third_party/blink/public/platform/web_video_frame_submitter.h" 23 #include "third_party/blink/renderer/modules/mediastream/video_renderer_algorithm_wrapper.h" 24 #include "third_party/blink/renderer/modules/modules_export.h" 25 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" 26 #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" 27 28 namespace base { 29 class SingleThreadTaskRunner; 30 class WaitableEvent; 31 } 32 33 namespace gfx { 34 class Size; 35 } 36 37 namespace media { 38 class VideoRendererAlgorithm; 39 } 40 41 namespace viz { 42 class SurfaceId; 43 } 44 45 namespace blink { 46 class MediaStreamDescriptor; 47 class WebMediaPlayerMS; 48 struct WebMediaPlayerMSCompositorTraits; 49 50 // This class is designed to handle the work load on compositor thread for 51 // WebMediaPlayerMS. It will be instantiated on the main thread, but destroyed 52 // on the thread holding the last reference. 53 // 54 // WebMediaPlayerMSCompositor utilizes VideoRendererAlgorithm to store the 55 // incoming frames and select the best frame for rendering to maximize the 56 // smoothness, if REFERENCE_TIMEs are populated for incoming VideoFrames. 57 // Otherwise, WebMediaPlayerMSCompositor will simply store the most recent 58 // frame, and submit it whenever asked by the compositor. 59 class MODULES_EXPORT WebMediaPlayerMSCompositor 60 : public cc::VideoFrameProvider, 61 public WTF::ThreadSafeRefCounted<WebMediaPlayerMSCompositor, 62 WebMediaPlayerMSCompositorTraits> { 63 public: 64 using OnNewFramePresentedCB = base::OnceClosure; 65 66 WebMediaPlayerMSCompositor( 67 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 68 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 69 MediaStreamDescriptor* media_stream_descriptor, 70 std::unique_ptr<WebVideoFrameSubmitter> submitter, 71 WebMediaPlayer::SurfaceLayerMode surface_layer_mode, 72 const base::WeakPtr<WebMediaPlayerMS>& player); 73 74 // Can be called from any thread. GetUpdateSubmissionStateCallback()75 cc::UpdateSubmissionStateCB GetUpdateSubmissionStateCallback() { 76 return update_submission_state_callback_; 77 } 78 79 void EnqueueFrame(scoped_refptr<media::VideoFrame> frame, bool is_copy); 80 81 // Statistical data 82 gfx::Size GetCurrentSize(); 83 base::TimeDelta GetCurrentTime(); 84 size_t total_frame_count(); 85 size_t dropped_frame_count(); 86 87 // Signals the VideoFrameSubmitter to prepare to receive BeginFrames and 88 // submit video frames given by WebMediaPlayerMSCompositor. 89 virtual void EnableSubmission( 90 const viz::SurfaceId& id, 91 media::VideoTransformation transformation, 92 bool force_submit); 93 94 // Notifies the |submitter_| that the frames must be submitted. 95 void SetForceSubmit(bool force_submit); 96 97 // Notifies the |submitter_| that the page is no longer visible. 98 void SetIsPageVisible(bool is_visible); 99 100 // VideoFrameProvider implementation. 101 void SetVideoFrameProviderClient( 102 cc::VideoFrameProvider::Client* client) override; 103 bool UpdateCurrentFrame(base::TimeTicks deadline_min, 104 base::TimeTicks deadline_max) override; 105 bool HasCurrentFrame() override; 106 scoped_refptr<media::VideoFrame> GetCurrentFrame() override; 107 void PutCurrentFrame() override; 108 base::TimeDelta GetPreferredRenderInterval() override; 109 110 void StartRendering(); 111 void StopRendering(); 112 void ReplaceCurrentFrameWithACopy(); 113 114 // Tell |video_frame_provider_client_| to stop using this instance in 115 // preparation for dtor. 116 void StopUsingProvider(); 117 118 // Sets a hook to be notified when a new frame is presented, to fulfill a 119 // prending video.requestAnimationFrame() request. 120 // Can be called from any thread. 121 void SetOnFramePresentedCallback(OnNewFramePresentedCB presented_cb); 122 123 // Gets the metadata for the last frame that was presented to the compositor. 124 // Used to populate the VideoFrameMetadata of video.requestVideoFrameCallback 125 // callbacks. See https://wicg.github.io/video-rvfc/. 126 // Can be called on any thread. 127 std::unique_ptr<WebMediaPlayer::VideoFramePresentationMetadata> 128 GetLastPresentedFrameMetadata(); 129 130 // Sets the ForceBeginFrames flag on |submitter_|. Can be called from any 131 // thread. 132 // 133 // The flag is used to keep receiving BeginFrame()/UpdateCurrentFrame() calls 134 // even if the video element is not visible, so websites can still use the 135 // requestVideoFrameCallback() API when the video is offscreen. 136 void SetForceBeginFrames(bool enable); 137 138 private: 139 friend class WTF::ThreadSafeRefCounted<WebMediaPlayerMSCompositor, 140 WebMediaPlayerMSCompositorTraits>; 141 friend class WebMediaPlayerMSTest; 142 friend struct WebMediaPlayerMSCompositorTraits; 143 144 // Struct used to keep information about frames pending in 145 // |rendering_frame_buffer_|. 146 struct PendingFrameInfo { 147 int unique_id; 148 base::TimeDelta timestamp; 149 base::TimeTicks reference_time; 150 bool is_copy; 151 }; 152 153 ~WebMediaPlayerMSCompositor() override; 154 155 // Ran on the |video_frame_compositor_task_runner_| to initialize 156 // |submitter_| 157 void InitializeSubmitter(); 158 159 // Signals the VideoFrameSubmitter to stop submitting frames. 160 void SetIsSurfaceVisible(bool, base::WaitableEvent*); 161 162 // The use of std::vector here is OK because this method is bound into a 163 // base::OnceCallback instance, and passed to media::VideoRendererAlgorithm 164 // ctor. 165 bool MapTimestampsToRenderTimeTicks( 166 const std::vector<base::TimeDelta>& timestamps, 167 std::vector<base::TimeTicks>* wall_clock_times); 168 169 // For algorithm enabled case only: given the render interval, call 170 // SetCurrentFrame() if a new frame is available. 171 // |video_frame_provider_client_| gets notified about the new frame when it 172 // calls UpdateCurrentFrame(). 173 void RenderUsingAlgorithm(base::TimeTicks deadline_min, 174 base::TimeTicks deadline_max); 175 176 // For algorithm disabled case only: call SetCurrentFrame() with the current 177 // frame immediately. |video_frame_provider_client_| gets notified about the 178 // new frame with a DidReceiveFrame() call. 179 void RenderWithoutAlgorithm(scoped_refptr<media::VideoFrame> frame, 180 bool is_copy); 181 void RenderWithoutAlgorithmOnCompositor( 182 scoped_refptr<media::VideoFrame> frame, 183 bool is_copy); 184 185 // Update |current_frame_| and |dropped_frame_count_| 186 void SetCurrentFrame( 187 scoped_refptr<media::VideoFrame> frame, 188 bool is_copy, 189 base::Optional<base::TimeTicks> expected_presentation_time); 190 // Following the update to |current_frame_|, this will check for changes that 191 // require updating video layer. 192 void CheckForFrameChanges( 193 bool is_first_frame, 194 bool has_frame_size_changed, 195 base::Optional<media::VideoRotation> new_frame_rotation, 196 base::Optional<bool> new_frame_opacity); 197 198 void StartRenderingInternal(); 199 void StopRenderingInternal(); 200 void StopUsingProviderInternal(); 201 void ReplaceCurrentFrameWithACopyInternal(); 202 203 void SetAlgorithmEnabledForTesting(bool algorithm_enabled); 204 205 // Used for DCHECKs to ensure method calls executed in the correct thread, 206 // which is renderer main thread in this class. 207 THREAD_CHECKER(thread_checker_); 208 209 const scoped_refptr<base::SingleThreadTaskRunner> 210 video_frame_compositor_task_runner_; 211 const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 212 const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; 213 214 base::WeakPtr<WebMediaPlayerMS> player_; 215 216 // TODO(qiangchen, emircan): It might be nice to use a real MediaLog here from 217 // the WebMediaPlayerMS instance, but it owns the MediaLog and this class has 218 // non-deterministic destruction paths (either compositor or IO). 219 media::NullMediaLog media_log_; 220 221 size_t serial_; 222 223 // A pointer back to the compositor to inform it about state changes. This 224 // is not |nullptr| while the compositor is actively using this 225 // VideoFrameProvider. This will be set to |nullptr| when the compositor stops 226 // serving this VideoFrameProvider. 227 cc::VideoFrameProvider::Client* video_frame_provider_client_; 228 229 // |current_frame_| is updated only on compositor thread. The object it 230 // holds can be freed on the compositor thread if it is the last to hold a 231 // reference but media::VideoFrame is a thread-safe ref-pointer. It is 232 // however read on the compositor and main thread so locking is required 233 // around all modifications and all reads on the any thread. 234 scoped_refptr<media::VideoFrame> current_frame_; 235 236 // |rendering_frame_buffer_| stores the incoming frames, and provides a frame 237 // selection method which returns the best frame for the render interval. 238 std::unique_ptr<VideoRendererAlgorithmWrapper> rendering_frame_buffer_; 239 240 // |current_frame_rendered_| is updated on compositor thread only. 241 // It's used to track whether |current_frame_| was painted for detecting 242 // when to increase |dropped_frame_count_|. It is also used when checking if 243 // new frame for display is available in UpdateCurrentFrame(). 244 bool current_frame_rendered_; 245 246 // Historical data about last rendering. These are for detecting whether 247 // rendering is paused (one reason is that the tab is not in the front), in 248 // which case we need to do background rendering. 249 base::TimeTicks last_deadline_max_; 250 base::TimeDelta last_render_length_; 251 252 size_t total_frame_count_; 253 size_t dropped_frame_count_; 254 255 bool current_frame_is_copy_ = false; 256 257 // Used to complete video.requestAnimationFrame() calls. Reported up via 258 // GetLastPresentedFrameMetadata(). 259 // TODO(https://crbug.com/1050755): Improve the accuracy of these fields for 260 // cases where we only use RenderWithoutAlgorithm(). 261 base::TimeTicks last_presentation_time_ GUARDED_BY(current_frame_lock_); 262 base::TimeTicks last_expected_display_time_ GUARDED_BY(current_frame_lock_); 263 size_t presented_frames_ GUARDED_BY(current_frame_lock_) = 0u; 264 265 // The value of GetPreferredRenderInterval() the last time |current_frame_| 266 // was updated. Used by GetLastPresentedFrameMetadata(), to prevent calling 267 // GetPreferredRenderInterval() from the main thread. 268 base::TimeDelta last_preferred_render_interval_ 269 GUARDED_BY(current_frame_lock_); 270 271 bool stopped_; 272 bool render_started_; 273 274 // Called when a new frame is enqueued, either in RenderWithoutAlgorithm() or 275 // in RenderUsingAlgorithm(). Used to fulfill video.requestAnimationFrame() 276 // requests. 277 base::Lock new_frame_presented_cb_lock_; 278 OnNewFramePresentedCB new_frame_presented_cb_; 279 280 std::unique_ptr<WebVideoFrameSubmitter> submitter_; 281 282 // Extra information about the frames pending in |rendering_frame_buffer_|. 283 WTF::Vector<PendingFrameInfo> pending_frames_info_; 284 285 cc::UpdateSubmissionStateCB update_submission_state_callback_; 286 287 // |current_frame_lock_| protects |current_frame_|, |rendering_frame_buffer_|, 288 // |dropped_frame_count_|, and |render_started_|. 289 base::Lock current_frame_lock_; 290 291 base::WeakPtrFactory<WebMediaPlayerMSCompositor> weak_ptr_factory_{this}; 292 293 DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerMSCompositor); 294 }; 295 296 struct WebMediaPlayerMSCompositorTraits { 297 // Ensure destruction occurs on main thread so that "Web" and other resources 298 // are destroyed on the correct thread. 299 static void Destruct(const WebMediaPlayerMSCompositor* player); 300 }; 301 302 } // namespace blink 303 304 #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_WEBMEDIAPLAYER_MS_COMPOSITOR_H_ 305