OLD | NEW |
1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008-2009 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 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, | 5 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, |
6 // potential deadlocks, etc... | 6 // potential deadlocks, etc... |
7 | 7 |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/condition_variable.h" | 9 #include "base/condition_variable.h" |
10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 NewRunnableMethod(this, &PipelineInternal::PlaybackRateChangedTask, | 321 NewRunnableMethod(this, &PipelineInternal::PlaybackRateChangedTask, |
322 playback_rate)); | 322 playback_rate)); |
323 } | 323 } |
324 | 324 |
325 // Called on client's thread. | 325 // Called on client's thread. |
326 void PipelineInternal::VolumeChanged(float volume) { | 326 void PipelineInternal::VolumeChanged(float volume) { |
327 message_loop_->PostTask(FROM_HERE, | 327 message_loop_->PostTask(FROM_HERE, |
328 NewRunnableMethod(this, &PipelineInternal::VolumeChangedTask, volume)); | 328 NewRunnableMethod(this, &PipelineInternal::VolumeChangedTask, volume)); |
329 } | 329 } |
330 | 330 |
331 // Called from any thread. | |
332 void PipelineInternal::InitializationComplete(FilterHostImpl* host) { | |
333 if (IsPipelineOk()) { | |
334 // Continue the initialize task by proceeding to the next stage. | |
335 message_loop_->PostTask(FROM_HERE, | |
336 NewRunnableMethod(this, &PipelineInternal::InitializeTask)); | |
337 } | |
338 } | |
339 | |
340 // Called from any thread. Updates the pipeline time. | 331 // Called from any thread. Updates the pipeline time. |
341 void PipelineInternal::SetTime(base::TimeDelta time) { | 332 void PipelineInternal::SetTime(base::TimeDelta time) { |
342 // TODO(scherkus): why not post a task? | 333 // TODO(scherkus): why not post a task? |
343 pipeline_->SetTime(time); | 334 pipeline_->SetTime(time); |
344 } | 335 } |
345 | 336 |
346 // Called from any thread. Sets the pipeline |error_| member and destroys all | 337 // Called from any thread. Sets the pipeline |error_| member and destroys all |
347 // filters. | 338 // filters. |
348 void PipelineInternal::Error(PipelineError error) { | 339 void PipelineInternal::Error(PipelineError error) { |
349 message_loop_->PostTask(FROM_HERE, | 340 message_loop_->PostTask(FROM_HERE, |
350 NewRunnableMethod(this, &PipelineInternal::ErrorTask, error)); | 341 NewRunnableMethod(this, &PipelineInternal::ErrorTask, error)); |
351 } | 342 } |
352 | 343 |
| 344 // Called from any thread. |
| 345 void PipelineInternal::OnFilterInitialize() { |
| 346 // Continue the initialize task by proceeding to the next stage. |
| 347 message_loop_->PostTask(FROM_HERE, |
| 348 NewRunnableMethod(this, &PipelineInternal::InitializeTask)); |
| 349 } |
| 350 |
| 351 // Called from any thread. |
| 352 void PipelineInternal::OnFilterSeek() { |
| 353 // TODO(scherkus): have PipelineInternal wait to receive replies from every |
| 354 // filter before calling the client's |seek_callback_|. |
| 355 } |
| 356 |
353 void PipelineInternal::StartTask(FilterFactory* filter_factory, | 357 void PipelineInternal::StartTask(FilterFactory* filter_factory, |
354 const std::string& url, | 358 const std::string& url, |
355 PipelineCallback* start_callback) { | 359 PipelineCallback* start_callback) { |
356 DCHECK_EQ(MessageLoop::current(), message_loop_); | 360 DCHECK_EQ(MessageLoop::current(), message_loop_); |
357 DCHECK_EQ(kCreated, state_); | 361 DCHECK_EQ(kCreated, state_); |
358 filter_factory_ = filter_factory; | 362 filter_factory_ = filter_factory; |
359 url_ = url; | 363 url_ = url; |
360 start_callback_.reset(start_callback); | 364 start_callback_.reset(start_callback); |
361 | 365 |
362 // Kick off initialization. | 366 // Kick off initialization. |
(...skipping 13 matching lines...) Expand all Loading... |
376 // When all required filters have been created and have called their | 380 // When all required filters have been created and have called their |
377 // FilterHost's InitializationComplete() method, the pipeline will update its | 381 // FilterHost's InitializationComplete() method, the pipeline will update its |
378 // state to kStarted and |init_callback_|, will be executed. | 382 // state to kStarted and |init_callback_|, will be executed. |
379 // | 383 // |
380 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 384 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It |
381 // works like a big state change table. If we no longer need to start filters | 385 // works like a big state change table. If we no longer need to start filters |
382 // in order, we need to get rid of all the state change. | 386 // in order, we need to get rid of all the state change. |
383 void PipelineInternal::InitializeTask() { | 387 void PipelineInternal::InitializeTask() { |
384 DCHECK_EQ(MessageLoop::current(), message_loop_); | 388 DCHECK_EQ(MessageLoop::current(), message_loop_); |
385 | 389 |
386 // If we have received the stop signal, return immediately. | 390 // If we have received the stop or error signal, return immediately. |
387 if (state_ == kStopped) | 391 if (state_ == kStopped || state_ == kError) |
388 return; | 392 return; |
389 | 393 |
390 DCHECK(state_ == kCreated || IsPipelineInitializing()); | 394 DCHECK(state_ == kCreated || IsPipelineInitializing()); |
391 | 395 |
392 // Just created, create data source. | 396 // Just created, create data source. |
393 if (state_ == kCreated) { | 397 if (state_ == kCreated) { |
394 state_ = kInitDataSource; | 398 state_ = kInitDataSource; |
395 CreateDataSource(); | 399 CreateDataSource(); |
396 return; | 400 return; |
397 } | 401 } |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 seek_callback_.reset(seek_callback); | 548 seek_callback_.reset(seek_callback); |
545 | 549 |
546 // Supress seeking if we haven't fully started. | 550 // Supress seeking if we haven't fully started. |
547 if (state_ != kStarted) { | 551 if (state_ != kStarted) { |
548 return; | 552 return; |
549 } | 553 } |
550 | 554 |
551 for (FilterHostVector::iterator iter = filter_hosts_.begin(); | 555 for (FilterHostVector::iterator iter = filter_hosts_.begin(); |
552 iter != filter_hosts_.end(); | 556 iter != filter_hosts_.end(); |
553 ++iter) { | 557 ++iter) { |
554 (*iter)->media_filter()->Seek(time); | 558 (*iter)->media_filter()->Seek(time, |
| 559 NewCallback(this, &PipelineInternal::OnFilterSeek)); |
555 } | 560 } |
556 | 561 |
557 // TODO(hclam): we should set the time when the above seek operations were all | 562 // TODO(hclam): we should set the time when the above seek operations were all |
558 // successful and first frame/packet at the desired time is decoded. I'm | 563 // successful and first frame/packet at the desired time is decoded. I'm |
559 // setting the time here because once we do the callback the user can ask for | 564 // setting the time here because once we do the callback the user can ask for |
560 // current time immediately, which is the old time. In order to get rid this | 565 // current time immediately, which is the old time. In order to get rid this |
561 // little glitch, we either assume the seek was successful and time is updated | 566 // little glitch, we either assume the seek was successful and time is updated |
562 // immediately here or we set time and do callback when we have new | 567 // immediately here or we set time and do callback when we have new |
563 // frames/packets. | 568 // frames/packets. |
564 SetTime(time); | 569 SetTime(time); |
(...skipping 30 matching lines...) Expand all Loading... |
595 filter_threads_.push_back(thread.release()); | 600 filter_threads_.push_back(thread.release()); |
596 } | 601 } |
597 | 602 |
598 // Create the filter's host. | 603 // Create the filter's host. |
599 DCHECK(IsPipelineOk()); | 604 DCHECK(IsPipelineOk()); |
600 scoped_ptr<FilterHostImpl> host(new FilterHostImpl(this, filter.get())); | 605 scoped_ptr<FilterHostImpl> host(new FilterHostImpl(this, filter.get())); |
601 filter->set_host(host.get()); | 606 filter->set_host(host.get()); |
602 filter_hosts_.push_back(host.release()); | 607 filter_hosts_.push_back(host.release()); |
603 | 608 |
604 // Now initialize the filter. | 609 // Now initialize the filter. |
605 if (!filter->Initialize(source)) { | 610 filter->Initialize(source, |
606 Error(PIPELINE_ERROR_INITIALIZATION_FAILED); | 611 NewCallback(this, &PipelineInternal::OnFilterInitialize)); |
607 } | |
608 } | 612 } |
609 | 613 |
610 void PipelineInternal::CreateDataSource() { | 614 void PipelineInternal::CreateDataSource() { |
611 DCHECK_EQ(MessageLoop::current(), message_loop_); | 615 DCHECK_EQ(MessageLoop::current(), message_loop_); |
612 DCHECK(IsPipelineOk()); | 616 DCHECK(IsPipelineOk()); |
613 | 617 |
614 MediaFormat url_format; | 618 MediaFormat url_format; |
615 url_format.SetAsString(MediaFormat::kMimeType, mime_type::kURL); | 619 url_format.SetAsString(MediaFormat::kMimeType, mime_type::kURL); |
616 url_format.SetAsString(MediaFormat::kURL, url_); | 620 url_format.SetAsString(MediaFormat::kURL, url_); |
617 CreateFilter<DataSource>(filter_factory_, url_, url_format); | 621 CreateFilter<DataSource>(filter_factory_, url_, url_format); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 } | 726 } |
723 | 727 |
724 // Reset the pipeline, which will decrement a reference to this object. | 728 // Reset the pipeline, which will decrement a reference to this object. |
725 // We will get destroyed as soon as the remaining tasks finish executing. | 729 // We will get destroyed as soon as the remaining tasks finish executing. |
726 // To be safe, we'll set our pipeline reference to NULL. | 730 // To be safe, we'll set our pipeline reference to NULL. |
727 STLDeleteElements(&filter_hosts_); | 731 STLDeleteElements(&filter_hosts_); |
728 STLDeleteElements(&filter_threads_); | 732 STLDeleteElements(&filter_threads_); |
729 } | 733 } |
730 | 734 |
731 } // namespace media | 735 } // namespace media |
OLD | NEW |