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

Side by Side Diff: media/renderers/renderer_impl.cc

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

Powered by Google App Engine
This is Rietveld 408576698