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