| 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 "content/renderer/media/buffered_data_source.h" | 5 #include "content/renderer/media/buffered_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/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
| 10 #include "media/base/media_log.h" | 10 #include "media/base/media_log.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 // static | 74 // static |
| 75 void BufferedDataSource::ReadOperation::Run( | 75 void BufferedDataSource::ReadOperation::Run( |
| 76 scoped_ptr<ReadOperation> read_op, int result) { | 76 scoped_ptr<ReadOperation> read_op, int result) { |
| 77 base::ResetAndReturn(&read_op->callback_).Run(result); | 77 base::ResetAndReturn(&read_op->callback_).Run(result); |
| 78 } | 78 } |
| 79 | 79 |
| 80 BufferedDataSource::BufferedDataSource( | 80 BufferedDataSource::BufferedDataSource( |
| 81 const scoped_refptr<base::MessageLoopProxy>& render_loop, | 81 const scoped_refptr<base::MessageLoopProxy>& render_loop, |
| 82 WebFrame* frame, | 82 WebFrame* frame, |
| 83 media::MediaLog* media_log, | 83 media::MediaLog* media_log, |
| 84 media::DataSourceHost* host, |
| 84 const DownloadingCB& downloading_cb) | 85 const DownloadingCB& downloading_cb) |
| 85 : cors_mode_(BufferedResourceLoader::kUnspecified), | 86 : cors_mode_(BufferedResourceLoader::kUnspecified), |
| 86 total_bytes_(kPositionNotSpecified), | 87 total_bytes_(kPositionNotSpecified), |
| 87 assume_fully_buffered_(false), | 88 assume_fully_buffered_(false), |
| 88 streaming_(false), | 89 streaming_(false), |
| 89 frame_(frame), | 90 frame_(frame), |
| 90 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), | 91 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), |
| 91 intermediate_read_buffer_size_(kInitialReadBufferSize), | 92 intermediate_read_buffer_size_(kInitialReadBufferSize), |
| 92 render_loop_(render_loop), | 93 render_loop_(render_loop), |
| 93 stop_signal_received_(false), | 94 stop_signal_received_(false), |
| 94 media_has_played_(false), | 95 media_has_played_(false), |
| 95 preload_(AUTO), | 96 preload_(AUTO), |
| 96 bitrate_(0), | 97 bitrate_(0), |
| 97 playback_rate_(0.0), | 98 playback_rate_(0.0), |
| 98 media_log_(media_log), | 99 media_log_(media_log), |
| 100 host_(host), |
| 99 downloading_cb_(downloading_cb), | 101 downloading_cb_(downloading_cb), |
| 100 weak_factory_(this) { | 102 weak_factory_(this) { |
| 101 DCHECK(!downloading_cb_.is_null()); | 103 DCHECK(!downloading_cb_.is_null()); |
| 102 } | 104 } |
| 103 | 105 |
| 104 BufferedDataSource::~BufferedDataSource() {} | 106 BufferedDataSource::~BufferedDataSource() {} |
| 105 | 107 |
| 106 // A factory method to create BufferedResourceLoader using the read parameters. | 108 // A factory method to create BufferedResourceLoader using the read parameters. |
| 107 // This method can be overridden to inject mock BufferedResourceLoader object | 109 // This method can be overridden to inject mock BufferedResourceLoader object |
| 108 // for testing purpose. | 110 // for testing purpose. |
| 109 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( | 111 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( |
| 110 int64 first_byte_position, int64 last_byte_position) { | 112 int64 first_byte_position, int64 last_byte_position) { |
| 111 DCHECK(render_loop_->BelongsToCurrentThread()); | 113 DCHECK(render_loop_->BelongsToCurrentThread()); |
| 112 | 114 |
| 113 BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ? | 115 BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ? |
| 114 BufferedResourceLoader::kReadThenDefer : | 116 BufferedResourceLoader::kReadThenDefer : |
| 115 BufferedResourceLoader::kCapacityDefer; | 117 BufferedResourceLoader::kCapacityDefer; |
| 116 | 118 |
| 117 return new BufferedResourceLoader(url_, | 119 return new BufferedResourceLoader(url_, |
| 118 cors_mode_, | 120 cors_mode_, |
| 119 first_byte_position, | 121 first_byte_position, |
| 120 last_byte_position, | 122 last_byte_position, |
| 121 strategy, | 123 strategy, |
| 122 bitrate_, | 124 bitrate_, |
| 123 playback_rate_, | 125 playback_rate_, |
| 124 media_log_.get()); | 126 media_log_.get()); |
| 125 } | 127 } |
| 126 | 128 |
| 127 void BufferedDataSource::set_host(media::DataSourceHost* host) { | |
| 128 DataSource::set_host(host); | |
| 129 | |
| 130 if (loader_) { | |
| 131 base::AutoLock auto_lock(lock_); | |
| 132 UpdateHostState_Locked(); | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 void BufferedDataSource::Initialize( | 129 void BufferedDataSource::Initialize( |
| 137 const GURL& url, | 130 const GURL& url, |
| 138 BufferedResourceLoader::CORSMode cors_mode, | 131 BufferedResourceLoader::CORSMode cors_mode, |
| 139 const InitializeCB& init_cb) { | 132 const InitializeCB& init_cb) { |
| 140 DCHECK(render_loop_->BelongsToCurrentThread()); | 133 DCHECK(render_loop_->BelongsToCurrentThread()); |
| 141 DCHECK(!init_cb.is_null()); | 134 DCHECK(!init_cb.is_null()); |
| 142 DCHECK(!loader_.get()); | 135 DCHECK(!loader_.get()); |
| 143 url_ = url; | 136 url_ = url; |
| 144 cors_mode_ = cors_mode; | 137 cors_mode_ = cors_mode; |
| 145 | 138 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 loader_->Stop(); | 366 loader_->Stop(); |
| 374 } | 367 } |
| 375 | 368 |
| 376 // TODO(scherkus): we shouldn't have to lock to signal host(), see | 369 // TODO(scherkus): we shouldn't have to lock to signal host(), see |
| 377 // http://crbug.com/113712 for details. | 370 // http://crbug.com/113712 for details. |
| 378 base::AutoLock auto_lock(lock_); | 371 base::AutoLock auto_lock(lock_); |
| 379 if (stop_signal_received_) | 372 if (stop_signal_received_) |
| 380 return; | 373 return; |
| 381 | 374 |
| 382 if (success) { | 375 if (success) { |
| 383 UpdateHostState_Locked(); | 376 if (total_bytes_ != kPositionNotSpecified) { |
| 377 host_->SetTotalBytes(total_bytes_); |
| 378 if (assume_fully_buffered_) |
| 379 host_->AddBufferedByteRange(0, total_bytes_); |
| 380 } |
| 381 |
| 384 media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin()); | 382 media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin()); |
| 385 media_log_->SetBooleanProperty("passed_cors_access_check", | 383 media_log_->SetBooleanProperty("passed_cors_access_check", |
| 386 loader_->DidPassCORSAccessCheck()); | 384 loader_->DidPassCORSAccessCheck()); |
| 387 media_log_->SetBooleanProperty("range_header_supported", | 385 media_log_->SetBooleanProperty("range_header_supported", |
| 388 loader_->range_supported()); | 386 loader_->range_supported()); |
| 389 } | 387 } |
| 390 | 388 |
| 391 base::ResetAndReturn(&init_cb_).Run(success); | 389 base::ResetAndReturn(&init_cb_).Run(success); |
| 392 } | 390 } |
| 393 | 391 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 } | 451 } |
| 454 | 452 |
| 455 if (bytes_read > 0) { | 453 if (bytes_read > 0) { |
| 456 memcpy(read_op_->data(), intermediate_read_buffer_.get(), bytes_read); | 454 memcpy(read_op_->data(), intermediate_read_buffer_.get(), bytes_read); |
| 457 } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) { | 455 } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) { |
| 458 // We've reached the end of the file and we didn't know the total size | 456 // We've reached the end of the file and we didn't know the total size |
| 459 // before. Update the total size so Read()s past the end of the file will | 457 // before. Update the total size so Read()s past the end of the file will |
| 460 // fail like they would if we had known the file size at the beginning. | 458 // fail like they would if we had known the file size at the beginning. |
| 461 total_bytes_ = loader_->instance_size(); | 459 total_bytes_ = loader_->instance_size(); |
| 462 | 460 |
| 463 if (host() && total_bytes_ != kPositionNotSpecified) { | 461 if (total_bytes_ != kPositionNotSpecified) { |
| 464 host()->SetTotalBytes(total_bytes_); | 462 host_->SetTotalBytes(total_bytes_); |
| 465 host()->AddBufferedByteRange(loader_->first_byte_position(), | 463 host_->AddBufferedByteRange(loader_->first_byte_position(), |
| 466 total_bytes_); | 464 total_bytes_); |
| 467 } | 465 } |
| 468 } | 466 } |
| 469 ReadOperation::Run(read_op_.Pass(), bytes_read); | 467 ReadOperation::Run(read_op_.Pass(), bytes_read); |
| 470 } | 468 } |
| 471 | 469 |
| 472 void BufferedDataSource::LoadingStateChangedCallback( | 470 void BufferedDataSource::LoadingStateChangedCallback( |
| 473 BufferedResourceLoader::LoadingState state) { | 471 BufferedResourceLoader::LoadingState state) { |
| 474 DCHECK(render_loop_->BelongsToCurrentThread()); | 472 DCHECK(render_loop_->BelongsToCurrentThread()); |
| 475 | 473 |
| 476 if (assume_fully_buffered_) | 474 if (assume_fully_buffered_) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 503 | 501 |
| 504 if (assume_fully_buffered_) | 502 if (assume_fully_buffered_) |
| 505 return; | 503 return; |
| 506 | 504 |
| 507 // TODO(scherkus): we shouldn't have to lock to signal host(), see | 505 // TODO(scherkus): we shouldn't have to lock to signal host(), see |
| 508 // http://crbug.com/113712 for details. | 506 // http://crbug.com/113712 for details. |
| 509 base::AutoLock auto_lock(lock_); | 507 base::AutoLock auto_lock(lock_); |
| 510 if (stop_signal_received_) | 508 if (stop_signal_received_) |
| 511 return; | 509 return; |
| 512 | 510 |
| 513 ReportOrQueueBufferedBytes(loader_->first_byte_position(), position); | 511 host_->AddBufferedByteRange(loader_->first_byte_position(), position); |
| 514 } | |
| 515 | |
| 516 void BufferedDataSource::ReportOrQueueBufferedBytes(int64 start, int64 end) { | |
| 517 if (host()) | |
| 518 host()->AddBufferedByteRange(start, end); | |
| 519 else | |
| 520 queued_buffered_byte_ranges_.Add(start, end); | |
| 521 } | |
| 522 | |
| 523 void BufferedDataSource::UpdateHostState_Locked() { | |
| 524 lock_.AssertAcquired(); | |
| 525 | |
| 526 if (!host()) | |
| 527 return; | |
| 528 | |
| 529 for (size_t i = 0; i < queued_buffered_byte_ranges_.size(); ++i) { | |
| 530 host()->AddBufferedByteRange(queued_buffered_byte_ranges_.start(i), | |
| 531 queued_buffered_byte_ranges_.end(i)); | |
| 532 } | |
| 533 queued_buffered_byte_ranges_.clear(); | |
| 534 | |
| 535 if (total_bytes_ == kPositionNotSpecified) | |
| 536 return; | |
| 537 | |
| 538 host()->SetTotalBytes(total_bytes_); | |
| 539 | |
| 540 if (assume_fully_buffered_) | |
| 541 host()->AddBufferedByteRange(0, total_bytes_); | |
| 542 } | 512 } |
| 543 | 513 |
| 544 void BufferedDataSource::UpdateDeferStrategy(bool paused) { | 514 void BufferedDataSource::UpdateDeferStrategy(bool paused) { |
| 545 // 200 responses end up not being reused to satisfy future range requests, | 515 // 200 responses end up not being reused to satisfy future range requests, |
| 546 // and we don't want to get too far ahead of the read-head (and thus require | 516 // and we don't want to get too far ahead of the read-head (and thus require |
| 547 // a restart), so keep to the thresholds. | 517 // a restart), so keep to the thresholds. |
| 548 if (!loader_->range_supported()) { | 518 if (!loader_->range_supported()) { |
| 549 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); | 519 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); |
| 550 return; | 520 return; |
| 551 } | 521 } |
| 552 | 522 |
| 553 // If the playback has started (at which point the preload value is ignored) | 523 // If the playback has started (at which point the preload value is ignored) |
| 554 // and we're paused, then try to load as much as possible (the loader will | 524 // and we're paused, then try to load as much as possible (the loader will |
| 555 // fall back to kCapacityDefer if it knows the current response won't be | 525 // fall back to kCapacityDefer if it knows the current response won't be |
| 556 // useful from the cache in the future). | 526 // useful from the cache in the future). |
| 557 if (media_has_played_ && paused) { | 527 if (media_has_played_ && paused) { |
| 558 loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); | 528 loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); |
| 559 return; | 529 return; |
| 560 } | 530 } |
| 561 | 531 |
| 562 // If media is currently playing or the page indicated preload=auto, | 532 // If media is currently playing or the page indicated preload=auto, |
| 563 // use threshold strategy to enable/disable deferring when the buffer | 533 // use threshold strategy to enable/disable deferring when the buffer |
| 564 // is full/depleted. | 534 // is full/depleted. |
| 565 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); | 535 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); |
| 566 } | 536 } |
| 567 | 537 |
| 568 } // namespace content | 538 } // namespace content |
| OLD | NEW |