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" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 }; | 73 }; |
74 | 74 |
75 RendererImpl::RendererImpl( | 75 RendererImpl::RendererImpl( |
76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
77 std::unique_ptr<AudioRenderer> audio_renderer, | 77 std::unique_ptr<AudioRenderer> audio_renderer, |
78 std::unique_ptr<VideoRenderer> video_renderer) | 78 std::unique_ptr<VideoRenderer> video_renderer) |
79 : state_(STATE_UNINITIALIZED), | 79 : state_(STATE_UNINITIALIZED), |
80 task_runner_(task_runner), | 80 task_runner_(task_runner), |
81 audio_renderer_(std::move(audio_renderer)), | 81 audio_renderer_(std::move(audio_renderer)), |
82 video_renderer_(std::move(video_renderer)), | 82 video_renderer_(std::move(video_renderer)), |
| 83 current_audio_stream_(nullptr), |
| 84 current_video_stream_(nullptr), |
83 time_source_(NULL), | 85 time_source_(NULL), |
84 time_ticking_(false), | 86 time_ticking_(false), |
85 playback_rate_(0.0), | 87 playback_rate_(0.0), |
86 audio_buffering_state_(BUFFERING_HAVE_NOTHING), | 88 audio_buffering_state_(BUFFERING_HAVE_NOTHING), |
87 video_buffering_state_(BUFFERING_HAVE_NOTHING), | 89 video_buffering_state_(BUFFERING_HAVE_NOTHING), |
88 audio_ended_(false), | 90 audio_ended_(false), |
89 video_ended_(false), | 91 video_ended_(false), |
90 cdm_context_(nullptr), | 92 cdm_context_(nullptr), |
91 underflow_disabled_for_testing_(false), | 93 underflow_disabled_for_testing_(false), |
92 clockless_video_playback_enabled_for_testing_(false), | 94 clockless_video_playback_enabled_for_testing_(false), |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 } | 192 } |
191 | 193 |
192 if (state_ != STATE_PLAYING) { | 194 if (state_ != STATE_PLAYING) { |
193 DCHECK_EQ(state_, STATE_ERROR); | 195 DCHECK_EQ(state_, STATE_ERROR); |
194 return; | 196 return; |
195 } | 197 } |
196 | 198 |
197 flush_cb_ = flush_cb; | 199 flush_cb_ = flush_cb; |
198 state_ = STATE_FLUSHING; | 200 state_ = STATE_FLUSHING; |
199 | 201 |
200 if (time_ticking_) | 202 // If we are currently handling a media stream status change, then postpone |
201 PausePlayback(); | 203 // Flush until after that's done (because stream status changes also flush |
| 204 // audio_renderer_/video_renderer_ and they need to be restarted before they |
| 205 // can be flushed again). OnStreamRestartCompleted will resume Flush |
| 206 // processing after audio/video restart has completed and there are no other |
| 207 // pending stream status changes. |
| 208 if (restarting_audio_ || restarting_video_) { |
| 209 pending_actions_.push_back( |
| 210 base::Bind(&RendererImpl::FlushInternal, weak_this_)); |
| 211 return; |
| 212 } |
202 | 213 |
203 FlushAudioRenderer(); | 214 FlushInternal(); |
204 } | 215 } |
205 | 216 |
206 void RendererImpl::StartPlayingFrom(base::TimeDelta time) { | 217 void RendererImpl::StartPlayingFrom(base::TimeDelta time) { |
207 DVLOG(1) << __func__; | 218 DVLOG(1) << __func__; |
208 DCHECK(task_runner_->BelongsToCurrentThread()); | 219 DCHECK(task_runner_->BelongsToCurrentThread()); |
209 | 220 |
210 if (state_ != STATE_FLUSHED) { | 221 if (state_ != STATE_FLUSHED) { |
211 DCHECK_EQ(state_, STATE_ERROR); | 222 DCHECK_EQ(state_, STATE_ERROR); |
212 return; | 223 return; |
213 } | 224 } |
214 | 225 |
215 time_source_->SetMediaTime(time); | 226 time_source_->SetMediaTime(time); |
216 | 227 |
217 state_ = STATE_PLAYING; | 228 state_ = STATE_PLAYING; |
218 if (audio_renderer_) | 229 if (audio_renderer_) |
219 audio_renderer_->StartPlaying(); | 230 audio_renderer_->StartPlaying(); |
220 if (video_renderer_) | 231 if (video_renderer_) |
221 video_renderer_->StartPlayingFrom(time); | 232 video_renderer_->StartPlayingFrom(time); |
222 } | 233 } |
223 | 234 |
224 void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, | |
225 bool enabled, | |
226 base::TimeDelta time) { | |
227 DCHECK(task_runner_->BelongsToCurrentThread()); | |
228 DCHECK(stream); | |
229 bool video = (stream->type() == DemuxerStream::VIDEO); | |
230 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream | |
231 << " enabled=" << enabled << " time=" << time.InSecondsF(); | |
232 if ((state_ != STATE_PLAYING) || (audio_ended_ && video_ended_)) | |
233 return; | |
234 if (restarting_audio_ || restarting_video_) { | |
235 DVLOG(3) << __func__ << ": postponed stream " << stream | |
236 << " status change handling."; | |
237 pending_stream_status_notifications_.push_back( | |
238 base::Bind(&RendererImpl::OnStreamStatusChanged, weak_this_, stream, | |
239 enabled, time)); | |
240 return; | |
241 } | |
242 if (stream->type() == DemuxerStream::VIDEO) { | |
243 DCHECK(video_renderer_); | |
244 restarting_video_ = true; | |
245 video_renderer_->Flush( | |
246 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time)); | |
247 } else if (stream->type() == DemuxerStream::AUDIO) { | |
248 DCHECK(audio_renderer_); | |
249 DCHECK(time_source_); | |
250 restarting_audio_ = true; | |
251 // Stop ticking (transition into paused state) in audio renderer before | |
252 // calling Flush, since after Flush we are going to restart playback by | |
253 // calling audio renderer StartPlaying which would fail in playing state. | |
254 if (time_ticking_) { | |
255 time_ticking_ = false; | |
256 time_source_->StopTicking(); | |
257 } | |
258 audio_renderer_->Flush( | |
259 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); | |
260 } | |
261 } | |
262 | |
263 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) { | |
264 DVLOG(3) << __func__; | |
265 DCHECK(task_runner_->BelongsToCurrentThread()); | |
266 DCHECK(video_renderer_); | |
267 DCHECK_EQ(state_, STATE_PLAYING); | |
268 video_ended_ = false; | |
269 video_renderer_->StartPlayingFrom(time); | |
270 } | |
271 | |
272 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) { | |
273 DVLOG(3) << __func__; | |
274 DCHECK(task_runner_->BelongsToCurrentThread()); | |
275 DCHECK_EQ(state_, STATE_PLAYING); | |
276 DCHECK(time_source_); | |
277 DCHECK(audio_renderer_); | |
278 audio_ended_ = false; | |
279 audio_renderer_->StartPlaying(); | |
280 } | |
281 | |
282 void RendererImpl::SetPlaybackRate(double playback_rate) { | 235 void RendererImpl::SetPlaybackRate(double playback_rate) { |
283 DVLOG(1) << __func__ << "(" << playback_rate << ")"; | 236 DVLOG(1) << __func__ << "(" << playback_rate << ")"; |
284 DCHECK(task_runner_->BelongsToCurrentThread()); | 237 DCHECK(task_runner_->BelongsToCurrentThread()); |
285 | 238 |
286 // Playback rate changes are only carried out while playing. | 239 // Playback rate changes are only carried out while playing. |
287 if (state_ != STATE_PLAYING && state_ != STATE_FLUSHED) | 240 if (state_ != STATE_PLAYING && state_ != STATE_FLUSHED) |
288 return; | 241 return; |
289 | 242 |
290 time_source_->SetPlaybackRate(playback_rate); | 243 time_source_->SetPlaybackRate(playback_rate); |
291 | 244 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 // TODO(servolk): Implement proper support for multiple streams. But for now | 346 // TODO(servolk): Implement proper support for multiple streams. But for now |
394 // pick the first enabled stream to preserve the existing behavior. | 347 // pick the first enabled stream to preserve the existing behavior. |
395 DemuxerStream* audio_stream = | 348 DemuxerStream* audio_stream = |
396 media_resource_->GetFirstStream(DemuxerStream::AUDIO); | 349 media_resource_->GetFirstStream(DemuxerStream::AUDIO); |
397 if (!audio_stream) { | 350 if (!audio_stream) { |
398 audio_renderer_.reset(); | 351 audio_renderer_.reset(); |
399 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); | 352 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); |
400 return; | 353 return; |
401 } | 354 } |
402 | 355 |
| 356 current_audio_stream_ = audio_stream; |
| 357 |
403 audio_renderer_client_.reset( | 358 audio_renderer_client_.reset( |
404 new RendererClientInternal(DemuxerStream::AUDIO, this)); | 359 new RendererClientInternal(DemuxerStream::AUDIO, this)); |
405 // Note: After the initialization of a renderer, error events from it may | 360 // Note: After the initialization of a renderer, error events from it may |
406 // happen at any time and all future calls must guard against STATE_ERROR. | 361 // happen at any time and all future calls must guard against STATE_ERROR. |
407 audio_renderer_->Initialize(audio_stream, cdm_context_, | 362 audio_renderer_->Initialize(audio_stream, cdm_context_, |
408 audio_renderer_client_.get(), done_cb); | 363 audio_renderer_client_.get(), done_cb); |
409 } | 364 } |
410 | 365 |
411 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { | 366 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { |
412 DVLOG(1) << __func__ << ": " << status; | 367 DVLOG(1) << __func__ << ": " << status; |
(...skipping 28 matching lines...) Expand all Loading... |
441 // TODO(servolk): Implement proper support for multiple streams. But for now | 396 // TODO(servolk): Implement proper support for multiple streams. But for now |
442 // pick the first enabled stream to preserve the existing behavior. | 397 // pick the first enabled stream to preserve the existing behavior. |
443 DemuxerStream* video_stream = | 398 DemuxerStream* video_stream = |
444 media_resource_->GetFirstStream(DemuxerStream::VIDEO); | 399 media_resource_->GetFirstStream(DemuxerStream::VIDEO); |
445 if (!video_stream) { | 400 if (!video_stream) { |
446 video_renderer_.reset(); | 401 video_renderer_.reset(); |
447 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); | 402 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); |
448 return; | 403 return; |
449 } | 404 } |
450 | 405 |
| 406 current_video_stream_ = video_stream; |
| 407 |
451 video_renderer_client_.reset( | 408 video_renderer_client_.reset( |
452 new RendererClientInternal(DemuxerStream::VIDEO, this)); | 409 new RendererClientInternal(DemuxerStream::VIDEO, this)); |
453 video_renderer_->Initialize( | 410 video_renderer_->Initialize( |
454 video_stream, cdm_context_, video_renderer_client_.get(), | 411 video_stream, cdm_context_, video_renderer_client_.get(), |
455 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), | 412 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), |
456 done_cb); | 413 done_cb); |
457 } | 414 } |
458 | 415 |
459 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { | 416 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { |
460 DVLOG(1) << __func__ << ": " << status; | 417 DVLOG(1) << __func__ << ": " << status; |
(...skipping 25 matching lines...) Expand all Loading... |
486 time_source_ = wall_clock_time_source_.get(); | 443 time_source_ = wall_clock_time_source_.get(); |
487 } | 444 } |
488 | 445 |
489 state_ = STATE_FLUSHED; | 446 state_ = STATE_FLUSHED; |
490 DCHECK(time_source_); | 447 DCHECK(time_source_); |
491 DCHECK(audio_renderer_ || video_renderer_); | 448 DCHECK(audio_renderer_ || video_renderer_); |
492 | 449 |
493 FinishInitialization(PIPELINE_OK); | 450 FinishInitialization(PIPELINE_OK); |
494 } | 451 } |
495 | 452 |
| 453 void RendererImpl::FlushInternal() { |
| 454 DVLOG(1) << __func__; |
| 455 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 456 DCHECK_EQ(state_, STATE_FLUSHING); |
| 457 DCHECK(!flush_cb_.is_null()); |
| 458 |
| 459 if (time_ticking_) |
| 460 PausePlayback(); |
| 461 |
| 462 FlushAudioRenderer(); |
| 463 } |
| 464 |
496 void RendererImpl::FlushAudioRenderer() { | 465 void RendererImpl::FlushAudioRenderer() { |
497 DVLOG(1) << __func__; | 466 DVLOG(1) << __func__; |
498 DCHECK(task_runner_->BelongsToCurrentThread()); | 467 DCHECK(task_runner_->BelongsToCurrentThread()); |
499 DCHECK_EQ(state_, STATE_FLUSHING); | 468 DCHECK_EQ(state_, STATE_FLUSHING); |
500 DCHECK(!flush_cb_.is_null()); | 469 DCHECK(!flush_cb_.is_null()); |
501 | 470 |
502 if (!audio_renderer_) { | 471 if (!audio_renderer_) { |
503 OnAudioRendererFlushDone(); | 472 OnAudioRendererFlushDone(); |
504 return; | 473 return; |
505 } | 474 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 return; | 522 return; |
554 } | 523 } |
555 | 524 |
556 DCHECK_EQ(state_, STATE_FLUSHING); | 525 DCHECK_EQ(state_, STATE_FLUSHING); |
557 DCHECK(!flush_cb_.is_null()); | 526 DCHECK(!flush_cb_.is_null()); |
558 | 527 |
559 DCHECK_EQ(video_buffering_state_, BUFFERING_HAVE_NOTHING); | 528 DCHECK_EQ(video_buffering_state_, BUFFERING_HAVE_NOTHING); |
560 video_ended_ = false; | 529 video_ended_ = false; |
561 state_ = STATE_FLUSHED; | 530 state_ = STATE_FLUSHED; |
562 base::ResetAndReturn(&flush_cb_).Run(); | 531 base::ResetAndReturn(&flush_cb_).Run(); |
| 532 |
| 533 if (!pending_actions_.empty()) { |
| 534 base::Closure closure = pending_actions_.front(); |
| 535 pending_actions_.pop_front(); |
| 536 closure.Run(); |
| 537 } |
| 538 } |
| 539 |
| 540 void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, |
| 541 bool enabled, |
| 542 base::TimeDelta time) { |
| 543 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 544 DCHECK(stream); |
| 545 bool video = (stream->type() == DemuxerStream::VIDEO); |
| 546 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream |
| 547 << " enabled=" << enabled << " time=" << time.InSecondsF(); |
| 548 |
| 549 if ((state_ != STATE_PLAYING && state_ != STATE_FLUSHING && |
| 550 state_ != STATE_FLUSHED) || |
| 551 (audio_ended_ && video_ended_)) |
| 552 return; |
| 553 |
| 554 if (restarting_audio_ || restarting_video_ || state_ == STATE_FLUSHING) { |
| 555 DVLOG(3) << __func__ << ": postponed stream " << stream |
| 556 << " status change handling."; |
| 557 pending_actions_.push_back(base::Bind(&RendererImpl::OnStreamStatusChanged, |
| 558 weak_this_, stream, enabled, time)); |
| 559 return; |
| 560 } |
| 561 |
| 562 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED); |
| 563 if (stream->type() == DemuxerStream::VIDEO) { |
| 564 DCHECK(video_renderer_); |
| 565 restarting_video_ = true; |
| 566 base::Closure handle_track_status_cb = |
| 567 base::Bind(stream == current_video_stream_ |
| 568 ? &RendererImpl::RestartVideoRenderer |
| 569 : &RendererImpl::ReinitializeVideoRenderer, |
| 570 weak_this_, stream, time); |
| 571 if (state_ == STATE_FLUSHED) |
| 572 handle_track_status_cb.Run(); |
| 573 else |
| 574 video_renderer_->Flush(handle_track_status_cb); |
| 575 } else if (stream->type() == DemuxerStream::AUDIO) { |
| 576 DCHECK(audio_renderer_); |
| 577 DCHECK(time_source_); |
| 578 restarting_audio_ = true; |
| 579 base::Closure handle_track_status_cb = |
| 580 base::Bind(stream == current_audio_stream_ |
| 581 ? &RendererImpl::RestartAudioRenderer |
| 582 : &RendererImpl::ReinitializeAudioRenderer, |
| 583 weak_this_, stream, time); |
| 584 if (state_ == STATE_FLUSHED) { |
| 585 handle_track_status_cb.Run(); |
| 586 return; |
| 587 } |
| 588 // Stop ticking (transition into paused state) in audio renderer before |
| 589 // calling Flush, since after Flush we are going to restart playback by |
| 590 // calling audio renderer StartPlaying which would fail in playing state. |
| 591 if (time_ticking_) { |
| 592 time_ticking_ = false; |
| 593 time_source_->StopTicking(); |
| 594 } |
| 595 audio_renderer_->Flush(handle_track_status_cb); |
| 596 } |
| 597 } |
| 598 |
| 599 void RendererImpl::ReinitializeAudioRenderer(DemuxerStream* stream, |
| 600 base::TimeDelta time) { |
| 601 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
| 602 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 603 DCHECK_NE(stream, current_audio_stream_); |
| 604 |
| 605 current_audio_stream_ = stream; |
| 606 audio_renderer_->Initialize( |
| 607 stream, cdm_context_, audio_renderer_client_.get(), |
| 608 base::Bind(&RendererImpl::OnAudioRendererReinitialized, weak_this_, |
| 609 stream, time)); |
| 610 } |
| 611 |
| 612 void RendererImpl::OnAudioRendererReinitialized(DemuxerStream* stream, |
| 613 base::TimeDelta time, |
| 614 PipelineStatus status) { |
| 615 DVLOG(2) << __func__ << ": status=" << status; |
| 616 DCHECK_EQ(stream, current_audio_stream_); |
| 617 |
| 618 if (status != PIPELINE_OK) { |
| 619 OnError(status); |
| 620 return; |
| 621 } |
| 622 RestartAudioRenderer(stream, time); |
| 623 } |
| 624 |
| 625 void RendererImpl::ReinitializeVideoRenderer(DemuxerStream* stream, |
| 626 base::TimeDelta time) { |
| 627 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
| 628 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 629 DCHECK_NE(stream, current_video_stream_); |
| 630 |
| 631 current_video_stream_ = stream; |
| 632 video_renderer_->OnTimeStopped(); |
| 633 video_renderer_->Initialize( |
| 634 stream, cdm_context_, video_renderer_client_.get(), |
| 635 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), |
| 636 base::Bind(&RendererImpl::OnVideoRendererReinitialized, weak_this_, |
| 637 stream, time)); |
| 638 } |
| 639 |
| 640 void RendererImpl::OnVideoRendererReinitialized(DemuxerStream* stream, |
| 641 base::TimeDelta time, |
| 642 PipelineStatus status) { |
| 643 DVLOG(2) << __func__ << ": status=" << status; |
| 644 DCHECK_EQ(stream, current_video_stream_); |
| 645 |
| 646 if (status != PIPELINE_OK) { |
| 647 OnError(status); |
| 648 return; |
| 649 } |
| 650 RestartVideoRenderer(stream, time); |
| 651 } |
| 652 |
| 653 void RendererImpl::RestartAudioRenderer(DemuxerStream* stream, |
| 654 base::TimeDelta time) { |
| 655 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
| 656 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 657 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED || |
| 658 state_ == STATE_FLUSHING); |
| 659 DCHECK(time_source_); |
| 660 DCHECK(audio_renderer_); |
| 661 DCHECK_EQ(stream, current_audio_stream_); |
| 662 |
| 663 audio_ended_ = false; |
| 664 if (state_ == STATE_FLUSHED) { |
| 665 // If we are in the FLUSHED state, then we are done. The audio renderer will |
| 666 // be restarted by a subsequent RendererImpl::StartPlayingFrom call. |
| 667 OnStreamRestartCompleted(); |
| 668 } else { |
| 669 // Stream restart will be completed when the audio renderer decodes enough |
| 670 // data and reports HAVE_ENOUGH to HandleRestartedStreamBufferingChanges. |
| 671 audio_renderer_->StartPlaying(); |
| 672 } |
| 673 } |
| 674 |
| 675 void RendererImpl::RestartVideoRenderer(DemuxerStream* stream, |
| 676 base::TimeDelta time) { |
| 677 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
| 678 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 679 DCHECK(video_renderer_); |
| 680 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED || |
| 681 state_ == STATE_FLUSHING); |
| 682 DCHECK_EQ(stream, current_video_stream_); |
| 683 |
| 684 video_ended_ = false; |
| 685 if (state_ == STATE_FLUSHED) { |
| 686 // If we are in the FLUSHED state, then we are done. The video renderer will |
| 687 // be restarted by a subsequent RendererImpl::StartPlayingFrom call. |
| 688 OnStreamRestartCompleted(); |
| 689 } else { |
| 690 // Stream restart will be completed when the video renderer decodes enough |
| 691 // data and reports HAVE_ENOUGH to HandleRestartedStreamBufferingChanges. |
| 692 video_renderer_->StartPlayingFrom(time); |
| 693 } |
563 } | 694 } |
564 | 695 |
565 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { | 696 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { |
566 DCHECK(task_runner_->BelongsToCurrentThread()); | 697 DCHECK(task_runner_->BelongsToCurrentThread()); |
567 client_->OnStatisticsUpdate(stats); | 698 client_->OnStatisticsUpdate(stats); |
568 } | 699 } |
569 | 700 |
570 bool RendererImpl::HandleRestartedStreamBufferingChanges( | 701 bool RendererImpl::HandleRestartedStreamBufferingChanges( |
571 DemuxerStream::Type type, | 702 DemuxerStream::Type type, |
572 BufferingState new_buffering_state) { | 703 BufferingState new_buffering_state) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 PausePlayback(); | 758 PausePlayback(); |
628 task_runner_->PostTask( | 759 task_runner_->PostTask( |
629 FROM_HERE, | 760 FROM_HERE, |
630 base::Bind(&RendererImpl::OnStreamRestartCompleted, weak_this_)); | 761 base::Bind(&RendererImpl::OnStreamRestartCompleted, weak_this_)); |
631 } | 762 } |
632 } | 763 } |
633 return false; | 764 return false; |
634 } | 765 } |
635 | 766 |
636 void RendererImpl::OnStreamRestartCompleted() { | 767 void RendererImpl::OnStreamRestartCompleted() { |
| 768 DVLOG(3) << __func__ << " restarting_audio_=" << restarting_audio_ |
| 769 << " restarting_video_=" << restarting_video_; |
| 770 DCHECK(task_runner_->BelongsToCurrentThread()); |
637 DCHECK(restarting_audio_ || restarting_video_); | 771 DCHECK(restarting_audio_ || restarting_video_); |
638 restarting_audio_ = false; | 772 restarting_audio_ = false; |
639 restarting_video_ = false; | 773 restarting_video_ = false; |
640 if (!pending_stream_status_notifications_.empty()) { | 774 if (!pending_actions_.empty()) { |
641 pending_stream_status_notifications_.front().Run(); | 775 base::Closure closure = pending_actions_.front(); |
642 pending_stream_status_notifications_.pop_front(); | 776 pending_actions_.pop_front(); |
| 777 closure.Run(); |
643 } | 778 } |
644 } | 779 } |
645 | 780 |
646 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type, | 781 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type, |
647 BufferingState new_buffering_state) { | 782 BufferingState new_buffering_state) { |
648 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); | 783 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); |
649 BufferingState* buffering_state = type == DemuxerStream::AUDIO | 784 BufferingState* buffering_state = type == DemuxerStream::AUDIO |
650 ? &audio_buffering_state_ | 785 ? &audio_buffering_state_ |
651 : &video_buffering_state_; | 786 : &video_buffering_state_; |
652 | 787 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 DCHECK(task_runner_->BelongsToCurrentThread()); | 991 DCHECK(task_runner_->BelongsToCurrentThread()); |
857 client_->OnVideoNaturalSizeChange(size); | 992 client_->OnVideoNaturalSizeChange(size); |
858 } | 993 } |
859 | 994 |
860 void RendererImpl::OnVideoOpacityChange(bool opaque) { | 995 void RendererImpl::OnVideoOpacityChange(bool opaque) { |
861 DCHECK(task_runner_->BelongsToCurrentThread()); | 996 DCHECK(task_runner_->BelongsToCurrentThread()); |
862 client_->OnVideoOpacityChange(opaque); | 997 client_->OnVideoOpacityChange(opaque); |
863 } | 998 } |
864 | 999 |
865 } // namespace media | 1000 } // namespace media |
OLD | NEW |