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

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

Issue 10735016: Collapse HTTP and non-HTTP codepaths into single methods. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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
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 webkit_media { 14 namespace webkit_media {
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 static const int kInitialReadBufferSize = 32768; 19 static const int kInitialReadBufferSize = 32768;
20 20
21 // Number of cache misses we allow for a single Read() before signalling an 21 // Number of cache misses we allow for a single Read() before signalling an
22 // error. 22 // error.
23 static const int kNumCacheMissRetries = 3; 23 static const int kNumCacheMissRetries = 3;
24 24
25 // Non-HTTP resources are assumed to be fully loaded so we ignore any
26 // loading/progress related callbacks.
27 static void NonHttpLoadingCallback(BufferedResourceLoader::LoadingState) {}
28 static void NonHttpProgressCallback(int64) {}
29
30 BufferedDataSource::BufferedDataSource( 25 BufferedDataSource::BufferedDataSource(
31 MessageLoop* render_loop, 26 MessageLoop* render_loop,
32 WebFrame* frame, 27 WebFrame* frame,
33 media::MediaLog* media_log) 28 media::MediaLog* media_log)
34 : total_bytes_(kPositionNotSpecified), 29 : total_bytes_(kPositionNotSpecified),
35 buffered_bytes_(0), 30 buffered_bytes_(0),
36 streaming_(false), 31 streaming_(false),
37 frame_(frame), 32 frame_(frame),
38 loader_(NULL), 33 loader_(NULL),
39 is_downloading_data_(false), 34 is_downloading_data_(false),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 DCHECK(!initialize_cb.is_null()); 86 DCHECK(!initialize_cb.is_null());
92 DCHECK(!loader_.get()); 87 DCHECK(!loader_.get());
93 url_ = url; 88 url_ = url;
94 89
95 initialize_cb_ = initialize_cb; 90 initialize_cb_ = initialize_cb;
96 91
97 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { 92 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) {
98 // Do an unbounded range request starting at the beginning. If the server 93 // Do an unbounded range request starting at the beginning. If the server
99 // responds with 200 instead of 206 we'll fall back into a streaming mode. 94 // responds with 200 instead of 206 we'll fall back into a streaming mode.
100 loader_.reset(CreateResourceLoader(0, kPositionNotSpecified)); 95 loader_.reset(CreateResourceLoader(0, kPositionNotSpecified));
101 loader_->Start( 96 } else {
102 base::Bind(&BufferedDataSource::HttpInitialStartCallback, this), 97 // For all other protocols, assume they support range request. We fetch
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 s/support/don't support/?
scherkus (not reviewing) 2012/07/10 18:37:27 My memory is foggy but I believe it _is_ support b
103 base::Bind(&BufferedDataSource::HttpLoadingCallback, this), 98 // the full range of the resource to obtain the instance size because
104 base::Bind(&BufferedDataSource::HttpProgressCallback, this), 99 // we won't be served HTTP headers.
105 frame_); 100 loader_.reset(CreateResourceLoader(kPositionNotSpecified,
106 return; 101 kPositionNotSpecified));
107 } 102 }
108 103
109 // For all other protocols, assume they support range request. We fetch
110 // the full range of the resource to obtain the instance size because
111 // we won't be served HTTP headers.
112 loader_.reset(CreateResourceLoader(kPositionNotSpecified,
113 kPositionNotSpecified));
114 loader_->Start( 104 loader_->Start(
115 base::Bind(&BufferedDataSource::NonHttpInitialStartCallback, this), 105 base::Bind(&BufferedDataSource::StartCallback, this),
116 base::Bind(&NonHttpLoadingCallback), 106 base::Bind(&BufferedDataSource::LoadingCallback, this),
117 base::Bind(&NonHttpProgressCallback), 107 base::Bind(&BufferedDataSource::ProgressCallback, this),
118 frame_); 108 frame_);
119 } 109 }
120 110
121 void BufferedDataSource::SetPreload(Preload preload) { 111 void BufferedDataSource::SetPreload(Preload preload) {
122 DCHECK(MessageLoop::current() == render_loop_); 112 DCHECK(MessageLoop::current() == render_loop_);
123 preload_ = preload; 113 preload_ = preload;
124 } 114 }
125 115
126 bool BufferedDataSource::HasSingleOrigin() { 116 bool BufferedDataSource::HasSingleOrigin() {
127 DCHECK(MessageLoop::current() == render_loop_); 117 DCHECK(MessageLoop::current() == render_loop_);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 return; 246 return;
257 247
258 { 248 {
259 // If there's no outstanding read then return early. 249 // If there's no outstanding read then return early.
260 base::AutoLock auto_lock(lock_); 250 base::AutoLock auto_lock(lock_);
261 if (read_cb_.is_null()) 251 if (read_cb_.is_null())
262 return; 252 return;
263 } 253 }
264 254
265 // Start reading from where we last left off until the end of the resource. 255 // Start reading from where we last left off until the end of the resource.
266 loader_.reset( 256 loader_.reset(CreateResourceLoader(last_read_start_, kPositionNotSpecified));
267 CreateResourceLoader(last_read_start_, kPositionNotSpecified)); 257 loader_->Start(
268 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { 258 base::Bind(&BufferedDataSource::PartialReadStartCallback, this),
269 loader_->Start( 259 base::Bind(&BufferedDataSource::LoadingCallback, this),
270 base::Bind(&BufferedDataSource::PartialReadStartCallback, this), 260 base::Bind(&BufferedDataSource::ProgressCallback, this),
271 base::Bind(&BufferedDataSource::HttpLoadingCallback, this), 261 frame_);
272 base::Bind(&BufferedDataSource::HttpProgressCallback, this),
273 frame_);
274 } else {
275 loader_->Start(
276 base::Bind(&BufferedDataSource::NonHttpInitialStartCallback, this),
scherkus (not reviewing) 2012/07/06 16:28:02 I believe this was a bug! if for whatever reason
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 Worth a test?
scherkus (not reviewing) 2012/07/10 18:37:27 I'm going to prep a separate CL that I'll land bef
277 base::Bind(&NonHttpLoadingCallback),
278 base::Bind(&NonHttpProgressCallback),
279 frame_);
280 }
281 } 262 }
282 263
283 void BufferedDataSource::SetPlaybackRateTask(float playback_rate) { 264 void BufferedDataSource::SetPlaybackRateTask(float playback_rate) {
284 DCHECK(MessageLoop::current() == render_loop_); 265 DCHECK(MessageLoop::current() == render_loop_);
285 DCHECK(loader_.get()); 266 DCHECK(loader_.get());
286 267
287 if (playback_rate != 0) 268 if (playback_rate != 0)
288 media_has_played_ = true; 269 media_has_played_ = true;
289 270
290 playback_rate_ = playback_rate; 271 playback_rate_ = playback_rate;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 DCHECK(MessageLoop::current() == render_loop_); 334 DCHECK(MessageLoop::current() == render_loop_);
354 DCHECK(!initialize_cb_.is_null()); 335 DCHECK(!initialize_cb_.is_null());
355 lock_.AssertAcquired(); 336 lock_.AssertAcquired();
356 337
357 initialize_cb_.Run(status); 338 initialize_cb_.Run(status);
358 initialize_cb_.Reset(); 339 initialize_cb_.Reset();
359 } 340 }
360 341
361 ///////////////////////////////////////////////////////////////////////////// 342 /////////////////////////////////////////////////////////////////////////////
362 // BufferedResourceLoader callback methods. 343 // BufferedResourceLoader callback methods.
363 void BufferedDataSource::HttpInitialStartCallback( 344 void BufferedDataSource::StartCallback(
364 BufferedResourceLoader::Status status) { 345 BufferedResourceLoader::Status status) {
365 DCHECK(MessageLoop::current() == render_loop_); 346 DCHECK(MessageLoop::current() == render_loop_);
366 DCHECK(loader_.get()); 347 DCHECK(loader_.get());
367 348
368 bool initialize_cb_is_null = false; 349 bool initialize_cb_is_null = false;
369 { 350 {
370 base::AutoLock auto_lock(lock_); 351 base::AutoLock auto_lock(lock_);
371 initialize_cb_is_null = initialize_cb_.is_null(); 352 initialize_cb_is_null = initialize_cb_.is_null();
372 } 353 }
373 if (initialize_cb_is_null) { 354 if (initialize_cb_is_null) {
374 loader_->Stop(); 355 loader_->Stop();
375 return; 356 return;
376 } 357 }
377 358
378 bool success = status == BufferedResourceLoader::kOk; 359 bool success = false;
379 if (success) { 360 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) {
380 // TODO(hclam): Needs more thinking about supporting servers without range 361 // HTTP responses only require a successful response even if content length
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 I think you meant the "only" to bind to "HTTP resp
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 I think this if/else would be a lot clearer if you
scherkus (not reviewing) 2012/07/10 18:37:27 Done.
scherkus (not reviewing) 2012/07/10 18:37:27 Done.
381 // request or their partial response is not complete. 362 // isn't known at the time.
382 total_bytes_ = loader_->instance_size(); 363 if (status == BufferedResourceLoader::kOk) {
383 streaming_ = (total_bytes_ == kPositionNotSpecified) || 364 success = true;
384 !loader_->range_supported(); 365 total_bytes_ = loader_->instance_size();
366 streaming_ = (total_bytes_ == kPositionNotSpecified) ||
367 !loader_->range_supported();
368 }
385 } else { 369 } else {
386 // TODO(hclam): In case of failure, we can retry several times. 370 // Non-HTTP resources should be full responses with known content length.
371 if (status == BufferedResourceLoader::kOk &&
372 loader_->instance_size() != kPositionNotSpecified) {
373 success = true;
374 total_bytes_ = loader_->instance_size();
375 buffered_bytes_ = loader_->instance_size();
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 This is consistent with the "before" code, but is
scherkus (not reviewing) 2012/07/10 18:37:27 We currently lie for all non-HTTP protocols
376 }
377 }
378
379 if (!success) {
387 loader_->Stop(); 380 loader_->Stop();
388 } 381 }
389 382
390 // Reference to prevent destruction while inside the |initialize_cb_| 383 // TODO(scherkus): we shouldn't have to lock to signal host(), see
391 // call. This is a temporary fix to prevent crashes caused by holding the 384 // http://crbug.com/113712 for details.
392 // lock and running the destructor.
393 // TODO: Review locking in this class and figure out a way to run the callback
394 // w/o the lock.
395 scoped_refptr<BufferedDataSource> destruction_guard(this); 385 scoped_refptr<BufferedDataSource> destruction_guard(this);
396 { 386 {
397 // We need to prevent calling to filter host and running the callback if
398 // we have received the stop signal. We need to lock down the whole callback
399 // method to prevent bad things from happening. The reason behind this is
400 // that we cannot guarantee tasks on render thread have completely stopped
401 // when we receive the Stop() method call. The only way to solve this is to
402 // let tasks on render thread to run but make sure they don't call outside
403 // this object when Stop() method is ever called. Locking this method is
404 // safe because |lock_| is only acquired in tasks on render thread.
405 base::AutoLock auto_lock(lock_); 387 base::AutoLock auto_lock(lock_);
406 if (stop_signal_received_) 388 if (stop_signal_received_)
407 return; 389 return;
408 390
409 if (!success) { 391 if (!success) {
410 DoneInitialization_Locked(media::PIPELINE_ERROR_NETWORK);
411 return;
412 }
413
414 UpdateHostState_Locked();
415 DoneInitialization_Locked(media::PIPELINE_OK);
416 }
417 }
418
419 void BufferedDataSource::NonHttpInitialStartCallback(
420 BufferedResourceLoader::Status status) {
421 DCHECK(MessageLoop::current() == render_loop_);
422 DCHECK(loader_.get());
423
424 bool initialize_cb_is_null = false;
425 {
426 base::AutoLock auto_lock(lock_);
427 initialize_cb_is_null = initialize_cb_.is_null();
428 }
429 if (initialize_cb_is_null) {
430 loader_->Stop();
431 return;
432 }
433
434 int64 instance_size = loader_->instance_size();
435 bool success = status == BufferedResourceLoader::kOk &&
436 instance_size != kPositionNotSpecified;
437
438 if (success) {
439 total_bytes_ = instance_size;
440 buffered_bytes_ = total_bytes_;
441 } else {
442 loader_->Stop();
443 }
444
445 // Reference to prevent destruction while inside the |initialize_cb_|
446 // call. This is a temporary fix to prevent crashes caused by holding the
447 // lock and running the destructor.
448 // TODO: Review locking in this class and figure out a way to run the callback
449 // w/o the lock.
450 scoped_refptr<BufferedDataSource> destruction_guard(this);
451 {
452 // We need to prevent calling to filter host and running the callback if
453 // we have received the stop signal. We need to lock down the whole callback
454 // method to prevent bad things from happening. The reason behind this is
455 // that we cannot guarantee tasks on render thread have completely stopped
456 // when we receive the Stop() method call. The only way to solve this is to
457 // let tasks on render thread to run but make sure they don't call outside
458 // this object when Stop() method is ever called. Locking this method is
459 // safe because |lock_| is only acquired in tasks on render thread.
460 base::AutoLock auto_lock(lock_);
461 if (stop_signal_received_ || initialize_cb_.is_null())
462 return;
463
464 if (!success) {
465 DoneInitialization_Locked(media::PIPELINE_ERROR_NETWORK); 392 DoneInitialization_Locked(media::PIPELINE_ERROR_NETWORK);
466 return; 393 return;
467 } 394 }
468 395
469 UpdateHostState_Locked(); 396 UpdateHostState_Locked();
470 DoneInitialization_Locked(media::PIPELINE_OK); 397 DoneInitialization_Locked(media::PIPELINE_OK);
471 } 398 }
472 } 399 }
473 400
474 void BufferedDataSource::PartialReadStartCallback( 401 void BufferedDataSource::PartialReadStartCallback(
475 BufferedResourceLoader::Status status) { 402 BufferedResourceLoader::Status status) {
476 DCHECK(MessageLoop::current() == render_loop_); 403 DCHECK(MessageLoop::current() == render_loop_);
477 DCHECK(loader_.get()); 404 DCHECK(loader_.get());
478 405
479 if (status == BufferedResourceLoader::kOk) { 406 if (status == BufferedResourceLoader::kOk) {
480 // Once the request has started successfully, we can proceed with 407 // Once the request has started successfully, we can proceed with
481 // reading from it. 408 // reading from it.
482 ReadInternal(); 409 ReadInternal();
483 return; 410 return;
484 } 411 }
485 412
486 // Stop the resource loader since we have received an error. 413 // Stop the resource loader since we have received an error.
487 loader_->Stop(); 414 loader_->Stop();
488 415
489 // We need to prevent calling to filter host and running the callback if 416 // TODO(scherkus): we shouldn't have to lock to signal host(), see
490 // we have received the stop signal. We need to lock down the whole callback 417 // http://crbug.com/113712 for details.
491 // method to prevent bad things from happening. The reason behind this is
492 // that we cannot guarantee tasks on render thread have completely stopped
493 // when we receive the Stop() method call. So only way to solve this is to
494 // let tasks on render thread to run but make sure they don't call outside
495 // this object when Stop() method is ever called. Locking this method is
496 // safe because |lock_| is only acquired in tasks on render thread.
497 base::AutoLock auto_lock(lock_); 418 base::AutoLock auto_lock(lock_);
498 if (stop_signal_received_) 419 if (stop_signal_received_)
499 return; 420 return;
500 DoneRead_Locked(kReadError); 421 DoneRead_Locked(kReadError);
501 } 422 }
502 423
503 void BufferedDataSource::ReadCallback( 424 void BufferedDataSource::ReadCallback(
504 BufferedResourceLoader::Status status, 425 BufferedResourceLoader::Status status,
505 int bytes_read) { 426 int bytes_read) {
506 DCHECK(MessageLoop::current() == render_loop_); 427 DCHECK(MessageLoop::current() == render_loop_);
(...skipping 29 matching lines...) Expand all
536 total_bytes_ = loader_->instance_size(); 457 total_bytes_ = loader_->instance_size();
537 458
538 if (host() && total_bytes_ != kPositionNotSpecified) { 459 if (host() && total_bytes_ != kPositionNotSpecified) {
539 host()->SetTotalBytes(total_bytes_); 460 host()->SetTotalBytes(total_bytes_);
540 host()->AddBufferedByteRange(last_read_start_, total_bytes_); 461 host()->AddBufferedByteRange(last_read_start_, total_bytes_);
541 } 462 }
542 } 463 }
543 DoneRead_Locked(bytes_read); 464 DoneRead_Locked(bytes_read);
544 } 465 }
545 466
546 void BufferedDataSource::HttpLoadingCallback( 467 void BufferedDataSource::LoadingCallback(
547 BufferedResourceLoader::LoadingState state) { 468 BufferedResourceLoader::LoadingState state) {
548 DCHECK(MessageLoop::current() == render_loop_); 469 DCHECK(MessageLoop::current() == render_loop_);
549 DCHECK(url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)); 470
471 // We assume non-HTTP resources are fully loaded: ignore any udpates.
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 udpates
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 Can we DCHECK the assumption?
scherkus (not reviewing) 2012/07/10 18:37:27 Done.
scherkus (not reviewing) 2012/07/10 18:37:27 I've switched to using assume_fully_buffered_ sinc
472 if (!url_.SchemeIs(kHttpScheme) && !url_.SchemeIs(kHttpsScheme))
473 return;
550 474
551 // TODO(scherkus): we shouldn't have to lock to signal host(), see 475 // TODO(scherkus): we shouldn't have to lock to signal host(), see
552 // http://crbug.com/113712 for details. 476 // http://crbug.com/113712 for details.
553 base::AutoLock auto_lock(lock_); 477 base::AutoLock auto_lock(lock_);
554 if (stop_signal_received_) 478 if (stop_signal_received_)
555 return; 479 return;
556 480
557 bool is_downloading_data; 481 bool is_downloading_data;
558 switch (state) { 482 switch (state) {
559 case BufferedResourceLoader::kLoading: 483 case BufferedResourceLoader::kLoading:
(...skipping 13 matching lines...) Expand all
573 return; 497 return;
574 } 498 }
575 499
576 if (is_downloading_data != is_downloading_data_) { 500 if (is_downloading_data != is_downloading_data_) {
577 is_downloading_data_ = is_downloading_data; 501 is_downloading_data_ = is_downloading_data;
578 if (host()) 502 if (host())
579 host()->SetNetworkActivity(is_downloading_data); 503 host()->SetNetworkActivity(is_downloading_data);
580 } 504 }
581 } 505 }
582 506
583 void BufferedDataSource::HttpProgressCallback(int64 position) { 507 void BufferedDataSource::ProgressCallback(int64 position) {
584 DCHECK(MessageLoop::current() == render_loop_); 508 DCHECK(MessageLoop::current() == render_loop_);
585 DCHECK(url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)); 509 DCHECK(url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme));
586 510
511 // We assume non-HTTP resources are fully loaded: ignore any udpates.
Ami GONE FROM CHROMIUM 2012/07/09 03:30:57 ditto to DCHECKing if possible.
scherkus (not reviewing) 2012/07/10 18:37:27 Done.
512 if (!url_.SchemeIs(kHttpScheme) && !url_.SchemeIs(kHttpsScheme))
513 return;
514
587 // TODO(scherkus): we shouldn't have to lock to signal host(), see 515 // TODO(scherkus): we shouldn't have to lock to signal host(), see
588 // http://crbug.com/113712 for details. 516 // http://crbug.com/113712 for details.
589 base::AutoLock auto_lock(lock_); 517 base::AutoLock auto_lock(lock_);
590 if (stop_signal_received_) 518 if (stop_signal_received_)
591 return; 519 return;
592 520
593 if (host() && position > last_read_start_) 521 if (host() && position > last_read_start_)
594 host()->AddBufferedByteRange(last_read_start_, position); 522 host()->AddBufferedByteRange(last_read_start_, position);
595 } 523 }
596 524
597 void BufferedDataSource::UpdateHostState_Locked() { 525 void BufferedDataSource::UpdateHostState_Locked() {
598 lock_.AssertAcquired(); 526 lock_.AssertAcquired();
599 527
600 if (!host()) 528 if (!host())
601 return; 529 return;
602 530
603 if (total_bytes_ != kPositionNotSpecified) 531 if (total_bytes_ != kPositionNotSpecified)
604 host()->SetTotalBytes(total_bytes_); 532 host()->SetTotalBytes(total_bytes_);
605 if (buffered_bytes_ > last_read_start_) 533 if (buffered_bytes_ > last_read_start_)
606 host()->AddBufferedByteRange(last_read_start_, buffered_bytes_); 534 host()->AddBufferedByteRange(last_read_start_, buffered_bytes_);
607 } 535 }
608 536
609 } // namespace webkit_media 537 } // namespace webkit_media
OLDNEW
« webkit/media/buffered_data_source.h ('K') | « webkit/media/buffered_data_source.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698