Chromium Code Reviews| 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 // Default backward capacity of the buffer. | 38 // Minimum capacity of the buffer in forward or backward direction. |
| 39 static const size_t kBackwardCapacity = 2 * kMegabyte; | 39 // |
| 40 | 40 // 2MB is an arbitrary limit; it just seems to be "good enough" in practice. |
| 41 // Default forward capacity of the buffer. | 41 static const size_t kMinBufferCapacity = 2 * kMegabyte; |
| 42 static const size_t kForwardCapacity = 10 * kMegabyte; | |
| 43 | 42 |
| 44 // Maximum capacity of the buffer in forward or backward direction. This is | 43 // Maximum capacity of the buffer in forward or backward direction. This is |
| 45 // effectively the largest single read the code path can handle. | 44 // effectively the largest single read the code path can handle. |
| 46 // 20MB is an arbitrary limit; it just seems to be "good enough" in practice. | 45 // 20MB is an arbitrary limit; it just seems to be "good enough" in practice. |
| 47 static const size_t kMaxBufferCapacity = 20 * kMegabyte; | 46 static const size_t kMaxBufferCapacity = 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 higher playback rates and clamp to prevent | |
| 72 // overflow. | |
| 73 bool backward_playback = playback_rate < 0.0f; | |
| 74 playback_rate = std::max(playback_rate, 1.0f); | |
|
acolwell GONE FROM CHROMIUM
2011/10/11 16:18:01
Why are we mapping 0 & all negative playback_rates
scherkus (not reviewing)
2011/10/11 20:13:19
whoops missed absolute value of playback_rate!
it
| |
| 75 playback_rate = std::min(playback_rate, kMaxPlaybackRate); | |
| 76 | |
| 77 size_t bytes_per_second = static_cast<size_t>(playback_rate * bitrate / 8.0); | |
| 78 | |
| 79 // Clamp between kMinBufferCapacity and kMaxBufferCapacity. | |
| 80 *out_forward_capacity = std::max( | |
| 81 kTargetSecondsBufferedAhead * bytes_per_second, kMinBufferCapacity); | |
| 82 *out_backward_capacity = std::max( | |
| 83 kTargetSecondsBufferedBehind * bytes_per_second, kMinBufferCapacity); | |
| 84 | |
| 85 *out_forward_capacity = std::min(*out_forward_capacity, kMaxBufferCapacity); | |
| 86 *out_backward_capacity = std::min(*out_backward_capacity, kMaxBufferCapacity); | |
| 87 | |
| 88 if (backward_playback) | |
| 89 std::swap(*out_forward_capacity, *out_backward_capacity); | |
| 90 } | |
| 91 | |
| 92 | |
| 55 BufferedResourceLoader::BufferedResourceLoader( | 93 BufferedResourceLoader::BufferedResourceLoader( |
| 56 const GURL& url, | 94 const GURL& url, |
| 57 int64 first_byte_position, | 95 int64 first_byte_position, |
| 58 int64 last_byte_position, | 96 int64 last_byte_position, |
| 97 DeferStrategy strategy, | |
| 98 int bitrate, | |
| 99 float playback_rate, | |
| 59 media::MediaLog* media_log) | 100 media::MediaLog* media_log) |
| 60 : buffer_(new media::SeekableBuffer(kBackwardCapacity, kForwardCapacity)), | 101 : deferred_(false), |
| 61 deferred_(false), | 102 defer_strategy_(strategy), |
| 62 defer_strategy_(kReadThenDefer), | |
| 63 completed_(false), | 103 completed_(false), |
| 64 range_requested_(false), | 104 range_requested_(false), |
| 65 range_supported_(false), | 105 range_supported_(false), |
| 66 saved_forward_capacity_(0), | 106 saved_forward_capacity_(0), |
| 67 url_(url), | 107 url_(url), |
| 68 first_byte_position_(first_byte_position), | 108 first_byte_position_(first_byte_position), |
| 69 last_byte_position_(last_byte_position), | 109 last_byte_position_(last_byte_position), |
| 70 single_origin_(true), | 110 single_origin_(true), |
| 71 start_callback_(NULL), | 111 start_callback_(NULL), |
| 72 offset_(0), | 112 offset_(0), |
| 73 content_length_(kPositionNotSpecified), | 113 content_length_(kPositionNotSpecified), |
| 74 instance_size_(kPositionNotSpecified), | 114 instance_size_(kPositionNotSpecified), |
| 75 read_callback_(NULL), | 115 read_callback_(NULL), |
| 76 read_position_(0), | 116 read_position_(0), |
| 77 read_size_(0), | 117 read_size_(0), |
| 78 read_buffer_(NULL), | 118 read_buffer_(NULL), |
| 79 first_offset_(0), | 119 first_offset_(0), |
| 80 last_offset_(0), | 120 last_offset_(0), |
| 81 keep_test_loader_(false), | 121 keep_test_loader_(false), |
| 82 bitrate_(0), | 122 bitrate_(bitrate), |
| 83 playback_rate_(0.0), | 123 playback_rate_(playback_rate), |
| 84 media_log_(media_log) { | 124 media_log_(media_log) { |
| 125 | |
| 126 size_t backward_capacity; | |
| 127 size_t forward_capacity; | |
| 128 ComputeTargetBufferWindow( | |
| 129 playback_rate_, bitrate_, &backward_capacity, &forward_capacity); | |
| 130 buffer_.reset(new media::SeekableBuffer(backward_capacity, forward_capacity)); | |
| 85 } | 131 } |
| 86 | 132 |
| 87 BufferedResourceLoader::~BufferedResourceLoader() { | 133 BufferedResourceLoader::~BufferedResourceLoader() { |
| 88 if (!completed_ && url_loader_.get()) | 134 if (!completed_ && url_loader_.get()) |
| 89 url_loader_->cancel(); | 135 url_loader_->cancel(); |
| 90 } | 136 } |
| 91 | 137 |
| 92 void BufferedResourceLoader::Start(net::OldCompletionCallback* start_callback, | 138 void BufferedResourceLoader::Start(net::OldCompletionCallback* start_callback, |
| 93 const base::Closure& event_callback, | 139 const base::Closure& event_callback, |
| 94 WebFrame* frame) { | 140 WebFrame* frame) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 | 271 |
| 226 // If we expect the read request to be fulfilled later, return | 272 // If we expect the read request to be fulfilled later, return |
| 227 // and let more data to flow in. | 273 // and let more data to flow in. |
| 228 if (WillFulfillRead()) { | 274 if (WillFulfillRead()) { |
| 229 // If necessary, expand the forward capacity of the buffer to accomodate an | 275 // If necessary, expand the forward capacity of the buffer to accomodate an |
| 230 // unusually large read. | 276 // unusually large read. |
| 231 if (read_size_ > buffer_->forward_capacity()) { | 277 if (read_size_ > buffer_->forward_capacity()) { |
| 232 saved_forward_capacity_ = buffer_->forward_capacity(); | 278 saved_forward_capacity_ = buffer_->forward_capacity(); |
| 233 buffer_->set_forward_capacity(read_size_); | 279 buffer_->set_forward_capacity(read_size_); |
| 234 } | 280 } |
| 235 return; | 281 return; |
| 236 } | 282 } |
| 237 | 283 |
| 238 // Make a callback to report failure. | 284 // Make a callback to report failure. |
| 239 DoneRead(net::ERR_CACHE_MISS); | 285 DoneRead(net::ERR_CACHE_MISS); |
| 240 } | 286 } |
| 241 | 287 |
| 242 int64 BufferedResourceLoader::GetBufferedPosition() { | 288 int64 BufferedResourceLoader::GetBufferedPosition() { |
| 243 if (buffer_.get()) | 289 if (buffer_.get()) |
| 244 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1; | 290 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1; |
| 245 return kPositionNotSpecified; | 291 return kPositionNotSpecified; |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 503 | 549 |
| 504 void BufferedResourceLoader::SetBitrate(int bitrate) { | 550 void BufferedResourceLoader::SetBitrate(int bitrate) { |
| 505 DCHECK(bitrate >= 0); | 551 DCHECK(bitrate >= 0); |
| 506 bitrate_ = bitrate; | 552 bitrate_ = bitrate; |
| 507 UpdateBufferWindow(); | 553 UpdateBufferWindow(); |
| 508 } | 554 } |
| 509 | 555 |
| 510 ///////////////////////////////////////////////////////////////////////////// | 556 ///////////////////////////////////////////////////////////////////////////// |
| 511 // Helper methods. | 557 // Helper methods. |
| 512 | 558 |
| 513 // Computes the suggested backward and forward capacity for the buffer | |
| 514 // if one wants to play at |playback_rate| * the natural playback speed. | |
| 515 // Use a value of 0 for |bitrate| if it is unknown. | |
| 516 static void ComputeTargetBufferWindow(float playback_rate, int bitrate, | |
| 517 size_t* out_backward_capacity, | |
| 518 size_t* out_forward_capacity) { | |
| 519 DCHECK_GE(bitrate, 0); | |
| 520 DCHECK_NE(playback_rate, 0.0); | |
| 521 static const size_t kDefaultBitrate = kMegabyte; | |
| 522 static const size_t kMaxBitrate = 50 * kMegabyte; | |
| 523 static const float kMaxPlaybackRate = 25.0; | |
| 524 static const size_t kTargetSecondsBufferedAhead = 10; | |
| 525 static const size_t kTargetSecondsBufferedBehind = 2; | |
| 526 | |
| 527 if (bitrate <= 0) | |
| 528 bitrate = kDefaultBitrate; | |
| 529 | |
| 530 bool backward_playback = playback_rate < 0.0; | |
| 531 if (backward_playback) | |
| 532 playback_rate *= -1.0; | |
| 533 | |
| 534 // Cap playback rate and bitrate to prevent overflow. | |
| 535 playback_rate = std::min(kMaxPlaybackRate, playback_rate); | |
| 536 bitrate = std::min(kMaxBitrate, static_cast<size_t>(bitrate)); | |
| 537 | |
| 538 size_t bytes_per_second = static_cast<size_t>(playback_rate * bitrate / 8.0); | |
| 539 | |
| 540 *out_forward_capacity = std::min( | |
| 541 kTargetSecondsBufferedAhead * bytes_per_second, kMaxBufferCapacity); | |
| 542 *out_backward_capacity = std::min( | |
| 543 kTargetSecondsBufferedBehind * bytes_per_second, kMaxBufferCapacity); | |
| 544 if (backward_playback) | |
| 545 std::swap(*out_forward_capacity, *out_backward_capacity); | |
| 546 } | |
| 547 | |
| 548 void BufferedResourceLoader::UpdateBufferWindow() { | 559 void BufferedResourceLoader::UpdateBufferWindow() { |
| 549 if (!buffer_.get()) | 560 if (!buffer_.get()) |
| 550 return; | 561 return; |
| 551 | 562 |
| 552 // Don't adjust buffer window if video is paused. | |
| 553 if (playback_rate_ == 0.0) | |
|
acolwell GONE FROM CHROMIUM
2011/10/11 16:18:01
Sanity check. This was removed because of the new
vrk (LEFT CHROMIUM)
2011/10/11 18:23:21
+1 what acolwell said; I don't think it makes sens
scherkus (not reviewing)
2011/10/11 20:13:19
Moved to SetPlaybackRate()
scherkus (not reviewing)
2011/10/11 20:13:19
Done.
| |
| 554 return; | |
| 555 | |
| 556 size_t backward_capacity; | 563 size_t backward_capacity; |
| 557 size_t forward_capacity; | 564 size_t forward_capacity; |
| 558 ComputeTargetBufferWindow( | 565 ComputeTargetBufferWindow( |
| 559 playback_rate_, bitrate_, &backward_capacity, &forward_capacity); | 566 playback_rate_, bitrate_, &backward_capacity, &forward_capacity); |
| 560 | 567 |
| 561 // This does not evict data from the buffer if the new capacities are less | 568 // This does not evict data from the buffer if the new capacities are less |
| 562 // than the current capacities; the new limits will be enforced after the | 569 // than the current capacities; the new limits will be enforced after the |
| 563 // existing excess buffered data is consumed. | 570 // existing excess buffered data is consumed. |
| 564 buffer_->set_backward_capacity(backward_capacity); | 571 buffer_->set_backward_capacity(backward_capacity); |
| 565 buffer_->set_forward_capacity(forward_capacity); | 572 buffer_->set_forward_capacity(forward_capacity); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 771 if (buffer_.get()) { | 778 if (buffer_.get()) { |
| 772 media_log_->AddEvent( | 779 media_log_->AddEvent( |
| 773 media_log_->CreateBufferedExtentsChangedEvent( | 780 media_log_->CreateBufferedExtentsChangedEvent( |
| 774 offset_ - buffer_->backward_bytes(), | 781 offset_ - buffer_->backward_bytes(), |
| 775 offset_, | 782 offset_, |
| 776 offset_ + buffer_->forward_bytes())); | 783 offset_ + buffer_->forward_bytes())); |
| 777 } | 784 } |
| 778 } | 785 } |
| 779 | 786 |
| 780 } // namespace webkit_glue | 787 } // namespace webkit_glue |
| OLD | NEW |