Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: chromecast/media/cma/pipeline/media_pipeline_impl.cc

Issue 1372393007: [Chromecast] Upgrade to new CMA backend API (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Address alokp@ comments Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 "chromecast/media/cma/pipeline/media_pipeline_impl.h" 5 #include "chromecast/media/cma/pipeline/media_pipeline_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h" 13 #include "base/thread_task_runner_handle.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "chromecast/media/cdm/browser_cdm_cast.h" 15 #include "chromecast/media/cdm/browser_cdm_cast.h"
16 #include "chromecast/media/cma/base/buffering_controller.h" 16 #include "chromecast/media/cma/base/buffering_controller.h"
17 #include "chromecast/media/cma/base/buffering_state.h" 17 #include "chromecast/media/cma/base/buffering_state.h"
18 #include "chromecast/media/cma/base/cma_logging.h" 18 #include "chromecast/media/cma/base/cma_logging.h"
19 #include "chromecast/media/cma/base/coded_frame_provider.h" 19 #include "chromecast/media/cma/base/coded_frame_provider.h"
20 #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h" 20 #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h"
21 #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" 21 #include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
22 #include "chromecast/public/media/media_clock_device.h"
23 #include "chromecast/public/media/media_pipeline_backend.h" 22 #include "chromecast/public/media/media_pipeline_backend.h"
24 #include "media/base/timestamp_constants.h" 23 #include "media/base/timestamp_constants.h"
25 24
26 namespace chromecast { 25 namespace chromecast {
27 namespace media { 26 namespace media {
28 27
29 namespace { 28 namespace {
30 29
31 // Buffering parameters when load_type is kLoadTypeUrl. 30 // Buffering parameters when load_type is kLoadTypeUrl.
32 const base::TimeDelta kLowBufferThresholdURL( 31 const base::TimeDelta kLowBufferThresholdURL(
(...skipping 11 matching lines...) Expand all
44 const base::TimeDelta kTimeUpdateInterval( 43 const base::TimeDelta kTimeUpdateInterval(
45 base::TimeDelta::FromMilliseconds(250)); 44 base::TimeDelta::FromMilliseconds(250));
46 45
47 // Interval between two updates of the statistics is equal to: 46 // Interval between two updates of the statistics is equal to:
48 // kTimeUpdateInterval * kStatisticsUpdatePeriod. 47 // kTimeUpdateInterval * kStatisticsUpdatePeriod.
49 const int kStatisticsUpdatePeriod = 4; 48 const int kStatisticsUpdatePeriod = 4;
50 49
51 } // namespace 50 } // namespace
52 51
53 MediaPipelineImpl::MediaPipelineImpl() 52 MediaPipelineImpl::MediaPipelineImpl()
54 : has_audio_(false), 53 : audio_decoder_(nullptr),
54 video_decoder_(nullptr),
55 backend_initialized_(false),
56 has_audio_(false),
55 has_video_(false), 57 has_video_(false),
56 target_playback_rate_(0.0), 58 paused_(false),
59 target_playback_rate_(1.0f),
57 enable_time_update_(false), 60 enable_time_update_(false),
58 pending_time_update_task_(false), 61 pending_time_update_task_(false),
59 statistics_rolling_counter_(0), 62 statistics_rolling_counter_(0),
60 weak_factory_(this) { 63 weak_factory_(this) {
61 CMALOG(kLogControl) << __FUNCTION__; 64 CMALOG(kLogControl) << __FUNCTION__;
62 weak_this_ = weak_factory_.GetWeakPtr(); 65 weak_this_ = weak_factory_.GetWeakPtr();
63 thread_checker_.DetachFromThread(); 66 thread_checker_.DetachFromThread();
64 } 67 }
65 68
66 MediaPipelineImpl::~MediaPipelineImpl() { 69 MediaPipelineImpl::~MediaPipelineImpl() {
(...skipping 10 matching lines...) Expand all
77 if (!client_.pipeline_backend_destroyed_cb.is_null()) 80 if (!client_.pipeline_backend_destroyed_cb.is_null())
78 client_.pipeline_backend_destroyed_cb.Run(); 81 client_.pipeline_backend_destroyed_cb.Run();
79 } 82 }
80 83
81 void MediaPipelineImpl::Initialize( 84 void MediaPipelineImpl::Initialize(
82 LoadType load_type, 85 LoadType load_type,
83 scoped_ptr<MediaPipelineBackend> media_pipeline_backend) { 86 scoped_ptr<MediaPipelineBackend> media_pipeline_backend) {
84 CMALOG(kLogControl) << __FUNCTION__; 87 CMALOG(kLogControl) << __FUNCTION__;
85 DCHECK(thread_checker_.CalledOnValidThread()); 88 DCHECK(thread_checker_.CalledOnValidThread());
86 media_pipeline_backend_.reset(media_pipeline_backend.release()); 89 media_pipeline_backend_.reset(media_pipeline_backend.release());
87 clock_device_ = media_pipeline_backend_->GetClock();
88 if (!client_.pipeline_backend_created_cb.is_null()) 90 if (!client_.pipeline_backend_created_cb.is_null())
89 client_.pipeline_backend_created_cb.Run(); 91 client_.pipeline_backend_created_cb.Run();
90 92
91 if (load_type == kLoadTypeURL || load_type == kLoadTypeMediaSource) { 93 if (load_type == kLoadTypeURL || load_type == kLoadTypeMediaSource) {
92 base::TimeDelta low_threshold(kLowBufferThresholdURL); 94 base::TimeDelta low_threshold(kLowBufferThresholdURL);
93 base::TimeDelta high_threshold(kHighBufferThresholdURL); 95 base::TimeDelta high_threshold(kHighBufferThresholdURL);
94 if (load_type == kLoadTypeMediaSource) { 96 if (load_type == kLoadTypeMediaSource) {
95 low_threshold = kLowBufferThresholdMediaSource; 97 low_threshold = kLowBufferThresholdMediaSource;
96 high_threshold = kHighBufferThresholdMediaSource; 98 high_threshold = kHighBufferThresholdMediaSource;
97 } 99 }
98 scoped_refptr<BufferingConfig> buffering_config( 100 scoped_refptr<BufferingConfig> buffering_config(
99 new BufferingConfig(low_threshold, high_threshold)); 101 new BufferingConfig(low_threshold, high_threshold));
100 buffering_controller_.reset(new BufferingController( 102 buffering_controller_.reset(new BufferingController(
101 buffering_config, 103 buffering_config,
102 base::Bind(&MediaPipelineImpl::OnBufferingNotification, weak_this_))); 104 base::Bind(&MediaPipelineImpl::OnBufferingNotification, weak_this_)));
103 } 105 }
104
105 audio_pipeline_.reset(
106 new AudioPipelineImpl(media_pipeline_backend_->GetAudio()));
107
108 video_pipeline_.reset(
109 new VideoPipelineImpl(media_pipeline_backend_->GetVideo()));
110 } 106 }
111 107
112 void MediaPipelineImpl::SetClient(const MediaPipelineClient& client) { 108 void MediaPipelineImpl::SetClient(const MediaPipelineClient& client) {
113 DCHECK(thread_checker_.CalledOnValidThread()); 109 DCHECK(thread_checker_.CalledOnValidThread());
114 DCHECK(!client.error_cb.is_null()); 110 DCHECK(!client.error_cb.is_null());
115 DCHECK(!client.time_update_cb.is_null()); 111 DCHECK(!client.time_update_cb.is_null());
116 DCHECK(!client.buffering_state_cb.is_null()); 112 DCHECK(!client.buffering_state_cb.is_null());
117 DCHECK(!client.pipeline_backend_created_cb.is_null()); 113 DCHECK(!client.pipeline_backend_created_cb.is_null());
118 DCHECK(!client.pipeline_backend_destroyed_cb.is_null()); 114 DCHECK(!client.pipeline_backend_destroyed_cb.is_null());
119 client_ = client; 115 client_ = client;
120 } 116 }
121 117
122 void MediaPipelineImpl::SetCdm(int cdm_id) { 118 void MediaPipelineImpl::SetCdm(int cdm_id) {
123 CMALOG(kLogControl) << __FUNCTION__ << " cdm_id=" << cdm_id; 119 CMALOG(kLogControl) << __FUNCTION__ << " cdm_id=" << cdm_id;
124 DCHECK(thread_checker_.CalledOnValidThread()); 120 DCHECK(thread_checker_.CalledOnValidThread());
125 NOTIMPLEMENTED(); 121 NOTIMPLEMENTED();
126 // TODO(gunsch): SetCdm(int) is not implemented. 122 // TODO(gunsch): SetCdm(int) is not implemented.
127 // One possibility would be a GetCdmByIdCB that's passed in. 123 // One possibility would be a GetCdmByIdCB that's passed in.
128 } 124 }
129 125
126 void MediaPipelineImpl::OnVideoResolutionChanged(
127 MediaPipelineBackend::VideoDecoder* decoder,
128 const Size& size) {
129 DCHECK(decoder == video_decoder_);
130 video_pipeline_->OnNaturalSizeChanged(size);
131 }
132
133 void MediaPipelineImpl::OnPushBufferComplete(
134 MediaPipelineBackend::Decoder* decoder,
135 MediaPipelineBackend::BufferStatus status) {
136 if (decoder == audio_decoder_)
137 audio_pipeline_->OnBufferPushed(status);
138 else if (decoder == video_decoder_)
139 video_pipeline_->OnBufferPushed(status);
140 }
141
142 void MediaPipelineImpl::OnEndOfStream(MediaPipelineBackend::Decoder* decoder) {
143 if (decoder == audio_decoder_)
144 audio_pipeline_->OnEndOfStream();
145 else if (decoder == video_decoder_)
146 video_pipeline_->OnEndOfStream();
147 }
148
149 void MediaPipelineImpl::OnDecoderError(MediaPipelineBackend::Decoder* decoder) {
150 if (decoder == audio_decoder_)
151 audio_pipeline_->OnError();
152 else if (decoder == video_decoder_)
153 video_pipeline_->OnError();
154 }
155
130 void MediaPipelineImpl::SetCdm(BrowserCdmCast* cdm) { 156 void MediaPipelineImpl::SetCdm(BrowserCdmCast* cdm) {
131 CMALOG(kLogControl) << __FUNCTION__; 157 CMALOG(kLogControl) << __FUNCTION__;
132 DCHECK(thread_checker_.CalledOnValidThread()); 158 DCHECK(thread_checker_.CalledOnValidThread());
133 audio_pipeline_->SetCdm(cdm); 159 audio_pipeline_->SetCdm(cdm);
134 video_pipeline_->SetCdm(cdm); 160 video_pipeline_->SetCdm(cdm);
135 } 161 }
136 162
137 AudioPipeline* MediaPipelineImpl::GetAudioPipeline() const {
138 return audio_pipeline_.get();
139 }
140
141 VideoPipeline* MediaPipelineImpl::GetVideoPipeline() const {
142 return video_pipeline_.get();
143 }
144
145 void MediaPipelineImpl::InitializeAudio( 163 void MediaPipelineImpl::InitializeAudio(
146 const ::media::AudioDecoderConfig& config, 164 const ::media::AudioDecoderConfig& config,
165 const AvPipelineClient& client,
147 scoped_ptr<CodedFrameProvider> frame_provider, 166 scoped_ptr<CodedFrameProvider> frame_provider,
148 const ::media::PipelineStatusCB& status_cb) { 167 const ::media::PipelineStatusCB& status_cb) {
149 DCHECK(thread_checker_.CalledOnValidThread()); 168 DCHECK(thread_checker_.CalledOnValidThread());
150 DCHECK(!has_audio_); 169 DCHECK(!has_audio_);
151 if (clock_device_->GetState() == MediaClockDevice::kStateUninitialized && 170
152 !clock_device_->SetState(MediaClockDevice::kStateIdle)) { 171 has_audio_ = true;
153 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED); 172
173 audio_decoder_ = media_pipeline_backend_->CreateAudioDecoder();
174 if (!audio_decoder_) {
175 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
154 return; 176 return;
155 } 177 }
156 has_audio_ = true; 178 audio_pipeline_.reset(new AudioPipelineImpl(audio_decoder_, client));
157 audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb); 179 audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
158 } 180 }
159 181
160 void MediaPipelineImpl::InitializeVideo( 182 void MediaPipelineImpl::InitializeVideo(
161 const std::vector<::media::VideoDecoderConfig>& configs, 183 const std::vector< ::media::VideoDecoderConfig>& configs,
184 const VideoPipelineClient& client,
162 scoped_ptr<CodedFrameProvider> frame_provider, 185 scoped_ptr<CodedFrameProvider> frame_provider,
163 const ::media::PipelineStatusCB& status_cb) { 186 const ::media::PipelineStatusCB& status_cb) {
164 DCHECK(thread_checker_.CalledOnValidThread()); 187 DCHECK(thread_checker_.CalledOnValidThread());
165 DCHECK(!has_video_); 188 DCHECK(!has_video_);
166 if (clock_device_->GetState() == MediaClockDevice::kStateUninitialized && 189
167 !clock_device_->SetState(MediaClockDevice::kStateIdle)) { 190 has_video_ = true;
168 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED); 191 video_decoder_ = media_pipeline_backend_->CreateVideoDecoder();
192 if (!video_decoder_) {
193 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
169 return; 194 return;
170 } 195 }
171 has_video_ = true; 196 video_pipeline_.reset(new VideoPipelineImpl(video_decoder_, client));
197
172 video_pipeline_->Initialize(configs, frame_provider.Pass(), status_cb); 198 video_pipeline_->Initialize(configs, frame_provider.Pass(), status_cb);
173 } 199 }
174 200
175 void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) { 201 void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) {
176 CMALOG(kLogControl) << __FUNCTION__ << " t0=" << time.InMilliseconds(); 202 CMALOG(kLogControl) << __FUNCTION__ << " t0=" << time.InMilliseconds();
177 DCHECK(thread_checker_.CalledOnValidThread()); 203 DCHECK(thread_checker_.CalledOnValidThread());
178 DCHECK(has_audio_ || has_video_); 204 DCHECK(has_audio_ || has_video_);
179 DCHECK(!pending_flush_callbacks_); 205 DCHECK(!pending_flush_callbacks_);
206 // When starting, we always enter the "playing" state (not paused).
207 paused_ = false;
180 208
181 // Reset the start of the timeline. 209 // Lazy initialise
182 DCHECK_EQ(clock_device_->GetState(), MediaClockDevice::kStateIdle); 210 if (!backend_initialized_) {
183 clock_device_->ResetTimeline(time.InMicroseconds()); 211 backend_initialized_ = media_pipeline_backend_->Initialize(this);
212 if (!backend_initialized_) {
213 OnError(::media::PIPELINE_ERROR_ABORT);
214 return;
215 }
216 }
184 217
185 // Start the clock. If the playback rate is 0, then the clock is started 218 // Start the backend.
186 // but does not increase. 219 if (!media_pipeline_backend_->Start(time.InMicroseconds())) {
187 if (!clock_device_->SetState(MediaClockDevice::kStateRunning)) {
188 OnError(::media::PIPELINE_ERROR_ABORT); 220 OnError(::media::PIPELINE_ERROR_ABORT);
189 return; 221 return;
190 } 222 }
191 223
192 // Enable time updates. 224 // Enable time updates.
193 enable_time_update_ = true; 225 enable_time_update_ = true;
194 statistics_rolling_counter_ = 0; 226 statistics_rolling_counter_ = 0;
195 if (!pending_time_update_task_) { 227 if (!pending_time_update_task_) {
196 pending_time_update_task_ = true; 228 pending_time_update_task_ = true;
197 base::ThreadTaskRunnerHandle::Get()->PostTask( 229 base::ThreadTaskRunnerHandle::Get()->PostTask(
(...skipping 19 matching lines...) Expand all
217 return; 249 return;
218 } 250 }
219 } 251 }
220 } 252 }
221 253
222 void MediaPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) { 254 void MediaPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
223 CMALOG(kLogControl) << __FUNCTION__; 255 CMALOG(kLogControl) << __FUNCTION__;
224 DCHECK(thread_checker_.CalledOnValidThread()); 256 DCHECK(thread_checker_.CalledOnValidThread());
225 DCHECK(has_audio_ || has_video_); 257 DCHECK(has_audio_ || has_video_);
226 DCHECK(!pending_flush_callbacks_); 258 DCHECK(!pending_flush_callbacks_);
227 DCHECK(clock_device_->GetState() == MediaClockDevice::kStateUninitialized ||
228 clock_device_->GetState() == MediaClockDevice::kStateRunning);
229 259
230 // No need to update media time anymore. 260 // No need to update media time anymore.
231 enable_time_update_ = false; 261 enable_time_update_ = false;
232 262
233 buffering_controller_->Reset(); 263 buffering_controller_->Reset();
234 264
235 // The clock should return to idle. 265 // Stop the backend
236 if (!clock_device_->SetState(MediaClockDevice::kStateIdle)) { 266 if (!media_pipeline_backend_->Stop()) {
237 status_cb.Run(::media::PIPELINE_ERROR_ABORT); 267 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
238 return; 268 return;
239 } 269 }
240 270
241 // Flush both the audio and video pipeline. 271 // Flush both the audio and video pipeline.
242 ::media::SerialRunner::Queue bound_fns; 272 ::media::SerialRunner::Queue bound_fns;
243 if (has_audio_) { 273 if (has_audio_) {
244 bound_fns.Push(base::Bind( 274 bound_fns.Push(base::Bind(
245 &AudioPipelineImpl::Flush, 275 &AudioPipelineImpl::Flush,
246 base::Unretained(audio_pipeline_.get()))); 276 base::Unretained(audio_pipeline_.get())));
(...skipping 15 matching lines...) Expand all
262 DCHECK(has_audio_ || has_video_); 292 DCHECK(has_audio_ || has_video_);
263 293
264 // Cancel pending flush callbacks since we are about to stop/shutdown 294 // Cancel pending flush callbacks since we are about to stop/shutdown
265 // audio/video pipelines. This will ensure A/V Flush won't happen in 295 // audio/video pipelines. This will ensure A/V Flush won't happen in
266 // stopped state. 296 // stopped state.
267 pending_flush_callbacks_.reset(); 297 pending_flush_callbacks_.reset();
268 298
269 // No need to update media time anymore. 299 // No need to update media time anymore.
270 enable_time_update_ = false; 300 enable_time_update_ = false;
271 301
272 // Release hardware resources on Stop.
273 // Note: Stop can be called from any state.
274 if (clock_device_->GetState() == MediaClockDevice::kStateRunning)
275 clock_device_->SetState(MediaClockDevice::kStateIdle);
276 if (clock_device_->GetState() == MediaClockDevice::kStateIdle)
277 clock_device_->SetState(MediaClockDevice::kStateUninitialized);
278
279 // Stop both the audio and video pipeline. 302 // Stop both the audio and video pipeline.
280 if (has_audio_) 303 if (has_audio_)
281 audio_pipeline_->Stop(); 304 audio_pipeline_->Stop();
282 if (has_video_) 305 if (has_video_)
283 video_pipeline_->Stop(); 306 video_pipeline_->Stop();
307
308 // Release hardware resources on Stop.
309 audio_pipeline_ = nullptr;
310 video_pipeline_ = nullptr;
311 media_pipeline_backend_.reset();
284 } 312 }
285 313
286 void MediaPipelineImpl::SetPlaybackRate(double rate) { 314 void MediaPipelineImpl::SetPlaybackRate(double rate) {
287 CMALOG(kLogControl) << __FUNCTION__ << " rate=" << rate; 315 CMALOG(kLogControl) << __FUNCTION__ << " rate=" << rate;
288 DCHECK(thread_checker_.CalledOnValidThread()); 316 DCHECK(thread_checker_.CalledOnValidThread());
317 if (!buffering_controller_ || !buffering_controller_->IsBuffering()) {
318 if (paused_ && rate != 0.0f) {
319 if (rate != target_playback_rate_)
320 media_pipeline_backend_->SetPlaybackRate(rate);
321 paused_ = false;
322 media_pipeline_backend_->Resume();
323 } else if (!paused_ && rate == 0.0f) {
324 paused_ = true;
325 media_pipeline_backend_->Pause();
326 } else {
327 media_pipeline_backend_->SetPlaybackRate(rate);
328 }
329 }
289 target_playback_rate_ = rate; 330 target_playback_rate_ = rate;
290 if (!buffering_controller_ || !buffering_controller_->IsBuffering())
291 media_pipeline_backend_->GetClock()->SetRate(rate);
292 } 331 }
293 332
294 AudioPipelineImpl* MediaPipelineImpl::GetAudioPipelineImpl() const { 333 void MediaPipelineImpl::SetVolume(float volume) {
295 return audio_pipeline_.get(); 334 CMALOG(kLogControl) << __FUNCTION__ << " vol=" << volume;
296 } 335 DCHECK(thread_checker_.CalledOnValidThread());
297 336 DCHECK(audio_pipeline_);
298 VideoPipelineImpl* MediaPipelineImpl::GetVideoPipelineImpl() const { 337 audio_pipeline_->SetVolume(volume);
299 return video_pipeline_.get();
300 } 338 }
301 339
302 void MediaPipelineImpl::StateTransition( 340 void MediaPipelineImpl::StateTransition(
303 const ::media::PipelineStatusCB& status_cb, 341 const ::media::PipelineStatusCB& status_cb,
304 ::media::PipelineStatus status) { 342 ::media::PipelineStatus status) {
305 pending_flush_callbacks_.reset(); 343 pending_flush_callbacks_.reset();
306 status_cb.Run(status); 344 status_cb.Run(status);
307 } 345 }
308 346
309 void MediaPipelineImpl::OnBufferingNotification(bool is_buffering) { 347 void MediaPipelineImpl::OnBufferingNotification(bool is_buffering) {
310 CMALOG(kLogControl) << __FUNCTION__ << " is_buffering=" << is_buffering; 348 CMALOG(kLogControl) << __FUNCTION__ << " is_buffering=" << is_buffering;
311 DCHECK(thread_checker_.CalledOnValidThread()); 349 DCHECK(thread_checker_.CalledOnValidThread());
312 DCHECK(buffering_controller_); 350 DCHECK(buffering_controller_);
313 351
314 if (!client_.buffering_state_cb.is_null()) { 352 if (!client_.buffering_state_cb.is_null()) {
315 ::media::BufferingState buffering_state = is_buffering ? 353 ::media::BufferingState buffering_state = is_buffering ?
316 ::media::BUFFERING_HAVE_NOTHING : ::media::BUFFERING_HAVE_ENOUGH; 354 ::media::BUFFERING_HAVE_NOTHING : ::media::BUFFERING_HAVE_ENOUGH;
317 client_.buffering_state_cb.Run(buffering_state); 355 client_.buffering_state_cb.Run(buffering_state);
318 } 356 }
319 357
320 if (media_pipeline_backend_->GetClock()->GetState() ==
321 MediaClockDevice::kStateUninitialized) {
322 return;
323 }
324
325 if (is_buffering) { 358 if (is_buffering) {
326 // Do not consume data in a rebuffering phase. 359 // Do not consume data in a rebuffering phase.
327 media_pipeline_backend_->GetClock()->SetRate(0.0); 360 if (!paused_) {
328 } else { 361 paused_ = true;
329 media_pipeline_backend_->GetClock()->SetRate(target_playback_rate_); 362 media_pipeline_backend_->Pause();
363 }
364 } else if (paused_) {
365 paused_ = false;
366 media_pipeline_backend_->Resume();
330 } 367 }
331 } 368 }
332 369
333 void MediaPipelineImpl::UpdateMediaTime() { 370 void MediaPipelineImpl::UpdateMediaTime() {
334 pending_time_update_task_ = false; 371 pending_time_update_task_ = false;
335 if (!enable_time_update_) 372 if (!enable_time_update_)
336 return; 373 return;
337 374
338 if (statistics_rolling_counter_ == 0) { 375 if (statistics_rolling_counter_ == 0) {
339 audio_pipeline_->UpdateStatistics(); 376 if (audio_pipeline_)
340 video_pipeline_->UpdateStatistics(); 377 audio_pipeline_->UpdateStatistics();
378 if (video_pipeline_)
379 video_pipeline_->UpdateStatistics();
341 } 380 }
342 statistics_rolling_counter_ = 381 statistics_rolling_counter_ =
343 (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod; 382 (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod;
344 383
345 base::TimeDelta media_time = 384 base::TimeDelta media_time = base::TimeDelta::FromMicroseconds(
346 base::TimeDelta::FromMicroseconds(clock_device_->GetTimeMicroseconds()); 385 media_pipeline_backend_->GetCurrentPts());
347 if (media_time == ::media::kNoTimestamp()) { 386 if (media_time == ::media::kNoTimestamp()) {
348 pending_time_update_task_ = true; 387 pending_time_update_task_ = true;
349 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 388 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
350 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_), 389 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_),
351 kTimeUpdateInterval); 390 kTimeUpdateInterval);
352 return; 391 return;
353 } 392 }
354 base::TimeTicks stc = base::TimeTicks::Now(); 393 base::TimeTicks stc = base::TimeTicks::Now();
355 394
356 base::TimeDelta max_rendering_time = media_time; 395 base::TimeDelta max_rendering_time = media_time;
(...skipping 25 matching lines...) Expand all
382 421
383 void MediaPipelineImpl::OnError(::media::PipelineStatus error) { 422 void MediaPipelineImpl::OnError(::media::PipelineStatus error) {
384 DCHECK(thread_checker_.CalledOnValidThread()); 423 DCHECK(thread_checker_.CalledOnValidThread());
385 DCHECK_NE(error, ::media::PIPELINE_OK) << "PIPELINE_OK is not an error!"; 424 DCHECK_NE(error, ::media::PIPELINE_OK) << "PIPELINE_OK is not an error!";
386 if (!client_.error_cb.is_null()) 425 if (!client_.error_cb.is_null())
387 client_.error_cb.Run(error); 426 client_.error_cb.Run(error);
388 } 427 }
389 428
390 } // namespace media 429 } // namespace media
391 } // namespace chromecast 430 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/media/cma/pipeline/media_pipeline_impl.h ('k') | chromecast/media/cma/pipeline/video_pipeline.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698