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

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: updates media::Renderer subclasses 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 task_runner_->PostTask(
101 FROM_HERE, base::Bind(&VideoRendererImpl::OnBufferingStateChange,
102 weak_factory_.GetWeakPtr(), buffering_state_));
99 } 103 }
100 received_end_of_stream_ = false; 104 received_end_of_stream_ = false;
101 rendered_end_of_stream_ = false; 105 rendered_end_of_stream_ = false;
102 106
103 algorithm_->Reset(); 107 algorithm_->Reset();
104 108
105 video_frame_stream_->Reset( 109 video_frame_stream_->Reset(
106 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone, 110 base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone,
107 weak_factory_.GetWeakPtr())); 111 weak_factory_.GetWeakPtr()));
108 } 112 }
109 113
110 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { 114 void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
111 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")"; 115 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InMicroseconds() << ")";
112 DCHECK(task_runner_->BelongsToCurrentThread()); 116 DCHECK(task_runner_->BelongsToCurrentThread());
113 base::AutoLock auto_lock(lock_); 117 base::AutoLock auto_lock(lock_);
114 DCHECK_EQ(state_, kFlushed); 118 DCHECK_EQ(state_, kFlushed);
115 DCHECK(!pending_read_); 119 DCHECK(!pending_read_);
116 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); 120 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
117 121
118 state_ = kPlaying; 122 state_ = kPlaying;
119 start_timestamp_ = timestamp; 123 start_timestamp_ = timestamp;
120 AttemptRead_Locked(); 124 AttemptRead_Locked();
121 } 125 }
122 126
123 void VideoRendererImpl::Initialize( 127 void VideoRendererImpl::Initialize(
124 DemuxerStream* stream, 128 DemuxerStream* stream,
125 const PipelineStatusCB& init_cb,
126 CdmContext* cdm_context, 129 CdmContext* cdm_context,
127 const StatisticsCB& statistics_cb, 130 RendererClient* client,
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, 131 const TimeSource::WallClockTimeCB& wall_clock_time_cb,
132 const base::Closure& waiting_for_decryption_key_cb) { 132 const PipelineStatusCB& init_cb) {
133 DCHECK(task_runner_->BelongsToCurrentThread()); 133 DCHECK(task_runner_->BelongsToCurrentThread());
134 base::AutoLock auto_lock(lock_); 134 base::AutoLock auto_lock(lock_);
135 DCHECK(stream); 135 DCHECK(stream);
136 DCHECK_EQ(stream->type(), DemuxerStream::VIDEO); 136 DCHECK_EQ(stream->type(), DemuxerStream::VIDEO);
137 DCHECK(!init_cb.is_null()); 137 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()); 138 DCHECK(!wall_clock_time_cb.is_null());
142 DCHECK_EQ(kUninitialized, state_); 139 DCHECK_EQ(kUninitialized, state_);
143 DCHECK(!render_first_frame_and_stop_); 140 DCHECK(!render_first_frame_and_stop_);
144 DCHECK(!posted_maybe_stop_after_first_paint_); 141 DCHECK(!posted_maybe_stop_after_first_paint_);
145 DCHECK(!was_background_rendering_); 142 DCHECK(!was_background_rendering_);
146 DCHECK(!time_progressing_); 143 DCHECK(!time_progressing_);
147 144
148 low_delay_ = (stream->liveness() == DemuxerStream::LIVENESS_LIVE); 145 low_delay_ = (stream->liveness() == DemuxerStream::LIVENESS_LIVE);
149 UMA_HISTOGRAM_BOOLEAN("Media.VideoRenderer.LowDelay", low_delay_); 146 UMA_HISTOGRAM_BOOLEAN("Media.VideoRenderer.LowDelay", low_delay_);
150 if (low_delay_) 147 if (low_delay_)
151 MEDIA_LOG(DEBUG, media_log_) << "Video rendering in low delay mode."; 148 MEDIA_LOG(DEBUG, media_log_) << "Video rendering in low delay mode.";
152 149
153 // Always post |init_cb_| because |this| could be destroyed if initialization 150 // Always post |init_cb_| because |this| could be destroyed if initialization
154 // failed. 151 // failed.
155 init_cb_ = BindToCurrentLoop(init_cb); 152 init_cb_ = BindToCurrentLoop(init_cb);
156 153
157 // Always post |buffering_state_cb_| because it may otherwise invoke reentrant 154 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; 155 wall_clock_time_cb_ = wall_clock_time_cb;
166 state_ = kInitializing; 156 state_ = kInitializing;
167 157
168 video_frame_stream_->Initialize( 158 video_frame_stream_->Initialize(
169 stream, base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized, 159 stream, base::Bind(&VideoRendererImpl::OnVideoFrameStreamInitialized,
170 weak_factory_.GetWeakPtr()), 160 weak_factory_.GetWeakPtr()),
171 cdm_context, statistics_cb, waiting_for_decryption_key_cb); 161 cdm_context, base::Bind(&VideoRendererImpl::OnStatisticsUpdate,
162 weak_factory_.GetWeakPtr()),
163 base::Bind(&VideoRendererImpl::OnWaitingForDecryptionKey,
164 weak_factory_.GetWeakPtr()));
172 } 165 }
173 166
174 scoped_refptr<VideoFrame> VideoRendererImpl::Render( 167 scoped_refptr<VideoFrame> VideoRendererImpl::Render(
175 base::TimeTicks deadline_min, 168 base::TimeTicks deadline_min,
176 base::TimeTicks deadline_max, 169 base::TimeTicks deadline_max,
177 bool background_rendering) { 170 bool background_rendering) {
178 base::AutoLock auto_lock(lock_); 171 base::AutoLock auto_lock(lock_);
179 DCHECK_EQ(state_, kPlaying); 172 DCHECK_EQ(state_, kPlaying);
180 173
181 size_t frames_dropped = 0; 174 size_t frames_dropped = 0;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 // have not populated any buffers yet. 262 // have not populated any buffers yet.
270 state_ = kFlushed; 263 state_ = kFlushed;
271 264
272 algorithm_.reset(new VideoRendererAlgorithm(wall_clock_time_cb_)); 265 algorithm_.reset(new VideoRendererAlgorithm(wall_clock_time_cb_));
273 if (!drop_frames_) 266 if (!drop_frames_)
274 algorithm_->disable_frame_dropping(); 267 algorithm_->disable_frame_dropping();
275 268
276 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 269 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
277 } 270 }
278 271
272 void VideoRendererImpl::OnPlaybackError(PipelineStatus error) {
273 DCHECK(task_runner_->BelongsToCurrentThread());
274 client_->OnError(error);
275 }
276
277 void VideoRendererImpl::OnPlaybackEnded() {
278 DCHECK(task_runner_->BelongsToCurrentThread());
279 client_->OnEnded();
280 }
281
282 void VideoRendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) {
283 DCHECK(task_runner_->BelongsToCurrentThread());
284 client_->OnStatisticsUpdate(stats);
285 }
286
287 void VideoRendererImpl::OnBufferingStateChange(BufferingState state) {
288 DCHECK(task_runner_->BelongsToCurrentThread());
289 client_->OnBufferingStateChange(state);
290 }
291
292 void VideoRendererImpl::OnWaitingForDecryptionKey() {
293 DCHECK(task_runner_->BelongsToCurrentThread());
294 client_->OnWaitingForDecryptionKey();
295 }
296
279 void VideoRendererImpl::SetTickClockForTesting( 297 void VideoRendererImpl::SetTickClockForTesting(
280 std::unique_ptr<base::TickClock> tick_clock) { 298 std::unique_ptr<base::TickClock> tick_clock) {
281 tick_clock_.swap(tick_clock); 299 tick_clock_.swap(tick_clock);
282 } 300 }
283 301
284 void VideoRendererImpl::SetGpuMemoryBufferVideoForTesting( 302 void VideoRendererImpl::SetGpuMemoryBufferVideoForTesting(
285 std::unique_ptr<GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool) { 303 std::unique_ptr<GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool) {
286 gpu_memory_buffer_pool_.swap(gpu_memory_buffer_pool); 304 gpu_memory_buffer_pool_.swap(gpu_memory_buffer_pool);
287 } 305 }
288 306
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 return; 367 return;
350 368
351 DCHECK_NE(state_, kUninitialized); 369 DCHECK_NE(state_, kUninitialized);
352 DCHECK_NE(state_, kFlushed); 370 DCHECK_NE(state_, kFlushed);
353 371
354 CHECK(pending_read_); 372 CHECK(pending_read_);
355 pending_read_ = false; 373 pending_read_ = false;
356 374
357 if (status == VideoFrameStream::DECODE_ERROR) { 375 if (status == VideoFrameStream::DECODE_ERROR) {
358 DCHECK(!frame); 376 DCHECK(!frame);
359 PipelineStatus error = PIPELINE_ERROR_DECODE; 377 task_runner_->PostTask(
360 task_runner_->PostTask(FROM_HERE, base::Bind(error_cb_, error)); 378 FROM_HERE,
379 base::Bind(&VideoRendererImpl::OnPlaybackError,
380 weak_factory_.GetWeakPtr(), PIPELINE_ERROR_DECODE));
361 return; 381 return;
362 } 382 }
363 383
364 // Already-queued VideoFrameStream ReadCB's can fire after various state 384 // Already-queued VideoFrameStream ReadCB's can fire after various state
365 // transitions have happened; in that case just drop those frames 385 // transitions have happened; in that case just drop those frames
366 // immediately. 386 // immediately.
367 if (state_ == kFlushing) 387 if (state_ == kFlushing)
368 return; 388 return;
369 389
370 DCHECK_EQ(state_, kPlaying); 390 DCHECK_EQ(state_, kPlaying);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 464
445 return algorithm_->effective_frames_queued() > 0; 465 return algorithm_->effective_frames_queued() > 0;
446 } 466 }
447 467
448 void VideoRendererImpl::TransitionToHaveEnough_Locked() { 468 void VideoRendererImpl::TransitionToHaveEnough_Locked() {
449 DCHECK(task_runner_->BelongsToCurrentThread()); 469 DCHECK(task_runner_->BelongsToCurrentThread());
450 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); 470 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING);
451 lock_.AssertAcquired(); 471 lock_.AssertAcquired();
452 472
453 buffering_state_ = BUFFERING_HAVE_ENOUGH; 473 buffering_state_ = BUFFERING_HAVE_ENOUGH;
454 buffering_state_cb_.Run(BUFFERING_HAVE_ENOUGH); 474 task_runner_->PostTask(
475 FROM_HERE, base::Bind(&VideoRendererImpl::OnBufferingStateChange,
476 weak_factory_.GetWeakPtr(), buffering_state_));
455 } 477 }
456 478
457 void VideoRendererImpl::TransitionToHaveNothing() { 479 void VideoRendererImpl::TransitionToHaveNothing() {
458 DCHECK(task_runner_->BelongsToCurrentThread()); 480 DCHECK(task_runner_->BelongsToCurrentThread());
459 481
460 base::AutoLock auto_lock(lock_); 482 base::AutoLock auto_lock(lock_);
461 if (buffering_state_ != BUFFERING_HAVE_ENOUGH || HaveEnoughData_Locked()) 483 if (buffering_state_ != BUFFERING_HAVE_ENOUGH || HaveEnoughData_Locked())
462 return; 484 return;
463 485
464 buffering_state_ = BUFFERING_HAVE_NOTHING; 486 buffering_state_ = BUFFERING_HAVE_NOTHING;
465 buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING); 487 task_runner_->PostTask(
488 FROM_HERE, base::Bind(&VideoRendererImpl::OnBufferingStateChange,
489 weak_factory_.GetWeakPtr(), buffering_state_));
466 } 490 }
467 491
468 void VideoRendererImpl::AddReadyFrame_Locked( 492 void VideoRendererImpl::AddReadyFrame_Locked(
469 const scoped_refptr<VideoFrame>& frame) { 493 const scoped_refptr<VideoFrame>& frame) {
470 DCHECK(task_runner_->BelongsToCurrentThread()); 494 DCHECK(task_runner_->BelongsToCurrentThread());
471 lock_.AssertAcquired(); 495 lock_.AssertAcquired();
472 DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)); 496 DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM));
473 497
474 frames_decoded_++; 498 frames_decoded_++;
475 499
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 DCHECK_GE(frames_dropped_, 0); 556 DCHECK_GE(frames_dropped_, 0);
533 557
534 if (frames_decoded_ || frames_dropped_) { 558 if (frames_decoded_ || frames_dropped_) {
535 PipelineStatistics statistics; 559 PipelineStatistics statistics;
536 statistics.video_frames_decoded = frames_decoded_; 560 statistics.video_frames_decoded = frames_decoded_;
537 statistics.video_frames_dropped = frames_dropped_; 561 statistics.video_frames_dropped = frames_dropped_;
538 562
539 const size_t memory_usage = algorithm_->GetMemoryUsage(); 563 const size_t memory_usage = algorithm_->GetMemoryUsage();
540 statistics.video_memory_usage = memory_usage - last_video_memory_usage_; 564 statistics.video_memory_usage = memory_usage - last_video_memory_usage_;
541 565
542 task_runner_->PostTask(FROM_HERE, base::Bind(statistics_cb_, statistics)); 566 task_runner_->PostTask(FROM_HERE,
567 base::Bind(&VideoRendererImpl::OnStatisticsUpdate,
568 weak_factory_.GetWeakPtr(), statistics));
543 frames_decoded_ = 0; 569 frames_decoded_ = 0;
544 frames_dropped_ = 0; 570 frames_dropped_ = 0;
545 last_video_memory_usage_ = memory_usage; 571 last_video_memory_usage_ = memory_usage;
546 } 572 }
547 } 573 }
548 574
549 void VideoRendererImpl::MaybeStopSinkAfterFirstPaint() { 575 void VideoRendererImpl::MaybeStopSinkAfterFirstPaint() {
550 DCHECK(task_runner_->BelongsToCurrentThread()); 576 DCHECK(task_runner_->BelongsToCurrentThread());
551 577
552 if (!time_progressing_ && sink_started_) 578 if (!time_progressing_ && sink_started_)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 623
598 // Don't fire ended if time isn't moving and we have frames. 624 // Don't fire ended if time isn't moving and we have frames.
599 if (!time_progressing && algorithm_->frames_queued()) 625 if (!time_progressing && algorithm_->frames_queued())
600 return; 626 return;
601 627
602 // Fire ended if we have no more effective frames or only ever had one frame. 628 // Fire ended if we have no more effective frames or only ever had one frame.
603 if (!algorithm_->effective_frames_queued() || 629 if (!algorithm_->effective_frames_queued() ||
604 (algorithm_->frames_queued() == 1u && 630 (algorithm_->frames_queued() == 1u &&
605 algorithm_->average_frame_duration().is_zero())) { 631 algorithm_->average_frame_duration().is_zero())) {
606 rendered_end_of_stream_ = true; 632 rendered_end_of_stream_ = true;
607 task_runner_->PostTask(FROM_HERE, ended_cb_); 633 task_runner_->PostTask(FROM_HERE,
634 base::Bind(&VideoRendererImpl::OnPlaybackEnded,
635 weak_factory_.GetWeakPtr()));
608 } 636 }
609 } 637 }
610 638
611 base::TimeTicks VideoRendererImpl::ConvertMediaTimestamp( 639 base::TimeTicks VideoRendererImpl::ConvertMediaTimestamp(
612 base::TimeDelta media_time) { 640 base::TimeDelta media_time) {
613 std::vector<base::TimeDelta> media_times(1, media_time); 641 std::vector<base::TimeDelta> media_times(1, media_time);
614 std::vector<base::TimeTicks> wall_clock_times; 642 std::vector<base::TimeTicks> wall_clock_times;
615 if (!wall_clock_time_cb_.Run(media_times, &wall_clock_times)) 643 if (!wall_clock_time_cb_.Run(media_times, &wall_clock_times))
616 return base::TimeTicks(); 644 return base::TimeTicks();
617 return wall_clock_times[0]; 645 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 693 // the entire queue. Note: this may cause slight inaccuracies in the number
666 // of dropped frames since the frame may have been rendered before. 694 // of dropped frames since the frame may have been rendered before.
667 if (!sink_started_ && !algorithm_->effective_frames_queued()) { 695 if (!sink_started_ && !algorithm_->effective_frames_queued()) {
668 frames_dropped_ += algorithm_->frames_queued(); 696 frames_dropped_ += algorithm_->frames_queued();
669 algorithm_->Reset( 697 algorithm_->Reset(
670 VideoRendererAlgorithm::ResetFlag::kPreserveNextFrameEstimates); 698 VideoRendererAlgorithm::ResetFlag::kPreserveNextFrameEstimates);
671 } 699 }
672 } 700 }
673 701
674 } // namespace media 702 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698