Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromecast / media / cma / pipeline / video_pipeline_impl.cc
blob89d82cfc9fb1868f622d1e49287140e2772dced8
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/base/buffering_defs.h"
9 #include "chromecast/media/cma/base/cma_logging.h"
10 #include "chromecast/media/cma/base/coded_frame_provider.h"
11 #include "chromecast/media/cma/base/decoder_config_adapter.h"
12 #include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
13 #include "chromecast/media/cma/pipeline/video_pipeline_device_client_impl.h"
14 #include "chromecast/public/graphics_types.h"
15 #include "chromecast/public/media/decoder_config.h"
16 #include "chromecast/public/media/video_pipeline_device.h"
17 #include "media/base/video_decoder_config.h"
19 namespace chromecast {
20 namespace media {
22 namespace {
23 const size_t kMaxVideoFrameSize = 1024 * 1024;
26 VideoPipelineImpl::VideoPipelineImpl(VideoPipelineDevice* video_device)
27 : video_device_(video_device),
28 weak_factory_(this) {
29 weak_this_ = weak_factory_.GetWeakPtr();
30 av_pipeline_impl_.reset(new AvPipelineImpl(
31 video_device_,
32 base::Bind(&VideoPipelineImpl::OnUpdateConfig, base::Unretained(this))));
35 VideoPipelineImpl::~VideoPipelineImpl() {
38 void VideoPipelineImpl::SetCodedFrameProvider(
39 scoped_ptr<CodedFrameProvider> frame_provider) {
40 av_pipeline_impl_->SetCodedFrameProvider(
41 frame_provider.Pass(), kAppVideoBufferSize, kMaxVideoFrameSize);
44 bool VideoPipelineImpl::StartPlayingFrom(
45 base::TimeDelta time,
46 const scoped_refptr<BufferingState>& buffering_state) {
47 CMALOG(kLogControl) << "VideoPipelineImpl::StartPlayingFrom t0="
48 << time.InMilliseconds();
50 // Reset the pipeline statistics.
51 previous_stats_ = ::media::PipelineStatistics();
53 // Start playing.
54 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError)
55 return false;
56 DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kFlushed);
58 if (!av_pipeline_impl_->StartPlayingFrom(time, buffering_state)) {
59 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kError);
60 return false;
62 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kPlaying);
64 return true;
67 void VideoPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
68 CMALOG(kLogControl) << "VideoPipelineImpl::Flush";
69 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
70 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
71 return;
73 DCHECK_EQ(av_pipeline_impl_->GetState(), AvPipelineImpl::kPlaying);
74 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushing);
75 av_pipeline_impl_->Flush(
76 base::Bind(&VideoPipelineImpl::OnFlushDone, weak_this_, status_cb));
79 void VideoPipelineImpl::OnFlushDone(
80 const ::media::PipelineStatusCB& status_cb) {
81 CMALOG(kLogControl) << "VideoPipelineImpl::OnFlushDone";
82 if (av_pipeline_impl_->GetState() == AvPipelineImpl::kError) {
83 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
84 return;
86 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
87 status_cb.Run(::media::PIPELINE_OK);
90 void VideoPipelineImpl::Stop() {
91 CMALOG(kLogControl) << "VideoPipelineImpl::Stop";
92 av_pipeline_impl_->Stop();
93 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kStopped);
96 void VideoPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
97 av_pipeline_impl_->SetCdm(media_keys);
100 void VideoPipelineImpl::SetClient(const VideoPipelineClient& client) {
101 video_client_ = client;
102 av_pipeline_impl_->SetClient(client.av_pipeline_client);
105 void VideoPipelineImpl::Initialize(
106 const std::vector<::media::VideoDecoderConfig>& configs,
107 scoped_ptr<CodedFrameProvider> frame_provider,
108 const ::media::PipelineStatusCB& status_cb) {
109 DCHECK_GT(configs.size(), 0u);
110 for (const auto& config : configs) {
111 CMALOG(kLogControl) << __FUNCTION__ << " "
112 << config.AsHumanReadableString();
114 video_device_->SetVideoClient(new VideoPipelineDeviceClientImpl(
115 base::Bind(&VideoPipelineImpl::OnNaturalSizeChanged, weak_this_)));
116 if (frame_provider)
117 SetCodedFrameProvider(frame_provider.Pass());
119 if (configs.empty()) {
120 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
121 return;
123 DCHECK(configs.size() <= 2);
124 DCHECK(configs[0].IsValidConfig());
125 VideoConfig video_config =
126 DecoderConfigAdapter::ToCastVideoConfig(kPrimary, configs[0]);
127 VideoConfig secondary_config;
128 if (configs.size() == 2) {
129 DCHECK(configs[1].IsValidConfig());
130 secondary_config = DecoderConfigAdapter::ToCastVideoConfig(kSecondary,
131 configs[1]);
132 video_config.additional_config = &secondary_config;
135 if (!video_device_->SetConfig(video_config) ||
136 !av_pipeline_impl_->Initialize()) {
137 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
138 return;
140 av_pipeline_impl_->TransitionToState(AvPipelineImpl::kFlushed);
141 status_cb.Run(::media::PIPELINE_OK);
144 void VideoPipelineImpl::OnUpdateConfig(
145 StreamId id,
146 const ::media::AudioDecoderConfig& audio_config,
147 const ::media::VideoDecoderConfig& video_config) {
148 if (video_config.IsValidConfig()) {
149 CMALOG(kLogControl) << "VideoPipelineImpl::OnUpdateConfig id:" << id << " "
150 << video_config.AsHumanReadableString();
152 bool success = video_device_->SetConfig(
153 DecoderConfigAdapter::ToCastVideoConfig(id, video_config));
154 if (!success &&
155 !video_client_.av_pipeline_client.playback_error_cb.is_null()) {
156 video_client_.av_pipeline_client.playback_error_cb.Run(
157 ::media::PIPELINE_ERROR_DECODE);
162 void VideoPipelineImpl::OnNaturalSizeChanged(const Size& size) {
163 if (av_pipeline_impl_->GetState() != AvPipelineImpl::kPlaying)
164 return;
166 if (!video_client_.natural_size_changed_cb.is_null()) {
167 video_client_.natural_size_changed_cb.Run(
168 gfx::Size(size.width, size.height));
172 void VideoPipelineImpl::UpdateStatistics() {
173 if (video_client_.av_pipeline_client.statistics_cb.is_null())
174 return;
176 MediaComponentDevice::Statistics device_stats;
177 if (!video_device_->GetStatistics(&device_stats))
178 return;
180 ::media::PipelineStatistics current_stats;
181 current_stats.video_bytes_decoded = device_stats.decoded_bytes;
182 current_stats.video_frames_decoded = device_stats.decoded_samples;
183 current_stats.video_frames_dropped = device_stats.dropped_samples;
185 ::media::PipelineStatistics delta_stats;
186 delta_stats.video_bytes_decoded =
187 current_stats.video_bytes_decoded - previous_stats_.video_bytes_decoded;
188 delta_stats.video_frames_decoded =
189 current_stats.video_frames_decoded - previous_stats_.video_frames_decoded;
190 delta_stats.video_frames_dropped =
191 current_stats.video_frames_dropped - previous_stats_.video_frames_dropped;
193 previous_stats_ = current_stats;
195 video_client_.av_pipeline_client.statistics_cb.Run(delta_stats);
198 } // namespace media
199 } // namespace chromecast