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