| OLD | NEW |
| 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 "media/base/pipeline.h" | 5 #include "media/base/pipeline.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 17 #include "base/synchronization/condition_variable.h" | 17 #include "base/synchronization/condition_variable.h" |
| 18 #include "media/base/audio_decoder.h" | 18 #include "media/base/audio_decoder.h" |
| 19 #include "media/base/audio_renderer.h" | 19 #include "media/base/audio_renderer.h" |
| 20 #include "media/base/callback_util.h" | 20 #include "media/base/callback_util.h" |
| 21 #include "media/base/clock.h" | 21 #include "media/base/clock.h" |
| 22 #include "media/base/composite_filter.h" | |
| 23 #include "media/base/filter_collection.h" | 22 #include "media/base/filter_collection.h" |
| 24 #include "media/base/media_log.h" | 23 #include "media/base/media_log.h" |
| 25 #include "media/base/video_decoder.h" | 24 #include "media/base/video_decoder.h" |
| 26 #include "media/base/video_renderer.h" | 25 #include "media/base/video_renderer.h" |
| 27 | 26 |
| 28 using base::TimeDelta; | 27 using base::TimeDelta; |
| 29 | 28 |
| 30 namespace media { | 29 namespace media { |
| 31 | 30 |
| 32 PipelineStatusNotification::PipelineStatusNotification() | 31 PipelineStatusNotification::PipelineStatusNotification() |
| (...skipping 25 matching lines...) Expand all Loading... |
| 58 | 57 |
| 59 media::PipelineStatus PipelineStatusNotification::status() { | 58 media::PipelineStatus PipelineStatusNotification::status() { |
| 60 base::AutoLock auto_lock(lock_); | 59 base::AutoLock auto_lock(lock_); |
| 61 DCHECK(notified_); | 60 DCHECK(notified_); |
| 62 return status_; | 61 return status_; |
| 63 } | 62 } |
| 64 | 63 |
| 65 struct Pipeline::PipelineInitState { | 64 struct Pipeline::PipelineInitState { |
| 66 scoped_refptr<AudioDecoder> audio_decoder; | 65 scoped_refptr<AudioDecoder> audio_decoder; |
| 67 scoped_refptr<VideoDecoder> video_decoder; | 66 scoped_refptr<VideoDecoder> video_decoder; |
| 68 scoped_refptr<VideoRenderer> video_renderer; | |
| 69 scoped_refptr<CompositeFilter> composite; | |
| 70 }; | 67 }; |
| 71 | 68 |
| 72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
| 73 : message_loop_(message_loop->message_loop_proxy()), | 70 : message_loop_(message_loop->message_loop_proxy()), |
| 74 media_log_(media_log), | 71 media_log_(media_log), |
| 75 clock_(new Clock(&base::Time::Now)), | 72 clock_(new Clock(&base::Time::Now)), |
| 76 waiting_for_clock_update_(false), | 73 waiting_for_clock_update_(false), |
| 77 state_(kCreated), | 74 state_(kCreated), |
| 78 creation_time_(base::Time::Now()) { | 75 creation_time_(base::Time::Now()) { |
| 79 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 76 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 return; | 179 return; |
| 183 | 180 |
| 184 base::AutoLock auto_lock(lock_); | 181 base::AutoLock auto_lock(lock_); |
| 185 volume_ = volume; | 182 volume_ = volume; |
| 186 if (running_ && !tearing_down_) { | 183 if (running_ && !tearing_down_) { |
| 187 message_loop_->PostTask(FROM_HERE, base::Bind( | 184 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 188 &Pipeline::VolumeChangedTask, this, volume)); | 185 &Pipeline::VolumeChangedTask, this, volume)); |
| 189 } | 186 } |
| 190 } | 187 } |
| 191 | 188 |
| 192 TimeDelta Pipeline::GetCurrentTime() const { | 189 TimeDelta Pipeline::GetMediaTime() const { |
| 193 base::AutoLock auto_lock(lock_); | 190 base::AutoLock auto_lock(lock_); |
| 194 return GetCurrentTime_Locked(); | |
| 195 } | |
| 196 | |
| 197 TimeDelta Pipeline::GetCurrentTime_Locked() const { | |
| 198 lock_.AssertAcquired(); | |
| 199 return clock_->Elapsed(); | 191 return clock_->Elapsed(); |
| 200 } | 192 } |
| 201 | 193 |
| 202 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() { | 194 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() { |
| 203 base::AutoLock auto_lock(lock_); | 195 base::AutoLock auto_lock(lock_); |
| 204 Ranges<TimeDelta> time_ranges; | 196 Ranges<TimeDelta> time_ranges; |
| 205 for (size_t i = 0; i < buffered_time_ranges_.size(); ++i) { | 197 for (size_t i = 0; i < buffered_time_ranges_.size(); ++i) { |
| 206 time_ranges.Add(buffered_time_ranges_.start(i), | 198 time_ranges.Add(buffered_time_ranges_.start(i), |
| 207 buffered_time_ranges_.end(i)); | 199 buffered_time_ranges_.end(i)); |
| 208 } | 200 } |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 DCHECK(IsRunning()); | 366 DCHECK(IsRunning()); |
| 375 DCHECK_NE(PIPELINE_OK, error); | 367 DCHECK_NE(PIPELINE_OK, error); |
| 376 VLOG(1) << "Media pipeline error: " << error; | 368 VLOG(1) << "Media pipeline error: " << error; |
| 377 | 369 |
| 378 message_loop_->PostTask(FROM_HERE, base::Bind( | 370 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 379 &Pipeline::ErrorChangedTask, this, error)); | 371 &Pipeline::ErrorChangedTask, this, error)); |
| 380 | 372 |
| 381 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); | 373 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); |
| 382 } | 374 } |
| 383 | 375 |
| 384 TimeDelta Pipeline::GetTime() const { | |
| 385 DCHECK(IsRunning()); | |
| 386 return GetCurrentTime(); | |
| 387 } | |
| 388 | |
| 389 TimeDelta Pipeline::GetDuration() const { | |
| 390 DCHECK(IsRunning()); | |
| 391 return GetMediaDuration(); | |
| 392 } | |
| 393 | |
| 394 void Pipeline::OnAudioDisabled() { | 376 void Pipeline::OnAudioDisabled() { |
| 395 DCHECK(IsRunning()); | 377 DCHECK(IsRunning()); |
| 396 message_loop_->PostTask(FROM_HERE, base::Bind( | 378 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 397 &Pipeline::AudioDisabledTask, this)); | 379 &Pipeline::AudioDisabledTask, this)); |
| 398 media_log_->AddEvent( | 380 media_log_->AddEvent( |
| 399 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 381 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); |
| 400 } | 382 } |
| 401 | 383 |
| 402 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 384 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
| 403 DCHECK(time <= max_time); | 385 DCHECK(time <= max_time); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 return time_offset; | 451 return time_offset; |
| 470 } | 452 } |
| 471 | 453 |
| 472 void Pipeline::DoPause(const base::Closure& done_cb) { | 454 void Pipeline::DoPause(const base::Closure& done_cb) { |
| 473 DCHECK(message_loop_->BelongsToCurrentThread()); | 455 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 474 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 456 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 475 | 457 |
| 476 if (audio_renderer_) | 458 if (audio_renderer_) |
| 477 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); | 459 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); |
| 478 | 460 |
| 479 if (pipeline_filter_) | 461 if (video_renderer_) |
| 480 closures->push(base::Bind(&Filter::Pause, pipeline_filter_)); | 462 closures->push(base::Bind(&VideoRenderer::Pause, video_renderer_)); |
| 481 | 463 |
| 482 RunInSeries(closures.Pass(), done_cb); | 464 RunInSeries(closures.Pass(), done_cb); |
| 483 } | 465 } |
| 484 | 466 |
| 485 void Pipeline::DoFlush(const base::Closure& done_cb) { | 467 void Pipeline::DoFlush(const base::Closure& done_cb) { |
| 486 DCHECK(message_loop_->BelongsToCurrentThread()); | 468 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 487 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 469 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 488 | 470 |
| 489 if (audio_renderer_) | 471 if (audio_renderer_) |
| 490 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); | 472 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); |
| 491 | 473 |
| 492 if (pipeline_filter_) | 474 if (video_renderer_) |
| 493 closures->push(base::Bind(&Filter::Flush, pipeline_filter_)); | 475 closures->push(base::Bind(&VideoRenderer::Flush, video_renderer_)); |
| 494 | 476 |
| 495 RunInParallel(closures.Pass(), done_cb); | 477 RunInParallel(closures.Pass(), done_cb); |
| 496 } | 478 } |
| 497 | 479 |
| 498 void Pipeline::DoPlay(const base::Closure& done_cb) { | 480 void Pipeline::DoPlay(const base::Closure& done_cb) { |
| 499 DCHECK(message_loop_->BelongsToCurrentThread()); | 481 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 500 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 482 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 501 | 483 |
| 502 if (audio_renderer_) | 484 if (audio_renderer_) |
| 503 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); | 485 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); |
| 504 | 486 |
| 505 if (pipeline_filter_) | 487 if (video_renderer_) |
| 506 closures->push(base::Bind(&Filter::Play, pipeline_filter_)); | 488 closures->push(base::Bind(&VideoRenderer::Play, video_renderer_)); |
| 507 | 489 |
| 508 RunInSeries(closures.Pass(), done_cb); | 490 RunInSeries(closures.Pass(), done_cb); |
| 509 } | 491 } |
| 510 | 492 |
| 511 void Pipeline::DoStop(const base::Closure& done_cb) { | 493 void Pipeline::DoStop(const base::Closure& done_cb) { |
| 512 DCHECK(message_loop_->BelongsToCurrentThread()); | 494 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 513 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 495 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 514 | 496 |
| 515 if (demuxer_) | 497 if (demuxer_) |
| 516 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); | 498 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); |
| 517 | 499 |
| 518 if (audio_renderer_) | 500 if (audio_renderer_) |
| 519 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); | 501 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); |
| 520 | 502 |
| 521 if (pipeline_filter_) | 503 if (video_renderer_) |
| 522 closures->push(base::Bind(&Filter::Stop, pipeline_filter_)); | 504 closures->push(base::Bind(&VideoRenderer::Stop, video_renderer_)); |
| 523 | 505 |
| 524 RunInSeries(closures.Pass(), done_cb); | 506 RunInSeries(closures.Pass(), done_cb); |
| 525 } | 507 } |
| 526 | 508 |
| 527 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { | 509 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { |
| 528 DCHECK(IsRunning()); | 510 DCHECK(IsRunning()); |
| 529 base::AutoLock auto_lock(lock_); | 511 base::AutoLock auto_lock(lock_); |
| 530 buffered_byte_ranges_.Add(start, end); | 512 buffered_byte_ranges_.Add(start, end); |
| 531 did_loading_progress_ = true; | 513 did_loading_progress_ = true; |
| 532 } | 514 } |
| 533 | 515 |
| 534 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, | 516 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, |
| 535 base::TimeDelta end) { | 517 base::TimeDelta end) { |
| 536 DCHECK(IsRunning()); | 518 DCHECK(IsRunning()); |
| 537 base::AutoLock auto_lock(lock_); | 519 base::AutoLock auto_lock(lock_); |
| 538 buffered_time_ranges_.Add(start, end); | 520 buffered_time_ranges_.Add(start, end); |
| 539 did_loading_progress_ = true; | 521 did_loading_progress_ = true; |
| 540 } | 522 } |
| 541 | 523 |
| 542 void Pipeline::SetNaturalVideoSize(const gfx::Size& size) { | 524 void Pipeline::OnNaturalVideoSizeChanged(const gfx::Size& size) { |
| 543 DCHECK(IsRunning()); | 525 DCHECK(IsRunning()); |
| 544 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( | 526 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( |
| 545 size.width(), size.height())); | 527 size.width(), size.height())); |
| 546 | 528 |
| 547 base::AutoLock auto_lock(lock_); | 529 base::AutoLock auto_lock(lock_); |
| 548 natural_size_ = size; | 530 natural_size_ = size; |
| 549 } | 531 } |
| 550 | 532 |
| 551 void Pipeline::NotifyEnded() { | 533 void Pipeline::OnRendererEnded() { |
| 552 DCHECK(IsRunning()); | 534 DCHECK(IsRunning()); |
| 553 message_loop_->PostTask(FROM_HERE, base::Bind( | 535 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 554 &Pipeline::NotifyEndedTask, this)); | 536 &Pipeline::OnRendererEndedTask, this)); |
| 555 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 537 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
| 556 } | 538 } |
| 557 | 539 |
| 558 // Called from any thread. | 540 // Called from any thread. |
| 559 void Pipeline::OnFilterInitialize(PipelineStatus status) { | 541 void Pipeline::OnFilterInitialize(PipelineStatus status) { |
| 560 // Continue the initialize task by proceeding to the next stage. | 542 // Continue the initialize task by proceeding to the next stage. |
| 561 message_loop_->PostTask(FROM_HERE, base::Bind( | 543 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 562 &Pipeline::InitializeTask, this, status)); | 544 &Pipeline::InitializeTask, this, status)); |
| 563 } | 545 } |
| 564 | 546 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 const PipelineStatusCB& start_cb) { | 583 const PipelineStatusCB& start_cb) { |
| 602 DCHECK(message_loop_->BelongsToCurrentThread()); | 584 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 603 DCHECK_EQ(kCreated, state_); | 585 DCHECK_EQ(kCreated, state_); |
| 604 filter_collection_ = filter_collection.Pass(); | 586 filter_collection_ = filter_collection.Pass(); |
| 605 ended_cb_ = ended_cb; | 587 ended_cb_ = ended_cb; |
| 606 error_cb_ = error_cb; | 588 error_cb_ = error_cb; |
| 607 seek_cb_ = start_cb; | 589 seek_cb_ = start_cb; |
| 608 | 590 |
| 609 // Kick off initialization. | 591 // Kick off initialization. |
| 610 pipeline_init_state_.reset(new PipelineInitState()); | 592 pipeline_init_state_.reset(new PipelineInitState()); |
| 611 pipeline_init_state_->composite = new CompositeFilter(message_loop_); | |
| 612 pipeline_init_state_->composite->SetHost(this); | |
| 613 | 593 |
| 614 SetState(kInitDemuxer); | 594 SetState(kInitDemuxer); |
| 615 InitializeDemuxer(); | 595 InitializeDemuxer(); |
| 616 } | 596 } |
| 617 | 597 |
| 618 // Main initialization method called on the pipeline thread. This code attempts | 598 // Main initialization method called on the pipeline thread. This code attempts |
| 619 // to use the specified filter factory to build a pipeline. | 599 // to use the specified filter factory to build a pipeline. |
| 620 // Initialization step performed in this method depends on current state of this | 600 // Initialization step performed in this method depends on current state of this |
| 621 // object, indicated by |state_|. After each step of initialization, this | 601 // object, indicated by |state_|. After each step of initialization, this |
| 622 // object transits to the next stage. It starts by creating a Demuxer, and then | 602 // object transits to the next stage. It starts by creating a Demuxer, and then |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 return; | 672 return; |
| 693 } | 673 } |
| 694 } | 674 } |
| 695 | 675 |
| 696 if (state_ == kInitVideoRenderer) { | 676 if (state_ == kInitVideoRenderer) { |
| 697 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { | 677 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { |
| 698 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); | 678 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); |
| 699 return; | 679 return; |
| 700 } | 680 } |
| 701 | 681 |
| 702 // Clear the collection of filters. | 682 // Clear initialization state now that we're done. |
| 703 filter_collection_->Clear(); | 683 filter_collection_.reset(); |
| 704 | |
| 705 pipeline_filter_ = pipeline_init_state_->composite; | |
| 706 | |
| 707 // Clear init state since we're done initializing. | |
| 708 pipeline_init_state_.reset(); | 684 pipeline_init_state_.reset(); |
| 709 | 685 |
| 710 // Initialization was successful, we are now considered paused, so it's safe | 686 // Initialization was successful, we are now considered paused, so it's safe |
| 711 // to set the initial playback rate and volume. | 687 // to set the initial playback rate and volume. |
| 712 PlaybackRateChangedTask(GetPlaybackRate()); | 688 PlaybackRateChangedTask(GetPlaybackRate()); |
| 713 VolumeChangedTask(GetVolume()); | 689 VolumeChangedTask(GetVolume()); |
| 714 | 690 |
| 715 // Fire a seek request to get the renderers to preroll. We can skip a seek | 691 // Fire a seek request to get the renderers to preroll. We can skip a seek |
| 716 // here as the demuxer should be at the start of the stream. | 692 // here as the demuxer should be at the start of the stream. |
| 717 seek_pending_ = true; | 693 seek_pending_ = true; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 pending_playback_rate_ = playback_rate; | 772 pending_playback_rate_ = playback_rate; |
| 797 playback_rate_change_pending_ = true; | 773 playback_rate_change_pending_ = true; |
| 798 return; | 774 return; |
| 799 } | 775 } |
| 800 | 776 |
| 801 { | 777 { |
| 802 base::AutoLock auto_lock(lock_); | 778 base::AutoLock auto_lock(lock_); |
| 803 clock_->SetPlaybackRate(playback_rate); | 779 clock_->SetPlaybackRate(playback_rate); |
| 804 } | 780 } |
| 805 | 781 |
| 806 // Notify |pipeline_filter_| if it has been initialized. If initialization | 782 // These will get set after initialization completes in case playback rate is |
| 807 // hasn't completed yet, the playback rate will be set when initialization | 783 // set prior to initialization. |
| 808 // completes. | 784 if (demuxer_) |
| 809 if (pipeline_filter_) { | |
| 810 demuxer_->SetPlaybackRate(playback_rate); | 785 demuxer_->SetPlaybackRate(playback_rate); |
| 811 pipeline_filter_->SetPlaybackRate(playback_rate); | 786 if (audio_renderer_) |
| 812 | 787 audio_renderer_->SetPlaybackRate(playback_rate_); |
| 813 if (audio_renderer_) | 788 if (video_renderer_) |
| 814 audio_renderer_->SetPlaybackRate(playback_rate_); | 789 video_renderer_->SetPlaybackRate(playback_rate_); |
| 815 } | |
| 816 } | 790 } |
| 817 | 791 |
| 818 void Pipeline::VolumeChangedTask(float volume) { | 792 void Pipeline::VolumeChangedTask(float volume) { |
| 819 DCHECK(message_loop_->BelongsToCurrentThread()); | 793 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 820 if (!running_ || tearing_down_) | 794 if (!running_ || tearing_down_) |
| 821 return; | 795 return; |
| 822 | 796 |
| 823 if (audio_renderer_) | 797 if (audio_renderer_) |
| 824 audio_renderer_->SetVolume(volume); | 798 audio_renderer_->SetVolume(volume); |
| 825 } | 799 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 853 | 827 |
| 854 // Kick off seeking! | 828 // Kick off seeking! |
| 855 { | 829 { |
| 856 base::AutoLock auto_lock(lock_); | 830 base::AutoLock auto_lock(lock_); |
| 857 if (clock_->IsPlaying()) | 831 if (clock_->IsPlaying()) |
| 858 clock_->Pause(); | 832 clock_->Pause(); |
| 859 } | 833 } |
| 860 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); | 834 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
| 861 } | 835 } |
| 862 | 836 |
| 863 void Pipeline::NotifyEndedTask() { | 837 void Pipeline::OnRendererEndedTask() { |
| 864 DCHECK(message_loop_->BelongsToCurrentThread()); | 838 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 865 | 839 |
| 866 // We can only end if we were actually playing. | 840 // We can only end if we were actually playing. |
| 867 if (state_ != kStarted) { | 841 if (state_ != kStarted) { |
| 868 return; | 842 return; |
| 869 } | 843 } |
| 870 | 844 |
| 871 DCHECK(audio_renderer_ || video_renderer_); | 845 DCHECK(audio_renderer_ || video_renderer_); |
| 872 | 846 |
| 873 // Make sure every extant renderer has ended. | 847 // Make sure every extant renderer has ended. |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 break; | 994 break; |
| 1021 // default: intentionally left out to force new states to cause compiler | 995 // default: intentionally left out to force new states to cause compiler |
| 1022 // errors. | 996 // errors. |
| 1023 }; | 997 }; |
| 1024 } | 998 } |
| 1025 | 999 |
| 1026 void Pipeline::FinishDestroyingFiltersTask() { | 1000 void Pipeline::FinishDestroyingFiltersTask() { |
| 1027 DCHECK(message_loop_->BelongsToCurrentThread()); | 1001 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1028 DCHECK(IsPipelineStopped()); | 1002 DCHECK(IsPipelineStopped()); |
| 1029 | 1003 |
| 1030 // Clear filter references. | |
| 1031 audio_renderer_ = NULL; | 1004 audio_renderer_ = NULL; |
| 1032 video_renderer_ = NULL; | 1005 video_renderer_ = NULL; |
| 1033 demuxer_ = NULL; | 1006 demuxer_ = NULL; |
| 1034 | 1007 |
| 1035 pipeline_filter_ = NULL; | |
| 1036 | |
| 1037 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) | 1008 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) |
| 1038 error_cb_.Run(status_); | 1009 error_cb_.Run(status_); |
| 1039 | 1010 |
| 1040 if (stop_pending_) { | 1011 if (stop_pending_) { |
| 1041 stop_pending_ = false; | 1012 stop_pending_ = false; |
| 1042 ResetState(); | 1013 ResetState(); |
| 1043 // Notify the client that stopping has finished. | 1014 // Notify the client that stopping has finished. |
| 1044 base::ResetAndReturn(&stop_cb_).Run(); | 1015 base::ResetAndReturn(&stop_cb_).Run(); |
| 1045 } | 1016 } |
| 1046 | 1017 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 if (!audio_renderer_) { | 1120 if (!audio_renderer_) { |
| 1150 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1121 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1151 return false; | 1122 return false; |
| 1152 } | 1123 } |
| 1153 | 1124 |
| 1154 audio_renderer_->Initialize( | 1125 audio_renderer_->Initialize( |
| 1155 decoder, | 1126 decoder, |
| 1156 base::Bind(&Pipeline::OnFilterInitialize, this), | 1127 base::Bind(&Pipeline::OnFilterInitialize, this), |
| 1157 base::Bind(&Pipeline::OnAudioUnderflow, this), | 1128 base::Bind(&Pipeline::OnAudioUnderflow, this), |
| 1158 base::Bind(&Pipeline::OnAudioTimeUpdate, this), | 1129 base::Bind(&Pipeline::OnAudioTimeUpdate, this), |
| 1159 base::Bind(&Pipeline::NotifyEnded, this), | 1130 base::Bind(&Pipeline::OnRendererEnded, this), |
| 1160 base::Bind(&Pipeline::OnAudioDisabled, this), | 1131 base::Bind(&Pipeline::OnAudioDisabled, this), |
| 1161 base::Bind(&Pipeline::SetError, this)); | 1132 base::Bind(&Pipeline::SetError, this)); |
| 1162 return true; | 1133 return true; |
| 1163 } | 1134 } |
| 1164 | 1135 |
| 1165 bool Pipeline::InitializeVideoRenderer( | 1136 bool Pipeline::InitializeVideoRenderer( |
| 1166 const scoped_refptr<VideoDecoder>& decoder) { | 1137 const scoped_refptr<VideoDecoder>& decoder) { |
| 1167 DCHECK(message_loop_->BelongsToCurrentThread()); | 1138 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1168 DCHECK(IsPipelineOk()); | 1139 DCHECK(IsPipelineOk()); |
| 1169 | 1140 |
| 1170 if (!decoder) | 1141 if (!decoder) |
| 1171 return false; | 1142 return false; |
| 1172 | 1143 |
| 1173 filter_collection_->SelectVideoRenderer( | 1144 filter_collection_->SelectVideoRenderer(&video_renderer_); |
| 1174 &pipeline_init_state_->video_renderer); | 1145 if (!video_renderer_) { |
| 1175 if (!pipeline_init_state_->video_renderer) { | |
| 1176 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1146 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1177 return false; | 1147 return false; |
| 1178 } | 1148 } |
| 1179 | 1149 |
| 1180 pipeline_init_state_->composite->AddFilter( | 1150 video_renderer_->Initialize( |
| 1181 pipeline_init_state_->video_renderer); | |
| 1182 | |
| 1183 pipeline_init_state_->video_renderer->Initialize( | |
| 1184 decoder, | 1151 decoder, |
| 1185 base::Bind(&Pipeline::OnFilterInitialize, this), | 1152 base::Bind(&Pipeline::OnFilterInitialize, this), |
| 1186 base::Bind(&Pipeline::OnUpdateStatistics, this), | 1153 base::Bind(&Pipeline::OnUpdateStatistics, this), |
| 1187 base::Bind(&Pipeline::OnVideoTimeUpdate, this)); | 1154 base::Bind(&Pipeline::OnVideoTimeUpdate, this), |
| 1188 | 1155 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), |
| 1189 video_renderer_ = pipeline_init_state_->video_renderer; | 1156 base::Bind(&Pipeline::OnRendererEnded, this), |
| 1157 base::Bind(&Pipeline::SetError, this), |
| 1158 base::Bind(&Pipeline::GetMediaTime, this), |
| 1159 base::Bind(&Pipeline::GetMediaDuration, this)); |
| 1190 return true; | 1160 return true; |
| 1191 } | 1161 } |
| 1192 | 1162 |
| 1193 void Pipeline::TearDownPipeline() { | 1163 void Pipeline::TearDownPipeline() { |
| 1194 DCHECK(message_loop_->BelongsToCurrentThread()); | 1164 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1195 DCHECK_NE(kStopped, state_); | 1165 DCHECK_NE(kStopped, state_); |
| 1196 | 1166 |
| 1197 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1167 DCHECK(!tearing_down_ || // Teardown on Stop(). |
| 1198 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1168 (tearing_down_ && error_caused_teardown_) || // Teardown on error. |
| 1199 (tearing_down_ && stop_pending_)); // Stop during teardown by error. | 1169 (tearing_down_ && stop_pending_)); // Stop during teardown by error. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1210 message_loop_->PostTask(FROM_HERE, base::Bind( | 1180 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 1211 &Pipeline::FinishDestroyingFiltersTask, this)); | 1181 &Pipeline::FinishDestroyingFiltersTask, this)); |
| 1212 break; | 1182 break; |
| 1213 | 1183 |
| 1214 case kInitDemuxer: | 1184 case kInitDemuxer: |
| 1215 case kInitAudioDecoder: | 1185 case kInitAudioDecoder: |
| 1216 case kInitAudioRenderer: | 1186 case kInitAudioRenderer: |
| 1217 case kInitVideoDecoder: | 1187 case kInitVideoDecoder: |
| 1218 case kInitVideoRenderer: | 1188 case kInitVideoRenderer: |
| 1219 // Make it look like initialization was successful. | 1189 // Make it look like initialization was successful. |
| 1220 pipeline_filter_ = pipeline_init_state_->composite; | 1190 filter_collection_.reset(); |
| 1221 pipeline_init_state_.reset(); | 1191 pipeline_init_state_.reset(); |
| 1222 filter_collection_.reset(); | |
| 1223 | 1192 |
| 1224 SetState(kStopping); | 1193 SetState(kStopping); |
| 1225 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 1194 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
| 1226 | 1195 |
| 1227 FinishInitialization(); | 1196 FinishInitialization(); |
| 1228 break; | 1197 break; |
| 1229 | 1198 |
| 1230 case kPausing: | 1199 case kPausing: |
| 1231 case kSeeking: | 1200 case kSeeking: |
| 1232 case kFlushing: | 1201 case kFlushing: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1263 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( | 1232 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( |
| 1264 new std::queue<PipelineStatusCBFunc>()); | 1233 new std::queue<PipelineStatusCBFunc>()); |
| 1265 | 1234 |
| 1266 if (!skip_demuxer_seek) | 1235 if (!skip_demuxer_seek) |
| 1267 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); | 1236 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); |
| 1268 | 1237 |
| 1269 if (audio_renderer_) | 1238 if (audio_renderer_) |
| 1270 status_cbs->push(base::Bind( | 1239 status_cbs->push(base::Bind( |
| 1271 &AudioRenderer::Seek, audio_renderer_, seek_timestamp)); | 1240 &AudioRenderer::Seek, audio_renderer_, seek_timestamp)); |
| 1272 | 1241 |
| 1273 if (pipeline_filter_) | 1242 if (video_renderer_) |
| 1274 status_cbs->push(base::Bind( | 1243 status_cbs->push(base::Bind( |
| 1275 &Filter::Seek, pipeline_filter_, seek_timestamp)); | 1244 &VideoRenderer::Seek, video_renderer_, seek_timestamp)); |
| 1276 | 1245 |
| 1277 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( | 1246 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( |
| 1278 &Pipeline::ReportStatus, this, done_cb)); | 1247 &Pipeline::ReportStatus, this, done_cb)); |
| 1279 } | 1248 } |
| 1280 | 1249 |
| 1281 void Pipeline::OnAudioUnderflow() { | 1250 void Pipeline::OnAudioUnderflow() { |
| 1282 if (!message_loop_->BelongsToCurrentThread()) { | 1251 if (!message_loop_->BelongsToCurrentThread()) { |
| 1283 message_loop_->PostTask(FROM_HERE, base::Bind( | 1252 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 1284 &Pipeline::OnAudioUnderflow, this)); | 1253 &Pipeline::OnAudioUnderflow, this)); |
| 1285 return; | 1254 return; |
| 1286 } | 1255 } |
| 1287 | 1256 |
| 1288 if (state_ != kStarted) | 1257 if (state_ != kStarted) |
| 1289 return; | 1258 return; |
| 1290 | 1259 |
| 1291 if (audio_renderer_) | 1260 if (audio_renderer_) |
| 1292 audio_renderer_->ResumeAfterUnderflow(true); | 1261 audio_renderer_->ResumeAfterUnderflow(true); |
| 1293 } | 1262 } |
| 1294 | 1263 |
| 1295 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1264 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 1296 lock_.AssertAcquired(); | 1265 lock_.AssertAcquired(); |
| 1297 if (!waiting_for_clock_update_) | 1266 if (!waiting_for_clock_update_) |
| 1298 return; | 1267 return; |
| 1299 | 1268 |
| 1300 waiting_for_clock_update_ = false; | 1269 waiting_for_clock_update_ = false; |
| 1301 clock_->Play(); | 1270 clock_->Play(); |
| 1302 } | 1271 } |
| 1303 | 1272 |
| 1304 } // namespace media | 1273 } // namespace media |
| OLD | NEW |