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

Side by Side Diff: media/base/pipeline.cc

Issue 379343005: Introduce media::TimeSource. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/base/pipeline.h" 5 #include "media/base/pipeline.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
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/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
16 #include "base/stl_util.h" 16 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/synchronization/condition_variable.h" 19 #include "base/synchronization/condition_variable.h"
20 #include "media/base/audio_decoder.h" 20 #include "media/base/audio_decoder.h"
21 #include "media/base/audio_renderer.h" 21 #include "media/base/audio_renderer.h"
22 #include "media/base/filter_collection.h" 22 #include "media/base/filter_collection.h"
23 #include "media/base/media_log.h" 23 #include "media/base/media_log.h"
24 #include "media/base/text_renderer.h" 24 #include "media/base/text_renderer.h"
25 #include "media/base/text_track_config.h" 25 #include "media/base/text_track_config.h"
26 #include "media/base/time_delta_interpolator.h"
27 #include "media/base/video_decoder.h" 26 #include "media/base/video_decoder.h"
28 #include "media/base/video_decoder_config.h" 27 #include "media/base/video_decoder_config.h"
29 #include "media/base/video_renderer.h" 28 #include "media/base/video_renderer.h"
29 #include "media/base/wall_clock_time_source.h"
30 30
31 using base::TimeDelta; 31 using base::TimeDelta;
32 32
33 namespace media { 33 namespace media {
34 34
35 Pipeline::Pipeline( 35 Pipeline::Pipeline(
36 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 36 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
37 MediaLog* media_log) 37 MediaLog* media_log)
38 : task_runner_(task_runner), 38 : task_runner_(task_runner),
39 media_log_(media_log), 39 media_log_(media_log),
40 running_(false), 40 running_(false),
41 did_loading_progress_(false), 41 did_loading_progress_(false),
42 volume_(1.0f), 42 volume_(1.0f),
43 playback_rate_(0.0f), 43 playback_rate_(0.0f),
44 interpolator_(new TimeDeltaInterpolator(&default_tick_clock_)),
45 interpolation_state_(INTERPOLATION_STOPPED),
46 status_(PIPELINE_OK), 44 status_(PIPELINE_OK),
47 state_(kCreated), 45 state_(kCreated),
48 audio_ended_(false), 46 audio_ended_(false),
49 video_ended_(false), 47 video_ended_(false),
50 text_ended_(false), 48 text_ended_(false),
51 audio_buffering_state_(BUFFERING_HAVE_NOTHING), 49 audio_buffering_state_(BUFFERING_HAVE_NOTHING),
52 video_buffering_state_(BUFFERING_HAVE_NOTHING), 50 video_buffering_state_(BUFFERING_HAVE_NOTHING),
53 demuxer_(NULL), 51 demuxer_(NULL),
52 time_source_(NULL),
54 underflow_disabled_for_testing_(false) { 53 underflow_disabled_for_testing_(false) {
55 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 54 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
56 media_log_->AddEvent( 55 media_log_->AddEvent(
57 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); 56 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED));
58 interpolator_->SetBounds(base::TimeDelta(), base::TimeDelta());
59 } 57 }
60 58
61 Pipeline::~Pipeline() { 59 Pipeline::~Pipeline() {
62 DCHECK(thread_checker_.CalledOnValidThread()) 60 DCHECK(thread_checker_.CalledOnValidThread())
63 << "Pipeline must be destroyed on same thread that created it"; 61 << "Pipeline must be destroyed on same thread that created it";
64 DCHECK(!running_) << "Stop() must complete before destroying object"; 62 DCHECK(!running_) << "Stop() must complete before destroying object";
65 DCHECK(stop_cb_.is_null()); 63 DCHECK(stop_cb_.is_null());
66 DCHECK(seek_cb_.is_null()); 64 DCHECK(seek_cb_.is_null());
67 65
68 media_log_->AddEvent( 66 media_log_->AddEvent(
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 base::AutoLock auto_lock(lock_); 148 base::AutoLock auto_lock(lock_);
151 volume_ = volume; 149 volume_ = volume;
152 if (running_) { 150 if (running_) {
153 task_runner_->PostTask(FROM_HERE, base::Bind( 151 task_runner_->PostTask(FROM_HERE, base::Bind(
154 &Pipeline::VolumeChangedTask, base::Unretained(this), volume)); 152 &Pipeline::VolumeChangedTask, base::Unretained(this), volume));
155 } 153 }
156 } 154 }
157 155
158 TimeDelta Pipeline::GetMediaTime() const { 156 TimeDelta Pipeline::GetMediaTime() const {
159 base::AutoLock auto_lock(lock_); 157 base::AutoLock auto_lock(lock_);
160 return std::min(interpolator_->GetInterpolatedTime(), duration_); 158 return time_source_->CurrentMediaTimestamp();
xhwang 2014/07/12 06:36:44 Other use of time_source_ in this file is not prot
161 } 159 }
162 160
163 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { 161 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const {
164 base::AutoLock auto_lock(lock_); 162 base::AutoLock auto_lock(lock_);
165 return buffered_time_ranges_; 163 return buffered_time_ranges_;
166 } 164 }
167 165
168 TimeDelta Pipeline::GetMediaDuration() const { 166 TimeDelta Pipeline::GetMediaDuration() const {
169 base::AutoLock auto_lock(lock_); 167 base::AutoLock auto_lock(lock_);
170 return duration_; 168 return duration_;
171 } 169 }
172 170
173 bool Pipeline::DidLoadingProgress() { 171 bool Pipeline::DidLoadingProgress() {
174 base::AutoLock auto_lock(lock_); 172 base::AutoLock auto_lock(lock_);
175 bool ret = did_loading_progress_; 173 bool ret = did_loading_progress_;
176 did_loading_progress_ = false; 174 did_loading_progress_ = false;
177 return ret; 175 return ret;
178 } 176 }
179 177
180 PipelineStatistics Pipeline::GetStatistics() const { 178 PipelineStatistics Pipeline::GetStatistics() const {
181 base::AutoLock auto_lock(lock_); 179 base::AutoLock auto_lock(lock_);
182 return statistics_; 180 return statistics_;
183 } 181 }
184 182
185 void Pipeline::SetTimeDeltaInterpolatorForTesting(
186 TimeDeltaInterpolator* interpolator) {
187 interpolator_.reset(interpolator);
188 }
189
190 void Pipeline::SetErrorForTesting(PipelineStatus status) { 183 void Pipeline::SetErrorForTesting(PipelineStatus status) {
191 SetError(status); 184 SetError(status);
192 } 185 }
193 186
194 void Pipeline::SetState(State next_state) { 187 void Pipeline::SetState(State next_state) {
195 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); 188 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state);
196 189
197 state_ = next_state; 190 state_ = next_state;
198 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); 191 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state));
199 } 192 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 DCHECK(IsRunning()); 269 DCHECK(IsRunning());
277 DCHECK_NE(PIPELINE_OK, error); 270 DCHECK_NE(PIPELINE_OK, error);
278 VLOG(1) << "Media pipeline error: " << error; 271 VLOG(1) << "Media pipeline error: " << error;
279 272
280 task_runner_->PostTask(FROM_HERE, base::Bind( 273 task_runner_->PostTask(FROM_HERE, base::Bind(
281 &Pipeline::ErrorChangedTask, base::Unretained(this), error)); 274 &Pipeline::ErrorChangedTask, base::Unretained(this), error));
282 275
283 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); 276 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
284 } 277 }
285 278
286 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) {
287 DCHECK(task_runner_->BelongsToCurrentThread());
288 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds());
289 base::AutoLock auto_lock(lock_);
290
291 if (interpolation_state_ == INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE &&
292 time < interpolator_->GetInterpolatedTime()) {
293 return;
294 }
295
296 if (state_ == kSeeking)
297 return;
298
299 interpolator_->SetBounds(time, max_time);
300 StartClockIfWaitingForTimeUpdate_Locked();
301 }
302
303 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) {
304 DCHECK(task_runner_->BelongsToCurrentThread());
305
306 if (audio_renderer_)
307 return;
308
309 if (state_ == kSeeking)
310 return;
311
312 base::AutoLock auto_lock(lock_);
313 DCHECK_NE(interpolation_state_, INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE);
314 interpolator_->SetUpperBound(max_time);
315 }
316
317 void Pipeline::SetDuration(TimeDelta duration) { 279 void Pipeline::SetDuration(TimeDelta duration) {
318 DCHECK(IsRunning()); 280 DCHECK(IsRunning());
319 media_log_->AddEvent( 281 media_log_->AddEvent(
320 media_log_->CreateTimeEvent( 282 media_log_->CreateTimeEvent(
321 MediaLogEvent::DURATION_SET, "duration", duration)); 283 MediaLogEvent::DURATION_SET, "duration", duration));
322 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); 284 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration);
323 285
324 base::AutoLock auto_lock(lock_); 286 base::AutoLock auto_lock(lock_);
325 duration_ = duration; 287 duration_ = duration;
326 if (!duration_change_cb_.is_null()) 288 if (!duration_change_cb_.is_null())
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 metadata.has_audio = audio_renderer_; 347 metadata.has_audio = audio_renderer_;
386 metadata.has_video = video_renderer_; 348 metadata.has_video = video_renderer_;
387 metadata.timeline_offset = demuxer_->GetTimelineOffset(); 349 metadata.timeline_offset = demuxer_->GetTimelineOffset();
388 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 350 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
389 if (stream) { 351 if (stream) {
390 metadata.natural_size = 352 metadata.natural_size =
391 stream->video_decoder_config().natural_size(); 353 stream->video_decoder_config().natural_size();
392 metadata.video_rotation = stream->video_rotation(); 354 metadata.video_rotation = stream->video_rotation();
393 } 355 }
394 metadata_cb_.Run(metadata); 356 metadata_cb_.Run(metadata);
357
358 if (audio_renderer_) {
359 time_source_ = audio_renderer_.get();
360 } else {
361 wall_clock_time_source_.reset(new WallClockTimeSource());
362 time_source_ = wall_clock_time_source_.get();
363 }
395 } 364 }
396 } 365 }
397 366
398 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); 367 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
399 368
400 { 369 time_source_->SetMediaTimestamp(start_timestamp_);
401 base::AutoLock auto_lock(lock_);
402 interpolator_->SetBounds(start_timestamp_, start_timestamp_);
403 }
404 370
405 if (audio_renderer_) 371 if (audio_renderer_)
406 audio_renderer_->StartPlayingFrom(start_timestamp_); 372 audio_renderer_->StartPlaying();
407 if (video_renderer_) 373 if (video_renderer_)
408 video_renderer_->StartPlayingFrom(start_timestamp_); 374 video_renderer_->StartPlaying();
409 if (text_renderer_) 375 if (text_renderer_)
410 text_renderer_->StartPlaying(); 376 text_renderer_->StartPlaying();
411 377
412 PlaybackRateChangedTask(GetPlaybackRate()); 378 PlaybackRateChangedTask(GetPlaybackRate());
413 VolumeChangedTask(GetVolume()); 379 VolumeChangedTask(GetVolume());
414 return; 380 return;
415 381
416 case kStopping: 382 case kStopping:
417 case kStopped: 383 case kStopped:
418 case kCreated: 384 case kCreated:
(...skipping 19 matching lines...) Expand all
438 #endif 404 #endif
439 405
440 void Pipeline::DoSeek( 406 void Pipeline::DoSeek(
441 base::TimeDelta seek_timestamp, 407 base::TimeDelta seek_timestamp,
442 const PipelineStatusCB& done_cb) { 408 const PipelineStatusCB& done_cb) {
443 DCHECK(task_runner_->BelongsToCurrentThread()); 409 DCHECK(task_runner_->BelongsToCurrentThread());
444 DCHECK(!pending_callbacks_.get()); 410 DCHECK(!pending_callbacks_.get());
445 SerialRunner::Queue bound_fns; 411 SerialRunner::Queue bound_fns;
446 { 412 {
447 base::AutoLock auto_lock(lock_); 413 base::AutoLock auto_lock(lock_);
448 PauseClockAndStopRendering_Locked(); 414 PausePlayback();
449 } 415 }
450 416
451 // Pause. 417 // Pause.
452 if (text_renderer_) { 418 if (text_renderer_) {
453 bound_fns.Push(base::Bind( 419 bound_fns.Push(base::Bind(
454 &TextRenderer::Pause, base::Unretained(text_renderer_.get()))); 420 &TextRenderer::Pause, base::Unretained(text_renderer_.get())));
455 } 421 }
456 422
457 // Flush. 423 // Flush.
458 if (audio_renderer_) { 424 if (audio_renderer_) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 DoStop(base::Bind(&Pipeline::OnStopCompleted, base::Unretained(this))); 601 DoStop(base::Bind(&Pipeline::OnStopCompleted, base::Unretained(this)));
636 } 602 }
637 603
638 void Pipeline::PlaybackRateChangedTask(float playback_rate) { 604 void Pipeline::PlaybackRateChangedTask(float playback_rate) {
639 DCHECK(task_runner_->BelongsToCurrentThread()); 605 DCHECK(task_runner_->BelongsToCurrentThread());
640 606
641 // Playback rate changes are only carried out while playing. 607 // Playback rate changes are only carried out while playing.
642 if (state_ != kPlaying) 608 if (state_ != kPlaying)
643 return; 609 return;
644 610
645 { 611 time_source_->SetPlaybackRate(playback_rate_);
646 base::AutoLock auto_lock(lock_);
647 interpolator_->SetPlaybackRate(playback_rate);
648 }
649
650 if (audio_renderer_)
651 audio_renderer_->SetPlaybackRate(playback_rate_);
652 } 612 }
653 613
654 void Pipeline::VolumeChangedTask(float volume) { 614 void Pipeline::VolumeChangedTask(float volume) {
655 DCHECK(task_runner_->BelongsToCurrentThread()); 615 DCHECK(task_runner_->BelongsToCurrentThread());
656 616
657 // Volume changes are only carried out while playing. 617 // Volume changes are only carried out while playing.
658 if (state_ != kPlaying) 618 if (state_ != kPlaying)
659 return; 619 return;
660 620
661 if (audio_renderer_) 621 if (audio_renderer_)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 653
694 void Pipeline::DoAudioRendererEnded() { 654 void Pipeline::DoAudioRendererEnded() {
695 DCHECK(task_runner_->BelongsToCurrentThread()); 655 DCHECK(task_runner_->BelongsToCurrentThread());
696 656
697 if (state_ != kPlaying) 657 if (state_ != kPlaying)
698 return; 658 return;
699 659
700 DCHECK(!audio_ended_); 660 DCHECK(!audio_ended_);
701 audio_ended_ = true; 661 audio_ended_ = true;
702 662
703 // Start clock since there is no more audio to trigger clock updates.
704 {
705 base::AutoLock auto_lock(lock_);
706 interpolator_->SetUpperBound(duration_);
707 StartClockIfWaitingForTimeUpdate_Locked();
708 }
709
710 RunEndedCallbackIfNeeded(); 663 RunEndedCallbackIfNeeded();
711 } 664 }
712 665
713 void Pipeline::DoVideoRendererEnded() { 666 void Pipeline::DoVideoRendererEnded() {
714 DCHECK(task_runner_->BelongsToCurrentThread()); 667 DCHECK(task_runner_->BelongsToCurrentThread());
715 668
716 if (state_ != kPlaying) 669 if (state_ != kPlaying)
717 return; 670 return;
718 671
719 DCHECK(!video_ended_); 672 DCHECK(!video_ended_);
(...skipping 19 matching lines...) Expand all
739 692
740 if (audio_renderer_ && !audio_ended_) 693 if (audio_renderer_ && !audio_ended_)
741 return; 694 return;
742 695
743 if (video_renderer_ && !video_ended_) 696 if (video_renderer_ && !video_ended_)
744 return; 697 return;
745 698
746 if (text_renderer_ && text_renderer_->HasTracks() && !text_ended_) 699 if (text_renderer_ && text_renderer_->HasTracks() && !text_ended_)
747 return; 700 return;
748 701
749 { 702 PausePlayback();
750 base::AutoLock auto_lock(lock_);
751 PauseClockAndStopRendering_Locked();
752 interpolator_->SetBounds(duration_, duration_);
753 }
754 703
755 DCHECK_EQ(status_, PIPELINE_OK); 704 DCHECK_EQ(status_, PIPELINE_OK);
756 ended_cb_.Run(); 705 ended_cb_.Run();
757 } 706 }
758 707
759 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, 708 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream,
760 const TextTrackConfig& config) { 709 const TextTrackConfig& config) {
761 DCHECK(task_runner_->BelongsToCurrentThread()); 710 DCHECK(task_runner_->BelongsToCurrentThread());
762 // TODO(matthewjheaney): fix up text_ended_ when text stream 711 // TODO(matthewjheaney): fix up text_ended_ when text stream
763 // is added (http://crbug.com/321446). 712 // is added (http://crbug.com/321446).
(...skipping 13 matching lines...) Expand all
777 } 726 }
778 727
779 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) { 728 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) {
780 DCHECK(task_runner_->BelongsToCurrentThread()); 729 DCHECK(task_runner_->BelongsToCurrentThread());
781 730
782 audio_renderer_ = filter_collection_->GetAudioRenderer(); 731 audio_renderer_ = filter_collection_->GetAudioRenderer();
783 audio_renderer_->Initialize( 732 audio_renderer_->Initialize(
784 demuxer_->GetStream(DemuxerStream::AUDIO), 733 demuxer_->GetStream(DemuxerStream::AUDIO),
785 done_cb, 734 done_cb,
786 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 735 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
787 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)),
788 base::Bind(&Pipeline::BufferingStateChanged, base::Unretained(this), 736 base::Bind(&Pipeline::BufferingStateChanged, base::Unretained(this),
789 &audio_buffering_state_), 737 &audio_buffering_state_),
790 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)), 738 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)),
791 base::Bind(&Pipeline::SetError, base::Unretained(this))); 739 base::Bind(&Pipeline::SetError, base::Unretained(this)));
792 } 740 }
793 741
794 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { 742 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) {
795 DCHECK(task_runner_->BelongsToCurrentThread()); 743 DCHECK(task_runner_->BelongsToCurrentThread());
796 744
797 video_renderer_ = filter_collection_->GetVideoRenderer(); 745 video_renderer_ = filter_collection_->GetVideoRenderer();
798 video_renderer_->Initialize( 746 video_renderer_->Initialize(
799 demuxer_->GetStream(DemuxerStream::VIDEO), 747 demuxer_->GetStream(DemuxerStream::VIDEO),
800 demuxer_->GetLiveness() == Demuxer::LIVENESS_LIVE, 748 demuxer_->GetLiveness() == Demuxer::LIVENESS_LIVE,
801 done_cb, 749 done_cb,
802 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 750 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
803 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)),
804 base::Bind(&Pipeline::BufferingStateChanged, base::Unretained(this), 751 base::Bind(&Pipeline::BufferingStateChanged, base::Unretained(this),
805 &video_buffering_state_), 752 &video_buffering_state_),
806 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)), 753 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)),
807 base::Bind(&Pipeline::SetError, base::Unretained(this)), 754 base::Bind(&Pipeline::SetError, base::Unretained(this)),
808 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)), 755 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)),
809 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this))); 756 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this)));
810 } 757 }
811 758
812 void Pipeline::BufferingStateChanged(BufferingState* buffering_state, 759 void Pipeline::BufferingStateChanged(BufferingState* buffering_state,
813 BufferingState new_buffering_state) { 760 BufferingState new_buffering_state) {
814 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " 761 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", "
815 << " " << new_buffering_state << ") " 762 << " " << new_buffering_state << ") "
816 << (buffering_state == &audio_buffering_state_ ? "audio" : "video"); 763 << (buffering_state == &audio_buffering_state_ ? "audio" : "video");
817 DCHECK(task_runner_->BelongsToCurrentThread()); 764 DCHECK(task_runner_->BelongsToCurrentThread());
818 bool was_waiting_for_enough_data = WaitingForEnoughData(); 765 bool was_waiting_for_enough_data = WaitingForEnoughData();
819 766
820 *buffering_state = new_buffering_state; 767 *buffering_state = new_buffering_state;
821 768
769 #if 0
822 // Disable underflow by ignoring updates that renderers have ran out of data 770 // Disable underflow by ignoring updates that renderers have ran out of data
823 // after we have started the clock. 771 // after we have started the clock.
824 if (state_ == kPlaying && underflow_disabled_for_testing_ && 772 if (state_ == kPlaying && underflow_disabled_for_testing_ &&
825 interpolation_state_ != INTERPOLATION_STOPPED) { 773 interpolation_state_ != INTERPOLATION_STOPPED) {
826 return; 774 return;
827 } 775 }
776 #endif
828 777
829 // Renderer underflowed. 778 // Renderer underflowed.
830 if (!was_waiting_for_enough_data && WaitingForEnoughData()) { 779 if (!was_waiting_for_enough_data && WaitingForEnoughData()) {
831 PausePlayback(); 780 PausePlayback();
832 781
833 // TODO(scherkus): Fire BUFFERING_HAVE_NOTHING callback to alert clients of 782 // TODO(scherkus): Fire BUFFERING_HAVE_NOTHING callback to alert clients of
834 // underflow state http://crbug.com/144683 783 // underflow state http://crbug.com/144683
835 return; 784 return;
836 } 785 }
837 786
(...skipping 15 matching lines...) Expand all
853 return true; 802 return true;
854 return false; 803 return false;
855 } 804 }
856 805
857 void Pipeline::PausePlayback() { 806 void Pipeline::PausePlayback() {
858 DVLOG(1) << __FUNCTION__; 807 DVLOG(1) << __FUNCTION__;
859 DCHECK_EQ(state_, kPlaying); 808 DCHECK_EQ(state_, kPlaying);
860 DCHECK(WaitingForEnoughData()); 809 DCHECK(WaitingForEnoughData());
861 DCHECK(task_runner_->BelongsToCurrentThread()); 810 DCHECK(task_runner_->BelongsToCurrentThread());
862 811
863 base::AutoLock auto_lock(lock_); 812 time_source_->StopTicking();
864 PauseClockAndStopRendering_Locked();
865 } 813 }
866 814
867 void Pipeline::StartPlayback() { 815 void Pipeline::StartPlayback() {
868 DVLOG(1) << __FUNCTION__; 816 DVLOG(1) << __FUNCTION__;
869 DCHECK_EQ(state_, kPlaying); 817 DCHECK_EQ(state_, kPlaying);
870 DCHECK_EQ(interpolation_state_, INTERPOLATION_STOPPED);
871 DCHECK(!WaitingForEnoughData()); 818 DCHECK(!WaitingForEnoughData());
872 DCHECK(task_runner_->BelongsToCurrentThread()); 819 DCHECK(task_runner_->BelongsToCurrentThread());
873 820
874 if (audio_renderer_) { 821 time_source_->StartTicking();
875 // We use audio stream to update the clock. So if there is such a
876 // stream, we pause the clock until we receive a valid timestamp.
877 base::AutoLock auto_lock(lock_);
878 interpolation_state_ = INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE;
879 audio_renderer_->StartRendering();
880 } else {
881 base::AutoLock auto_lock(lock_);
882 interpolation_state_ = INTERPOLATION_STARTED;
883 interpolator_->SetUpperBound(duration_);
884 interpolator_->StartInterpolating();
885 }
886 }
887
888 void Pipeline::PauseClockAndStopRendering_Locked() {
889 lock_.AssertAcquired();
890 switch (interpolation_state_) {
891 case INTERPOLATION_STOPPED:
892 return;
893
894 case INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE:
895 audio_renderer_->StopRendering();
896 break;
897
898 case INTERPOLATION_STARTED:
899 if (audio_renderer_)
900 audio_renderer_->StopRendering();
901 interpolator_->StopInterpolating();
902 break;
903 }
904
905 interpolation_state_ = INTERPOLATION_STOPPED;
906 }
907
908 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
909 lock_.AssertAcquired();
910 if (interpolation_state_ != INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE)
911 return;
912
913 interpolation_state_ = INTERPOLATION_STARTED;
914 interpolator_->StartInterpolating();
915 } 822 }
916 823
917 } // namespace media 824 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline.h ('k') | media/base/time_source.h » ('j') | media/base/time_source.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698