| OLD | NEW |
| 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 "media/renderers/renderer_impl.h" | 5 #include "media/renderers/renderer_impl.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/location.h" | 14 #include "base/location.h" |
| 15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "media/base/audio_decoder_config.h" |
| 17 #include "media/base/audio_renderer.h" | 18 #include "media/base/audio_renderer.h" |
| 18 #include "media/base/bind_to_current_loop.h" | 19 #include "media/base/bind_to_current_loop.h" |
| 19 #include "media/base/demuxer_stream_provider.h" | 20 #include "media/base/demuxer_stream_provider.h" |
| 20 #include "media/base/media_switches.h" | 21 #include "media/base/media_switches.h" |
| 21 #include "media/base/time_source.h" | 22 #include "media/base/time_source.h" |
| 23 #include "media/base/video_decoder_config.h" |
| 22 #include "media/base/video_renderer.h" | 24 #include "media/base/video_renderer.h" |
| 23 #include "media/base/wall_clock_time_source.h" | 25 #include "media/base/wall_clock_time_source.h" |
| 24 | 26 |
| 25 namespace media { | 27 namespace media { |
| 26 | 28 |
| 27 // See |video_underflow_threshold_|. | 29 // See |video_underflow_threshold_|. |
| 28 static const int kDefaultVideoUnderflowThresholdMs = 3000; | 30 static const int kDefaultVideoUnderflowThresholdMs = 3000; |
| 29 | 31 |
| 30 RendererImpl::RendererImpl( | 32 RendererImpl::RendererImpl( |
| 31 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 33 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 | 67 |
| 66 RendererImpl::~RendererImpl() { | 68 RendererImpl::~RendererImpl() { |
| 67 DVLOG(1) << __FUNCTION__; | 69 DVLOG(1) << __FUNCTION__; |
| 68 DCHECK(task_runner_->BelongsToCurrentThread()); | 70 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 69 | 71 |
| 70 // Tear down in opposite order of construction as |video_renderer_| can still | 72 // Tear down in opposite order of construction as |video_renderer_| can still |
| 71 // need |time_source_| (which can be |audio_renderer_|) to be alive. | 73 // need |time_source_| (which can be |audio_renderer_|) to be alive. |
| 72 video_renderer_.reset(); | 74 video_renderer_.reset(); |
| 73 audio_renderer_.reset(); | 75 audio_renderer_.reset(); |
| 74 | 76 |
| 75 if (!init_cb_.is_null()) | 77 if (!init_cb_.is_null()) { |
| 76 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | 78 FinishInitialization(PIPELINE_ERROR_ABORT); |
| 77 else if (!flush_cb_.is_null()) | 79 } else if (!flush_cb_.is_null()) { |
| 78 base::ResetAndReturn(&flush_cb_).Run(); | 80 base::ResetAndReturn(&flush_cb_).Run(); |
| 81 } |
| 79 } | 82 } |
| 80 | 83 |
| 81 void RendererImpl::Initialize( | 84 void RendererImpl::Initialize( |
| 82 DemuxerStreamProvider* demuxer_stream_provider, | 85 DemuxerStreamProvider* demuxer_stream_provider, |
| 83 const PipelineStatusCB& init_cb, | 86 const PipelineStatusCB& init_cb, |
| 84 const StatisticsCB& statistics_cb, | 87 const StatisticsCB& statistics_cb, |
| 85 const BufferingStateCB& buffering_state_cb, | 88 const BufferingStateCB& buffering_state_cb, |
| 86 const base::Closure& ended_cb, | 89 const base::Closure& ended_cb, |
| 87 const PipelineStatusCB& error_cb, | 90 const PipelineStatusCB& error_cb, |
| 88 const base::Closure& waiting_for_decryption_key_cb) { | 91 const base::Closure& waiting_for_decryption_key_cb) { |
| 89 DVLOG(1) << __FUNCTION__; | 92 DVLOG(1) << __FUNCTION__; |
| 90 DCHECK(task_runner_->BelongsToCurrentThread()); | 93 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 91 DCHECK_EQ(state_, STATE_UNINITIALIZED); | 94 DCHECK_EQ(state_, STATE_UNINITIALIZED); |
| 92 DCHECK(!init_cb.is_null()); | 95 DCHECK(!init_cb.is_null()); |
| 93 DCHECK(!statistics_cb.is_null()); | 96 DCHECK(!statistics_cb.is_null()); |
| 94 DCHECK(!buffering_state_cb.is_null()); | 97 DCHECK(!buffering_state_cb.is_null()); |
| 95 DCHECK(!ended_cb.is_null()); | 98 DCHECK(!ended_cb.is_null()); |
| 96 DCHECK(!error_cb.is_null()); | 99 DCHECK(!error_cb.is_null()); |
| 97 DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) || | 100 DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) || |
| 98 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO)); | 101 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO)); |
| 99 | 102 |
| 100 demuxer_stream_provider_ = demuxer_stream_provider; | 103 demuxer_stream_provider_ = demuxer_stream_provider; |
| 101 statistics_cb_ = statistics_cb; | 104 statistics_cb_ = statistics_cb; |
| 102 buffering_state_cb_ = buffering_state_cb; | 105 buffering_state_cb_ = buffering_state_cb; |
| 103 ended_cb_ = ended_cb; | 106 ended_cb_ = ended_cb; |
| 104 error_cb_ = error_cb; | 107 error_cb_ = error_cb; |
| 105 init_cb_ = init_cb; | 108 init_cb_ = init_cb; |
| 106 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; | 109 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; |
| 107 | 110 |
| 111 if (HasEncryptedStream() && !cdm_context_) { |
| 112 state_ = STATE_INIT_PENDING_CDM; |
| 113 return; |
| 114 } |
| 115 |
| 108 state_ = STATE_INITIALIZING; | 116 state_ = STATE_INITIALIZING; |
| 109 InitializeAudioRenderer(); | 117 InitializeAudioRenderer(); |
| 110 } | 118 } |
| 111 | 119 |
| 112 void RendererImpl::SetCdm(CdmContext* cdm_context, | 120 void RendererImpl::SetCdm(CdmContext* cdm_context, |
| 113 const CdmAttachedCB& cdm_attached_cb) { | 121 const CdmAttachedCB& cdm_attached_cb) { |
| 114 DVLOG(1) << __FUNCTION__; | 122 DVLOG(1) << __FUNCTION__; |
| 115 DCHECK(task_runner_->BelongsToCurrentThread()); | 123 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 116 DCHECK(cdm_context); | 124 DCHECK(cdm_context); |
| 117 | 125 |
| 118 if (cdm_context_) { | 126 if (cdm_context_) { |
| 119 DVLOG(1) << "Switching CDM not supported."; | 127 DVLOG(1) << "Switching CDM not supported."; |
| 120 cdm_attached_cb.Run(false); | 128 cdm_attached_cb.Run(false); |
| 121 return; | 129 return; |
| 122 } | 130 } |
| 123 | 131 |
| 124 cdm_context_ = cdm_context; | 132 cdm_context_ = cdm_context; |
| 125 | 133 |
| 126 if (cdm_ready_cb_.is_null()) { | 134 if (state_ != STATE_INIT_PENDING_CDM) { |
| 127 cdm_attached_cb.Run(true); | 135 cdm_attached_cb.Run(true); |
| 128 return; | 136 return; |
| 129 } | 137 } |
| 130 | 138 |
| 131 base::ResetAndReturn(&cdm_ready_cb_).Run(cdm_context, cdm_attached_cb); | 139 DCHECK(!init_cb_.is_null()); |
| 140 state_ = STATE_INITIALIZING; |
| 141 // |cdm_attached_cb| will be fired after initialization finishes. |
| 142 pending_cdm_attached_cb_ = cdm_attached_cb; |
| 143 |
| 144 InitializeAudioRenderer(); |
| 132 } | 145 } |
| 133 | 146 |
| 134 void RendererImpl::Flush(const base::Closure& flush_cb) { | 147 void RendererImpl::Flush(const base::Closure& flush_cb) { |
| 135 DVLOG(1) << __FUNCTION__; | 148 DVLOG(1) << __FUNCTION__; |
| 136 DCHECK(task_runner_->BelongsToCurrentThread()); | 149 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 137 DCHECK(flush_cb_.is_null()); | 150 DCHECK(flush_cb_.is_null()); |
| 138 | 151 |
| 139 if (state_ != STATE_PLAYING) { | 152 if (state_ != STATE_PLAYING) { |
| 140 DCHECK_EQ(state_, STATE_ERROR); | 153 DCHECK_EQ(state_, STATE_ERROR); |
| 141 return; | 154 return; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 for (auto const &media_time : media_timestamps) { | 260 for (auto const &media_time : media_timestamps) { |
| 248 wall_clock_times->push_back(base::TimeTicks() + media_time); | 261 wall_clock_times->push_back(base::TimeTicks() + media_time); |
| 249 } | 262 } |
| 250 } | 263 } |
| 251 return true; | 264 return true; |
| 252 } | 265 } |
| 253 | 266 |
| 254 return time_source_->GetWallClockTimes(media_timestamps, wall_clock_times); | 267 return time_source_->GetWallClockTimes(media_timestamps, wall_clock_times); |
| 255 } | 268 } |
| 256 | 269 |
| 257 void RendererImpl::SetCdmReadyCallback(const CdmReadyCB& cdm_ready_cb) { | 270 bool RendererImpl::HasEncryptedStream() { |
| 258 // Cancels the previous CDM request. | 271 DemuxerStream* audio_stream = |
| 259 if (cdm_ready_cb.is_null()) { | 272 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO); |
| 260 if (!cdm_ready_cb_.is_null()) { | 273 if (audio_stream && audio_stream->audio_decoder_config().is_encrypted()) |
| 261 base::ResetAndReturn(&cdm_ready_cb_) | 274 return true; |
| 262 .Run(nullptr, base::Bind(IgnoreCdmAttached)); | |
| 263 } | |
| 264 return; | |
| 265 } | |
| 266 | 275 |
| 267 // We initialize audio and video decoders in sequence. | 276 DemuxerStream* video_stream = |
| 268 DCHECK(cdm_ready_cb_.is_null()); | 277 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO); |
| 278 if (video_stream && video_stream->video_decoder_config().is_encrypted()) |
| 279 return true; |
| 269 | 280 |
| 270 if (cdm_context_) { | 281 return false; |
| 271 cdm_ready_cb.Run(cdm_context_, base::Bind(IgnoreCdmAttached)); | 282 } |
| 272 return; | |
| 273 } | |
| 274 | 283 |
| 275 cdm_ready_cb_ = cdm_ready_cb; | 284 void RendererImpl::FinishInitialization(PipelineStatus status) { |
| 285 DCHECK(!init_cb_.is_null()); |
| 286 |
| 287 if (!pending_cdm_attached_cb_.is_null()) |
| 288 base::ResetAndReturn(&pending_cdm_attached_cb_).Run(status == PIPELINE_OK); |
| 289 |
| 290 base::ResetAndReturn(&init_cb_).Run(status); |
| 276 } | 291 } |
| 277 | 292 |
| 278 void RendererImpl::InitializeAudioRenderer() { | 293 void RendererImpl::InitializeAudioRenderer() { |
| 279 DVLOG(1) << __FUNCTION__; | 294 DVLOG(1) << __FUNCTION__; |
| 280 DCHECK(task_runner_->BelongsToCurrentThread()); | 295 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 281 DCHECK_EQ(state_, STATE_INITIALIZING); | 296 DCHECK_EQ(state_, STATE_INITIALIZING); |
| 282 DCHECK(!init_cb_.is_null()); | 297 DCHECK(!init_cb_.is_null()); |
| 283 | 298 |
| 284 PipelineStatusCB done_cb = | 299 PipelineStatusCB done_cb = |
| 285 base::Bind(&RendererImpl::OnAudioRendererInitializeDone, weak_this_); | 300 base::Bind(&RendererImpl::OnAudioRendererInitializeDone, weak_this_); |
| 286 | 301 |
| 287 if (!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO)) { | 302 if (!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO)) { |
| 288 audio_renderer_.reset(); | 303 audio_renderer_.reset(); |
| 289 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); | 304 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); |
| 290 return; | 305 return; |
| 291 } | 306 } |
| 292 | 307 |
| 293 // Note: After the initialization of a renderer, error events from it may | 308 // Note: After the initialization of a renderer, error events from it may |
| 294 // happen at any time and all future calls must guard against STATE_ERROR. | 309 // happen at any time and all future calls must guard against STATE_ERROR. |
| 295 audio_renderer_->Initialize( | 310 audio_renderer_->Initialize( |
| 296 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), done_cb, | 311 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO), done_cb, |
| 297 base::Bind(&RendererImpl::SetCdmReadyCallback, weak_this_), | 312 cdm_context_, base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), |
| 298 base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), | |
| 299 base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, | 313 base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, |
| 300 &audio_buffering_state_), | 314 &audio_buffering_state_), |
| 301 base::Bind(&RendererImpl::OnAudioRendererEnded, weak_this_), | 315 base::Bind(&RendererImpl::OnAudioRendererEnded, weak_this_), |
| 302 base::Bind(&RendererImpl::OnError, weak_this_), | 316 base::Bind(&RendererImpl::OnError, weak_this_), |
| 303 waiting_for_decryption_key_cb_); | 317 waiting_for_decryption_key_cb_); |
| 304 } | 318 } |
| 305 | 319 |
| 306 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { | 320 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { |
| 307 DVLOG(1) << __FUNCTION__ << ": " << status; | 321 DVLOG(1) << __FUNCTION__ << ": " << status; |
| 308 DCHECK(task_runner_->BelongsToCurrentThread()); | 322 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 309 | 323 |
| 310 // OnError() may be fired at any time by the renderers, even if they thought | 324 // OnError() may be fired at any time by the renderers, even if they thought |
| 311 // they initialized successfully (due to delayed output device setup). | 325 // they initialized successfully (due to delayed output device setup). |
| 312 if (state_ != STATE_INITIALIZING) { | 326 if (state_ != STATE_INITIALIZING) { |
| 313 DCHECK(init_cb_.is_null()); | 327 DCHECK(init_cb_.is_null()); |
| 314 audio_renderer_.reset(); | 328 audio_renderer_.reset(); |
| 315 return; | 329 return; |
| 316 } | 330 } |
| 317 | 331 |
| 318 if (status != PIPELINE_OK) { | 332 if (status != PIPELINE_OK) { |
| 319 base::ResetAndReturn(&init_cb_).Run(status); | 333 FinishInitialization(status); |
| 320 return; | 334 return; |
| 321 } | 335 } |
| 322 | 336 |
| 323 DCHECK(!init_cb_.is_null()); | 337 DCHECK(!init_cb_.is_null()); |
| 324 InitializeVideoRenderer(); | 338 InitializeVideoRenderer(); |
| 325 } | 339 } |
| 326 | 340 |
| 327 void RendererImpl::InitializeVideoRenderer() { | 341 void RendererImpl::InitializeVideoRenderer() { |
| 328 DVLOG(1) << __FUNCTION__; | 342 DVLOG(1) << __FUNCTION__; |
| 329 DCHECK(task_runner_->BelongsToCurrentThread()); | 343 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 330 DCHECK_EQ(state_, STATE_INITIALIZING); | 344 DCHECK_EQ(state_, STATE_INITIALIZING); |
| 331 DCHECK(!init_cb_.is_null()); | 345 DCHECK(!init_cb_.is_null()); |
| 332 | 346 |
| 333 PipelineStatusCB done_cb = | 347 PipelineStatusCB done_cb = |
| 334 base::Bind(&RendererImpl::OnVideoRendererInitializeDone, weak_this_); | 348 base::Bind(&RendererImpl::OnVideoRendererInitializeDone, weak_this_); |
| 335 | 349 |
| 336 if (!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO)) { | 350 if (!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO)) { |
| 337 video_renderer_.reset(); | 351 video_renderer_.reset(); |
| 338 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); | 352 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); |
| 339 return; | 353 return; |
| 340 } | 354 } |
| 341 | 355 |
| 342 video_renderer_->Initialize( | 356 video_renderer_->Initialize( |
| 343 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), done_cb, | 357 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO), done_cb, |
| 344 base::Bind(&RendererImpl::SetCdmReadyCallback, weak_this_), | 358 cdm_context_, base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), |
| 345 base::Bind(&RendererImpl::OnUpdateStatistics, weak_this_), | |
| 346 base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, | 359 base::Bind(&RendererImpl::OnBufferingStateChanged, weak_this_, |
| 347 &video_buffering_state_), | 360 &video_buffering_state_), |
| 348 base::Bind(&RendererImpl::OnVideoRendererEnded, weak_this_), | 361 base::Bind(&RendererImpl::OnVideoRendererEnded, weak_this_), |
| 349 base::Bind(&RendererImpl::OnError, weak_this_), | 362 base::Bind(&RendererImpl::OnError, weak_this_), |
| 350 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), | 363 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), |
| 351 waiting_for_decryption_key_cb_); | 364 waiting_for_decryption_key_cb_); |
| 352 } | 365 } |
| 353 | 366 |
| 354 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { | 367 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { |
| 355 DVLOG(1) << __FUNCTION__ << ": " << status; | 368 DVLOG(1) << __FUNCTION__ << ": " << status; |
| 356 DCHECK(task_runner_->BelongsToCurrentThread()); | 369 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 357 | 370 |
| 358 // OnError() may be fired at any time by the renderers, even if they thought | 371 // OnError() may be fired at any time by the renderers, even if they thought |
| 359 // they initialized successfully (due to delayed output device setup). | 372 // they initialized successfully (due to delayed output device setup). |
| 360 if (state_ != STATE_INITIALIZING) { | 373 if (state_ != STATE_INITIALIZING) { |
| 361 DCHECK(init_cb_.is_null()); | 374 DCHECK(init_cb_.is_null()); |
| 362 audio_renderer_.reset(); | 375 audio_renderer_.reset(); |
| 363 video_renderer_.reset(); | 376 video_renderer_.reset(); |
| 364 return; | 377 return; |
| 365 } | 378 } |
| 366 | 379 |
| 367 DCHECK(!init_cb_.is_null()); | 380 DCHECK(!init_cb_.is_null()); |
| 368 | 381 |
| 369 if (status != PIPELINE_OK) { | 382 if (status != PIPELINE_OK) { |
| 370 base::ResetAndReturn(&init_cb_).Run(status); | 383 FinishInitialization(status); |
| 371 return; | 384 return; |
| 372 } | 385 } |
| 373 | 386 |
| 374 if (audio_renderer_) { | 387 if (audio_renderer_) { |
| 375 time_source_ = audio_renderer_->GetTimeSource(); | 388 time_source_ = audio_renderer_->GetTimeSource(); |
| 376 } else if (!time_source_) { | 389 } else if (!time_source_) { |
| 377 wall_clock_time_source_.reset(new WallClockTimeSource()); | 390 wall_clock_time_source_.reset(new WallClockTimeSource()); |
| 378 time_source_ = wall_clock_time_source_.get(); | 391 time_source_ = wall_clock_time_source_.get(); |
| 379 } | 392 } |
| 380 | 393 |
| 381 state_ = STATE_PLAYING; | 394 state_ = STATE_PLAYING; |
| 382 DCHECK(time_source_); | 395 DCHECK(time_source_); |
| 383 DCHECK(audio_renderer_ || video_renderer_); | 396 DCHECK(audio_renderer_ || video_renderer_); |
| 384 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 397 |
| 398 FinishInitialization(PIPELINE_OK); |
| 385 } | 399 } |
| 386 | 400 |
| 387 void RendererImpl::FlushAudioRenderer() { | 401 void RendererImpl::FlushAudioRenderer() { |
| 388 DVLOG(1) << __FUNCTION__; | 402 DVLOG(1) << __FUNCTION__; |
| 389 DCHECK(task_runner_->BelongsToCurrentThread()); | 403 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 390 DCHECK_EQ(state_, STATE_FLUSHING); | 404 DCHECK_EQ(state_, STATE_FLUSHING); |
| 391 DCHECK(!flush_cb_.is_null()); | 405 DCHECK(!flush_cb_.is_null()); |
| 392 | 406 |
| 393 if (!audio_renderer_) { | 407 if (!audio_renderer_) { |
| 394 OnAudioRendererFlushDone(); | 408 OnAudioRendererFlushDone(); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 case STATE_PLAYING: | 552 case STATE_PLAYING: |
| 539 DCHECK(PlaybackHasEnded() || WaitingForEnoughData()) | 553 DCHECK(PlaybackHasEnded() || WaitingForEnoughData()) |
| 540 << "Playback should only pause due to ending or underflowing"; | 554 << "Playback should only pause due to ending or underflowing"; |
| 541 break; | 555 break; |
| 542 | 556 |
| 543 case STATE_FLUSHING: | 557 case STATE_FLUSHING: |
| 544 // It's OK to pause playback when flushing. | 558 // It's OK to pause playback when flushing. |
| 545 break; | 559 break; |
| 546 | 560 |
| 547 case STATE_UNINITIALIZED: | 561 case STATE_UNINITIALIZED: |
| 562 case STATE_INIT_PENDING_CDM: |
| 548 case STATE_INITIALIZING: | 563 case STATE_INITIALIZING: |
| 549 NOTREACHED() << "Invalid state: " << state_; | 564 NOTREACHED() << "Invalid state: " << state_; |
| 550 break; | 565 break; |
| 551 | 566 |
| 552 case STATE_ERROR: | 567 case STATE_ERROR: |
| 553 // An error state may occur at any time. | 568 // An error state may occur at any time. |
| 554 break; | 569 break; |
| 555 } | 570 } |
| 556 | 571 |
| 557 time_ticking_ = false; | 572 time_ticking_ = false; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 DCHECK(task_runner_->BelongsToCurrentThread()); | 645 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 631 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 646 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; |
| 632 | 647 |
| 633 // An error has already been delivered. | 648 // An error has already been delivered. |
| 634 if (state_ == STATE_ERROR) | 649 if (state_ == STATE_ERROR) |
| 635 return; | 650 return; |
| 636 | 651 |
| 637 const State old_state = state_; | 652 const State old_state = state_; |
| 638 state_ = STATE_ERROR; | 653 state_ = STATE_ERROR; |
| 639 | 654 |
| 640 if (old_state == STATE_INITIALIZING) { | 655 if (!init_cb_.is_null()) { |
| 641 base::ResetAndReturn(&init_cb_).Run(error); | 656 DCHECK(old_state == STATE_INITIALIZING || |
| 657 old_state == STATE_INIT_PENDING_CDM); |
| 658 FinishInitialization(error); |
| 642 return; | 659 return; |
| 643 } | 660 } |
| 644 | 661 |
| 645 // After OnError() returns, the pipeline may destroy |this|. | 662 // After OnError() returns, the pipeline may destroy |this|. |
| 646 base::ResetAndReturn(&error_cb_).Run(error); | 663 base::ResetAndReturn(&error_cb_).Run(error); |
| 647 | 664 |
| 648 if (!flush_cb_.is_null()) | 665 if (!flush_cb_.is_null()) |
| 649 base::ResetAndReturn(&flush_cb_).Run(); | 666 base::ResetAndReturn(&flush_cb_).Run(); |
| 650 } | 667 } |
| 651 | 668 |
| 652 } // namespace media | 669 } // namespace media |
| OLD | NEW |