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

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

Issue 1658303002: Create abstract interface for media::Pipeline. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove scoped_ptr pointers. Created 4 years, 10 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
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 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 14 matching lines...) Expand all
25 #include "media/base/renderer.h" 25 #include "media/base/renderer.h"
26 #include "media/base/text_renderer.h" 26 #include "media/base/text_renderer.h"
27 #include "media/base/text_track_config.h" 27 #include "media/base/text_track_config.h"
28 #include "media/base/timestamp_constants.h" 28 #include "media/base/timestamp_constants.h"
29 #include "media/base/video_decoder_config.h" 29 #include "media/base/video_decoder_config.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 PipelineImpl::PipelineImpl(
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.0), 43 playback_rate_(0.0),
44 status_(PIPELINE_OK), 44 status_(PIPELINE_OK),
45 state_(kCreated), 45 state_(kCreated),
46 suspend_timestamp_(kNoTimestamp()), 46 suspend_timestamp_(kNoTimestamp()),
47 renderer_ended_(false), 47 renderer_ended_(false),
48 text_renderer_ended_(false), 48 text_renderer_ended_(false),
49 demuxer_(NULL), 49 demuxer_(NULL),
50 pending_cdm_context_(nullptr), 50 pending_cdm_context_(nullptr),
51 weak_factory_(this) { 51 weak_factory_(this) {
52 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 52 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
53 } 53 }
54 54
55 Pipeline::~Pipeline() { 55 PipelineImpl::~PipelineImpl() {
56 DCHECK(thread_checker_.CalledOnValidThread()) 56 DCHECK(thread_checker_.CalledOnValidThread())
57 << "Pipeline must be destroyed on same thread that created it"; 57 << "Pipeline must be destroyed on same thread that created it";
58 DCHECK(!running_) << "Stop() must complete before destroying object"; 58 DCHECK(!running_) << "Stop() must complete before destroying object";
59 DCHECK(stop_cb_.is_null()); 59 DCHECK(stop_cb_.is_null());
60 DCHECK(seek_cb_.is_null()); 60 DCHECK(seek_cb_.is_null());
61 } 61 }
62 62
63 void Pipeline::Start(Demuxer* demuxer, 63 void PipelineImpl::Start(Demuxer* demuxer,
64 scoped_ptr<Renderer> renderer, 64 scoped_ptr<Renderer> renderer,
65 const base::Closure& ended_cb, 65 const base::Closure& ended_cb,
66 const PipelineStatusCB& error_cb, 66 const PipelineStatusCB& error_cb,
67 const PipelineStatusCB& seek_cb, 67 const PipelineStatusCB& seek_cb,
68 const PipelineMetadataCB& metadata_cb, 68 const PipelineMetadataCB& metadata_cb,
69 const BufferingStateCB& buffering_state_cb, 69 const BufferingStateCB& buffering_state_cb,
70 const base::Closure& duration_change_cb, 70 const base::Closure& duration_change_cb,
71 const AddTextTrackCB& add_text_track_cb, 71 const AddTextTrackCB& add_text_track_cb,
72 const base::Closure& waiting_for_decryption_key_cb) { 72 const base::Closure& waiting_for_decryption_key_cb) {
73 DCHECK(!ended_cb.is_null()); 73 DCHECK(!ended_cb.is_null());
74 DCHECK(!error_cb.is_null()); 74 DCHECK(!error_cb.is_null());
75 DCHECK(!seek_cb.is_null()); 75 DCHECK(!seek_cb.is_null());
76 DCHECK(!metadata_cb.is_null()); 76 DCHECK(!metadata_cb.is_null());
77 DCHECK(!buffering_state_cb.is_null()); 77 DCHECK(!buffering_state_cb.is_null());
78 78
79 base::AutoLock auto_lock(lock_); 79 base::AutoLock auto_lock(lock_);
80 CHECK(!running_) << "Media pipeline is already running"; 80 CHECK(!running_) << "Media pipeline is already running";
81 running_ = true; 81 running_ = true;
82 82
83 demuxer_ = demuxer; 83 demuxer_ = demuxer;
84 renderer_ = std::move(renderer); 84 renderer_ = std::move(renderer);
85 ended_cb_ = ended_cb; 85 ended_cb_ = ended_cb;
86 error_cb_ = error_cb; 86 error_cb_ = error_cb;
87 seek_cb_ = seek_cb; 87 seek_cb_ = seek_cb;
88 metadata_cb_ = metadata_cb; 88 metadata_cb_ = metadata_cb;
89 buffering_state_cb_ = buffering_state_cb; 89 buffering_state_cb_ = buffering_state_cb;
90 duration_change_cb_ = duration_change_cb; 90 duration_change_cb_ = duration_change_cb;
91 add_text_track_cb_ = add_text_track_cb; 91 add_text_track_cb_ = add_text_track_cb;
92 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; 92 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb;
93 93
94 task_runner_->PostTask( 94 task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::StartTask,
95 FROM_HERE, base::Bind(&Pipeline::StartTask, weak_factory_.GetWeakPtr())); 95 weak_factory_.GetWeakPtr()));
96 } 96 }
97 97
98 void Pipeline::Stop(const base::Closure& stop_cb) { 98 void PipelineImpl::Stop(const base::Closure& stop_cb) {
99 DVLOG(2) << __FUNCTION__; 99 DVLOG(2) << __FUNCTION__;
100 task_runner_->PostTask( 100 task_runner_->PostTask(
101 FROM_HERE, 101 FROM_HERE,
102 base::Bind(&Pipeline::StopTask, weak_factory_.GetWeakPtr(), stop_cb)); 102 base::Bind(&PipelineImpl::StopTask, weak_factory_.GetWeakPtr(), stop_cb));
103 } 103 }
104 104
105 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { 105 void PipelineImpl::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
106 base::AutoLock auto_lock(lock_); 106 base::AutoLock auto_lock(lock_);
107 if (!running_) { 107 if (!running_) {
108 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek()."; 108 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek().";
109 return; 109 return;
110 } 110 }
111 111
112 task_runner_->PostTask( 112 task_runner_->PostTask(
113 FROM_HERE, 113 FROM_HERE, base::Bind(&PipelineImpl::SeekTask, weak_factory_.GetWeakPtr(),
114 base::Bind( 114 time, seek_cb));
115 &Pipeline::SeekTask, weak_factory_.GetWeakPtr(), time, seek_cb));
116 } 115 }
117 116
118 bool Pipeline::IsRunning() const { 117 bool PipelineImpl::IsRunning() const {
119 base::AutoLock auto_lock(lock_); 118 base::AutoLock auto_lock(lock_);
120 return running_; 119 return running_;
121 } 120 }
122 121
123 double Pipeline::GetPlaybackRate() const { 122 double PipelineImpl::GetPlaybackRate() const {
124 base::AutoLock auto_lock(lock_); 123 base::AutoLock auto_lock(lock_);
125 return playback_rate_; 124 return playback_rate_;
126 } 125 }
127 126
128 void Pipeline::SetPlaybackRate(double playback_rate) { 127 void PipelineImpl::SetPlaybackRate(double playback_rate) {
129 if (playback_rate < 0.0) 128 if (playback_rate < 0.0)
130 return; 129 return;
131 130
132 base::AutoLock auto_lock(lock_); 131 base::AutoLock auto_lock(lock_);
133 playback_rate_ = playback_rate; 132 playback_rate_ = playback_rate;
134 if (running_) { 133 if (running_) {
135 task_runner_->PostTask(FROM_HERE, 134 task_runner_->PostTask(
136 base::Bind(&Pipeline::PlaybackRateChangedTask, 135 FROM_HERE, base::Bind(&PipelineImpl::PlaybackRateChangedTask,
137 weak_factory_.GetWeakPtr(), 136 weak_factory_.GetWeakPtr(), playback_rate));
138 playback_rate));
139 } 137 }
140 } 138 }
141 139
142 void Pipeline::Suspend(const PipelineStatusCB& suspend_cb) { 140 void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb) {
143 task_runner_->PostTask( 141 task_runner_->PostTask(FROM_HERE,
144 FROM_HERE, base::Bind(&Pipeline::SuspendTask, weak_factory_.GetWeakPtr(), 142 base::Bind(&PipelineImpl::SuspendTask,
145 suspend_cb)); 143 weak_factory_.GetWeakPtr(), suspend_cb));
146 } 144 }
147 145
148 void Pipeline::Resume(scoped_ptr<Renderer> renderer, 146 void PipelineImpl::Resume(scoped_ptr<Renderer> renderer,
149 base::TimeDelta timestamp, 147 base::TimeDelta timestamp,
150 const PipelineStatusCB& seek_cb) { 148 const PipelineStatusCB& seek_cb) {
151 task_runner_->PostTask( 149 task_runner_->PostTask(
152 FROM_HERE, 150 FROM_HERE,
153 base::Bind(&Pipeline::ResumeTask, weak_factory_.GetWeakPtr(), 151 base::Bind(&PipelineImpl::ResumeTask, weak_factory_.GetWeakPtr(),
154 base::Passed(std::move(renderer)), timestamp, seek_cb)); 152 base::Passed(&renderer), timestamp, seek_cb));
155 } 153 }
156 154
157 float Pipeline::GetVolume() const { 155 float PipelineImpl::GetVolume() const {
158 base::AutoLock auto_lock(lock_); 156 base::AutoLock auto_lock(lock_);
159 return volume_; 157 return volume_;
160 } 158 }
161 159
162 void Pipeline::SetVolume(float volume) { 160 void PipelineImpl::SetVolume(float volume) {
163 if (volume < 0.0f || volume > 1.0f) 161 if (volume < 0.0f || volume > 1.0f)
164 return; 162 return;
165 163
166 base::AutoLock auto_lock(lock_); 164 base::AutoLock auto_lock(lock_);
167 volume_ = volume; 165 volume_ = volume;
168 if (running_) { 166 if (running_) {
169 task_runner_->PostTask( 167 task_runner_->PostTask(FROM_HERE,
170 FROM_HERE, 168 base::Bind(&PipelineImpl::VolumeChangedTask,
171 base::Bind( 169 weak_factory_.GetWeakPtr(), volume));
172 &Pipeline::VolumeChangedTask, weak_factory_.GetWeakPtr(), volume));
173 } 170 }
174 } 171 }
175 172
176 TimeDelta Pipeline::GetMediaTime() const { 173 TimeDelta PipelineImpl::GetMediaTime() const {
177 base::AutoLock auto_lock(lock_); 174 base::AutoLock auto_lock(lock_);
178 if (suspend_timestamp_ != kNoTimestamp()) 175 if (suspend_timestamp_ != kNoTimestamp())
179 return suspend_timestamp_; 176 return suspend_timestamp_;
180 return renderer_ ? std::min(renderer_->GetMediaTime(), duration_) 177 return renderer_ ? std::min(renderer_->GetMediaTime(), duration_)
181 : TimeDelta(); 178 : TimeDelta();
182 } 179 }
183 180
184 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() const { 181 Ranges<TimeDelta> PipelineImpl::GetBufferedTimeRanges() const {
185 base::AutoLock auto_lock(lock_); 182 base::AutoLock auto_lock(lock_);
186 return buffered_time_ranges_; 183 return buffered_time_ranges_;
187 } 184 }
188 185
189 TimeDelta Pipeline::GetMediaDuration() const { 186 TimeDelta PipelineImpl::GetMediaDuration() const {
190 base::AutoLock auto_lock(lock_); 187 base::AutoLock auto_lock(lock_);
191 return duration_; 188 return duration_;
192 } 189 }
193 190
194 bool Pipeline::DidLoadingProgress() { 191 bool PipelineImpl::DidLoadingProgress() {
195 base::AutoLock auto_lock(lock_); 192 base::AutoLock auto_lock(lock_);
196 bool ret = did_loading_progress_; 193 bool ret = did_loading_progress_;
197 did_loading_progress_ = false; 194 did_loading_progress_ = false;
198 return ret; 195 return ret;
199 } 196 }
200 197
201 PipelineStatistics Pipeline::GetStatistics() const { 198 PipelineStatistics PipelineImpl::GetStatistics() const {
202 base::AutoLock auto_lock(lock_); 199 base::AutoLock auto_lock(lock_);
203 return statistics_; 200 return statistics_;
204 } 201 }
205 202
206 void Pipeline::SetCdm(CdmContext* cdm_context, 203 void PipelineImpl::SetCdm(CdmContext* cdm_context,
207 const CdmAttachedCB& cdm_attached_cb) { 204 const CdmAttachedCB& cdm_attached_cb) {
208 task_runner_->PostTask( 205 task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::SetCdmTask,
209 FROM_HERE, base::Bind(&Pipeline::SetCdmTask, weak_factory_.GetWeakPtr(), 206 weak_factory_.GetWeakPtr(),
210 cdm_context, cdm_attached_cb)); 207 cdm_context, cdm_attached_cb));
211 } 208 }
212 209
213 void Pipeline::SetErrorForTesting(PipelineStatus status) { 210 void PipelineImpl::SetErrorForTesting(PipelineStatus status) {
214 OnError(status); 211 OnError(status);
215 } 212 }
216 213
217 bool Pipeline::HasWeakPtrsForTesting() const { 214 bool PipelineImpl::HasWeakPtrsForTesting() const {
218 DCHECK(task_runner_->BelongsToCurrentThread()); 215 DCHECK(task_runner_->BelongsToCurrentThread());
219 return weak_factory_.HasWeakPtrs(); 216 return weak_factory_.HasWeakPtrs();
220 } 217 }
221 218
222 void Pipeline::SetState(State next_state) { 219 void PipelineImpl::SetState(State next_state) {
223 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); 220 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state);
224 221
225 state_ = next_state; 222 state_ = next_state;
226 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); 223 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state));
227 } 224 }
228 225
229 #define RETURN_STRING(state) case state: return #state; 226 #define RETURN_STRING(state) case state: return #state;
230 227
231 const char* Pipeline::GetStateString(State state) { 228 const char* PipelineImpl::GetStateString(State state) {
232 switch (state) { 229 switch (state) {
233 RETURN_STRING(kCreated); 230 RETURN_STRING(kCreated);
234 RETURN_STRING(kInitDemuxer); 231 RETURN_STRING(kInitDemuxer);
235 RETURN_STRING(kInitRenderer); 232 RETURN_STRING(kInitRenderer);
236 RETURN_STRING(kSeeking); 233 RETURN_STRING(kSeeking);
237 RETURN_STRING(kPlaying); 234 RETURN_STRING(kPlaying);
238 RETURN_STRING(kStopping); 235 RETURN_STRING(kStopping);
239 RETURN_STRING(kStopped); 236 RETURN_STRING(kStopped);
240 RETURN_STRING(kSuspending); 237 RETURN_STRING(kSuspending);
241 RETURN_STRING(kSuspended); 238 RETURN_STRING(kSuspended);
242 RETURN_STRING(kResuming); 239 RETURN_STRING(kResuming);
243 } 240 }
244 NOTREACHED(); 241 NOTREACHED();
245 return "INVALID"; 242 return "INVALID";
246 } 243 }
247 244
248 #undef RETURN_STRING 245 #undef RETURN_STRING
249 246
250 Pipeline::State Pipeline::GetNextState() const { 247 PipelineImpl::State PipelineImpl::GetNextState() const {
251 DCHECK(task_runner_->BelongsToCurrentThread()); 248 DCHECK(task_runner_->BelongsToCurrentThread());
252 DCHECK(stop_cb_.is_null()) 249 DCHECK(stop_cb_.is_null())
253 << "State transitions don't happen when stopping"; 250 << "State transitions don't happen when stopping";
254 DCHECK_EQ(status_, PIPELINE_OK) 251 DCHECK_EQ(status_, PIPELINE_OK)
255 << "State transitions don't happen when there's an error: " << status_; 252 << "State transitions don't happen when there's an error: " << status_;
256 253
257 switch (state_) { 254 switch (state_) {
258 case kCreated: 255 case kCreated:
259 return kInitDemuxer; 256 return kInitDemuxer;
260 257
(...skipping 15 matching lines...) Expand all
276 273
277 case kPlaying: 274 case kPlaying:
278 case kStopping: 275 case kStopping:
279 case kStopped: 276 case kStopped:
280 break; 277 break;
281 } 278 }
282 NOTREACHED() << "State has no transition: " << state_; 279 NOTREACHED() << "State has no transition: " << state_;
283 return state_; 280 return state_;
284 } 281 }
285 282
286 void Pipeline::OnDemuxerError(PipelineStatus error) { 283 void PipelineImpl::OnDemuxerError(PipelineStatus error) {
287 task_runner_->PostTask(FROM_HERE, 284 task_runner_->PostTask(FROM_HERE,
288 base::Bind(&Pipeline::ErrorChangedTask, 285 base::Bind(&PipelineImpl::ErrorChangedTask,
289 weak_factory_.GetWeakPtr(), 286 weak_factory_.GetWeakPtr(), error));
290 error));
291 } 287 }
292 288
293 void Pipeline::AddTextStream(DemuxerStream* text_stream, 289 void PipelineImpl::AddTextStream(DemuxerStream* text_stream,
294 const TextTrackConfig& config) { 290 const TextTrackConfig& config) {
295 task_runner_->PostTask(FROM_HERE, 291 task_runner_->PostTask(
296 base::Bind(&Pipeline::AddTextStreamTask, 292 FROM_HERE, base::Bind(&PipelineImpl::AddTextStreamTask,
297 weak_factory_.GetWeakPtr(), 293 weak_factory_.GetWeakPtr(), text_stream, config));
298 text_stream,
299 config));
300 } 294 }
301 295
302 void Pipeline::RemoveTextStream(DemuxerStream* text_stream) { 296 void PipelineImpl::RemoveTextStream(DemuxerStream* text_stream) {
303 task_runner_->PostTask(FROM_HERE, 297 task_runner_->PostTask(FROM_HERE,
304 base::Bind(&Pipeline::RemoveTextStreamTask, 298 base::Bind(&PipelineImpl::RemoveTextStreamTask,
305 weak_factory_.GetWeakPtr(), 299 weak_factory_.GetWeakPtr(), text_stream));
306 text_stream));
307 } 300 }
308 301
309 void Pipeline::OnError(PipelineStatus error) { 302 void PipelineImpl::OnError(PipelineStatus error) {
310 DCHECK(task_runner_->BelongsToCurrentThread()); 303 DCHECK(task_runner_->BelongsToCurrentThread());
311 DCHECK(IsRunning()); 304 DCHECK(IsRunning());
312 DCHECK_NE(PIPELINE_OK, error); 305 DCHECK_NE(PIPELINE_OK, error);
313 VLOG(1) << "Media pipeline error: " << error; 306 VLOG(1) << "Media pipeline error: " << error;
314 307
315 task_runner_->PostTask(FROM_HERE, base::Bind( 308 task_runner_->PostTask(FROM_HERE,
316 &Pipeline::ErrorChangedTask, weak_factory_.GetWeakPtr(), error)); 309 base::Bind(&PipelineImpl::ErrorChangedTask,
310 weak_factory_.GetWeakPtr(), error));
317 } 311 }
318 312
319 void Pipeline::SetDuration(TimeDelta duration) { 313 void PipelineImpl::SetDuration(TimeDelta duration) {
320 DCHECK(IsRunning()); 314 DCHECK(IsRunning());
321 media_log_->AddEvent( 315 media_log_->AddEvent(
322 media_log_->CreateTimeEvent( 316 media_log_->CreateTimeEvent(
323 MediaLogEvent::DURATION_SET, "duration", duration)); 317 MediaLogEvent::DURATION_SET, "duration", duration));
324 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); 318 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration);
325 319
326 base::AutoLock auto_lock(lock_); 320 base::AutoLock auto_lock(lock_);
327 duration_ = duration; 321 duration_ = duration;
328 if (!duration_change_cb_.is_null()) 322 if (!duration_change_cb_.is_null())
329 duration_change_cb_.Run(); 323 duration_change_cb_.Run();
330 } 324 }
331 325
332 void Pipeline::StateTransitionTask(PipelineStatus status) { 326 void PipelineImpl::StateTransitionTask(PipelineStatus status) {
333 DCHECK(task_runner_->BelongsToCurrentThread()); 327 DCHECK(task_runner_->BelongsToCurrentThread());
334 328
335 // No-op any state transitions if we're stopping. 329 // No-op any state transitions if we're stopping.
336 if (state_ == kStopping || state_ == kStopped) 330 if (state_ == kStopping || state_ == kStopped)
337 return; 331 return;
338 332
339 // Preserve existing abnormal status, otherwise update based on the result of 333 // Preserve existing abnormal status, otherwise update based on the result of
340 // the previous operation. 334 // the previous operation.
341 status_ = (status_ != PIPELINE_OK ? status_ : status); 335 status_ = (status_ != PIPELINE_OK ? status_ : status);
342 336
343 if (status_ != PIPELINE_OK) { 337 if (status_ != PIPELINE_OK) {
344 ErrorChangedTask(status_); 338 ErrorChangedTask(status_);
345 return; 339 return;
346 } 340 }
347 341
348 // Guard against accidentally clearing |pending_callbacks_| for states that 342 // Guard against accidentally clearing |pending_callbacks_| for states that
349 // use it as well as states that should not be using it. 343 // use it as well as states that should not be using it.
350 DCHECK_EQ(pending_callbacks_.get() != NULL, 344 DCHECK_EQ(pending_callbacks_.get() != NULL,
351 state_ == kSeeking || state_ == kSuspending || state_ == kResuming); 345 state_ == kSeeking || state_ == kSuspending || state_ == kResuming);
352 346
353 pending_callbacks_.reset(); 347 pending_callbacks_.reset();
354 348
355 PipelineStatusCB done_cb = 349 PipelineStatusCB done_cb = base::Bind(&PipelineImpl::StateTransitionTask,
356 base::Bind(&Pipeline::StateTransitionTask, weak_factory_.GetWeakPtr()); 350 weak_factory_.GetWeakPtr());
357 351
358 // Switch states, performing any entrance actions for the new state as well. 352 // Switch states, performing any entrance actions for the new state as well.
359 SetState(GetNextState()); 353 SetState(GetNextState());
360 switch (state_) { 354 switch (state_) {
361 case kInitDemuxer: 355 case kInitDemuxer:
362 return InitializeDemuxer(done_cb); 356 return InitializeDemuxer(done_cb);
363 357
364 case kInitRenderer: 358 case kInitRenderer:
365 // When the state_ transfers to kInitRenderer, it means the demuxer has 359 // When the state_ transfers to kInitRenderer, it means the demuxer has
366 // finished parsing the init info. It should call ReportMetadata in case 360 // finished parsing the init info. It should call ReportMetadata in case
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 NOTREACHED() << "State has no transition: " << state_; 397 NOTREACHED() << "State has no transition: " << state_;
404 return; 398 return;
405 } 399 }
406 } 400 }
407 401
408 // Note that the usage of base::Unretained() with the renderers is considered 402 // Note that the usage of base::Unretained() with the renderers is considered
409 // safe as they are owned by |pending_callbacks_| and share the same lifetime. 403 // safe as they are owned by |pending_callbacks_| and share the same lifetime.
410 // 404 //
411 // That being said, deleting the renderers while keeping |pending_callbacks_| 405 // That being said, deleting the renderers while keeping |pending_callbacks_|
412 // running on the media thread would result in crashes. 406 // running on the media thread would result in crashes.
413 void Pipeline::DoSeek(TimeDelta seek_timestamp, 407 void PipelineImpl::DoSeek(TimeDelta seek_timestamp,
414 const PipelineStatusCB& done_cb) { 408 const PipelineStatusCB& done_cb) {
415 DCHECK(task_runner_->BelongsToCurrentThread()); 409 DCHECK(task_runner_->BelongsToCurrentThread());
416 DCHECK(!pending_callbacks_.get()); 410 DCHECK(!pending_callbacks_.get());
417 DCHECK_EQ(state_, kSeeking); 411 DCHECK_EQ(state_, kSeeking);
418 SerialRunner::Queue bound_fns; 412 SerialRunner::Queue bound_fns;
419 413
420 // Pause. 414 // Pause.
421 if (text_renderer_) { 415 if (text_renderer_) {
422 bound_fns.Push(base::Bind( 416 bound_fns.Push(base::Bind(
423 &TextRenderer::Pause, base::Unretained(text_renderer_.get()))); 417 &TextRenderer::Pause, base::Unretained(text_renderer_.get())));
424 } 418 }
425 419
426 // Flush. 420 // Flush.
427 DCHECK(renderer_); 421 DCHECK(renderer_);
428 bound_fns.Push( 422 bound_fns.Push(
429 base::Bind(&Renderer::Flush, base::Unretained(renderer_.get()))); 423 base::Bind(&Renderer::Flush, base::Unretained(renderer_.get())));
430 424
431 if (text_renderer_) { 425 if (text_renderer_) {
432 bound_fns.Push(base::Bind( 426 bound_fns.Push(base::Bind(
433 &TextRenderer::Flush, base::Unretained(text_renderer_.get()))); 427 &TextRenderer::Flush, base::Unretained(text_renderer_.get())));
434 } 428 }
435 429
436 // Seek demuxer. 430 // Seek demuxer.
437 bound_fns.Push(base::Bind( 431 bound_fns.Push(base::Bind(
438 &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); 432 &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp));
439 433
440 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); 434 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb);
441 } 435 }
442 436
443 void Pipeline::DoStop(const PipelineStatusCB& done_cb) { 437 void PipelineImpl::DoStop(const PipelineStatusCB& done_cb) {
444 DVLOG(2) << __FUNCTION__; 438 DVLOG(2) << __FUNCTION__;
445 DCHECK(task_runner_->BelongsToCurrentThread()); 439 DCHECK(task_runner_->BelongsToCurrentThread());
446 DCHECK(!pending_callbacks_.get()); 440 DCHECK(!pending_callbacks_.get());
447 441
448 // TODO(scherkus): Enforce that Renderer is only called on a single thread, 442 // TODO(scherkus): Enforce that Renderer is only called on a single thread,
449 // even for accessing media time http://crbug.com/370634 443 // even for accessing media time http://crbug.com/370634
450 scoped_ptr<Renderer> renderer; 444 scoped_ptr<Renderer> renderer;
451 { 445 {
452 base::AutoLock auto_lock(lock_); 446 base::AutoLock auto_lock(lock_);
453 renderer.swap(renderer_); 447 renderer.swap(renderer_);
454 } 448 }
455 renderer.reset(); 449 renderer.reset();
456 text_renderer_.reset(); 450 text_renderer_.reset();
457 451
458 if (demuxer_) { 452 if (demuxer_) {
459 demuxer_->Stop(); 453 demuxer_->Stop();
460 demuxer_ = NULL; 454 demuxer_ = NULL;
461 } 455 }
462 456
463 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 457 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
464 } 458 }
465 459
466 void Pipeline::OnStopCompleted(PipelineStatus status) { 460 void PipelineImpl::OnStopCompleted(PipelineStatus status) {
467 DVLOG(2) << __FUNCTION__; 461 DVLOG(2) << __FUNCTION__;
468 DCHECK(task_runner_->BelongsToCurrentThread()); 462 DCHECK(task_runner_->BelongsToCurrentThread());
469 DCHECK_EQ(state_, kStopping); 463 DCHECK_EQ(state_, kStopping);
470 DCHECK(!renderer_); 464 DCHECK(!renderer_);
471 DCHECK(!text_renderer_); 465 DCHECK(!text_renderer_);
472 466
473 { 467 {
474 base::AutoLock auto_lock(lock_); 468 base::AutoLock auto_lock(lock_);
475 running_ = false; 469 running_ = false;
476 } 470 }
(...skipping 23 matching lines...) Expand all
500 // NOTE: pipeline may be deleted at this point in time as a result of 494 // NOTE: pipeline may be deleted at this point in time as a result of
501 // executing |stop_cb_|. 495 // executing |stop_cb_|.
502 return; 496 return;
503 } 497 }
504 if (!error_cb_.is_null()) { 498 if (!error_cb_.is_null()) {
505 DCHECK_NE(status_, PIPELINE_OK); 499 DCHECK_NE(status_, PIPELINE_OK);
506 base::ResetAndReturn(&error_cb_).Run(status_); 500 base::ResetAndReturn(&error_cb_).Run(status_);
507 } 501 }
508 } 502 }
509 503
510 void Pipeline::OnBufferedTimeRangesChanged( 504 void PipelineImpl::OnBufferedTimeRangesChanged(
511 const Ranges<base::TimeDelta>& ranges) { 505 const Ranges<base::TimeDelta>& ranges) {
512 DCHECK(IsRunning()); 506 DCHECK(IsRunning());
513 base::AutoLock auto_lock(lock_); 507 base::AutoLock auto_lock(lock_);
514 buffered_time_ranges_ = ranges; 508 buffered_time_ranges_ = ranges;
515 did_loading_progress_ = true; 509 did_loading_progress_ = true;
516 } 510 }
517 511
518 // Called from any thread. 512 // Called from any thread.
519 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats_delta) { 513 void PipelineImpl::OnUpdateStatistics(const PipelineStatistics& stats_delta) {
520 base::AutoLock auto_lock(lock_); 514 base::AutoLock auto_lock(lock_);
521 statistics_.audio_bytes_decoded += stats_delta.audio_bytes_decoded; 515 statistics_.audio_bytes_decoded += stats_delta.audio_bytes_decoded;
522 statistics_.video_bytes_decoded += stats_delta.video_bytes_decoded; 516 statistics_.video_bytes_decoded += stats_delta.video_bytes_decoded;
523 statistics_.video_frames_decoded += stats_delta.video_frames_decoded; 517 statistics_.video_frames_decoded += stats_delta.video_frames_decoded;
524 statistics_.video_frames_dropped += stats_delta.video_frames_dropped; 518 statistics_.video_frames_dropped += stats_delta.video_frames_dropped;
525 statistics_.audio_memory_usage += stats_delta.audio_memory_usage; 519 statistics_.audio_memory_usage += stats_delta.audio_memory_usage;
526 statistics_.video_memory_usage += stats_delta.video_memory_usage; 520 statistics_.video_memory_usage += stats_delta.video_memory_usage;
527 } 521 }
528 522
529 void Pipeline::StartTask() { 523 void PipelineImpl::StartTask() {
530 DCHECK(task_runner_->BelongsToCurrentThread()); 524 DCHECK(task_runner_->BelongsToCurrentThread());
531 525
532 CHECK_EQ(kCreated, state_) 526 CHECK_EQ(kCreated, state_)
533 << "Media pipeline cannot be started more than once"; 527 << "Media pipeline cannot be started more than once";
534 528
535 text_renderer_ = CreateTextRenderer(); 529 text_renderer_ = CreateTextRenderer();
536 if (text_renderer_) { 530 if (text_renderer_) {
537 text_renderer_->Initialize( 531 text_renderer_->Initialize(base::Bind(&PipelineImpl::OnTextRendererEnded,
538 base::Bind(&Pipeline::OnTextRendererEnded, weak_factory_.GetWeakPtr())); 532 weak_factory_.GetWeakPtr()));
539 } 533 }
540 534
541 // Set CDM early to avoid unnecessary delay in Renderer::Initialize(). 535 // Set CDM early to avoid unnecessary delay in Renderer::Initialize().
542 if (pending_cdm_context_) { 536 if (pending_cdm_context_) {
543 renderer_->SetCdm(pending_cdm_context_, base::Bind(&IgnoreCdmAttached)); 537 renderer_->SetCdm(pending_cdm_context_, base::Bind(&IgnoreCdmAttached));
544 pending_cdm_context_ = nullptr; 538 pending_cdm_context_ = nullptr;
545 } 539 }
546 540
547 StateTransitionTask(PIPELINE_OK); 541 StateTransitionTask(PIPELINE_OK);
548 } 542 }
549 543
550 void Pipeline::StopTask(const base::Closure& stop_cb) { 544 void PipelineImpl::StopTask(const base::Closure& stop_cb) {
551 DCHECK(task_runner_->BelongsToCurrentThread()); 545 DCHECK(task_runner_->BelongsToCurrentThread());
552 DCHECK(stop_cb_.is_null()); 546 DCHECK(stop_cb_.is_null());
553 547
554 if (state_ == kStopped) { 548 if (state_ == kStopped) {
555 // Invalid all weak pointers so it's safe to destroy |this| on the render 549 // Invalid all weak pointers so it's safe to destroy |this| on the render
556 // main thread. 550 // main thread.
557 weak_factory_.InvalidateWeakPtrs(); 551 weak_factory_.InvalidateWeakPtrs();
558 552
559 // NOTE: pipeline may be deleted at this point in time as a result of 553 // NOTE: pipeline may be deleted at this point in time as a result of
560 // executing |stop_cb|. 554 // executing |stop_cb|.
(...skipping 13 matching lines...) Expand all
574 state_ == kSuspended || state_ == kResuming) { 568 state_ == kSuspended || state_ == kResuming) {
575 PipelineStatistics stats = GetStatistics(); 569 PipelineStatistics stats = GetStatistics();
576 if (stats.video_frames_decoded > 0) { 570 if (stats.video_frames_decoded > 0) {
577 UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount", 571 UMA_HISTOGRAM_COUNTS("Media.DroppedFrameCount",
578 stats.video_frames_dropped); 572 stats.video_frames_dropped);
579 } 573 }
580 } 574 }
581 575
582 SetState(kStopping); 576 SetState(kStopping);
583 pending_callbacks_.reset(); 577 pending_callbacks_.reset();
584 DoStop(base::Bind(&Pipeline::OnStopCompleted, weak_factory_.GetWeakPtr())); 578 DoStop(
579 base::Bind(&PipelineImpl::OnStopCompleted, weak_factory_.GetWeakPtr()));
585 } 580 }
586 581
587 void Pipeline::ErrorChangedTask(PipelineStatus error) { 582 void PipelineImpl::ErrorChangedTask(PipelineStatus error) {
588 DCHECK(task_runner_->BelongsToCurrentThread()); 583 DCHECK(task_runner_->BelongsToCurrentThread());
589 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; 584 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!";
590 585
591 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); 586 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
592 587
593 if (state_ == kStopping || state_ == kStopped) 588 if (state_ == kStopping || state_ == kStopped)
594 return; 589 return;
595 590
596 SetState(kStopping); 591 SetState(kStopping);
597 pending_callbacks_.reset(); 592 pending_callbacks_.reset();
598 status_ = error; 593 status_ = error;
599 594
600 DoStop(base::Bind(&Pipeline::OnStopCompleted, weak_factory_.GetWeakPtr())); 595 DoStop(
596 base::Bind(&PipelineImpl::OnStopCompleted, weak_factory_.GetWeakPtr()));
601 } 597 }
602 598
603 void Pipeline::PlaybackRateChangedTask(double playback_rate) { 599 void PipelineImpl::PlaybackRateChangedTask(double playback_rate) {
604 DCHECK(task_runner_->BelongsToCurrentThread()); 600 DCHECK(task_runner_->BelongsToCurrentThread());
605 601
606 // Playback rate changes are only carried out while playing. 602 // Playback rate changes are only carried out while playing.
607 if (state_ != kPlaying) 603 if (state_ != kPlaying)
608 return; 604 return;
609 605
610 renderer_->SetPlaybackRate(playback_rate); 606 renderer_->SetPlaybackRate(playback_rate);
611 } 607 }
612 608
613 void Pipeline::VolumeChangedTask(float volume) { 609 void PipelineImpl::VolumeChangedTask(float volume) {
614 DCHECK(task_runner_->BelongsToCurrentThread()); 610 DCHECK(task_runner_->BelongsToCurrentThread());
615 611
616 // Volume changes are only carried out while playing. 612 // Volume changes are only carried out while playing.
617 if (state_ != kPlaying) 613 if (state_ != kPlaying)
618 return; 614 return;
619 615
620 renderer_->SetVolume(volume); 616 renderer_->SetVolume(volume);
621 } 617 }
622 618
623 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { 619 void PipelineImpl::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
624 DCHECK(task_runner_->BelongsToCurrentThread()); 620 DCHECK(task_runner_->BelongsToCurrentThread());
625 DCHECK(stop_cb_.is_null()); 621 DCHECK(stop_cb_.is_null());
626 622
627 // Suppress seeking if we're not fully started. 623 // Suppress seeking if we're not fully started.
628 if (state_ != kPlaying) { 624 if (state_ != kPlaying) {
629 DCHECK(state_ == kStopping || state_ == kStopped) 625 DCHECK(state_ == kStopping || state_ == kStopped)
630 << "Receive seek in unexpected state: " << state_; 626 << "Receive seek in unexpected state: " << state_;
631 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE); 627 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE);
632 return; 628 return;
633 } 629 }
634 630
635 DCHECK(seek_cb_.is_null()); 631 DCHECK(seek_cb_.is_null());
636 632
637 const base::TimeDelta seek_timestamp = 633 const base::TimeDelta seek_timestamp =
638 std::max(time, demuxer_->GetStartTime()); 634 std::max(time, demuxer_->GetStartTime());
639 635
640 SetState(kSeeking); 636 SetState(kSeeking);
641 seek_cb_ = seek_cb; 637 seek_cb_ = seek_cb;
642 renderer_ended_ = false; 638 renderer_ended_ = false;
643 text_renderer_ended_ = false; 639 text_renderer_ended_ = false;
644 start_timestamp_ = seek_timestamp; 640 start_timestamp_ = seek_timestamp;
645 641
646 DoSeek(seek_timestamp, base::Bind(&Pipeline::StateTransitionTask, 642 DoSeek(seek_timestamp, base::Bind(&PipelineImpl::StateTransitionTask,
647 weak_factory_.GetWeakPtr())); 643 weak_factory_.GetWeakPtr()));
648 } 644 }
649 645
650 void Pipeline::SuspendTask(const PipelineStatusCB& suspend_cb) { 646 void PipelineImpl::SuspendTask(const PipelineStatusCB& suspend_cb) {
651 DCHECK(task_runner_->BelongsToCurrentThread()); 647 DCHECK(task_runner_->BelongsToCurrentThread());
652 648
653 // Suppress suspending if we're not playing. 649 // Suppress suspending if we're not playing.
654 if (state_ != kPlaying) { 650 if (state_ != kPlaying) {
655 DCHECK(state_ == kStopping || state_ == kStopped) 651 DCHECK(state_ == kStopping || state_ == kStopped)
656 << "Receive suspend in unexpected state: " << state_; 652 << "Receive suspend in unexpected state: " << state_;
657 suspend_cb.Run(PIPELINE_ERROR_INVALID_STATE); 653 suspend_cb.Run(PIPELINE_ERROR_INVALID_STATE);
658 return; 654 return;
659 } 655 }
660 DCHECK(renderer_); 656 DCHECK(renderer_);
(...skipping 21 matching lines...) Expand all
682 base::Unretained(text_renderer_.get()))); 678 base::Unretained(text_renderer_.get())));
683 } 679 }
684 680
685 fns.Push(base::Bind(&Renderer::Flush, base::Unretained(renderer_.get()))); 681 fns.Push(base::Bind(&Renderer::Flush, base::Unretained(renderer_.get())));
686 682
687 if (text_renderer_) { 683 if (text_renderer_) {
688 fns.Push(base::Bind(&TextRenderer::Flush, 684 fns.Push(base::Bind(&TextRenderer::Flush,
689 base::Unretained(text_renderer_.get()))); 685 base::Unretained(text_renderer_.get())));
690 } 686 }
691 687
692 pending_callbacks_ = SerialRunner::Run( 688 pending_callbacks_ =
693 fns, 689 SerialRunner::Run(fns, base::Bind(&PipelineImpl::StateTransitionTask,
694 base::Bind(&Pipeline::StateTransitionTask, weak_factory_.GetWeakPtr())); 690 weak_factory_.GetWeakPtr()));
695 } 691 }
696 692
697 void Pipeline::ResumeTask(scoped_ptr<Renderer> renderer, 693 void PipelineImpl::ResumeTask(scoped_ptr<Renderer> renderer,
698 base::TimeDelta timestamp, 694 base::TimeDelta timestamp,
699 const PipelineStatusCB& seek_cb) { 695 const PipelineStatusCB& seek_cb) {
700 DCHECK(task_runner_->BelongsToCurrentThread()); 696 DCHECK(task_runner_->BelongsToCurrentThread());
701 697
702 // Suppress resuming if we're not suspended. 698 // Suppress resuming if we're not suspended.
703 if (state_ != kSuspended) { 699 if (state_ != kSuspended) {
704 DCHECK(state_ == kStopping || state_ == kStopped) 700 DCHECK(state_ == kStopping || state_ == kStopped)
705 << "Receive resume in unexpected state: " << state_; 701 << "Receive resume in unexpected state: " << state_;
706 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE); 702 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE);
707 return; 703 return;
708 } 704 }
709 DCHECK(!renderer_); 705 DCHECK(!renderer_);
710 DCHECK(!pending_callbacks_.get()); 706 DCHECK(!pending_callbacks_.get());
711 707
712 SetState(kResuming); 708 SetState(kResuming);
713 renderer_ = std::move(renderer); 709 renderer_ = std::move(renderer);
714 710
715 // Set up for a seek. (Matches setup in SeekTask().) 711 // Set up for a seek. (Matches setup in SeekTask().)
716 // TODO(sandersd): Share implementation with SeekTask(). 712 // TODO(sandersd): Share implementation with SeekTask().
717 seek_cb_ = seek_cb; 713 seek_cb_ = seek_cb;
718 renderer_ended_ = false; 714 renderer_ended_ = false;
719 text_renderer_ended_ = false; 715 text_renderer_ended_ = false;
720 start_timestamp_ = std::max(timestamp, demuxer_->GetStartTime()); 716 start_timestamp_ = std::max(timestamp, demuxer_->GetStartTime());
721 717
722 // Queue the asynchronous actions required to start playback. Unlike DoSeek(), 718 // Queue the asynchronous actions required to start playback. Unlike DoSeek(),
723 // we need to initialize the renderer ourselves (we don't want to enter state 719 // we need to initialize the renderer ourselves (we don't want to enter state
724 // kInitDemuxer, and even if we did the current code would seek to the start 720 // kInitDemuxer, and even if we did the current code would seek to the start
725 // instead of |timestamp|). 721 // instead of |timestamp|).
726 SerialRunner::Queue fns; 722 SerialRunner::Queue fns;
727 base::WeakPtr<Pipeline> weak_this = weak_factory_.GetWeakPtr(); 723 base::WeakPtr<PipelineImpl> weak_this = weak_factory_.GetWeakPtr();
728 724
729 fns.Push( 725 fns.Push(
730 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), start_timestamp_)); 726 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), start_timestamp_));
731 727
732 fns.Push(base::Bind(&Pipeline::InitializeRenderer, weak_this)); 728 fns.Push(base::Bind(&PipelineImpl::InitializeRenderer, weak_this));
733 729
734 pending_callbacks_ = SerialRunner::Run( 730 pending_callbacks_ = SerialRunner::Run(
735 fns, base::Bind(&Pipeline::StateTransitionTask, weak_this)); 731 fns, base::Bind(&PipelineImpl::StateTransitionTask, weak_this));
736 } 732 }
737 733
738 void Pipeline::SetCdmTask(CdmContext* cdm_context, 734 void PipelineImpl::SetCdmTask(CdmContext* cdm_context,
739 const CdmAttachedCB& cdm_attached_cb) { 735 const CdmAttachedCB& cdm_attached_cb) {
740 base::AutoLock auto_lock(lock_); 736 base::AutoLock auto_lock(lock_);
741 if (!renderer_) { 737 if (!renderer_) {
742 pending_cdm_context_ = cdm_context; 738 pending_cdm_context_ = cdm_context;
743 cdm_attached_cb.Run(true); 739 cdm_attached_cb.Run(true);
744 return; 740 return;
745 } 741 }
746 742
747 renderer_->SetCdm(cdm_context, cdm_attached_cb); 743 renderer_->SetCdm(cdm_context, cdm_attached_cb);
748 } 744 }
749 745
750 void Pipeline::OnRendererEnded() { 746 void PipelineImpl::OnRendererEnded() {
751 DCHECK(task_runner_->BelongsToCurrentThread()); 747 DCHECK(task_runner_->BelongsToCurrentThread());
752 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); 748 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED));
753 749
754 if (state_ != kPlaying) 750 if (state_ != kPlaying)
755 return; 751 return;
756 752
757 DCHECK(!renderer_ended_); 753 DCHECK(!renderer_ended_);
758 renderer_ended_ = true; 754 renderer_ended_ = true;
759 755
760 RunEndedCallbackIfNeeded(); 756 RunEndedCallbackIfNeeded();
761 } 757 }
762 758
763 void Pipeline::OnTextRendererEnded() { 759 void PipelineImpl::OnTextRendererEnded() {
764 DCHECK(task_runner_->BelongsToCurrentThread()); 760 DCHECK(task_runner_->BelongsToCurrentThread());
765 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED)); 761 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED));
766 762
767 if (state_ != kPlaying) 763 if (state_ != kPlaying)
768 return; 764 return;
769 765
770 DCHECK(!text_renderer_ended_); 766 DCHECK(!text_renderer_ended_);
771 text_renderer_ended_ = true; 767 text_renderer_ended_ = true;
772 768
773 RunEndedCallbackIfNeeded(); 769 RunEndedCallbackIfNeeded();
774 } 770 }
775 771
776 void Pipeline::RunEndedCallbackIfNeeded() { 772 void PipelineImpl::RunEndedCallbackIfNeeded() {
777 DCHECK(task_runner_->BelongsToCurrentThread()); 773 DCHECK(task_runner_->BelongsToCurrentThread());
778 774
779 if (renderer_ && !renderer_ended_) 775 if (renderer_ && !renderer_ended_)
780 return; 776 return;
781 777
782 if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_) 778 if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_)
783 return; 779 return;
784 780
785 DCHECK_EQ(status_, PIPELINE_OK); 781 DCHECK_EQ(status_, PIPELINE_OK);
786 ended_cb_.Run(); 782 ended_cb_.Run();
787 } 783 }
788 784
789 scoped_ptr<TextRenderer> Pipeline::CreateTextRenderer() { 785 scoped_ptr<TextRenderer> PipelineImpl::CreateTextRenderer() {
790 DCHECK(task_runner_->BelongsToCurrentThread()); 786 DCHECK(task_runner_->BelongsToCurrentThread());
791 787
792 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); 788 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
793 if (!cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) 789 if (!cmd_line->HasSwitch(switches::kEnableInbandTextTracks))
794 return scoped_ptr<media::TextRenderer>(); 790 return scoped_ptr<media::TextRenderer>();
795 791
796 return scoped_ptr<media::TextRenderer>(new media::TextRenderer( 792 return scoped_ptr<media::TextRenderer>(new media::TextRenderer(
797 task_runner_, 793 task_runner_,
798 base::Bind(&Pipeline::OnAddTextTrack, weak_factory_.GetWeakPtr()))); 794 base::Bind(&PipelineImpl::OnAddTextTrack, weak_factory_.GetWeakPtr())));
799 } 795 }
800 796
801 void Pipeline::AddTextStreamTask(DemuxerStream* text_stream, 797 void PipelineImpl::AddTextStreamTask(DemuxerStream* text_stream,
802 const TextTrackConfig& config) { 798 const TextTrackConfig& config) {
803 DCHECK(task_runner_->BelongsToCurrentThread()); 799 DCHECK(task_runner_->BelongsToCurrentThread());
804 // TODO(matthewjheaney): fix up text_ended_ when text stream 800 // TODO(matthewjheaney): fix up text_ended_ when text stream
805 // is added (http://crbug.com/321446). 801 // is added (http://crbug.com/321446).
806 if (text_renderer_) 802 if (text_renderer_)
807 text_renderer_->AddTextStream(text_stream, config); 803 text_renderer_->AddTextStream(text_stream, config);
808 } 804 }
809 805
810 void Pipeline::RemoveTextStreamTask(DemuxerStream* text_stream) { 806 void PipelineImpl::RemoveTextStreamTask(DemuxerStream* text_stream) {
811 DCHECK(task_runner_->BelongsToCurrentThread()); 807 DCHECK(task_runner_->BelongsToCurrentThread());
812 if (text_renderer_) 808 if (text_renderer_)
813 text_renderer_->RemoveTextStream(text_stream); 809 text_renderer_->RemoveTextStream(text_stream);
814 } 810 }
815 811
816 void Pipeline::OnAddTextTrack(const TextTrackConfig& config, 812 void PipelineImpl::OnAddTextTrack(const TextTrackConfig& config,
817 const AddTextTrackDoneCB& done_cb) { 813 const AddTextTrackDoneCB& done_cb) {
818 DCHECK(task_runner_->BelongsToCurrentThread()); 814 DCHECK(task_runner_->BelongsToCurrentThread());
819 add_text_track_cb_.Run(config, done_cb); 815 add_text_track_cb_.Run(config, done_cb);
820 } 816 }
821 817
822 void Pipeline::InitializeDemuxer(const PipelineStatusCB& done_cb) { 818 void PipelineImpl::InitializeDemuxer(const PipelineStatusCB& done_cb) {
823 DCHECK(task_runner_->BelongsToCurrentThread()); 819 DCHECK(task_runner_->BelongsToCurrentThread());
824 demuxer_->Initialize(this, done_cb, !!text_renderer_); 820 demuxer_->Initialize(this, done_cb, !!text_renderer_);
825 } 821 }
826 822
827 void Pipeline::InitializeRenderer(const PipelineStatusCB& done_cb) { 823 void PipelineImpl::InitializeRenderer(const PipelineStatusCB& done_cb) {
828 DCHECK(task_runner_->BelongsToCurrentThread()); 824 DCHECK(task_runner_->BelongsToCurrentThread());
829 825
830 if (!demuxer_->GetStream(DemuxerStream::AUDIO) && 826 if (!demuxer_->GetStream(DemuxerStream::AUDIO) &&
831 !demuxer_->GetStream(DemuxerStream::VIDEO)) { 827 !demuxer_->GetStream(DemuxerStream::VIDEO)) {
832 { 828 {
833 base::AutoLock auto_lock(lock_); 829 base::AutoLock auto_lock(lock_);
834 renderer_.reset(); 830 renderer_.reset();
835 } 831 }
836 OnError(PIPELINE_ERROR_COULD_NOT_RENDER); 832 OnError(PIPELINE_ERROR_COULD_NOT_RENDER);
837 return; 833 return;
838 } 834 }
839 835
840 base::WeakPtr<Pipeline> weak_this = weak_factory_.GetWeakPtr(); 836 base::WeakPtr<PipelineImpl> weak_this = weak_factory_.GetWeakPtr();
841 renderer_->Initialize( 837 renderer_->Initialize(
842 demuxer_, 838 demuxer_, done_cb,
843 done_cb, 839 base::Bind(&PipelineImpl::OnUpdateStatistics, weak_this),
844 base::Bind(&Pipeline::OnUpdateStatistics, weak_this), 840 base::Bind(&PipelineImpl::BufferingStateChanged, weak_this),
845 base::Bind(&Pipeline::BufferingStateChanged, weak_this), 841 base::Bind(&PipelineImpl::OnRendererEnded, weak_this),
846 base::Bind(&Pipeline::OnRendererEnded, weak_this), 842 base::Bind(&PipelineImpl::OnError, weak_this),
847 base::Bind(&Pipeline::OnError, weak_this),
848 waiting_for_decryption_key_cb_); 843 waiting_for_decryption_key_cb_);
849 } 844 }
850 845
851 void Pipeline::ReportMetadata() { 846 void PipelineImpl::ReportMetadata() {
852 DCHECK(task_runner_->BelongsToCurrentThread()); 847 DCHECK(task_runner_->BelongsToCurrentThread());
853 PipelineMetadata metadata; 848 PipelineMetadata metadata;
854 metadata.timeline_offset = demuxer_->GetTimelineOffset(); 849 metadata.timeline_offset = demuxer_->GetTimelineOffset();
855 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 850 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
856 if (stream) { 851 if (stream) {
857 metadata.has_video = true; 852 metadata.has_video = true;
858 metadata.natural_size = stream->video_decoder_config().natural_size(); 853 metadata.natural_size = stream->video_decoder_config().natural_size();
859 metadata.video_rotation = stream->video_rotation(); 854 metadata.video_rotation = stream->video_rotation();
860 } 855 }
861 if (demuxer_->GetStream(DemuxerStream::AUDIO)) { 856 if (demuxer_->GetStream(DemuxerStream::AUDIO)) {
862 metadata.has_audio = true; 857 metadata.has_audio = true;
863 } 858 }
864 metadata_cb_.Run(metadata); 859 metadata_cb_.Run(metadata);
865 } 860 }
866 861
867 void Pipeline::BufferingStateChanged(BufferingState new_buffering_state) { 862 void PipelineImpl::BufferingStateChanged(BufferingState new_buffering_state) {
868 DVLOG(1) << __FUNCTION__ << "(" << new_buffering_state << ") "; 863 DVLOG(1) << __FUNCTION__ << "(" << new_buffering_state << ") ";
869 DCHECK(task_runner_->BelongsToCurrentThread()); 864 DCHECK(task_runner_->BelongsToCurrentThread());
870 buffering_state_cb_.Run(new_buffering_state); 865 buffering_state_cb_.Run(new_buffering_state);
871 } 866 }
872 867
873 } // namespace media 868 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698