[MediaRouter] Update MR-2-Extension's PostMessage to return boolean.
[chromium-blink-merge.git] / chromecast / media / cma / pipeline / video_pipeline_impl.cc
blob38335318bd3a4892df3252196dd07943dbb5d766
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
7 #include "base/bind.h"
8 #include "chromecast/media/cma/backend/video_pipeline_device.h"
9 #include "chromecast/media/cma/base/buffering_defs.h"
10 #include "chromecast/media/cma/base/cma_logging.h"
11 #include "chromecast/media/cma/base/coded_frame_provider.h"
12 #include "chromecast/media/cma/base/decoder_config_adapter.h"
13 #include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
14 #include "chromecast/public/media/decoder_config.h"
15 #include "media/base/video_decoder_config.h"
17 namespace chromecast {
18 namespace media {
20 namespace {
21 const size_t kMaxVideoFrameSize = 1024 * 1024;
24 VideoPipelineImpl::VideoPipelineImpl(VideoPipelineDevice* video_device)
25 : video_device_(video_device),
26 weak_factory_(this) {
27 weak_this_ = weak_factory_.GetWeakPtr();
28 av_pipeline_impl_.reset(new AvPipelineImpl(
29 video_device_,
30 base::Bind(&VideoPipelineImpl::OnUpdateConfig, base::Unretained(this))));
33 VideoPipelineImpl::~VideoPipelineImpl() {
36 void VideoPipelineImpl::SetCodedFrameProvider(
37 scoped_ptr<CodedFrameProvider> frame_provider) {
38 av_pipeline_impl_->SetCodedFrameProvider(
39 frame_provider.Pass(), kAppVideoBufferSize, kMaxVideoFrameSize);
42 bool VideoPipelineImpl::StartPlayingFrom(
43 base::TimeDelta time,
44 const scoped_refptr<BufferingState>& buffering_state) {
45 CMALOG(kLogControl) << "VideoPipelineImpl::StartPlayingFrom t0="
46 << time.InMilliseconds();
48 // Reset the pipeline statistics.
49 previous_stats_ = ::media::PipelineStatistics();
51 // Start playing.
52 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError)
53 return false;
54 DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kFlushed);
56 if (!av_pipeline_impl_->StartPlayingFrom(time, buffering_state)) {
57 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kError);
58 return false;
60 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kPlaying);
62 return true;
65 void VideoPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
66 CMALOG(kLogControl) << "VideoPipelineImpl::Flush";
67 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
68 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
69 return;
71 DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kPlaying);
72 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushing);
73 av_pipeline_impl_->Flush(
74 base::Bind(&VideoPipelineImpl::OnFlushDone, weak_this_, status_cb));
77 void VideoPipelineImpl::OnFlushDone(
78 const ::media::PipelineStatusCB& status_cb) {
79 CMALOG(kLogControl) << "VideoPipelineImpl::OnFlushDone";
80 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
81 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
82 return;
84 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
85 status_cb.Run(::media::PIPELINE_OK);
88 void VideoPipelineImpl::Stop() {
89 CMALOG(kLogControl) << "VideoPipelineImpl::Stop";
90 av_pipeline_impl_->Stop();
91 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kStopped);
94 void VideoPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
95 av_pipeline_impl_->SetCdm(media_keys);
98 void VideoPipelineImpl::SetClient(const VideoPipelineClient& client) {
99 video_client_ = client;
100 av_pipeline_impl_->SetClient(client.av_pipeline_client);
103 void VideoPipelineImpl::Initialize(
104 const std::vector<::media::VideoDecoderConfig>& configs,
105 scoped_ptr<CodedFrameProvider> frame_provider,
106 const ::media::PipelineStatusCB& status_cb) {
107 CMALOG(kLogControl) << __FUNCTION__ << " config (" << configs.size() << ")";
108 VideoPipelineDevice::VideoClient client;
109 client.natural_size_changed_cb =
110 base::Bind(&VideoPipelineImpl::OnNaturalSizeChanged, weak_this_);
111 video_device_->SetVideoClient(client);
112 if (frame_provider)
113 SetCodedFrameProvider(frame_provider.Pass());
115 if (configs.empty()) {
116 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
117 return;
119 DCHECK(configs.size() <= 2);
120 DCHECK(configs[0].IsValidConfig());
121 VideoConfig video_config =
122 DecoderConfigAdapter::ToCastVideoConfig(kPrimary, configs[0]);
123 VideoConfig secondary_config;
124 if (configs.size() == 2) {
125 DCHECK(configs[1].IsValidConfig());
126 secondary_config = DecoderConfigAdapter::ToCastVideoConfig(kSecondary,
127 configs[1]);
128 video_config.additional_config = &secondary_config;
131 if (!video_device_->SetConfig(video_config) ||
132 !av_pipeline_impl_->Initialize()) {
133 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
134 return;
136 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
137 status_cb.Run(::media::PIPELINE_OK);
140 void VideoPipelineImpl::OnUpdateConfig(
141 StreamId id,
142 const ::media::AudioDecoderConfig& audio_config,
143 const ::media::VideoDecoderConfig& video_config) {
144 if (video_config.IsValidConfig()) {
145 CMALOG(kLogControl) << "VideoPipelineImpl::OnUpdateConfig id:" << id << " "
146 << video_config.AsHumanReadableString();
148 bool success = video_device_->SetConfig(
149 DecoderConfigAdapter::ToCastVideoConfig(id, video_config));
150 if (!success &&
151 !video_client_.av_pipeline_client.playback_error_cb.is_null()) {
152 video_client_.av_pipeline_client.playback_error_cb.Run(
153 ::media::PIPELINE_ERROR_DECODE);
158 void VideoPipelineImpl::OnNaturalSizeChanged(const gfx::Size& size) {
159 if (av_pipeline_impl_->GetState() != AvPipelineImpl::kPlaying)
160 return;
162 if (!video_client_.natural_size_changed_cb.is_null())
163 video_client_.natural_size_changed_cb.Run(size);
166 void VideoPipelineImpl::UpdateStatistics() {
167 if (video_client_.av_pipeline_client.statistics_cb.is_null())
168 return;
170 MediaComponentDevice::Statistics device_stats;
171 if (!video_device_->GetStatistics(&device_stats))
172 return;
174 ::media::PipelineStatistics current_stats;
175 current_stats.video_bytes_decoded = device_stats.decoded_bytes;
176 current_stats.video_frames_decoded = device_stats.decoded_samples;
177 current_stats.video_frames_dropped = device_stats.dropped_samples;
179 ::media::PipelineStatistics delta_stats;
180 delta_stats.video_bytes_decoded =
181 current_stats.video_bytes_decoded - previous_stats_.video_bytes_decoded;
182 delta_stats.video_frames_decoded =
183 current_stats.video_frames_decoded - previous_stats_.video_frames_decoded;
184 delta_stats.video_frames_dropped =
185 current_stats.video_frames_dropped - previous_stats_.video_frames_dropped;
187 previous_stats_ = current_stats;
189 video_client_.av_pipeline_client.statistics_cb.Run(delta_stats);
192 } // namespace media
193 } // namespace chromecast