| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/glue/media/buffered_data_source.h" | 5 #include "webkit/glue/media/buffered_data_source.h" |
| 6 | 6 |
| 7 #include "media/base/filter_host.h" | 7 #include "media/base/filter_host.h" |
| 8 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" |
| 9 #include "webkit/glue/media/web_data_source_factory.h" | 9 #include "webkit/glue/media/web_data_source_factory.h" |
| 10 #include "webkit/glue/webkit_glue.h" | 10 #include "webkit/glue/webkit_glue.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 BufferedDataSource::BufferedDataSource( | 39 BufferedDataSource::BufferedDataSource( |
| 40 MessageLoop* render_loop, | 40 MessageLoop* render_loop, |
| 41 WebFrame* frame) | 41 WebFrame* frame) |
| 42 : total_bytes_(kPositionNotSpecified), | 42 : total_bytes_(kPositionNotSpecified), |
| 43 buffered_bytes_(0), | 43 buffered_bytes_(0), |
| 44 loaded_(false), | 44 loaded_(false), |
| 45 streaming_(false), | 45 streaming_(false), |
| 46 frame_(frame), | 46 frame_(frame), |
| 47 loader_(NULL), | 47 loader_(NULL), |
| 48 network_activity_(false), | 48 network_activity_(false), |
| 49 initialize_callback_(NULL), | |
| 50 read_callback_(NULL), | 49 read_callback_(NULL), |
| 51 read_position_(0), | 50 read_position_(0), |
| 52 read_size_(0), | 51 read_size_(0), |
| 53 read_buffer_(NULL), | 52 read_buffer_(NULL), |
| 54 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), | 53 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), |
| 55 intermediate_read_buffer_size_(kInitialReadBufferSize), | 54 intermediate_read_buffer_size_(kInitialReadBufferSize), |
| 56 render_loop_(render_loop), | 55 render_loop_(render_loop), |
| 57 stop_signal_received_(false), | 56 stop_signal_received_(false), |
| 58 stopped_on_render_loop_(false), | 57 stopped_on_render_loop_(false), |
| 59 media_is_paused_(true), | 58 media_is_paused_(true), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 78 } | 77 } |
| 79 | 78 |
| 80 void BufferedDataSource::set_host(media::FilterHost* host) { | 79 void BufferedDataSource::set_host(media::FilterHost* host) { |
| 81 DataSource::set_host(host); | 80 DataSource::set_host(host); |
| 82 | 81 |
| 83 if (loader_.get()) | 82 if (loader_.get()) |
| 84 UpdateHostState(); | 83 UpdateHostState(); |
| 85 } | 84 } |
| 86 | 85 |
| 87 void BufferedDataSource::Initialize(const std::string& url, | 86 void BufferedDataSource::Initialize(const std::string& url, |
| 88 media::PipelineStatusCallback* callback) { | 87 const media::PipelineStatusCB& callback) { |
| 89 // Saves the url. | 88 // Saves the url. |
| 90 url_ = GURL(url); | 89 url_ = GURL(url); |
| 91 | 90 |
| 92 // This data source doesn't support data:// protocol so reject it. | 91 // This data source doesn't support data:// protocol so reject it. |
| 93 if (url_.SchemeIs(kDataScheme)) { | 92 if (url_.SchemeIs(kDataScheme)) { |
| 94 callback->Run(media::DATASOURCE_ERROR_URL_NOT_SUPPORTED); | 93 callback.Run(media::DATASOURCE_ERROR_URL_NOT_SUPPORTED); |
| 95 delete callback; | |
| 96 return; | 94 return; |
| 97 } else if (!IsProtocolSupportedForMedia(url_)) { | 95 } else if (!IsProtocolSupportedForMedia(url_)) { |
| 98 callback->Run(media::PIPELINE_ERROR_NETWORK); | 96 callback.Run(media::PIPELINE_ERROR_NETWORK); |
| 99 delete callback; | |
| 100 return; | 97 return; |
| 101 } | 98 } |
| 102 | 99 |
| 103 DCHECK(callback); | 100 DCHECK(!callback.is_null()); |
| 104 initialize_callback_.reset(callback); | 101 initialize_cb_ = callback; |
| 105 | 102 |
| 106 // Post a task to complete the initialization task. | 103 // Post a task to complete the initialization task. |
| 107 render_loop_->PostTask(FROM_HERE, | 104 render_loop_->PostTask(FROM_HERE, |
| 108 NewRunnableMethod(this, &BufferedDataSource::InitializeTask)); | 105 NewRunnableMethod(this, &BufferedDataSource::InitializeTask)); |
| 109 } | 106 } |
| 110 | 107 |
| 111 void BufferedDataSource::CancelInitialize() { | 108 void BufferedDataSource::CancelInitialize() { |
| 112 base::AutoLock auto_lock(lock_); | 109 base::AutoLock auto_lock(lock_); |
| 113 DCHECK(initialize_callback_.get()); | 110 DCHECK(!initialize_cb_.is_null()); |
| 114 | 111 |
| 115 initialize_callback_.reset(); | 112 initialize_cb_.Reset(); |
| 116 | 113 |
| 117 render_loop_->PostTask( | 114 render_loop_->PostTask( |
| 118 FROM_HERE, NewRunnableMethod(this, &BufferedDataSource::CleanupTask)); | 115 FROM_HERE, NewRunnableMethod(this, &BufferedDataSource::CleanupTask)); |
| 119 } | 116 } |
| 120 | 117 |
| 121 ///////////////////////////////////////////////////////////////////////////// | 118 ///////////////////////////////////////////////////////////////////////////// |
| 122 // media::Filter implementation. | 119 // media::Filter implementation. |
| 123 void BufferedDataSource::Stop(media::FilterCallback* callback) { | 120 void BufferedDataSource::Stop(media::FilterCallback* callback) { |
| 124 { | 121 { |
| 125 base::AutoLock auto_lock(lock_); | 122 base::AutoLock auto_lock(lock_); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 | 192 |
| 196 CleanupTask(); | 193 CleanupTask(); |
| 197 frame_ = NULL; | 194 frame_ = NULL; |
| 198 } | 195 } |
| 199 | 196 |
| 200 ///////////////////////////////////////////////////////////////////////////// | 197 ///////////////////////////////////////////////////////////////////////////// |
| 201 // Render thread tasks. | 198 // Render thread tasks. |
| 202 void BufferedDataSource::InitializeTask() { | 199 void BufferedDataSource::InitializeTask() { |
| 203 DCHECK(MessageLoop::current() == render_loop_); | 200 DCHECK(MessageLoop::current() == render_loop_); |
| 204 DCHECK(!loader_.get()); | 201 DCHECK(!loader_.get()); |
| 205 if (stopped_on_render_loop_ || !initialize_callback_.get()) | 202 if (stopped_on_render_loop_ || initialize_cb_.is_null()) |
| 206 return; | 203 return; |
| 207 | 204 |
| 208 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { | 205 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { |
| 209 // Do an unbounded range request starting at the beginning. If the server | 206 // Do an unbounded range request starting at the beginning. If the server |
| 210 // responds with 200 instead of 206 we'll fall back into a streaming mode. | 207 // responds with 200 instead of 206 we'll fall back into a streaming mode. |
| 211 loader_ = CreateResourceLoader(0, kPositionNotSpecified); | 208 loader_ = CreateResourceLoader(0, kPositionNotSpecified); |
| 212 loader_->Start( | 209 loader_->Start( |
| 213 NewCallback(this, &BufferedDataSource::HttpInitialStartCallback), | 210 NewCallback(this, &BufferedDataSource::HttpInitialStartCallback), |
| 214 NewCallback(this, &BufferedDataSource::NetworkEventCallback), | 211 NewCallback(this, &BufferedDataSource::NetworkEventCallback), |
| 215 frame_); | 212 frame_); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 | 369 |
| 373 read_callback_.reset(); | 370 read_callback_.reset(); |
| 374 read_position_ = 0; | 371 read_position_ = 0; |
| 375 read_size_ = 0; | 372 read_size_ = 0; |
| 376 read_buffer_ = 0; | 373 read_buffer_ = 0; |
| 377 } | 374 } |
| 378 | 375 |
| 379 void BufferedDataSource::DoneInitialization_Locked( | 376 void BufferedDataSource::DoneInitialization_Locked( |
| 380 media::PipelineStatus status) { | 377 media::PipelineStatus status) { |
| 381 DCHECK(MessageLoop::current() == render_loop_); | 378 DCHECK(MessageLoop::current() == render_loop_); |
| 382 DCHECK(initialize_callback_.get()); | 379 DCHECK(!initialize_cb_.is_null()); |
| 383 lock_.AssertAcquired(); | 380 lock_.AssertAcquired(); |
| 384 | 381 |
| 385 scoped_ptr<media::PipelineStatusCallback> initialize_callback( | 382 initialize_cb_.Run(status); |
| 386 initialize_callback_.release()); | 383 initialize_cb_.Reset(); |
| 387 initialize_callback->Run(status); | |
| 388 } | 384 } |
| 389 | 385 |
| 390 ///////////////////////////////////////////////////////////////////////////// | 386 ///////////////////////////////////////////////////////////////////////////// |
| 391 // BufferedResourceLoader callback methods. | 387 // BufferedResourceLoader callback methods. |
| 392 void BufferedDataSource::HttpInitialStartCallback(int error) { | 388 void BufferedDataSource::HttpInitialStartCallback(int error) { |
| 393 DCHECK(MessageLoop::current() == render_loop_); | 389 DCHECK(MessageLoop::current() == render_loop_); |
| 394 DCHECK(loader_.get()); | 390 DCHECK(loader_.get()); |
| 395 | 391 |
| 396 int64 instance_size = loader_->instance_size(); | 392 int64 instance_size = loader_->instance_size(); |
| 397 bool success = error == net::OK; | 393 bool success = error == net::OK; |
| 398 | 394 |
| 399 if (!initialize_callback_.get()) { | 395 if (initialize_cb_.is_null()) { |
| 400 loader_->Stop(); | 396 loader_->Stop(); |
| 401 return; | 397 return; |
| 402 } | 398 } |
| 403 | 399 |
| 404 if (success) { | 400 if (success) { |
| 405 // TODO(hclam): Needs more thinking about supporting servers without range | 401 // TODO(hclam): Needs more thinking about supporting servers without range |
| 406 // request or their partial response is not complete. | 402 // request or their partial response is not complete. |
| 407 total_bytes_ = instance_size; | 403 total_bytes_ = instance_size; |
| 408 loaded_ = false; | 404 loaded_ = false; |
| 409 streaming_ = (instance_size == kPositionNotSpecified) || | 405 streaming_ = (instance_size == kPositionNotSpecified) || |
| 410 !loader_->range_supported(); | 406 !loader_->range_supported(); |
| 411 } else { | 407 } else { |
| 412 // TODO(hclam): In case of failure, we can retry several times. | 408 // TODO(hclam): In case of failure, we can retry several times. |
| 413 loader_->Stop(); | 409 loader_->Stop(); |
| 414 } | 410 } |
| 415 | 411 |
| 416 if (error == net::ERR_INVALID_RESPONSE && using_range_request_) { | 412 if (error == net::ERR_INVALID_RESPONSE && using_range_request_) { |
| 417 // Assuming that the Range header was causing the problem. Retry without | 413 // Assuming that the Range header was causing the problem. Retry without |
| 418 // the Range header. | 414 // the Range header. |
| 419 using_range_request_ = false; | 415 using_range_request_ = false; |
| 420 loader_ = CreateResourceLoader(kPositionNotSpecified, | 416 loader_ = CreateResourceLoader(kPositionNotSpecified, |
| 421 kPositionNotSpecified); | 417 kPositionNotSpecified); |
| 422 loader_->Start( | 418 loader_->Start( |
| 423 NewCallback(this, &BufferedDataSource::HttpInitialStartCallback), | 419 NewCallback(this, &BufferedDataSource::HttpInitialStartCallback), |
| 424 NewCallback(this, &BufferedDataSource::NetworkEventCallback), | 420 NewCallback(this, &BufferedDataSource::NetworkEventCallback), |
| 425 frame_); | 421 frame_); |
| 426 return; | 422 return; |
| 427 } | 423 } |
| 428 | 424 |
| 429 // Reference to prevent destruction while inside the |initialize_callback_| | 425 // Reference to prevent destruction while inside the |initialize_cb_| |
| 430 // call. This is a temporary fix to prevent crashes caused by holding the | 426 // call. This is a temporary fix to prevent crashes caused by holding the |
| 431 // lock and running the destructor. | 427 // lock and running the destructor. |
| 432 // TODO: Review locking in this class and figure out a way to run the callback | 428 // TODO: Review locking in this class and figure out a way to run the callback |
| 433 // w/o the lock. | 429 // w/o the lock. |
| 434 scoped_refptr<BufferedDataSource> destruction_guard(this); | 430 scoped_refptr<BufferedDataSource> destruction_guard(this); |
| 435 { | 431 { |
| 436 // We need to prevent calling to filter host and running the callback if | 432 // We need to prevent calling to filter host and running the callback if |
| 437 // we have received the stop signal. We need to lock down the whole callback | 433 // we have received the stop signal. We need to lock down the whole callback |
| 438 // method to prevent bad things from happening. The reason behind this is | 434 // method to prevent bad things from happening. The reason behind this is |
| 439 // that we cannot guarantee tasks on render thread have completely stopped | 435 // that we cannot guarantee tasks on render thread have completely stopped |
| (...skipping 12 matching lines...) Expand all Loading... |
| 452 | 448 |
| 453 UpdateHostState(); | 449 UpdateHostState(); |
| 454 DoneInitialization_Locked(media::PIPELINE_OK); | 450 DoneInitialization_Locked(media::PIPELINE_OK); |
| 455 } | 451 } |
| 456 } | 452 } |
| 457 | 453 |
| 458 void BufferedDataSource::NonHttpInitialStartCallback(int error) { | 454 void BufferedDataSource::NonHttpInitialStartCallback(int error) { |
| 459 DCHECK(MessageLoop::current() == render_loop_); | 455 DCHECK(MessageLoop::current() == render_loop_); |
| 460 DCHECK(loader_.get()); | 456 DCHECK(loader_.get()); |
| 461 | 457 |
| 462 if (!initialize_callback_.get()) { | 458 if (initialize_cb_.is_null()) { |
| 463 loader_->Stop(); | 459 loader_->Stop(); |
| 464 return; | 460 return; |
| 465 } | 461 } |
| 466 | 462 |
| 467 int64 instance_size = loader_->instance_size(); | 463 int64 instance_size = loader_->instance_size(); |
| 468 bool success = error == net::OK && instance_size != kPositionNotSpecified; | 464 bool success = error == net::OK && instance_size != kPositionNotSpecified; |
| 469 | 465 |
| 470 if (success) { | 466 if (success) { |
| 471 total_bytes_ = instance_size; | 467 total_bytes_ = instance_size; |
| 472 buffered_bytes_ = total_bytes_; | 468 buffered_bytes_ = total_bytes_; |
| 473 loaded_ = true; | 469 loaded_ = true; |
| 474 } else { | 470 } else { |
| 475 loader_->Stop(); | 471 loader_->Stop(); |
| 476 } | 472 } |
| 477 | 473 |
| 478 // Reference to prevent destruction while inside the |initialize_callback_| | 474 // Reference to prevent destruction while inside the |initialize_cb_| |
| 479 // call. This is a temporary fix to prevent crashes caused by holding the | 475 // call. This is a temporary fix to prevent crashes caused by holding the |
| 480 // lock and running the destructor. | 476 // lock and running the destructor. |
| 481 // TODO: Review locking in this class and figure out a way to run the callback | 477 // TODO: Review locking in this class and figure out a way to run the callback |
| 482 // w/o the lock. | 478 // w/o the lock. |
| 483 scoped_refptr<BufferedDataSource> destruction_guard(this); | 479 scoped_refptr<BufferedDataSource> destruction_guard(this); |
| 484 { | 480 { |
| 485 // We need to prevent calling to filter host and running the callback if | 481 // We need to prevent calling to filter host and running the callback if |
| 486 // we have received the stop signal. We need to lock down the whole callback | 482 // we have received the stop signal. We need to lock down the whole callback |
| 487 // method to prevent bad things from happening. The reason behind this is | 483 // method to prevent bad things from happening. The reason behind this is |
| 488 // that we cannot guarantee tasks on render thread have completely stopped | 484 // that we cannot guarantee tasks on render thread have completely stopped |
| 489 // when we receive the Stop() method call. The only way to solve this is to | 485 // when we receive the Stop() method call. The only way to solve this is to |
| 490 // let tasks on render thread to run but make sure they don't call outside | 486 // let tasks on render thread to run but make sure they don't call outside |
| 491 // this object when Stop() method is ever called. Locking this method is | 487 // this object when Stop() method is ever called. Locking this method is |
| 492 // safe because |lock_| is only acquired in tasks on render thread. | 488 // safe because |lock_| is only acquired in tasks on render thread. |
| 493 base::AutoLock auto_lock(lock_); | 489 base::AutoLock auto_lock(lock_); |
| 494 if (stop_signal_received_ || !initialize_callback_.get()) | 490 if (stop_signal_received_ || initialize_cb_.is_null()) |
| 495 return; | 491 return; |
| 496 | 492 |
| 497 if (!success) { | 493 if (!success) { |
| 498 DoneInitialization_Locked(media::PIPELINE_ERROR_NETWORK); | 494 DoneInitialization_Locked(media::PIPELINE_ERROR_NETWORK); |
| 499 return; | 495 return; |
| 500 } | 496 } |
| 501 | 497 |
| 502 UpdateHostState(); | 498 UpdateHostState(); |
| 503 DoneInitialization_Locked(media::PIPELINE_OK); | 499 DoneInitialization_Locked(media::PIPELINE_OK); |
| 504 } | 500 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 | 621 |
| 626 if (streaming_) { | 622 if (streaming_) { |
| 627 filter_host->SetStreaming(true); | 623 filter_host->SetStreaming(true); |
| 628 } else { | 624 } else { |
| 629 filter_host->SetTotalBytes(total_bytes_); | 625 filter_host->SetTotalBytes(total_bytes_); |
| 630 filter_host->SetBufferedBytes(buffered_bytes_); | 626 filter_host->SetBufferedBytes(buffered_bytes_); |
| 631 } | 627 } |
| 632 } | 628 } |
| 633 | 629 |
| 634 } // namespace webkit_glue | 630 } // namespace webkit_glue |
| OLD | NEW |