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

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

Issue 10692106: Split BufferedResourceLoader's network callback into separate loading state and progress callbacks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: trying again Created 8 years, 5 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
« no previous file with comments | « webkit/media/buffered_data_source.h ('k') | webkit/media/buffered_data_source_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/media/buffered_data_source.h" 5 #include "webkit/media/buffered_data_source.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "media/base/media_log.h" 9 #include "media/base/media_log.h"
10 #include "net/base/net_errors.h" 10 #include "net/base/net_errors.h"
11 11
12 using WebKit::WebFrame; 12 using WebKit::WebFrame;
13 13
14 namespace { 14 namespace {
15 15
16 // BufferedDataSource has an intermediate buffer, this value governs the initial 16 // BufferedDataSource has an intermediate buffer, this value governs the initial
17 // size of that buffer. It is set to 32KB because this is a typical read size 17 // size of that buffer. It is set to 32KB because this is a typical read size
18 // of FFmpeg. 18 // of FFmpeg.
19 const int kInitialReadBufferSize = 32768; 19 const int kInitialReadBufferSize = 32768;
20 20
21 // Number of cache misses we allow for a single Read() before signaling an 21 // Number of cache misses we allow for a single Read() before signaling an
22 // error. 22 // error.
23 const int kNumCacheMissRetries = 3; 23 const int kNumCacheMissRetries = 3;
24 24
25 } // namespace 25 } // namespace
26 26
27 namespace webkit_media { 27 namespace webkit_media {
28 28
29 // Non-HTTP resources are assumed to be fully loaded so we ignore any
30 // loading/progress related callbacks.
31 static void NonHttpLoadingStateChangedCallback(
32 BufferedResourceLoader::LoadingState) {
33 }
34 static void NonHttpProgressCallback(int64) {}
35
29 BufferedDataSource::BufferedDataSource( 36 BufferedDataSource::BufferedDataSource(
30 MessageLoop* render_loop, 37 MessageLoop* render_loop,
31 WebFrame* frame, 38 WebFrame* frame,
32 media::MediaLog* media_log, 39 media::MediaLog* media_log,
33 const DownloadingCB& downloading_cb) 40 const DownloadingCB& downloading_cb)
34 : cors_mode_(BufferedResourceLoader::kUnspecified), 41 : cors_mode_(BufferedResourceLoader::kUnspecified),
35 total_bytes_(kPositionNotSpecified), 42 total_bytes_(kPositionNotSpecified),
36 buffered_bytes_(0), 43 buffered_bytes_(0),
37 streaming_(false), 44 streaming_(false),
38 frame_(frame), 45 frame_(frame),
39 is_downloading_data_(false),
40 read_size_(0), 46 read_size_(0),
41 read_buffer_(NULL), 47 read_buffer_(NULL),
42 last_read_start_(0), 48 last_read_start_(0),
43 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), 49 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]),
44 intermediate_read_buffer_size_(kInitialReadBufferSize), 50 intermediate_read_buffer_size_(kInitialReadBufferSize),
45 render_loop_(render_loop), 51 render_loop_(render_loop),
46 stop_signal_received_(false), 52 stop_signal_received_(false),
47 stopped_on_render_loop_(false), 53 stopped_on_render_loop_(false),
48 media_has_played_(false), 54 media_has_played_(false),
49 preload_(AUTO), 55 preload_(AUTO),
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 cors_mode_ = cors_mode; 104 cors_mode_ = cors_mode;
99 105
100 initialize_cb_ = initialize_cb; 106 initialize_cb_ = initialize_cb;
101 107
102 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { 108 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) {
103 // Do an unbounded range request starting at the beginning. If the server 109 // Do an unbounded range request starting at the beginning. If the server
104 // responds with 200 instead of 206 we'll fall back into a streaming mode. 110 // responds with 200 instead of 206 we'll fall back into a streaming mode.
105 loader_.reset(CreateResourceLoader(0, kPositionNotSpecified)); 111 loader_.reset(CreateResourceLoader(0, kPositionNotSpecified));
106 loader_->Start( 112 loader_->Start(
107 base::Bind(&BufferedDataSource::HttpInitialStartCallback, this), 113 base::Bind(&BufferedDataSource::HttpInitialStartCallback, this),
108 base::Bind(&BufferedDataSource::NetworkEventCallback, this), 114 base::Bind(&BufferedDataSource::HttpLoadingStateChangedCallback, this),
115 base::Bind(&BufferedDataSource::HttpProgressCallback, this),
109 frame_); 116 frame_);
110 return; 117 return;
111 } 118 }
112 119
113 // For all other protocols, assume they support range request. We fetch 120 // For all other protocols, assume they support range request. We fetch
114 // the full range of the resource to obtain the instance size because 121 // the full range of the resource to obtain the instance size because
115 // we won't be served HTTP headers. 122 // we won't be served HTTP headers.
116 loader_.reset(CreateResourceLoader(kPositionNotSpecified, 123 loader_.reset(CreateResourceLoader(kPositionNotSpecified,
117 kPositionNotSpecified)); 124 kPositionNotSpecified));
118 loader_->Start( 125 loader_->Start(
119 base::Bind(&BufferedDataSource::NonHttpInitialStartCallback, this), 126 base::Bind(&BufferedDataSource::NonHttpInitialStartCallback, this),
120 base::Bind(&BufferedDataSource::NetworkEventCallback, this), 127 base::Bind(&NonHttpLoadingStateChangedCallback),
128 base::Bind(&NonHttpProgressCallback),
121 frame_); 129 frame_);
122 } 130 }
123 131
124 void BufferedDataSource::SetPreload(Preload preload) { 132 void BufferedDataSource::SetPreload(Preload preload) {
125 DCHECK(MessageLoop::current() == render_loop_); 133 DCHECK(MessageLoop::current() == render_loop_);
126 preload_ = preload; 134 preload_ = preload;
127 } 135 }
128 136
129 bool BufferedDataSource::HasSingleOrigin() { 137 bool BufferedDataSource::HasSingleOrigin() {
130 DCHECK(MessageLoop::current() == render_loop_); 138 DCHECK(MessageLoop::current() == render_loop_);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 if (stopped_on_render_loop_) 270 if (stopped_on_render_loop_)
263 return; 271 return;
264 272
265 { 273 {
266 // If there's no outstanding read then return early. 274 // If there's no outstanding read then return early.
267 base::AutoLock auto_lock(lock_); 275 base::AutoLock auto_lock(lock_);
268 if (read_cb_.is_null()) 276 if (read_cb_.is_null())
269 return; 277 return;
270 } 278 }
271 279
280 // Start reading from where we last left off until the end of the resource.
272 loader_.reset( 281 loader_.reset(
273 CreateResourceLoader(last_read_start_, kPositionNotSpecified)); 282 CreateResourceLoader(last_read_start_, kPositionNotSpecified));
274 loader_->Start( 283 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) {
275 base::Bind(&BufferedDataSource::PartialReadStartCallback, this), 284 loader_->Start(
276 base::Bind(&BufferedDataSource::NetworkEventCallback, this), 285 base::Bind(&BufferedDataSource::PartialReadStartCallback, this),
277 frame_); 286 base::Bind(&BufferedDataSource::HttpLoadingStateChangedCallback, this),
287 base::Bind(&BufferedDataSource::HttpProgressCallback, this),
288 frame_);
289 } else {
290 loader_->Start(
291 base::Bind(&BufferedDataSource::NonHttpInitialStartCallback, this),
292 base::Bind(&NonHttpLoadingStateChangedCallback),
293 base::Bind(&NonHttpProgressCallback),
294 frame_);
295 }
278 } 296 }
279 297
280 void BufferedDataSource::SetPlaybackRateTask(float playback_rate) { 298 void BufferedDataSource::SetPlaybackRateTask(float playback_rate) {
281 DCHECK(MessageLoop::current() == render_loop_); 299 DCHECK(MessageLoop::current() == render_loop_);
282 DCHECK(loader_.get()); 300 DCHECK(loader_.get());
283 301
284 if (playback_rate != 0) 302 if (playback_rate != 0)
285 media_has_played_ = true; 303 media_has_played_ = true;
286 304
287 playback_rate_ = playback_rate; 305 playback_rate_ = playback_rate;
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 cache_miss_retries_left_--; 529 cache_miss_retries_left_--;
512 render_loop_->PostTask(FROM_HERE, 530 render_loop_->PostTask(FROM_HERE,
513 base::Bind(&BufferedDataSource::RestartLoadingTask, this)); 531 base::Bind(&BufferedDataSource::RestartLoadingTask, this));
514 return; 532 return;
515 } 533 }
516 534
517 // Fall through to signal a read error. 535 // Fall through to signal a read error.
518 bytes_read = kReadError; 536 bytes_read = kReadError;
519 } 537 }
520 538
521 // We need to prevent calling to filter host and running the callback if 539 // TODO(scherkus): we shouldn't have to lock to signal host(), see
522 // we have received the stop signal. We need to lock down the whole callback 540 // http://crbug.com/113712 for details.
523 // method to prevent bad things from happening. The reason behind this is
524 // that we cannot guarantee tasks on render thread have completely stopped
525 // when we receive the Stop() method call. So only way to solve this is to
526 // let tasks on render thread to run but make sure they don't call outside
527 // this object when Stop() method is ever called. Locking this method is safe
528 // because |lock_| is only acquired in tasks on render thread.
529 base::AutoLock auto_lock(lock_); 541 base::AutoLock auto_lock(lock_);
530 if (stop_signal_received_) 542 if (stop_signal_received_)
531 return; 543 return;
532 544
533 if (bytes_read > 0) { 545 if (bytes_read > 0) {
534 memcpy(read_buffer_, intermediate_read_buffer_.get(), bytes_read); 546 memcpy(read_buffer_, intermediate_read_buffer_.get(), bytes_read);
535 } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) { 547 } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) {
536 // We've reached the end of the file and we didn't know the total size 548 // We've reached the end of the file and we didn't know the total size
537 // before. Update the total size so Read()s past the end of the file will 549 // before. Update the total size so Read()s past the end of the file will
538 // fail like they would if we had known the file size at the beginning. 550 // fail like they would if we had known the file size at the beginning.
539 total_bytes_ = loader_->instance_size(); 551 total_bytes_ = loader_->instance_size();
540 552
541 if (host() && total_bytes_ != kPositionNotSpecified) { 553 if (host() && total_bytes_ != kPositionNotSpecified) {
542 host()->SetTotalBytes(total_bytes_); 554 host()->SetTotalBytes(total_bytes_);
543 host()->AddBufferedByteRange(loader_->first_byte_position(), 555 host()->AddBufferedByteRange(loader_->first_byte_position(),
544 total_bytes_); 556 total_bytes_);
545 } 557 }
546 } 558 }
547 DoneRead_Locked(bytes_read); 559 DoneRead_Locked(bytes_read);
548 } 560 }
549 561
550 void BufferedDataSource::NetworkEventCallback() { 562 void BufferedDataSource::HttpLoadingStateChangedCallback(
563 BufferedResourceLoader::LoadingState state) {
551 DCHECK(MessageLoop::current() == render_loop_); 564 DCHECK(MessageLoop::current() == render_loop_);
552 DCHECK(loader_.get()); 565 DCHECK(url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme));
553 566
554 // In case of non-HTTP request we don't need to report network events, 567 bool is_downloading_data;
555 // so return immediately. 568 switch (state) {
556 if (!url_.SchemeIs(kHttpScheme) && !url_.SchemeIs(kHttpsScheme)) 569 case BufferedResourceLoader::kLoading:
557 return; 570 is_downloading_data = true;
571 break;
572 case BufferedResourceLoader::kLoadingDeferred:
573 is_downloading_data = false;
574 break;
558 575
559 downloading_cb_.Run(loader_->is_downloading_data()); 576 // TODO(scherkus): we don't signal network activity changes when loads
577 // complete or fail to preserve existing behaviour when deferring is
578 // toggled, however we considering changing DownloadingCB to also
579 // propagate loading state. For example there isn't any signal today
580 // to notify the client that loading has failed/finished (we only get
581 // errors on subsequent reads).
582 case BufferedResourceLoader::kLoadingFailed:
583 case BufferedResourceLoader::kLoadingFinished:
584 return;
585 }
560 586
561 int64 current_buffered_position = loader_->GetBufferedPosition(); 587 downloading_cb_.Run(is_downloading_data);
588 }
562 589
563 // If we get an unspecified value, return immediately. 590 void BufferedDataSource::HttpProgressCallback(int64 position) {
564 if (current_buffered_position == kPositionNotSpecified) 591 DCHECK(MessageLoop::current() == render_loop_);
565 return; 592 DCHECK(url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme));
566 593
567 // We need to prevent calling to filter host and running the callback if 594 // TODO(scherkus): we shouldn't have to lock to signal host(), see
568 // we have received the stop signal. We need to lock down the whole callback 595 // http://crbug.com/113712 for details.
569 // method to prevent bad things from happening. The reason behind this is
570 // that we cannot guarantee tasks on render thread have completely stopped
571 // when we receive the Stop() method call. So only way to solve this is to
572 // let tasks on render thread to run but make sure they don't call outside
573 // this object when Stop() method is ever called. Locking this method is safe
574 // because |lock_| is only acquired in tasks on render thread.
575 base::AutoLock auto_lock(lock_); 596 base::AutoLock auto_lock(lock_);
576 if (stop_signal_received_) 597 if (stop_signal_received_)
577 return; 598 return;
578 599
579 int64 start = loader_->first_byte_position(); 600 if (host() && position > last_read_start_)
580 if (host() && current_buffered_position > start) 601 host()->AddBufferedByteRange(last_read_start_, position);
581 host()->AddBufferedByteRange(start, current_buffered_position);
582 } 602 }
583 603
584 void BufferedDataSource::UpdateHostState_Locked() { 604 void BufferedDataSource::UpdateHostState_Locked() {
585 // Called from various threads, under lock.
586 lock_.AssertAcquired(); 605 lock_.AssertAcquired();
587 606
588 if (!host()) 607 if (!host())
589 return; 608 return;
590 609
591 if (total_bytes_ != kPositionNotSpecified) 610 if (total_bytes_ != kPositionNotSpecified)
592 host()->SetTotalBytes(total_bytes_); 611 host()->SetTotalBytes(total_bytes_);
593 int64 start = loader_->first_byte_position(); 612 int64 start = loader_->first_byte_position();
594 if (buffered_bytes_ > start) 613 if (buffered_bytes_ > start)
595 host()->AddBufferedByteRange(start, buffered_bytes_); 614 host()->AddBufferedByteRange(start, buffered_bytes_);
596 } 615 }
597 616
598 } // namespace webkit_media 617 } // namespace webkit_media
OLDNEW
« no previous file with comments | « webkit/media/buffered_data_source.h ('k') | webkit/media/buffered_data_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698