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