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

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

Issue 8224028: Numerous fixes to audio/video buffered resource loading. (Closed) Base URL: svn://chrome-svn/chrome/trunk/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 // 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698