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