| Index: chromecast/media/cma/pipeline/video_pipeline_impl.cc
|
| diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.cc b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d3ae9bec1a911f9a4050961593010d39302f06c4
|
| --- /dev/null
|
| +++ b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
|
| @@ -0,0 +1,174 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "chromecast/media/cma/backend/video_pipeline_device.h"
|
| +#include "chromecast/media/cma/base/buffering_defs.h"
|
| +#include "chromecast/media/cma/base/cma_logging.h"
|
| +#include "chromecast/media/cma/base/coded_frame_provider.h"
|
| +#include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
|
| +#include "media/base/video_decoder_config.h"
|
| +
|
| +namespace chromecast {
|
| +namespace media {
|
| +
|
| +namespace {
|
| +const size_t kMaxVideoFrameSize = 1024 * 1024;
|
| +}
|
| +
|
| +VideoPipelineImpl::VideoPipelineImpl(VideoPipelineDevice* video_device)
|
| + : video_device_(video_device),
|
| + weak_factory_(this) {
|
| + weak_this_ = weak_factory_.GetWeakPtr();
|
| + av_pipeline_impl_.reset(new AvPipelineImpl(
|
| + video_device_,
|
| + base::Bind(&VideoPipelineImpl::OnUpdateConfig, base::Unretained(this))));
|
| +}
|
| +
|
| +VideoPipelineImpl::~VideoPipelineImpl() {
|
| +}
|
| +
|
| +void VideoPipelineImpl::SetCodedFrameProvider(
|
| + scoped_ptr<CodedFrameProvider> frame_provider) {
|
| + av_pipeline_impl_->SetCodedFrameProvider(
|
| + frame_provider.Pass(), kAppVideoBufferSize, kMaxVideoFrameSize);
|
| +}
|
| +
|
| +bool VideoPipelineImpl::StartPlayingFrom(
|
| + base::TimeDelta time,
|
| + const scoped_refptr<BufferingState>& buffering_state) {
|
| + CMALOG(kLogControl) << "VideoPipelineImpl::StartPlayingFrom t0="
|
| + << time.InMilliseconds();
|
| +
|
| + // Reset the pipeline statistics.
|
| + previous_stats_ = ::media::PipelineStatistics();
|
| +
|
| + // Start playing.
|
| + if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError)
|
| + return false;
|
| + DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kFlushed);
|
| +
|
| + if (!av_pipeline_impl_->StartPlayingFrom(time, buffering_state)) {
|
| + av_pipeline_impl_->TransitionToState(AvPipelineImpl::kError);
|
| + return false;
|
| + }
|
| + av_pipeline_impl_->TransitionToState(AvPipelineImpl::kPlaying);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void VideoPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
|
| + CMALOG(kLogControl) << "VideoPipelineImpl::Flush";
|
| + if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
|
| + status_cb.Run(::media::PIPELINE_ERROR_ABORT);
|
| + return;
|
| + }
|
| + DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kPlaying);
|
| + av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushing);
|
| + av_pipeline_impl_->Flush(
|
| + base::Bind(&VideoPipelineImpl::OnFlushDone, weak_this_, status_cb));
|
| +}
|
| +
|
| +void VideoPipelineImpl::OnFlushDone(
|
| + const ::media::PipelineStatusCB& status_cb) {
|
| + CMALOG(kLogControl) << "VideoPipelineImpl::OnFlushDone";
|
| + if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
|
| + status_cb.Run(::media::PIPELINE_ERROR_ABORT);
|
| + return;
|
| + }
|
| + av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
|
| + status_cb.Run(::media::PIPELINE_OK);
|
| +}
|
| +
|
| +void VideoPipelineImpl::Stop() {
|
| + CMALOG(kLogControl) << "VideoPipelineImpl::Stop";
|
| + av_pipeline_impl_->Stop();
|
| + av_pipeline_impl_->TransitionToState(AvPipelineImpl::kStopped);
|
| +}
|
| +
|
| +void VideoPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
|
| + av_pipeline_impl_->SetCdm(media_keys);
|
| +}
|
| +
|
| +void VideoPipelineImpl::SetClient(const VideoPipelineClient& client) {
|
| + video_client_ = client;
|
| + av_pipeline_impl_->SetClient(client.av_pipeline_client);
|
| +}
|
| +
|
| +void VideoPipelineImpl::Initialize(
|
| + const ::media::VideoDecoderConfig& video_config,
|
| + scoped_ptr<CodedFrameProvider> frame_provider,
|
| + const ::media::PipelineStatusCB& status_cb) {
|
| + CMALOG(kLogControl) << "VideoPipelineImpl::Initialize "
|
| + << video_config.AsHumanReadableString();
|
| + VideoPipelineDevice::VideoClient client;
|
| + client.natural_size_changed_cb =
|
| + base::Bind(&VideoPipelineImpl::OnNaturalSizeChanged, weak_this_);
|
| + video_device_->SetVideoClient(client);
|
| + if (frame_provider)
|
| + SetCodedFrameProvider(frame_provider.Pass());
|
| +
|
| + if (!video_device_->SetConfig(video_config) ||
|
| + !av_pipeline_impl_->Initialize()) {
|
| + status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
|
| + return;
|
| + }
|
| + av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
|
| + status_cb.Run(::media::PIPELINE_OK);
|
| +}
|
| +
|
| +void VideoPipelineImpl::OnUpdateConfig(
|
| + const ::media::AudioDecoderConfig& audio_config,
|
| + const ::media::VideoDecoderConfig& video_config) {
|
| + if (video_config.IsValidConfig()) {
|
| + CMALOG(kLogControl) << "VideoPipelineImpl::OnUpdateConfig "
|
| + << video_config.AsHumanReadableString();
|
| +
|
| + bool success = video_device_->SetConfig(video_config);
|
| + if (!success &&
|
| + !video_client_.av_pipeline_client.playback_error_cb.is_null()) {
|
| + video_client_.av_pipeline_client.playback_error_cb.Run(
|
| + ::media::PIPELINE_ERROR_DECODE);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void VideoPipelineImpl::OnNaturalSizeChanged(const gfx::Size& size) {
|
| + if (av_pipeline_impl_->GetState() != AvPipelineImpl::kPlaying)
|
| + return;
|
| +
|
| + if (!video_client_.natural_size_changed_cb.is_null())
|
| + video_client_.natural_size_changed_cb.Run(size);
|
| +}
|
| +
|
| +void VideoPipelineImpl::UpdateStatistics() {
|
| + if (video_client_.av_pipeline_client.statistics_cb.is_null())
|
| + return;
|
| +
|
| + MediaComponentDevice::Statistics device_stats;
|
| + if (!video_device_->GetStatistics(&device_stats))
|
| + return;
|
| +
|
| + ::media::PipelineStatistics current_stats;
|
| + current_stats.video_bytes_decoded = device_stats.decoded_bytes;
|
| + current_stats.video_frames_decoded = device_stats.decoded_samples;
|
| + current_stats.video_frames_dropped = device_stats.dropped_samples;
|
| +
|
| + ::media::PipelineStatistics delta_stats;
|
| + delta_stats.video_bytes_decoded =
|
| + current_stats.video_bytes_decoded - previous_stats_.video_bytes_decoded;
|
| + delta_stats.video_frames_decoded =
|
| + current_stats.video_frames_decoded - previous_stats_.video_frames_decoded;
|
| + delta_stats.video_frames_dropped =
|
| + current_stats.video_frames_dropped - previous_stats_.video_frames_dropped;
|
| +
|
| + previous_stats_ = current_stats;
|
| +
|
| + video_client_.av_pipeline_client.statistics_cb.Run(delta_stats);
|
| +}
|
| +
|
| +} // namespace media
|
| +} // namespace chromecast
|
|
|