| Index: media/base/pipeline.cc
|
| diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc
|
| index bbdc95f2e4bd6551e32f097057cb24e0286f9bb6..70aa2a4e1239a2eb9b4bdafe366900a16eda4631 100644
|
| --- a/media/base/pipeline.cc
|
| +++ b/media/base/pipeline.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/bind.h"
|
| #include "base/callback.h"
|
| #include "base/callback_helpers.h"
|
| +#include "base/command_line.h"
|
| #include "base/compiler_specific.h"
|
| #include "base/location.h"
|
| #include "base/metrics/histogram.h"
|
| @@ -17,8 +18,8 @@
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/strings/string_util.h"
|
| #include "base/synchronization/condition_variable.h"
|
| -#include "media/base/filter_collection.h"
|
| #include "media/base/media_log.h"
|
| +#include "media/base/media_switches.h"
|
| #include "media/base/renderer.h"
|
| #include "media/base/text_renderer.h"
|
| #include "media/base/text_track_config.h"
|
| @@ -60,13 +61,15 @@ Pipeline::~Pipeline() {
|
| media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED));
|
| }
|
|
|
| -void Pipeline::Start(scoped_ptr<FilterCollection> collection,
|
| +void Pipeline::Start(Demuxer* demuxer,
|
| + scoped_ptr<Renderer> renderer,
|
| const base::Closure& ended_cb,
|
| const PipelineStatusCB& error_cb,
|
| const PipelineStatusCB& seek_cb,
|
| const PipelineMetadataCB& metadata_cb,
|
| const BufferingStateCB& buffering_state_cb,
|
| - const base::Closure& duration_change_cb) {
|
| + const base::Closure& duration_change_cb,
|
| + const AddTextTrackCB& add_text_track_cb) {
|
| DCHECK(!ended_cb.is_null());
|
| DCHECK(!error_cb.is_null());
|
| DCHECK(!seek_cb.is_null());
|
| @@ -77,13 +80,15 @@ void Pipeline::Start(scoped_ptr<FilterCollection> collection,
|
| CHECK(!running_) << "Media pipeline is already running";
|
| running_ = true;
|
|
|
| - filter_collection_ = collection.Pass();
|
| + demuxer_ = demuxer;
|
| + renderer_ = renderer.Pass();
|
| ended_cb_ = ended_cb;
|
| error_cb_ = error_cb;
|
| seek_cb_ = seek_cb;
|
| metadata_cb_ = metadata_cb;
|
| buffering_state_cb_ = buffering_state_cb;
|
| duration_change_cb_ = duration_change_cb;
|
| + add_text_track_cb_ = add_text_track_cb;
|
|
|
| task_runner_->PostTask(
|
| FROM_HERE, base::Bind(&Pipeline::StartTask, weak_factory_.GetWeakPtr()));
|
| @@ -230,11 +235,7 @@ Pipeline::State Pipeline::GetNextState() const {
|
| return kInitDemuxer;
|
|
|
| case kInitDemuxer:
|
| - if (demuxer_->GetStream(DemuxerStream::AUDIO) ||
|
| - demuxer_->GetStream(DemuxerStream::VIDEO)) {
|
| - return kInitRenderer;
|
| - }
|
| - return kPlaying;
|
| + return kInitRenderer;
|
|
|
| case kInitRenderer:
|
| case kSeeking:
|
| @@ -339,29 +340,10 @@ void Pipeline::StateTransitionTask(PipelineStatus status) {
|
| return InitializeRenderer(done_cb);
|
|
|
| case kPlaying:
|
| - // Finish initial start sequence the first time we enter the playing
|
| - // state.
|
| + // Report metadata the first time we enter the playing state.
|
| if (!is_initialized_) {
|
| - if (!renderer_) {
|
| - ErrorChangedTask(PIPELINE_ERROR_COULD_NOT_RENDER);
|
| - return;
|
| - }
|
| -
|
| is_initialized_ = true;
|
| -
|
| - {
|
| - PipelineMetadata metadata;
|
| - metadata.has_audio = renderer_->HasAudio();
|
| - metadata.has_video = renderer_->HasVideo();
|
| - metadata.timeline_offset = demuxer_->GetTimelineOffset();
|
| - DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
|
| - if (stream) {
|
| - metadata.natural_size =
|
| - stream->video_decoder_config().natural_size();
|
| - metadata.video_rotation = stream->video_rotation();
|
| - }
|
| - metadata_cb_.Run(metadata);
|
| - }
|
| + ReportMetadata();
|
| }
|
|
|
| base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
|
| @@ -448,7 +430,6 @@ void Pipeline::OnStopCompleted(PipelineStatus status) {
|
| }
|
|
|
| SetState(kStopped);
|
| - filter_collection_.reset();
|
| demuxer_ = NULL;
|
|
|
| // If we stop during initialization/seeking we want to run |seek_cb_|
|
| @@ -498,8 +479,7 @@ void Pipeline::StartTask() {
|
| CHECK_EQ(kCreated, state_)
|
| << "Media pipeline cannot be started more than once";
|
|
|
| - text_renderer_ = filter_collection_->GetTextRenderer();
|
| -
|
| + text_renderer_ = CreateTextRenderer();
|
| if (text_renderer_) {
|
| text_renderer_->Initialize(
|
| base::Bind(&Pipeline::OnTextRendererEnded, weak_factory_.GetWeakPtr()));
|
| @@ -530,9 +510,14 @@ void Pipeline::StopTask(const base::Closure& stop_cb) {
|
| if (state_ == kStopping)
|
| return;
|
|
|
| - PipelineStatistics stats = GetStatistics();
|
| - if (renderer_ && renderer_->HasVideo() && stats.video_frames_decoded > 0)
|
| - UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount", stats.video_frames_dropped);
|
| + // Do not report statistics if the pipeline is not fully initialized.
|
| + if (state_ == kSeeking || state_ == kPlaying) {
|
| + PipelineStatistics stats = GetStatistics();
|
| + if (renderer_->HasVideo() && stats.video_frames_decoded > 0) {
|
| + UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount",
|
| + stats.video_frames_dropped);
|
| + }
|
| + }
|
|
|
| SetState(kStopping);
|
| pending_callbacks_.reset();
|
| @@ -642,30 +627,54 @@ void Pipeline::RunEndedCallbackIfNeeded() {
|
| ended_cb_.Run();
|
| }
|
|
|
| +scoped_ptr<TextRenderer> Pipeline::CreateTextRenderer() {
|
| + DCHECK(task_runner_->BelongsToCurrentThread());
|
| +
|
| + const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
|
| + if (!cmd_line->HasSwitch(switches::kEnableInbandTextTracks))
|
| + return scoped_ptr<media::TextRenderer>();
|
| +
|
| + return scoped_ptr<media::TextRenderer>(new media::TextRenderer(
|
| + task_runner_,
|
| + base::Bind(&Pipeline::OnAddTextTrack, weak_factory_.GetWeakPtr())));
|
| +}
|
| +
|
| void Pipeline::AddTextStreamTask(DemuxerStream* text_stream,
|
| const TextTrackConfig& config) {
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| // TODO(matthewjheaney): fix up text_ended_ when text stream
|
| // is added (http://crbug.com/321446).
|
| - text_renderer_->AddTextStream(text_stream, config);
|
| + if (text_renderer_)
|
| + text_renderer_->AddTextStream(text_stream, config);
|
| }
|
|
|
| void Pipeline::RemoveTextStreamTask(DemuxerStream* text_stream) {
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| - text_renderer_->RemoveTextStream(text_stream);
|
| + if (text_renderer_)
|
| + text_renderer_->RemoveTextStream(text_stream);
|
| }
|
|
|
| -void Pipeline::InitializeDemuxer(const PipelineStatusCB& done_cb) {
|
| +void Pipeline::OnAddTextTrack(const TextTrackConfig& config,
|
| + const AddTextTrackDoneCB& done_cb) {
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| + add_text_track_cb_.Run(config, done_cb);
|
| +}
|
|
|
| - demuxer_ = filter_collection_->GetDemuxer();
|
| +void Pipeline::InitializeDemuxer(const PipelineStatusCB& done_cb) {
|
| + DCHECK(task_runner_->BelongsToCurrentThread());
|
| demuxer_->Initialize(this, done_cb, text_renderer_);
|
| }
|
|
|
| void Pipeline::InitializeRenderer(const PipelineStatusCB& done_cb) {
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
|
|
| - renderer_ = filter_collection_->GetRenderer();
|
| + if (!demuxer_->GetStream(DemuxerStream::AUDIO) &&
|
| + !demuxer_->GetStream(DemuxerStream::VIDEO)) {
|
| + renderer_.reset();
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(done_cb, PIPELINE_ERROR_COULD_NOT_RENDER));
|
| + return;
|
| + }
|
|
|
| base::WeakPtr<Pipeline> weak_this = weak_factory_.GetWeakPtr();
|
| renderer_->Initialize(
|
| @@ -677,6 +686,20 @@ void Pipeline::InitializeRenderer(const PipelineStatusCB& done_cb) {
|
| base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this)));
|
| }
|
|
|
| +void Pipeline::ReportMetadata() {
|
| + DCHECK(task_runner_->BelongsToCurrentThread());
|
| + PipelineMetadata metadata;
|
| + metadata.has_audio = renderer_->HasAudio();
|
| + metadata.has_video = renderer_->HasVideo();
|
| + metadata.timeline_offset = demuxer_->GetTimelineOffset();
|
| + DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
|
| + if (stream) {
|
| + metadata.natural_size = stream->video_decoder_config().natural_size();
|
| + metadata.video_rotation = stream->video_rotation();
|
| + }
|
| + metadata_cb_.Run(metadata);
|
| +}
|
| +
|
| void Pipeline::BufferingStateChanged(BufferingState new_buffering_state) {
|
| DVLOG(1) << __FUNCTION__ << "(" << new_buffering_state << ") ";
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
|
|