| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "media/blink/multibuffer_data_source.h" | 5 #include "media/blink/multibuffer_data_source.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
| 11 #include "media/base/media_log.h" | 11 #include "media/base/media_log.h" |
| 12 #include "media/blink/multibuffer_reader.h" | 12 #include "media/blink/multibuffer_reader.h" |
| 13 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
| 14 | 14 |
| 15 using blink::WebFrame; | 15 using blink::WebFrame; |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 // Minimum preload buffer. | 19 // Minimum preload buffer. |
| 20 const int64 kMinBufferPreload = 2 << 20; // 2 Mb | 20 const int64_t kMinBufferPreload = 2 << 20; // 2 Mb |
| 21 // Maxmimum preload buffer. | 21 // Maxmimum preload buffer. |
| 22 const int64 kMaxBufferPreload = 20 << 20; // 20 Mb | 22 const int64_t kMaxBufferPreload = 20 << 20; // 20 Mb |
| 23 | 23 |
| 24 // Preload this much extra, then stop preloading until we fall below the | 24 // Preload this much extra, then stop preloading until we fall below the |
| 25 // kTargetSecondsBufferedAhead. | 25 // kTargetSecondsBufferedAhead. |
| 26 const int64 kPreloadHighExtra = 1 << 20; // 1 Mb | 26 const int64_t kPreloadHighExtra = 1 << 20; // 1 Mb |
| 27 | 27 |
| 28 // Total size of the pinned region in the cache. | 28 // Total size of the pinned region in the cache. |
| 29 const int64 kMaxBufferSize = 25 << 20; // 25 Mb | 29 const int64_t kMaxBufferSize = 25 << 20; // 25 Mb |
| 30 | 30 |
| 31 // If bitrate is not known, use this. | 31 // If bitrate is not known, use this. |
| 32 const int64 kDefaultBitrate = 200 * 8 << 10; // 200 Kbps. | 32 const int64_t kDefaultBitrate = 200 * 8 << 10; // 200 Kbps. |
| 33 | 33 |
| 34 // Maximum bitrate for buffer calculations. | 34 // Maximum bitrate for buffer calculations. |
| 35 const int64 kMaxBitrate = 20 * 8 << 20; // 20 Mbps. | 35 const int64_t kMaxBitrate = 20 * 8 << 20; // 20 Mbps. |
| 36 | 36 |
| 37 // Maximum playback rate for buffer calculations. | 37 // Maximum playback rate for buffer calculations. |
| 38 const double kMaxPlaybackRate = 25.0; | 38 const double kMaxPlaybackRate = 25.0; |
| 39 | 39 |
| 40 // Preload this many seconds of data by default. | 40 // Preload this many seconds of data by default. |
| 41 const int64 kTargetSecondsBufferedAhead = 10; | 41 const int64_t kTargetSecondsBufferedAhead = 10; |
| 42 | 42 |
| 43 // Keep this many seconds of data for going back by default. | 43 // Keep this many seconds of data for going back by default. |
| 44 const int64 kTargetSecondsBufferedBehind = 2; | 44 const int64_t kTargetSecondsBufferedBehind = 2; |
| 45 | 45 |
| 46 } // namespace | 46 } // namespace |
| 47 | 47 |
| 48 namespace media { | 48 namespace media { |
| 49 | 49 |
| 50 template <typename T> | 50 template <typename T> |
| 51 T clamp(T value, T min, T max) { | 51 T clamp(T value, T min, T max) { |
| 52 return std::max(std::min(value, max), min); | 52 return std::max(std::min(value, max), min); |
| 53 } | 53 } |
| 54 | 54 |
| 55 class MultibufferDataSource::ReadOperation { | 55 class MultibufferDataSource::ReadOperation { |
| 56 public: | 56 public: |
| 57 ReadOperation(int64 position, | 57 ReadOperation(int64_t position, |
| 58 int size, | 58 int size, |
| 59 uint8* data, | 59 uint8_t* data, |
| 60 const DataSource::ReadCB& callback); | 60 const DataSource::ReadCB& callback); |
| 61 ~ReadOperation(); | 61 ~ReadOperation(); |
| 62 | 62 |
| 63 // Runs |callback_| with the given |result|, deleting the operation | 63 // Runs |callback_| with the given |result|, deleting the operation |
| 64 // afterwards. | 64 // afterwards. |
| 65 static void Run(scoped_ptr<ReadOperation> read_op, int result); | 65 static void Run(scoped_ptr<ReadOperation> read_op, int result); |
| 66 | 66 |
| 67 int64 position() { return position_; } | 67 int64_t position() { return position_; } |
| 68 int size() { return size_; } | 68 int size() { return size_; } |
| 69 uint8* data() { return data_; } | 69 uint8_t* data() { return data_; } |
| 70 | 70 |
| 71 private: | 71 private: |
| 72 const int64 position_; | 72 const int64_t position_; |
| 73 const int size_; | 73 const int size_; |
| 74 uint8* data_; | 74 uint8_t* data_; |
| 75 DataSource::ReadCB callback_; | 75 DataSource::ReadCB callback_; |
| 76 | 76 |
| 77 DISALLOW_IMPLICIT_CONSTRUCTORS(ReadOperation); | 77 DISALLOW_IMPLICIT_CONSTRUCTORS(ReadOperation); |
| 78 }; | 78 }; |
| 79 | 79 |
| 80 MultibufferDataSource::ReadOperation::ReadOperation( | 80 MultibufferDataSource::ReadOperation::ReadOperation( |
| 81 int64 position, | 81 int64_t position, |
| 82 int size, | 82 int size, |
| 83 uint8* data, | 83 uint8_t* data, |
| 84 const DataSource::ReadCB& callback) | 84 const DataSource::ReadCB& callback) |
| 85 : position_(position), size_(size), data_(data), callback_(callback) { | 85 : position_(position), size_(size), data_(data), callback_(callback) { |
| 86 DCHECK(!callback_.is_null()); | 86 DCHECK(!callback_.is_null()); |
| 87 } | 87 } |
| 88 | 88 |
| 89 MultibufferDataSource::ReadOperation::~ReadOperation() { | 89 MultibufferDataSource::ReadOperation::~ReadOperation() { |
| 90 DCHECK(callback_.is_null()); | 90 DCHECK(callback_.is_null()); |
| 91 } | 91 } |
| 92 | 92 |
| 93 // static | 93 // static |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 } | 141 } |
| 142 | 142 |
| 143 bool MultibufferDataSource::media_has_played() const { | 143 bool MultibufferDataSource::media_has_played() const { |
| 144 return media_has_played_; | 144 return media_has_played_; |
| 145 } | 145 } |
| 146 | 146 |
| 147 bool MultibufferDataSource::assume_fully_buffered() { | 147 bool MultibufferDataSource::assume_fully_buffered() { |
| 148 return !url_data_->url().SchemeIsHTTPOrHTTPS(); | 148 return !url_data_->url().SchemeIsHTTPOrHTTPS(); |
| 149 } | 149 } |
| 150 | 150 |
| 151 void MultibufferDataSource::CreateResourceLoader(int64 first_byte_position, | 151 void MultibufferDataSource::CreateResourceLoader(int64_t first_byte_position, |
| 152 int64 last_byte_position) { | 152 int64_t last_byte_position) { |
| 153 DCHECK(render_task_runner_->BelongsToCurrentThread()); | 153 DCHECK(render_task_runner_->BelongsToCurrentThread()); |
| 154 | 154 |
| 155 reader_.reset(new MultiBufferReader( | 155 reader_.reset(new MultiBufferReader( |
| 156 url_data_->multibuffer(), first_byte_position, last_byte_position, | 156 url_data_->multibuffer(), first_byte_position, last_byte_position, |
| 157 base::Bind(&MultibufferDataSource::ProgressCallback, weak_ptr_))); | 157 base::Bind(&MultibufferDataSource::ProgressCallback, weak_ptr_))); |
| 158 UpdateBufferSizes(); | 158 UpdateBufferSizes(); |
| 159 } | 159 } |
| 160 | 160 |
| 161 void MultibufferDataSource::Initialize(const InitializeCB& init_cb) { | 161 void MultibufferDataSource::Initialize(const InitializeCB& init_cb) { |
| 162 DCHECK(render_task_runner_->BelongsToCurrentThread()); | 162 DCHECK(render_task_runner_->BelongsToCurrentThread()); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 reader_.reset(nullptr); | 319 reader_.reset(nullptr); |
| 320 } | 320 } |
| 321 } | 321 } |
| 322 | 322 |
| 323 int64_t MultibufferDataSource::GetMemoryUsage() const { | 323 int64_t MultibufferDataSource::GetMemoryUsage() const { |
| 324 // TODO(hubbe): Make more accurate when url_data_ is shared. | 324 // TODO(hubbe): Make more accurate when url_data_ is shared. |
| 325 return url_data_->CachedSize() | 325 return url_data_->CachedSize() |
| 326 << url_data_->multibuffer()->block_size_shift(); | 326 << url_data_->multibuffer()->block_size_shift(); |
| 327 } | 327 } |
| 328 | 328 |
| 329 void MultibufferDataSource::Read(int64 position, | 329 void MultibufferDataSource::Read(int64_t position, |
| 330 int size, | 330 int size, |
| 331 uint8* data, | 331 uint8_t* data, |
| 332 const DataSource::ReadCB& read_cb) { | 332 const DataSource::ReadCB& read_cb) { |
| 333 DVLOG(1) << "Read: " << position << " offset, " << size << " bytes"; | 333 DVLOG(1) << "Read: " << position << " offset, " << size << " bytes"; |
| 334 // Reading is not allowed until after initialization. | 334 // Reading is not allowed until after initialization. |
| 335 DCHECK(init_cb_.is_null()); | 335 DCHECK(init_cb_.is_null()); |
| 336 DCHECK(!read_cb.is_null()); | 336 DCHECK(!read_cb.is_null()); |
| 337 | 337 |
| 338 { | 338 { |
| 339 base::AutoLock auto_lock(lock_); | 339 base::AutoLock auto_lock(lock_); |
| 340 DCHECK(!read_op_); | 340 DCHECK(!read_op_); |
| 341 | 341 |
| 342 if (stop_signal_received_) { | 342 if (stop_signal_received_) { |
| 343 read_cb.Run(kReadError); | 343 read_cb.Run(kReadError); |
| 344 return; | 344 return; |
| 345 } | 345 } |
| 346 | 346 |
| 347 read_op_.reset(new ReadOperation(position, size, data, read_cb)); | 347 read_op_.reset(new ReadOperation(position, size, data, read_cb)); |
| 348 } | 348 } |
| 349 | 349 |
| 350 render_task_runner_->PostTask( | 350 render_task_runner_->PostTask( |
| 351 FROM_HERE, | 351 FROM_HERE, |
| 352 base::Bind(&MultibufferDataSource::ReadTask, weak_factory_.GetWeakPtr())); | 352 base::Bind(&MultibufferDataSource::ReadTask, weak_factory_.GetWeakPtr())); |
| 353 } | 353 } |
| 354 | 354 |
| 355 bool MultibufferDataSource::GetSize(int64* size_out) { | 355 bool MultibufferDataSource::GetSize(int64_t* size_out) { |
| 356 *size_out = url_data_->length(); | 356 *size_out = url_data_->length(); |
| 357 return *size_out != kPositionNotSpecified; | 357 return *size_out != kPositionNotSpecified; |
| 358 } | 358 } |
| 359 | 359 |
| 360 bool MultibufferDataSource::IsStreaming() { | 360 bool MultibufferDataSource::IsStreaming() { |
| 361 return streaming_; | 361 return streaming_; |
| 362 } | 362 } |
| 363 | 363 |
| 364 ///////////////////////////////////////////////////////////////////////////// | 364 ///////////////////////////////////////////////////////////////////////////// |
| 365 // This method is the place where actual read happens, | 365 // This method is the place where actual read happens, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 } | 477 } |
| 478 | 478 |
| 479 render_task_runner_->PostTask( | 479 render_task_runner_->PostTask( |
| 480 FROM_HERE, base::Bind(base::ResetAndReturn(&init_cb_), success)); | 480 FROM_HERE, base::Bind(base::ResetAndReturn(&init_cb_), success)); |
| 481 | 481 |
| 482 // Even if data is cached, say that we're loading at this point for | 482 // Even if data is cached, say that we're loading at this point for |
| 483 // compatibility. | 483 // compatibility. |
| 484 UpdateLoadingState(true); | 484 UpdateLoadingState(true); |
| 485 } | 485 } |
| 486 | 486 |
| 487 void MultibufferDataSource::ProgressCallback(int64 begin, int64 end) { | 487 void MultibufferDataSource::ProgressCallback(int64_t begin, int64_t end) { |
| 488 DVLOG(1) << __FUNCTION__ << "(" << begin << ", " << end << ")"; | 488 DVLOG(1) << __FUNCTION__ << "(" << begin << ", " << end << ")"; |
| 489 DCHECK(render_task_runner_->BelongsToCurrentThread()); | 489 DCHECK(render_task_runner_->BelongsToCurrentThread()); |
| 490 | 490 |
| 491 if (assume_fully_buffered()) | 491 if (assume_fully_buffered()) |
| 492 return; | 492 return; |
| 493 | 493 |
| 494 if (end > begin) { | 494 if (end > begin) { |
| 495 // TODO(scherkus): we shouldn't have to lock to signal host(), see | 495 // TODO(scherkus): we shouldn't have to lock to signal host(), see |
| 496 // http://crbug.com/113712 for details. | 496 // http://crbug.com/113712 for details. |
| 497 base::AutoLock auto_lock(lock_); | 497 base::AutoLock auto_lock(lock_); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 // why bother?) | 533 // why bother?) |
| 534 bool aggressive = (buffering_strategy_ == BUFFERING_STRATEGY_AGGRESSIVE); | 534 bool aggressive = (buffering_strategy_ == BUFFERING_STRATEGY_AGGRESSIVE); |
| 535 if (media_has_played_ && aggressive && url_data_ && | 535 if (media_has_played_ && aggressive && url_data_ && |
| 536 url_data_->range_supported() && url_data_->cacheable()) { | 536 url_data_->range_supported() && url_data_->cacheable()) { |
| 537 reader_->SetPreload(1LL << 40, 1LL << 40); // 1 Tb | 537 reader_->SetPreload(1LL << 40, 1LL << 40); // 1 Tb |
| 538 return; | 538 return; |
| 539 } | 539 } |
| 540 } | 540 } |
| 541 | 541 |
| 542 // Use a default bit rate if unknown and clamp to prevent overflow. | 542 // Use a default bit rate if unknown and clamp to prevent overflow. |
| 543 int64 bitrate = clamp<int64>(bitrate_, 0, kMaxBitrate); | 543 int64_t bitrate = clamp<int64_t>(bitrate_, 0, kMaxBitrate); |
| 544 if (bitrate == 0) | 544 if (bitrate == 0) |
| 545 bitrate = kDefaultBitrate; | 545 bitrate = kDefaultBitrate; |
| 546 | 546 |
| 547 // Only scale the buffer window for playback rates greater than 1.0 in | 547 // Only scale the buffer window for playback rates greater than 1.0 in |
| 548 // magnitude and clamp to prevent overflow. | 548 // magnitude and clamp to prevent overflow. |
| 549 double playback_rate = playback_rate_; | 549 double playback_rate = playback_rate_; |
| 550 | 550 |
| 551 playback_rate = std::max(playback_rate, 1.0); | 551 playback_rate = std::max(playback_rate, 1.0); |
| 552 playback_rate = std::min(playback_rate, kMaxPlaybackRate); | 552 playback_rate = std::min(playback_rate, kMaxPlaybackRate); |
| 553 | 553 |
| 554 int64 bytes_per_second = (bitrate / 8.0) * playback_rate; | 554 int64_t bytes_per_second = (bitrate / 8.0) * playback_rate; |
| 555 | 555 |
| 556 int64 preload = clamp(kTargetSecondsBufferedAhead * bytes_per_second, | 556 int64_t preload = clamp(kTargetSecondsBufferedAhead * bytes_per_second, |
| 557 kMinBufferPreload, kMaxBufferPreload); | 557 kMinBufferPreload, kMaxBufferPreload); |
| 558 int64 back_buffer = clamp(kTargetSecondsBufferedBehind * bytes_per_second, | 558 int64_t back_buffer = clamp(kTargetSecondsBufferedBehind * bytes_per_second, |
| 559 kMinBufferPreload, kMaxBufferPreload); | 559 kMinBufferPreload, kMaxBufferPreload); |
| 560 int64 pin_forwards = kMaxBufferSize - back_buffer; | 560 int64_t pin_forwards = kMaxBufferSize - back_buffer; |
| 561 DCHECK_LE(preload_ + kPreloadHighExtra, pin_forwards); | 561 DCHECK_LE(preload_ + kPreloadHighExtra, pin_forwards); |
| 562 reader_->SetMaxBuffer(back_buffer, pin_forwards); | 562 reader_->SetMaxBuffer(back_buffer, pin_forwards); |
| 563 | 563 |
| 564 if (preload_ == METADATA) { | 564 if (preload_ == METADATA) { |
| 565 reader_->SetPreload(0, 0); | 565 reader_->SetPreload(0, 0); |
| 566 } else { | 566 } else { |
| 567 reader_->SetPreload(preload + kPreloadHighExtra, preload); | 567 reader_->SetPreload(preload + kPreloadHighExtra, preload); |
| 568 } | 568 } |
| 569 } | 569 } |
| 570 | 570 |
| 571 } // namespace media | 571 } // namespace media |
| OLD | NEW |