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.
12 // WebMediaPlayerImpl works with multiple objects, the most important ones are:
15 // The media playback pipeline.
18 // Video renderer object.
20 // WebKit::WebMediaPlayerClient
21 // WebKit client of this media player object.
23 // The following diagram shows the relationship of these objects:
24 // (note: ref-counted reference is marked by a "r".)
26 // WebMediaPlayerClient (WebKit object)
29 // WebMediaPlayerImpl ---> Pipeline
32 // | | VideoRendererBase
35 // '---> WebMediaPlayerProxy --'
37 // Notice that WebMediaPlayerProxy and VideoRendererBase are referencing each
38 // other. This interdependency has to be treated carefully.
41 // During tear down of the whole browser or a tab, the DOM tree may not be
42 // destructed nicely, and there will be some dangling media threads trying to
43 // the main thread, so we need this class to listen to destruction event of the
44 // main thread and cleanup the media threads when the even is received. Also
45 // at destruction of this class we will need to unhook it from destruction event
46 // list of the main thread.
48 #ifndef WEBKIT_MEDIA_WEBMEDIAPLAYER_IMPL_H_
49 #define WEBKIT_MEDIA_WEBMEDIAPLAYER_IMPL_H_
53 #include "base/memory/ref_counted.h"
54 #include "base/memory/scoped_ptr.h"
55 #include "base/memory/weak_ptr.h"
56 #include "base/message_loop.h"
57 #include "googleurl/src/gurl.h"
58 #include "media/base/audio_renderer_sink.h"
59 #include "media/base/decryptor.h"
60 #include "media/base/filters.h"
61 #include "media/base/message_loop_factory.h"
62 #include "media/base/pipeline.h"
63 #include "skia/ext/platform_canvas.h"
64 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAudioSourceProvider.h"
65 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayer.h"
66 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.h"
67 #include "webkit/media/crypto/key_systems.h"
68 #include "webkit/media/crypto/proxy_decryptor.h"
70 class RenderAudioSourceProvider
;
73 class WebAudioSourceProvider
;
78 class AudioRendererSink
;
82 namespace webkit_media
{
84 class MediaStreamClient
;
85 class WebMediaPlayerDelegate
;
86 class WebMediaPlayerProxy
;
88 class WebMediaPlayerImpl
89 : public WebKit::WebMediaPlayer
,
90 public MessageLoop::DestructionObserver
,
91 public base::SupportsWeakPtr
<WebMediaPlayerImpl
> {
93 // Construct a WebMediaPlayerImpl with reference to the client, and media
94 // filter collection. By providing the filter collection the implementor can
95 // provide more specific media filters that does resource loading and
98 // WebMediaPlayerImpl comes packaged with the following media filters:
101 // - Software audio/video decoding
104 // Clients are expected to add their platform-specific audio rendering media
105 // filter if they wish to hear any sound coming out the speakers, otherwise
106 // audio data is discarded and media plays back based on wall clock time.
108 // When calling this, the |audio_source_provider| and
109 // |audio_renderer_sink| arguments should be the same object.
111 // TODO(scherkus): Remove WebAudioSourceProvider parameter once we
112 // refactor RenderAudioSourceProvider to live under webkit/media/
113 // instead of content/renderer/, see http://crbug.com/136442
115 WebMediaPlayerImpl(WebKit::WebFrame
* frame
,
116 WebKit::WebMediaPlayerClient
* client
,
117 base::WeakPtr
<WebMediaPlayerDelegate
> delegate
,
118 media::FilterCollection
* collection
,
119 WebKit::WebAudioSourceProvider
* audio_source_provider
,
120 media::AudioRendererSink
* audio_renderer_sink
,
121 media::MessageLoopFactory
* message_loop_factory
,
122 MediaStreamClient
* media_stream_client
,
123 media::MediaLog
* media_log
);
124 virtual ~WebMediaPlayerImpl();
126 virtual void load(const WebKit::WebURL
& url
, CORSMode cors_mode
);
127 virtual void cancelLoad();
129 // Playback controls.
131 virtual void pause();
132 virtual bool supportsFullscreen() const;
133 virtual bool supportsSave() const;
134 virtual void seek(float seconds
);
135 virtual void setEndTime(float seconds
);
136 virtual void setRate(float rate
);
137 virtual void setVolume(float volume
);
138 virtual void setVisible(bool visible
);
139 virtual void setPreload(WebKit::WebMediaPlayer::Preload preload
);
140 virtual bool totalBytesKnown();
141 virtual const WebKit::WebTimeRanges
& buffered();
142 virtual float maxTimeSeekable() const;
144 // Methods for painting.
145 virtual void setSize(const WebKit::WebSize
& size
);
147 // This variant (without alpha) is just present during staging of this API
148 // change. Later we will again only have one virtual paint().
149 virtual void paint(WebKit::WebCanvas
* canvas
, const WebKit::WebRect
& rect
);
150 virtual void paint(WebKit::WebCanvas
* canvas
,
151 const WebKit::WebRect
& rect
,
154 // True if the loaded media has a playable video/audio track.
155 virtual bool hasVideo() const;
156 virtual bool hasAudio() const;
158 // Dimensions of the video.
159 virtual WebKit::WebSize
naturalSize() const;
161 // Getters of playback state.
162 virtual bool paused() const;
163 virtual bool seeking() const;
164 virtual float duration() const;
165 virtual float currentTime() const;
167 // Get rate of loading the resource.
168 virtual int32
dataRate() const;
170 // Internal states of loading and network.
171 // TODO(hclam): Ask the pipeline about the state rather than having reading
172 // them from members which would cause race conditions.
173 virtual WebKit::WebMediaPlayer::NetworkState
networkState() const;
174 virtual WebKit::WebMediaPlayer::ReadyState
readyState() const;
176 virtual bool didLoadingProgress() const;
177 virtual unsigned long long totalBytes() const;
179 virtual bool hasSingleSecurityOrigin() const;
180 virtual bool didPassCORSAccessCheck() const;
181 virtual WebKit::WebMediaPlayer::MovieLoadType
movieLoadType() const;
183 virtual float mediaTimeForTimeValue(float timeValue
) const;
185 virtual unsigned decodedFrameCount() const;
186 virtual unsigned droppedFrameCount() const;
187 virtual unsigned audioDecodedByteCount() const;
188 virtual unsigned videoDecodedByteCount() const;
190 virtual WebKit::WebVideoFrame
* getCurrentFrame();
191 virtual void putCurrentFrame(WebKit::WebVideoFrame
* web_video_frame
);
193 virtual WebKit::WebAudioSourceProvider
* audioSourceProvider();
195 // TODO(acolwell): Remove once new sourceAddId() signature is checked into
197 virtual AddIdStatus
sourceAddId(const WebKit::WebString
& id
,
198 const WebKit::WebString
& type
);
199 virtual AddIdStatus
sourceAddId(
200 const WebKit::WebString
& id
,
201 const WebKit::WebString
& type
,
202 const WebKit::WebVector
<WebKit::WebString
>& codecs
);
203 virtual bool sourceRemoveId(const WebKit::WebString
& id
);
204 virtual WebKit::WebTimeRanges
sourceBuffered(const WebKit::WebString
& id
);
205 // TODO(acolwell): Remove non-id version when http://webk.it/83788 fix lands.
206 virtual bool sourceAppend(const unsigned char* data
, unsigned length
);
207 virtual bool sourceAppend(const WebKit::WebString
& id
,
208 const unsigned char* data
,
210 virtual bool sourceAbort(const WebKit::WebString
& id
);
211 virtual void sourceEndOfStream(EndOfStreamStatus status
);
213 virtual MediaKeyException
generateKeyRequest(
214 const WebKit::WebString
& key_system
,
215 const unsigned char* init_data
,
216 unsigned init_data_length
);
218 virtual MediaKeyException
addKey(const WebKit::WebString
& key_system
,
219 const unsigned char* key
,
221 const unsigned char* init_data
,
222 unsigned init_data_length
,
223 const WebKit::WebString
& session_id
);
225 virtual MediaKeyException
cancelKeyRequest(
226 const WebKit::WebString
& key_system
,
227 const WebKit::WebString
& session_id
);
229 // As we are closing the tab or even the browser, |main_loop_| is destroyed
230 // even before this object gets destructed, so we need to know when
231 // |main_loop_| is being destroyed and we can stop posting repaint task
233 virtual void WillDestroyCurrentMessageLoop() OVERRIDE
;
237 void OnPipelineInitialize(media::PipelineStatus status
);
238 void OnPipelineSeek(media::PipelineStatus status
);
239 void OnPipelineEnded(media::PipelineStatus status
);
240 void OnPipelineError(media::PipelineStatus error
);
241 void OnDemuxerOpened();
242 void OnKeyAdded(const std::string
& key_system
, const std::string
& session_id
);
243 void OnKeyError(const std::string
& key_system
,
244 const std::string
& session_id
,
245 media::Decryptor::KeyError error_code
,
247 void OnKeyMessage(const std::string
& key_system
,
248 const std::string
& session_id
,
249 scoped_array
<uint8
> message
,
251 const std::string
& default_url
);
252 void OnNeedKey(const std::string
& key_system
,
253 const std::string
& session_id
,
254 scoped_array
<uint8
> init_data
,
256 void SetOpaque(bool);
259 // Called after asynchronous initialization of a data source completed.
260 void DataSourceInitialized(const GURL
& gurl
, media::PipelineStatus status
);
262 // Called when the data source is downloading or paused.
263 void NotifyDownloading(bool is_downloading
);
265 // Finishes starting the pipeline due to a call to load().
266 void StartPipeline();
268 // Helpers that set the network/ready state and notifies the client if
270 void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state
);
271 void SetReadyState(WebKit::WebMediaPlayer::ReadyState state
);
273 // Destroy resources held.
276 // Getter method to |client_|.
277 WebKit::WebMediaPlayerClient
* GetClient();
279 // Lets V8 know that player uses extra resources not managed by V8.
280 void IncrementExternallyAllocatedMemory();
282 WebKit::WebFrame
* frame_
;
284 // TODO(hclam): get rid of these members and read from the pipeline directly.
285 WebKit::WebMediaPlayer::NetworkState network_state_
;
286 WebKit::WebMediaPlayer::ReadyState ready_state_
;
288 // Keep a list of buffered time ranges.
289 WebKit::WebTimeRanges buffered_
;
291 // Message loops for posting tasks between Chrome's main thread. Also used
292 // for DCHECKs so methods calls won't execute in the wrong thread.
293 MessageLoop
* main_loop_
;
295 // A collection of filters.
296 scoped_ptr
<media::FilterCollection
> filter_collection_
;
298 // The media pipeline and a bool tracking whether we have started it yet.
300 // TODO(scherkus): replace |started_| with a pointer check for |pipeline_| and
301 // have WebMediaPlayerImpl return the default values to WebKit instead of
302 // relying on Pipeline to take care of default values.
303 scoped_refptr
<media::Pipeline
> pipeline_
;
306 // The currently selected key system. Empty string means that no key system
307 // has been selected.
308 WebKit::WebString current_key_system_
;
310 scoped_ptr
<media::MessageLoopFactory
> message_loop_factory_
;
314 // TODO(scherkus): we have these because Pipeline favours the simplicity of a
315 // single "playback rate" over worrying about paused/stopped etc... It forces
316 // all clients to manage the pause+playback rate externally, but is that
317 // really a bad thing?
319 // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want
320 // to hang the render thread during pause(), we record the time at the same
321 // time we pause and then return that value in currentTime(). Otherwise our
322 // clock can creep forward a little bit while the asynchronous
323 // SetPlaybackRate(0) is being executed.
326 float playback_rate_
;
327 base::TimeDelta paused_time_
;
329 // Seek gets pending if another seek is in progress. Only last pending seek
332 float pending_seek_seconds_
;
334 WebKit::WebMediaPlayerClient
* client_
;
336 scoped_refptr
<WebMediaPlayerProxy
> proxy_
;
338 base::WeakPtr
<WebMediaPlayerDelegate
> delegate_
;
340 MediaStreamClient
* media_stream_client_
;
342 scoped_refptr
<media::MediaLog
> media_log_
;
344 // Since accelerated compositing status is only known after the first layout,
345 // we delay reporting it to UMA until that time.
346 bool accelerated_compositing_reported_
;
348 bool incremented_externally_allocated_memory_
;
350 WebKit::WebAudioSourceProvider
* audio_source_provider_
;
352 scoped_refptr
<media::AudioRendererSink
> audio_renderer_sink_
;
354 bool is_local_source_
;
356 // The decryptor that manages decryption keys and decrypts encrypted frames.
357 ProxyDecryptor decryptor_
;
359 DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl
);
362 } // namespace webkit_media
364 #endif // WEBKIT_MEDIA_WEBMEDIAPLAYER_IMPL_H_