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

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

Issue 1904793002: Move Pipeline permanent callbacks into Pipeline::Client interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 7 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_impl.h" 5 #include "media/base/pipeline_impl.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"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/callback_helpers.h" 13 #include "base/callback_helpers.h"
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/compiler_specific.h" 15 #include "base/compiler_specific.h"
16 #include "base/location.h" 16 #include "base/location.h"
17 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
18 #include "base/metrics/histogram.h" 18 #include "base/metrics/histogram.h"
19 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
20 #include "base/stl_util.h" 20 #include "base/stl_util.h"
21 #include "base/strings/string_number_conversions.h" 21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_util.h" 22 #include "base/strings/string_util.h"
23 #include "base/synchronization/condition_variable.h" 23 #include "base/thread_task_runner_handle.h"
24 #include "media/base/bind_to_current_loop.h"
24 #include "media/base/media_log.h" 25 #include "media/base/media_log.h"
25 #include "media/base/media_switches.h" 26 #include "media/base/media_switches.h"
26 #include "media/base/renderer.h" 27 #include "media/base/renderer.h"
27 #include "media/base/text_renderer.h" 28 #include "media/base/text_renderer.h"
28 #include "media/base/text_track_config.h" 29 #include "media/base/text_track_config.h"
29 #include "media/base/timestamp_constants.h" 30 #include "media/base/timestamp_constants.h"
30 #include "media/base/video_decoder_config.h" 31 #include "media/base/video_decoder_config.h"
31 32
32 using base::TimeDelta; 33 using base::TimeDelta;
33 34
34 namespace media { 35 namespace media {
35 36
36 PipelineImpl::PipelineImpl( 37 PipelineImpl::PipelineImpl(
37 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 38 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
38 MediaLog* media_log) 39 MediaLog* media_log)
39 : task_runner_(task_runner), 40 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
41 media_task_runner_(media_task_runner),
40 media_log_(media_log), 42 media_log_(media_log),
41 running_(false), 43 running_(false),
42 did_loading_progress_(false), 44 did_loading_progress_(false),
43 volume_(1.0f), 45 volume_(1.0f),
44 playback_rate_(0.0), 46 playback_rate_(0.0),
45 status_(PIPELINE_OK), 47 status_(PIPELINE_OK),
46 state_(kCreated), 48 state_(kCreated),
47 suspend_timestamp_(kNoTimestamp()), 49 suspend_timestamp_(kNoTimestamp()),
48 renderer_ended_(false), 50 renderer_ended_(false),
49 text_renderer_ended_(false), 51 text_renderer_ended_(false),
50 demuxer_(NULL), 52 demuxer_(NULL),
53 client_(nullptr),
51 cdm_context_(nullptr), 54 cdm_context_(nullptr),
52 weak_factory_(this) { 55 weak_factory_(this) {
53 weak_this_ = weak_factory_.GetWeakPtr(); 56 weak_this_ = weak_factory_.GetWeakPtr();
54 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 57 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
55 } 58 }
56 59
57 PipelineImpl::~PipelineImpl() { 60 PipelineImpl::~PipelineImpl() {
58 DCHECK(thread_checker_.CalledOnValidThread()) 61 DCHECK(main_task_runner_->BelongsToCurrentThread())
59 << "Pipeline must be destroyed on same thread that created it"; 62 << "Pipeline must be destroyed on same thread that created it";
60 DCHECK(!running_) << "Stop() must complete before destroying object"; 63 DCHECK(!running_) << "Stop() must complete before destroying object";
61 DCHECK(stop_cb_.is_null()); 64 DCHECK(stop_cb_.is_null());
62 DCHECK(seek_cb_.is_null()); 65 DCHECK(seek_cb_.is_null());
63 } 66 }
64 67
65 void PipelineImpl::Start(Demuxer* demuxer, 68 void PipelineImpl::Start(Demuxer* demuxer,
66 std::unique_ptr<Renderer> renderer, 69 std::unique_ptr<Renderer> renderer,
67 const base::Closure& ended_cb, 70 Client* client,
68 const PipelineStatusCB& error_cb, 71 const PipelineStatusCB& seek_cb) {
69 const PipelineStatusCB& seek_cb, 72 DCHECK(main_task_runner_->BelongsToCurrentThread());
70 const PipelineMetadataCB& metadata_cb, 73 DCHECK(client);
71 const BufferingStateCB& buffering_state_cb,
72 const base::Closure& duration_change_cb,
73 const AddTextTrackCB& add_text_track_cb,
74 const base::Closure& waiting_for_decryption_key_cb) {
75 DCHECK(!ended_cb.is_null());
76 DCHECK(!error_cb.is_null());
77 DCHECK(!seek_cb.is_null()); 74 DCHECK(!seek_cb.is_null());
78 DCHECK(!metadata_cb.is_null());
79 DCHECK(!buffering_state_cb.is_null());
80 75
81 base::AutoLock auto_lock(lock_); 76 base::AutoLock auto_lock(lock_);
82 CHECK(!running_) << "Media pipeline is already running"; 77 CHECK(!running_) << "Media pipeline is already running";
83 running_ = true; 78 running_ = true;
84 79
85 demuxer_ = demuxer; 80 demuxer_ = demuxer;
86 renderer_ = std::move(renderer); 81 renderer_ = std::move(renderer);
87 ended_cb_ = ended_cb; 82 client_ = client;
88 error_cb_ = error_cb; 83 seek_cb_ = media::BindToCurrentLoop(seek_cb);
89 seek_cb_ = seek_cb; 84 media_task_runner_->PostTask(
90 metadata_cb_ = metadata_cb; 85 FROM_HERE, base::Bind(&PipelineImpl::StartTask, weak_this_));
91 buffering_state_cb_ = buffering_state_cb;
92 duration_change_cb_ = duration_change_cb;
93 add_text_track_cb_ = add_text_track_cb;
94 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb;
95
96 task_runner_->PostTask(FROM_HERE,
97 base::Bind(&PipelineImpl::StartTask, weak_this_));
98 } 86 }
99 87
100 void PipelineImpl::Stop(const base::Closure& stop_cb) { 88 void PipelineImpl::Stop(const base::Closure& stop_cb) {
89 DCHECK(main_task_runner_->BelongsToCurrentThread());
101 DVLOG(2) << __FUNCTION__; 90 DVLOG(2) << __FUNCTION__;
102 task_runner_->PostTask( 91
103 FROM_HERE, base::Bind(&PipelineImpl::StopTask, weak_this_, stop_cb)); 92 media_task_runner_->PostTask(FROM_HERE,
93 base::Bind(&PipelineImpl::StopTask, weak_this_,
94 media::BindToCurrentLoop(stop_cb)));
104 } 95 }
105 96
106 void PipelineImpl::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { 97 void PipelineImpl::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
107 base::AutoLock auto_lock(lock_); 98 DCHECK(main_task_runner_->BelongsToCurrentThread());
108 if (!running_) { 99
100 if (!IsRunning()) {
109 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek()."; 101 DLOG(ERROR) << "Media pipeline isn't running. Ignoring Seek().";
110 return; 102 return;
111 } 103 }
112 104
113 task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::SeekTask, 105 media_task_runner_->PostTask(
114 weak_this_, time, seek_cb)); 106 FROM_HERE, base::Bind(&PipelineImpl::SeekTask, weak_this_, time,
107 media::BindToCurrentLoop(seek_cb)));
115 } 108 }
116 109
117 bool PipelineImpl::IsRunning() const { 110 bool PipelineImpl::IsRunning() const {
111 // TODO(alokp): Add thread DCHECK after removing the internal usage
112 // media thread.
118 base::AutoLock auto_lock(lock_); 113 base::AutoLock auto_lock(lock_);
119 return running_; 114 return running_;
120 } 115 }
121 116
122 double PipelineImpl::GetPlaybackRate() const { 117 double PipelineImpl::GetPlaybackRate() const {
118 // TODO(alokp): Add thread DCHECK after removing the internal usage
119 // media thread.
123 base::AutoLock auto_lock(lock_); 120 base::AutoLock auto_lock(lock_);
124 return playback_rate_; 121 return playback_rate_;
125 } 122 }
126 123
127 void PipelineImpl::SetPlaybackRate(double playback_rate) { 124 void PipelineImpl::SetPlaybackRate(double playback_rate) {
125 DCHECK(main_task_runner_->BelongsToCurrentThread());
126
128 if (playback_rate < 0.0) 127 if (playback_rate < 0.0)
129 return; 128 return;
130 129
131 base::AutoLock auto_lock(lock_); 130 base::AutoLock auto_lock(lock_);
132 playback_rate_ = playback_rate; 131 playback_rate_ = playback_rate;
133 if (running_) { 132 if (running_) {
134 task_runner_->PostTask(FROM_HERE, 133 media_task_runner_->PostTask(
135 base::Bind(&PipelineImpl::PlaybackRateChangedTask, 134 FROM_HERE, base::Bind(&PipelineImpl::PlaybackRateChangedTask,
136 weak_this_, playback_rate)); 135 weak_this_, playback_rate));
137 } 136 }
138 } 137 }
139 138
140 void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb) { 139 void PipelineImpl::Suspend(const PipelineStatusCB& suspend_cb) {
141 task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::SuspendTask, 140 DCHECK(main_task_runner_->BelongsToCurrentThread());
142 weak_this_, suspend_cb)); 141
142 media_task_runner_->PostTask(
143 FROM_HERE, base::Bind(&PipelineImpl::SuspendTask, weak_this_,
144 media::BindToCurrentLoop(suspend_cb)));
143 } 145 }
144 146
145 void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer, 147 void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer,
146 base::TimeDelta timestamp, 148 base::TimeDelta timestamp,
147 const PipelineStatusCB& seek_cb) { 149 const PipelineStatusCB& seek_cb) {
148 task_runner_->PostTask( 150 DCHECK(main_task_runner_->BelongsToCurrentThread());
149 FROM_HERE, base::Bind(&PipelineImpl::ResumeTask, weak_this_, 151
150 base::Passed(&renderer), timestamp, seek_cb)); 152 media_task_runner_->PostTask(
153 FROM_HERE,
154 base::Bind(&PipelineImpl::ResumeTask, weak_this_, base::Passed(&renderer),
155 timestamp, media::BindToCurrentLoop(seek_cb)));
151 } 156 }
152 157
153 float PipelineImpl::GetVolume() const { 158 float PipelineImpl::GetVolume() const {
159 // TODO(alokp): Add thread DCHECK after removing the internal usage
160 // media thread.
154 base::AutoLock auto_lock(lock_); 161 base::AutoLock auto_lock(lock_);
155 return volume_; 162 return volume_;
156 } 163 }
157 164
158 void PipelineImpl::SetVolume(float volume) { 165 void PipelineImpl::SetVolume(float volume) {
166 DCHECK(main_task_runner_->BelongsToCurrentThread());
167
159 if (volume < 0.0f || volume > 1.0f) 168 if (volume < 0.0f || volume > 1.0f)
160 return; 169 return;
161 170
162 base::AutoLock auto_lock(lock_); 171 base::AutoLock auto_lock(lock_);
163 volume_ = volume; 172 volume_ = volume;
164 if (running_) { 173 if (running_) {
165 task_runner_->PostTask( 174 media_task_runner_->PostTask(
166 FROM_HERE, 175 FROM_HERE,
167 base::Bind(&PipelineImpl::VolumeChangedTask, weak_this_, volume)); 176 base::Bind(&PipelineImpl::VolumeChangedTask, weak_this_, volume));
168 } 177 }
169 } 178 }
170 179
171 TimeDelta PipelineImpl::GetMediaTime() const { 180 TimeDelta PipelineImpl::GetMediaTime() const {
181 DCHECK(main_task_runner_->BelongsToCurrentThread());
182
172 base::AutoLock auto_lock(lock_); 183 base::AutoLock auto_lock(lock_);
173 if (suspend_timestamp_ != kNoTimestamp()) 184 if (suspend_timestamp_ != kNoTimestamp())
174 return suspend_timestamp_; 185 return suspend_timestamp_;
175 return renderer_ ? std::min(renderer_->GetMediaTime(), duration_) 186 return renderer_ ? std::min(renderer_->GetMediaTime(), duration_)
176 : TimeDelta(); 187 : TimeDelta();
177 } 188 }
178 189
179 Ranges<TimeDelta> PipelineImpl::GetBufferedTimeRanges() const { 190 Ranges<TimeDelta> PipelineImpl::GetBufferedTimeRanges() const {
191 DCHECK(main_task_runner_->BelongsToCurrentThread());
192
180 base::AutoLock auto_lock(lock_); 193 base::AutoLock auto_lock(lock_);
181 return buffered_time_ranges_; 194 return buffered_time_ranges_;
182 } 195 }
183 196
184 TimeDelta PipelineImpl::GetMediaDuration() const { 197 TimeDelta PipelineImpl::GetMediaDuration() const {
198 DCHECK(main_task_runner_->BelongsToCurrentThread());
199
185 base::AutoLock auto_lock(lock_); 200 base::AutoLock auto_lock(lock_);
186 return duration_; 201 return duration_;
187 } 202 }
188 203
189 bool PipelineImpl::DidLoadingProgress() { 204 bool PipelineImpl::DidLoadingProgress() {
205 DCHECK(main_task_runner_->BelongsToCurrentThread());
206
190 base::AutoLock auto_lock(lock_); 207 base::AutoLock auto_lock(lock_);
191 bool ret = did_loading_progress_; 208 bool ret = did_loading_progress_;
192 did_loading_progress_ = false; 209 did_loading_progress_ = false;
193 return ret; 210 return ret;
194 } 211 }
195 212
196 PipelineStatistics PipelineImpl::GetStatistics() const { 213 PipelineStatistics PipelineImpl::GetStatistics() const {
214 // TODO(alokp): Add thread DCHECK after removing the internal usage
215 // media thread.
197 base::AutoLock auto_lock(lock_); 216 base::AutoLock auto_lock(lock_);
198 return statistics_; 217 return statistics_;
199 } 218 }
200 219
201 void PipelineImpl::SetCdm(CdmContext* cdm_context, 220 void PipelineImpl::SetCdm(CdmContext* cdm_context,
202 const CdmAttachedCB& cdm_attached_cb) { 221 const CdmAttachedCB& cdm_attached_cb) {
203 task_runner_->PostTask( 222 DCHECK(main_task_runner_->BelongsToCurrentThread());
223
224 media_task_runner_->PostTask(
204 FROM_HERE, base::Bind(&PipelineImpl::SetCdmTask, weak_this_, cdm_context, 225 FROM_HERE, base::Bind(&PipelineImpl::SetCdmTask, weak_this_, cdm_context,
205 cdm_attached_cb)); 226 cdm_attached_cb));
206 } 227 }
207 228
208 void PipelineImpl::SetErrorForTesting(PipelineStatus status) { 229 void PipelineImpl::SetErrorForTesting(PipelineStatus status) {
209 OnError(status); 230 OnError(status);
210 } 231 }
211 232
212 bool PipelineImpl::HasWeakPtrsForTesting() const { 233 bool PipelineImpl::HasWeakPtrsForTesting() const {
213 DCHECK(task_runner_->BelongsToCurrentThread()); 234 DCHECK(media_task_runner_->BelongsToCurrentThread());
214 return weak_factory_.HasWeakPtrs(); 235 return weak_factory_.HasWeakPtrs();
215 } 236 }
216 237
217 void PipelineImpl::SetState(State next_state) { 238 void PipelineImpl::SetState(State next_state) {
239 DCHECK(media_task_runner_->BelongsToCurrentThread());
218 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state); 240 DVLOG(1) << GetStateString(state_) << " -> " << GetStateString(next_state);
219 241
220 state_ = next_state; 242 state_ = next_state;
221 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); 243 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state));
222 } 244 }
223 245
224 #define RETURN_STRING(state) \ 246 #define RETURN_STRING(state) \
225 case state: \ 247 case state: \
226 return #state; 248 return #state;
227 249
(...skipping 10 matching lines...) Expand all
238 RETURN_STRING(kSuspended); 260 RETURN_STRING(kSuspended);
239 RETURN_STRING(kResuming); 261 RETURN_STRING(kResuming);
240 } 262 }
241 NOTREACHED(); 263 NOTREACHED();
242 return "INVALID"; 264 return "INVALID";
243 } 265 }
244 266
245 #undef RETURN_STRING 267 #undef RETURN_STRING
246 268
247 PipelineImpl::State PipelineImpl::GetNextState() const { 269 PipelineImpl::State PipelineImpl::GetNextState() const {
248 DCHECK(task_runner_->BelongsToCurrentThread()); 270 DCHECK(media_task_runner_->BelongsToCurrentThread());
249 DCHECK(stop_cb_.is_null()) << "State transitions don't happen when stopping"; 271 DCHECK(stop_cb_.is_null()) << "State transitions don't happen when stopping";
250 DCHECK_EQ(status_, PIPELINE_OK) 272 DCHECK_EQ(status_, PIPELINE_OK)
251 << "State transitions don't happen when there's an error: " << status_; 273 << "State transitions don't happen when there's an error: " << status_;
252 274
253 switch (state_) { 275 switch (state_) {
254 case kCreated: 276 case kCreated:
255 return kInitDemuxer; 277 return kInitDemuxer;
256 278
257 case kInitDemuxer: 279 case kInitDemuxer:
258 return kInitRenderer; 280 return kInitRenderer;
(...skipping 14 matching lines...) Expand all
273 case kPlaying: 295 case kPlaying:
274 case kStopping: 296 case kStopping:
275 case kStopped: 297 case kStopped:
276 break; 298 break;
277 } 299 }
278 NOTREACHED() << "State has no transition: " << state_; 300 NOTREACHED() << "State has no transition: " << state_;
279 return state_; 301 return state_;
280 } 302 }
281 303
282 void PipelineImpl::OnDemuxerError(PipelineStatus error) { 304 void PipelineImpl::OnDemuxerError(PipelineStatus error) {
283 task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::ErrorChangedTask, 305 DCHECK(media_task_runner_->BelongsToCurrentThread());
284 weak_this_, error)); 306 media_task_runner_->PostTask(
307 FROM_HERE,
308 base::Bind(&PipelineImpl::ErrorChangedTask, weak_this_, error));
285 } 309 }
286 310
287 void PipelineImpl::AddTextStream(DemuxerStream* text_stream, 311 void PipelineImpl::AddTextStream(DemuxerStream* text_stream,
288 const TextTrackConfig& config) { 312 const TextTrackConfig& config) {
289 task_runner_->PostTask( 313 DCHECK(media_task_runner_->BelongsToCurrentThread());
314 media_task_runner_->PostTask(
290 FROM_HERE, base::Bind(&PipelineImpl::AddTextStreamTask, weak_this_, 315 FROM_HERE, base::Bind(&PipelineImpl::AddTextStreamTask, weak_this_,
291 text_stream, config)); 316 text_stream, config));
292 } 317 }
293 318
294 void PipelineImpl::RemoveTextStream(DemuxerStream* text_stream) { 319 void PipelineImpl::RemoveTextStream(DemuxerStream* text_stream) {
295 task_runner_->PostTask( 320 DCHECK(media_task_runner_->BelongsToCurrentThread());
321 media_task_runner_->PostTask(
296 FROM_HERE, 322 FROM_HERE,
297 base::Bind(&PipelineImpl::RemoveTextStreamTask, weak_this_, text_stream)); 323 base::Bind(&PipelineImpl::RemoveTextStreamTask, weak_this_, text_stream));
298 } 324 }
299 325
300 void PipelineImpl::OnError(PipelineStatus error) { 326 void PipelineImpl::OnError(PipelineStatus error) {
301 DCHECK(task_runner_->BelongsToCurrentThread()); 327 DCHECK(media_task_runner_->BelongsToCurrentThread());
302 DCHECK(IsRunning()); 328 DCHECK(IsRunning());
303 DCHECK_NE(PIPELINE_OK, error); 329 DCHECK_NE(PIPELINE_OK, error);
304 VLOG(1) << "Media pipeline error: " << error; 330 VLOG(1) << "Media pipeline error: " << error;
305 331
306 task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::ErrorChangedTask, 332 media_task_runner_->PostTask(
307 weak_this_, error)); 333 FROM_HERE,
334 base::Bind(&PipelineImpl::ErrorChangedTask, weak_this_, error));
308 } 335 }
309 336
310 void PipelineImpl::SetDuration(TimeDelta duration) { 337 void PipelineImpl::SetDuration(TimeDelta duration) {
338 DCHECK(media_task_runner_->BelongsToCurrentThread());
311 DCHECK(IsRunning()); 339 DCHECK(IsRunning());
312 media_log_->AddEvent(media_log_->CreateTimeEvent(MediaLogEvent::DURATION_SET, 340 media_log_->AddEvent(media_log_->CreateTimeEvent(MediaLogEvent::DURATION_SET,
313 "duration", duration)); 341 "duration", duration));
314 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); 342 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration);
315 343
316 base::AutoLock auto_lock(lock_); 344 base::AutoLock auto_lock(lock_);
317 duration_ = duration; 345 duration_ = duration;
318 if (!duration_change_cb_.is_null()) 346 main_task_runner_->PostTask(FROM_HERE,
319 duration_change_cb_.Run(); 347 base::Bind(&Pipeline::Client::OnDurationChange,
348 base::Unretained(client_)));
320 } 349 }
321 350
322 void PipelineImpl::StateTransitionTask(PipelineStatus status) { 351 void PipelineImpl::StateTransitionTask(PipelineStatus status) {
323 DCHECK(task_runner_->BelongsToCurrentThread()); 352 DCHECK(media_task_runner_->BelongsToCurrentThread());
324 353
325 // No-op any state transitions if we're stopping. 354 // No-op any state transitions if we're stopping.
326 if (state_ == kStopping || state_ == kStopped) 355 if (state_ == kStopping || state_ == kStopped)
327 return; 356 return;
328 357
329 // Preserve existing abnormal status, otherwise update based on the result of 358 // Preserve existing abnormal status, otherwise update based on the result of
330 // the previous operation. 359 // the previous operation.
331 status_ = (status_ != PIPELINE_OK ? status_ : status); 360 status_ = (status_ != PIPELINE_OK ? status_ : status);
332 361
333 if (status_ != PIPELINE_OK) { 362 if (status_ != PIPELINE_OK) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 426 }
398 } 427 }
399 428
400 // Note that the usage of base::Unretained() with the renderers is considered 429 // Note that the usage of base::Unretained() with the renderers is considered
401 // safe as they are owned by |pending_callbacks_| and share the same lifetime. 430 // safe as they are owned by |pending_callbacks_| and share the same lifetime.
402 // 431 //
403 // That being said, deleting the renderers while keeping |pending_callbacks_| 432 // That being said, deleting the renderers while keeping |pending_callbacks_|
404 // running on the media thread would result in crashes. 433 // running on the media thread would result in crashes.
405 void PipelineImpl::DoSeek(TimeDelta seek_timestamp, 434 void PipelineImpl::DoSeek(TimeDelta seek_timestamp,
406 const PipelineStatusCB& done_cb) { 435 const PipelineStatusCB& done_cb) {
407 DCHECK(task_runner_->BelongsToCurrentThread()); 436 DCHECK(media_task_runner_->BelongsToCurrentThread());
408 DCHECK(!pending_callbacks_.get()); 437 DCHECK(!pending_callbacks_.get());
409 DCHECK_EQ(state_, kSeeking); 438 DCHECK_EQ(state_, kSeeking);
410 SerialRunner::Queue bound_fns; 439 SerialRunner::Queue bound_fns;
411 440
412 // Pause. 441 // Pause.
413 if (text_renderer_) { 442 if (text_renderer_) {
414 bound_fns.Push(base::Bind(&TextRenderer::Pause, 443 bound_fns.Push(base::Bind(&TextRenderer::Pause,
415 base::Unretained(text_renderer_.get()))); 444 base::Unretained(text_renderer_.get())));
416 } 445 }
417 446
418 // Flush. 447 // Flush.
419 DCHECK(renderer_); 448 DCHECK(renderer_);
420 bound_fns.Push( 449 bound_fns.Push(
421 base::Bind(&Renderer::Flush, base::Unretained(renderer_.get()))); 450 base::Bind(&Renderer::Flush, base::Unretained(renderer_.get())));
422 451
423 if (text_renderer_) { 452 if (text_renderer_) {
424 bound_fns.Push(base::Bind(&TextRenderer::Flush, 453 bound_fns.Push(base::Bind(&TextRenderer::Flush,
425 base::Unretained(text_renderer_.get()))); 454 base::Unretained(text_renderer_.get())));
426 } 455 }
427 456
428 // Seek demuxer. 457 // Seek demuxer.
429 bound_fns.Push( 458 bound_fns.Push(
430 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); 459 base::Bind(&Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp));
431 460
432 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); 461 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb);
433 } 462 }
434 463
435 void PipelineImpl::DoStop(const PipelineStatusCB& done_cb) { 464 void PipelineImpl::DoStop(const PipelineStatusCB& done_cb) {
436 DVLOG(2) << __FUNCTION__; 465 DVLOG(2) << __FUNCTION__;
437 DCHECK(task_runner_->BelongsToCurrentThread()); 466 DCHECK(media_task_runner_->BelongsToCurrentThread());
438 DCHECK(!pending_callbacks_.get()); 467 DCHECK(!pending_callbacks_.get());
439 468
440 // TODO(scherkus): Enforce that Renderer is only called on a single thread, 469 // TODO(scherkus): Enforce that Renderer is only called on a single thread,
441 // even for accessing media time http://crbug.com/370634 470 // even for accessing media time http://crbug.com/370634
442 std::unique_ptr<Renderer> renderer; 471 std::unique_ptr<Renderer> renderer;
443 { 472 {
444 base::AutoLock auto_lock(lock_); 473 base::AutoLock auto_lock(lock_);
445 renderer.swap(renderer_); 474 renderer.swap(renderer_);
446 } 475 }
447 renderer.reset(); 476 renderer.reset();
448 text_renderer_.reset(); 477 text_renderer_.reset();
449 478
450 if (demuxer_) { 479 if (demuxer_) {
451 demuxer_->Stop(); 480 demuxer_->Stop();
452 demuxer_ = NULL; 481 demuxer_ = NULL;
453 } 482 }
454 483
455 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 484 media_task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
456 } 485 }
457 486
458 void PipelineImpl::OnStopCompleted(PipelineStatus status) { 487 void PipelineImpl::OnStopCompleted(PipelineStatus status) {
459 DVLOG(2) << __FUNCTION__; 488 DVLOG(2) << __FUNCTION__;
460 DCHECK(task_runner_->BelongsToCurrentThread()); 489 DCHECK(media_task_runner_->BelongsToCurrentThread());
461 DCHECK_EQ(state_, kStopping); 490 DCHECK_EQ(state_, kStopping);
462 DCHECK(!renderer_); 491 DCHECK(!renderer_);
463 DCHECK(!text_renderer_); 492 DCHECK(!text_renderer_);
464 493
465 { 494 {
466 base::AutoLock auto_lock(lock_); 495 base::AutoLock auto_lock(lock_);
467 running_ = false; 496 running_ = false;
468 } 497 }
469 498
470 SetState(kStopped); 499 SetState(kStopped);
471 demuxer_ = NULL; 500 demuxer_ = NULL;
472 501
473 // If we stop during initialization/seeking/suspending we don't want to leave 502 // If we stop during initialization/seeking/suspending we don't want to leave
474 // outstanding callbacks around. 503 // outstanding callbacks around.
504 bool status_reported = false;
475 if (!seek_cb_.is_null()) { 505 if (!seek_cb_.is_null()) {
476 base::ResetAndReturn(&seek_cb_).Run(status_); 506 base::ResetAndReturn(&seek_cb_).Run(status_);
477 error_cb_.Reset(); 507 status_reported = true;
478 } 508 }
479 if (!suspend_cb_.is_null()) { 509 if (!suspend_cb_.is_null()) {
480 base::ResetAndReturn(&suspend_cb_).Run(status_); 510 base::ResetAndReturn(&suspend_cb_).Run(status_);
481 error_cb_.Reset(); 511 status_reported = true;
482 } 512 }
483 if (!stop_cb_.is_null()) { 513 if (!stop_cb_.is_null()) {
484 error_cb_.Reset();
485
486 // Invalid all weak pointers so it's safe to destroy |this| on the render 514 // Invalid all weak pointers so it's safe to destroy |this| on the render
487 // main thread. 515 // main thread.
488 weak_factory_.InvalidateWeakPtrs(); 516 weak_factory_.InvalidateWeakPtrs();
489 517
490 base::ResetAndReturn(&stop_cb_).Run(); 518 base::ResetAndReturn(&stop_cb_).Run();
491 519
492 // NOTE: pipeline may be deleted at this point in time as a result of 520 // NOTE: pipeline may be deleted at this point in time as a result of
493 // executing |stop_cb_|. 521 // executing |stop_cb_|.
494 return; 522 return;
495 } 523 }
496 if (!error_cb_.is_null()) { 524 if (!status_reported) {
497 DCHECK_NE(status_, PIPELINE_OK); 525 DCHECK_NE(status_, PIPELINE_OK);
498 base::ResetAndReturn(&error_cb_).Run(status_); 526 main_task_runner_->PostTask(FROM_HERE,
527 base::Bind(&Pipeline::Client::OnError,
528 base::Unretained(client_), status_));
499 } 529 }
500 } 530 }
501 531
502 void PipelineImpl::OnBufferedTimeRangesChanged( 532 void PipelineImpl::OnBufferedTimeRangesChanged(
503 const Ranges<base::TimeDelta>& ranges) { 533 const Ranges<base::TimeDelta>& ranges) {
534 DCHECK(media_task_runner_->BelongsToCurrentThread());
535
504 base::AutoLock auto_lock(lock_); 536 base::AutoLock auto_lock(lock_);
505 buffered_time_ranges_ = ranges; 537 buffered_time_ranges_ = ranges;
506 did_loading_progress_ = true; 538 did_loading_progress_ = true;
507 } 539 }
508 540
509 // Called from any thread. 541 // Called from any thread.
510 void PipelineImpl::OnUpdateStatistics(const PipelineStatistics& stats_delta) { 542 void PipelineImpl::OnUpdateStatistics(const PipelineStatistics& stats_delta) {
511 base::AutoLock auto_lock(lock_); 543 base::AutoLock auto_lock(lock_);
512 statistics_.audio_bytes_decoded += stats_delta.audio_bytes_decoded; 544 statistics_.audio_bytes_decoded += stats_delta.audio_bytes_decoded;
513 statistics_.video_bytes_decoded += stats_delta.video_bytes_decoded; 545 statistics_.video_bytes_decoded += stats_delta.video_bytes_decoded;
514 statistics_.video_frames_decoded += stats_delta.video_frames_decoded; 546 statistics_.video_frames_decoded += stats_delta.video_frames_decoded;
515 statistics_.video_frames_dropped += stats_delta.video_frames_dropped; 547 statistics_.video_frames_dropped += stats_delta.video_frames_dropped;
516 statistics_.audio_memory_usage += stats_delta.audio_memory_usage; 548 statistics_.audio_memory_usage += stats_delta.audio_memory_usage;
517 statistics_.video_memory_usage += stats_delta.video_memory_usage; 549 statistics_.video_memory_usage += stats_delta.video_memory_usage;
518 } 550 }
519 551
552 void PipelineImpl::OnWaitingForDecryptionKey() {
553 DCHECK(media_task_runner_->BelongsToCurrentThread());
554
555 main_task_runner_->PostTask(
556 FROM_HERE, base::Bind(&Pipeline::Client::OnWaitingForDecryptionKey,
557 base::Unretained(client_)));
558 }
559
520 void PipelineImpl::StartTask() { 560 void PipelineImpl::StartTask() {
521 DCHECK(task_runner_->BelongsToCurrentThread()); 561 DCHECK(media_task_runner_->BelongsToCurrentThread());
522 562
523 CHECK_EQ(kCreated, state_) 563 CHECK_EQ(kCreated, state_)
524 << "Media pipeline cannot be started more than once"; 564 << "Media pipeline cannot be started more than once";
525 565
526 text_renderer_ = CreateTextRenderer(); 566 text_renderer_ = CreateTextRenderer();
527 if (text_renderer_) { 567 if (text_renderer_) {
528 text_renderer_->Initialize( 568 text_renderer_->Initialize(
529 base::Bind(&PipelineImpl::OnTextRendererEnded, weak_this_)); 569 base::Bind(&PipelineImpl::OnTextRendererEnded, weak_this_));
530 } 570 }
531 571
532 StateTransitionTask(PIPELINE_OK); 572 StateTransitionTask(PIPELINE_OK);
533 } 573 }
534 574
535 void PipelineImpl::StopTask(const base::Closure& stop_cb) { 575 void PipelineImpl::StopTask(const base::Closure& stop_cb) {
536 DCHECK(task_runner_->BelongsToCurrentThread()); 576 DCHECK(media_task_runner_->BelongsToCurrentThread());
537 DCHECK(stop_cb_.is_null()); 577 DCHECK(stop_cb_.is_null());
538 578
539 if (state_ == kStopped) { 579 if (state_ == kStopped) {
540 // Invalid all weak pointers so it's safe to destroy |this| on the render 580 // Invalid all weak pointers so it's safe to destroy |this| on the render
541 // main thread. 581 // main thread.
542 weak_factory_.InvalidateWeakPtrs(); 582 weak_factory_.InvalidateWeakPtrs();
543 583
544 // NOTE: pipeline may be deleted at this point in time as a result of 584 // NOTE: pipeline may be deleted at this point in time as a result of
545 // executing |stop_cb|. 585 // executing |stop_cb|.
546 stop_cb.Run(); 586 stop_cb.Run();
(...skipping 16 matching lines...) Expand all
563 stats.video_frames_dropped); 603 stats.video_frames_dropped);
564 } 604 }
565 } 605 }
566 606
567 SetState(kStopping); 607 SetState(kStopping);
568 pending_callbacks_.reset(); 608 pending_callbacks_.reset();
569 DoStop(base::Bind(&PipelineImpl::OnStopCompleted, weak_this_)); 609 DoStop(base::Bind(&PipelineImpl::OnStopCompleted, weak_this_));
570 } 610 }
571 611
572 void PipelineImpl::ErrorChangedTask(PipelineStatus error) { 612 void PipelineImpl::ErrorChangedTask(PipelineStatus error) {
573 DCHECK(task_runner_->BelongsToCurrentThread()); 613 DCHECK(media_task_runner_->BelongsToCurrentThread());
574 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; 614 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!";
575 615
576 // Don't report pipeline error events to the media log here. The embedder will 616 // Don't report pipeline error events to the media log here. The embedder will
577 // log this when |error_cb_| is called. If the pipeline is already stopped or 617 // log this when |error_cb_| is called. If the pipeline is already stopped or
578 // stopping we also don't want to log any event. In case we are suspending or 618 // stopping we also don't want to log any event. In case we are suspending or
579 // suspended, the error may be recoverable, so don't propagate it now, instead 619 // suspended, the error may be recoverable, so don't propagate it now, instead
580 // let the subsequent seek during resume propagate it if it's unrecoverable. 620 // let the subsequent seek during resume propagate it if it's unrecoverable.
581 621
582 if (state_ == kStopping || state_ == kStopped || state_ == kSuspending || 622 if (state_ == kStopping || state_ == kStopped || state_ == kSuspending ||
583 state_ == kSuspended) { 623 state_ == kSuspended) {
584 return; 624 return;
585 } 625 }
586 626
587 SetState(kStopping); 627 SetState(kStopping);
588 pending_callbacks_.reset(); 628 pending_callbacks_.reset();
589 status_ = error; 629 status_ = error;
590 630
591 DoStop(base::Bind(&PipelineImpl::OnStopCompleted, weak_this_)); 631 DoStop(base::Bind(&PipelineImpl::OnStopCompleted, weak_this_));
592 } 632 }
593 633
594 void PipelineImpl::PlaybackRateChangedTask(double playback_rate) { 634 void PipelineImpl::PlaybackRateChangedTask(double playback_rate) {
595 DCHECK(task_runner_->BelongsToCurrentThread()); 635 DCHECK(media_task_runner_->BelongsToCurrentThread());
596 636
597 // Playback rate changes are only carried out while playing. 637 // Playback rate changes are only carried out while playing.
598 if (state_ != kPlaying) 638 if (state_ != kPlaying)
599 return; 639 return;
600 640
601 renderer_->SetPlaybackRate(playback_rate); 641 renderer_->SetPlaybackRate(playback_rate);
602 } 642 }
603 643
604 void PipelineImpl::VolumeChangedTask(float volume) { 644 void PipelineImpl::VolumeChangedTask(float volume) {
605 DCHECK(task_runner_->BelongsToCurrentThread()); 645 DCHECK(media_task_runner_->BelongsToCurrentThread());
606 646
607 // Volume changes are only carried out while playing. 647 // Volume changes are only carried out while playing.
608 if (state_ != kPlaying) 648 if (state_ != kPlaying)
609 return; 649 return;
610 650
611 renderer_->SetVolume(volume); 651 renderer_->SetVolume(volume);
612 } 652 }
613 653
614 void PipelineImpl::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { 654 void PipelineImpl::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
615 DCHECK(task_runner_->BelongsToCurrentThread()); 655 DCHECK(media_task_runner_->BelongsToCurrentThread());
616 DCHECK(stop_cb_.is_null()); 656 DCHECK(stop_cb_.is_null());
617 657
618 // Suppress seeking if we're not fully started. 658 // Suppress seeking if we're not fully started.
619 if (state_ != kPlaying) { 659 if (state_ != kPlaying) {
620 DCHECK(state_ == kStopping || state_ == kStopped) 660 DCHECK(state_ == kStopping || state_ == kStopped)
621 << "Receive seek in unexpected state: " << state_; 661 << "Receive seek in unexpected state: " << state_;
622 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE); 662 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE);
623 return; 663 return;
624 } 664 }
625 665
626 DCHECK(seek_cb_.is_null()); 666 DCHECK(seek_cb_.is_null());
627 667
628 const base::TimeDelta seek_timestamp = 668 const base::TimeDelta seek_timestamp =
629 std::max(time, demuxer_->GetStartTime()); 669 std::max(time, demuxer_->GetStartTime());
630 670
631 SetState(kSeeking); 671 SetState(kSeeking);
632 seek_cb_ = seek_cb; 672 seek_cb_ = seek_cb;
633 renderer_ended_ = false; 673 renderer_ended_ = false;
634 text_renderer_ended_ = false; 674 text_renderer_ended_ = false;
635 start_timestamp_ = seek_timestamp; 675 start_timestamp_ = seek_timestamp;
636 676
637 DoSeek(seek_timestamp, 677 DoSeek(seek_timestamp,
638 base::Bind(&PipelineImpl::StateTransitionTask, weak_this_)); 678 base::Bind(&PipelineImpl::StateTransitionTask, weak_this_));
639 } 679 }
640 680
641 void PipelineImpl::SuspendTask(const PipelineStatusCB& suspend_cb) { 681 void PipelineImpl::SuspendTask(const PipelineStatusCB& suspend_cb) {
642 DCHECK(task_runner_->BelongsToCurrentThread()); 682 DCHECK(media_task_runner_->BelongsToCurrentThread());
643 683
644 // Suppress suspending if we're not playing. 684 // Suppress suspending if we're not playing.
645 if (state_ != kPlaying) { 685 if (state_ != kPlaying) {
646 DCHECK(state_ == kStopping || state_ == kStopped) 686 DCHECK(state_ == kStopping || state_ == kStopped)
647 << "Receive suspend in unexpected state: " << state_; 687 << "Receive suspend in unexpected state: " << state_;
648 suspend_cb.Run(PIPELINE_ERROR_INVALID_STATE); 688 suspend_cb.Run(PIPELINE_ERROR_INVALID_STATE);
649 return; 689 return;
650 } 690 }
651 DCHECK(renderer_); 691 DCHECK(renderer_);
652 DCHECK(!pending_callbacks_.get()); 692 DCHECK(!pending_callbacks_.get());
(...skipping 27 matching lines...) Expand all
680 base::Unretained(text_renderer_.get()))); 720 base::Unretained(text_renderer_.get())));
681 } 721 }
682 722
683 pending_callbacks_ = SerialRunner::Run( 723 pending_callbacks_ = SerialRunner::Run(
684 fns, base::Bind(&PipelineImpl::StateTransitionTask, weak_this_)); 724 fns, base::Bind(&PipelineImpl::StateTransitionTask, weak_this_));
685 } 725 }
686 726
687 void PipelineImpl::ResumeTask(std::unique_ptr<Renderer> renderer, 727 void PipelineImpl::ResumeTask(std::unique_ptr<Renderer> renderer,
688 base::TimeDelta timestamp, 728 base::TimeDelta timestamp,
689 const PipelineStatusCB& seek_cb) { 729 const PipelineStatusCB& seek_cb) {
690 DCHECK(task_runner_->BelongsToCurrentThread()); 730 DCHECK(media_task_runner_->BelongsToCurrentThread());
691 731
692 // Suppress resuming if we're not suspended. 732 // Suppress resuming if we're not suspended.
693 if (state_ != kSuspended) { 733 if (state_ != kSuspended) {
694 DCHECK(state_ == kStopping || state_ == kStopped) 734 DCHECK(state_ == kStopping || state_ == kStopped)
695 << "Receive resume in unexpected state: " << state_; 735 << "Receive resume in unexpected state: " << state_;
696 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE); 736 seek_cb.Run(PIPELINE_ERROR_INVALID_STATE);
697 return; 737 return;
698 } 738 }
699 DCHECK(!renderer_); 739 DCHECK(!renderer_);
700 DCHECK(!pending_callbacks_.get()); 740 DCHECK(!pending_callbacks_.get());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 } 774 }
735 775
736 renderer_->SetCdm(cdm_context, 776 renderer_->SetCdm(cdm_context,
737 base::Bind(&PipelineImpl::OnCdmAttached, weak_this_, 777 base::Bind(&PipelineImpl::OnCdmAttached, weak_this_,
738 cdm_attached_cb, cdm_context)); 778 cdm_attached_cb, cdm_context));
739 } 779 }
740 780
741 void PipelineImpl::OnCdmAttached(const CdmAttachedCB& cdm_attached_cb, 781 void PipelineImpl::OnCdmAttached(const CdmAttachedCB& cdm_attached_cb,
742 CdmContext* cdm_context, 782 CdmContext* cdm_context,
743 bool success) { 783 bool success) {
744 DCHECK(task_runner_->BelongsToCurrentThread()); 784 DCHECK(media_task_runner_->BelongsToCurrentThread());
745 if (success) 785 if (success)
746 cdm_context_ = cdm_context; 786 cdm_context_ = cdm_context;
747 cdm_attached_cb.Run(success); 787 cdm_attached_cb.Run(success);
748 } 788 }
749 789
750 void PipelineImpl::OnRendererEnded() { 790 void PipelineImpl::OnRendererEnded() {
751 DCHECK(task_runner_->BelongsToCurrentThread()); 791 DCHECK(media_task_runner_->BelongsToCurrentThread());
752 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); 792 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED));
753 793
754 if (state_ != kPlaying) 794 if (state_ != kPlaying)
755 return; 795 return;
756 796
757 DCHECK(!renderer_ended_); 797 DCHECK(!renderer_ended_);
758 renderer_ended_ = true; 798 renderer_ended_ = true;
759 799
760 RunEndedCallbackIfNeeded(); 800 RunEndedCallbackIfNeeded();
761 } 801 }
762 802
763 void PipelineImpl::OnTextRendererEnded() { 803 void PipelineImpl::OnTextRendererEnded() {
764 DCHECK(task_runner_->BelongsToCurrentThread()); 804 DCHECK(media_task_runner_->BelongsToCurrentThread());
765 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED)); 805 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::TEXT_ENDED));
766 806
767 if (state_ != kPlaying) 807 if (state_ != kPlaying)
768 return; 808 return;
769 809
770 DCHECK(!text_renderer_ended_); 810 DCHECK(!text_renderer_ended_);
771 text_renderer_ended_ = true; 811 text_renderer_ended_ = true;
772 812
773 RunEndedCallbackIfNeeded(); 813 RunEndedCallbackIfNeeded();
774 } 814 }
775 815
776 void PipelineImpl::RunEndedCallbackIfNeeded() { 816 void PipelineImpl::RunEndedCallbackIfNeeded() {
777 DCHECK(task_runner_->BelongsToCurrentThread()); 817 DCHECK(media_task_runner_->BelongsToCurrentThread());
778 818
779 if (renderer_ && !renderer_ended_) 819 if (renderer_ && !renderer_ended_)
780 return; 820 return;
781 821
782 if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_) 822 if (text_renderer_ && text_renderer_->HasTracks() && !text_renderer_ended_)
783 return; 823 return;
784 824
785 DCHECK_EQ(status_, PIPELINE_OK); 825 DCHECK_EQ(status_, PIPELINE_OK);
786 ended_cb_.Run(); 826 main_task_runner_->PostTask(FROM_HERE, base::Bind(&Pipeline::Client::OnEnded,
827 base::Unretained(client_)));
787 } 828 }
788 829
789 std::unique_ptr<TextRenderer> PipelineImpl::CreateTextRenderer() { 830 std::unique_ptr<TextRenderer> PipelineImpl::CreateTextRenderer() {
790 DCHECK(task_runner_->BelongsToCurrentThread()); 831 DCHECK(media_task_runner_->BelongsToCurrentThread());
791 832
792 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); 833 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
793 if (!cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) 834 if (!cmd_line->HasSwitch(switches::kEnableInbandTextTracks))
794 return nullptr; 835 return nullptr;
795 836
796 return base::WrapUnique(new media::TextRenderer( 837 return base::WrapUnique(new media::TextRenderer(
797 task_runner_, base::Bind(&PipelineImpl::OnAddTextTrack, weak_this_))); 838 media_task_runner_,
839 base::Bind(&PipelineImpl::OnAddTextTrack, weak_this_)));
798 } 840 }
799 841
800 void PipelineImpl::AddTextStreamTask(DemuxerStream* text_stream, 842 void PipelineImpl::AddTextStreamTask(DemuxerStream* text_stream,
801 const TextTrackConfig& config) { 843 const TextTrackConfig& config) {
802 DCHECK(task_runner_->BelongsToCurrentThread()); 844 DCHECK(media_task_runner_->BelongsToCurrentThread());
803 // TODO(matthewjheaney): fix up text_ended_ when text stream 845 // TODO(matthewjheaney): fix up text_ended_ when text stream
804 // is added (http://crbug.com/321446). 846 // is added (http://crbug.com/321446).
805 if (text_renderer_) 847 if (text_renderer_)
806 text_renderer_->AddTextStream(text_stream, config); 848 text_renderer_->AddTextStream(text_stream, config);
807 } 849 }
808 850
809 void PipelineImpl::RemoveTextStreamTask(DemuxerStream* text_stream) { 851 void PipelineImpl::RemoveTextStreamTask(DemuxerStream* text_stream) {
810 DCHECK(task_runner_->BelongsToCurrentThread()); 852 DCHECK(media_task_runner_->BelongsToCurrentThread());
853
811 if (text_renderer_) 854 if (text_renderer_)
812 text_renderer_->RemoveTextStream(text_stream); 855 text_renderer_->RemoveTextStream(text_stream);
813 } 856 }
814 857
815 void PipelineImpl::OnAddTextTrack(const TextTrackConfig& config, 858 void PipelineImpl::OnAddTextTrack(const TextTrackConfig& config,
816 const AddTextTrackDoneCB& done_cb) { 859 const AddTextTrackDoneCB& done_cb) {
817 DCHECK(task_runner_->BelongsToCurrentThread()); 860 DCHECK(media_task_runner_->BelongsToCurrentThread());
818 add_text_track_cb_.Run(config, done_cb); 861
862 main_task_runner_->PostTask(
863 FROM_HERE, base::Bind(&Pipeline::Client::OnAddTextTrack,
864 base::Unretained(client_), config, done_cb));
819 } 865 }
820 866
821 void PipelineImpl::InitializeDemuxer(const PipelineStatusCB& done_cb) { 867 void PipelineImpl::InitializeDemuxer(const PipelineStatusCB& done_cb) {
822 DCHECK(task_runner_->BelongsToCurrentThread()); 868 DCHECK(media_task_runner_->BelongsToCurrentThread());
869
823 demuxer_->Initialize(this, done_cb, !!text_renderer_); 870 demuxer_->Initialize(this, done_cb, !!text_renderer_);
824 } 871 }
825 872
826 void PipelineImpl::InitializeRenderer(const PipelineStatusCB& done_cb) { 873 void PipelineImpl::InitializeRenderer(const PipelineStatusCB& done_cb) {
827 DCHECK(task_runner_->BelongsToCurrentThread()); 874 DCHECK(media_task_runner_->BelongsToCurrentThread());
828 875
829 if (!demuxer_->GetStream(DemuxerStream::AUDIO) && 876 if (!demuxer_->GetStream(DemuxerStream::AUDIO) &&
830 !demuxer_->GetStream(DemuxerStream::VIDEO)) { 877 !demuxer_->GetStream(DemuxerStream::VIDEO)) {
831 { 878 {
832 base::AutoLock auto_lock(lock_); 879 base::AutoLock auto_lock(lock_);
833 renderer_.reset(); 880 renderer_.reset();
834 } 881 }
835 OnError(PIPELINE_ERROR_COULD_NOT_RENDER); 882 OnError(PIPELINE_ERROR_COULD_NOT_RENDER);
836 return; 883 return;
837 } 884 }
838 885
839 if (cdm_context_) 886 if (cdm_context_)
840 renderer_->SetCdm(cdm_context_, base::Bind(&IgnoreCdmAttached)); 887 renderer_->SetCdm(cdm_context_, base::Bind(&IgnoreCdmAttached));
841 888
842 renderer_->Initialize( 889 renderer_->Initialize(
843 demuxer_, done_cb, 890 demuxer_, done_cb,
844 base::Bind(&PipelineImpl::OnUpdateStatistics, weak_this_), 891 base::Bind(&PipelineImpl::OnUpdateStatistics, weak_this_),
845 base::Bind(&PipelineImpl::BufferingStateChanged, weak_this_), 892 base::Bind(&PipelineImpl::BufferingStateChanged, weak_this_),
846 base::Bind(&PipelineImpl::OnRendererEnded, weak_this_), 893 base::Bind(&PipelineImpl::OnRendererEnded, weak_this_),
847 base::Bind(&PipelineImpl::OnError, weak_this_), 894 base::Bind(&PipelineImpl::OnError, weak_this_),
848 waiting_for_decryption_key_cb_); 895 base::Bind(&PipelineImpl::OnWaitingForDecryptionKey, weak_this_));
849 } 896 }
850 897
851 void PipelineImpl::ReportMetadata() { 898 void PipelineImpl::ReportMetadata() {
852 DCHECK(task_runner_->BelongsToCurrentThread()); 899 DCHECK(media_task_runner_->BelongsToCurrentThread());
900
853 PipelineMetadata metadata; 901 PipelineMetadata metadata;
854 metadata.timeline_offset = demuxer_->GetTimelineOffset(); 902 metadata.timeline_offset = demuxer_->GetTimelineOffset();
855 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 903 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
856 if (stream) { 904 if (stream) {
857 metadata.has_video = true; 905 metadata.has_video = true;
858 metadata.natural_size = stream->video_decoder_config().natural_size(); 906 metadata.natural_size = stream->video_decoder_config().natural_size();
859 metadata.video_rotation = stream->video_rotation(); 907 metadata.video_rotation = stream->video_rotation();
860 } 908 }
861 if (demuxer_->GetStream(DemuxerStream::AUDIO)) { 909 if (demuxer_->GetStream(DemuxerStream::AUDIO)) {
862 metadata.has_audio = true; 910 metadata.has_audio = true;
863 } 911 }
864 metadata_cb_.Run(metadata); 912
913 main_task_runner_->PostTask(FROM_HERE,
914 base::Bind(&Pipeline::Client::OnMetadata,
915 base::Unretained(client_), metadata));
865 } 916 }
866 917
867 void PipelineImpl::BufferingStateChanged(BufferingState new_buffering_state) { 918 void PipelineImpl::BufferingStateChanged(BufferingState new_buffering_state) {
919 DCHECK(media_task_runner_->BelongsToCurrentThread());
868 DVLOG(1) << __FUNCTION__ << "(" << new_buffering_state << ") "; 920 DVLOG(1) << __FUNCTION__ << "(" << new_buffering_state << ") ";
869 DCHECK(task_runner_->BelongsToCurrentThread()); 921
870 buffering_state_cb_.Run(new_buffering_state); 922 main_task_runner_->PostTask(
923 FROM_HERE, base::Bind(&Pipeline::Client::OnBufferingStateChange,
924 base::Unretained(client_), new_buffering_state));
871 } 925 }
872 926
873 } // namespace media 927 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698