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/time/time.h"
17#include "cc/layers/video_frame_provider.h"
18#include "content/common/media/media_player_messages_enums_android.h"
19#include "content/public/renderer/render_frame_observer.h"
20#include "content/renderer/media/android/media_info_loader.h"
21#include "content/renderer/media/android/media_source_delegate.h"
22#include "content/renderer/media/android/stream_texture_factory.h"
23#include "content/renderer/media/crypto/proxy_decryptor.h"
24#include "gpu/command_buffer/common/mailbox.h"
25#include "media/base/android/media_player_android.h"
26#include "media/base/demuxer_stream.h"
27#include "media/base/media_keys.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/WebSize.h"
31#include "third_party/WebKit/public/platform/WebURL.h"
32#include "ui/gfx/rect_f.h"
33
34namespace base {
35class MessageLoopProxy;
36}
37
38namespace blink {
39class WebContentDecryptionModule;
40class WebFrame;
41class WebURL;
42}
43
44namespace gpu {
45struct MailboxHolder;
46}
47
48namespace media {
49class MediaLog;
50}
51
52namespace content {
53class RendererCdmManager;
54class RendererMediaPlayerManager;
55class WebContentDecryptionModuleImpl;
56class WebLayerImpl;
57class WebMediaPlayerDelegate;
58
59// This class implements blink::WebMediaPlayer by keeping the android
60// media player in the browser process. It listens to all the status changes
61// sent from the browser process and sends playback controls to the media
62// player.
63class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
64                              public cc::VideoFrameProvider,
65                              public RenderFrameObserver,
66                              public StreamTextureFactoryContextObserver {
67 public:
68  // Construct a WebMediaPlayerAndroid object. This class communicates with the
69  // MediaPlayerAndroid object in the browser process through |proxy|.
70  // TODO(qinmin): |frame| argument is used to determine whether the current
71  // player can enter fullscreen. This logic should probably be moved into
72  // blink, so that enterFullscreen() will not be called if another video is
73  // already in fullscreen.
74  WebMediaPlayerAndroid(blink::WebFrame* frame,
75                        blink::WebMediaPlayerClient* client,
76                        base::WeakPtr<WebMediaPlayerDelegate> delegate,
77                        RendererMediaPlayerManager* player_manager,
78                        RendererCdmManager* cdm_manager,
79                        scoped_refptr<StreamTextureFactory> factory,
80                        const scoped_refptr<base::MessageLoopProxy>& media_loop,
81                        media::MediaLog* media_log);
82  virtual ~WebMediaPlayerAndroid();
83
84  // blink::WebMediaPlayer implementation.
85  virtual void enterFullscreen();
86  virtual void exitFullscreen();
87  virtual bool canEnterFullscreen() const;
88
89  // Resource loading.
90  virtual void load(LoadType load_type,
91                    const blink::WebURL& url,
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 supportsSave() const;
99  virtual void setRate(double rate);
100  virtual void setVolume(double volume);
101  virtual blink::WebTimeRanges buffered() const;
102  virtual double maxTimeSeekable() const;
103
104  // Poster image, as defined in the <video> element.
105  virtual void setPoster(const blink::WebURL& poster) OVERRIDE;
106
107  // Methods for painting.
108  virtual void paint(blink::WebCanvas* canvas,
109                     const blink::WebRect& rect,
110                     unsigned char alpha);
111
112  virtual bool copyVideoTextureToPlatformTexture(
113      blink::WebGraphicsContext3D* web_graphics_context,
114      unsigned int texture,
115      unsigned int level,
116      unsigned int internal_format,
117      unsigned int type,
118      bool premultiply_alpha,
119      bool flip_y);
120
121  // True if the loaded media has a playable video/audio track.
122  virtual bool hasVideo() const;
123  virtual bool hasAudio() const;
124
125  // Dimensions of the video.
126  virtual blink::WebSize naturalSize() const;
127
128  // Getters of playback state.
129  virtual bool paused() const;
130  virtual bool seeking() const;
131  virtual double duration() const;
132  virtual double timelineOffset() const;
133  virtual double currentTime() const;
134
135  virtual bool didLoadingProgress();
136
137  // Internal states of loading and network.
138  virtual blink::WebMediaPlayer::NetworkState networkState() const;
139  virtual blink::WebMediaPlayer::ReadyState readyState() const;
140
141  virtual bool hasSingleSecurityOrigin() const;
142  virtual bool didPassCORSAccessCheck() const;
143
144  virtual double mediaTimeForTimeValue(double timeValue) const;
145
146  // Provide statistics.
147  virtual unsigned decodedFrameCount() const;
148  virtual unsigned droppedFrameCount() const;
149  virtual unsigned audioDecodedByteCount() const;
150  virtual unsigned videoDecodedByteCount() const;
151
152  // cc::VideoFrameProvider implementation. These methods are running on the
153  // compositor thread.
154  virtual void SetVideoFrameProviderClient(
155      cc::VideoFrameProvider::Client* client) OVERRIDE;
156  virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE;
157  virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
158      OVERRIDE;
159
160  // Media player callback handlers.
161  void OnMediaMetadataChanged(const base::TimeDelta& duration, int width,
162                              int height, bool success);
163  void OnPlaybackComplete();
164  void OnBufferingUpdate(int percentage);
165  void OnSeekRequest(const base::TimeDelta& time_to_seek);
166  void OnSeekComplete(const base::TimeDelta& current_time);
167  void OnMediaError(int error_type);
168  void OnVideoSizeChanged(int width, int height);
169  void OnDurationChanged(const base::TimeDelta& duration);
170
171  // Called to update the current time.
172  void OnTimeUpdate(const base::TimeDelta& current_time);
173
174  // Functions called when media player status changes.
175  void OnConnectedToRemoteDevice(const std::string& remote_playback_message);
176  void OnDisconnectedFromRemoteDevice();
177  void OnDidEnterFullscreen();
178  void OnDidExitFullscreen();
179  void OnMediaPlayerPlay();
180  void OnMediaPlayerPause();
181  void OnRequestFullscreen();
182
183  // StreamTextureFactoryContextObserver implementation.
184  virtual void ResetStreamTextureProxy() OVERRIDE;
185
186  // Called when the player is released.
187  virtual void OnPlayerReleased();
188
189  // This function is called by the RendererMediaPlayerManager to pause the
190  // video and release the media player and surface texture when we switch tabs.
191  // However, the actual GlTexture is not released to keep the video screenshot.
192  virtual void ReleaseMediaResources();
193
194  // RenderFrameObserver implementation.
195  virtual void OnDestruct() OVERRIDE;
196
197#if defined(VIDEO_HOLE)
198  // Calculate the boundary rectangle of the media player (i.e. location and
199  // size of the video frame).
200  // Returns true if the geometry has been changed since the last call.
201  bool UpdateBoundaryRectangle();
202
203  const gfx::RectF GetBoundaryRectangle();
204#endif  // defined(VIDEO_HOLE)
205
206  virtual MediaKeyException generateKeyRequest(
207      const blink::WebString& key_system,
208      const unsigned char* init_data,
209      unsigned init_data_length);
210  virtual MediaKeyException addKey(
211      const blink::WebString& key_system,
212      const unsigned char* key,
213      unsigned key_length,
214      const unsigned char* init_data,
215      unsigned init_data_length,
216      const blink::WebString& session_id);
217  virtual MediaKeyException cancelKeyRequest(
218      const blink::WebString& key_system,
219      const blink::WebString& session_id);
220  virtual void setContentDecryptionModule(
221      blink::WebContentDecryptionModule* cdm);
222
223  void OnKeyAdded(const std::string& session_id);
224  void OnKeyError(const std::string& session_id,
225                  media::MediaKeys::KeyError error_code,
226                  uint32 system_code);
227  void OnKeyMessage(const std::string& session_id,
228                    const std::vector<uint8>& message,
229                    const GURL& destination_url);
230
231  void OnMediaSourceOpened(blink::WebMediaSource* web_media_source);
232
233  void OnNeedKey(const std::string& type,
234                 const std::vector<uint8>& init_data);
235
236  // TODO(xhwang): Implement WebMediaPlayer::setContentDecryptionModule().
237  // See: http://crbug.com/224786
238
239 protected:
240  // Helper method to update the playing state.
241  void UpdatePlayingState(bool is_playing_);
242
243  // Helper methods for posting task for setting states and update WebKit.
244  void UpdateNetworkState(blink::WebMediaPlayer::NetworkState state);
245  void UpdateReadyState(blink::WebMediaPlayer::ReadyState state);
246  void TryCreateStreamTextureProxyIfNeeded();
247  void DoCreateStreamTexture();
248
249  // Helper method to reestablish the surface texture peer for android
250  // media player.
251  void EstablishSurfaceTexturePeer();
252
253  // Requesting whether the surface texture peer needs to be reestablished.
254  void SetNeedsEstablishPeer(bool needs_establish_peer);
255
256 private:
257  void InitializePlayer(const GURL& url,
258                        const GURL& first_party_for_cookies,
259                        bool allowed_stored_credentials,
260                        int demuxer_client_id);
261  void Pause(bool is_media_related_action);
262  void DrawRemotePlaybackText(const std::string& remote_playback_message);
263  void ReallocateVideoFrame();
264  void SetCurrentFrameInternal(scoped_refptr<media::VideoFrame>& frame);
265  void DidLoadMediaInfo(MediaInfoLoader::Status status,
266                        const GURL& redirected_url,
267                        const GURL& first_party_for_cookies,
268                        bool allow_stored_credentials);
269  bool IsKeySystemSupported(const std::string& key_system);
270
271  // Actually do the work for generateKeyRequest/addKey so they can easily
272  // report results to UMA.
273  MediaKeyException GenerateKeyRequestInternal(const std::string& key_system,
274                                               const unsigned char* init_data,
275                                               unsigned init_data_length);
276  MediaKeyException AddKeyInternal(const std::string& key_system,
277                                   const unsigned char* key,
278                                   unsigned key_length,
279                                   const unsigned char* init_data,
280                                   unsigned init_data_length,
281                                   const std::string& session_id);
282  MediaKeyException CancelKeyRequestInternal(const std::string& key_system,
283                                             const std::string& session_id);
284
285  // Requests that this object notifies when a decryptor is ready through the
286  // |decryptor_ready_cb| provided.
287  // If |decryptor_ready_cb| is null, the existing callback will be fired with
288  // NULL immediately and reset.
289  void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb);
290
291  blink::WebFrame* const frame_;
292
293  blink::WebMediaPlayerClient* const client_;
294
295  // |delegate_| is used to notify the browser process of the player status, so
296  // that the browser process can control screen locks.
297  // TODO(qinmin): Currently android mediaplayer takes care of the screen
298  // lock. So this is only used for media source. Will apply this to regular
299  // media tag once http://crbug.com/247892 is fixed.
300  base::WeakPtr<WebMediaPlayerDelegate> delegate_;
301
302  // Save the list of buffered time ranges.
303  blink::WebTimeRanges buffered_;
304
305  // Size of the video.
306  blink::WebSize natural_size_;
307
308  // Size that has been sent to StreamTexture.
309  blink::WebSize cached_stream_texture_size_;
310
311  // The video frame object used for rendering by the compositor.
312  scoped_refptr<media::VideoFrame> current_frame_;
313  base::Lock current_frame_lock_;
314
315  base::ThreadChecker main_thread_checker_;
316
317  // Message loop for media thread.
318  const scoped_refptr<base::MessageLoopProxy> media_loop_;
319
320  // URL of the media file to be fetched.
321  GURL url_;
322
323  // Media duration.
324  base::TimeDelta duration_;
325
326  // Flag to remember if we have a trusted duration_ value provided by
327  // MediaSourceDelegate notifying OnDurationChanged(). In this case, ignore
328  // any subsequent duration value passed to OnMediaMetadataChange().
329  bool ignore_metadata_duration_change_;
330
331  // Seek gets pending if another seek is in progress. Only last pending seek
332  // will have effect.
333  bool pending_seek_;
334  base::TimeDelta pending_seek_time_;
335
336  // Internal seek state.
337  bool seeking_;
338  base::TimeDelta seek_time_;
339
340  // Whether loading has progressed since the last call to didLoadingProgress.
341  bool did_loading_progress_;
342
343  // Manages this object and delegates player calls to the browser process.
344  // Owned by RenderFrameImpl.
345  RendererMediaPlayerManager* player_manager_;
346
347  // Delegates EME calls to the browser process. Owned by RenderFrameImpl.
348  // TODO(xhwang): Remove |cdm_manager_| when prefixed EME is deprecated. See
349  // http://crbug.com/249976
350  RendererCdmManager* cdm_manager_;
351
352  // Player ID assigned by the |player_manager_|.
353  int player_id_;
354
355  // Current player states.
356  blink::WebMediaPlayer::NetworkState network_state_;
357  blink::WebMediaPlayer::ReadyState ready_state_;
358
359  // GL texture ID allocated to the video.
360  unsigned int texture_id_;
361
362  // GL texture mailbox for texture_id_ to provide in the VideoFrame, and sync
363  // point for when the mailbox was produced.
364  gpu::Mailbox texture_mailbox_;
365
366  // Stream texture ID allocated to the video.
367  unsigned int stream_id_;
368
369  // Whether the mediaplayer is playing.
370  bool is_playing_;
371
372  // Whether media player needs to re-establish the surface texture peer.
373  bool needs_establish_peer_;
374
375  // Whether the video size info is available.
376  bool has_size_info_;
377
378  const scoped_refptr<base::MessageLoopProxy> compositor_loop_;
379
380  // Object for allocating stream textures.
381  scoped_refptr<StreamTextureFactory> stream_texture_factory_;
382
383  // Object for calling back the compositor thread to repaint the video when a
384  // frame available. It should be initialized on the compositor thread.
385  // Accessed on main thread and on compositor thread when main thread is
386  // blocked.
387  ScopedStreamTextureProxy stream_texture_proxy_;
388
389  // Whether media player needs external surface.
390  // Only used for the VIDEO_HOLE logic.
391  bool needs_external_surface_;
392
393  // A pointer back to the compositor to inform it about state changes. This is
394  // not NULL while the compositor is actively using this webmediaplayer.
395  // Accessed on main thread and on compositor thread when main thread is
396  // blocked.
397  cc::VideoFrameProvider::Client* video_frame_provider_client_;
398
399  scoped_ptr<WebLayerImpl> video_weblayer_;
400
401#if defined(VIDEO_HOLE)
402  // A rectangle represents the geometry of video frame, when computed last
403  // time.
404  gfx::RectF last_computed_rect_;
405
406  // Whether to use the video overlay for all embedded video.
407  // True only for testing.
408  bool force_use_overlay_embedded_video_;
409#endif  // defined(VIDEO_HOLE)
410
411  scoped_ptr<MediaSourceDelegate,
412             MediaSourceDelegate::Destroyer> media_source_delegate_;
413
414  // Internal pending playback state.
415  // Store a playback request that cannot be started immediately.
416  bool pending_playback_;
417
418  MediaPlayerHostMsg_Initialize_Type player_type_;
419
420  // The current playing time. Because the media player is in the browser
421  // process, it will regularly update the |current_time_| by calling
422  // OnTimeUpdate().
423  double current_time_;
424
425  // Whether the browser is currently connected to a remote media player.
426  bool is_remote_;
427
428  media::MediaLog* media_log_;
429
430  scoped_ptr<MediaInfoLoader> info_loader_;
431
432  // The currently selected key system. Empty string means that no key system
433  // has been selected.
434  std::string current_key_system_;
435
436  // Temporary for EME v0.1. In the future the init data type should be passed
437  // through GenerateKeyRequest() directly from WebKit.
438  std::string init_data_type_;
439
440  // Manages decryption keys and decrypts encrypted frames.
441  scoped_ptr<ProxyDecryptor> proxy_decryptor_;
442
443  // Non-owned pointer to the CDM. Updated via calls to
444  // setContentDecryptionModule().
445  WebContentDecryptionModuleImpl* web_cdm_;
446
447  // This is only Used by Clear Key key system implementation, where a renderer
448  // side CDM will be used. This is similar to WebMediaPlayerImpl. For other key
449  // systems, a browser side CDM will be used and we set CDM by calling
450  // player_manager_->SetCdm() directly.
451  media::DecryptorReadyCB decryptor_ready_cb_;
452
453  // Whether stored credentials are allowed to be passed to the server.
454  bool allow_stored_credentials_;
455
456  // NOTE: Weak pointers must be invalidated before all other member variables.
457  base::WeakPtrFactory<WebMediaPlayerAndroid> weak_factory_;
458
459  DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerAndroid);
460};
461
462}  // namespace content
463
464#endif  // CONTENT_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_ANDROID_H_
465