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