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) { |
| 103 DCHECK(host_); |
101 DCHECK(!downloading_cb_.is_null()); | 104 DCHECK(!downloading_cb_.is_null()); |
102 } | 105 } |
103 | 106 |
104 BufferedDataSource::~BufferedDataSource() {} | 107 BufferedDataSource::~BufferedDataSource() {} |
105 | 108 |
106 // A factory method to create BufferedResourceLoader using the read parameters. | 109 // A factory method to create BufferedResourceLoader using the read parameters. |
107 // This method can be overridden to inject mock BufferedResourceLoader object | 110 // This method can be overridden to inject mock BufferedResourceLoader object |
108 // for testing purpose. | 111 // for testing purpose. |
109 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( | 112 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( |
110 int64 first_byte_position, int64 last_byte_position) { | 113 int64 first_byte_position, int64 last_byte_position) { |
111 DCHECK(render_loop_->BelongsToCurrentThread()); | 114 DCHECK(render_loop_->BelongsToCurrentThread()); |
112 | 115 |
113 BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ? | 116 BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ? |
114 BufferedResourceLoader::kReadThenDefer : | 117 BufferedResourceLoader::kReadThenDefer : |
115 BufferedResourceLoader::kCapacityDefer; | 118 BufferedResourceLoader::kCapacityDefer; |
116 | 119 |
117 return new BufferedResourceLoader(url_, | 120 return new BufferedResourceLoader(url_, |
118 cors_mode_, | 121 cors_mode_, |
119 first_byte_position, | 122 first_byte_position, |
120 last_byte_position, | 123 last_byte_position, |
121 strategy, | 124 strategy, |
122 bitrate_, | 125 bitrate_, |
123 playback_rate_, | 126 playback_rate_, |
124 media_log_.get()); | 127 media_log_.get()); |
125 } | 128 } |
126 | 129 |
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( | 130 void BufferedDataSource::Initialize( |
137 const GURL& url, | 131 const GURL& url, |
138 BufferedResourceLoader::CORSMode cors_mode, | 132 BufferedResourceLoader::CORSMode cors_mode, |
139 const InitializeCB& init_cb) { | 133 const InitializeCB& init_cb) { |
140 DCHECK(render_loop_->BelongsToCurrentThread()); | 134 DCHECK(render_loop_->BelongsToCurrentThread()); |
141 DCHECK(!init_cb.is_null()); | 135 DCHECK(!init_cb.is_null()); |
142 DCHECK(!loader_.get()); | 136 DCHECK(!loader_.get()); |
143 url_ = url; | 137 url_ = url; |
144 cors_mode_ = cors_mode; | 138 cors_mode_ = cors_mode; |
145 | 139 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 loader_->Stop(); | 367 loader_->Stop(); |
374 } | 368 } |
375 | 369 |
376 // TODO(scherkus): we shouldn't have to lock to signal host(), see | 370 // TODO(scherkus): we shouldn't have to lock to signal host(), see |
377 // http://crbug.com/113712 for details. | 371 // http://crbug.com/113712 for details. |
378 base::AutoLock auto_lock(lock_); | 372 base::AutoLock auto_lock(lock_); |
379 if (stop_signal_received_) | 373 if (stop_signal_received_) |
380 return; | 374 return; |
381 | 375 |
382 if (success) { | 376 if (success) { |
383 UpdateHostState_Locked(); | 377 if (total_bytes_ != kPositionNotSpecified) { |
| 378 host_->SetTotalBytes(total_bytes_); |
| 379 if (assume_fully_buffered_) |
| 380 host_->AddBufferedByteRange(0, total_bytes_); |
| 381 } |
| 382 |
384 media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin()); | 383 media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin()); |
385 media_log_->SetBooleanProperty("passed_cors_access_check", | 384 media_log_->SetBooleanProperty("passed_cors_access_check", |
386 loader_->DidPassCORSAccessCheck()); | 385 loader_->DidPassCORSAccessCheck()); |
387 media_log_->SetBooleanProperty("range_header_supported", | 386 media_log_->SetBooleanProperty("range_header_supported", |
388 loader_->range_supported()); | 387 loader_->range_supported()); |
389 } | 388 } |
390 | 389 |
391 base::ResetAndReturn(&init_cb_).Run(success); | 390 base::ResetAndReturn(&init_cb_).Run(success); |
392 } | 391 } |
393 | 392 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 } | 452 } |
454 | 453 |
455 if (bytes_read > 0) { | 454 if (bytes_read > 0) { |
456 memcpy(read_op_->data(), intermediate_read_buffer_.get(), bytes_read); | 455 memcpy(read_op_->data(), intermediate_read_buffer_.get(), bytes_read); |
457 } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) { | 456 } 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 | 457 // 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 | 458 // 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. | 459 // fail like they would if we had known the file size at the beginning. |
461 total_bytes_ = loader_->instance_size(); | 460 total_bytes_ = loader_->instance_size(); |
462 | 461 |
463 if (host() && total_bytes_ != kPositionNotSpecified) { | 462 if (total_bytes_ != kPositionNotSpecified) { |
464 host()->SetTotalBytes(total_bytes_); | 463 host_->SetTotalBytes(total_bytes_); |
465 host()->AddBufferedByteRange(loader_->first_byte_position(), | 464 host_->AddBufferedByteRange(loader_->first_byte_position(), |
466 total_bytes_); | 465 total_bytes_); |
467 } | 466 } |
468 } | 467 } |
469 ReadOperation::Run(read_op_.Pass(), bytes_read); | 468 ReadOperation::Run(read_op_.Pass(), bytes_read); |
470 } | 469 } |
471 | 470 |
472 void BufferedDataSource::LoadingStateChangedCallback( | 471 void BufferedDataSource::LoadingStateChangedCallback( |
473 BufferedResourceLoader::LoadingState state) { | 472 BufferedResourceLoader::LoadingState state) { |
474 DCHECK(render_loop_->BelongsToCurrentThread()); | 473 DCHECK(render_loop_->BelongsToCurrentThread()); |
475 | 474 |
476 if (assume_fully_buffered_) | 475 if (assume_fully_buffered_) |
(...skipping 26 matching lines...) Expand all Loading... |
503 | 502 |
504 if (assume_fully_buffered_) | 503 if (assume_fully_buffered_) |
505 return; | 504 return; |
506 | 505 |
507 // TODO(scherkus): we shouldn't have to lock to signal host(), see | 506 // TODO(scherkus): we shouldn't have to lock to signal host(), see |
508 // http://crbug.com/113712 for details. | 507 // http://crbug.com/113712 for details. |
509 base::AutoLock auto_lock(lock_); | 508 base::AutoLock auto_lock(lock_); |
510 if (stop_signal_received_) | 509 if (stop_signal_received_) |
511 return; | 510 return; |
512 | 511 |
513 ReportOrQueueBufferedBytes(loader_->first_byte_position(), position); | 512 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 } | 513 } |
543 | 514 |
544 void BufferedDataSource::UpdateDeferStrategy(bool paused) { | 515 void BufferedDataSource::UpdateDeferStrategy(bool paused) { |
545 // 200 responses end up not being reused to satisfy future range requests, | 516 // 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 | 517 // 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. | 518 // a restart), so keep to the thresholds. |
548 if (!loader_->range_supported()) { | 519 if (!loader_->range_supported()) { |
549 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); | 520 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); |
550 return; | 521 return; |
551 } | 522 } |
552 | 523 |
553 // If the playback has started (at which point the preload value is ignored) | 524 // 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 | 525 // 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 | 526 // fall back to kCapacityDefer if it knows the current response won't be |
556 // useful from the cache in the future). | 527 // useful from the cache in the future). |
557 if (media_has_played_ && paused) { | 528 if (media_has_played_ && paused) { |
558 loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); | 529 loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); |
559 return; | 530 return; |
560 } | 531 } |
561 | 532 |
562 // If media is currently playing or the page indicated preload=auto, | 533 // If media is currently playing or the page indicated preload=auto, |
563 // use threshold strategy to enable/disable deferring when the buffer | 534 // use threshold strategy to enable/disable deferring when the buffer |
564 // is full/depleted. | 535 // is full/depleted. |
565 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); | 536 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); |
566 } | 537 } |
567 | 538 |
568 } // namespace content | 539 } // namespace content |
OLD | NEW |