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

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

Issue 423073012: Pipeline: Use WeakPtr for DemuxerHost Calls and Tasks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: drop weak_this_for_demuxer_ Created 6 years, 4 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
« no previous file with comments | « no previous file | media/base/pipeline_unittest.cc » ('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 (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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 DCHECK(thread_checker_.CalledOnValidThread()) 65 DCHECK(thread_checker_.CalledOnValidThread())
66 << "Pipeline must be destroyed on same thread that created it"; 66 << "Pipeline must be destroyed on same thread that created it";
67 DCHECK(!running_) << "Stop() must complete before destroying object"; 67 DCHECK(!running_) << "Stop() must complete before destroying object";
68 DCHECK(stop_cb_.is_null()); 68 DCHECK(stop_cb_.is_null());
69 DCHECK(seek_cb_.is_null()); 69 DCHECK(seek_cb_.is_null());
70 70
71 media_log_->AddEvent( 71 media_log_->AddEvent(
72 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); 72 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED));
73 } 73 }
74 74
75 // The base::Unretained(this) in these functions are safe because:
76 // 1, No public methods (except for the dtor) should be called after Stop().
77 // 2, |this| will not be destructed until the stop callback is fired.
78 // 3, Stop() also posts StopTask(), hence all XxxTask() will be executed before
79 // StopTask(), and therefore before the dtor.
80
81 void Pipeline::Start(scoped_ptr<FilterCollection> collection, 75 void Pipeline::Start(scoped_ptr<FilterCollection> collection,
82 const base::Closure& ended_cb, 76 const base::Closure& ended_cb,
83 const PipelineStatusCB& error_cb, 77 const PipelineStatusCB& error_cb,
84 const PipelineStatusCB& seek_cb, 78 const PipelineStatusCB& seek_cb,
85 const PipelineMetadataCB& metadata_cb, 79 const PipelineMetadataCB& metadata_cb,
86 const BufferingStateCB& buffering_state_cb, 80 const BufferingStateCB& buffering_state_cb,
87 const base::Closure& duration_change_cb) { 81 const base::Closure& duration_change_cb) {
88 DCHECK(!ended_cb.is_null()); 82 DCHECK(!ended_cb.is_null());
89 DCHECK(!error_cb.is_null()); 83 DCHECK(!error_cb.is_null());
90 DCHECK(!seek_cb.is_null()); 84 DCHECK(!seek_cb.is_null());
91 DCHECK(!metadata_cb.is_null()); 85 DCHECK(!metadata_cb.is_null());
92 DCHECK(!buffering_state_cb.is_null()); 86 DCHECK(!buffering_state_cb.is_null());
93 87
94 base::AutoLock auto_lock(lock_); 88 base::AutoLock auto_lock(lock_);
95 CHECK(!running_) << "Media pipeline is already running"; 89 CHECK(!running_) << "Media pipeline is already running";
96 running_ = true; 90 running_ = true;
97 91
98 filter_collection_ = collection.Pass(); 92 filter_collection_ = collection.Pass();
99 ended_cb_ = ended_cb; 93 ended_cb_ = ended_cb;
100 error_cb_ = error_cb; 94 error_cb_ = error_cb;
101 seek_cb_ = seek_cb; 95 seek_cb_ = seek_cb;
102 metadata_cb_ = metadata_cb; 96 metadata_cb_ = metadata_cb;
103 buffering_state_cb_ = buffering_state_cb; 97 buffering_state_cb_ = buffering_state_cb;
104 duration_change_cb_ = duration_change_cb; 98 duration_change_cb_ = duration_change_cb;
105 99
106 task_runner_->PostTask( 100 task_runner_->PostTask(
107 FROM_HERE, base::Bind(&Pipeline::StartTask, base::Unretained(this))); 101 FROM_HERE, base::Bind(&Pipeline::StartTask, weak_factory_.GetWeakPtr()));
108 } 102 }
109 103
110 void Pipeline::Stop(const base::Closure& stop_cb) { 104 void Pipeline::Stop(const base::Closure& stop_cb) {
111 DVLOG(2) << __FUNCTION__; 105 DVLOG(2) << __FUNCTION__;
112 task_runner_->PostTask( 106 task_runner_->PostTask(
113 FROM_HERE, 107 FROM_HERE,
114 base::Bind(&Pipeline::StopTask, base::Unretained(this), stop_cb)); 108 base::Bind(&Pipeline::StopTask, weak_factory_.GetWeakPtr(), stop_cb));
115 } 109 }
116 110
117 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { 111 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
118 base::AutoLock auto_lock(lock_); 112 base::AutoLock auto_lock(lock_);
119 if (!running_) { 113 if (!running_) {
120 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek()."; 114 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek().";
121 return; 115 return;
122 } 116 }
123 117
124 task_runner_->PostTask( 118 task_runner_->PostTask(
125 FROM_HERE, 119 FROM_HERE,
126 base::Bind(&Pipeline::SeekTask, base::Unretained(this), time, seek_cb)); 120 base::Bind(
121 &Pipeline::SeekTask, weak_factory_.GetWeakPtr(), time, seek_cb));
127 } 122 }
128 123
129 bool Pipeline::IsRunning() const { 124 bool Pipeline::IsRunning() const {
130 base::AutoLock auto_lock(lock_); 125 base::AutoLock auto_lock(lock_);
131 return running_; 126 return running_;
132 } 127 }
133 128
134 float Pipeline::GetPlaybackRate() const { 129 float Pipeline::GetPlaybackRate() const {
135 base::AutoLock auto_lock(lock_); 130 base::AutoLock auto_lock(lock_);
136 return playback_rate_; 131 return playback_rate_;
137 } 132 }
138 133
139 void Pipeline::SetPlaybackRate(float playback_rate) { 134 void Pipeline::SetPlaybackRate(float playback_rate) {
140 if (playback_rate < 0.0f) 135 if (playback_rate < 0.0f)
141 return; 136 return;
142 137
143 base::AutoLock auto_lock(lock_); 138 base::AutoLock auto_lock(lock_);
144 playback_rate_ = playback_rate; 139 playback_rate_ = playback_rate;
145 if (running_) { 140 if (running_) {
146 task_runner_->PostTask(FROM_HERE, 141 task_runner_->PostTask(FROM_HERE,
147 base::Bind(&Pipeline::PlaybackRateChangedTask, 142 base::Bind(&Pipeline::PlaybackRateChangedTask,
148 base::Unretained(this), 143 weak_factory_.GetWeakPtr(),
149 playback_rate)); 144 playback_rate));
150 } 145 }
151 } 146 }
152 147
153 float Pipeline::GetVolume() const { 148 float Pipeline::GetVolume() const {
154 base::AutoLock auto_lock(lock_); 149 base::AutoLock auto_lock(lock_);
155 return volume_; 150 return volume_;
156 } 151 }
157 152
158 void Pipeline::SetVolume(float volume) { 153 void Pipeline::SetVolume(float volume) {
159 if (volume < 0.0f || volume > 1.0f) 154 if (volume < 0.0f || volume > 1.0f)
160 return; 155 return;
161 156
162 base::AutoLock auto_lock(lock_); 157 base::AutoLock auto_lock(lock_);
163 volume_ = volume; 158 volume_ = volume;
164 if (running_) { 159 if (running_) {
165 task_runner_->PostTask( 160 task_runner_->PostTask(
166 FROM_HERE, 161 FROM_HERE,
167 base::Bind( 162 base::Bind(
168 &Pipeline::VolumeChangedTask, base::Unretained(this), volume)); 163 &Pipeline::VolumeChangedTask, weak_factory_.GetWeakPtr(), volume));
169 } 164 }
170 } 165 }
171 166
172 TimeDelta Pipeline::GetMediaTime() const { 167 TimeDelta Pipeline::GetMediaTime() const {
173 base::AutoLock auto_lock(lock_); 168 base::AutoLock auto_lock(lock_);
174 return std::min(interpolator_->GetInterpolatedTime(), duration_); 169 return std::min(interpolator_->GetInterpolatedTime(), duration_);
175 } 170 }
176 171
177 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { 172 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const {
178 base::AutoLock auto_lock(lock_); 173 base::AutoLock auto_lock(lock_);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 257
263 case kPlaying: 258 case kPlaying:
264 case kStopping: 259 case kStopping:
265 case kStopped: 260 case kStopped:
266 break; 261 break;
267 } 262 }
268 NOTREACHED() << "State has no transition: " << state_; 263 NOTREACHED() << "State has no transition: " << state_;
269 return state_; 264 return state_;
270 } 265 }
271 266
272 // The use of base::Unretained(this) in the following 3 functions is safe
273 // because these functions are called by the Demuxer directly, before the stop
274 // callback is posted by the Demuxer. So the posted tasks will always be
275 // executed before the stop callback is executed, and hence before the Pipeline
276 // is destructed.
277
278 void Pipeline::OnDemuxerError(PipelineStatus error) { 267 void Pipeline::OnDemuxerError(PipelineStatus error) {
279 task_runner_->PostTask(FROM_HERE, 268 task_runner_->PostTask(FROM_HERE,
280 base::Bind(&Pipeline::ErrorChangedTask, 269 base::Bind(&Pipeline::ErrorChangedTask,
281 base::Unretained(this), 270 weak_factory_.GetWeakPtr(),
282 error)); 271 error));
283 } 272 }
284 273
285 void Pipeline::AddTextStream(DemuxerStream* text_stream, 274 void Pipeline::AddTextStream(DemuxerStream* text_stream,
286 const TextTrackConfig& config) { 275 const TextTrackConfig& config) {
287 task_runner_->PostTask(FROM_HERE, 276 task_runner_->PostTask(FROM_HERE,
288 base::Bind(&Pipeline::AddTextStreamTask, 277 base::Bind(&Pipeline::AddTextStreamTask,
289 base::Unretained(this), 278 weak_factory_.GetWeakPtr(),
290 text_stream, 279 text_stream,
291 config)); 280 config));
292 } 281 }
293 282
294 void Pipeline::RemoveTextStream(DemuxerStream* text_stream) { 283 void Pipeline::RemoveTextStream(DemuxerStream* text_stream) {
295 task_runner_->PostTask(FROM_HERE, 284 task_runner_->PostTask(FROM_HERE,
296 base::Bind(&Pipeline::RemoveTextStreamTask, 285 base::Bind(&Pipeline::RemoveTextStreamTask,
297 base::Unretained(this), 286 weak_factory_.GetWeakPtr(),
298 text_stream)); 287 text_stream));
299 } 288 }
300 289
301 void Pipeline::OnError(PipelineStatus error) { 290 void Pipeline::OnError(PipelineStatus error) {
302 DCHECK(task_runner_->BelongsToCurrentThread()); 291 DCHECK(task_runner_->BelongsToCurrentThread());
303 DCHECK(IsRunning()); 292 DCHECK(IsRunning());
304 DCHECK_NE(PIPELINE_OK, error); 293 DCHECK_NE(PIPELINE_OK, error);
305 VLOG(1) << "Media pipeline error: " << error; 294 VLOG(1) << "Media pipeline error: " << error;
306 295
307 task_runner_->PostTask(FROM_HERE, base::Bind( 296 task_runner_->PostTask(FROM_HERE, base::Bind(
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 demuxer_ = NULL; 540 demuxer_ = NULL;
552 541
553 // If we stop during initialization/seeking we want to run |seek_cb_| 542 // If we stop during initialization/seeking we want to run |seek_cb_|
554 // followed by |stop_cb_| so we don't leave outstanding callbacks around. 543 // followed by |stop_cb_| so we don't leave outstanding callbacks around.
555 if (!seek_cb_.is_null()) { 544 if (!seek_cb_.is_null()) {
556 base::ResetAndReturn(&seek_cb_).Run(status_); 545 base::ResetAndReturn(&seek_cb_).Run(status_);
557 error_cb_.Reset(); 546 error_cb_.Reset();
558 } 547 }
559 if (!stop_cb_.is_null()) { 548 if (!stop_cb_.is_null()) {
560 error_cb_.Reset(); 549 error_cb_.Reset();
550
551 // Invalid all weak pointers so it's safe to destroy |this| on the render
552 // main thread.
553 weak_factory_.InvalidateWeakPtrs();
xhwang 2014/08/05 20:44:47 Move this down here because OnStopComplete() can a
554
561 base::ResetAndReturn(&stop_cb_).Run(); 555 base::ResetAndReturn(&stop_cb_).Run();
562 556
563 // NOTE: pipeline may be deleted at this point in time as a result of 557 // NOTE: pipeline may be deleted at this point in time as a result of
564 // executing |stop_cb_|. 558 // executing |stop_cb_|.
565 return; 559 return;
566 } 560 }
567 if (!error_cb_.is_null()) { 561 if (!error_cb_.is_null()) {
568 DCHECK_NE(status_, PIPELINE_OK); 562 DCHECK_NE(status_, PIPELINE_OK);
569 base::ResetAndReturn(&error_cb_).Run(status_); 563 base::ResetAndReturn(&error_cb_).Run(status_);
570 } 564 }
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 911 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
918 lock_.AssertAcquired(); 912 lock_.AssertAcquired();
919 if (interpolation_state_ != INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE) 913 if (interpolation_state_ != INTERPOLATION_WAITING_FOR_AUDIO_TIME_UPDATE)
920 return; 914 return;
921 915
922 interpolation_state_ = INTERPOLATION_STARTED; 916 interpolation_state_ = INTERPOLATION_STARTED;
923 interpolator_->StartInterpolating(); 917 interpolator_->StartInterpolating();
924 } 918 }
925 919
926 } // namespace media 920 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/base/pipeline_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698