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 |