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

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

Issue 248012: Change how <video> fetch a resource to make it friendly to sparse caching (Closed)
Patch Set: style Created 11 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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 #include "base/compiler_specific.h" 5 #include "base/compiler_specific.h"
6 #include "base/message_loop.h" 6 #include "base/message_loop.h"
7 #include "base/process_util.h" 7 #include "base/process_util.h"
8 #include "base/stl_util-inl.h" 8 #include "base/stl_util-inl.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "chrome/common/extensions/url_pattern.h" 10 #include "chrome/common/extensions/url_pattern.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 // BufferedResourceLoader 65 // BufferedResourceLoader
66 BufferedResourceLoader::BufferedResourceLoader( 66 BufferedResourceLoader::BufferedResourceLoader(
67 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory, 67 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory,
68 const GURL& url, 68 const GURL& url,
69 int64 first_byte_position, 69 int64 first_byte_position,
70 int64 last_byte_position) 70 int64 last_byte_position)
71 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)), 71 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)),
72 deferred_(false), 72 deferred_(false),
73 completed_(false), 73 completed_(false),
74 range_requested_(false), 74 range_requested_(false),
75 partial_response_(false),
75 bridge_factory_(bridge_factory), 76 bridge_factory_(bridge_factory),
76 url_(url), 77 url_(url),
77 first_byte_position_(first_byte_position), 78 first_byte_position_(first_byte_position),
78 last_byte_position_(last_byte_position), 79 last_byte_position_(last_byte_position),
79 start_callback_(NULL), 80 start_callback_(NULL),
80 bridge_(NULL), 81 bridge_(NULL),
81 offset_(0), 82 offset_(0),
82 content_length_(kPositionNotSpecified), 83 content_length_(kPositionNotSpecified),
83 instance_size_(kPositionNotSpecified), 84 instance_size_(kPositionNotSpecified),
84 read_callback_(NULL), 85 read_callback_(NULL),
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 // We make a strong assumption that when we reach here we have either 229 // We make a strong assumption that when we reach here we have either
229 // received a response from HTTP/HTTPS protocol or the request was 230 // received a response from HTTP/HTTPS protocol or the request was
230 // successful (in particular range request). So we only verify the partial 231 // successful (in particular range request). So we only verify the partial
231 // response for HTTP and HTTPS protocol. 232 // response for HTTP and HTTPS protocol.
232 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { 233 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) {
233 int error = net::OK; 234 int error = net::OK;
234 if (!info.headers) { 235 if (!info.headers) {
235 // We expect to receive headers because this is a HTTP or HTTPS protocol, 236 // We expect to receive headers because this is a HTTP or HTTPS protocol,
236 // if not report failure. 237 // if not report failure.
237 error = net::ERR_INVALID_RESPONSE; 238 error = net::ERR_INVALID_RESPONSE;
238 } else if (range_requested_) { 239 } else {
239 // If we have verified the partial response and it is correct, we will 240 if (info.headers->response_code() == kHttpPartialContent)
240 // return net::OK. 241 partial_response_ = true;
241 if (!VerifyPartialResponse(info)) 242
242 error = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE; 243 if (range_requested_ && partial_response_) {
243 } else if (info.headers->response_code() != kHttpOK) { 244 // If we have verified the partial response and it is correct, we will
244 // We didn't request a range but server didn't reply with "200 OK". 245 // return net::OK.
245 error = net::ERR_FAILED; 246 if (!VerifyPartialResponse(info))
247 error = net::ERR_INVALID_RESPONSE;
248 } else if (info.headers->response_code() != kHttpOK) {
249 // We didn't request a range but server didn't reply with "200 OK".
250 error = net::ERR_FAILED;
251 }
246 } 252 }
247 253
248 if (error != net::OK) { 254 if (error != net::OK) {
249 DoneStart(error); 255 DoneStart(error);
250 Stop(); 256 Stop();
251 return; 257 return;
252 } 258 }
259 } else {
260 // For any protocol other than HTTP and HTTPS, assume range request is
261 // always fulfilled.
262 partial_response_ = range_requested_;
253 } 263 }
254 264
255 // |info.content_length| can be -1, in that case |content_length_| is 265 // |info.content_length| can be -1, in that case |content_length_| is
256 // not specified and this is a streaming response. 266 // not specified and this is a streaming response.
257 content_length_ = info.content_length; 267 content_length_ = info.content_length;
258 268
259 // If we have not requested a range, then the size of the instance is equal 269 // If we have not requested a range, then the size of the instance is equal
260 // to the content length. 270 // to the content length.
261 if (!range_requested_) 271 if (!partial_response_)
262 instance_size_ = content_length_; 272 instance_size_ = content_length_;
263 273
264 // Calls with a successful response. 274 // Calls with a successful response.
265 DoneStart(net::OK); 275 DoneStart(net::OK);
266 } 276 }
267 277
268 void BufferedResourceLoader::OnReceivedData(const char* data, int len) { 278 void BufferedResourceLoader::OnReceivedData(const char* data, int len) {
269 DCHECK(bridge_.get()); 279 DCHECK(bridge_.get());
270 280
271 // If this loader has been stopped, |buffer_| would be destroyed. 281 // If this loader has been stopped, |buffer_| would be destroyed.
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 last_offset_ = 0; 421 last_offset_ = 0;
412 } 422 }
413 423
414 void BufferedResourceLoader::DoneStart(int error) { 424 void BufferedResourceLoader::DoneStart(int error) {
415 start_callback_->RunWithParams(Tuple1<int>(error)); 425 start_callback_->RunWithParams(Tuple1<int>(error));
416 start_callback_.reset(); 426 start_callback_.reset();
417 } 427 }
418 428
419 bool BufferedResourceLoader::VerifyPartialResponse( 429 bool BufferedResourceLoader::VerifyPartialResponse(
420 const ResourceLoaderBridge::ResponseInfo& info) { 430 const ResourceLoaderBridge::ResponseInfo& info) {
421 if (info.headers->response_code() != kHttpPartialContent)
422 return false;
423
424 int64 first_byte_position, last_byte_position, instance_size; 431 int64 first_byte_position, last_byte_position, instance_size;
425 if (!info.headers->GetContentRange(&first_byte_position, 432 if (!info.headers->GetContentRange(&first_byte_position,
426 &last_byte_position, 433 &last_byte_position,
427 &instance_size)) { 434 &instance_size)) {
428 return false; 435 return false;
429 } 436 }
430 437
431 if (instance_size != kPositionNotSpecified) 438 if (instance_size != kPositionNotSpecified)
432 instance_size_ = instance_size; 439 instance_size_ = instance_size;
433 440
(...skipping 14 matching lines...) Expand all
448 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) 455 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory)
449 : total_bytes_(kPositionNotSpecified), 456 : total_bytes_(kPositionNotSpecified),
450 streaming_(false), 457 streaming_(false),
451 bridge_factory_(bridge_factory), 458 bridge_factory_(bridge_factory),
452 loader_(NULL), 459 loader_(NULL),
453 initialize_callback_(NULL), 460 initialize_callback_(NULL),
454 read_callback_(NULL), 461 read_callback_(NULL),
455 read_position_(0), 462 read_position_(0),
456 read_size_(0), 463 read_size_(0),
457 read_buffer_(NULL), 464 read_buffer_(NULL),
458 initial_response_received_(false),
459 probe_response_received_(false),
460 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), 465 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]),
461 intermediate_read_buffer_size_(kInitialReadBufferSize), 466 intermediate_read_buffer_size_(kInitialReadBufferSize),
462 render_loop_(render_loop), 467 render_loop_(render_loop),
463 stopped_(false), 468 stopped_(false),
464 stop_task_finished_(false) { 469 stop_task_finished_(false) {
465 } 470 }
466 471
467 BufferedDataSource::~BufferedDataSource() { 472 BufferedDataSource::~BufferedDataSource() {
468 } 473 }
469 474
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 549
545 bool BufferedDataSource::IsStreaming() { 550 bool BufferedDataSource::IsStreaming() {
546 return streaming_; 551 return streaming_;
547 } 552 }
548 553
549 ///////////////////////////////////////////////////////////////////////////// 554 /////////////////////////////////////////////////////////////////////////////
550 // BufferedDataSource, render thread tasks 555 // BufferedDataSource, render thread tasks
551 void BufferedDataSource::InitializeTask() { 556 void BufferedDataSource::InitializeTask() {
552 DCHECK(MessageLoop::current() == render_loop_); 557 DCHECK(MessageLoop::current() == render_loop_);
553 DCHECK(!loader_.get()); 558 DCHECK(!loader_.get());
554 DCHECK(!probe_loader_.get());
555 559
556 // Kick starts the watch dog task that will handle connection timeout. 560 // Kick starts the watch dog task that will handle connection timeout.
557 // We run the watch dog 2 times faster the actual timeout so as to catch 561 // We run the watch dog 2 times faster the actual timeout so as to catch
558 // the timeout more accurately. 562 // the timeout more accurately.
559 watch_dog_timer_.Start( 563 watch_dog_timer_.Start(
560 GetTimeoutMilliseconds() / 2, 564 GetTimeoutMilliseconds() / 2,
561 this, 565 this,
562 &BufferedDataSource::WatchDogTask); 566 &BufferedDataSource::WatchDogTask);
563 567
564 // Creates a new resource loader with the full range and a probe resource 568 // Fetch only first 1024 bytes as this usually covers the header portion
565 // loader. Creates a probe resource loader to make sure the server supports 569 // of a media file that gives enough information about the codecs, etc.
566 // partial range request. 570 // This also serve as a probe to determine server capability to serve
567 // TODO(hclam): Only request 1 byte for this probe request, it may be useful 571 // range request.
568 // that we perform a suffix range request and fetch the index. That way we 572 // TODO(hclam): Do some experiments for the best approach.
569 // can minimize the number of requests made. 573 loader_ = CreateLoader(0, 1024);
scherkus (not reviewing) 2009/09/29 23:10:34 ok.. might have to request this be made a constant
570 loader_ = CreateLoader(-1, -1);
571 probe_loader_ = CreateLoader(1, 1);
572
573 loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback)); 574 loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback));
574 probe_loader_->Start(
575 NewCallback(this, &BufferedDataSource::ProbeStartCallback));
576 } 575 }
577 576
578 void BufferedDataSource::ReadTask( 577 void BufferedDataSource::ReadTask(
579 int64 position, int read_size, uint8* buffer, 578 int64 position, int read_size, uint8* buffer,
580 media::DataSource::ReadCallback* read_callback) { 579 media::DataSource::ReadCallback* read_callback) {
581 DCHECK(MessageLoop::current() == render_loop_); 580 DCHECK(MessageLoop::current() == render_loop_);
582 581
583 // If StopTask() was executed we should return immediately. We check this 582 // If StopTask() was executed we should return immediately. We check this
584 // variable to prevent doing any actual work after clean up was done. We do 583 // variable to prevent doing any actual work after clean up was done. We do
585 // not check |stopped_| because anything use of it has to be within |lock_| 584 // not check |stopped_| because anything use of it has to be within |lock_|
(...skipping 19 matching lines...) Expand all
605 void BufferedDataSource::StopTask() { 604 void BufferedDataSource::StopTask() {
606 DCHECK(MessageLoop::current() == render_loop_); 605 DCHECK(MessageLoop::current() == render_loop_);
607 606
608 // Stop the watch dog. 607 // Stop the watch dog.
609 watch_dog_timer_.Stop(); 608 watch_dog_timer_.Stop();
610 609
611 // We just need to stop the loader, so it stops activity. 610 // We just need to stop the loader, so it stops activity.
612 if (loader_.get()) 611 if (loader_.get())
613 loader_->Stop(); 612 loader_->Stop();
614 613
615 // If the probe request is still active, stop it too.
616 if (probe_loader_.get())
617 probe_loader_->Stop();
618
619 // Reset the parameters of the current read request. 614 // Reset the parameters of the current read request.
620 read_callback_.reset(); 615 read_callback_.reset();
621 read_position_ = 0; 616 read_position_ = 0;
622 read_size_ = 0; 617 read_size_ = 0;
623 read_buffer_ = 0; 618 read_buffer_ = 0;
624 read_submitted_time_ = base::Time(); 619 read_submitted_time_ = base::Time();
625 read_attempts_ = 0; 620 read_attempts_ = 0;
626 621
627 // Signal that stop task has finished execution. 622 // Signal that stop task has finished execution.
628 stop_task_finished_ = true; 623 stop_task_finished_ = true;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 // this object when Stop() method is ever called. Locking this method is safe 719 // this object when Stop() method is ever called. Locking this method is safe
725 // because |lock_| is only acquired in tasks on render thread. 720 // because |lock_| is only acquired in tasks on render thread.
726 AutoLock auto_lock(lock_); 721 AutoLock auto_lock(lock_);
727 if (stopped_) 722 if (stopped_)
728 return; 723 return;
729 724
730 if (error != net::OK) { 725 if (error != net::OK) {
731 // TODO(hclam): In case of failure, we can retry several times. 726 // TODO(hclam): In case of failure, we can retry several times.
732 host()->SetError(media::PIPELINE_ERROR_NETWORK); 727 host()->SetError(media::PIPELINE_ERROR_NETWORK);
733 DCHECK(loader_.get()); 728 DCHECK(loader_.get());
734 DCHECK(probe_loader_.get());
735 loader_->Stop(); 729 loader_->Stop();
736 probe_loader_->Stop();
737 DoneInitialization(); 730 DoneInitialization();
738 return; 731 return;
739 } 732 }
740 733
734 // TODO(hclam): Needs more thinking about supporting servers without range
735 // request or their partial response is not complete.
741 total_bytes_ = loader_->instance_size(); 736 total_bytes_ = loader_->instance_size();
742 if (total_bytes_ >= 0) { 737 if (total_bytes_ >= 0 && loader_->partial_response()) {
743 // This value governs the range that we can seek to. 738 // This value governs the range that we can seek to.
744 // TODO(hclam): Report the correct value of buffered bytes. 739 // TODO(hclam): Report the correct value of buffered bytes.
745 host()->SetTotalBytes(total_bytes_); 740 host()->SetTotalBytes(total_bytes_);
746 host()->SetBufferedBytes(total_bytes_); 741 host()->SetBufferedBytes(total_bytes_);
747 } else { 742 } else {
748 // If the server didn't reply with a content length, it is likely this 743 // If the server didn't reply with an instance size, it is likely this
749 // is a streaming response. 744 // is a streaming response.
750 streaming_ = true; 745 streaming_ = true;
751 host()->SetStreaming(true); 746 host()->SetStreaming(true);
752 } 747 }
753 748
754 // Currently, only files can be used reliably w/o a network. 749 // Currently, only files can be used reliably w/o a network.
755 host()->SetLoaded(url_.SchemeIsFile()); 750 host()->SetLoaded(url_.SchemeIsFile());
756 751 DoneInitialization();
757 initial_response_received_ = true;
758 if (probe_response_received_)
759 DoneInitialization();
760 }
761
762 void BufferedDataSource::ProbeStartCallback(int error) {
763 DCHECK(MessageLoop::current() == render_loop_);
764
765 // We need to prevent calling to filter host and running the callback if
766 // we have received the stop signal. We need to lock down the whole callback
767 // method to prevent bad things from happening. The reason behind this is
768 // that we cannot guarantee tasks on render thread have completely stopped
769 // when we receive the Stop() method call. The only way to solve this is to
770 // let tasks on render thread to run but make sure they don't call outside
771 // this object when Stop() method is ever called. Locking this method is safe
772 // because |lock_| is only acquired in tasks on render thread.
773 AutoLock auto_lock(lock_);
774 if (stopped_)
775 return;
776
777 if (error != net::OK) {
778 streaming_ = true;
779 host()->SetStreaming(true);
780 }
781
782 DCHECK(probe_loader_.get());
783 probe_loader_->Stop();
784 probe_response_received_ = true;
785 if (initial_response_received_)
786 DoneInitialization();
787 } 752 }
788 753
789 void BufferedDataSource::PartialReadStartCallback(int error) { 754 void BufferedDataSource::PartialReadStartCallback(int error) {
790 DCHECK(MessageLoop::current() == render_loop_); 755 DCHECK(MessageLoop::current() == render_loop_);
791 DCHECK(loader_.get()); 756 DCHECK(loader_.get());
792 757
793 if (error == net::OK) { 758 // This callback method is invoked after we have verified the server has
794 // Once the range request has start successfully, we can proceed with 759 // range request capability, so as a safety guard verify again the response
760 // is partial.
761 if (error == net::OK && loader_->partial_response()) {
762 // Once the range request has started successfully, we can proceed with
795 // reading from it. 763 // reading from it.
796 ReadInternal(); 764 ReadInternal();
797 } else { 765 } else {
798 loader_->Stop(); 766 loader_->Stop();
799 767
800 // We need to prevent calling to filter host and running the callback if 768 // We need to prevent calling to filter host and running the callback if
801 // we have received the stop signal. We need to lock down the whole callback 769 // we have received the stop signal. We need to lock down the whole callback
802 // method to prevent bad things from happening. The reason behind this is 770 // method to prevent bad things from happening. The reason behind this is
803 // that we cannot guarantee tasks on render thread have completely stopped 771 // that we cannot guarantee tasks on render thread have completely stopped
804 // when we receive the Stop() method call. So only way to solve this is to 772 // when we receive the Stop() method call. So only way to solve this is to
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 render_loop_->PostTask(FROM_HERE, 818 render_loop_->PostTask(FROM_HERE,
851 NewRunnableMethod(this, &BufferedDataSource::SwapLoaderTask, 819 NewRunnableMethod(this, &BufferedDataSource::SwapLoaderTask,
852 CreateLoader(read_position_, -1))); 820 CreateLoader(read_position_, -1)));
853 } else { 821 } else {
854 loader_->Stop(); 822 loader_->Stop();
855 DoneRead(error); 823 DoneRead(error);
856 } 824 }
857 } 825 }
858 826
859 } // namespace webkit_glue 827 } // namespace webkit_glue
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698