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

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

Issue 1935873002: Implement disabling and enabling media tracks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@track-control2
Patch Set: Check track ids via track_id_to_demux_stream_map_ Created 4 years, 5 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"
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 DCHECK_EQ(state_, STATE_UNINITIALIZED); 122 DCHECK_EQ(state_, STATE_UNINITIALIZED);
123 DCHECK(!init_cb.is_null()); 123 DCHECK(!init_cb.is_null());
124 DCHECK(client); 124 DCHECK(client);
125 DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) || 125 DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) ||
126 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO)); 126 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO));
127 127
128 client_ = client; 128 client_ = client;
129 demuxer_stream_provider_ = demuxer_stream_provider; 129 demuxer_stream_provider_ = demuxer_stream_provider;
130 init_cb_ = init_cb; 130 init_cb_ = init_cb;
131 131
132 DemuxerStream* audio_stream =
133 demuxer_stream_provider->GetStream(DemuxerStream::AUDIO);
134 if (audio_stream)
135 audio_stream->SetStreamRestartedCB(
136 base::Bind(&RendererImpl::RestartStreamPlayback, weak_this_));
137 DemuxerStream* video_stream =
138 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO);
139 if (video_stream)
140 video_stream->SetStreamRestartedCB(
141 base::Bind(&RendererImpl::RestartStreamPlayback, weak_this_));
142
132 if (HasEncryptedStream() && !cdm_context_) { 143 if (HasEncryptedStream() && !cdm_context_) {
133 state_ = STATE_INIT_PENDING_CDM; 144 state_ = STATE_INIT_PENDING_CDM;
134 return; 145 return;
135 } 146 }
136 147
137 state_ = STATE_INITIALIZING; 148 state_ = STATE_INITIALIZING;
138 InitializeAudioRenderer(); 149 InitializeAudioRenderer();
139 } 150 }
140 151
141 void RendererImpl::SetCdm(CdmContext* cdm_context, 152 void RendererImpl::SetCdm(CdmContext* cdm_context,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 205 }
195 206
196 time_source_->SetMediaTime(time); 207 time_source_->SetMediaTime(time);
197 208
198 if (audio_renderer_) 209 if (audio_renderer_)
199 audio_renderer_->StartPlaying(); 210 audio_renderer_->StartPlaying();
200 if (video_renderer_) 211 if (video_renderer_)
201 video_renderer_->StartPlayingFrom(time); 212 video_renderer_->StartPlayingFrom(time);
202 } 213 }
203 214
215 void RendererImpl::RestartStreamPlayback(DemuxerStream* stream,
216 base::TimeDelta time) {
217 DVLOG(1) << __FUNCTION__ << " stream=" << stream
218 << " time=" << time.InSecondsF();
219 DCHECK(task_runner_->BelongsToCurrentThread());
220 if (stream->type() == DemuxerStream::VIDEO) {
221 DCHECK(video_renderer_);
222 DCHECK(video_ended_);
223 video_ended_ = false;
224 restarting_video_ = true;
225 video_renderer_->Flush(
226 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time));
227 } else if (stream->type() == DemuxerStream::AUDIO) {
228 DCHECK(audio_renderer_);
229 DCHECK(time_source_);
230 DCHECK(audio_ended_);
231 audio_ended_ = false;
232 restarting_audio_ = true;
233 // Stop ticking (transition into paused state) in audio renderer before
234 // calling Flush, since after Flush we are going to restart playback by
235 // calling audio renderer StartPlaying which would fail in playing state.
236 time_ticking_ = false;
237 time_source_->StopTicking();
238 audio_renderer_->Flush(
239 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time));
240 }
241 }
242
243 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) {
244 DCHECK(task_runner_->BelongsToCurrentThread());
245 if (state_ == STATE_PLAYING) {
246 DCHECK(video_renderer_);
247 video_renderer_->StartPlayingFrom(time);
248 }
249 }
250
251 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) {
252 DCHECK(task_runner_->BelongsToCurrentThread());
253 if (state_ == STATE_PLAYING) {
254 DCHECK(time_source_);
255 DCHECK(audio_renderer_);
256 audio_renderer_->StartPlaying();
257 }
258 }
259
204 void RendererImpl::SetPlaybackRate(double playback_rate) { 260 void RendererImpl::SetPlaybackRate(double playback_rate) {
205 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; 261 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
206 DCHECK(task_runner_->BelongsToCurrentThread()); 262 DCHECK(task_runner_->BelongsToCurrentThread());
207 263
208 // Playback rate changes are only carried out while playing. 264 // Playback rate changes are only carried out while playing.
209 if (state_ != STATE_PLAYING) 265 if (state_ != STATE_PLAYING)
210 return; 266 return;
211 267
212 time_source_->SetPlaybackRate(playback_rate); 268 time_source_->SetPlaybackRate(playback_rate);
213 269
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 ? &audio_buffering_state_ 551 ? &audio_buffering_state_
496 : &video_buffering_state_; 552 : &video_buffering_state_;
497 553
498 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " 554 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", "
499 << new_buffering_state << ") " 555 << new_buffering_state << ") "
500 << (type == DemuxerStream::AUDIO ? "audio" : "video"); 556 << (type == DemuxerStream::AUDIO ? "audio" : "video");
501 DCHECK(task_runner_->BelongsToCurrentThread()); 557 DCHECK(task_runner_->BelongsToCurrentThread());
502 558
503 bool was_waiting_for_enough_data = WaitingForEnoughData(); 559 bool was_waiting_for_enough_data = WaitingForEnoughData();
504 560
561 // When restarting playback we want to ignore the BUFFERING_HAVE_NOTHING for
562 // the stream being restarted, to allow continuing uninterrupted playback on
563 // the other stream.
564 if (type == DemuxerStream::VIDEO && restarting_video_) {
chcunningham 2016/06/24 23:32:55 For both audio and video, my previous comments sti
servolk 2016/06/25 00:36:33 Well, I have looked into this some more after your
chcunningham 2016/06/27 20:31:52 This is true, but its also a bug that I'm soon fix
servolk 2016/06/28 00:15:58 Ok, sure, if you are fixing the delivery of HAVE_N
565 if (new_buffering_state == BUFFERING_HAVE_NOTHING) {
566 DVLOG(1) << __FUNCTION__ << " Ignoring BUFFERING_HAVE_NOTHING for video "
567 "stream which is being restarted.";
568 } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) {
569 DVLOG(1) << __FUNCTION__ << " Got BUFFERING_HAVE_ENOUGH for video stream,"
570 " resuming playback.";
571 restarting_video_ = false;
572 if (playback_rate_ > 0)
573 video_renderer_->OnTimeStateChanged(true);
chcunningham 2016/06/24 23:32:55 Re-posting discussion from earlier - ping xhwang o
servolk 2016/06/25 00:36:33 Acknowledged. Should we open a separate bug for th
chcunningham 2016/06/27 20:31:52 Since xhwang is AFK and wolenetz is just CC, I rea
servolk 2016/06/28 00:15:58 Done.
574 }
575 return;
576 }
577
578 if (type == DemuxerStream::AUDIO && restarting_audio_) {
579 if (new_buffering_state == BUFFERING_HAVE_NOTHING) {
580 DVLOG(1) << __FUNCTION__ << " Ignoring BUFFERING_HAVE_NOTHING for audio "
581 "stream which is being restarted.";
582 } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) {
583 DVLOG(1) << __FUNCTION__ << " Got BUFFERING_HAVE_ENOUGH for audio stream,"
584 " resuming playback.";
585
586 restarting_audio_ = false;
587
588 // Now that we have decoded enough audio, pause and unpause playback
589 // momentarily to ensure video renderer is synchronised with audio.
590 double curr_playback_rate = playback_rate_;
591 SetPlaybackRate(0);
chcunningham 2016/06/24 23:32:55 My previous comment is not addressed. Reposting W
servolk 2016/06/25 00:36:33 Prior to this point only the audio renderer is pau
chcunningham 2016/06/27 20:31:52 Can you instead try to audio_renderer_->SetMediaTi
servolk 2016/06/28 00:15:58 We need to be very careful here. audio_renderer_->
servolk 2016/06/28 02:05:43 Btw, just FYI: When I tried to set audio_renderer_
servolk 2016/06/28 18:51:44 I think we can make this better by allowing PauseP
servolk 2016/06/28 23:03:40 Ok, and patchset #48 implements deferred reporting
592 SetPlaybackRate(curr_playback_rate);
593
594 time_ticking_ = true;
595 time_source_->StartTicking();
596 }
597 return;
598 }
599
505 // When audio is present and has enough data, defer video underflow callbacks 600 // When audio is present and has enough data, defer video underflow callbacks
506 // for some time to avoid unnecessary glitches in audio; see 601 // for some time to avoid unnecessary glitches in audio; see
507 // http://crbug.com/144683#c53. 602 // http://crbug.com/144683#c53.
508 if (audio_renderer_ && type == DemuxerStream::VIDEO && 603 if (audio_renderer_ && type == DemuxerStream::VIDEO &&
509 state_ == STATE_PLAYING) { 604 state_ == STATE_PLAYING) {
510 if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH && 605 if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH &&
511 audio_buffering_state_ == BUFFERING_HAVE_ENOUGH && 606 audio_buffering_state_ == BUFFERING_HAVE_ENOUGH &&
512 new_buffering_state == BUFFERING_HAVE_NOTHING && 607 new_buffering_state == BUFFERING_HAVE_NOTHING &&
513 deferred_underflow_cb_.IsCancelled()) { 608 deferred_underflow_cb_.IsCancelled()) {
514 deferred_underflow_cb_.Reset( 609 deferred_underflow_cb_.Reset(
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 DCHECK(!time_ticking_); 700 DCHECK(!time_ticking_);
606 DCHECK(!WaitingForEnoughData()); 701 DCHECK(!WaitingForEnoughData());
607 702
608 time_ticking_ = true; 703 time_ticking_ = true;
609 time_source_->StartTicking(); 704 time_source_->StartTicking();
610 if (playback_rate_ > 0 && video_renderer_) 705 if (playback_rate_ > 0 && video_renderer_)
611 video_renderer_->OnTimeStateChanged(true); 706 video_renderer_->OnTimeStateChanged(true);
612 } 707 }
613 708
614 void RendererImpl::OnRendererEnded(DemuxerStream::Type type) { 709 void RendererImpl::OnRendererEnded(DemuxerStream::Type type) {
615 DVLOG(1) << __FUNCTION__; 710 DVLOG(1) << __FUNCTION__
711 << (type == DemuxerStream::AUDIO ? " audio" : " video");
616 DCHECK(task_runner_->BelongsToCurrentThread()); 712 DCHECK(task_runner_->BelongsToCurrentThread());
617 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); 713 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
618 714
619 if (state_ != STATE_PLAYING) 715 if (state_ != STATE_PLAYING)
620 return; 716 return;
621 717
622 if (type == DemuxerStream::AUDIO) { 718 if (type == DemuxerStream::AUDIO) {
623 DCHECK(!audio_ended_); 719 DCHECK(!audio_ended_);
624 audio_ended_ = true; 720 audio_ended_ = true;
625 } else { 721 } else {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 DCHECK(task_runner_->BelongsToCurrentThread()); 787 DCHECK(task_runner_->BelongsToCurrentThread());
692 client_->OnVideoNaturalSizeChange(size); 788 client_->OnVideoNaturalSizeChange(size);
693 } 789 }
694 790
695 void RendererImpl::OnVideoOpacityChange(bool opaque) { 791 void RendererImpl::OnVideoOpacityChange(bool opaque) {
696 DCHECK(task_runner_->BelongsToCurrentThread()); 792 DCHECK(task_runner_->BelongsToCurrentThread());
697 client_->OnVideoOpacityChange(opaque); 793 client_->OnVideoOpacityChange(opaque);
698 } 794 }
699 795
700 } // namespace media 796 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698