• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
media_format()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