| 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/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" | 
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" | 
| 15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" | 
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" | 
| 17 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" | 
| 18 #include "base/synchronization/condition_variable.h" | 18 #include "base/synchronization/condition_variable.h" | 
| 19 #include "media/base/audio_decoder.h" | 19 #include "media/base/audio_decoder.h" | 
| 20 #include "media/base/audio_renderer.h" | 20 #include "media/base/audio_renderer.h" | 
| 21 #include "media/base/clock.h" | 21 #include "media/base/clock.h" | 
| 22 #include "media/base/filter_collection.h" | 22 #include "media/base/filter_collection.h" | 
| 23 #include "media/base/media_log.h" | 23 #include "media/base/media_log.h" | 
|  | 24 #include "media/base/text_renderer.h" | 
|  | 25 #include "media/base/text_track_config.h" | 
| 24 #include "media/base/video_decoder.h" | 26 #include "media/base/video_decoder.h" | 
| 25 #include "media/base/video_decoder_config.h" | 27 #include "media/base/video_decoder_config.h" | 
| 26 #include "media/base/video_renderer.h" | 28 #include "media/base/video_renderer.h" | 
| 27 | 29 | 
| 28 using base::TimeDelta; | 30 using base::TimeDelta; | 
| 29 | 31 | 
| 30 namespace media { | 32 namespace media { | 
| 31 | 33 | 
| 32 Pipeline::Pipeline(const scoped_refptr<base::MessageLoopProxy>& message_loop, | 34 Pipeline::Pipeline(const scoped_refptr<base::MessageLoopProxy>& message_loop, | 
| 33                    MediaLog* media_log) | 35                    MediaLog* media_log) | 
| 34     : message_loop_(message_loop), | 36     : message_loop_(message_loop), | 
| 35       media_log_(media_log), | 37       media_log_(media_log), | 
| 36       running_(false), | 38       running_(false), | 
| 37       did_loading_progress_(false), | 39       did_loading_progress_(false), | 
| 38       total_bytes_(0), | 40       total_bytes_(0), | 
| 39       natural_size_(0, 0), | 41       natural_size_(0, 0), | 
| 40       volume_(1.0f), | 42       volume_(1.0f), | 
| 41       playback_rate_(0.0f), | 43       playback_rate_(0.0f), | 
| 42       clock_(new Clock(&default_tick_clock_)), | 44       clock_(new Clock(&default_tick_clock_)), | 
| 43       waiting_for_clock_update_(false), | 45       waiting_for_clock_update_(false), | 
| 44       status_(PIPELINE_OK), | 46       status_(PIPELINE_OK), | 
| 45       has_audio_(false), | 47       has_audio_(false), | 
| 46       has_video_(false), | 48       has_video_(false), | 
| 47       state_(kCreated), | 49       state_(kCreated), | 
| 48       audio_ended_(false), | 50       audio_ended_(false), | 
| 49       video_ended_(false), | 51       video_ended_(false), | 
|  | 52       text_ended_(false), | 
| 50       audio_disabled_(false), | 53       audio_disabled_(false), | 
| 51       demuxer_(NULL), | 54       demuxer_(NULL), | 
| 52       creation_time_(default_tick_clock_.NowTicks()) { | 55       creation_time_(default_tick_clock_.NowTicks()) { | 
| 53   media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 56   media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 
| 54   media_log_->AddEvent( | 57   media_log_->AddEvent( | 
| 55       media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 58       media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 
| 56 } | 59 } | 
| 57 | 60 | 
| 58 Pipeline::~Pipeline() { | 61 Pipeline::~Pipeline() { | 
| 59   DCHECK(thread_checker_.CalledOnValidThread()) | 62   DCHECK(thread_checker_.CalledOnValidThread()) | 
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 286       break; | 289       break; | 
| 287   } | 290   } | 
| 288   NOTREACHED() << "State has no transition: " << state_; | 291   NOTREACHED() << "State has no transition: " << state_; | 
| 289   return state_; | 292   return state_; | 
| 290 } | 293 } | 
| 291 | 294 | 
| 292 void Pipeline::OnDemuxerError(PipelineStatus error) { | 295 void Pipeline::OnDemuxerError(PipelineStatus error) { | 
| 293   SetError(error); | 296   SetError(error); | 
| 294 } | 297 } | 
| 295 | 298 | 
|  | 299 void Pipeline::AddTextStream(DemuxerStream* text_stream, | 
|  | 300                              const TextTrackConfig& config) { | 
|  | 301   message_loop_->PostTask(FROM_HERE, base::Bind( | 
|  | 302     &Pipeline::AddTextStreamTask, base::Unretained(this), | 
|  | 303     text_stream, config)); | 
|  | 304 } | 
|  | 305 | 
|  | 306 void Pipeline::RemoveTextStream(DemuxerStream* text_stream) { | 
|  | 307   message_loop_->PostTask(FROM_HERE, base::Bind( | 
|  | 308     &Pipeline::RemoveTextStreamTask, base::Unretained(this), | 
|  | 309     text_stream)); | 
|  | 310 } | 
|  | 311 | 
| 296 void Pipeline::SetError(PipelineStatus error) { | 312 void Pipeline::SetError(PipelineStatus error) { | 
| 297   DCHECK(IsRunning()); | 313   DCHECK(IsRunning()); | 
| 298   DCHECK_NE(PIPELINE_OK, error); | 314   DCHECK_NE(PIPELINE_OK, error); | 
| 299   VLOG(1) << "Media pipeline error: " << error; | 315   VLOG(1) << "Media pipeline error: " << error; | 
| 300 | 316 | 
| 301   message_loop_->PostTask(FROM_HERE, base::Bind( | 317   message_loop_->PostTask(FROM_HERE, base::Bind( | 
| 302       &Pipeline::ErrorChangedTask, base::Unretained(this), error)); | 318       &Pipeline::ErrorChangedTask, base::Unretained(this), error)); | 
| 303 | 319 | 
| 304   media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); | 320   media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); | 
| 305 } | 321 } | 
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 530 | 546 | 
| 531   // Pause. | 547   // Pause. | 
| 532   if (audio_renderer_) { | 548   if (audio_renderer_) { | 
| 533     bound_fns.Push(base::Bind( | 549     bound_fns.Push(base::Bind( | 
| 534         &AudioRenderer::Pause, base::Unretained(audio_renderer_.get()))); | 550         &AudioRenderer::Pause, base::Unretained(audio_renderer_.get()))); | 
| 535   } | 551   } | 
| 536   if (video_renderer_) { | 552   if (video_renderer_) { | 
| 537     bound_fns.Push(base::Bind( | 553     bound_fns.Push(base::Bind( | 
| 538         &VideoRenderer::Pause, base::Unretained(video_renderer_.get()))); | 554         &VideoRenderer::Pause, base::Unretained(video_renderer_.get()))); | 
| 539   } | 555   } | 
|  | 556   if (text_renderer_) { | 
|  | 557     bound_fns.Push(base::Bind( | 
|  | 558         &TextRenderer::Pause, base::Unretained(text_renderer_.get()))); | 
|  | 559   } | 
| 540 | 560 | 
| 541   // Flush. | 561   // Flush. | 
| 542   if (audio_renderer_) { | 562   if (audio_renderer_) { | 
| 543     bound_fns.Push(base::Bind( | 563     bound_fns.Push(base::Bind( | 
| 544         &AudioRenderer::Flush, base::Unretained(audio_renderer_.get()))); | 564         &AudioRenderer::Flush, base::Unretained(audio_renderer_.get()))); | 
| 545   } | 565   } | 
| 546   if (video_renderer_) { | 566   if (video_renderer_) { | 
| 547     bound_fns.Push(base::Bind( | 567     bound_fns.Push(base::Bind( | 
| 548         &VideoRenderer::Flush, base::Unretained(video_renderer_.get()))); | 568         &VideoRenderer::Flush, base::Unretained(video_renderer_.get()))); | 
| 549   } | 569   } | 
|  | 570   if (text_renderer_) { | 
|  | 571     bound_fns.Push(base::Bind( | 
|  | 572         &TextRenderer::Flush, base::Unretained(text_renderer_.get()))); | 
|  | 573   } | 
| 550 | 574 | 
| 551   // Seek demuxer. | 575   // Seek demuxer. | 
| 552   bound_fns.Push(base::Bind( | 576   bound_fns.Push(base::Bind( | 
| 553       &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); | 577       &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); | 
| 554 | 578 | 
| 555   // Preroll renderers. | 579   // Preroll renderers. | 
| 556   if (audio_renderer_) { | 580   if (audio_renderer_) { | 
| 557     bound_fns.Push(base::Bind( | 581     bound_fns.Push(base::Bind( | 
| 558         &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()), | 582         &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()), | 
| 559         seek_timestamp)); | 583         seek_timestamp)); | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 579   if (audio_renderer_) { | 603   if (audio_renderer_) { | 
| 580     bound_fns.Push(base::Bind( | 604     bound_fns.Push(base::Bind( | 
| 581         &AudioRenderer::Play, base::Unretained(audio_renderer_.get()))); | 605         &AudioRenderer::Play, base::Unretained(audio_renderer_.get()))); | 
| 582   } | 606   } | 
| 583 | 607 | 
| 584   if (video_renderer_) { | 608   if (video_renderer_) { | 
| 585     bound_fns.Push(base::Bind( | 609     bound_fns.Push(base::Bind( | 
| 586         &VideoRenderer::Play, base::Unretained(video_renderer_.get()))); | 610         &VideoRenderer::Play, base::Unretained(video_renderer_.get()))); | 
| 587   } | 611   } | 
| 588 | 612 | 
|  | 613   if (text_renderer_) { | 
|  | 614     bound_fns.Push(base::Bind( | 
|  | 615         &TextRenderer::Play, base::Unretained(text_renderer_.get()))); | 
|  | 616   } | 
|  | 617 | 
| 589   pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 618   pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 
| 590 } | 619 } | 
| 591 | 620 | 
| 592 void Pipeline::DoStop(const PipelineStatusCB& done_cb) { | 621 void Pipeline::DoStop(const PipelineStatusCB& done_cb) { | 
| 593   DCHECK(message_loop_->BelongsToCurrentThread()); | 622   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 594   DCHECK(!pending_callbacks_.get()); | 623   DCHECK(!pending_callbacks_.get()); | 
| 595   SerialRunner::Queue bound_fns; | 624   SerialRunner::Queue bound_fns; | 
| 596 | 625 | 
| 597   if (demuxer_) { | 626   if (demuxer_) { | 
| 598     bound_fns.Push(base::Bind( | 627     bound_fns.Push(base::Bind( | 
| 599         &Demuxer::Stop, base::Unretained(demuxer_))); | 628         &Demuxer::Stop, base::Unretained(demuxer_))); | 
| 600   } | 629   } | 
| 601 | 630 | 
| 602   if (audio_renderer_) { | 631   if (audio_renderer_) { | 
| 603     bound_fns.Push(base::Bind( | 632     bound_fns.Push(base::Bind( | 
| 604         &AudioRenderer::Stop, base::Unretained(audio_renderer_.get()))); | 633         &AudioRenderer::Stop, base::Unretained(audio_renderer_.get()))); | 
| 605   } | 634   } | 
| 606 | 635 | 
| 607   if (video_renderer_) { | 636   if (video_renderer_) { | 
| 608     bound_fns.Push(base::Bind( | 637     bound_fns.Push(base::Bind( | 
| 609         &VideoRenderer::Stop, base::Unretained(video_renderer_.get()))); | 638         &VideoRenderer::Stop, base::Unretained(video_renderer_.get()))); | 
| 610   } | 639   } | 
| 611 | 640 | 
|  | 641   if (text_renderer_) { | 
|  | 642     bound_fns.Push(base::Bind( | 
|  | 643         &TextRenderer::Stop, base::Unretained(text_renderer_.get()))); | 
|  | 644   } | 
|  | 645 | 
| 612   pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 646   pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 
| 613 } | 647 } | 
| 614 | 648 | 
| 615 void Pipeline::OnStopCompleted(PipelineStatus status) { | 649 void Pipeline::OnStopCompleted(PipelineStatus status) { | 
| 616   DCHECK(message_loop_->BelongsToCurrentThread()); | 650   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 617   DCHECK_EQ(state_, kStopping); | 651   DCHECK_EQ(state_, kStopping); | 
| 618   { | 652   { | 
| 619     base::AutoLock l(lock_); | 653     base::AutoLock l(lock_); | 
| 620     running_ = false; | 654     running_ = false; | 
| 621   } | 655   } | 
| 622 | 656 | 
| 623   SetState(kStopped); | 657   SetState(kStopped); | 
| 624   pending_callbacks_.reset(); | 658   pending_callbacks_.reset(); | 
| 625   filter_collection_.reset(); | 659   filter_collection_.reset(); | 
| 626   audio_renderer_.reset(); | 660   audio_renderer_.reset(); | 
| 627   video_renderer_.reset(); | 661   video_renderer_.reset(); | 
|  | 662   text_renderer_.reset(); | 
| 628   demuxer_ = NULL; | 663   demuxer_ = NULL; | 
| 629 | 664 | 
| 630   // If we stop during initialization/seeking we want to run |seek_cb_| | 665   // If we stop during initialization/seeking we want to run |seek_cb_| | 
| 631   // followed by |stop_cb_| so we don't leave outstanding callbacks around. | 666   // followed by |stop_cb_| so we don't leave outstanding callbacks around. | 
| 632   if (!seek_cb_.is_null()) { | 667   if (!seek_cb_.is_null()) { | 
| 633     base::ResetAndReturn(&seek_cb_).Run(status_); | 668     base::ResetAndReturn(&seek_cb_).Run(status_); | 
| 634     error_cb_.Reset(); | 669     error_cb_.Reset(); | 
| 635   } | 670   } | 
| 636   if (!stop_cb_.is_null()) { | 671   if (!stop_cb_.is_null()) { | 
| 637     error_cb_.Reset(); | 672     error_cb_.Reset(); | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 678   media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::AUDIO_ENDED)); | 713   media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::AUDIO_ENDED)); | 
| 679 } | 714 } | 
| 680 | 715 | 
| 681 void Pipeline::OnVideoRendererEnded() { | 716 void Pipeline::OnVideoRendererEnded() { | 
| 682   // Force post to process ended messages after current execution frame. | 717   // Force post to process ended messages after current execution frame. | 
| 683   message_loop_->PostTask(FROM_HERE, base::Bind( | 718   message_loop_->PostTask(FROM_HERE, base::Bind( | 
| 684       &Pipeline::DoVideoRendererEnded, base::Unretained(this))); | 719       &Pipeline::DoVideoRendererEnded, base::Unretained(this))); | 
| 685   media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::VIDEO_ENDED)); | 720   media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::VIDEO_ENDED)); | 
| 686 } | 721 } | 
| 687 | 722 | 
|  | 723 void Pipeline::OnTextRendererEnded() { | 
|  | 724   // Force post to process ended messages after current execution frame. | 
|  | 725   message_loop_->PostTask(FROM_HERE, base::Bind( | 
|  | 726       &Pipeline::DoTextRendererEnded, base::Unretained(this))); | 
|  | 727   media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED)); | 
|  | 728 } | 
|  | 729 | 
| 688 // Called from any thread. | 730 // Called from any thread. | 
| 689 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { | 731 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { | 
| 690   base::AutoLock auto_lock(lock_); | 732   base::AutoLock auto_lock(lock_); | 
| 691   statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; | 733   statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; | 
| 692   statistics_.video_bytes_decoded += stats.video_bytes_decoded; | 734   statistics_.video_bytes_decoded += stats.video_bytes_decoded; | 
| 693   statistics_.video_frames_decoded += stats.video_frames_decoded; | 735   statistics_.video_frames_decoded += stats.video_frames_decoded; | 
| 694   statistics_.video_frames_dropped += stats.video_frames_dropped; | 736   statistics_.video_frames_dropped += stats.video_frames_dropped; | 
| 695 } | 737 } | 
| 696 | 738 | 
| 697 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, | 739 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, | 
| 698                          const base::Closure& ended_cb, | 740                          const base::Closure& ended_cb, | 
| 699                          const PipelineStatusCB& error_cb, | 741                          const PipelineStatusCB& error_cb, | 
| 700                          const PipelineStatusCB& seek_cb, | 742                          const PipelineStatusCB& seek_cb, | 
| 701                          const BufferingStateCB& buffering_state_cb, | 743                          const BufferingStateCB& buffering_state_cb, | 
| 702                          const base::Closure& duration_change_cb) { | 744                          const base::Closure& duration_change_cb) { | 
| 703   DCHECK(message_loop_->BelongsToCurrentThread()); | 745   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 704   CHECK_EQ(kCreated, state_) | 746   CHECK_EQ(kCreated, state_) | 
| 705       << "Media pipeline cannot be started more than once"; | 747       << "Media pipeline cannot be started more than once"; | 
| 706 | 748 | 
| 707   filter_collection_ = filter_collection.Pass(); | 749   filter_collection_ = filter_collection.Pass(); | 
| 708   ended_cb_ = ended_cb; | 750   ended_cb_ = ended_cb; | 
| 709   error_cb_ = error_cb; | 751   error_cb_ = error_cb; | 
| 710   seek_cb_ = seek_cb; | 752   seek_cb_ = seek_cb; | 
| 711   buffering_state_cb_ = buffering_state_cb; | 753   buffering_state_cb_ = buffering_state_cb; | 
| 712   duration_change_cb_ = duration_change_cb; | 754   duration_change_cb_ = duration_change_cb; | 
| 713 | 755 | 
|  | 756   text_renderer_ = filter_collection_->GetTextRenderer(); | 
|  | 757 | 
|  | 758   if (text_renderer_) { | 
|  | 759     text_renderer_->Initialize( | 
|  | 760         base::Bind(&Pipeline::OnTextRendererEnded, base::Unretained(this))); | 
|  | 761   } | 
|  | 762 | 
| 714   StateTransitionTask(PIPELINE_OK); | 763   StateTransitionTask(PIPELINE_OK); | 
| 715 } | 764 } | 
| 716 | 765 | 
| 717 void Pipeline::StopTask(const base::Closure& stop_cb) { | 766 void Pipeline::StopTask(const base::Closure& stop_cb) { | 
| 718   DCHECK(message_loop_->BelongsToCurrentThread()); | 767   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 719   DCHECK(stop_cb_.is_null()); | 768   DCHECK(stop_cb_.is_null()); | 
| 720 | 769 | 
| 721   if (state_ == kStopped) { | 770   if (state_ == kStopped) { | 
| 722     stop_cb.Run(); | 771     stop_cb.Run(); | 
| 723     return; | 772     return; | 
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 793     return; | 842     return; | 
| 794   } | 843   } | 
| 795 | 844 | 
| 796   DCHECK(seek_cb_.is_null()); | 845   DCHECK(seek_cb_.is_null()); | 
| 797 | 846 | 
| 798   SetState(kSeeking); | 847   SetState(kSeeking); | 
| 799   base::TimeDelta seek_timestamp = std::max(time, demuxer_->GetStartTime()); | 848   base::TimeDelta seek_timestamp = std::max(time, demuxer_->GetStartTime()); | 
| 800   seek_cb_ = seek_cb; | 849   seek_cb_ = seek_cb; | 
| 801   audio_ended_ = false; | 850   audio_ended_ = false; | 
| 802   video_ended_ = false; | 851   video_ended_ = false; | 
|  | 852   text_ended_ = false; | 
| 803 | 853 | 
| 804   // Kick off seeking! | 854   // Kick off seeking! | 
| 805   { | 855   { | 
| 806     base::AutoLock auto_lock(lock_); | 856     base::AutoLock auto_lock(lock_); | 
| 807     if (clock_->IsPlaying()) | 857     if (clock_->IsPlaying()) | 
| 808       clock_->Pause(); | 858       clock_->Pause(); | 
| 809     clock_->SetTime(seek_timestamp, seek_timestamp); | 859     clock_->SetTime(seek_timestamp, seek_timestamp); | 
| 810   } | 860   } | 
| 811   DoSeek(seek_timestamp, base::Bind( | 861   DoSeek(seek_timestamp, base::Bind( | 
| 812       &Pipeline::OnStateTransition, base::Unretained(this))); | 862       &Pipeline::OnStateTransition, base::Unretained(this))); | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 836 | 886 | 
| 837   if (state_ != kStarted) | 887   if (state_ != kStarted) | 
| 838     return; | 888     return; | 
| 839 | 889 | 
| 840   DCHECK(!video_ended_); | 890   DCHECK(!video_ended_); | 
| 841   video_ended_ = true; | 891   video_ended_ = true; | 
| 842 | 892 | 
| 843   RunEndedCallbackIfNeeded(); | 893   RunEndedCallbackIfNeeded(); | 
| 844 } | 894 } | 
| 845 | 895 | 
|  | 896 void Pipeline::DoTextRendererEnded() { | 
|  | 897   DCHECK(message_loop_->BelongsToCurrentThread()); | 
|  | 898 | 
|  | 899   if (state_ != kStarted) | 
|  | 900     return; | 
|  | 901 | 
|  | 902   DCHECK(!text_ended_); | 
|  | 903   text_ended_ = true; | 
|  | 904 | 
|  | 905   RunEndedCallbackIfNeeded(); | 
|  | 906 } | 
|  | 907 | 
| 846 void Pipeline::RunEndedCallbackIfNeeded() { | 908 void Pipeline::RunEndedCallbackIfNeeded() { | 
| 847   DCHECK(message_loop_->BelongsToCurrentThread()); | 909   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 848 | 910 | 
| 849   if (audio_renderer_ && !audio_ended_ && !audio_disabled_) | 911   if (audio_renderer_ && !audio_ended_ && !audio_disabled_) | 
| 850     return; | 912     return; | 
| 851 | 913 | 
| 852   if (video_renderer_ && !video_ended_) | 914   if (video_renderer_ && !video_ended_) | 
| 853     return; | 915     return; | 
| 854 | 916 | 
|  | 917   if (text_renderer_ && text_renderer_->HasTracks() && !text_ended_) | 
|  | 918     return; | 
|  | 919 | 
| 855   { | 920   { | 
| 856     base::AutoLock auto_lock(lock_); | 921     base::AutoLock auto_lock(lock_); | 
| 857     clock_->EndOfStream(); | 922     clock_->EndOfStream(); | 
| 858   } | 923   } | 
| 859 | 924 | 
| 860   DCHECK_EQ(status_, PIPELINE_OK); | 925   DCHECK_EQ(status_, PIPELINE_OK); | 
| 861   ended_cb_.Run(); | 926   ended_cb_.Run(); | 
| 862 } | 927 } | 
| 863 | 928 | 
| 864 void Pipeline::AudioDisabledTask() { | 929 void Pipeline::AudioDisabledTask() { | 
| 865   DCHECK(message_loop_->BelongsToCurrentThread()); | 930   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 866 | 931 | 
| 867   base::AutoLock auto_lock(lock_); | 932   base::AutoLock auto_lock(lock_); | 
| 868   has_audio_ = false; | 933   has_audio_ = false; | 
| 869   audio_disabled_ = true; | 934   audio_disabled_ = true; | 
| 870 | 935 | 
| 871   // Notify our demuxer that we're no longer rendering audio. | 936   // Notify our demuxer that we're no longer rendering audio. | 
| 872   demuxer_->OnAudioRendererDisabled(); | 937   demuxer_->OnAudioRendererDisabled(); | 
| 873 | 938 | 
| 874   // Start clock since there is no more audio to trigger clock updates. | 939   // Start clock since there is no more audio to trigger clock updates. | 
| 875   clock_->SetMaxTime(clock_->Duration()); | 940   clock_->SetMaxTime(clock_->Duration()); | 
| 876   StartClockIfWaitingForTimeUpdate_Locked(); | 941   StartClockIfWaitingForTimeUpdate_Locked(); | 
| 877 } | 942 } | 
| 878 | 943 | 
|  | 944 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, | 
|  | 945                                  const TextTrackConfig& config) { | 
|  | 946   DCHECK(message_loop_->BelongsToCurrentThread()); | 
|  | 947   // TODO(matthewjheaney): fix up text_ended_ when text stream | 
|  | 948   // is added (http://crbug.com/321446). | 
|  | 949   text_renderer_->AddTextStream(text_stream, config); | 
|  | 950 } | 
|  | 951 | 
|  | 952 void Pipeline::RemoveTextStreamTask(DemuxerStream* text_stream) { | 
|  | 953   DCHECK(message_loop_->BelongsToCurrentThread()); | 
|  | 954   text_renderer_->RemoveTextStream(text_stream); | 
|  | 955 } | 
|  | 956 | 
| 879 void Pipeline::InitializeDemuxer(const PipelineStatusCB& done_cb) { | 957 void Pipeline::InitializeDemuxer(const PipelineStatusCB& done_cb) { | 
| 880   DCHECK(message_loop_->BelongsToCurrentThread()); | 958   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 881 | 959 | 
| 882   demuxer_ = filter_collection_->GetDemuxer(); | 960   demuxer_ = filter_collection_->GetDemuxer(); | 
| 883   demuxer_->Initialize(this, done_cb); | 961   demuxer_->Initialize(this, done_cb, text_renderer_); | 
| 884 } | 962 } | 
| 885 | 963 | 
| 886 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) { | 964 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) { | 
| 887   DCHECK(message_loop_->BelongsToCurrentThread()); | 965   DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 888 | 966 | 
| 889   audio_renderer_ = filter_collection_->GetAudioRenderer(); | 967   audio_renderer_ = filter_collection_->GetAudioRenderer(); | 
| 890   audio_renderer_->Initialize( | 968   audio_renderer_->Initialize( | 
| 891       demuxer_->GetStream(DemuxerStream::AUDIO), | 969       demuxer_->GetStream(DemuxerStream::AUDIO), | 
| 892       done_cb, | 970       done_cb, | 
| 893       base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), | 971       base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 940 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1018 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 
| 941   lock_.AssertAcquired(); | 1019   lock_.AssertAcquired(); | 
| 942   if (!waiting_for_clock_update_) | 1020   if (!waiting_for_clock_update_) | 
| 943     return; | 1021     return; | 
| 944 | 1022 | 
| 945   waiting_for_clock_update_ = false; | 1023   waiting_for_clock_update_ = false; | 
| 946   clock_->Play(); | 1024   clock_->Play(); | 
| 947 } | 1025 } | 
| 948 | 1026 | 
| 949 }  // namespace media | 1027 }  // namespace media | 
| OLD | NEW | 
|---|