Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2011 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 WEBKIT_GLUE_MEDIA_BUFFERED_DATA_SOURCE_H_
      6 #define WEBKIT_GLUE_MEDIA_BUFFERED_DATA_SOURCE_H_
      7 
      8 #include <string>
      9 
     10 #include "base/callback.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/synchronization/lock.h"
     13 #include "media/base/filter_factories.h"
     14 #include "media/base/filters.h"
     15 #include "webkit/glue/media/buffered_resource_loader.h"
     16 
     17 namespace webkit_glue {
     18 
     19 class BufferedDataSource : public WebDataSource {
     20  public:
     21   // Creates a DataSourceFactory for building BufferedDataSource objects.
     22   static media::DataSourceFactory* CreateFactory(
     23       MessageLoop* render_loop,
     24       WebKit::WebFrame* frame,
     25       WebDataSourceBuildObserverHack* build_observer);
     26 
     27   BufferedDataSource(MessageLoop* render_loop,
     28                      WebKit::WebFrame* frame);
     29 
     30   virtual ~BufferedDataSource();
     31 
     32   // media::Filter implementation.
     33   virtual void set_host(media::FilterHost* host);
     34   virtual void Stop(media::FilterCallback* callback);
     35   virtual void SetPlaybackRate(float playback_rate);
     36 
     37   // media::DataSource implementation.
     38   // Called from demuxer thread.
     39   virtual void Read(int64 position, size_t size,
     40                     uint8* data,
     41                     media::DataSource::ReadCallback* read_callback);
     42   virtual bool GetSize(int64* size_out);
     43   virtual bool IsStreaming();
     44   virtual void SetPreload(media::Preload preload);
     45 
     46   const media::MediaFormat& media_format() {
     47     return media_format_;
     48   }
     49 
     50   // webkit_glue::WebDataSource implementation.
     51   virtual void Initialize(const std::string& url,
     52                           media::PipelineStatusCallback* callback);
     53   virtual void CancelInitialize();
     54   virtual bool HasSingleOrigin();
     55   virtual void Abort();
     56 
     57  protected:
     58   // A factory method to create a BufferedResourceLoader based on the read
     59   // parameters. We can override this file to object a mock
     60   // BufferedResourceLoader for testing.
     61   virtual BufferedResourceLoader* CreateResourceLoader(
     62       int64 first_byte_position, int64 last_byte_position);
     63 
     64   // Gets the number of milliseconds to declare a request timeout since
     65   // the request was made. This method is made virtual so as to inject a
     66   // different number for testing purpose.
     67   virtual base::TimeDelta GetTimeoutMilliseconds();
     68 
     69  private:
     70   // Posted to perform initialization on render thread and start resource
     71   // loading.
     72   void InitializeTask();
     73 
     74   // Task posted to perform actual reading on the render thread.
     75   void ReadTask(int64 position, int read_size, uint8* read_buffer);
     76 
     77   // Task posted when Stop() is called. Stops |watch_dog_timer_| and
     78   // |loader_|, reset Read() variables, and set |stopped_on_render_loop_|
     79   // to signal any remaining tasks to stop.
     80   void CleanupTask();
     81 
     82   // Restart resource loading on render thread.
     83   void RestartLoadingTask();
     84 
     85   // This task monitors the current active read request. If the current read
     86   // request has timed out, this task will destroy the current loader and
     87   // creates a new one to accommodate the read request.
     88   void WatchDogTask();
     89 
     90   // This task uses the current playback rate with the previous playback rate
     91   // to determine whether we are going from pause to play and play to pause,
     92   // and signals the buffered resource loader accordingly.
     93   void SetPlaybackRateTask(float playback_rate);
     94 
     95   // This task saves the preload value for the media.
     96   void SetPreloadTask(media::Preload preload);
     97 
     98   // Decides which DeferStrategy to used based on the current state of the
     99   // BufferedDataSource.
    100   BufferedResourceLoader::DeferStrategy ChooseDeferStrategy();
    101 
    102   // The method that performs actual read. This method can only be executed on
    103   // the render thread.
    104   void ReadInternal();
    105 
    106   // Calls |read_callback_| and reset all read parameters.
    107   void DoneRead_Locked(int error);
    108 
    109   // Calls |initialize_callback_| and reset it.
    110   void DoneInitialization_Locked(media::PipelineStatus status);
    111 
    112   // Callback method for |loader_| if URL for the resource requested is using
    113   // HTTP protocol. This method is called when response for initial request is
    114   // received.
    115   void HttpInitialStartCallback(int error);
    116 
    117   // Callback method for |loader_| if URL for the resource requested is using
    118   // a non-HTTP protocol, e.g. local files. This method is called when response
    119   // for initial request is received.
    120   void NonHttpInitialStartCallback(int error);
    121 
    122   // Callback method to be passed to BufferedResourceLoader during range
    123   // request. Once a resource request has started, this method will be called
    124   // with the error code. This method will be executed on the thread
    125   // BufferedResourceLoader lives, i.e. render thread.
    126   void PartialReadStartCallback(int error);
    127 
    128   // Callback method for making a read request to BufferedResourceLoader.
    129   // If data arrives or the request has failed, this method is called with
    130   // the error code or the number of bytes read.
    131   void ReadCallback(int error);
    132 
    133   // Callback method when a network event is received.
    134   void NetworkEventCallback();
    135 
    136   void UpdateHostState();
    137 
    138   media::MediaFormat media_format_;
    139 
    140   // URL of the resource requested.
    141   GURL url_;
    142 
    143   // Members for total bytes of the requested object. It is written once on
    144   // render thread but may be read from any thread. However reading of this
    145   // member is guaranteed to happen after it is first written, so we don't
    146   // need to protect it.
    147   int64 total_bytes_;
    148   int64 buffered_bytes_;
    149 
    150   // True if this data source is considered loaded.
    151   bool loaded_;
    152 
    153   // This value will be true if this data source can only support streaming.
    154   // i.e. range request is not supported.
    155   bool streaming_;
    156 
    157   // A webframe for loading.
    158   WebKit::WebFrame* frame_;
    159 
    160   // A resource loader for the media resource.
    161   scoped_refptr<BufferedResourceLoader> loader_;
    162 
    163   // True if network is active.
    164   bool network_activity_;
    165 
    166   // Callback method from the pipeline for initialization.
    167   scoped_ptr<media::PipelineStatusCallback> initialize_callback_;
    168 
    169   // Read parameters received from the Read() method call.
    170   scoped_ptr<media::DataSource::ReadCallback> read_callback_;
    171   int64 read_position_;
    172   int read_size_;
    173   uint8* read_buffer_;
    174   base::Time read_submitted_time_;
    175   int read_attempts_;
    176 
    177   // This buffer is intermediate, we use it for BufferedResourceLoader to write
    178   // to. And when read in BufferedResourceLoader is done, we copy data from
    179   // this buffer to |read_buffer_|. The reason for an additional copy is that
    180   // we don't own |read_buffer_|. But since the read operation is asynchronous,
    181   // |read_buffer| can be destroyed at any time, so we only copy into
    182   // |read_buffer| in the final step when it is safe.
    183   // Memory is allocated for this member during initialization of this object
    184   // because we want buffer to be passed into BufferedResourceLoader to be
    185   // always non-null. And by initializing this member with a default size we can
    186   // avoid creating zero-sized buffered if the first read has zero size.
    187   scoped_array<uint8> intermediate_read_buffer_;
    188   int intermediate_read_buffer_size_;
    189 
    190   // The message loop of the render thread.
    191   MessageLoop* render_loop_;
    192 
    193   // Protects |stopped_|.
    194   base::Lock lock_;
    195 
    196   // Stop signal to suppressing activities. This variable is set on the pipeline
    197   // thread and read from the render thread.
    198   bool stop_signal_received_;
    199 
    200   // This variable is set by CleanupTask() that indicates this object is stopped
    201   // on the render thread and work should no longer progress.
    202   bool stopped_on_render_loop_;
    203 
    204   // This variable is true when we are in a paused state and false when we
    205   // are in a playing state.
    206   bool media_is_paused_;
    207 
    208   // This variable is true when the user has requested the video to play at
    209   // least once.
    210   bool media_has_played_;
    211 
    212   // This variable holds the value of the preload attribute for the video
    213   // element.
    214   media::Preload preload_;
    215 
    216   // This timer is to run the WatchDogTask repeatedly. We use a timer instead
    217   // of doing PostDelayedTask() reduce the extra reference held by the message
    218   // loop. The RepeatingTimer does PostDelayedTask() internally, by using it
    219   // the message loop doesn't hold a reference for the watch dog task.
    220   base::RepeatingTimer<BufferedDataSource> watch_dog_timer_;
    221 
    222   // Keeps track of whether we used a Range header in the initialization
    223   // request.
    224   bool using_range_request_;
    225 
    226   DISALLOW_COPY_AND_ASSIGN(BufferedDataSource);
    227 };
    228 
    229 }  // namespace webkit_glue
    230 
    231 #endif  // WEBKIT_GLUE_MEDIA_BUFFERED_DATA_SOURCE_H_
    232