OLD | NEW |
| (Empty) |
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 MEDIA_BLINK_BUFFERED_DATA_SOURCE_H_ | |
6 #define MEDIA_BLINK_BUFFERED_DATA_SOURCE_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include <memory> | |
11 #include <string> | |
12 #include <vector> | |
13 | |
14 #include "base/callback.h" | |
15 #include "base/macros.h" | |
16 #include "base/memory/weak_ptr.h" | |
17 #include "base/synchronization/lock.h" | |
18 #include "media/base/data_source.h" | |
19 #include "media/base/ranges.h" | |
20 #include "media/blink/buffered_resource_loader.h" | |
21 #include "media/blink/media_blink_export.h" | |
22 #include "url/gurl.h" | |
23 | |
24 namespace base { | |
25 class SingleThreadTaskRunner; | |
26 } | |
27 | |
28 namespace media { | |
29 class MediaLog; | |
30 | |
31 class MEDIA_BLINK_EXPORT BufferedDataSourceHost { | |
32 public: | |
33 // Notify the host of the total size of the media file. | |
34 virtual void SetTotalBytes(int64_t total_bytes) = 0; | |
35 | |
36 // Notify the host that byte range [start,end] has been buffered. | |
37 // TODO(fischman): remove this method when demuxing is push-based instead of | |
38 // pull-based. http://crbug.com/131444 | |
39 virtual void AddBufferedByteRange(int64_t start, int64_t end) = 0; | |
40 | |
41 protected: | |
42 virtual ~BufferedDataSourceHost() {} | |
43 }; | |
44 | |
45 // This interface is temporary and will go away once MultibufferDataSource | |
46 // has been fully evaluated. | |
47 class BufferedDataSourceInterface : public DataSource { | |
48 public: | |
49 // Used to specify video preload states. They are "hints" to the browser about | |
50 // how aggressively the browser should load and buffer data. | |
51 // Please see the HTML5 spec for the descriptions of these values: | |
52 // http://www.w3.org/TR/html5/video.html#attr-media-preload | |
53 // | |
54 // Enum values must match the values in blink::WebMediaPlayer::Preload and | |
55 // there will be assertions at compile time if they do not match. | |
56 enum Preload { | |
57 NONE, | |
58 METADATA, | |
59 AUTO, | |
60 }; | |
61 | |
62 // Enum values must match the values in | |
63 // blink::WebMediaPlayer::BufferingStrategy and there will be assertions at | |
64 // compile time if they do not match. | |
65 enum BufferingStrategy { | |
66 BUFFERING_STRATEGY_NORMAL, | |
67 BUFFERING_STRATEGY_AGGRESSIVE, | |
68 }; | |
69 | |
70 // Executes |init_cb| with the result of initialization when it has completed. | |
71 // | |
72 // Method called on the render thread. | |
73 typedef base::Callback<void(bool)> InitializeCB; | |
74 virtual void Initialize(const InitializeCB& init_cb) = 0; | |
75 | |
76 // Adjusts the buffering algorithm based on the given preload value. | |
77 virtual void SetPreload(Preload preload) = 0; | |
78 | |
79 // Adjusts the buffering algorithm based on the given buffering strategy | |
80 // value. | |
81 virtual void SetBufferingStrategy(BufferingStrategy buffering_strategy) = 0; | |
82 | |
83 // Returns true if the media resource has a single origin, false otherwise. | |
84 // Only valid to call after Initialize() has completed. | |
85 // | |
86 // Method called on the render thread. | |
87 virtual bool HasSingleOrigin() = 0; | |
88 | |
89 // Returns true if the media resource passed a CORS access control check. | |
90 virtual bool DidPassCORSAccessCheck() const = 0; | |
91 | |
92 // Cancels initialization, any pending loaders, and any pending read calls | |
93 // from the demuxer. The caller is expected to release its reference to this | |
94 // object and never call it again. | |
95 // | |
96 // Method called on the render thread. | |
97 virtual void Abort() = 0; | |
98 | |
99 // Notifies changes in playback state for controlling media buffering | |
100 // behavior. | |
101 virtual void MediaPlaybackRateChanged(double playback_rate) = 0; | |
102 virtual void MediaIsPlaying() = 0; | |
103 virtual bool media_has_played() const = 0; | |
104 | |
105 // Returns true if the resource is local. | |
106 virtual bool assume_fully_buffered() = 0; | |
107 | |
108 // Cancels any open network connections once reaching the deferred state. If | |
109 // |always_cancel| is false this is done only for preload=metadata, non- | |
110 // streaming resources that have not started playback. If |always_cancel| is | |
111 // true, all resource types will have their connections canceled. If already | |
112 // deferred, connections will be immediately closed. | |
113 virtual void OnBufferingHaveEnough(bool always_cancel) = 0; | |
114 | |
115 // Returns an estimate of the number of bytes held by the data source. | |
116 virtual int64_t GetMemoryUsage() const = 0; | |
117 | |
118 // Returns the post-Initialize() URL after redirects have been followed; this | |
119 // value may change at a later time. | |
120 virtual GURL GetUrlAfterRedirects() const = 0; | |
121 }; | |
122 | |
123 // A data source capable of loading URLs and buffering the data using an | |
124 // in-memory sliding window. | |
125 // | |
126 // BufferedDataSource must be created and destroyed on the thread associated | |
127 // with the |task_runner| passed in the constructor. | |
128 class MEDIA_BLINK_EXPORT BufferedDataSource | |
129 : NON_EXPORTED_BASE(public BufferedDataSourceInterface) { | |
130 public: | |
131 // Number of cache misses or read failures we allow for a single Read() before | |
132 // signaling an error. | |
133 enum { kLoaderRetries = 30 }; | |
134 typedef base::Callback<void(bool)> DownloadingCB; | |
135 | |
136 // |url| and |cors_mode| are passed to the object. Buffered byte range changes | |
137 // will be reported to |host|. |downloading_cb| will be called whenever the | |
138 // downloading/paused state of the source changes. | |
139 BufferedDataSource( | |
140 const GURL& url, | |
141 BufferedResourceLoader::CORSMode cors_mode, | |
142 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | |
143 blink::WebFrame* frame, | |
144 MediaLog* media_log, | |
145 BufferedDataSourceHost* host, | |
146 const DownloadingCB& downloading_cb); | |
147 ~BufferedDataSource() override; | |
148 | |
149 // Executes |init_cb| with the result of initialization when it has completed. | |
150 // | |
151 // Method called on the render thread. | |
152 typedef base::Callback<void(bool)> InitializeCB; | |
153 void Initialize(const InitializeCB& init_cb) override; | |
154 | |
155 // Adjusts the buffering algorithm based on the given preload value. | |
156 void SetPreload(Preload preload) override; | |
157 | |
158 // Adjusts the buffering algorithm based on the given buffering strategy | |
159 // value. | |
160 void SetBufferingStrategy(BufferingStrategy buffering_strategy) override; | |
161 | |
162 // Returns true if the media resource has a single origin, false otherwise. | |
163 // Only valid to call after Initialize() has completed. | |
164 // | |
165 // Method called on the render thread. | |
166 bool HasSingleOrigin() override; | |
167 | |
168 // Returns true if the media resource passed a CORS access control check. | |
169 bool DidPassCORSAccessCheck() const override; | |
170 | |
171 // Cancels initialization, any pending loaders, and any pending read calls | |
172 // from the demuxer. The caller is expected to release its reference to this | |
173 // object and never call it again. | |
174 // | |
175 // Method called on the render thread. | |
176 void Abort() override; | |
177 | |
178 // Notifies changes in playback state for controlling media buffering | |
179 // behavior. | |
180 void MediaPlaybackRateChanged(double playback_rate) override; | |
181 void MediaIsPlaying() override; | |
182 bool media_has_played() const override; | |
183 | |
184 // Returns true if the resource is local. | |
185 bool assume_fully_buffered() override; | |
186 | |
187 // Cancels any open network connections once reaching the deferred state. If | |
188 // |always_cancel| is false this is done only for preload=metadata, non- | |
189 // streaming resources that have not started playback. If |always_cancel| is | |
190 // true, all resource types will have their connections canceled. If already | |
191 // deferred, connections will be immediately closed. | |
192 void OnBufferingHaveEnough(bool always_cancel) override; | |
193 | |
194 // Returns an estimate of the number of bytes held by the data source. | |
195 int64_t GetMemoryUsage() const override; | |
196 | |
197 GURL GetUrlAfterRedirects() const override; | |
198 | |
199 // DataSource implementation. | |
200 // Called from demuxer thread. | |
201 void Stop() override; | |
202 | |
203 void Read(int64_t position, | |
204 int size, | |
205 uint8_t* data, | |
206 const DataSource::ReadCB& read_cb) override; | |
207 bool GetSize(int64_t* size_out) override; | |
208 bool IsStreaming() override; | |
209 void SetBitrate(int bitrate) override; | |
210 | |
211 protected: | |
212 // A factory method to create a BufferedResourceLoader based on the read | |
213 // parameters. We can override this file to object a mock | |
214 // BufferedResourceLoader for testing. | |
215 virtual BufferedResourceLoader* CreateResourceLoader( | |
216 int64_t first_byte_position, | |
217 int64_t last_byte_position); | |
218 | |
219 private: | |
220 friend class BufferedDataSourceTest; | |
221 | |
222 // Task posted to perform actual reading on the render thread. | |
223 void ReadTask(); | |
224 | |
225 // Cancels oustanding callbacks and sets |stop_signal_received_|. Safe to call | |
226 // from any thread. | |
227 void StopInternal_Locked(); | |
228 | |
229 // Stops |loader_| if present. Used by Abort() and Stop(). | |
230 void StopLoader(); | |
231 | |
232 // Tells |loader_| the bitrate of the media. | |
233 void SetBitrateTask(int bitrate); | |
234 | |
235 // The method that performs actual read. This method can only be executed on | |
236 // the render thread. | |
237 void ReadInternal(); | |
238 | |
239 // BufferedResourceLoader::Start() callback for initial load. | |
240 void StartCallback(BufferedResourceLoader::Status status); | |
241 | |
242 // BufferedResourceLoader::Start() callback for subsequent loads (i.e., | |
243 // when accessing ranges that are outside initial buffered region). | |
244 void PartialReadStartCallback(BufferedResourceLoader::Status status); | |
245 | |
246 // Returns true if we can accept the new partial response. | |
247 bool CheckPartialResponseURL(const GURL& partial_response_original_url) const; | |
248 | |
249 // BufferedResourceLoader callbacks. | |
250 void ReadCallback(BufferedResourceLoader::Status status, int bytes_read); | |
251 void LoadingStateChangedCallback(BufferedResourceLoader::LoadingState state); | |
252 void ProgressCallback(int64_t position); | |
253 | |
254 // Update |loader_|'s deferring strategy. | |
255 void UpdateDeferStrategy(); | |
256 | |
257 // URL of the resource requested. | |
258 GURL url_; | |
259 // crossorigin attribute on the corresponding HTML media element, if any. | |
260 BufferedResourceLoader::CORSMode cors_mode_; | |
261 | |
262 // The total size of the resource. Set during StartCallback() if the size is | |
263 // known, otherwise it will remain kPositionNotSpecified until the size is | |
264 // determined by reaching EOF. | |
265 int64_t total_bytes_; | |
266 | |
267 // This value will be true if this data source can only support streaming. | |
268 // i.e. range request is not supported. | |
269 bool streaming_; | |
270 | |
271 // A webframe for loading. | |
272 blink::WebFrame* frame_; | |
273 | |
274 // A resource loader for the media resource. | |
275 std::unique_ptr<BufferedResourceLoader> loader_; | |
276 | |
277 // Callback method from the pipeline for initialization. | |
278 InitializeCB init_cb_; | |
279 | |
280 // Read parameters received from the Read() method call. Must be accessed | |
281 // under |lock_|. | |
282 class ReadOperation; | |
283 std::unique_ptr<ReadOperation> read_op_; | |
284 | |
285 // This buffer is intermediate, we use it for BufferedResourceLoader to write | |
286 // to. And when read in BufferedResourceLoader is done, we copy data from | |
287 // this buffer to |read_buffer_|. The reason for an additional copy is that | |
288 // we don't own |read_buffer_|. But since the read operation is asynchronous, | |
289 // |read_buffer| can be destroyed at any time, so we only copy into | |
290 // |read_buffer| in the final step when it is safe. | |
291 // Memory is allocated for this member during initialization of this object | |
292 // because we want buffer to be passed into BufferedResourceLoader to be | |
293 // always non-null. And by initializing this member with a default size we can | |
294 // avoid creating zero-sized buffered if the first read has zero size. | |
295 std::vector<uint8_t> intermediate_read_buffer_; | |
296 | |
297 // The task runner of the render thread. | |
298 const scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_; | |
299 | |
300 // Protects |stop_signal_received_| and |read_op_|. | |
301 base::Lock lock_; | |
302 | |
303 // Whether we've been told to stop via Abort() or Stop(). | |
304 bool stop_signal_received_; | |
305 | |
306 // This variable is true when the user has requested the video to play at | |
307 // least once. | |
308 bool media_has_played_; | |
309 | |
310 // Buffering strategy as configured by SetBufferingStrategy(). | |
311 BufferingStrategy buffering_strategy_; | |
312 | |
313 // This variable holds the value of the preload attribute for the video | |
314 // element. | |
315 Preload preload_; | |
316 | |
317 // Bitrate of the content, 0 if unknown. | |
318 int bitrate_; | |
319 | |
320 // Current playback rate. | |
321 double playback_rate_; | |
322 | |
323 scoped_refptr<MediaLog> media_log_; | |
324 | |
325 // Host object to report buffered byte range changes to. | |
326 BufferedDataSourceHost* host_; | |
327 | |
328 DownloadingCB downloading_cb_; | |
329 | |
330 // The original URL of the first response. If the request is redirected to | |
331 // another URL it is the URL after redirected. If the response is generated in | |
332 // a Service Worker this URL is empty. BufferedDataSource checks the original | |
333 // URL of each successive response. If the origin URL of it is different from | |
334 // the original URL of the first response, it is treated as an error. | |
335 GURL response_original_url_; | |
336 | |
337 // Disallow rebinding WeakReference ownership to a different thread by keeping | |
338 // a persistent reference. This avoids problems with the thread-safety of | |
339 // reaching into this class from multiple threads to attain a WeakPtr. | |
340 base::WeakPtr<BufferedDataSource> weak_ptr_; | |
341 base::WeakPtrFactory<BufferedDataSource> weak_factory_; | |
342 | |
343 DISALLOW_COPY_AND_ASSIGN(BufferedDataSource); | |
344 }; | |
345 | |
346 } // namespace media | |
347 | |
348 #endif // MEDIA_BLINK_BUFFERED_DATA_SOURCE_H_ | |
OLD | NEW |