Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: webkit/glue/media/buffered_resource_loader.cc

Issue 8294025: Merge 105121 - Numerous fixes to audio/video buffered resource loading. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/874/src/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « webkit/glue/media/buffered_resource_loader.h ('k') | webkit/glue/media/buffered_resource_loader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698