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

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

Issue 2684103005: Allow media track switching. (Closed)
Patch Set: CR feedback Created 3 years, 9 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 DVLOG(3) << __func__ << ": postponed stream " << stream 231 DVLOG(3) << __func__ << ": postponed stream " << stream
230 << " status change handling."; 232 << " status change handling.";
231 pending_stream_status_notifications_.push_back( 233 pending_stream_status_notifications_.push_back(
232 base::Bind(&RendererImpl::OnStreamStatusChanged, weak_this_, stream, 234 base::Bind(&RendererImpl::OnStreamStatusChanged, weak_this_, stream,
233 enabled, time)); 235 enabled, time));
234 return; 236 return;
235 } 237 }
236 if (stream->type() == DemuxerStream::VIDEO) { 238 if (stream->type() == DemuxerStream::VIDEO) {
237 DCHECK(video_renderer_); 239 DCHECK(video_renderer_);
238 restarting_video_ = true; 240 restarting_video_ = true;
239 video_renderer_->Flush( 241 video_renderer_->Flush(base::Bind(&RendererImpl::RestartVideoRenderer,
240 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time)); 242 weak_this_, stream, time));
241 } else if (stream->type() == DemuxerStream::AUDIO) { 243 } else if (stream->type() == DemuxerStream::AUDIO) {
242 DCHECK(audio_renderer_); 244 DCHECK(audio_renderer_);
243 DCHECK(time_source_); 245 DCHECK(time_source_);
244 restarting_audio_ = true; 246 restarting_audio_ = true;
245 // Stop ticking (transition into paused state) in audio renderer before 247 // Stop ticking (transition into paused state) in audio renderer before
246 // calling Flush, since after Flush we are going to restart playback by 248 // calling Flush, since after Flush we are going to restart playback by
247 // calling audio renderer StartPlaying which would fail in playing state. 249 // calling audio renderer StartPlaying which would fail in playing state.
248 if (time_ticking_) { 250 if (time_ticking_) {
249 time_ticking_ = false; 251 time_ticking_ = false;
250 time_source_->StopTicking(); 252 time_source_->StopTicking();
251 } 253 }
252 audio_renderer_->Flush( 254 audio_renderer_->Flush(base::Bind(&RendererImpl::RestartAudioRenderer,
253 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); 255 weak_this_, stream, time));
254 } 256 }
255 } 257 }
256 258
257 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) { 259 void RendererImpl::RestartVideoRenderer(DemuxerStream* stream,
258 DVLOG(3) << __func__; 260 base::TimeDelta time) {
261 DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
259 DCHECK(task_runner_->BelongsToCurrentThread()); 262 DCHECK(task_runner_->BelongsToCurrentThread());
260 DCHECK(video_renderer_); 263 DCHECK(video_renderer_);
261 DCHECK_EQ(state_, STATE_PLAYING); 264 DCHECK_EQ(state_, STATE_PLAYING);
265 if (stream != current_video_stream_) {
266 DVLOG(3) << __func__ << ": detected stream change, reinitializing decoder";
267 current_video_stream_ = stream;
268 video_renderer_->OnTimeStopped();
269 video_renderer_->Initialize(
270 stream, cdm_context_, video_renderer_client_.get(),
271 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
272 base::Bind(&RendererImpl::OnVideoRendererReinitCompleted, weak_this_,
273 stream, time));
274 return;
275 }
262 video_ended_ = false; 276 video_ended_ = false;
263 video_renderer_->StartPlayingFrom(time); 277 video_renderer_->StartPlayingFrom(time);
264 } 278 }
265 279
266 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) { 280 void RendererImpl::OnVideoRendererReinitCompleted(DemuxerStream* stream,
267 DVLOG(3) << __func__; 281 base::TimeDelta time,
282 PipelineStatus status) {
283 DVLOG(3) << __func__ << ": status=" << status;
284 if (status != PIPELINE_OK) {
285 OnError(status);
286 return;
287 }
288 DCHECK_EQ(stream, current_video_stream_);
DaleCurtis 2017/03/24 19:35:22 Seems like this could change if called in fast suc
servolk 2017/03/24 21:15:32 No, it should be fine. Here is how it works: when
289 RestartVideoRenderer(stream, time);
290 }
291
292 void RendererImpl::RestartAudioRenderer(DemuxerStream* stream,
293 base::TimeDelta time) {
294 DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
268 DCHECK(task_runner_->BelongsToCurrentThread()); 295 DCHECK(task_runner_->BelongsToCurrentThread());
269 DCHECK_EQ(state_, STATE_PLAYING); 296 DCHECK_EQ(state_, STATE_PLAYING);
270 DCHECK(time_source_); 297 DCHECK(time_source_);
271 DCHECK(audio_renderer_); 298 DCHECK(audio_renderer_);
299 if (stream != current_audio_stream_) {
300 DVLOG(3) << __func__ << ": detected stream change, reinitializing decoder";
301 current_audio_stream_ = stream;
302 audio_renderer_->Initialize(
303 stream, cdm_context_, audio_renderer_client_.get(),
304 base::Bind(&RendererImpl::OnAudioRendererReinitCompleted, weak_this_,
305 stream, time));
306 return;
307 }
272 audio_ended_ = false; 308 audio_ended_ = false;
273 audio_renderer_->StartPlaying(); 309 audio_renderer_->StartPlaying();
274 } 310 }
275 311
312 void RendererImpl::OnAudioRendererReinitCompleted(DemuxerStream* stream,
313 base::TimeDelta time,
314 PipelineStatus status) {
315 DVLOG(3) << __func__ << ": status=" << status;
316 if (status != PIPELINE_OK) {
317 OnError(status);
318 return;
319 }
320 DCHECK_EQ(stream, current_audio_stream_);
321 RestartAudioRenderer(stream, time);
322 }
323
276 void RendererImpl::SetPlaybackRate(double playback_rate) { 324 void RendererImpl::SetPlaybackRate(double playback_rate) {
277 DVLOG(1) << __func__ << "(" << playback_rate << ")"; 325 DVLOG(1) << __func__ << "(" << playback_rate << ")";
278 DCHECK(task_runner_->BelongsToCurrentThread()); 326 DCHECK(task_runner_->BelongsToCurrentThread());
279 327
280 // Playback rate changes are only carried out while playing. 328 // Playback rate changes are only carried out while playing.
281 if (state_ != STATE_PLAYING) 329 if (state_ != STATE_PLAYING)
282 return; 330 return;
283 331
284 time_source_->SetPlaybackRate(playback_rate); 332 time_source_->SetPlaybackRate(playback_rate);
285 333
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 // TODO(servolk): Implement proper support for multiple streams. But for now 435 // TODO(servolk): Implement proper support for multiple streams. But for now
388 // pick the first enabled stream to preserve the existing behavior. 436 // pick the first enabled stream to preserve the existing behavior.
389 DemuxerStream* audio_stream = 437 DemuxerStream* audio_stream =
390 media_resource_->GetFirstStream(DemuxerStream::AUDIO); 438 media_resource_->GetFirstStream(DemuxerStream::AUDIO);
391 if (!audio_stream) { 439 if (!audio_stream) {
392 audio_renderer_.reset(); 440 audio_renderer_.reset();
393 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 441 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
394 return; 442 return;
395 } 443 }
396 444
445 current_audio_stream_ = audio_stream;
446
397 audio_renderer_client_.reset( 447 audio_renderer_client_.reset(
398 new RendererClientInternal(DemuxerStream::AUDIO, this)); 448 new RendererClientInternal(DemuxerStream::AUDIO, this));
399 // Note: After the initialization of a renderer, error events from it may 449 // Note: After the initialization of a renderer, error events from it may
400 // happen at any time and all future calls must guard against STATE_ERROR. 450 // happen at any time and all future calls must guard against STATE_ERROR.
401 audio_renderer_->Initialize(audio_stream, cdm_context_, 451 audio_renderer_->Initialize(audio_stream, cdm_context_,
402 audio_renderer_client_.get(), done_cb); 452 audio_renderer_client_.get(), done_cb);
403 } 453 }
404 454
405 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { 455 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) {
406 DVLOG(1) << __func__ << ": " << status; 456 DVLOG(1) << __func__ << ": " << status;
(...skipping 28 matching lines...) Expand all
435 // TODO(servolk): Implement proper support for multiple streams. But for now 485 // TODO(servolk): Implement proper support for multiple streams. But for now
436 // pick the first enabled stream to preserve the existing behavior. 486 // pick the first enabled stream to preserve the existing behavior.
437 DemuxerStream* video_stream = 487 DemuxerStream* video_stream =
438 media_resource_->GetFirstStream(DemuxerStream::VIDEO); 488 media_resource_->GetFirstStream(DemuxerStream::VIDEO);
439 if (!video_stream) { 489 if (!video_stream) {
440 video_renderer_.reset(); 490 video_renderer_.reset();
441 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 491 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
442 return; 492 return;
443 } 493 }
444 494
495 current_video_stream_ = video_stream;
496
445 video_renderer_client_.reset( 497 video_renderer_client_.reset(
446 new RendererClientInternal(DemuxerStream::VIDEO, this)); 498 new RendererClientInternal(DemuxerStream::VIDEO, this));
447 video_renderer_->Initialize( 499 video_renderer_->Initialize(
448 video_stream, cdm_context_, video_renderer_client_.get(), 500 video_stream, cdm_context_, video_renderer_client_.get(),
449 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), 501 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
450 done_cb); 502 done_cb);
451 } 503 }
452 504
453 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { 505 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) {
454 DVLOG(1) << __func__ << ": " << status; 506 DVLOG(1) << __func__ << ": " << status;
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 DCHECK(task_runner_->BelongsToCurrentThread()); 901 DCHECK(task_runner_->BelongsToCurrentThread());
850 client_->OnVideoNaturalSizeChange(size); 902 client_->OnVideoNaturalSizeChange(size);
851 } 903 }
852 904
853 void RendererImpl::OnVideoOpacityChange(bool opaque) { 905 void RendererImpl::OnVideoOpacityChange(bool opaque) {
854 DCHECK(task_runner_->BelongsToCurrentThread()); 906 DCHECK(task_runner_->BelongsToCurrentThread());
855 client_->OnVideoOpacityChange(opaque); 907 client_->OnVideoOpacityChange(opaque);
856 } 908 }
857 909
858 } // namespace media 910 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698