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 #ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ 6 #define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/threading/thread.h" 16 #include "content/renderer/media/buffered_data_source_host_impl.h" 17 #include "content/renderer/media/crypto/proxy_decryptor.h" 18 #include "content/renderer/media/video_frame_compositor.h" 19 #include "media/base/audio_renderer_sink.h" 20 #include "media/base/decryptor.h" 21 // TODO(xhwang): Remove when we remove prefixed EME implementation. 22 #include "media/base/media_keys.h" 23 #include "media/base/pipeline.h" 24 #include "media/base/text_track.h" 25 #include "media/filters/skcanvas_video_renderer.h" 26 #include "skia/ext/platform_canvas.h" 27 #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" 28 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 29 #include "third_party/WebKit/public/platform/WebMediaPlayer.h" 30 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" 31 #include "url/gurl.h" 32 33 class RenderAudioSourceProvider; 34 35 namespace blink { 36 class WebContentDecryptionModule; 37 class WebLocalFrame; 38 } 39 40 namespace base { 41 class MessageLoopProxy; 42 } 43 44 namespace media { 45 class ChunkDemuxer; 46 class GpuVideoAcceleratorFactories; 47 class MediaLog; 48 } 49 50 51 namespace content { 52 class BufferedDataSource; 53 class VideoFrameCompositor; 54 class WebAudioSourceProviderImpl; 55 class WebContentDecryptionModuleImpl; 56 class WebLayerImpl; 57 class WebMediaPlayerDelegate; 58 class WebMediaPlayerParams; 59 class WebTextTrackImpl; 60 61 // The canonical implementation of blink::WebMediaPlayer that's backed by 62 // media::Pipeline. Handles normal resource loading, Media Source, and 63 // Encrypted Media. 64 class WebMediaPlayerImpl 65 : public blink::WebMediaPlayer, 66 public base::SupportsWeakPtr<WebMediaPlayerImpl> { 67 public: 68 // Constructs a WebMediaPlayer implementation using Chromium's media stack. 69 // |delegate| may be null. 70 WebMediaPlayerImpl(blink::WebLocalFrame* frame, 71 blink::WebMediaPlayerClient* client, 72 base::WeakPtr<WebMediaPlayerDelegate> delegate, 73 const WebMediaPlayerParams& params); 74 virtual ~WebMediaPlayerImpl(); 75 76 virtual void load(LoadType load_type, 77 const blink::WebURL& url, 78 CORSMode cors_mode); 79 80 // Playback controls. 81 virtual void play(); 82 virtual void pause(); 83 virtual bool supportsSave() const; 84 virtual void seek(double seconds); 85 virtual void setRate(double rate); 86 virtual void setVolume(double volume); 87 virtual void setPreload(blink::WebMediaPlayer::Preload preload); 88 virtual blink::WebTimeRanges buffered() const; 89 virtual double maxTimeSeekable() const; 90 91 // Methods for painting. 92 virtual void paint(blink::WebCanvas* canvas, 93 const blink::WebRect& rect, 94 unsigned char alpha); 95 96 // True if the loaded media has a playable video/audio track. 97 virtual bool hasVideo() const; 98 virtual bool hasAudio() const; 99 100 // Dimensions of the video. 101 virtual blink::WebSize naturalSize() const; 102 103 // Getters of playback state. 104 virtual bool paused() const; 105 virtual bool seeking() const; 106 virtual double duration() const; 107 virtual double timelineOffset() const; 108 virtual double currentTime() const; 109 110 // Internal states of loading and network. 111 // TODO(hclam): Ask the pipeline about the state rather than having reading 112 // them from members which would cause race conditions. 113 virtual blink::WebMediaPlayer::NetworkState networkState() const; 114 virtual blink::WebMediaPlayer::ReadyState readyState() const; 115 116 virtual bool didLoadingProgress(); 117 118 virtual bool hasSingleSecurityOrigin() const; 119 virtual bool didPassCORSAccessCheck() const; 120 121 virtual double mediaTimeForTimeValue(double timeValue) const; 122 123 virtual unsigned decodedFrameCount() const; 124 virtual unsigned droppedFrameCount() const; 125 virtual unsigned audioDecodedByteCount() const; 126 virtual unsigned videoDecodedByteCount() const; 127 128 virtual bool copyVideoTextureToPlatformTexture( 129 blink::WebGraphicsContext3D* web_graphics_context, 130 unsigned int texture, 131 unsigned int level, 132 unsigned int internal_format, 133 unsigned int type, 134 bool premultiply_alpha, 135 bool flip_y); 136 137 virtual blink::WebAudioSourceProvider* audioSourceProvider(); 138 139 virtual MediaKeyException generateKeyRequest( 140 const blink::WebString& key_system, 141 const unsigned char* init_data, 142 unsigned init_data_length); 143 144 virtual MediaKeyException addKey(const blink::WebString& key_system, 145 const unsigned char* key, 146 unsigned key_length, 147 const unsigned char* init_data, 148 unsigned init_data_length, 149 const blink::WebString& session_id); 150 151 virtual MediaKeyException cancelKeyRequest( 152 const blink::WebString& key_system, 153 const blink::WebString& session_id); 154 155 virtual void setContentDecryptionModule( 156 blink::WebContentDecryptionModule* cdm); 157 158 // Notifies blink that the entire media element region has been invalidated. 159 // This path is slower than notifying the compositor directly as it performs 160 // more work and can trigger layouts. It should only be used in two cases: 161 // 1) Major state changes (e.g., first frame available, run time error 162 // occured) 163 // 2) Compositing not available 164 void InvalidateOnMainThread(); 165 166 void OnPipelineSeek(media::PipelineStatus status); 167 void OnPipelineEnded(); 168 void OnPipelineError(media::PipelineStatus error); 169 void OnPipelineMetadata(media::PipelineMetadata metadata); 170 void OnPipelinePrerollCompleted(); 171 void OnDemuxerOpened(); 172 void OnKeyAdded(const std::string& session_id); 173 void OnKeyError(const std::string& session_id, 174 media::MediaKeys::KeyError error_code, 175 uint32 system_code); 176 void OnKeyMessage(const std::string& session_id, 177 const std::vector<uint8>& message, 178 const GURL& destination_url); 179 void OnNeedKey(const std::string& type, 180 const std::vector<uint8>& init_data); 181 void OnAddTextTrack(const media::TextTrackConfig& config, 182 const media::AddTextTrackDoneCB& done_cb); 183 184 private: 185 // Called after |defer_load_cb_| has decided to allow the load. If 186 // |defer_load_cb_| is null this is called immediately. 187 void DoLoad(LoadType load_type, 188 const blink::WebURL& url, 189 CORSMode cors_mode); 190 191 // Called after asynchronous initialization of a data source completed. 192 void DataSourceInitialized(bool success); 193 194 // Called when the data source is downloading or paused. 195 void NotifyDownloading(bool is_downloading); 196 197 // Finishes starting the pipeline due to a call to load(). 198 void StartPipeline(); 199 200 // Helpers that set the network/ready state and notifies the client if 201 // they've changed. 202 void SetNetworkState(blink::WebMediaPlayer::NetworkState state); 203 void SetReadyState(blink::WebMediaPlayer::ReadyState state); 204 205 // Lets V8 know that player uses extra resources not managed by V8. 206 void IncrementExternallyAllocatedMemory(); 207 208 // Actually do the work for generateKeyRequest/addKey so they can easily 209 // report results to UMA. 210 MediaKeyException GenerateKeyRequestInternal(const std::string& key_system, 211 const unsigned char* init_data, 212 unsigned init_data_length); 213 MediaKeyException AddKeyInternal(const std::string& key_system, 214 const unsigned char* key, 215 unsigned key_length, 216 const unsigned char* init_data, 217 unsigned init_data_length, 218 const std::string& session_id); 219 MediaKeyException CancelKeyRequestInternal(const std::string& key_system, 220 const std::string& session_id); 221 222 // Gets the duration value reported by the pipeline. 223 double GetPipelineDuration() const; 224 225 // Callbacks from |pipeline_| that are forwarded to |client_|. 226 void OnDurationChanged(); 227 void OnNaturalSizeChanged(gfx::Size size); 228 void OnOpacityChanged(bool opaque); 229 230 // Called by VideoRendererImpl on its internal thread with the new frame to be 231 // painted. 232 void FrameReady(const scoped_refptr<media::VideoFrame>& frame); 233 234 // Requests that this object notifies when a decryptor is ready through the 235 // |decryptor_ready_cb| provided. 236 // If |decryptor_ready_cb| is null, the existing callback will be fired with 237 // NULL immediately and reset. 238 void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb); 239 240 // Returns the current video frame from |compositor_|. Blocks until the 241 // compositor can return the frame. 242 scoped_refptr<media::VideoFrame> GetCurrentFrameFromCompositor(); 243 244 blink::WebLocalFrame* frame_; 245 246 // TODO(hclam): get rid of these members and read from the pipeline directly. 247 blink::WebMediaPlayer::NetworkState network_state_; 248 blink::WebMediaPlayer::ReadyState ready_state_; 249 250 // Message loops for posting tasks on Chrome's main thread. Also used 251 // for DCHECKs so methods calls won't execute in the wrong thread. 252 const scoped_refptr<base::MessageLoopProxy> main_loop_; 253 254 scoped_refptr<base::MessageLoopProxy> media_loop_; 255 scoped_refptr<media::MediaLog> media_log_; 256 media::Pipeline pipeline_; 257 258 // The currently selected key system. Empty string means that no key system 259 // has been selected. 260 std::string current_key_system_; 261 262 // The LoadType passed in the |load_type| parameter of the load() call. 263 LoadType load_type_; 264 265 // Cache of metadata for answering hasAudio(), hasVideo(), and naturalSize(). 266 media::PipelineMetadata pipeline_metadata_; 267 268 // Whether the video is known to be opaque or not. 269 bool opaque_; 270 271 // Playback state. 272 // 273 // TODO(scherkus): we have these because Pipeline favours the simplicity of a 274 // single "playback rate" over worrying about paused/stopped etc... It forces 275 // all clients to manage the pause+playback rate externally, but is that 276 // really a bad thing? 277 // 278 // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want 279 // to hang the render thread during pause(), we record the time at the same 280 // time we pause and then return that value in currentTime(). Otherwise our 281 // clock can creep forward a little bit while the asynchronous 282 // SetPlaybackRate(0) is being executed. 283 bool paused_; 284 bool seeking_; 285 double playback_rate_; 286 base::TimeDelta paused_time_; 287 288 // Seek gets pending if another seek is in progress. Only last pending seek 289 // will have effect. 290 bool pending_seek_; 291 double pending_seek_seconds_; 292 293 blink::WebMediaPlayerClient* client_; 294 295 base::WeakPtr<WebMediaPlayerDelegate> delegate_; 296 297 base::Callback<void(const base::Closure&)> defer_load_cb_; 298 299 // Since accelerated compositing status is only known after the first layout, 300 // we delay reporting it to UMA until that time. 301 bool accelerated_compositing_reported_; 302 303 bool incremented_externally_allocated_memory_; 304 305 // Factories for supporting video accelerators. May be null. 306 scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_; 307 308 // Routes audio playback to either AudioRendererSink or WebAudio. 309 scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_; 310 311 bool supports_save_; 312 313 // These two are mutually exclusive: 314 // |data_source_| is used for regular resource loads. 315 // |chunk_demuxer_| is used for Media Source resource loads. 316 // 317 // |demuxer_| will contain the appropriate demuxer based on which resource 318 // load strategy we're using. 319 scoped_ptr<BufferedDataSource> data_source_; 320 scoped_ptr<media::Demuxer> demuxer_; 321 media::ChunkDemuxer* chunk_demuxer_; 322 323 BufferedDataSourceHostImpl buffered_data_source_host_; 324 325 // Temporary for EME v0.1. In the future the init data type should be passed 326 // through GenerateKeyRequest() directly from WebKit. 327 std::string init_data_type_; 328 329 // Video rendering members. 330 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; 331 VideoFrameCompositor* compositor_; // Deleted on |compositor_task_runner_|. 332 media::SkCanvasVideoRenderer skcanvas_video_renderer_; 333 334 // The compositor layer for displaying the video content when using composited 335 // playback. 336 scoped_ptr<WebLayerImpl> video_weblayer_; 337 338 // Text track objects get a unique index value when they're created. 339 int text_track_index_; 340 341 // Manages decryption keys and decrypts encrypted frames. 342 scoped_ptr<ProxyDecryptor> proxy_decryptor_; 343 344 // Non-owned pointer to the CDM. Updated via calls to 345 // setContentDecryptionModule(). 346 WebContentDecryptionModuleImpl* web_cdm_; 347 348 media::DecryptorReadyCB decryptor_ready_cb_; 349 350 DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); 351 }; 352 353 } // namespace content 354 355 #endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ 356