OLD | NEW |
---|---|
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" |
(...skipping 27 matching lines...) Expand all Loading... | |
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 total_bytes_(0), | 42 total_bytes_(0), |
43 volume_(1.0f), | 43 volume_(1.0f), |
44 playback_rate_(0.0f), | 44 playback_rate_(0.0f), |
45 clock_(new Clock(&default_tick_clock_)), | 45 clock_(new Clock(&default_tick_clock_)), |
46 waiting_for_clock_update_(false), | 46 waiting_for_clock_update_(false), |
47 status_(PIPELINE_OK), | 47 status_(PIPELINE_OK), |
48 has_audio_(false), | |
49 has_video_(false), | |
50 state_(kCreated), | 48 state_(kCreated), |
51 audio_ended_(false), | 49 audio_ended_(false), |
52 video_ended_(false), | 50 video_ended_(false), |
53 text_ended_(false), | 51 text_ended_(false), |
54 audio_disabled_(false), | 52 audio_disabled_(false), |
55 demuxer_(NULL), | 53 demuxer_(NULL), |
56 creation_time_(default_tick_clock_.NowTicks()) { | 54 creation_time_(default_tick_clock_.NowTicks()) { |
57 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 55 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
58 media_log_->AddEvent( | 56 media_log_->AddEvent( |
59 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 57 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); |
60 } | 58 } |
61 | 59 |
62 Pipeline::~Pipeline() { | 60 Pipeline::~Pipeline() { |
63 DCHECK(thread_checker_.CalledOnValidThread()) | 61 DCHECK(thread_checker_.CalledOnValidThread()) |
64 << "Pipeline must be destroyed on same thread that created it"; | 62 << "Pipeline must be destroyed on same thread that created it"; |
65 DCHECK(!running_) << "Stop() must complete before destroying object"; | 63 DCHECK(!running_) << "Stop() must complete before destroying object"; |
66 DCHECK(stop_cb_.is_null()); | 64 DCHECK(stop_cb_.is_null()); |
67 DCHECK(seek_cb_.is_null()); | 65 DCHECK(seek_cb_.is_null()); |
68 | 66 |
69 media_log_->AddEvent( | 67 media_log_->AddEvent( |
70 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); | 68 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); |
71 } | 69 } |
72 | 70 |
73 void Pipeline::Start(scoped_ptr<FilterCollection> collection, | 71 void Pipeline::Start(scoped_ptr<FilterCollection> collection, |
74 const base::Closure& ended_cb, | 72 const base::Closure& ended_cb, |
75 const PipelineStatusCB& error_cb, | 73 const PipelineStatusCB& error_cb, |
76 const PipelineStatusCB& seek_cb, | 74 const PipelineStatusCB& seek_cb, |
77 const BufferingStateCB& buffering_state_cb, | 75 const PipelineMetadataCB& metadata_cb, |
76 const base::Closure& preroll_completed_cb, | |
78 const base::Closure& duration_change_cb) { | 77 const base::Closure& duration_change_cb) { |
78 DCHECK(!ended_cb.is_null()); | |
79 DCHECK(!error_cb.is_null()); | |
80 DCHECK(!seek_cb.is_null()); | |
81 DCHECK(!metadata_cb.is_null()); | |
82 DCHECK(!preroll_completed_cb.is_null()); | |
83 | |
79 base::AutoLock auto_lock(lock_); | 84 base::AutoLock auto_lock(lock_); |
80 CHECK(!running_) << "Media pipeline is already running"; | 85 CHECK(!running_) << "Media pipeline is already running"; |
81 DCHECK(!buffering_state_cb.is_null()); | 86 running_ = true; |
82 | 87 |
83 running_ = true; | 88 filter_collection_ = collection.Pass(); |
84 task_runner_->PostTask(FROM_HERE, base::Bind( | 89 ended_cb_ = ended_cb; |
85 &Pipeline::StartTask, base::Unretained(this), base::Passed(&collection), | 90 error_cb_ = error_cb; |
86 ended_cb, error_cb, seek_cb, buffering_state_cb, duration_change_cb)); | 91 seek_cb_ = seek_cb; |
92 metadata_cb_ = metadata_cb; | |
93 preroll_completed_cb_ = preroll_completed_cb; | |
94 duration_change_cb_ = duration_change_cb; | |
95 | |
96 task_runner_->PostTask( | |
97 FROM_HERE, base::Bind(&Pipeline::StartTask, base::Unretained(this))); | |
87 } | 98 } |
88 | 99 |
89 void Pipeline::Stop(const base::Closure& stop_cb) { | 100 void Pipeline::Stop(const base::Closure& stop_cb) { |
90 base::AutoLock auto_lock(lock_); | 101 base::AutoLock auto_lock(lock_); |
91 task_runner_->PostTask(FROM_HERE, base::Bind( | 102 task_runner_->PostTask(FROM_HERE, base::Bind( |
92 &Pipeline::StopTask, base::Unretained(this), stop_cb)); | 103 &Pipeline::StopTask, base::Unretained(this), stop_cb)); |
93 } | 104 } |
94 | 105 |
95 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { | 106 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { |
96 base::AutoLock auto_lock(lock_); | 107 base::AutoLock auto_lock(lock_); |
97 if (!running_) { | 108 if (!running_) { |
98 NOTREACHED() << "Media pipeline isn't running"; | 109 NOTREACHED() << "Media pipeline isn't running"; |
99 return; | 110 return; |
100 } | 111 } |
101 | 112 |
102 task_runner_->PostTask(FROM_HERE, base::Bind( | 113 task_runner_->PostTask(FROM_HERE, base::Bind( |
103 &Pipeline::SeekTask, base::Unretained(this), time, seek_cb)); | 114 &Pipeline::SeekTask, base::Unretained(this), time, seek_cb)); |
104 } | 115 } |
105 | 116 |
106 bool Pipeline::IsRunning() const { | 117 bool Pipeline::IsRunning() const { |
107 base::AutoLock auto_lock(lock_); | 118 base::AutoLock auto_lock(lock_); |
108 return running_; | 119 return running_; |
109 } | 120 } |
110 | 121 |
111 bool Pipeline::HasAudio() const { | |
112 base::AutoLock auto_lock(lock_); | |
113 return has_audio_; | |
114 } | |
115 | |
116 bool Pipeline::HasVideo() const { | |
117 base::AutoLock auto_lock(lock_); | |
118 return has_video_; | |
119 } | |
120 | |
121 float Pipeline::GetPlaybackRate() const { | 122 float Pipeline::GetPlaybackRate() const { |
122 base::AutoLock auto_lock(lock_); | 123 base::AutoLock auto_lock(lock_); |
123 return playback_rate_; | 124 return playback_rate_; |
124 } | 125 } |
125 | 126 |
126 void Pipeline::SetPlaybackRate(float playback_rate) { | 127 void Pipeline::SetPlaybackRate(float playback_rate) { |
127 if (playback_rate < 0.0f) | 128 if (playback_rate < 0.0f) |
128 return; | 129 return; |
129 | 130 |
130 base::AutoLock auto_lock(lock_); | 131 base::AutoLock auto_lock(lock_); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 TimeDelta Pipeline::GetMediaDuration() const { | 182 TimeDelta Pipeline::GetMediaDuration() const { |
182 base::AutoLock auto_lock(lock_); | 183 base::AutoLock auto_lock(lock_); |
183 return clock_->Duration(); | 184 return clock_->Duration(); |
184 } | 185 } |
185 | 186 |
186 int64 Pipeline::GetTotalBytes() const { | 187 int64 Pipeline::GetTotalBytes() const { |
187 base::AutoLock auto_lock(lock_); | 188 base::AutoLock auto_lock(lock_); |
188 return total_bytes_; | 189 return total_bytes_; |
189 } | 190 } |
190 | 191 |
191 gfx::Size Pipeline::GetInitialNaturalSize() const { | |
192 base::AutoLock auto_lock(lock_); | |
193 return initial_natural_size_; | |
194 } | |
195 | |
196 bool Pipeline::DidLoadingProgress() const { | 192 bool Pipeline::DidLoadingProgress() const { |
197 base::AutoLock auto_lock(lock_); | 193 base::AutoLock auto_lock(lock_); |
198 bool ret = did_loading_progress_; | 194 bool ret = did_loading_progress_; |
199 did_loading_progress_ = false; | 195 did_loading_progress_ = false; |
200 return ret; | 196 return ret; |
201 } | 197 } |
202 | 198 |
203 PipelineStatistics Pipeline::GetStatistics() const { | 199 PipelineStatistics Pipeline::GetStatistics() const { |
204 base::AutoLock auto_lock(lock_); | 200 base::AutoLock auto_lock(lock_); |
205 return statistics_; | 201 return statistics_; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 &Pipeline::AudioDisabledTask, base::Unretained(this))); | 322 &Pipeline::AudioDisabledTask, base::Unretained(this))); |
327 media_log_->AddEvent( | 323 media_log_->AddEvent( |
328 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 324 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); |
329 } | 325 } |
330 | 326 |
331 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 327 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
332 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); | 328 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); |
333 DCHECK(IsRunning()); | 329 DCHECK(IsRunning()); |
334 base::AutoLock auto_lock(lock_); | 330 base::AutoLock auto_lock(lock_); |
335 | 331 |
336 if (!has_audio_) | 332 if (audio_disabled_) |
337 return; | 333 return; |
334 | |
338 if (waiting_for_clock_update_ && time < clock_->Elapsed()) | 335 if (waiting_for_clock_update_ && time < clock_->Elapsed()) |
339 return; | 336 return; |
340 | 337 |
341 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see | 338 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see |
342 // http://crbug.com/137973 | 339 // http://crbug.com/137973 |
343 if (state_ == kSeeking) | 340 if (state_ == kSeeking) |
344 return; | 341 return; |
345 | 342 |
346 clock_->SetTime(time, max_time); | 343 clock_->SetTime(time, max_time); |
347 StartClockIfWaitingForTimeUpdate_Locked(); | 344 StartClockIfWaitingForTimeUpdate_Locked(); |
348 } | 345 } |
349 | 346 |
350 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { | 347 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { |
351 DCHECK(IsRunning()); | 348 DCHECK(IsRunning()); |
352 base::AutoLock auto_lock(lock_); | 349 base::AutoLock auto_lock(lock_); |
353 | 350 |
354 if (has_audio_) | 351 if (audio_renderer_ && !audio_disabled_) |
355 return; | 352 return; |
356 | 353 |
357 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see | 354 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see |
358 // http://crbug.com/137973 | 355 // http://crbug.com/137973 |
359 if (state_ == kSeeking) | 356 if (state_ == kSeeking) |
360 return; | 357 return; |
361 | 358 |
362 DCHECK(!waiting_for_clock_update_); | 359 DCHECK(!waiting_for_clock_update_); |
363 clock_->SetMaxTime(max_time); | 360 clock_->SetMaxTime(max_time); |
364 } | 361 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
455 case kInitVideoRenderer: | 452 case kInitVideoRenderer: |
456 return InitializeVideoRenderer(done_cb); | 453 return InitializeVideoRenderer(done_cb); |
457 | 454 |
458 case kInitPrerolling: | 455 case kInitPrerolling: |
459 filter_collection_.reset(); | 456 filter_collection_.reset(); |
460 { | 457 { |
461 base::AutoLock l(lock_); | 458 base::AutoLock l(lock_); |
462 // We do not want to start the clock running. We only want to set the | 459 // We do not want to start the clock running. We only want to set the |
463 // base media time so our timestamp calculations will be correct. | 460 // base media time so our timestamp calculations will be correct. |
464 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); | 461 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); |
465 | |
466 // TODO(scherkus): |has_audio_| should be true no matter what -- | |
467 // otherwise people with muted/disabled sound cards will make our | |
468 // default controls look as if every video doesn't contain an audio | |
469 // track. | |
470 has_audio_ = audio_renderer_ != NULL && !audio_disabled_; | |
471 has_video_ = video_renderer_ != NULL; | |
472 } | 462 } |
473 if (!audio_renderer_ && !video_renderer_) { | 463 if (!audio_renderer_ && !video_renderer_) { |
474 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); | 464 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); |
475 return; | 465 return; |
476 } | 466 } |
477 | 467 |
478 buffering_state_cb_.Run(kHaveMetadata); | 468 { |
469 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); | |
470 gfx::Size natural_size = stream->video_decoder_config().natural_size(); | |
scherkus (not reviewing)
2014/03/21 23:36:36
we should still check whether |stream| exists (the
| |
471 | |
472 PipelineMetadata metadata; | |
473 metadata.has_audio = audio_renderer_; | |
474 metadata.has_video = video_renderer_; | |
475 metadata.natural_size = natural_size; | |
476 metadata_cb_.Run(metadata); | |
477 } | |
479 | 478 |
480 return DoInitialPreroll(done_cb); | 479 return DoInitialPreroll(done_cb); |
481 | 480 |
482 case kStarting: | 481 case kStarting: |
483 return DoPlay(done_cb); | 482 return DoPlay(done_cb); |
484 | 483 |
485 case kStarted: | 484 case kStarted: |
486 { | 485 { |
487 base::AutoLock l(lock_); | 486 base::AutoLock l(lock_); |
488 // We use audio stream to update the clock. So if there is such a | 487 // We use audio stream to update the clock. So if there is such a |
489 // stream, we pause the clock until we receive a valid timestamp. | 488 // stream, we pause the clock until we receive a valid timestamp. |
490 waiting_for_clock_update_ = true; | 489 waiting_for_clock_update_ = true; |
491 if (!has_audio_) { | 490 if (!audio_renderer_ || audio_disabled_) { |
492 clock_->SetMaxTime(clock_->Duration()); | 491 clock_->SetMaxTime(clock_->Duration()); |
493 StartClockIfWaitingForTimeUpdate_Locked(); | 492 StartClockIfWaitingForTimeUpdate_Locked(); |
494 } | 493 } |
495 } | 494 } |
496 | 495 |
497 DCHECK(!seek_cb_.is_null()); | 496 DCHECK(!seek_cb_.is_null()); |
498 DCHECK_EQ(status_, PIPELINE_OK); | 497 DCHECK_EQ(status_, PIPELINE_OK); |
499 | 498 |
500 // Fire canplaythrough immediately after playback begins because of | 499 // Fire canplaythrough immediately after playback begins because of |
501 // crbug.com/106480. | 500 // crbug.com/106480. |
502 // TODO(vrk): set ready state to HaveFutureData when bug above is fixed. | 501 // TODO(vrk): set ready state to HaveFutureData when bug above is fixed. |
503 buffering_state_cb_.Run(kPrerollCompleted); | 502 preroll_completed_cb_.Run(); |
504 return base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | 503 return base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); |
505 | 504 |
506 case kStopping: | 505 case kStopping: |
507 case kStopped: | 506 case kStopped: |
508 case kCreated: | 507 case kCreated: |
509 case kSeeking: | 508 case kSeeking: |
510 NOTREACHED() << "State has no transition: " << state_; | 509 NOTREACHED() << "State has no transition: " << state_; |
511 return; | 510 return; |
512 } | 511 } |
513 } | 512 } |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 | 723 |
725 // Called from any thread. | 724 // Called from any thread. |
726 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { | 725 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { |
727 base::AutoLock auto_lock(lock_); | 726 base::AutoLock auto_lock(lock_); |
728 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; | 727 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; |
729 statistics_.video_bytes_decoded += stats.video_bytes_decoded; | 728 statistics_.video_bytes_decoded += stats.video_bytes_decoded; |
730 statistics_.video_frames_decoded += stats.video_frames_decoded; | 729 statistics_.video_frames_decoded += stats.video_frames_decoded; |
731 statistics_.video_frames_dropped += stats.video_frames_dropped; | 730 statistics_.video_frames_dropped += stats.video_frames_dropped; |
732 } | 731 } |
733 | 732 |
734 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, | 733 void Pipeline::StartTask() { |
735 const base::Closure& ended_cb, | |
736 const PipelineStatusCB& error_cb, | |
737 const PipelineStatusCB& seek_cb, | |
738 const BufferingStateCB& buffering_state_cb, | |
739 const base::Closure& duration_change_cb) { | |
740 DCHECK(task_runner_->BelongsToCurrentThread()); | 734 DCHECK(task_runner_->BelongsToCurrentThread()); |
741 CHECK_EQ(kCreated, state_) | 735 CHECK_EQ(kCreated, state_) |
742 << "Media pipeline cannot be started more than once"; | 736 << "Media pipeline cannot be started more than once"; |
743 | 737 |
744 filter_collection_ = filter_collection.Pass(); | |
745 ended_cb_ = ended_cb; | |
746 error_cb_ = error_cb; | |
747 seek_cb_ = seek_cb; | |
748 buffering_state_cb_ = buffering_state_cb; | |
749 duration_change_cb_ = duration_change_cb; | |
750 | |
751 text_renderer_ = filter_collection_->GetTextRenderer(); | 738 text_renderer_ = filter_collection_->GetTextRenderer(); |
752 | 739 |
753 if (text_renderer_) { | 740 if (text_renderer_) { |
754 text_renderer_->Initialize( | 741 text_renderer_->Initialize( |
755 base::Bind(&Pipeline::OnTextRendererEnded, base::Unretained(this))); | 742 base::Bind(&Pipeline::OnTextRendererEnded, base::Unretained(this))); |
756 } | 743 } |
757 | 744 |
758 StateTransitionTask(PIPELINE_OK); | 745 StateTransitionTask(PIPELINE_OK); |
759 } | 746 } |
760 | 747 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
918 } | 905 } |
919 | 906 |
920 DCHECK_EQ(status_, PIPELINE_OK); | 907 DCHECK_EQ(status_, PIPELINE_OK); |
921 ended_cb_.Run(); | 908 ended_cb_.Run(); |
922 } | 909 } |
923 | 910 |
924 void Pipeline::AudioDisabledTask() { | 911 void Pipeline::AudioDisabledTask() { |
925 DCHECK(task_runner_->BelongsToCurrentThread()); | 912 DCHECK(task_runner_->BelongsToCurrentThread()); |
926 | 913 |
927 base::AutoLock auto_lock(lock_); | 914 base::AutoLock auto_lock(lock_); |
928 has_audio_ = false; | |
929 audio_disabled_ = true; | 915 audio_disabled_ = true; |
930 | 916 |
931 // Notify our demuxer that we're no longer rendering audio. | 917 // Notify our demuxer that we're no longer rendering audio. |
932 demuxer_->OnAudioRendererDisabled(); | 918 demuxer_->OnAudioRendererDisabled(); |
933 | 919 |
934 // Start clock since there is no more audio to trigger clock updates. | 920 // Start clock since there is no more audio to trigger clock updates. |
935 clock_->SetMaxTime(clock_->Duration()); | 921 clock_->SetMaxTime(clock_->Duration()); |
936 StartClockIfWaitingForTimeUpdate_Locked(); | 922 StartClockIfWaitingForTimeUpdate_Locked(); |
937 } | 923 } |
938 | 924 |
(...skipping 28 matching lines...) Expand all Loading... | |
967 base::Bind(&Pipeline::OnAudioUnderflow, base::Unretained(this)), | 953 base::Bind(&Pipeline::OnAudioUnderflow, base::Unretained(this)), |
968 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)), | 954 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)), |
969 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)), | 955 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)), |
970 base::Bind(&Pipeline::OnAudioDisabled, base::Unretained(this)), | 956 base::Bind(&Pipeline::OnAudioDisabled, base::Unretained(this)), |
971 base::Bind(&Pipeline::SetError, base::Unretained(this))); | 957 base::Bind(&Pipeline::SetError, base::Unretained(this))); |
972 } | 958 } |
973 | 959 |
974 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { | 960 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { |
975 DCHECK(task_runner_->BelongsToCurrentThread()); | 961 DCHECK(task_runner_->BelongsToCurrentThread()); |
976 | 962 |
977 // Get an initial natural size so we have something when we signal | |
978 // the kHaveMetadata buffering state. | |
979 // | |
980 // TODO(acolwell): We have to query demuxer outside of the lock to prevent a | |
981 // deadlock between ChunkDemuxer and Pipeline. See http://crbug.com/334325 for | |
982 // ideas on removing locking from ChunkDemuxer. | |
983 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); | |
984 gfx::Size initial_natural_size = | |
985 stream->video_decoder_config().natural_size(); | |
986 { | |
987 base::AutoLock l(lock_); | |
988 initial_natural_size_ = initial_natural_size; | |
989 } | |
990 | |
991 video_renderer_ = filter_collection_->GetVideoRenderer(); | 963 video_renderer_ = filter_collection_->GetVideoRenderer(); |
992 video_renderer_->Initialize( | 964 video_renderer_->Initialize( |
993 stream, | 965 demuxer_->GetStream(DemuxerStream::VIDEO), |
994 done_cb, | 966 done_cb, |
995 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), | 967 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), |
996 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)), | 968 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)), |
997 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)), | 969 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)), |
998 base::Bind(&Pipeline::SetError, base::Unretained(this)), | 970 base::Bind(&Pipeline::SetError, base::Unretained(this)), |
999 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)), | 971 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)), |
1000 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this))); | 972 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this))); |
1001 } | 973 } |
1002 | 974 |
1003 void Pipeline::OnAudioUnderflow() { | 975 void Pipeline::OnAudioUnderflow() { |
(...skipping 13 matching lines...) Expand all Loading... | |
1017 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 989 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1018 lock_.AssertAcquired(); | 990 lock_.AssertAcquired(); |
1019 if (!waiting_for_clock_update_) | 991 if (!waiting_for_clock_update_) |
1020 return; | 992 return; |
1021 | 993 |
1022 waiting_for_clock_update_ = false; | 994 waiting_for_clock_update_ = false; |
1023 clock_->Play(); | 995 clock_->Play(); |
1024 } | 996 } |
1025 | 997 |
1026 } // namespace media | 998 } // namespace media |
OLD | NEW |