• 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 // 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 
47 class RenderAudioSourceProvider;
48 
49 namespace blink {
50 class WebFrame;
51 }
52 
53 namespace base {
54 class MessageLoopProxy;
55 }
56 
57 namespace media {
58 class ChunkDemuxer;
59 class GpuVideoAcceleratorFactories;
60 class MediaLog;
61 }
62 
63 namespace webkit {
64 class WebLayerImpl;
65 }
66 
67 namespace content {
68 class BufferedDataSource;
69 class WebAudioSourceProviderImpl;
70 class WebMediaPlayerDelegate;
71 class WebMediaPlayerParams;
72 class WebTextTrackImpl;
73 
74 class 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