1 // Copyright 2013 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 // Delegate calls from WebCore::MediaPlayerPrivate to Chrome's video player. 6 // It contains Pipeline which is the actual media player pipeline, it glues 7 // the media player pipeline, data source, audio renderer and renderer. 8 // Pipeline would creates multiple threads and access some public methods 9 // of this class, so we need to be extra careful about concurrent access of 10 // methods and members. 11 // 12 // Other issues: 13 // During tear down of the whole browser or a tab, the DOM tree may not be 14 // destructed nicely, and there will be some dangling media threads trying to 15 // the main thread, so we need this class to listen to destruction event of the 16 // main thread and cleanup the media threads when the even is received. Also 17 // at destruction of this class we will need to unhook it from destruction event 18 // list of the main thread. 19 20 #ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ 21 #define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ 22 23 #include <string> 24 #include <vector> 25 26 #include "base/basictypes.h" 27 #include "base/memory/ref_counted.h" 28 #include "base/memory/scoped_ptr.h" 29 #include "base/memory/weak_ptr.h" 30 #include "base/threading/thread.h" 31 #include "cc/layers/video_frame_provider.h" 32 #include "content/public/renderer/render_view_observer.h" 33 #include "content/renderer/media/crypto/proxy_decryptor.h" 34 #include "media/base/audio_renderer_sink.h" 35 #include "media/base/decryptor.h" 36 #include "media/base/media_keys.h" 37 #include "media/base/pipeline.h" 38 #include "media/base/text_track.h" 39 #include "media/filters/skcanvas_video_renderer.h" 40 #include "skia/ext/platform_canvas.h" 41 #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" 42 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 43 #include "third_party/WebKit/public/platform/WebMediaPlayer.h" 44 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" 45 #include "url/gurl.h" 46 47 class RenderAudioSourceProvider; 48 49 namespace blink { 50 class WebFrame; 51 } 52 53 namespace base { 54 class MessageLoopProxy; 55 } 56 57 namespace media { 58 class ChunkDemuxer; 59 class GpuVideoAcceleratorFactories; 60 class MediaLog; 61 } 62 63 namespace webkit { 64 class WebLayerImpl; 65 } 66 67 namespace content { 68 class BufferedDataSource; 69 class WebAudioSourceProviderImpl; 70 class WebMediaPlayerDelegate; 71 class WebMediaPlayerParams; 72 class WebTextTrackImpl; 73 74 class WebMediaPlayerImpl 75 : public blink::WebMediaPlayer, 76 public cc::VideoFrameProvider, 77 public content::RenderViewObserver, 78 public base::SupportsWeakPtr<WebMediaPlayerImpl> { 79 public: 80 // Constructs a WebMediaPlayer implementation using Chromium's media stack. 81 // |render_view| is passed only for the purpose of registering |this| as an 82 // observer of it. 83 // |delegate| may be null. 84 WebMediaPlayerImpl( 85 content::RenderView* render_view, 86 blink::WebFrame* frame, 87 blink::WebMediaPlayerClient* client, 88 base::WeakPtr<WebMediaPlayerDelegate> delegate, 89 const WebMediaPlayerParams& params); 90 virtual ~WebMediaPlayerImpl(); 91 92 virtual void load(LoadType load_type, 93 const blink::WebURL& url, 94 CORSMode cors_mode) OVERRIDE; 95 96 // Playback controls. 97 virtual void play(); 98 virtual void pause(); 99 virtual bool supportsFullscreen() const; 100 virtual bool supportsSave() const; 101 virtual void seek(double seconds); 102 virtual void setRate(double rate); 103 virtual void setVolume(double volume); 104 virtual void setPreload(blink::WebMediaPlayer::Preload preload); 105 virtual const blink::WebTimeRanges& buffered(); 106 virtual double maxTimeSeekable() const; 107 108 // Methods for painting. 109 virtual void paint(blink::WebCanvas* canvas, 110 const blink::WebRect& rect, 111 unsigned char alpha); 112 113 // True if the loaded media has a playable video/audio track. 114 virtual bool hasVideo() const; 115 virtual bool hasAudio() const; 116 117 // Dimensions of the video. 118 virtual blink::WebSize naturalSize() const; 119 120 // Getters of playback state. 121 virtual bool paused() const; 122 virtual bool seeking() const; 123 virtual double duration() const; 124 virtual double currentTime() const; 125 126 // Internal states of loading and network. 127 // TODO(hclam): Ask the pipeline about the state rather than having reading 128 // them from members which would cause race conditions. 129 virtual blink::WebMediaPlayer::NetworkState networkState() const; 130 virtual blink::WebMediaPlayer::ReadyState readyState() const; 131 132 virtual bool didLoadingProgress() const; 133 134 virtual bool hasSingleSecurityOrigin() const; 135 virtual bool didPassCORSAccessCheck() const; 136 137 virtual double mediaTimeForTimeValue(double timeValue) const; 138 139 virtual unsigned decodedFrameCount() const; 140 virtual unsigned droppedFrameCount() const; 141 virtual unsigned audioDecodedByteCount() const; 142 virtual unsigned videoDecodedByteCount() const; 143 144 // cc::VideoFrameProvider implementation. 145 virtual void SetVideoFrameProviderClient( 146 cc::VideoFrameProvider::Client* client) OVERRIDE; 147 virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE; 148 virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame) 149 OVERRIDE; 150 151 virtual bool copyVideoTextureToPlatformTexture( 152 blink::WebGraphicsContext3D* web_graphics_context, 153 unsigned int texture, 154 unsigned int level, 155 unsigned int internal_format, 156 unsigned int type, 157 bool premultiply_alpha, 158 bool flip_y); 159 160 virtual blink::WebAudioSourceProvider* audioSourceProvider(); 161 162 virtual MediaKeyException generateKeyRequest( 163 const blink::WebString& key_system, 164 const unsigned char* init_data, 165 unsigned init_data_length); 166 167 virtual MediaKeyException addKey(const blink::WebString& key_system, 168 const unsigned char* key, 169 unsigned key_length, 170 const unsigned char* init_data, 171 unsigned init_data_length, 172 const blink::WebString& session_id); 173 174 virtual MediaKeyException cancelKeyRequest( 175 const blink::WebString& key_system, 176 const blink::WebString& session_id); 177 178 // content::RenderViewObserver implementation. 179 virtual void OnDestruct() OVERRIDE; 180 181 void Repaint(); 182 183 void OnPipelineSeek(media::PipelineStatus status); 184 void OnPipelineEnded(); 185 void OnPipelineError(media::PipelineStatus error); 186 void OnPipelineBufferingState( 187 media::Pipeline::BufferingState buffering_state); 188 void OnDemuxerOpened(); 189 void OnKeyAdded(const std::string& session_id); 190 void OnKeyError(const std::string& session_id, 191 media::MediaKeys::KeyError error_code, 192 int system_code); 193 void OnKeyMessage(const std::string& session_id, 194 const std::vector<uint8>& message, 195 const std::string& default_url); 196 void OnNeedKey(const std::string& type, 197 const std::vector<uint8>& init_data); 198 void OnAddTextTrack(const media::TextTrackConfig& config, 199 const media::AddTextTrackDoneCB& done_cb); 200 void SetOpaque(bool); 201 202 private: 203 // Called after |defer_load_cb_| has decided to allow the load. If 204 // |defer_load_cb_| is null this is called immediately. 205 void DoLoad(LoadType load_type, 206 const blink::WebURL& url, 207 CORSMode cors_mode); 208 209 // Called after asynchronous initialization of a data source completed. 210 void DataSourceInitialized(const GURL& gurl, bool success); 211 212 // Called when the data source is downloading or paused. 213 void NotifyDownloading(bool is_downloading); 214 215 // Finishes starting the pipeline due to a call to load(). 216 void StartPipeline(); 217 218 // Helpers that set the network/ready state and notifies the client if 219 // they've changed. 220 void SetNetworkState(blink::WebMediaPlayer::NetworkState state); 221 void SetReadyState(blink::WebMediaPlayer::ReadyState state); 222 223 // Destroy resources held. 224 void Destroy(); 225 226 // Getter method to |client_|. 227 blink::WebMediaPlayerClient* GetClient(); 228 229 // Lets V8 know that player uses extra resources not managed by V8. 230 void IncrementExternallyAllocatedMemory(); 231 232 // Actually do the work for generateKeyRequest/addKey so they can easily 233 // report results to UMA. 234 MediaKeyException GenerateKeyRequestInternal( 235 const blink::WebString& key_system, 236 const unsigned char* init_data, 237 unsigned init_data_length); 238 MediaKeyException AddKeyInternal(const blink::WebString& key_system, 239 const unsigned char* key, 240 unsigned key_length, 241 const unsigned char* init_data, 242 unsigned init_data_length, 243 const blink::WebString& session_id); 244 MediaKeyException CancelKeyRequestInternal( 245 const blink::WebString& key_system, 246 const blink::WebString& session_id); 247 248 // Gets the duration value reported by the pipeline. 249 double GetPipelineDuration() const; 250 251 // Notifies WebKit of the duration change. 252 void OnDurationChange(); 253 254 // Called by VideoRendererImpl on its internal thread with the new frame to be 255 // painted. 256 void FrameReady(const scoped_refptr<media::VideoFrame>& frame); 257 258 // Called when a paint or a new frame arrives to indicate that we are 259 // no longer waiting for |current_frame_| to be painted. 260 // |painting_frame| is set to true if |current_frame_| is being painted. 261 // False indicates |current_frame_| is being replaced with a new frame. 262 void DoneWaitingForPaint(bool painting_frame); 263 264 blink::WebFrame* frame_; 265 266 // TODO(hclam): get rid of these members and read from the pipeline directly. 267 blink::WebMediaPlayer::NetworkState network_state_; 268 blink::WebMediaPlayer::ReadyState ready_state_; 269 270 // Keep a list of buffered time ranges. 271 blink::WebTimeRanges buffered_; 272 273 // Message loops for posting tasks on Chrome's main thread. Also used 274 // for DCHECKs so methods calls won't execute in the wrong thread. 275 const scoped_refptr<base::MessageLoopProxy> main_loop_; 276 277 scoped_ptr<media::Pipeline> pipeline_; 278 scoped_refptr<base::MessageLoopProxy> media_loop_; 279 280 // The currently selected key system. Empty string means that no key system 281 // has been selected. 282 blink::WebString current_key_system_; 283 284 // The LoadType passed in the |load_type| parameter of the load() call. 285 LoadType load_type_; 286 287 // Playback state. 288 // 289 // TODO(scherkus): we have these because Pipeline favours the simplicity of a 290 // single "playback rate" over worrying about paused/stopped etc... It forces 291 // all clients to manage the pause+playback rate externally, but is that 292 // really a bad thing? 293 // 294 // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want 295 // to hang the render thread during pause(), we record the time at the same 296 // time we pause and then return that value in currentTime(). Otherwise our 297 // clock can creep forward a little bit while the asynchronous 298 // SetPlaybackRate(0) is being executed. 299 bool paused_; 300 bool seeking_; 301 double playback_rate_; 302 base::TimeDelta paused_time_; 303 304 // Seek gets pending if another seek is in progress. Only last pending seek 305 // will have effect. 306 bool pending_seek_; 307 double pending_seek_seconds_; 308 309 blink::WebMediaPlayerClient* client_; 310 311 base::WeakPtr<WebMediaPlayerDelegate> delegate_; 312 313 base::Callback<void(const base::Closure&)> defer_load_cb_; 314 315 scoped_refptr<media::MediaLog> media_log_; 316 317 // Since accelerated compositing status is only known after the first layout, 318 // we delay reporting it to UMA until that time. 319 bool accelerated_compositing_reported_; 320 321 bool incremented_externally_allocated_memory_; 322 323 // Factories for supporting video accelerators. May be null. 324 scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_; 325 326 // Routes audio playback to either AudioRendererSink or WebAudio. 327 scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_; 328 329 bool is_local_source_; 330 bool supports_save_; 331 332 // The decryptor that manages decryption keys and decrypts encrypted frames. 333 scoped_ptr<ProxyDecryptor> decryptor_; 334 335 bool starting_; 336 337 // These two are mutually exclusive: 338 // |data_source_| is used for regular resource loads. 339 // |chunk_demuxer_| is used for Media Source resource loads. 340 // 341 // |demuxer_| will contain the appropriate demuxer based on which resource 342 // load strategy we're using. 343 scoped_ptr<BufferedDataSource> data_source_; 344 scoped_ptr<media::Demuxer> demuxer_; 345 media::ChunkDemuxer* chunk_demuxer_; 346 347 // Temporary for EME v0.1. In the future the init data type should be passed 348 // through GenerateKeyRequest() directly from WebKit. 349 std::string init_data_type_; 350 351 // Video frame rendering members. 352 // 353 // |lock_| protects |current_frame_|, |current_frame_painted_|, and 354 // |frames_dropped_before_paint_| since new frames arrive on the video 355 // rendering thread, yet are accessed for rendering on either the main thread 356 // or compositing thread depending on whether accelerated compositing is used. 357 mutable base::Lock lock_; 358 media::SkCanvasVideoRenderer skcanvas_video_renderer_; 359 scoped_refptr<media::VideoFrame> current_frame_; 360 bool current_frame_painted_; 361 uint32 frames_dropped_before_paint_; 362 bool pending_repaint_; 363 bool pending_size_change_; 364 365 // The compositor layer for displaying the video content when using composited 366 // playback. 367 scoped_ptr<webkit::WebLayerImpl> video_weblayer_; 368 369 // A pointer back to the compositor to inform it about state changes. This is 370 // not NULL while the compositor is actively using this webmediaplayer. 371 cc::VideoFrameProvider::Client* video_frame_provider_client_; 372 373 // Text track objects get a unique index value when they're created. 374 int text_track_index_; 375 376 DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); 377 }; 378 379 } // namespace content 380 381 #endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ 382