• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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