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

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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
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(
240 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time)); 242 base::Bind((stream == current_video_stream_)
243 ? &RendererImpl::RestartVideoRenderer
244 : &RendererImpl::ReinitializeVideoRenderer,
245 weak_this_, stream, time));
241 } else if (stream->type() == DemuxerStream::AUDIO) { 246 } else if (stream->type() == DemuxerStream::AUDIO) {
242 DCHECK(audio_renderer_); 247 DCHECK(audio_renderer_);
243 DCHECK(time_source_); 248 DCHECK(time_source_);
244 restarting_audio_ = true; 249 restarting_audio_ = true;
245 // Stop ticking (transition into paused state) in audio renderer before 250 // Stop ticking (transition into paused state) in audio renderer before
246 // calling Flush, since after Flush we are going to restart playback by 251 // calling Flush, since after Flush we are going to restart playback by
247 // calling audio renderer StartPlaying which would fail in playing state. 252 // calling audio renderer StartPlaying which would fail in playing state.
248 if (time_ticking_) { 253 if (time_ticking_) {
249 time_ticking_ = false; 254 time_ticking_ = false;
250 time_source_->StopTicking(); 255 time_source_->StopTicking();
251 } 256 }
252 audio_renderer_->Flush( 257 audio_renderer_->Flush(
253 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); 258 base::Bind((stream == current_audio_stream_)
259 ? &RendererImpl::RestartAudioRenderer
260 : &RendererImpl::ReinitializeAudioRenderer,
261 weak_this_, stream, time));
254 } 262 }
255 } 263 }
256 264
257 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) { 265 void RendererImpl::ReinitializeVideoRenderer(DemuxerStream* stream,
258 DVLOG(3) << __func__; 266 base::TimeDelta time) {
267 DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
xhwang 2017/03/29 00:16:47 nit: here and everywhere else, media switching isn
servolk 2017/03/29 01:49:33 Done.
268 DCHECK(task_runner_->BelongsToCurrentThread());
269 DCHECK_NE(stream, current_video_stream_);
270
271 current_video_stream_ = stream;
272 video_renderer_->OnTimeStopped();
273 video_renderer_->Initialize(
274 stream, cdm_context_, video_renderer_client_.get(),
275 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
276 base::Bind(&RendererImpl::OnVideoRendererReinitialized, weak_this_,
277 stream, time));
278 }
279
280 void RendererImpl::OnVideoRendererReinitialized(DemuxerStream* stream,
xhwang 2017/03/29 00:16:47 nit: Why do we need to pass in the |stream| here a
servolk 2017/03/29 01:49:33 Well, we could do without it, but it's just slight
281 base::TimeDelta time,
282 PipelineStatus status) {
283 DVLOG(3) << __func__ << ": status=" << status;
284 DCHECK_EQ(stream, current_video_stream_);
285
286 if (status != PIPELINE_OK) {
287 OnError(status);
288 return;
289 }
290 RestartVideoRenderer(stream, time);
291 }
292
293 void RendererImpl::RestartVideoRenderer(DemuxerStream* stream,
294 base::TimeDelta time) {
295 DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
259 DCHECK(task_runner_->BelongsToCurrentThread()); 296 DCHECK(task_runner_->BelongsToCurrentThread());
260 DCHECK(video_renderer_); 297 DCHECK(video_renderer_);
261 DCHECK_EQ(state_, STATE_PLAYING); 298 DCHECK_EQ(state_, STATE_PLAYING);
299 DCHECK_EQ(stream, current_video_stream_);
300
262 video_ended_ = false; 301 video_ended_ = false;
263 video_renderer_->StartPlayingFrom(time); 302 video_renderer_->StartPlayingFrom(time);
264 } 303 }
265 304
266 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) { 305 void RendererImpl::ReinitializeAudioRenderer(DemuxerStream* stream,
267 DVLOG(3) << __func__; 306 base::TimeDelta time) {
307 DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
308 DCHECK(task_runner_->BelongsToCurrentThread());
309 DCHECK_NE(stream, current_audio_stream_);
310
311 current_audio_stream_ = stream;
312 audio_renderer_->Initialize(
313 stream, cdm_context_, audio_renderer_client_.get(),
314 base::Bind(&RendererImpl::OnAudioRendererReinitialized, weak_this_,
315 stream, time));
316 }
317
318 void RendererImpl::OnAudioRendererReinitialized(DemuxerStream* stream,
319 base::TimeDelta time,
320 PipelineStatus status) {
321 DVLOG(3) << __func__ << ": status=" << status;
322 DCHECK_EQ(stream, current_audio_stream_);
323
324 if (status != PIPELINE_OK) {
325 OnError(status);
326 return;
327 }
328 RestartAudioRenderer(stream, time);
329 }
330
331 void RendererImpl::RestartAudioRenderer(DemuxerStream* stream,
332 base::TimeDelta time) {
333 DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
268 DCHECK(task_runner_->BelongsToCurrentThread()); 334 DCHECK(task_runner_->BelongsToCurrentThread());
269 DCHECK_EQ(state_, STATE_PLAYING); 335 DCHECK_EQ(state_, STATE_PLAYING);
270 DCHECK(time_source_); 336 DCHECK(time_source_);
271 DCHECK(audio_renderer_); 337 DCHECK(audio_renderer_);
338 DCHECK_EQ(stream, current_audio_stream_);
339
272 audio_ended_ = false; 340 audio_ended_ = false;
273 audio_renderer_->StartPlaying(); 341 audio_renderer_->StartPlaying();
274 } 342 }
275 343
276 void RendererImpl::SetPlaybackRate(double playback_rate) { 344 void RendererImpl::SetPlaybackRate(double playback_rate) {
277 DVLOG(1) << __func__ << "(" << playback_rate << ")"; 345 DVLOG(1) << __func__ << "(" << playback_rate << ")";
278 DCHECK(task_runner_->BelongsToCurrentThread()); 346 DCHECK(task_runner_->BelongsToCurrentThread());
279 347
280 // Playback rate changes are only carried out while playing. 348 // Playback rate changes are only carried out while playing.
281 if (state_ != STATE_PLAYING) 349 if (state_ != STATE_PLAYING)
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 // TODO(servolk): Implement proper support for multiple streams. But for now 455 // TODO(servolk): Implement proper support for multiple streams. But for now
388 // pick the first enabled stream to preserve the existing behavior. 456 // pick the first enabled stream to preserve the existing behavior.
389 DemuxerStream* audio_stream = 457 DemuxerStream* audio_stream =
390 media_resource_->GetFirstStream(DemuxerStream::AUDIO); 458 media_resource_->GetFirstStream(DemuxerStream::AUDIO);
391 if (!audio_stream) { 459 if (!audio_stream) {
392 audio_renderer_.reset(); 460 audio_renderer_.reset();
393 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 461 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
394 return; 462 return;
395 } 463 }
396 464
465 current_audio_stream_ = audio_stream;
466
397 audio_renderer_client_.reset( 467 audio_renderer_client_.reset(
398 new RendererClientInternal(DemuxerStream::AUDIO, this)); 468 new RendererClientInternal(DemuxerStream::AUDIO, this));
399 // Note: After the initialization of a renderer, error events from it may 469 // 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. 470 // happen at any time and all future calls must guard against STATE_ERROR.
401 audio_renderer_->Initialize(audio_stream, cdm_context_, 471 audio_renderer_->Initialize(audio_stream, cdm_context_,
402 audio_renderer_client_.get(), done_cb); 472 audio_renderer_client_.get(), done_cb);
403 } 473 }
404 474
405 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { 475 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) {
406 DVLOG(1) << __func__ << ": " << status; 476 DVLOG(1) << __func__ << ": " << status;
(...skipping 28 matching lines...) Expand all
435 // TODO(servolk): Implement proper support for multiple streams. But for now 505 // TODO(servolk): Implement proper support for multiple streams. But for now
436 // pick the first enabled stream to preserve the existing behavior. 506 // pick the first enabled stream to preserve the existing behavior.
437 DemuxerStream* video_stream = 507 DemuxerStream* video_stream =
438 media_resource_->GetFirstStream(DemuxerStream::VIDEO); 508 media_resource_->GetFirstStream(DemuxerStream::VIDEO);
439 if (!video_stream) { 509 if (!video_stream) {
440 video_renderer_.reset(); 510 video_renderer_.reset();
441 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 511 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
442 return; 512 return;
443 } 513 }
444 514
515 current_video_stream_ = video_stream;
516
445 video_renderer_client_.reset( 517 video_renderer_client_.reset(
446 new RendererClientInternal(DemuxerStream::VIDEO, this)); 518 new RendererClientInternal(DemuxerStream::VIDEO, this));
447 video_renderer_->Initialize( 519 video_renderer_->Initialize(
448 video_stream, cdm_context_, video_renderer_client_.get(), 520 video_stream, cdm_context_, video_renderer_client_.get(),
449 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), 521 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
450 done_cb); 522 done_cb);
451 } 523 }
452 524
453 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { 525 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) {
454 DVLOG(1) << __func__ << ": " << status; 526 DVLOG(1) << __func__ << ": " << status;
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 DCHECK(task_runner_->BelongsToCurrentThread()); 921 DCHECK(task_runner_->BelongsToCurrentThread());
850 client_->OnVideoNaturalSizeChange(size); 922 client_->OnVideoNaturalSizeChange(size);
851 } 923 }
852 924
853 void RendererImpl::OnVideoOpacityChange(bool opaque) { 925 void RendererImpl::OnVideoOpacityChange(bool opaque) {
854 DCHECK(task_runner_->BelongsToCurrentThread()); 926 DCHECK(task_runner_->BelongsToCurrentThread());
855 client_->OnVideoOpacityChange(opaque); 927 client_->OnVideoOpacityChange(opaque);
856 } 928 }
857 929
858 } // namespace media 930 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698