OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |