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

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

Issue 2366373003: Not for submission. fastSeek prototype. (Closed)
Patch Set: Created 4 years, 2 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
« no previous file with comments | « media/renderers/renderer_impl.h ('k') | media/renderers/video_renderer_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "media/base/audio_decoder_config.h" 17 #include "media/base/audio_decoder_config.h"
18 #include "media/base/audio_renderer.h" 18 #include "media/base/audio_renderer.h"
19 #include "media/base/bind_to_current_loop.h" 19 #include "media/base/bind_to_current_loop.h"
20 #include "media/base/demuxer_stream_provider.h" 20 #include "media/base/demuxer_stream_provider.h"
21 #include "media/base/media_switches.h" 21 #include "media/base/media_switches.h"
22 #include "media/base/renderer_client.h" 22 #include "media/base/renderer_client.h"
23 #include "media/base/stream_position.h"
23 #include "media/base/time_source.h" 24 #include "media/base/time_source.h"
24 #include "media/base/video_decoder_config.h" 25 #include "media/base/video_decoder_config.h"
25 #include "media/base/video_renderer.h" 26 #include "media/base/video_renderer.h"
26 #include "media/base/wall_clock_time_source.h" 27 #include "media/base/wall_clock_time_source.h"
27 28
28 namespace media { 29 namespace media {
29 30
30 // See |video_underflow_threshold_|. 31 // See |video_underflow_threshold_|.
31 static const int kDefaultVideoUnderflowThresholdMs = 3000; 32 static const int kDefaultVideoUnderflowThresholdMs = 3000;
32 33
33 static const int kAudioRestartUnderflowThresholdMs = 2000; 34 static const int kAudioRestartUnderflowThresholdMs = 2000;
34 35
35 class RendererImpl::RendererClientInternal : public RendererClient { 36 class RendererImpl::RendererClientInternal : public RendererClient {
36 public: 37 public:
37 RendererClientInternal(DemuxerStream::Type type, RendererImpl* renderer) 38 RendererClientInternal(DemuxerStream::Type type, RendererImpl* renderer)
38 : type_(type), renderer_(renderer) { 39 : type_(type), renderer_(renderer) {
39 DCHECK((type_ == DemuxerStream::AUDIO) || (type_ == DemuxerStream::VIDEO)); 40 DCHECK((type_ == DemuxerStream::AUDIO) || (type_ == DemuxerStream::VIDEO));
40 } 41 }
41 42
42 void OnError(PipelineStatus error) override { renderer_->OnError(error); } 43 void OnError(PipelineStatus error) override { renderer_->OnError(error); }
43 void OnEnded() override { renderer_->OnRendererEnded(type_); } 44 void OnEnded() override { renderer_->OnRendererEnded(type_); }
44 void OnStatisticsUpdate(const PipelineStatistics& stats) override { 45 void OnStatisticsUpdate(const PipelineStatistics& stats) override {
45 renderer_->OnStatisticsUpdate(stats); 46 renderer_->OnStatisticsUpdate(stats);
46 } 47 }
48 void OnFirstVideoFrameTimestampKnown(base::TimeDelta timestamp) override {
49 renderer_->OnFirstVideoFrameTimestampKnown(timestamp);
50 }
47 void OnBufferingStateChange(BufferingState state) override { 51 void OnBufferingStateChange(BufferingState state) override {
48 renderer_->OnBufferingStateChange(type_, state); 52 renderer_->OnBufferingStateChange(type_, state);
49 } 53 }
50 void OnWaitingForDecryptionKey() override { 54 void OnWaitingForDecryptionKey() override {
51 renderer_->OnWaitingForDecryptionKey(); 55 renderer_->OnWaitingForDecryptionKey();
52 } 56 }
53 void OnVideoNaturalSizeChange(const gfx::Size& size) override { 57 void OnVideoNaturalSizeChange(const gfx::Size& size) override {
54 DCHECK(type_ == DemuxerStream::VIDEO); 58 DCHECK(type_ == DemuxerStream::VIDEO);
55 renderer_->OnVideoNaturalSizeChange(size); 59 renderer_->OnVideoNaturalSizeChange(size);
56 } 60 }
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 201
198 flush_cb_ = flush_cb; 202 flush_cb_ = flush_cb;
199 state_ = STATE_FLUSHING; 203 state_ = STATE_FLUSHING;
200 204
201 if (time_ticking_) 205 if (time_ticking_)
202 PausePlayback(); 206 PausePlayback();
203 207
204 FlushAudioRenderer(); 208 FlushAudioRenderer();
205 } 209 }
206 210
207 void RendererImpl::StartPlayingFrom(base::TimeDelta time) { 211 void RendererImpl::StartPlayingFrom(StreamPosition position) {
208 DVLOG(1) << __func__; 212 DVLOG(1) << __func__;
209 DCHECK(task_runner_->BelongsToCurrentThread()); 213 DCHECK(task_runner_->BelongsToCurrentThread());
210 214
211 if (state_ != STATE_PLAYING) { 215 if (state_ != STATE_PLAYING) {
212 DCHECK_EQ(state_, STATE_ERROR); 216 DCHECK_EQ(state_, STATE_ERROR);
213 return; 217 return;
214 } 218 }
215 219
216 time_source_->SetMediaTime(time); 220 time_source_->SetMediaTime(position.time);
217 221
222 // XXX: There's no synchronization b/w the renderers. Is it safe to assume the
223 // demuxers will give us frames close enough to one another? If not we could
224 // start the video renderer, wait until we know the time of the first frame,
225 // and then start the audio renderer.
218 if (audio_renderer_) 226 if (audio_renderer_)
219 audio_renderer_->StartPlaying(); 227 audio_renderer_->StartPlayingFrom(position);
220 if (video_renderer_) 228 if (video_renderer_)
221 video_renderer_->StartPlayingFrom(time); 229 video_renderer_->StartPlayingFrom(position);
222 } 230 }
223 231
224 void RendererImpl::RestartStreamPlayback(DemuxerStream* stream, 232 void RendererImpl::RestartStreamPlayback(DemuxerStream* stream,
225 bool enabled, 233 bool enabled,
226 base::TimeDelta time) { 234 base::TimeDelta time) {
227 DCHECK(task_runner_->BelongsToCurrentThread()); 235 DCHECK(task_runner_->BelongsToCurrentThread());
228 DCHECK(stream); 236 DCHECK(stream);
229 bool video = (stream->type() == DemuxerStream::VIDEO); 237 bool video = (stream->type() == DemuxerStream::VIDEO);
230 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream 238 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream
231 << " enabled=" << stream->enabled() << " time=" << time.InSecondsF(); 239 << " enabled=" << stream->enabled() << " time=" << time.InSecondsF();
(...skipping 23 matching lines...) Expand all
255 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); 263 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time));
256 } 264 }
257 } 265 }
258 266
259 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) { 267 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) {
260 DVLOG(3) << __func__; 268 DVLOG(3) << __func__;
261 DCHECK(task_runner_->BelongsToCurrentThread()); 269 DCHECK(task_runner_->BelongsToCurrentThread());
262 DCHECK(video_renderer_); 270 DCHECK(video_renderer_);
263 DCHECK_EQ(state_, STATE_PLAYING); 271 DCHECK_EQ(state_, STATE_PLAYING);
264 video_ended_ = false; 272 video_ended_ = false;
265 video_renderer_->StartPlayingFrom(time); 273 // XXX: Converted without thought.
274 video_renderer_->StartPlayingFrom(StreamPosition::Precise(time));
266 } 275 }
267 276
268 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) { 277 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) {
269 DVLOG(3) << __func__; 278 DVLOG(3) << __func__;
270 DCHECK(task_runner_->BelongsToCurrentThread()); 279 DCHECK(task_runner_->BelongsToCurrentThread());
271 DCHECK_EQ(state_, STATE_PLAYING); 280 DCHECK_EQ(state_, STATE_PLAYING);
272 DCHECK(time_source_); 281 DCHECK(time_source_);
273 DCHECK(audio_renderer_); 282 DCHECK(audio_renderer_);
274 audio_ended_ = false; 283 audio_ended_ = false;
275 audio_renderer_->StartPlaying(); 284 // XXX: Converted without thought.
285 audio_renderer_->StartPlayingFrom(StreamPosition::Precise(time));
276 } 286 }
277 287
278 void RendererImpl::SetPlaybackRate(double playback_rate) { 288 void RendererImpl::SetPlaybackRate(double playback_rate) {
279 DVLOG(1) << __func__ << "(" << playback_rate << ")"; 289 DVLOG(1) << __func__ << "(" << playback_rate << ")";
280 DCHECK(task_runner_->BelongsToCurrentThread()); 290 DCHECK(task_runner_->BelongsToCurrentThread());
281 291
282 // Playback rate changes are only carried out while playing. 292 // Playback rate changes are only carried out while playing.
283 if (state_ != STATE_PLAYING) 293 if (state_ != STATE_PLAYING)
284 return; 294 return;
285 295
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 << "Underflow must be disabled for clockless video playback"; 346 << "Underflow must be disabled for clockless video playback";
337 347
338 clockless_video_playback_enabled_for_testing_ = true; 348 clockless_video_playback_enabled_for_testing_ = true;
339 } 349 }
340 350
341 bool RendererImpl::GetWallClockTimes( 351 bool RendererImpl::GetWallClockTimes(
342 const std::vector<base::TimeDelta>& media_timestamps, 352 const std::vector<base::TimeDelta>& media_timestamps,
343 std::vector<base::TimeTicks>* wall_clock_times) { 353 std::vector<base::TimeTicks>* wall_clock_times) {
344 // No BelongsToCurrentThread() checking because this can be called from other 354 // No BelongsToCurrentThread() checking because this can be called from other
345 // threads. 355 // threads.
346 //
347 // TODO(scherkus): Currently called from VideoRendererImpl's internal thread,
348 // which should go away at some point http://crbug.com/110814
349 if (clockless_video_playback_enabled_for_testing_) { 356 if (clockless_video_playback_enabled_for_testing_) {
350 if (media_timestamps.empty()) { 357 if (media_timestamps.empty()) {
351 *wall_clock_times = std::vector<base::TimeTicks>(1, 358 *wall_clock_times = std::vector<base::TimeTicks>(1,
352 base::TimeTicks::Now()); 359 base::TimeTicks::Now());
353 } else { 360 } else {
354 *wall_clock_times = std::vector<base::TimeTicks>(); 361 *wall_clock_times = std::vector<base::TimeTicks>();
355 for (auto const &media_time : media_timestamps) { 362 for (auto const &media_time : media_timestamps) {
356 wall_clock_times->push_back(base::TimeTicks() + media_time); 363 wall_clock_times->push_back(base::TimeTicks() + media_time);
357 } 364 }
358 } 365 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 video_ended_ = false; 562 video_ended_ = false;
556 state_ = STATE_PLAYING; 563 state_ = STATE_PLAYING;
557 base::ResetAndReturn(&flush_cb_).Run(); 564 base::ResetAndReturn(&flush_cb_).Run();
558 } 565 }
559 566
560 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { 567 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) {
561 DCHECK(task_runner_->BelongsToCurrentThread()); 568 DCHECK(task_runner_->BelongsToCurrentThread());
562 client_->OnStatisticsUpdate(stats); 569 client_->OnStatisticsUpdate(stats);
563 } 570 }
564 571
572 // XXX: Revisit: I don't really like this. I considered letting the video
573 // renderer own the wall clock time source and manage this itself, but it didn't
574 // work for some reason. Try again.
575 void RendererImpl::OnFirstVideoFrameTimestampKnown(base::TimeDelta timestamp) {
576 DCHECK(task_runner_->BelongsToCurrentThread());
577 LOG(ERROR) << __func__ << " " << timestamp.InMicroseconds();
578 if (wall_clock_time_source_)
579 wall_clock_time_source_->SetMediaTime(timestamp);
580 }
581
565 namespace { 582 namespace {
566 583
567 const char* BufferingStateStr(BufferingState state) { 584 const char* BufferingStateStr(BufferingState state) {
568 switch (state) { 585 switch (state) {
569 case BUFFERING_HAVE_NOTHING: 586 case BUFFERING_HAVE_NOTHING:
570 return "HAVE_NOTHING"; 587 return "HAVE_NOTHING";
571 case BUFFERING_HAVE_ENOUGH: 588 case BUFFERING_HAVE_ENOUGH:
572 return "HAVE_ENOUGH"; 589 return "HAVE_ENOUGH";
573 } 590 }
574 NOTREACHED(); 591 NOTREACHED();
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 DCHECK(task_runner_->BelongsToCurrentThread()); 866 DCHECK(task_runner_->BelongsToCurrentThread());
850 client_->OnVideoNaturalSizeChange(size); 867 client_->OnVideoNaturalSizeChange(size);
851 } 868 }
852 869
853 void RendererImpl::OnVideoOpacityChange(bool opaque) { 870 void RendererImpl::OnVideoOpacityChange(bool opaque) {
854 DCHECK(task_runner_->BelongsToCurrentThread()); 871 DCHECK(task_runner_->BelongsToCurrentThread());
855 client_->OnVideoOpacityChange(opaque); 872 client_->OnVideoOpacityChange(opaque);
856 } 873 }
857 874
858 } // namespace media 875 } // namespace media
OLDNEW
« no previous file with comments | « media/renderers/renderer_impl.h ('k') | media/renderers/video_renderer_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698