1 // Copyright (c) 2012 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.
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.
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.
20 #ifndef WEBKIT_MEDIA_WEBMEDIAPLAYER_IMPL_H_
21 #define WEBKIT_MEDIA_WEBMEDIAPLAYER_IMPL_H_
25 #include "base/memory/ref_counted.h"
26 #include "base/memory/scoped_ptr.h"
27 #include "base/memory/weak_ptr.h"
28 #include "base/threading/thread.h"
29 #include "cc/layers/video_frame_provider.h"
30 #include "googleurl/src/gurl.h"
31 #include "media/base/audio_renderer_sink.h"
32 #include "media/base/decryptor.h"
33 #include "media/base/pipeline.h"
34 #include "media/filters/gpu_video_decoder.h"
35 #include "media/filters/skcanvas_video_renderer.h"
36 #include "skia/ext/platform_canvas.h"
37 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
38 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioSourceProvider.h"
39 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayer.h"
40 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.h"
41 #include "webkit/media/crypto/key_systems.h"
42 #include "webkit/media/crypto/proxy_decryptor.h"
44 class RenderAudioSourceProvider
;
51 class MessageLoopProxy
;
64 namespace webkit_media
{
66 class BufferedDataSource
;
67 class MediaStreamClient
;
68 class WebAudioSourceProviderImpl
;
69 class WebMediaPlayerDelegate
;
70 class WebMediaPlayerParams
;
72 class WebMediaPlayerImpl
73 : public WebKit::WebMediaPlayer
,
74 public cc::VideoFrameProvider
,
75 public base::MessageLoop::DestructionObserver
,
76 public base::SupportsWeakPtr
<WebMediaPlayerImpl
> {
78 // Constructs a WebMediaPlayer implementation using Chromium's media stack.
80 // |delegate| may be null.
82 WebKit::WebFrame
* frame
,
83 WebKit::WebMediaPlayerClient
* client
,
84 base::WeakPtr
<WebMediaPlayerDelegate
> delegate
,
85 const WebMediaPlayerParams
& params
);
86 virtual ~WebMediaPlayerImpl();
88 virtual void load(const WebKit::WebURL
& url
, CORSMode cors_mode
);
89 virtual void load(const WebKit::WebURL
& url
,
90 WebKit::WebMediaSource
* media_source
,
92 virtual void cancelLoad();
97 virtual bool supportsFullscreen() const;
98 virtual bool supportsSave() const;
99 virtual void seek(double seconds
);
100 virtual void setRate(double rate
);
101 virtual void setVolume(double volume
);
102 virtual void setVisible(bool visible
);
103 virtual void setPreload(WebKit::WebMediaPlayer::Preload preload
);
104 virtual bool totalBytesKnown();
105 virtual const WebKit::WebTimeRanges
& buffered();
106 virtual double maxTimeSeekable() const;
108 // Methods for painting.
109 virtual void setSize(const WebKit::WebSize
& size
);
111 virtual void paint(WebKit::WebCanvas
* canvas
,
112 const WebKit::WebRect
& rect
,
115 // True if the loaded media has a playable video/audio track.
116 virtual bool hasVideo() const;
117 virtual bool hasAudio() const;
119 // Dimensions of the video.
120 virtual WebKit::WebSize
naturalSize() const;
122 // Getters of playback state.
123 virtual bool paused() const;
124 virtual bool seeking() const;
125 virtual double duration() const;
126 virtual double currentTime() const;
128 // Get rate of loading the resource.
129 virtual int32
dataRate() const;
131 // Internal states of loading and network.
132 // TODO(hclam): Ask the pipeline about the state rather than having reading
133 // them from members which would cause race conditions.
134 virtual WebKit::WebMediaPlayer::NetworkState
networkState() const;
135 virtual WebKit::WebMediaPlayer::ReadyState
readyState() const;
137 virtual bool didLoadingProgress() const;
138 virtual unsigned long long totalBytes() const;
140 virtual bool hasSingleSecurityOrigin() const;
141 virtual bool didPassCORSAccessCheck() const;
142 virtual WebKit::WebMediaPlayer::MovieLoadType
movieLoadType() const;
144 virtual double mediaTimeForTimeValue(double timeValue
) const;
146 virtual unsigned decodedFrameCount() const;
147 virtual unsigned droppedFrameCount() const;
148 virtual unsigned audioDecodedByteCount() const;
149 virtual unsigned videoDecodedByteCount() const;
151 // cc::VideoFrameProvider implementation.
152 virtual void SetVideoFrameProviderClient(
153 cc::VideoFrameProvider::Client
* client
) OVERRIDE
;
154 virtual scoped_refptr
<media::VideoFrame
> GetCurrentFrame() OVERRIDE
;
155 virtual void PutCurrentFrame(const scoped_refptr
<media::VideoFrame
>& frame
)
158 virtual bool copyVideoTextureToPlatformTexture(
159 WebKit::WebGraphicsContext3D
* web_graphics_context
,
160 unsigned int texture
,
162 unsigned int internal_format
,
164 bool premultiply_alpha
,
167 virtual WebKit::WebAudioSourceProvider
* audioSourceProvider();
169 virtual MediaKeyException
generateKeyRequest(
170 const WebKit::WebString
& key_system
,
171 const unsigned char* init_data
,
172 unsigned init_data_length
);
174 virtual MediaKeyException
addKey(const WebKit::WebString
& key_system
,
175 const unsigned char* key
,
177 const unsigned char* init_data
,
178 unsigned init_data_length
,
179 const WebKit::WebString
& session_id
);
181 virtual MediaKeyException
cancelKeyRequest(
182 const WebKit::WebString
& key_system
,
183 const WebKit::WebString
& session_id
);
185 // As we are closing the tab or even the browser, |main_loop_| is destroyed
186 // even before this object gets destructed, so we need to know when
187 // |main_loop_| is being destroyed and we can stop posting repaint task
189 virtual void WillDestroyCurrentMessageLoop() OVERRIDE
;
193 void OnPipelineSeek(media::PipelineStatus status
);
194 void OnPipelineEnded();
195 void OnPipelineError(media::PipelineStatus error
);
196 void OnPipelineBufferingState(
197 media::Pipeline::BufferingState buffering_state
);
198 void OnDemuxerOpened(scoped_ptr
<WebKit::WebMediaSource
> media_source
);
199 void OnKeyAdded(const std::string
& key_system
, const std::string
& session_id
);
200 void OnKeyError(const std::string
& key_system
,
201 const std::string
& session_id
,
202 media::Decryptor::KeyError error_code
,
204 void OnKeyMessage(const std::string
& key_system
,
205 const std::string
& session_id
,
206 const std::string
& message
,
207 const std::string
& default_url
);
208 void OnNeedKey(const std::string
& key_system
,
209 const std::string
& type
,
210 const std::string
& session_id
,
211 scoped_ptr
<uint8
[]> init_data
,
213 void SetOpaque(bool);
216 // Contains common logic used across the different types loading.
217 void LoadSetup(const WebKit::WebURL
& url
);
219 // Called after asynchronous initialization of a data source completed.
220 void DataSourceInitialized(const GURL
& gurl
, bool success
);
222 // Called when the data source is downloading or paused.
223 void NotifyDownloading(bool is_downloading
);
225 // Finishes starting the pipeline due to a call to load().
227 // A non-null |media_source| will construct a Media Source pipeline.
228 void StartPipeline(WebKit::WebMediaSource
* media_source
);
230 // Helpers that set the network/ready state and notifies the client if
232 void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state
);
233 void SetReadyState(WebKit::WebMediaPlayer::ReadyState state
);
235 // Destroy resources held.
238 // Getter method to |client_|.
239 WebKit::WebMediaPlayerClient
* GetClient();
241 // Lets V8 know that player uses extra resources not managed by V8.
242 void IncrementExternallyAllocatedMemory();
244 // Actually do the work for generateKeyRequest/addKey so they can easily
245 // report results to UMA.
246 MediaKeyException
GenerateKeyRequestInternal(
247 const WebKit::WebString
& key_system
,
248 const unsigned char* init_data
,
249 unsigned init_data_length
);
250 MediaKeyException
AddKeyInternal(const WebKit::WebString
& key_system
,
251 const unsigned char* key
,
253 const unsigned char* init_data
,
254 unsigned init_data_length
,
255 const WebKit::WebString
& session_id
);
256 MediaKeyException
CancelKeyRequestInternal(
257 const WebKit::WebString
& key_system
,
258 const WebKit::WebString
& session_id
);
260 // Gets the duration value reported by the pipeline.
261 double GetPipelineDuration() const;
263 // Notifies WebKit of the duration change.
264 void OnDurationChange();
266 // Called by VideoRendererBase on its internal thread with the new frame to be
268 void FrameReady(const scoped_refptr
<media::VideoFrame
>& frame
);
270 WebKit::WebFrame
* frame_
;
272 // TODO(hclam): get rid of these members and read from the pipeline directly.
273 WebKit::WebMediaPlayer::NetworkState network_state_
;
274 WebKit::WebMediaPlayer::ReadyState ready_state_
;
276 // Keep a list of buffered time ranges.
277 WebKit::WebTimeRanges buffered_
;
279 // Message loops for posting tasks on Chrome's main thread. Also used
280 // for DCHECKs so methods calls won't execute in the wrong thread.
281 const scoped_refptr
<base::MessageLoopProxy
> main_loop_
;
283 scoped_ptr
<media::Pipeline
> pipeline_
;
284 base::Thread media_thread_
;
286 // The currently selected key system. Empty string means that no key system
287 // has been selected.
288 WebKit::WebString current_key_system_
;
292 // TODO(scherkus): we have these because Pipeline favours the simplicity of a
293 // single "playback rate" over worrying about paused/stopped etc... It forces
294 // all clients to manage the pause+playback rate externally, but is that
295 // really a bad thing?
297 // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want
298 // to hang the render thread during pause(), we record the time at the same
299 // time we pause and then return that value in currentTime(). Otherwise our
300 // clock can creep forward a little bit while the asynchronous
301 // SetPlaybackRate(0) is being executed.
304 double playback_rate_
;
305 base::TimeDelta paused_time_
;
307 // Seek gets pending if another seek is in progress. Only last pending seek
310 double pending_seek_seconds_
;
312 WebKit::WebMediaPlayerClient
* client_
;
314 base::WeakPtr
<WebMediaPlayerDelegate
> delegate_
;
316 MediaStreamClient
* media_stream_client_
;
318 scoped_refptr
<media::MediaLog
> media_log_
;
320 // Since accelerated compositing status is only known after the first layout,
321 // we delay reporting it to UMA until that time.
322 bool accelerated_compositing_reported_
;
324 bool incremented_externally_allocated_memory_
;
326 // Factories for supporting GpuVideoDecoder. May be null.
327 scoped_refptr
<media::GpuVideoDecoder::Factories
> gpu_factories_
;
329 // Routes audio playback to either AudioRendererSink or WebAudio.
330 scoped_refptr
<WebAudioSourceProviderImpl
> audio_source_provider_
;
332 bool is_local_source_
;
335 // The decryptor that manages decryption keys and decrypts encrypted frames.
336 scoped_ptr
<ProxyDecryptor
> decryptor_
;
340 // These two are mutually exclusive:
341 // |data_source_| is used for regular resource loads.
342 // |chunk_demuxer_| is used for Media Source resource loads.
344 // |demuxer_| will contain the appropriate demuxer based on which resource
345 // load strategy we're using.
346 scoped_ptr
<BufferedDataSource
> data_source_
;
347 scoped_ptr
<media::Demuxer
> demuxer_
;
348 media::ChunkDemuxer
* chunk_demuxer_
;
350 // Temporary for EME v0.1. In the future the init data type should be passed
351 // through GenerateKeyRequest() directly from WebKit.
352 std::string init_data_type_
;
354 // Video frame rendering members.
356 // |lock_| protects |current_frame_| since new frames arrive on the video
357 // rendering thread, yet are accessed for rendering on either the main thread
358 // or compositing thread depending on whether accelerated compositing is used.
360 media::SkCanvasVideoRenderer skcanvas_video_renderer_
;
361 scoped_refptr
<media::VideoFrame
> current_frame_
;
362 bool pending_repaint_
;
363 bool pending_size_change_
;
365 // The compositor layer for displaying the video content when using composited
367 scoped_ptr
<webkit::WebLayerImpl
> video_weblayer_
;
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_
;
373 DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl
);
376 } // namespace webkit_media
378 #endif // WEBKIT_MEDIA_WEBMEDIAPLAYER_IMPL_H_