OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/glue/media/buffered_resource_loader.h" | 5 #include "webkit/glue/media/buffered_resource_loader.h" |
6 | 6 |
7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "media/base/media_log.h" | 10 #include "media/base/media_log.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 using webkit_glue::MultipartResponseDelegate; | 28 using webkit_glue::MultipartResponseDelegate; |
29 | 29 |
30 namespace webkit_glue { | 30 namespace webkit_glue { |
31 | 31 |
32 static const int kHttpOK = 200; | 32 static const int kHttpOK = 200; |
33 static const int kHttpPartialContent = 206; | 33 static const int kHttpPartialContent = 206; |
34 | 34 |
35 // Define the number of bytes in a megabyte. | 35 // Define the number of bytes in a megabyte. |
36 static const size_t kMegabyte = 1024 * 1024; | 36 static const size_t kMegabyte = 1024 * 1024; |
37 | 37 |
38 // Backward capacity of the buffer, by default 2MB. | 38 // Minimum capacity of the buffer in forward or backward direction. |
39 static const size_t kBackwardCapacity = 2 * kMegabyte; | 39 // |
| 40 // 2MB is an arbitrary limit; it just seems to be "good enough" in practice. |
| 41 static const size_t kMinBufferCapacity = 2 * kMegabyte; |
40 | 42 |
41 // Forward capacity of the buffer, by default 10MB. | 43 // Maximum capacity of the buffer in forward or backward direction. This is |
42 static const size_t kForwardCapacity = 10 * kMegabyte; | 44 // effectively the largest single read the code path can handle. |
43 | 45 // 20MB is an arbitrary limit; it just seems to be "good enough" in practice. |
44 // Maximum forward capacity of the buffer, by default 20MB. This is effectively | 46 static const size_t kMaxBufferCapacity = 20 * kMegabyte; |
45 // the largest single read teh code path can handle. 20MB is an arbitrary limit; | |
46 // it just seems to be "good enough" in practice. | |
47 static const size_t kMaxForwardCapacity = 20 * kMegabyte; | |
48 | 47 |
49 // Maximum number of bytes outside the buffer we will wait for in order to | 48 // Maximum number of bytes outside the buffer we will wait for in order to |
50 // fulfill a read. If a read starts more than 2MB away from the data we | 49 // fulfill a read. If a read starts more than 2MB away from the data we |
51 // currently have in the buffer, we will not wait for buffer to reach the read's | 50 // currently have in the buffer, we will not wait for buffer to reach the read's |
52 // location and will instead reset the request. | 51 // location and will instead reset the request. |
53 static const int kForwardWaitThreshold = 2 * kMegabyte; | 52 static const int kForwardWaitThreshold = 2 * kMegabyte; |
54 | 53 |
| 54 // Computes the suggested backward and forward capacity for the buffer |
| 55 // if one wants to play at |playback_rate| * the natural playback speed. |
| 56 // Use a value of 0 for |bitrate| if it is unknown. |
| 57 static void ComputeTargetBufferWindow(float playback_rate, int bitrate, |
| 58 size_t* out_backward_capacity, |
| 59 size_t* out_forward_capacity) { |
| 60 static const size_t kDefaultBitrate = 200 * 1024 * 8; // 200 Kbps. |
| 61 static const size_t kMaxBitrate = 20 * kMegabyte * 8; // 20 Mbps. |
| 62 static const float kMaxPlaybackRate = 25.0; |
| 63 static const size_t kTargetSecondsBufferedAhead = 10; |
| 64 static const size_t kTargetSecondsBufferedBehind = 2; |
| 65 |
| 66 // Use a default bit rate if unknown and clamp to prevent overflow. |
| 67 if (bitrate <= 0) |
| 68 bitrate = kDefaultBitrate; |
| 69 bitrate = std::min(static_cast<size_t>(bitrate), kMaxBitrate); |
| 70 |
| 71 // Only scale the buffer window for playback rates greater than 1.0 in |
| 72 // magnitude and clamp to prevent overflow. |
| 73 bool backward_playback = false; |
| 74 if (playback_rate < 0.0f) { |
| 75 backward_playback = true; |
| 76 playback_rate *= -1.0f; |
| 77 } |
| 78 |
| 79 playback_rate = std::max(playback_rate, 1.0f); |
| 80 playback_rate = std::min(playback_rate, kMaxPlaybackRate); |
| 81 |
| 82 size_t bytes_per_second = static_cast<size_t>(playback_rate * bitrate / 8.0); |
| 83 |
| 84 // Clamp between kMinBufferCapacity and kMaxBufferCapacity. |
| 85 *out_forward_capacity = std::max( |
| 86 kTargetSecondsBufferedAhead * bytes_per_second, kMinBufferCapacity); |
| 87 *out_backward_capacity = std::max( |
| 88 kTargetSecondsBufferedBehind * bytes_per_second, kMinBufferCapacity); |
| 89 |
| 90 *out_forward_capacity = std::min(*out_forward_capacity, kMaxBufferCapacity); |
| 91 *out_backward_capacity = std::min(*out_backward_capacity, kMaxBufferCapacity); |
| 92 |
| 93 if (backward_playback) |
| 94 std::swap(*out_forward_capacity, *out_backward_capacity); |
| 95 } |
| 96 |
| 97 |
55 BufferedResourceLoader::BufferedResourceLoader( | 98 BufferedResourceLoader::BufferedResourceLoader( |
56 const GURL& url, | 99 const GURL& url, |
57 int64 first_byte_position, | 100 int64 first_byte_position, |
58 int64 last_byte_position, | 101 int64 last_byte_position, |
| 102 DeferStrategy strategy, |
| 103 int bitrate, |
| 104 float playback_rate, |
59 media::MediaLog* media_log) | 105 media::MediaLog* media_log) |
60 : buffer_(new media::SeekableBuffer(kBackwardCapacity, kForwardCapacity)), | 106 : deferred_(false), |
61 deferred_(false), | 107 defer_strategy_(strategy), |
62 defer_strategy_(kReadThenDefer), | |
63 completed_(false), | 108 completed_(false), |
64 range_requested_(false), | 109 range_requested_(false), |
65 range_supported_(false), | 110 range_supported_(false), |
66 saved_forward_capacity_(0), | 111 saved_forward_capacity_(0), |
67 url_(url), | 112 url_(url), |
68 first_byte_position_(first_byte_position), | 113 first_byte_position_(first_byte_position), |
69 last_byte_position_(last_byte_position), | 114 last_byte_position_(last_byte_position), |
70 single_origin_(true), | 115 single_origin_(true), |
71 start_callback_(NULL), | 116 start_callback_(NULL), |
72 offset_(0), | 117 offset_(0), |
73 content_length_(kPositionNotSpecified), | 118 content_length_(kPositionNotSpecified), |
74 instance_size_(kPositionNotSpecified), | 119 instance_size_(kPositionNotSpecified), |
75 read_callback_(NULL), | 120 read_callback_(NULL), |
76 read_position_(0), | 121 read_position_(0), |
77 read_size_(0), | 122 read_size_(0), |
78 read_buffer_(NULL), | 123 read_buffer_(NULL), |
79 first_offset_(0), | 124 first_offset_(0), |
80 last_offset_(0), | 125 last_offset_(0), |
81 keep_test_loader_(false), | 126 keep_test_loader_(false), |
| 127 bitrate_(bitrate), |
| 128 playback_rate_(playback_rate), |
82 media_log_(media_log) { | 129 media_log_(media_log) { |
| 130 |
| 131 size_t backward_capacity; |
| 132 size_t forward_capacity; |
| 133 ComputeTargetBufferWindow( |
| 134 playback_rate_, bitrate_, &backward_capacity, &forward_capacity); |
| 135 buffer_.reset(new media::SeekableBuffer(backward_capacity, forward_capacity)); |
83 } | 136 } |
84 | 137 |
85 BufferedResourceLoader::~BufferedResourceLoader() { | 138 BufferedResourceLoader::~BufferedResourceLoader() { |
86 if (!completed_ && url_loader_.get()) | 139 if (!completed_ && url_loader_.get()) |
87 url_loader_->cancel(); | 140 url_loader_->cancel(); |
88 } | 141 } |
89 | 142 |
90 void BufferedResourceLoader::Start(net::CompletionCallback* start_callback, | 143 void BufferedResourceLoader::Start(net::CompletionCallback* start_callback, |
91 NetworkEventCallback* event_callback, | 144 NetworkEventCallback* event_callback, |
92 WebFrame* frame) { | 145 WebFrame* frame) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 // Make sure |offset_| and |read_position_| does not differ by a large | 246 // Make sure |offset_| and |read_position_| does not differ by a large |
194 // amount. | 247 // amount. |
195 if (read_position_ > offset_ + kint32max || | 248 if (read_position_ > offset_ + kint32max || |
196 read_position_ < offset_ + kint32min) { | 249 read_position_ < offset_ + kint32min) { |
197 DoneRead(net::ERR_CACHE_MISS); | 250 DoneRead(net::ERR_CACHE_MISS); |
198 return; | 251 return; |
199 } | 252 } |
200 | 253 |
201 // Make sure |read_size_| is not too large for the buffer to ever be able to | 254 // Make sure |read_size_| is not too large for the buffer to ever be able to |
202 // fulfill the read request. | 255 // fulfill the read request. |
203 if (read_size_ > kMaxForwardCapacity) { | 256 if (read_size_ > kMaxBufferCapacity) { |
204 DoneRead(net::ERR_FAILED); | 257 DoneRead(net::ERR_FAILED); |
205 return; | 258 return; |
206 } | 259 } |
207 | 260 |
208 // Prepare the parameters. | 261 // Prepare the parameters. |
209 first_offset_ = static_cast<int>(read_position_ - offset_); | 262 first_offset_ = static_cast<int>(read_position_ - offset_); |
210 last_offset_ = first_offset_ + read_size_; | 263 last_offset_ = first_offset_ + read_size_; |
211 | 264 |
212 // If we can serve the request now, do the actual read. | 265 // If we can serve the request now, do the actual read. |
213 if (CanFulfillRead()) { | 266 if (CanFulfillRead()) { |
214 ReadInternal(); | 267 ReadInternal(); |
215 UpdateDeferBehavior(); | 268 UpdateDeferBehavior(); |
216 return; | 269 return; |
217 } | 270 } |
218 | 271 |
219 // If you're deferred and you can't fulfill the read because you don't have | 272 // If you're deferred and you can't fulfill the read because you don't have |
220 // enough data, you will never fulfill the read. | 273 // enough data, you will never fulfill the read. |
221 // Update defer behavior to re-enable deferring if need be. | 274 // Update defer behavior to re-enable deferring if need be. |
222 UpdateDeferBehavior(); | 275 UpdateDeferBehavior(); |
223 | 276 |
224 // If we expect the read request to be fulfilled later, return | 277 // If we expect the read request to be fulfilled later, return |
225 // and let more data to flow in. | 278 // and let more data to flow in. |
226 if (WillFulfillRead()) { | 279 if (WillFulfillRead()) { |
227 // If necessary, expand the forward capacity of the buffer to accomodate an | 280 // If necessary, expand the forward capacity of the buffer to accomodate an |
228 // unusually large read. | 281 // unusually large read. |
229 if (read_size_ > buffer_->forward_capacity()) { | 282 if (read_size_ > buffer_->forward_capacity()) { |
230 saved_forward_capacity_ = buffer_->forward_capacity(); | 283 saved_forward_capacity_ = buffer_->forward_capacity(); |
231 buffer_->set_forward_capacity(read_size_); | 284 buffer_->set_forward_capacity(read_size_); |
232 } | 285 } |
233 return; | 286 return; |
234 } | 287 } |
235 | 288 |
236 // Make a callback to report failure. | 289 // Make a callback to report failure. |
237 DoneRead(net::ERR_CACHE_MISS); | 290 DoneRead(net::ERR_CACHE_MISS); |
238 } | 291 } |
239 | 292 |
240 int64 BufferedResourceLoader::GetBufferedPosition() { | 293 int64 BufferedResourceLoader::GetBufferedPosition() { |
241 if (buffer_.get()) | 294 if (buffer_.get()) |
242 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1; | 295 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1; |
243 return kPositionNotSpecified; | 296 return kPositionNotSpecified; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 NotifyNetworkEvent(); | 535 NotifyNetworkEvent(); |
483 | 536 |
484 url_loader_.reset(); | 537 url_loader_.reset(); |
485 Release(); | 538 Release(); |
486 } | 539 } |
487 | 540 |
488 bool BufferedResourceLoader::HasSingleOrigin() const { | 541 bool BufferedResourceLoader::HasSingleOrigin() const { |
489 return single_origin_; | 542 return single_origin_; |
490 } | 543 } |
491 | 544 |
| 545 void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) { |
| 546 defer_strategy_ = strategy; |
| 547 UpdateDeferBehavior(); |
| 548 } |
| 549 |
| 550 void BufferedResourceLoader::SetPlaybackRate(float playback_rate) { |
| 551 playback_rate_ = playback_rate; |
| 552 |
| 553 // This is a pause so don't bother updating the buffer window as we'll likely |
| 554 // get unpaused in the future. |
| 555 if (playback_rate_ == 0.0) |
| 556 return; |
| 557 |
| 558 UpdateBufferWindow(); |
| 559 } |
| 560 |
| 561 void BufferedResourceLoader::SetBitrate(int bitrate) { |
| 562 DCHECK(bitrate >= 0); |
| 563 bitrate_ = bitrate; |
| 564 UpdateBufferWindow(); |
| 565 } |
| 566 |
492 ///////////////////////////////////////////////////////////////////////////// | 567 ///////////////////////////////////////////////////////////////////////////// |
493 // Helper methods. | 568 // Helper methods. |
| 569 |
| 570 void BufferedResourceLoader::UpdateBufferWindow() { |
| 571 if (!buffer_.get()) |
| 572 return; |
| 573 |
| 574 size_t backward_capacity; |
| 575 size_t forward_capacity; |
| 576 ComputeTargetBufferWindow( |
| 577 playback_rate_, bitrate_, &backward_capacity, &forward_capacity); |
| 578 |
| 579 // This does not evict data from the buffer if the new capacities are less |
| 580 // than the current capacities; the new limits will be enforced after the |
| 581 // existing excess buffered data is consumed. |
| 582 buffer_->set_backward_capacity(backward_capacity); |
| 583 buffer_->set_forward_capacity(forward_capacity); |
| 584 } |
| 585 |
494 void BufferedResourceLoader::UpdateDeferBehavior() { | 586 void BufferedResourceLoader::UpdateDeferBehavior() { |
495 if (!url_loader_.get() || !buffer_.get()) | 587 if (!url_loader_.get() || !buffer_.get()) |
496 return; | 588 return; |
497 | 589 |
498 if ((deferred_ && ShouldDisableDefer()) || | 590 if ((deferred_ && ShouldDisableDefer()) || |
499 (!deferred_ && ShouldEnableDefer())) { | 591 (!deferred_ && ShouldEnableDefer())) { |
500 bool eventOccurred = ToggleDeferring(); | 592 bool eventOccurred = ToggleDeferring(); |
501 if (eventOccurred) | 593 if (eventOccurred) |
502 NotifyNetworkEvent(); | 594 NotifyNetworkEvent(); |
503 } | 595 } |
504 } | 596 } |
505 | 597 |
506 void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) { | |
507 defer_strategy_ = strategy; | |
508 UpdateDeferBehavior(); | |
509 } | |
510 | |
511 bool BufferedResourceLoader::ShouldEnableDefer() { | 598 bool BufferedResourceLoader::ShouldEnableDefer() { |
512 // If we're already deferring, then enabling makes no sense. | 599 // If we're already deferring, then enabling makes no sense. |
513 if (deferred_) | 600 if (deferred_) |
514 return false; | 601 return false; |
515 | 602 |
516 switch(defer_strategy_) { | 603 switch(defer_strategy_) { |
517 // Never defer at all, so never enable defer. | 604 // Never defer at all, so never enable defer. |
518 case kNeverDefer: | 605 case kNeverDefer: |
519 return false; | 606 return false; |
520 | 607 |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 if (buffer_.get()) { | 789 if (buffer_.get()) { |
703 media_log_->AddEvent( | 790 media_log_->AddEvent( |
704 media_log_->CreateBufferedExtentsChangedEvent( | 791 media_log_->CreateBufferedExtentsChangedEvent( |
705 offset_ - buffer_->backward_bytes(), | 792 offset_ - buffer_->backward_bytes(), |
706 offset_, | 793 offset_, |
707 offset_ + buffer_->forward_bytes())); | 794 offset_ + buffer_->forward_bytes())); |
708 } | 795 } |
709 } | 796 } |
710 | 797 |
711 } // namespace webkit_glue | 798 } // namespace webkit_glue |
OLD | NEW |