webmediaplayer_android.h revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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_ANDROID_WEBMEDIAPLAYER_ANDROID_H_
6#define CONTENT_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_ANDROID_H_
7
8#include <jni.h>
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/weak_ptr.h"
16#include "base/message_loop.h"
17#include "base/time/time.h"
18#include "cc/layers/video_frame_provider.h"
19#include "content/renderer/media/android/media_info_loader.h"
20#include "content/renderer/media/android/media_source_delegate.h"
21#include "content/renderer/media/android/stream_texture_factory_android.h"
22#include "content/renderer/media/crypto/proxy_decryptor.h"
23#include "gpu/command_buffer/common/mailbox.h"
24#include "media/base/android/media_player_android.h"
25#include "media/base/demuxer_stream.h"
26#include "media/base/media_keys.h"
27#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
28#include "third_party/WebKit/public/platform/WebSize.h"
29#include "third_party/WebKit/public/platform/WebURL.h"
30#include "third_party/WebKit/public/web/WebMediaPlayer.h"
31#include "ui/gfx/rect_f.h"
32
33namespace media {
34class Demuxer;
35class MediaLog;
36}
37
38namespace WebKit {
39class WebFrame;
40}
41
42namespace webkit {
43class WebLayerImpl;
44}
45
46namespace content {
47class WebMediaPlayerDelegate;
48class RendererMediaPlayerManager;
49class WebMediaPlayerProxyAndroid;
50
51#if defined(GOOGLE_TV)
52class MediaStreamAudioRenderer;
53class MediaStreamClient;
54#endif
55
56// This class implements WebKit::WebMediaPlayer by keeping the android
57// media player in the browser process. It listens to all the status changes
58// sent from the browser process and sends playback controls to the media
59// player.
60class WebMediaPlayerAndroid
61    : public WebKit::WebMediaPlayer,
62      public cc::VideoFrameProvider,
63      public base::MessageLoop::DestructionObserver,
64      public base::SupportsWeakPtr<WebMediaPlayerAndroid> {
65 public:
66  // Construct a WebMediaPlayerAndroid object. This class communicates
67  // with the MediaPlayerAndroid object in the browser process through
68  // |proxy|.
69  // TODO(qinmin): |frame| argument is used to determine whether the current
70  // player can enter fullscreen. This logic should probably be moved into
71  // blink, so that enterFullscreen() will not be called if another video is
72  // already in fullscreen.
73  WebMediaPlayerAndroid(
74      WebKit::WebFrame* frame,
75      WebKit::WebMediaPlayerClient* client,
76      base::WeakPtr<WebMediaPlayerDelegate> delegate,
77      RendererMediaPlayerManager* manager,
78      WebMediaPlayerProxyAndroid* proxy,
79      StreamTextureFactory* factory,
80      media::MediaLog* media_log);
81  virtual ~WebMediaPlayerAndroid();
82
83  // WebKit::WebMediaPlayer implementation.
84  virtual void enterFullscreen();
85  virtual void exitFullscreen();
86  virtual bool canEnterFullscreen() const;
87
88  // Resource loading.
89  virtual void load(const WebKit::WebURL& url, CORSMode cors_mode);
90  virtual void load(const WebKit::WebURL& url,
91                    WebKit::WebMediaSource* media_source,
92                    CORSMode cors_mode);
93
94  // Playback controls.
95  virtual void play();
96  virtual void pause();
97  virtual void seek(double seconds);
98  virtual bool supportsFullscreen() const;
99  virtual bool supportsSave() const;
100  virtual void setRate(double rate);
101  virtual void setVolume(double volume);
102  virtual const WebKit::WebTimeRanges& buffered();
103  virtual double maxTimeSeekable() const;
104
105  // Methods for painting.
106  virtual void paint(WebKit::WebCanvas* canvas,
107                     const WebKit::WebRect& rect,
108                     unsigned char alpha);
109
110  virtual bool copyVideoTextureToPlatformTexture(
111      WebKit::WebGraphicsContext3D* web_graphics_context,
112      unsigned int texture,
113      unsigned int level,
114      unsigned int internal_format,
115      unsigned int type,
116      bool premultiply_alpha,
117      bool flip_y);
118
119  // True if the loaded media has a playable video/audio track.
120  virtual bool hasVideo() const;
121  virtual bool hasAudio() const;
122
123  // Dimensions of the video.
124  virtual WebKit::WebSize naturalSize() const;
125
126  // Getters of playback state.
127  virtual bool paused() const;
128  virtual bool seeking() const;
129  virtual double duration() const;
130  virtual double currentTime() const;
131
132  virtual bool didLoadingProgress() const;
133
134  // Internal states of loading and network.
135  virtual WebKit::WebMediaPlayer::NetworkState networkState() const;
136  virtual WebKit::WebMediaPlayer::ReadyState readyState() const;
137
138  virtual bool hasSingleSecurityOrigin() const;
139  virtual bool didPassCORSAccessCheck() const;
140
141  virtual double mediaTimeForTimeValue(double timeValue) const;
142
143  // Provide statistics.
144  virtual unsigned decodedFrameCount() const;
145  virtual unsigned droppedFrameCount() const;
146  virtual unsigned audioDecodedByteCount() const;
147  virtual unsigned videoDecodedByteCount() const;
148
149  // cc::VideoFrameProvider implementation. These methods are running on the
150  // compositor thread.
151  virtual void SetVideoFrameProviderClient(
152      cc::VideoFrameProvider::Client* client) OVERRIDE;
153  virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE;
154  virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
155      OVERRIDE;
156
157  // Media player callback handlers.
158  void OnMediaMetadataChanged(base::TimeDelta duration, int width,
159                              int height, bool success);
160  void OnPlaybackComplete();
161  void OnBufferingUpdate(int percentage);
162  void OnSeekComplete(base::TimeDelta current_time);
163  void OnMediaError(int error_type);
164  void OnVideoSizeChanged(int width, int height);
165  void OnMediaSeekRequest(base::TimeDelta time_to_seek,
166                          unsigned seek_request_id);
167  void OnMediaConfigRequest();
168  void OnDurationChange(const base::TimeDelta& duration);
169
170  // Called to update the current time.
171  void OnTimeUpdate(base::TimeDelta current_time);
172
173  // Functions called when media player status changes.
174  void OnMediaPlayerPlay();
175  void OnMediaPlayerPause();
176  void OnDidEnterFullscreen();
177  void OnDidExitFullscreen();
178
179  // Called when the player is released.
180  virtual void OnPlayerReleased();
181
182  // This function is called by the RendererMediaPlayerManager to pause the
183  // video and release the media player and surface texture when we switch tabs.
184  // However, the actual GlTexture is not released to keep the video screenshot.
185  virtual void ReleaseMediaResources();
186
187  // Method inherited from DestructionObserver.
188  virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
189
190  // Detach the player from its manager.
191  void Detach();
192
193#if defined(GOOGLE_TV)
194  // Retrieve geometry of the media player (i.e. location and size of the video
195  // frame) if changed. Returns true only if the geometry has been changed since
196  // the last call.
197  bool RetrieveGeometryChange(gfx::RectF* rect);
198#endif
199
200  virtual MediaKeyException generateKeyRequest(
201      const WebKit::WebString& key_system,
202      const unsigned char* init_data,
203      unsigned init_data_length) OVERRIDE;
204  virtual MediaKeyException addKey(
205      const WebKit::WebString& key_system,
206      const unsigned char* key,
207      unsigned key_length,
208      const unsigned char* init_data,
209      unsigned init_data_length,
210      const WebKit::WebString& session_id) OVERRIDE;
211  virtual MediaKeyException cancelKeyRequest(
212      const WebKit::WebString& key_system,
213      const WebKit::WebString& session_id) OVERRIDE;
214
215  void OnKeyAdded(const std::string& session_id);
216  void OnKeyError(const std::string& session_id,
217                  media::MediaKeys::KeyError error_code,
218                  int system_code);
219  void OnKeyMessage(const std::string& session_id,
220                    const std::vector<uint8>& message,
221                    const std::string& destination_url);
222
223  void OnNeedKey(const std::string& type,
224                 const std::string& session_id,
225                 scoped_ptr<uint8[]> init_data,
226                 int init_data_size);
227
228#if defined(GOOGLE_TV)
229  bool InjectMediaStream(MediaStreamClient* media_stream_client,
230                         media::Demuxer* demuxer,
231                         const base::Closure& destroy_demuxer_cb);
232#endif
233
234  // Called when DemuxerStreamPlayer needs to read data from ChunkDemuxer.
235  void OnReadFromDemuxer(media::DemuxerStream::Type type);
236
237 protected:
238  // Helper method to update the playing state.
239  void UpdatePlayingState(bool is_playing_);
240
241  // Helper methods for posting task for setting states and update WebKit.
242  void UpdateNetworkState(WebKit::WebMediaPlayer::NetworkState state);
243  void UpdateReadyState(WebKit::WebMediaPlayer::ReadyState state);
244
245  // Helper method to reestablish the surface texture peer for android
246  // media player.
247  void EstablishSurfaceTexturePeer();
248
249  // Requesting whether the surface texture peer needs to be reestablished.
250  void SetNeedsEstablishPeer(bool needs_establish_peer);
251
252  void InitializeMediaPlayer(const WebKit::WebURL& url);
253
254#if defined(GOOGLE_TV)
255  // Request external surface for out-of-band composition.
256  void RequestExternalSurface();
257#endif
258
259 private:
260  void ReallocateVideoFrame();
261  void DidLoadMediaInfo(MediaInfoLoader::Status status);
262
263  // Actually do the work for generateKeyRequest/addKey so they can easily
264  // report results to UMA.
265  MediaKeyException GenerateKeyRequestInternal(
266      const WebKit::WebString& key_system,
267      const unsigned char* init_data,
268      unsigned init_data_length);
269  MediaKeyException AddKeyInternal(const WebKit::WebString& key_system,
270                                   const unsigned char* key,
271                                   unsigned key_length,
272                                   const unsigned char* init_data,
273                                   unsigned init_data_length,
274                                   const WebKit::WebString& session_id);
275  MediaKeyException CancelKeyRequestInternal(
276      const WebKit::WebString& key_system,
277      const WebKit::WebString& session_id);
278
279  WebKit::WebFrame* const frame_;
280
281  WebKit::WebMediaPlayerClient* const client_;
282
283  // |delegate_| is used to notify the browser process of the player status, so
284  // that the browser process can control screen locks.
285  // TODO(qinmin): Currently android mediaplayer takes care of the screen
286  // lock. So this is only used for media source. Will apply this to regular
287  // media tag once http://crbug.com/247892 is fixed.
288  base::WeakPtr<WebMediaPlayerDelegate> delegate_;
289
290  // Save the list of buffered time ranges.
291  WebKit::WebTimeRanges buffered_;
292
293  // Size of the video.
294  WebKit::WebSize natural_size_;
295
296  // Size that has been sent to StreamTexture.
297  WebKit::WebSize cached_stream_texture_size_;
298
299  // The video frame object used for rendering by the compositor.
300  scoped_refptr<media::VideoFrame> current_frame_;
301
302  // Message loop for main renderer thread.
303  const scoped_refptr<base::MessageLoopProxy> main_loop_;
304
305  // URL of the media file to be fetched.
306  GURL url_;
307
308  // Media duration.
309  base::TimeDelta duration_;
310
311  // Flag to remember if we have a trusted duration_ value provided by
312  // MediaSourceDelegate notifying OnDurationChange(). In this case, ignore
313  // any subsequent duration value passed to OnMediaMetadataChange().
314  bool ignore_metadata_duration_change_;
315
316  // The time android media player is trying to seek.
317  double pending_seek_;
318
319  // Internal seek state.
320  bool seeking_;
321
322  // Whether loading has progressed since the last call to didLoadingProgress.
323  mutable bool did_loading_progress_;
324
325  // Manager for managing this object.
326  RendererMediaPlayerManager* manager_;
327
328  // Player ID assigned by the |manager_|.
329  int player_id_;
330
331  // Current player states.
332  WebKit::WebMediaPlayer::NetworkState network_state_;
333  WebKit::WebMediaPlayer::ReadyState ready_state_;
334
335  // GL texture ID allocated to the video.
336  unsigned int texture_id_;
337
338  // GL texture mailbox for texture_id_ to provide in the VideoFrame, and sync
339  // point for when the mailbox was produced.
340  gpu::Mailbox texture_mailbox_;
341  unsigned int texture_mailbox_sync_point_;
342
343  // Stream texture ID allocated to the video.
344  unsigned int stream_id_;
345
346  // Whether the mediaplayer is playing.
347  bool is_playing_;
348
349  // Whether media player needs to re-establish the surface texture peer.
350  bool needs_establish_peer_;
351
352  // Whether |stream_texture_proxy_| is initialized.
353  bool stream_texture_proxy_initialized_;
354
355  // Whether the video size info is available.
356  bool has_size_info_;
357
358  // Whether the video metadata and info are available.
359  bool has_media_metadata_;
360  bool has_media_info_;
361
362  // Object for allocating stream textures.
363  scoped_ptr<StreamTextureFactory> stream_texture_factory_;
364
365  // Object for calling back the compositor thread to repaint the video when a
366  // frame available. It should be initialized on the compositor thread.
367  ScopedStreamTextureProxy stream_texture_proxy_;
368
369  // Whether media player needs external surface.
370  bool needs_external_surface_;
371
372  // A pointer back to the compositor to inform it about state changes. This is
373  // not NULL while the compositor is actively using this webmediaplayer.
374  cc::VideoFrameProvider::Client* video_frame_provider_client_;
375
376  scoped_ptr<webkit::WebLayerImpl> video_weblayer_;
377
378#if defined(GOOGLE_TV)
379  // Pixel threshold for external surface usage. Negative value means that the
380  // threshold is not defined, so that external surface is never used.
381  int external_surface_threshold_;
382
383  // A rectangle represents the geometry of video frame, when computed last
384  // time.
385  gfx::RectF last_computed_rect_;
386
387  // Media Stream related fields.
388  media::Demuxer* demuxer_;
389  base::Closure destroy_demuxer_cb_;
390  scoped_refptr<MediaStreamAudioRenderer> audio_renderer_;
391  MediaStreamClient* media_stream_client_;
392#endif
393
394  scoped_ptr<MediaSourceDelegate,
395             MediaSourceDelegate::Destroyer> media_source_delegate_;
396
397  media::MediaPlayerAndroid::SourceType source_type_;
398
399  // Proxy object that delegates method calls on Render Thread.
400  // This object is created on the Render Thread and is only called in the
401  // destructor.
402  WebMediaPlayerProxyAndroid* proxy_;
403
404  // The current playing time. Because the media player is in the browser
405  // process, it will regularly update the |current_time_| by calling
406  // OnTimeUpdate().
407  double current_time_;
408
409  media::MediaLog* media_log_;
410
411  scoped_ptr<MediaInfoLoader> info_loader_;
412
413  // The currently selected key system. Empty string means that no key system
414  // has been selected.
415  WebKit::WebString current_key_system_;
416
417  // Temporary for EME v0.1. In the future the init data type should be passed
418  // through GenerateKeyRequest() directly from WebKit.
419  std::string init_data_type_;
420
421  // The decryptor that manages decryption keys and decrypts encrypted frames.
422  scoped_ptr<ProxyDecryptor> decryptor_;
423
424  DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerAndroid);
425};
426
427}  // namespace content
428
429#endif  // CONTENT_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_ANDROID_H_
430