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

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: 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 BrowserMediaPipelineClient& 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::Decoder* 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 BrowserAvPipelineClient& 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)) {
153 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
154 return;
155 }
156 has_audio_ = true; 171 has_audio_ = true;
172
173 audio_decoder_ = media_pipeline_backend_->CreateAudioDecoder();
174 audio_pipeline_.reset(new AudioPipelineImpl(audio_decoder_, client));
157 audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb); 175 audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
158 } 176 }
159 177
160 void MediaPipelineImpl::InitializeVideo( 178 void MediaPipelineImpl::InitializeVideo(
161 const std::vector<::media::VideoDecoderConfig>& configs, 179 const std::vector< ::media::VideoDecoderConfig>& configs,
180 const BrowserVideoPipelineClient& client,
162 scoped_ptr<CodedFrameProvider> frame_provider, 181 scoped_ptr<CodedFrameProvider> frame_provider,
163 const ::media::PipelineStatusCB& status_cb) { 182 const ::media::PipelineStatusCB& status_cb) {
164 DCHECK(thread_checker_.CalledOnValidThread()); 183 DCHECK(thread_checker_.CalledOnValidThread());
165 DCHECK(!has_video_); 184 DCHECK(!has_video_);
166 if (clock_device_->GetState() == MediaClockDevice::kStateUninitialized && 185
167 !clock_device_->SetState(MediaClockDevice::kStateIdle)) {
168 status_cb.Run(::media::PIPELINE_ERROR_INITIALIZATION_FAILED);
169 return;
170 }
171 has_video_ = true; 186 has_video_ = true;
187 video_decoder_ = media_pipeline_backend_->CreateVideoDecoder();
188 video_pipeline_.reset(new VideoPipelineImpl(video_decoder_, client));
189
172 video_pipeline_->Initialize(configs, frame_provider.Pass(), status_cb); 190 video_pipeline_->Initialize(configs, frame_provider.Pass(), status_cb);
173 } 191 }
174 192
175 void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) { 193 void MediaPipelineImpl::StartPlayingFrom(base::TimeDelta time) {
176 CMALOG(kLogControl) << __FUNCTION__ << " t0=" << time.InMilliseconds(); 194 CMALOG(kLogControl) << __FUNCTION__ << " t0=" << time.InMilliseconds();
177 DCHECK(thread_checker_.CalledOnValidThread()); 195 DCHECK(thread_checker_.CalledOnValidThread());
178 DCHECK(has_audio_ || has_video_); 196 DCHECK(has_audio_ || has_video_);
179 DCHECK(!pending_flush_callbacks_); 197 DCHECK(!pending_flush_callbacks_);
198 // When starting, we always enter the "playing" state (not paused).
199 paused_ = false;
180 200
181 // Reset the start of the timeline. 201 // Lazy initialise
182 DCHECK_EQ(clock_device_->GetState(), MediaClockDevice::kStateIdle); 202 if (!backend_initialized_) {
183 clock_device_->ResetTimeline(time.InMicroseconds()); 203 backend_initialized_ = media_pipeline_backend_->Initialize(this);
204 if (!backend_initialized_) {
205 OnError(::media::PIPELINE_ERROR_ABORT);
206 return;
207 }
208 }
184 209
185 // Start the clock. If the playback rate is 0, then the clock is started 210 // Start the backend.
186 // but does not increase. 211 if (!media_pipeline_backend_->Start(time.InMicroseconds())) {
187 if (!clock_device_->SetState(MediaClockDevice::kStateRunning)) {
188 OnError(::media::PIPELINE_ERROR_ABORT); 212 OnError(::media::PIPELINE_ERROR_ABORT);
189 return; 213 return;
190 } 214 }
191 215
192 // Enable time updates. 216 // Enable time updates.
193 enable_time_update_ = true; 217 enable_time_update_ = true;
194 statistics_rolling_counter_ = 0; 218 statistics_rolling_counter_ = 0;
195 if (!pending_time_update_task_) { 219 if (!pending_time_update_task_) {
196 pending_time_update_task_ = true; 220 pending_time_update_task_ = true;
197 base::ThreadTaskRunnerHandle::Get()->PostTask( 221 base::ThreadTaskRunnerHandle::Get()->PostTask(
(...skipping 19 matching lines...) Expand all
217 return; 241 return;
218 } 242 }
219 } 243 }
220 } 244 }
221 245
222 void MediaPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) { 246 void MediaPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
223 CMALOG(kLogControl) << __FUNCTION__; 247 CMALOG(kLogControl) << __FUNCTION__;
224 DCHECK(thread_checker_.CalledOnValidThread()); 248 DCHECK(thread_checker_.CalledOnValidThread());
225 DCHECK(has_audio_ || has_video_); 249 DCHECK(has_audio_ || has_video_);
226 DCHECK(!pending_flush_callbacks_); 250 DCHECK(!pending_flush_callbacks_);
227 DCHECK(clock_device_->GetState() == MediaClockDevice::kStateUninitialized ||
228 clock_device_->GetState() == MediaClockDevice::kStateRunning);
229 251
230 // No need to update media time anymore. 252 // No need to update media time anymore.
231 enable_time_update_ = false; 253 enable_time_update_ = false;
232 254
233 buffering_controller_->Reset(); 255 buffering_controller_->Reset();
234 256
235 // The clock should return to idle. 257 // Stop the backend
236 if (!clock_device_->SetState(MediaClockDevice::kStateIdle)) { 258 if (!media_pipeline_backend_->Stop()) {
237 status_cb.Run(::media::PIPELINE_ERROR_ABORT); 259 status_cb.Run(::media::PIPELINE_ERROR_ABORT);
238 return; 260 return;
239 } 261 }
240 262
241 // Flush both the audio and video pipeline. 263 // Flush both the audio and video pipeline.
242 ::media::SerialRunner::Queue bound_fns; 264 ::media::SerialRunner::Queue bound_fns;
243 if (has_audio_) { 265 if (has_audio_) {
244 bound_fns.Push(base::Bind( 266 bound_fns.Push(base::Bind(
245 &AudioPipelineImpl::Flush, 267 &AudioPipelineImpl::Flush,
246 base::Unretained(audio_pipeline_.get()))); 268 base::Unretained(audio_pipeline_.get())));
(...skipping 15 matching lines...) Expand all
262 DCHECK(has_audio_ || has_video_); 284 DCHECK(has_audio_ || has_video_);
263 285
264 // Cancel pending flush callbacks since we are about to stop/shutdown 286 // 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 287 // audio/video pipelines. This will ensure A/V Flush won't happen in
266 // stopped state. 288 // stopped state.
267 pending_flush_callbacks_.reset(); 289 pending_flush_callbacks_.reset();
268 290
269 // No need to update media time anymore. 291 // No need to update media time anymore.
270 enable_time_update_ = false; 292 enable_time_update_ = false;
271 293
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. 294 // Stop both the audio and video pipeline.
280 if (has_audio_) 295 if (has_audio_)
281 audio_pipeline_->Stop(); 296 audio_pipeline_->Stop();
282 if (has_video_) 297 if (has_video_)
283 video_pipeline_->Stop(); 298 video_pipeline_->Stop();
299
300 // Release hardware resources on Stop.
301 audio_pipeline_ = nullptr;
302 video_pipeline_ = nullptr;
303 media_pipeline_backend_.reset();
284 } 304 }
285 305
286 void MediaPipelineImpl::SetPlaybackRate(double rate) { 306 void MediaPipelineImpl::SetPlaybackRate(double rate) {
287 CMALOG(kLogControl) << __FUNCTION__ << " rate=" << rate; 307 CMALOG(kLogControl) << __FUNCTION__ << " rate=" << rate;
288 DCHECK(thread_checker_.CalledOnValidThread()); 308 DCHECK(thread_checker_.CalledOnValidThread());
309 if (!buffering_controller_ || !buffering_controller_->IsBuffering()) {
310 if (paused_ && rate != 0.0f) {
311 if (rate != target_playback_rate_)
312 media_pipeline_backend_->SetPlaybackRate(rate);
313 paused_ = false;
314 media_pipeline_backend_->Resume();
315 } else if (!paused_ && rate == 0.0f) {
316 paused_ = true;
317 media_pipeline_backend_->Pause();
318 } else {
319 media_pipeline_backend_->SetPlaybackRate(rate);
320 }
321 }
289 target_playback_rate_ = rate; 322 target_playback_rate_ = rate;
290 if (!buffering_controller_ || !buffering_controller_->IsBuffering())
291 media_pipeline_backend_->GetClock()->SetRate(rate);
292 } 323 }
293 324
294 AudioPipelineImpl* MediaPipelineImpl::GetAudioPipelineImpl() const { 325 void MediaPipelineImpl::SetVolume(float volume) {
295 return audio_pipeline_.get(); 326 CMALOG(kLogControl) << __FUNCTION__ << " vol=" << volume;
296 } 327 DCHECK(thread_checker_.CalledOnValidThread());
297 328 DCHECK(audio_pipeline_);
298 VideoPipelineImpl* MediaPipelineImpl::GetVideoPipelineImpl() const { 329 audio_pipeline_->SetVolume(volume);
299 return video_pipeline_.get();
300 } 330 }
301 331
302 void MediaPipelineImpl::StateTransition( 332 void MediaPipelineImpl::StateTransition(
303 const ::media::PipelineStatusCB& status_cb, 333 const ::media::PipelineStatusCB& status_cb,
304 ::media::PipelineStatus status) { 334 ::media::PipelineStatus status) {
305 pending_flush_callbacks_.reset(); 335 pending_flush_callbacks_.reset();
306 status_cb.Run(status); 336 status_cb.Run(status);
307 } 337 }
308 338
309 void MediaPipelineImpl::OnBufferingNotification(bool is_buffering) { 339 void MediaPipelineImpl::OnBufferingNotification(bool is_buffering) {
310 CMALOG(kLogControl) << __FUNCTION__ << " is_buffering=" << is_buffering; 340 CMALOG(kLogControl) << __FUNCTION__ << " is_buffering=" << is_buffering;
311 DCHECK(thread_checker_.CalledOnValidThread()); 341 DCHECK(thread_checker_.CalledOnValidThread());
312 DCHECK(buffering_controller_); 342 DCHECK(buffering_controller_);
313 343
314 if (!client_.buffering_state_cb.is_null()) { 344 if (!client_.buffering_state_cb.is_null()) {
315 ::media::BufferingState buffering_state = is_buffering ? 345 ::media::BufferingState buffering_state = is_buffering ?
316 ::media::BUFFERING_HAVE_NOTHING : ::media::BUFFERING_HAVE_ENOUGH; 346 ::media::BUFFERING_HAVE_NOTHING : ::media::BUFFERING_HAVE_ENOUGH;
317 client_.buffering_state_cb.Run(buffering_state); 347 client_.buffering_state_cb.Run(buffering_state);
318 } 348 }
319 349
320 if (media_pipeline_backend_->GetClock()->GetState() ==
321 MediaClockDevice::kStateUninitialized) {
322 return;
323 }
324
325 if (is_buffering) { 350 if (is_buffering) {
326 // Do not consume data in a rebuffering phase. 351 // Do not consume data in a rebuffering phase.
327 media_pipeline_backend_->GetClock()->SetRate(0.0); 352 if (!paused_) {
328 } else { 353 paused_ = true;
329 media_pipeline_backend_->GetClock()->SetRate(target_playback_rate_); 354 media_pipeline_backend_->Pause();
355 }
356 } else if (paused_) {
357 paused_ = false;
358 media_pipeline_backend_->Resume();
330 } 359 }
331 } 360 }
332 361
333 void MediaPipelineImpl::UpdateMediaTime() { 362 void MediaPipelineImpl::UpdateMediaTime() {
334 pending_time_update_task_ = false; 363 pending_time_update_task_ = false;
335 if (!enable_time_update_) 364 if (!enable_time_update_)
336 return; 365 return;
337 366
338 if (statistics_rolling_counter_ == 0) { 367 if (statistics_rolling_counter_ == 0) {
339 audio_pipeline_->UpdateStatistics(); 368 if (audio_pipeline_)
340 video_pipeline_->UpdateStatistics(); 369 audio_pipeline_->UpdateStatistics();
370 if (video_pipeline_)
371 video_pipeline_->UpdateStatistics();
341 } 372 }
342 statistics_rolling_counter_ = 373 statistics_rolling_counter_ =
343 (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod; 374 (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod;
344 375
345 base::TimeDelta media_time = 376 base::TimeDelta media_time = base::TimeDelta::FromMicroseconds(
346 base::TimeDelta::FromMicroseconds(clock_device_->GetTimeMicroseconds()); 377 media_pipeline_backend_->GetCurrentPts());
347 if (media_time == ::media::kNoTimestamp()) { 378 if (media_time == ::media::kNoTimestamp()) {
348 pending_time_update_task_ = true; 379 pending_time_update_task_ = true;
349 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 380 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
350 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_), 381 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_),
351 kTimeUpdateInterval); 382 kTimeUpdateInterval);
352 return; 383 return;
353 } 384 }
354 base::TimeTicks stc = base::TimeTicks::Now(); 385 base::TimeTicks stc = base::TimeTicks::Now();
355 386
356 base::TimeDelta max_rendering_time = media_time; 387 base::TimeDelta max_rendering_time = media_time;
(...skipping 25 matching lines...) Expand all
382 413
383 void MediaPipelineImpl::OnError(::media::PipelineStatus error) { 414 void MediaPipelineImpl::OnError(::media::PipelineStatus error) {
384 DCHECK(thread_checker_.CalledOnValidThread()); 415 DCHECK(thread_checker_.CalledOnValidThread());
385 DCHECK_NE(error, ::media::PIPELINE_OK) << "PIPELINE_OK is not an error!"; 416 DCHECK_NE(error, ::media::PIPELINE_OK) << "PIPELINE_OK is not an error!";
386 if (!client_.error_cb.is_null()) 417 if (!client_.error_cb.is_null())
387 client_.error_cb.Run(error); 418 client_.error_cb.Run(error);
388 } 419 }
389 420
390 } // namespace media 421 } // namespace media
391 } // namespace chromecast 422 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698