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

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

Issue 1955843002: Move Renderer permanent callbacks into RendererClient interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 7 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/video_renderer_impl.h" 5 #include "media/renderers/video_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/location.h" 12 #include "base/location.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
16 #include "base/time/default_tick_clock.h" 16 #include "base/time/default_tick_clock.h"
17 #include "base/trace_event/trace_event.h" 17 #include "base/trace_event/trace_event.h"
18 #include "media/base/bind_to_current_loop.h" 18 #include "media/base/bind_to_current_loop.h"
19 #include "media/base/limits.h" 19 #include "media/base/limits.h"
20 #include "media/base/media_log.h" 20 #include "media/base/media_log.h"
21 #include "media/base/media_switches.h" 21 #include "media/base/media_switches.h"
22 #include "media/base/pipeline_status.h" 22 #include "media/base/pipeline_status.h"
23 #include "media/base/renderer_client.h"
23 #include "media/base/video_frame.h" 24 #include "media/base/video_frame.h"
24 #include "media/renderers/gpu_video_accelerator_factories.h" 25 #include "media/renderers/gpu_video_accelerator_factories.h"
25 #include "media/video/gpu_memory_buffer_video_frame_pool.h" 26 #include "media/video/gpu_memory_buffer_video_frame_pool.h"
26 27
27 namespace media { 28 namespace media {
28 29
29 VideoRendererImpl::VideoRendererImpl( 30 VideoRendererImpl::VideoRendererImpl(
30 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, 31 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
31 const scoped_refptr<base::TaskRunner>& worker_task_runner, 32 const scoped_refptr<base::TaskRunner>& worker_task_runner,
32 VideoRendererSink* sink, 33 VideoRendererSink* sink,
33 ScopedVector<VideoDecoder> decoders, 34 ScopedVector<VideoDecoder> decoders,
34 bool drop_frames, 35 bool drop_frames,
35 GpuVideoAcceleratorFactories* gpu_factories, 36 GpuVideoAcceleratorFactories* gpu_factories,
36 const scoped_refptr<MediaLog>& media_log) 37 const scoped_refptr<MediaLog>& media_log)
37 : task_runner_(media_task_runner), 38 : task_runner_(media_task_runner),
38 sink_(sink), 39 sink_(sink),
39 sink_started_(false), 40 sink_started_(false),
41 client_(nullptr),
40 video_frame_stream_(new VideoFrameStream(media_task_runner, 42 video_frame_stream_(new VideoFrameStream(media_task_runner,
41 std::move(decoders), 43 std::move(decoders),
42 media_log)), 44 media_log)),
43 gpu_memory_buffer_pool_(nullptr), 45 gpu_memory_buffer_pool_(nullptr),
44 media_log_(media_log), 46 media_log_(media_log),
45 low_delay_(false), 47 low_delay_(false),
46 received_end_of_stream_(false), 48 received_end_of_stream_(false),
47 rendered_end_of_stream_(false), 49 rendered_end_of_stream_(false),
48 state_(kUninitialized), 50 state_(kUninitialized),
49 sequence_token_(0), 51 sequence_token_(0),
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 90
89 base::AutoLock auto_lock(lock_); 91 base::AutoLock auto_lock(lock_);
90 DCHECK_EQ(state_, kPlaying); 92 DCHECK_EQ(state_, kPlaying);
91 flush_cb_ = callback; 93 flush_cb_ = callback;
92 state_ = kFlushing; 94 state_ = kFlushing;
93 95
94 // This is necessary if the |video_frame_stream_| has already seen an end of 96 // This is necessary if the |video_frame_stream_| has already seen an end of
95 // stream and needs to drain it before flushing it. 97 // stream and needs to drain it before flushing it.
96 if (buffering_state_ != BUFFERING_HAVE_NOTHING) { 98 if (buffering_state_ != BUFFERING_HAVE_NOTHING) {
97 buffering_state_ = BUFFERING_HAVE_NOTHING; 99 buffering_state_ = BUFFERING_HAVE_NOTHING;
98 buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING); 100 client_->OnBufferingStateChange(buffering_state_);
99 } 101 }
100 received_end_of_stream_ = false; 102 received_end_of_stream_ = false;
101 rendered_end_of_stream_ = false; 103 rendered_end_of_stream_ = false;
102 104
103 algorithm_->Reset(); 105 algorithm_->Reset();
104 106
105 video_frame_stream_->Reset( 107 video_frame_stream_->Reset(
106 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone, 108 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone,
107 weak_factory_.GetWeakPtr())); 109 weak_factory_.GetWeakPtr()));
108 } 110 }
109 111
110 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { 112 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
111 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; 113 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")";
112 DCHECK(task_runner_->BelongsToCurrentThread()); 114 DCHECK(task_runner_->BelongsToCurrentThread());
113 base::AutoLock auto_lock(lock_); 115 base::AutoLock auto_lock(lock_);
114 DCHECK_EQ(state_, kFlushed); 116 DCHECK_EQ(state_, kFlushed);
115 DCHECK(!pending_read_); 117 DCHECK(!pending_read_);
116 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); 118 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
117 119
118 state_ = kPlaying; 120 state_ = kPlaying;
119 start_timestamp_ = timestamp; 121 start_timestamp_ = timestamp;
120 AttemptRead_Locked(); 122 AttemptRead_Locked();
121 } 123 }
122 124
123 void VideoRendererImpl::Initialize( 125 void VideoRendererImpl::Initialize(
126 RendererClient* client,
124 DemuxerStream* stream, 127 DemuxerStream* stream,
125 const PipelineStatusCB& init_cb,
126 CdmContext* cdm_context, 128 CdmContext* cdm_context,
127 const StatisticsCB& statistics_cb,
128 const BufferingStateCB& buffering_state_cb,
129 const base::Closure& ended_cb,
130 const PipelineStatusCB& error_cb,
131 const TimeSource::WallClockTimeCB& wall_clock_time_cb, 129 const TimeSource::WallClockTimeCB& wall_clock_time_cb,
132 const base::Closure& waiting_for_decryption_key_cb) { 130 const PipelineStatusCB& init_cb) {
133 DCHECK(task_runner_->BelongsToCurrentThread()); 131 DCHECK(task_runner_->BelongsToCurrentThread());
134 base::AutoLock auto_lock(lock_); 132 base::AutoLock auto_lock(lock_);
135 DCHECK(stream); 133 DCHECK(stream);
136 DCHECK_EQ(stream->type(), DemuxerStream::VIDEO); 134 DCHECK_EQ(stream->type(), DemuxerStream::VIDEO);
137 DCHECK(!init_cb.is_null()); 135 DCHECK(!init_cb.is_null());
138 DCHECK(!statistics_cb.is_null());
139 DCHECK(!buffering_state_cb.is_null());
140 DCHECK(!ended_cb.is_null());
141 DCHECK(!wall_clock_time_cb.is_null()); 136 DCHECK(!wall_clock_time_cb.is_null());
142 DCHECK_EQ(kUninitialized, state_); 137 DCHECK_EQ(kUninitialized, state_);
143 DCHECK(!render_first_frame_and_stop_); 138 DCHECK(!render_first_frame_and_stop_);
144 DCHECK(!posted_maybe_stop_after_first_paint_); 139 DCHECK(!posted_maybe_stop_after_first_paint_);
145 DCHECK(!was_background_rendering_); 140 DCHECK(!was_background_rendering_);
146 DCHECK(!time_progressing_); 141 DCHECK(!time_progressing_);
147 142
148 low_delay_ = (stream->liveness() == DemuxerStream::LIVENESS_LIVE); 143 low_delay_ = (stream->liveness() == DemuxerStream::LIVENESS_LIVE);
149 UMA_HISTOGRAM_BOOLEAN("Media.VideoRenderer.LowDelay", low_delay_); 144 UMA_HISTOGRAM_BOOLEAN("Media.VideoRenderer.LowDelay", low_delay_);
150 if (low_delay_) 145 if (low_delay_)
151 MEDIA_LOG(DEBUG, media_log_) << "Video rendering in low delay mode."; 146 MEDIA_LOG(DEBUG, media_log_) << "Video rendering in low delay mode.";
152 147
153 // Always post |init_cb_| because |this| could be destroyed if initialization 148 // Always post |init_cb_| because |this| could be destroyed if initialization
154 // failed. 149 // failed.
155 init_cb_ = BindToCurrentLoop(init_cb); 150 init_cb_ = BindToCurrentLoop(init_cb);
156 151
157 // Always post |buffering_state_cb_| because it may otherwise invoke reentrant 152 client_ = client;
158 // calls to OnTimeStateChanged() under lock, which can deadlock the compositor
159 // and media threads.
160 buffering_state_cb_ = BindToCurrentLoop(buffering_state_cb);
161
162 statistics_cb_ = statistics_cb;
163 ended_cb_ = ended_cb;
164 error_cb_ = error_cb;
165 wall_clock_time_cb_ = wall_clock_time_cb; 153 wall_clock_time_cb_ = wall_clock_time_cb;
166 state_ = kInitializing; 154 state_ = kInitializing;
167 155
168 video_frame_stream_->Initialize( 156 video_frame_stream_->Initialize(
169 stream, base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized, 157 stream, base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized,
170 weak_factory_.GetWeakPtr()), 158 weak_factory_.GetWeakPtr()),
171 cdm_context, statistics_cb, waiting_for_decryption_key_cb); 159 cdm_context, base::Bind(&VideoRendererImpl::OnStatisticsUpdate,
160 weak_factory_.GetWeakPtr()),
161 base::Bind(&VideoRendererImpl::OnWaitingForDecryptionKey,
162 weak_factory_.GetWeakPtr()));
172 } 163 }
173 164
174 scoped_refptr<VideoFrame> VideoRendererImpl::Render( 165 scoped_refptr<VideoFrame> VideoRendererImpl::Render(
175 base::TimeTicks deadline_min, 166 base::TimeTicks deadline_min,
176 base::TimeTicks deadline_max, 167 base::TimeTicks deadline_max,
177 bool background_rendering) { 168 bool background_rendering) {
178 base::AutoLock auto_lock(lock_); 169 base::AutoLock auto_lock(lock_);
179 DCHECK_EQ(state_, kPlaying); 170 DCHECK_EQ(state_, kPlaying);
180 171
181 size_t frames_dropped = 0; 172 size_t frames_dropped = 0;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 // have not populated any buffers yet. 260 // have not populated any buffers yet.
270 state_ = kFlushed; 261 state_ = kFlushed;
271 262
272 algorithm_.reset(new VideoRendererAlgorithm(wall_clock_time_cb_)); 263 algorithm_.reset(new VideoRendererAlgorithm(wall_clock_time_cb_));
273 if (!drop_frames_) 264 if (!drop_frames_)
274 algorithm_->disable_frame_dropping(); 265 algorithm_->disable_frame_dropping();
275 266
276 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 267 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
277 } 268 }
278 269
270 void VideoRendererImpl::OnPlaybackEnded() {
271 DCHECK(task_runner_->BelongsToCurrentThread());
272 client_->OnEnded();
273 }
274
275 void VideoRendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) {
276 DCHECK(task_runner_->BelongsToCurrentThread());
277 client_->OnStatisticsUpdate(stats);
278 }
279
280 void VideoRendererImpl::OnWaitingForDecryptionKey() {
281 DCHECK(task_runner_->BelongsToCurrentThread());
282 client_->OnWaitingForDecryptionKey();
283 }
284
279 void VideoRendererImpl::SetTickClockForTesting( 285 void VideoRendererImpl::SetTickClockForTesting(
280 std::unique_ptr<base::TickClock> tick_clock) { 286 std::unique_ptr<base::TickClock> tick_clock) {
281 tick_clock_.swap(tick_clock); 287 tick_clock_.swap(tick_clock);
282 } 288 }
283 289
284 void VideoRendererImpl::SetGpuMemoryBufferVideoForTesting( 290 void VideoRendererImpl::SetGpuMemoryBufferVideoForTesting(
285 std::unique_ptr<GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool) { 291 std::unique_ptr<GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool) {
286 gpu_memory_buffer_pool_.swap(gpu_memory_buffer_pool); 292 gpu_memory_buffer_pool_.swap(gpu_memory_buffer_pool);
287 } 293 }
288 294
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 return; 355 return;
350 356
351 DCHECK_NE(state_, kUninitialized); 357 DCHECK_NE(state_, kUninitialized);
352 DCHECK_NE(state_, kFlushed); 358 DCHECK_NE(state_, kFlushed);
353 359
354 CHECK(pending_read_); 360 CHECK(pending_read_);
355 pending_read_ = false; 361 pending_read_ = false;
356 362
357 if (status == VideoFrameStream::DECODE_ERROR) { 363 if (status == VideoFrameStream::DECODE_ERROR) {
358 DCHECK(!frame); 364 DCHECK(!frame);
359 PipelineStatus error = PIPELINE_ERROR_DECODE; 365 client_->OnError(PIPELINE_ERROR_DECODE);
xhwang 2016/05/09 18:13:23 The old code posts the callback (probably because
alokp 2016/05/09 21:31:44 Done.
360 task_runner_->PostTask(FROM_HERE, base::Bind(error_cb_, error));
361 return; 366 return;
362 } 367 }
363 368
364 // Already-queued VideoFrameStream ReadCB's can fire after various state 369 // Already-queued VideoFrameStream ReadCB's can fire after various state
365 // transitions have happened; in that case just drop those frames 370 // transitions have happened; in that case just drop those frames
366 // immediately. 371 // immediately.
367 if (state_ == kFlushing) 372 if (state_ == kFlushing)
368 return; 373 return;
369 374
370 DCHECK_EQ(state_, kPlaying); 375 DCHECK_EQ(state_, kPlaying);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 449
445 return algorithm_->effective_frames_queued() > 0; 450 return algorithm_->effective_frames_queued() > 0;
446 } 451 }
447 452
448 void VideoRendererImpl::TransitionToHaveEnough_Locked() { 453 void VideoRendererImpl::TransitionToHaveEnough_Locked() {
449 DCHECK(task_runner_->BelongsToCurrentThread()); 454 DCHECK(task_runner_->BelongsToCurrentThread());
450 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); 455 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
451 lock_.AssertAcquired(); 456 lock_.AssertAcquired();
452 457
453 buffering_state_ = BUFFERING_HAVE_ENOUGH; 458 buffering_state_ = BUFFERING_HAVE_ENOUGH;
454 buffering_state_cb_.Run(BUFFERING_HAVE_ENOUGH); 459 client_->OnBufferingStateChange(buffering_state_);
xhwang 2016/05/09 18:13:23 The old |buffering_state_cb_| involves a post (Bin
alokp 2016/05/09 21:31:44 Done.
455 } 460 }
456 461
457 void VideoRendererImpl::TransitionToHaveNothing() { 462 void VideoRendererImpl::TransitionToHaveNothing() {
458 DCHECK(task_runner_->BelongsToCurrentThread()); 463 DCHECK(task_runner_->BelongsToCurrentThread());
459 464
460 base::AutoLock auto_lock(lock_); 465 base::AutoLock auto_lock(lock_);
461 if (buffering_state_ != BUFFERING_HAVE_ENOUGH || HaveEnoughData_Locked()) 466 if (buffering_state_ != BUFFERING_HAVE_ENOUGH || HaveEnoughData_Locked())
462 return; 467 return;
463 468
464 buffering_state_ = BUFFERING_HAVE_NOTHING; 469 buffering_state_ = BUFFERING_HAVE_NOTHING;
465 buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING); 470 client_->OnBufferingStateChange(buffering_state_);
xhwang 2016/05/09 18:13:23 ditto about post
alokp 2016/05/09 21:31:44 Done.
466 } 471 }
467 472
468 void VideoRendererImpl::AddReadyFrame_Locked( 473 void VideoRendererImpl::AddReadyFrame_Locked(
469 const scoped_refptr<VideoFrame>& frame) { 474 const scoped_refptr<VideoFrame>& frame) {
470 DCHECK(task_runner_->BelongsToCurrentThread()); 475 DCHECK(task_runner_->BelongsToCurrentThread());
471 lock_.AssertAcquired(); 476 lock_.AssertAcquired();
472 DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)); 477 DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM));
473 478
474 frames_decoded_++; 479 frames_decoded_++;
475 480
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 DCHECK_GE(frames_dropped_, 0); 537 DCHECK_GE(frames_dropped_, 0);
533 538
534 if (frames_decoded_ || frames_dropped_) { 539 if (frames_decoded_ || frames_dropped_) {
535 PipelineStatistics statistics; 540 PipelineStatistics statistics;
536 statistics.video_frames_decoded = frames_decoded_; 541 statistics.video_frames_decoded = frames_decoded_;
537 statistics.video_frames_dropped = frames_dropped_; 542 statistics.video_frames_dropped = frames_dropped_;
538 543
539 const size_t memory_usage = algorithm_->GetMemoryUsage(); 544 const size_t memory_usage = algorithm_->GetMemoryUsage();
540 statistics.video_memory_usage = memory_usage - last_video_memory_usage_; 545 statistics.video_memory_usage = memory_usage - last_video_memory_usage_;
541 546
542 task_runner_->PostTask(FROM_HERE, base::Bind(statistics_cb_, statistics)); 547 task_runner_->PostTask(FROM_HERE,
548 base::Bind(&VideoRendererImpl::OnStatisticsUpdate,
549 weak_factory_.GetWeakPtr(), statistics));
543 frames_decoded_ = 0; 550 frames_decoded_ = 0;
544 frames_dropped_ = 0; 551 frames_dropped_ = 0;
545 last_video_memory_usage_ = memory_usage; 552 last_video_memory_usage_ = memory_usage;
546 } 553 }
547 } 554 }
548 555
549 void VideoRendererImpl::MaybeStopSinkAfterFirstPaint() { 556 void VideoRendererImpl::MaybeStopSinkAfterFirstPaint() {
550 DCHECK(task_runner_->BelongsToCurrentThread()); 557 DCHECK(task_runner_->BelongsToCurrentThread());
551 558
552 if (!time_progressing_ && sink_started_) 559 if (!time_progressing_ && sink_started_)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 604
598 // Don't fire ended if time isn't moving and we have frames. 605 // Don't fire ended if time isn't moving and we have frames.
599 if (!time_progressing && algorithm_->frames_queued()) 606 if (!time_progressing && algorithm_->frames_queued())
600 return; 607 return;
601 608
602 // Fire ended if we have no more effective frames or only ever had one frame. 609 // Fire ended if we have no more effective frames or only ever had one frame.
603 if (!algorithm_->effective_frames_queued() || 610 if (!algorithm_->effective_frames_queued() ||
604 (algorithm_->frames_queued() == 1u && 611 (algorithm_->frames_queued() == 1u &&
605 algorithm_->average_frame_duration().is_zero())) { 612 algorithm_->average_frame_duration().is_zero())) {
606 rendered_end_of_stream_ = true; 613 rendered_end_of_stream_ = true;
607 task_runner_->PostTask(FROM_HERE, ended_cb_); 614 task_runner_->PostTask(FROM_HERE,
615 base::Bind(&VideoRendererImpl::OnPlaybackEnded,
616 weak_factory_.GetWeakPtr()));
608 } 617 }
609 } 618 }
610 619
611 base::TimeTicks VideoRendererImpl::ConvertMediaTimestamp( 620 base::TimeTicks VideoRendererImpl::ConvertMediaTimestamp(
612 base::TimeDelta media_time) { 621 base::TimeDelta media_time) {
613 std::vector<base::TimeDelta> media_times(1, media_time); 622 std::vector<base::TimeDelta> media_times(1, media_time);
614 std::vector<base::TimeTicks> wall_clock_times; 623 std::vector<base::TimeTicks> wall_clock_times;
615 if (!wall_clock_time_cb_.Run(media_times, &wall_clock_times)) 624 if (!wall_clock_time_cb_.Run(media_times, &wall_clock_times))
616 return base::TimeTicks(); 625 return base::TimeTicks();
617 return wall_clock_times[0]; 626 return wall_clock_times[0];
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 // the entire queue. Note: this may cause slight inaccuracies in the number 674 // the entire queue. Note: this may cause slight inaccuracies in the number
666 // of dropped frames since the frame may have been rendered before. 675 // of dropped frames since the frame may have been rendered before.
667 if (!sink_started_ && !algorithm_->effective_frames_queued()) { 676 if (!sink_started_ && !algorithm_->effective_frames_queued()) {
668 frames_dropped_ += algorithm_->frames_queued(); 677 frames_dropped_ += algorithm_->frames_queued();
669 algorithm_->Reset( 678 algorithm_->Reset(
670 VideoRendererAlgorithm::ResetFlag::kPreserveNextFrameEstimates); 679 VideoRendererAlgorithm::ResetFlag::kPreserveNextFrameEstimates);
671 } 680 }
672 } 681 }
673 682
674 } // namespace media 683 } // namespace media
OLDNEW
« media/renderers/video_renderer_impl.h ('K') | « media/renderers/video_renderer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698