Chromium Code Reviews| 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 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 DCHECK(IsRunning()); | 371 DCHECK(IsRunning()); |
| 375 DCHECK_NE(PIPELINE_OK, error); | 372 DCHECK_NE(PIPELINE_OK, error); |
| 376 VLOG(1) << "Media pipeline error: " << error; | 373 VLOG(1) << "Media pipeline error: " << error; |
| 377 | 374 |
| 378 message_loop_->PostTask(FROM_HERE, base::Bind( | 375 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 379 &Pipeline::ErrorChangedTask, this, error)); | 376 &Pipeline::ErrorChangedTask, this, error)); |
| 380 | 377 |
| 381 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); | 378 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); |
| 382 } | 379 } |
| 383 | 380 |
| 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() { | 381 void Pipeline::OnAudioDisabled() { |
| 395 DCHECK(IsRunning()); | 382 DCHECK(IsRunning()); |
| 396 message_loop_->PostTask(FROM_HERE, base::Bind( | 383 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 397 &Pipeline::AudioDisabledTask, this)); | 384 &Pipeline::AudioDisabledTask, this)); |
| 398 media_log_->AddEvent( | 385 media_log_->AddEvent( |
| 399 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 386 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); |
| 400 } | 387 } |
| 401 | 388 |
| 402 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 389 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
| 403 DCHECK(time <= max_time); | 390 DCHECK(time <= max_time); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 return time_offset; | 456 return time_offset; |
| 470 } | 457 } |
| 471 | 458 |
| 472 void Pipeline::DoPause(const base::Closure& done_cb) { | 459 void Pipeline::DoPause(const base::Closure& done_cb) { |
| 473 DCHECK(message_loop_->BelongsToCurrentThread()); | 460 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 474 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 461 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 475 | 462 |
| 476 if (audio_renderer_) | 463 if (audio_renderer_) |
| 477 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); | 464 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); |
| 478 | 465 |
| 479 if (pipeline_filter_) | 466 if (video_renderer_) |
| 480 closures->push(base::Bind(&Filter::Pause, pipeline_filter_)); | 467 closures->push(base::Bind(&VideoRenderer::Pause, video_renderer_)); |
| 481 | 468 |
| 482 RunInSeries(closures.Pass(), done_cb); | 469 RunInSeries(closures.Pass(), done_cb); |
| 483 } | 470 } |
| 484 | 471 |
| 485 void Pipeline::DoFlush(const base::Closure& done_cb) { | 472 void Pipeline::DoFlush(const base::Closure& done_cb) { |
| 486 DCHECK(message_loop_->BelongsToCurrentThread()); | 473 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 487 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 474 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 488 | 475 |
| 489 if (audio_renderer_) | 476 if (audio_renderer_) |
| 490 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); | 477 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); |
| 491 | 478 |
| 492 if (pipeline_filter_) | 479 if (video_renderer_) |
| 493 closures->push(base::Bind(&Filter::Flush, pipeline_filter_)); | 480 closures->push(base::Bind(&VideoRenderer::Flush, video_renderer_)); |
| 494 | 481 |
| 495 RunInParallel(closures.Pass(), done_cb); | 482 RunInParallel(closures.Pass(), done_cb); |
| 496 } | 483 } |
| 497 | 484 |
| 498 void Pipeline::DoPlay(const base::Closure& done_cb) { | 485 void Pipeline::DoPlay(const base::Closure& done_cb) { |
| 499 DCHECK(message_loop_->BelongsToCurrentThread()); | 486 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 500 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 487 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 501 | 488 |
| 502 if (audio_renderer_) | 489 if (audio_renderer_) |
| 503 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); | 490 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); |
| 504 | 491 |
| 505 if (pipeline_filter_) | 492 if (video_renderer_) |
| 506 closures->push(base::Bind(&Filter::Play, pipeline_filter_)); | 493 closures->push(base::Bind(&VideoRenderer::Play, video_renderer_)); |
| 507 | 494 |
| 508 RunInSeries(closures.Pass(), done_cb); | 495 RunInSeries(closures.Pass(), done_cb); |
| 509 } | 496 } |
| 510 | 497 |
| 511 void Pipeline::DoStop(const base::Closure& done_cb) { | 498 void Pipeline::DoStop(const base::Closure& done_cb) { |
| 512 DCHECK(message_loop_->BelongsToCurrentThread()); | 499 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 513 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 500 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
| 514 | 501 |
| 515 if (demuxer_) | 502 if (demuxer_) |
| 516 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); | 503 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); |
| 517 | 504 |
| 518 if (audio_renderer_) | 505 if (audio_renderer_) |
| 519 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); | 506 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); |
| 520 | 507 |
| 521 if (pipeline_filter_) | 508 if (video_renderer_) |
| 522 closures->push(base::Bind(&Filter::Stop, pipeline_filter_)); | 509 closures->push(base::Bind(&VideoRenderer::Stop, video_renderer_)); |
| 523 | 510 |
| 524 RunInSeries(closures.Pass(), done_cb); | 511 RunInSeries(closures.Pass(), done_cb); |
| 525 } | 512 } |
| 526 | 513 |
| 527 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { | 514 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { |
| 528 DCHECK(IsRunning()); | 515 DCHECK(IsRunning()); |
| 529 base::AutoLock auto_lock(lock_); | 516 base::AutoLock auto_lock(lock_); |
| 530 buffered_byte_ranges_.Add(start, end); | 517 buffered_byte_ranges_.Add(start, end); |
| 531 did_loading_progress_ = true; | 518 did_loading_progress_ = true; |
| 532 } | 519 } |
| 533 | 520 |
| 534 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, | 521 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, |
| 535 base::TimeDelta end) { | 522 base::TimeDelta end) { |
| 536 DCHECK(IsRunning()); | 523 DCHECK(IsRunning()); |
| 537 base::AutoLock auto_lock(lock_); | 524 base::AutoLock auto_lock(lock_); |
| 538 buffered_time_ranges_.Add(start, end); | 525 buffered_time_ranges_.Add(start, end); |
| 539 did_loading_progress_ = true; | 526 did_loading_progress_ = true; |
| 540 } | 527 } |
| 541 | 528 |
| 542 void Pipeline::SetNaturalVideoSize(const gfx::Size& size) { | 529 void Pipeline::OnNaturalVideoSizeChanged(const gfx::Size& size) { |
| 543 DCHECK(IsRunning()); | 530 DCHECK(IsRunning()); |
| 544 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( | 531 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( |
| 545 size.width(), size.height())); | 532 size.width(), size.height())); |
| 546 | 533 |
| 547 base::AutoLock auto_lock(lock_); | 534 base::AutoLock auto_lock(lock_); |
| 548 natural_size_ = size; | 535 natural_size_ = size; |
| 549 } | 536 } |
| 550 | 537 |
| 551 void Pipeline::NotifyEnded() { | 538 void Pipeline::OnRendererEnded() { |
| 552 DCHECK(IsRunning()); | 539 DCHECK(IsRunning()); |
| 553 message_loop_->PostTask(FROM_HERE, base::Bind( | 540 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 554 &Pipeline::NotifyEndedTask, this)); | 541 &Pipeline::OnRendererEndedTask, this)); |
| 555 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 542 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
| 556 } | 543 } |
| 557 | 544 |
| 558 // Called from any thread. | 545 // Called from any thread. |
| 559 void Pipeline::OnFilterInitialize(PipelineStatus status) { | 546 void Pipeline::OnFilterInitialize(PipelineStatus status) { |
| 560 // Continue the initialize task by proceeding to the next stage. | 547 // Continue the initialize task by proceeding to the next stage. |
| 561 message_loop_->PostTask(FROM_HERE, base::Bind( | 548 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 562 &Pipeline::InitializeTask, this, status)); | 549 &Pipeline::InitializeTask, this, status)); |
| 563 } | 550 } |
| 564 | 551 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 const PipelineStatusCB& start_cb) { | 588 const PipelineStatusCB& start_cb) { |
| 602 DCHECK(message_loop_->BelongsToCurrentThread()); | 589 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 603 DCHECK_EQ(kCreated, state_); | 590 DCHECK_EQ(kCreated, state_); |
| 604 filter_collection_ = filter_collection.Pass(); | 591 filter_collection_ = filter_collection.Pass(); |
| 605 ended_cb_ = ended_cb; | 592 ended_cb_ = ended_cb; |
| 606 error_cb_ = error_cb; | 593 error_cb_ = error_cb; |
| 607 seek_cb_ = start_cb; | 594 seek_cb_ = start_cb; |
| 608 | 595 |
| 609 // Kick off initialization. | 596 // Kick off initialization. |
| 610 pipeline_init_state_.reset(new PipelineInitState()); | 597 pipeline_init_state_.reset(new PipelineInitState()); |
| 611 pipeline_init_state_->composite = new CompositeFilter(message_loop_); | |
| 612 pipeline_init_state_->composite->SetHost(this); | |
| 613 | 598 |
| 614 SetState(kInitDemuxer); | 599 SetState(kInitDemuxer); |
| 615 InitializeDemuxer(); | 600 InitializeDemuxer(); |
| 616 } | 601 } |
| 617 | 602 |
| 618 // Main initialization method called on the pipeline thread. This code attempts | 603 // Main initialization method called on the pipeline thread. This code attempts |
| 619 // to use the specified filter factory to build a pipeline. | 604 // to use the specified filter factory to build a pipeline. |
| 620 // Initialization step performed in this method depends on current state of this | 605 // Initialization step performed in this method depends on current state of this |
| 621 // object, indicated by |state_|. After each step of initialization, this | 606 // 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 | 607 // 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; | 677 return; |
| 693 } | 678 } |
| 694 } | 679 } |
| 695 | 680 |
| 696 if (state_ == kInitVideoRenderer) { | 681 if (state_ == kInitVideoRenderer) { |
| 697 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { | 682 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { |
| 698 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); | 683 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); |
| 699 return; | 684 return; |
| 700 } | 685 } |
| 701 | 686 |
| 702 // Clear the collection of filters. | 687 // Clear initialization state now that we're done. |
| 703 filter_collection_->Clear(); | 688 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(); | 689 pipeline_init_state_.reset(); |
| 709 | 690 |
| 710 // Initialization was successful, we are now considered paused, so it's safe | 691 // Initialization was successful, we are now considered paused, so it's safe |
| 711 // to set the initial playback rate and volume. | 692 // to set the initial playback rate and volume. |
| 712 PlaybackRateChangedTask(GetPlaybackRate()); | 693 PlaybackRateChangedTask(GetPlaybackRate()); |
| 713 VolumeChangedTask(GetVolume()); | 694 VolumeChangedTask(GetVolume()); |
| 714 | 695 |
| 715 // Fire a seek request to get the renderers to preroll. We can skip a seek | 696 // 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. | 697 // here as the demuxer should be at the start of the stream. |
| 717 seek_pending_ = true; | 698 seek_pending_ = true; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 796 pending_playback_rate_ = playback_rate; | 777 pending_playback_rate_ = playback_rate; |
| 797 playback_rate_change_pending_ = true; | 778 playback_rate_change_pending_ = true; |
| 798 return; | 779 return; |
| 799 } | 780 } |
| 800 | 781 |
| 801 { | 782 { |
| 802 base::AutoLock auto_lock(lock_); | 783 base::AutoLock auto_lock(lock_); |
| 803 clock_->SetPlaybackRate(playback_rate); | 784 clock_->SetPlaybackRate(playback_rate); |
| 804 } | 785 } |
| 805 | 786 |
| 806 // Notify |pipeline_filter_| if it has been initialized. If initialization | 787 // 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 | 788 // set prior to initialization. |
| 808 // completes. | 789 if (demuxer_) |
| 809 if (pipeline_filter_) { | |
| 810 demuxer_->SetPlaybackRate(playback_rate); | 790 demuxer_->SetPlaybackRate(playback_rate); |
| 811 pipeline_filter_->SetPlaybackRate(playback_rate); | 791 if (audio_renderer_) |
| 812 | 792 audio_renderer_->SetPlaybackRate(playback_rate_); |
| 813 if (audio_renderer_) | 793 if (video_renderer_) |
| 814 audio_renderer_->SetPlaybackRate(playback_rate_); | 794 video_renderer_->SetPlaybackRate(playback_rate_); |
| 815 } | |
| 816 } | 795 } |
| 817 | 796 |
| 818 void Pipeline::VolumeChangedTask(float volume) { | 797 void Pipeline::VolumeChangedTask(float volume) { |
| 819 DCHECK(message_loop_->BelongsToCurrentThread()); | 798 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 820 if (!running_ || tearing_down_) | 799 if (!running_ || tearing_down_) |
| 821 return; | 800 return; |
| 822 | 801 |
| 823 if (audio_renderer_) | 802 if (audio_renderer_) |
| 824 audio_renderer_->SetVolume(volume); | 803 audio_renderer_->SetVolume(volume); |
| 825 } | 804 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 853 | 832 |
| 854 // Kick off seeking! | 833 // Kick off seeking! |
| 855 { | 834 { |
| 856 base::AutoLock auto_lock(lock_); | 835 base::AutoLock auto_lock(lock_); |
| 857 if (clock_->IsPlaying()) | 836 if (clock_->IsPlaying()) |
| 858 clock_->Pause(); | 837 clock_->Pause(); |
| 859 } | 838 } |
| 860 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); | 839 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
| 861 } | 840 } |
| 862 | 841 |
| 863 void Pipeline::NotifyEndedTask() { | 842 void Pipeline::OnRendererEndedTask() { |
| 864 DCHECK(message_loop_->BelongsToCurrentThread()); | 843 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 865 | 844 |
| 866 // We can only end if we were actually playing. | 845 // We can only end if we were actually playing. |
| 867 if (state_ != kStarted) { | 846 if (state_ != kStarted) { |
| 868 return; | 847 return; |
| 869 } | 848 } |
| 870 | 849 |
| 871 DCHECK(audio_renderer_ || video_renderer_); | 850 DCHECK(audio_renderer_ || video_renderer_); |
| 872 | 851 |
| 873 // Make sure every extant renderer has ended. | 852 // Make sure every extant renderer has ended. |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1020 break; | 999 break; |
| 1021 // default: intentionally left out to force new states to cause compiler | 1000 // default: intentionally left out to force new states to cause compiler |
| 1022 // errors. | 1001 // errors. |
| 1023 }; | 1002 }; |
| 1024 } | 1003 } |
| 1025 | 1004 |
| 1026 void Pipeline::FinishDestroyingFiltersTask() { | 1005 void Pipeline::FinishDestroyingFiltersTask() { |
| 1027 DCHECK(message_loop_->BelongsToCurrentThread()); | 1006 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1028 DCHECK(IsPipelineStopped()); | 1007 DCHECK(IsPipelineStopped()); |
| 1029 | 1008 |
| 1030 // Clear filter references. | |
| 1031 audio_renderer_ = NULL; | 1009 audio_renderer_ = NULL; |
| 1032 video_renderer_ = NULL; | 1010 video_renderer_ = NULL; |
| 1033 demuxer_ = NULL; | 1011 demuxer_ = NULL; |
| 1034 | 1012 |
| 1035 pipeline_filter_ = NULL; | |
| 1036 | |
| 1037 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) | 1013 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) |
| 1038 error_cb_.Run(status_); | 1014 error_cb_.Run(status_); |
| 1039 | 1015 |
| 1040 if (stop_pending_) { | 1016 if (stop_pending_) { |
| 1041 stop_pending_ = false; | 1017 stop_pending_ = false; |
| 1042 ResetState(); | 1018 ResetState(); |
| 1043 // Notify the client that stopping has finished. | 1019 // Notify the client that stopping has finished. |
| 1044 base::ResetAndReturn(&stop_cb_).Run(); | 1020 base::ResetAndReturn(&stop_cb_).Run(); |
| 1045 } | 1021 } |
| 1046 | 1022 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1149 if (!audio_renderer_) { | 1125 if (!audio_renderer_) { |
| 1150 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1126 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1151 return false; | 1127 return false; |
| 1152 } | 1128 } |
| 1153 | 1129 |
| 1154 audio_renderer_->Initialize( | 1130 audio_renderer_->Initialize( |
| 1155 decoder, | 1131 decoder, |
| 1156 base::Bind(&Pipeline::OnFilterInitialize, this), | 1132 base::Bind(&Pipeline::OnFilterInitialize, this), |
| 1157 base::Bind(&Pipeline::OnAudioUnderflow, this), | 1133 base::Bind(&Pipeline::OnAudioUnderflow, this), |
| 1158 base::Bind(&Pipeline::OnAudioTimeUpdate, this), | 1134 base::Bind(&Pipeline::OnAudioTimeUpdate, this), |
| 1159 base::Bind(&Pipeline::NotifyEnded, this), | 1135 base::Bind(&Pipeline::OnRendererEnded, this), |
| 1160 base::Bind(&Pipeline::OnAudioDisabled, this), | 1136 base::Bind(&Pipeline::OnAudioDisabled, this), |
| 1161 base::Bind(&Pipeline::SetError, this)); | 1137 base::Bind(&Pipeline::SetError, this)); |
| 1162 return true; | 1138 return true; |
| 1163 } | 1139 } |
| 1164 | 1140 |
| 1165 bool Pipeline::InitializeVideoRenderer( | 1141 bool Pipeline::InitializeVideoRenderer( |
| 1166 const scoped_refptr<VideoDecoder>& decoder) { | 1142 const scoped_refptr<VideoDecoder>& decoder) { |
| 1167 DCHECK(message_loop_->BelongsToCurrentThread()); | 1143 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1168 DCHECK(IsPipelineOk()); | 1144 DCHECK(IsPipelineOk()); |
| 1169 | 1145 |
| 1170 if (!decoder) | 1146 if (!decoder) |
| 1171 return false; | 1147 return false; |
| 1172 | 1148 |
| 1173 filter_collection_->SelectVideoRenderer( | 1149 filter_collection_->SelectVideoRenderer( |
|
Ami GONE FROM CHROMIUM
2012/07/21 05:02:35
single line
scherkus (not reviewing)
2012/07/23 03:21:12
Done.
| |
| 1174 &pipeline_init_state_->video_renderer); | 1150 &video_renderer_); |
| 1175 if (!pipeline_init_state_->video_renderer) { | 1151 if (!video_renderer_) { |
| 1176 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1152 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1177 return false; | 1153 return false; |
| 1178 } | 1154 } |
| 1179 | 1155 |
| 1180 pipeline_init_state_->composite->AddFilter( | 1156 video_renderer_->Initialize( |
| 1181 pipeline_init_state_->video_renderer); | |
| 1182 | |
| 1183 pipeline_init_state_->video_renderer->Initialize( | |
| 1184 decoder, | 1157 decoder, |
| 1185 base::Bind(&Pipeline::OnFilterInitialize, this), | 1158 base::Bind(&Pipeline::OnFilterInitialize, this), |
| 1186 base::Bind(&Pipeline::OnUpdateStatistics, this), | 1159 base::Bind(&Pipeline::OnUpdateStatistics, this), |
| 1187 base::Bind(&Pipeline::OnVideoTimeUpdate, this)); | 1160 base::Bind(&Pipeline::OnVideoTimeUpdate, this), |
| 1188 | 1161 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), |
| 1189 video_renderer_ = pipeline_init_state_->video_renderer; | 1162 base::Bind(&Pipeline::OnRendererEnded, this), |
| 1163 base::Bind(&Pipeline::SetError, this), | |
| 1164 base::Bind(&Pipeline::GetCurrentTime, this), | |
| 1165 base::Bind(&Pipeline::GetMediaDuration, this)); | |
| 1190 return true; | 1166 return true; |
| 1191 } | 1167 } |
| 1192 | 1168 |
| 1193 void Pipeline::TearDownPipeline() { | 1169 void Pipeline::TearDownPipeline() { |
| 1194 DCHECK(message_loop_->BelongsToCurrentThread()); | 1170 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1195 DCHECK_NE(kStopped, state_); | 1171 DCHECK_NE(kStopped, state_); |
| 1196 | 1172 |
| 1197 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1173 DCHECK(!tearing_down_ || // Teardown on Stop(). |
| 1198 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1174 (tearing_down_ && error_caused_teardown_) || // Teardown on error. |
| 1199 (tearing_down_ && stop_pending_)); // Stop during teardown by error. | 1175 (tearing_down_ && stop_pending_)); // Stop during teardown by error. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1210 message_loop_->PostTask(FROM_HERE, base::Bind( | 1186 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 1211 &Pipeline::FinishDestroyingFiltersTask, this)); | 1187 &Pipeline::FinishDestroyingFiltersTask, this)); |
| 1212 break; | 1188 break; |
| 1213 | 1189 |
| 1214 case kInitDemuxer: | 1190 case kInitDemuxer: |
| 1215 case kInitAudioDecoder: | 1191 case kInitAudioDecoder: |
| 1216 case kInitAudioRenderer: | 1192 case kInitAudioRenderer: |
| 1217 case kInitVideoDecoder: | 1193 case kInitVideoDecoder: |
| 1218 case kInitVideoRenderer: | 1194 case kInitVideoRenderer: |
| 1219 // Make it look like initialization was successful. | 1195 // Make it look like initialization was successful. |
| 1220 pipeline_filter_ = pipeline_init_state_->composite; | 1196 filter_collection_.reset(); |
| 1221 pipeline_init_state_.reset(); | 1197 pipeline_init_state_.reset(); |
| 1222 filter_collection_.reset(); | |
| 1223 | 1198 |
| 1224 SetState(kStopping); | 1199 SetState(kStopping); |
| 1225 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 1200 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
| 1226 | 1201 |
| 1227 FinishInitialization(); | 1202 FinishInitialization(); |
| 1228 break; | 1203 break; |
| 1229 | 1204 |
| 1230 case kPausing: | 1205 case kPausing: |
| 1231 case kSeeking: | 1206 case kSeeking: |
| 1232 case kFlushing: | 1207 case kFlushing: |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1263 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( | 1238 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( |
| 1264 new std::queue<PipelineStatusCBFunc>()); | 1239 new std::queue<PipelineStatusCBFunc>()); |
| 1265 | 1240 |
| 1266 if (!skip_demuxer_seek) | 1241 if (!skip_demuxer_seek) |
| 1267 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); | 1242 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); |
| 1268 | 1243 |
| 1269 if (audio_renderer_) | 1244 if (audio_renderer_) |
| 1270 status_cbs->push(base::Bind( | 1245 status_cbs->push(base::Bind( |
| 1271 &AudioRenderer::Seek, audio_renderer_, seek_timestamp)); | 1246 &AudioRenderer::Seek, audio_renderer_, seek_timestamp)); |
| 1272 | 1247 |
| 1273 if (pipeline_filter_) | 1248 if (video_renderer_) |
| 1274 status_cbs->push(base::Bind( | 1249 status_cbs->push(base::Bind( |
| 1275 &Filter::Seek, pipeline_filter_, seek_timestamp)); | 1250 &VideoRenderer::Seek, video_renderer_, seek_timestamp)); |
| 1276 | 1251 |
| 1277 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( | 1252 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( |
| 1278 &Pipeline::ReportStatus, this, done_cb)); | 1253 &Pipeline::ReportStatus, this, done_cb)); |
| 1279 } | 1254 } |
| 1280 | 1255 |
| 1281 void Pipeline::OnAudioUnderflow() { | 1256 void Pipeline::OnAudioUnderflow() { |
| 1282 if (!message_loop_->BelongsToCurrentThread()) { | 1257 if (!message_loop_->BelongsToCurrentThread()) { |
| 1283 message_loop_->PostTask(FROM_HERE, base::Bind( | 1258 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 1284 &Pipeline::OnAudioUnderflow, this)); | 1259 &Pipeline::OnAudioUnderflow, this)); |
| 1285 return; | 1260 return; |
| 1286 } | 1261 } |
| 1287 | 1262 |
| 1288 if (state_ != kStarted) | 1263 if (state_ != kStarted) |
| 1289 return; | 1264 return; |
| 1290 | 1265 |
| 1291 if (audio_renderer_) | 1266 if (audio_renderer_) |
| 1292 audio_renderer_->ResumeAfterUnderflow(true); | 1267 audio_renderer_->ResumeAfterUnderflow(true); |
| 1293 } | 1268 } |
| 1294 | 1269 |
| 1295 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1270 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 1296 lock_.AssertAcquired(); | 1271 lock_.AssertAcquired(); |
| 1297 if (!waiting_for_clock_update_) | 1272 if (!waiting_for_clock_update_) |
| 1298 return; | 1273 return; |
| 1299 | 1274 |
| 1300 waiting_for_clock_update_ = false; | 1275 waiting_for_clock_update_ = false; |
| 1301 clock_->Play(); | 1276 clock_->Play(); |
| 1302 } | 1277 } |
| 1303 | 1278 |
| 1304 } // namespace media | 1279 } // namespace media |
| OLD | NEW |