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 |