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

Side by Side Diff: media/base/android/media_source_player.cc

Issue 254473010: Refactor MSE implementation on Android to simplify the logic and improve the performance (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/android/media_source_player.h" 5 #include "media/base/android/media_source_player.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/android/jni_android.h" 9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
(...skipping 17 matching lines...) Expand all
28 MediaPlayerManager* manager, 28 MediaPlayerManager* manager,
29 const RequestMediaResourcesCB& request_media_resources_cb, 29 const RequestMediaResourcesCB& request_media_resources_cb,
30 const ReleaseMediaResourcesCB& release_media_resources_cb, 30 const ReleaseMediaResourcesCB& release_media_resources_cb,
31 scoped_ptr<DemuxerAndroid> demuxer) 31 scoped_ptr<DemuxerAndroid> demuxer)
32 : MediaPlayerAndroid(player_id, 32 : MediaPlayerAndroid(player_id,
33 manager, 33 manager,
34 request_media_resources_cb, 34 request_media_resources_cb,
35 release_media_resources_cb), 35 release_media_resources_cb),
36 demuxer_(demuxer.Pass()), 36 demuxer_(demuxer.Pass()),
37 pending_event_(NO_EVENT_PENDING), 37 pending_event_(NO_EVENT_PENDING),
38 width_(0),
39 height_(0),
40 audio_codec_(kUnknownAudioCodec),
41 video_codec_(kUnknownVideoCodec),
42 num_channels_(0),
43 sampling_rate_(0),
44 reached_audio_eos_(false),
45 reached_video_eos_(false),
46 playing_(false), 38 playing_(false),
47 is_audio_encrypted_(false),
48 is_video_encrypted_(false),
49 volume_(-1.0),
50 clock_(&default_tick_clock_), 39 clock_(&default_tick_clock_),
51 next_video_data_is_iframe_(true),
52 doing_browser_seek_(false), 40 doing_browser_seek_(false),
53 pending_seek_(false), 41 pending_seek_(false),
54 reconfig_audio_decoder_(false),
55 reconfig_video_decoder_(false),
56 drm_bridge_(NULL), 42 drm_bridge_(NULL),
57 is_waiting_for_key_(false), 43 is_waiting_for_key_(false),
58 has_pending_audio_data_request_(false), 44 is_waiting_for_audio_decoder_(false),
59 has_pending_video_data_request_(false), 45 is_waiting_for_video_decoder_(false),
60 weak_factory_(this) { 46 weak_factory_(this) {
47 audio_decoder_job_.reset(new AudioDecoderJob(
48 base::Bind(&DemuxerAndroid::RequestDemuxerData,
49 base::Unretained(demuxer_.get()),
50 DemuxerStream::AUDIO),
51 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged,
52 weak_factory_.GetWeakPtr())));
53 video_decoder_job_.reset(new VideoDecoderJob(
54 base::Bind(&DemuxerAndroid::RequestDemuxerData,
55 base::Unretained(demuxer_.get()),
56 DemuxerStream::VIDEO),
57 base::Bind(request_media_resources_cb_, player_id),
58 base::Bind(release_media_resources_cb_, player_id),
59 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged,
60 weak_factory_.GetWeakPtr())));
61 demuxer_->Initialize(this); 61 demuxer_->Initialize(this);
62 clock_.SetMaxTime(base::TimeDelta()); 62 clock_.SetMaxTime(base::TimeDelta());
63 } 63 }
64 64
65 MediaSourcePlayer::~MediaSourcePlayer() { 65 MediaSourcePlayer::~MediaSourcePlayer() {
66 Release(); 66 Release();
67 } 67 }
68 68
69 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { 69 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) {
70 // For an empty surface, always pass it to the decoder job so that it 70 DVLOG(1) << __FUNCTION__;
71 // can detach from the current one. Otherwise, don't pass an unprotected 71 // If the player is waiting for the video decoder job, retry video decoder
72 // surface if the video content requires a protected one. 72 // creation.
73 if (!surface.IsEmpty() && 73 if (is_waiting_for_video_decoder_)
74 IsProtectedSurfaceRequired() && !surface.is_protected()) { 74 is_waiting_for_video_decoder_ = false;
75
76 if (!video_decoder_job_->SetVideoSurface(surface.Pass()))
75 return; 77 return;
76 } 78 if (IsEventPending(DECODER_CREATION_EVENT_PENDING))
77 79 ProcessPendingEvents();
78 surface_ = surface.Pass();
79 is_surface_in_use_ = true;
80
81 // If there is a pending surface change event, just wait for it to be
82 // processed.
83 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING))
84 return;
85
86 // Eventual processing of surface change will take care of feeding the new
87 // video decoder initially with I-frame. See b/8950387.
88 SetPendingEvent(SURFACE_CHANGE_EVENT_PENDING);
89
90 // If seek is already pending, processing of the pending surface change
91 // event will occur in OnDemuxerSeekDone().
92 if (IsEventPending(SEEK_EVENT_PENDING))
93 return;
94
95 // If video config change is already pending, processing of the pending
96 // surface change event will occur in OnDemuxerConfigsAvailable().
97 if (reconfig_video_decoder_ && IsEventPending(CONFIG_CHANGE_EVENT_PENDING))
98 return;
99
100 // Otherwise we need to trigger pending event processing now.
101 ProcessPendingEvents();
102 } 80 }
103 81
104 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( 82 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding(
105 base::TimeDelta seek_time) { 83 base::TimeDelta seek_time) {
106 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; 84 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")";
107 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); 85 DCHECK(!IsEventPending(SEEK_EVENT_PENDING));
108 86
109 pending_seek_ = false; 87 pending_seek_ = false;
110 88
111 clock_.SetTime(seek_time, seek_time); 89 clock_.SetTime(seek_time, seek_time);
112 90
113 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) 91 if (audio_decoder_job_->is_decoding())
114 audio_decoder_job_->StopDecode(); 92 audio_decoder_job_->StopDecode();
115 if (video_decoder_job_ && video_decoder_job_->is_decoding()) 93 if (video_decoder_job_->is_decoding())
116 video_decoder_job_->StopDecode(); 94 video_decoder_job_->StopDecode();
117 95
118 SetPendingEvent(SEEK_EVENT_PENDING); 96 SetPendingEvent(SEEK_EVENT_PENDING);
119 ProcessPendingEvents(); 97 ProcessPendingEvents();
120 } 98 }
121 99
122 void MediaSourcePlayer::BrowserSeekToCurrentTime() { 100 void MediaSourcePlayer::BrowserSeekToCurrentTime() {
123 DVLOG(1) << __FUNCTION__; 101 DVLOG(1) << __FUNCTION__;
124 102
125 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); 103 DCHECK(!IsEventPending(SEEK_EVENT_PENDING));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 // MediaDecoderCallback() is called. 135 // MediaDecoderCallback() is called.
158 playing_ = false; 136 playing_ = false;
159 start_time_ticks_ = base::TimeTicks(); 137 start_time_ticks_ = base::TimeTicks();
160 } 138 }
161 139
162 bool MediaSourcePlayer::IsPlaying() { 140 bool MediaSourcePlayer::IsPlaying() {
163 return playing_; 141 return playing_;
164 } 142 }
165 143
166 int MediaSourcePlayer::GetVideoWidth() { 144 int MediaSourcePlayer::GetVideoWidth() {
167 return width_; 145 return video_decoder_job_->width();
168 } 146 }
169 147
170 int MediaSourcePlayer::GetVideoHeight() { 148 int MediaSourcePlayer::GetVideoHeight() {
171 return height_; 149 return video_decoder_job_->height();
172 } 150 }
173 151
174 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { 152 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
175 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")"; 153 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")";
176 154
177 if (IsEventPending(SEEK_EVENT_PENDING)) { 155 if (IsEventPending(SEEK_EVENT_PENDING)) {
178 DCHECK(doing_browser_seek_) << "SeekTo while SeekTo in progress"; 156 DCHECK(doing_browser_seek_) << "SeekTo while SeekTo in progress";
179 DCHECK(!pending_seek_) << "SeekTo while SeekTo pending browser seek"; 157 DCHECK(!pending_seek_) << "SeekTo while SeekTo pending browser seek";
180 158
181 // There is a browser seek currently in progress to obtain I-frame to feed 159 // There is a browser seek currently in progress to obtain I-frame to feed
(...skipping 12 matching lines...) Expand all
194 return clock_.Elapsed(); 172 return clock_.Elapsed();
195 } 173 }
196 174
197 base::TimeDelta MediaSourcePlayer::GetDuration() { 175 base::TimeDelta MediaSourcePlayer::GetDuration() {
198 return duration_; 176 return duration_;
199 } 177 }
200 178
201 void MediaSourcePlayer::Release() { 179 void MediaSourcePlayer::Release() {
202 DVLOG(1) << __FUNCTION__; 180 DVLOG(1) << __FUNCTION__;
203 181
204 // Allow pending seeks and config changes to survive this Release().
205 // If previously pending a prefetch done event, or a job was still decoding,
206 // then at end of Release() we need to ProcessPendingEvents() to process any
207 // seek or config change that was blocked by the prefetch or decode.
208 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data
209 // or drop data received across Release()+Start(). See http://crbug.com/306314
210 // and http://crbug.com/304234.
211 bool process_pending_events = false;
212 process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) ||
213 (audio_decoder_job_ && audio_decoder_job_->is_decoding()) ||
214 (video_decoder_job_ && video_decoder_job_->is_decoding());
215
216 // Clear all the pending events except seeks and config changes.
217 pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING);
218 is_surface_in_use_ = false; 182 is_surface_in_use_ = false;
219 ResetAudioDecoderJob(); 183 audio_decoder_job_->ReleaseDecoderResources();
220 ResetVideoDecoderJob(); 184 video_decoder_job_->ReleaseDecoderResources();
221
222 // Prevent job re-creation attempts in OnDemuxerConfigsAvailable()
223 reconfig_audio_decoder_ = false;
224 reconfig_video_decoder_ = false;
225 185
226 // Prevent player restart, including job re-creation attempts. 186 // Prevent player restart, including job re-creation attempts.
227 playing_ = false; 187 playing_ = false;
228 188
229 decoder_starvation_callback_.Cancel(); 189 decoder_starvation_callback_.Cancel();
230 surface_ = gfx::ScopedJavaSurface();
231 if (process_pending_events) {
232 DVLOG(1) << __FUNCTION__ << " : Resuming seek or config change processing";
233 ProcessPendingEvents();
234 }
235 } 190 }
236 191
237 void MediaSourcePlayer::SetVolume(double volume) { 192 void MediaSourcePlayer::SetVolume(double volume) {
238 volume_ = volume; 193 audio_decoder_job_->SetVolume(volume);
239 SetVolumeInternal();
240 } 194 }
241 195
242 void MediaSourcePlayer::OnKeyAdded() { 196 void MediaSourcePlayer::OnKeyAdded() {
243 DVLOG(1) << __FUNCTION__; 197 DVLOG(1) << __FUNCTION__;
244 if (!is_waiting_for_key_) 198 if (!is_waiting_for_key_)
245 return; 199 return;
246 200
247 is_waiting_for_key_ = false; 201 is_waiting_for_key_ = false;
248 if (playing_) 202 if (playing_)
249 StartInternal(); 203 StartInternal();
(...skipping 23 matching lines...) Expand all
273 DVLOG(1) << __FUNCTION__; 227 DVLOG(1) << __FUNCTION__;
274 // If there are pending events, wait for them finish. 228 // If there are pending events, wait for them finish.
275 if (pending_event_ != NO_EVENT_PENDING) 229 if (pending_event_ != NO_EVENT_PENDING)
276 return; 230 return;
277 231
278 // When we start, we'll have new demuxed data coming in. This new data could 232 // When we start, we'll have new demuxed data coming in. This new data could
279 // be clear (not encrypted) or encrypted with different keys. So 233 // be clear (not encrypted) or encrypted with different keys. So
280 // |is_waiting_for_key_| condition may not be true anymore. 234 // |is_waiting_for_key_| condition may not be true anymore.
281 is_waiting_for_key_ = false; 235 is_waiting_for_key_ = false;
282 236
283 // Create decoder jobs if they are not created
284 ConfigureAudioDecoderJob();
285 ConfigureVideoDecoderJob();
286
287 // If one of the decoder job is not ready, do nothing.
288 if ((HasAudio() && !audio_decoder_job_) ||
289 (HasVideo() && !video_decoder_job_)) {
290 return;
291 }
292
293 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 237 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
294 ProcessPendingEvents(); 238 ProcessPendingEvents();
295 } 239 }
296 240
297 void MediaSourcePlayer::OnDemuxerConfigsAvailable( 241 void MediaSourcePlayer::OnDemuxerConfigsAvailable(
298 const DemuxerConfigs& configs) { 242 const DemuxerConfigs& configs) {
299 DVLOG(1) << __FUNCTION__; 243 DVLOG(1) << __FUNCTION__;
300 duration_ = configs.duration; 244 duration_ = configs.duration;
301 clock_.SetDuration(duration_); 245 clock_.SetDuration(duration_);
302 246
303 audio_codec_ = configs.audio_codec; 247 audio_decoder_job_->SetDemuxerConfigs(configs);
304 num_channels_ = configs.audio_channels; 248 video_decoder_job_->SetDemuxerConfigs(configs);
305 sampling_rate_ = configs.audio_sampling_rate; 249 OnDemuxerConfigsChanged();
306 is_audio_encrypted_ = configs.is_audio_encrypted;
307 audio_extra_data_ = configs.audio_extra_data;
308 video_codec_ = configs.video_codec;
309 width_ = configs.video_size.width();
310 height_ = configs.video_size.height();
311 is_video_encrypted_ = configs.is_video_encrypted;
312
313 manager()->OnMediaMetadataChanged(
314 player_id(), duration_, width_, height_, true);
315
316 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) {
317 if (reconfig_audio_decoder_)
318 ConfigureAudioDecoderJob();
319
320 if (reconfig_video_decoder_)
321 ConfigureVideoDecoderJob();
322
323 ClearPendingEvent(CONFIG_CHANGE_EVENT_PENDING);
324
325 // Resume decoding after the config change if we are still playing.
326 if (playing_)
327 StartInternal();
328 }
329 } 250 }
330 251
331 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { 252 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) {
332 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")"; 253 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")";
333 DCHECK_LT(0u, data.access_units.size()); 254 DCHECK_LT(0u, data.access_units.size());
334 255
335 if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { 256 if (data.type == DemuxerStream::AUDIO)
336 has_pending_audio_data_request_ = false;
337 ProcessPendingEvents();
338 return;
339 }
340
341 if (has_pending_video_data_request_ && data.type == DemuxerStream::VIDEO) {
342 next_video_data_is_iframe_ = false;
343 has_pending_video_data_request_ = false;
344 ProcessPendingEvents();
345 return;
346 }
347
348 if (data.type == DemuxerStream::AUDIO && audio_decoder_job_) {
349 audio_decoder_job_->OnDataReceived(data); 257 audio_decoder_job_->OnDataReceived(data);
350 } else if (data.type == DemuxerStream::VIDEO) { 258 else if (data.type == DemuxerStream::VIDEO)
351 next_video_data_is_iframe_ = false; 259 video_decoder_job_->OnDataReceived(data);
352 if (video_decoder_job_)
353 video_decoder_job_->OnDataReceived(data);
354 }
355 } 260 }
356 261
357 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) { 262 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) {
358 duration_ = duration; 263 duration_ = duration;
359 clock_.SetDuration(duration_); 264 clock_.SetDuration(duration_);
360 } 265 }
361 266
362 base::android::ScopedJavaLocalRef<jobject> MediaSourcePlayer::GetMediaCrypto() { 267 base::android::ScopedJavaLocalRef<jobject> MediaSourcePlayer::GetMediaCrypto() {
363 base::android::ScopedJavaLocalRef<jobject> media_crypto; 268 base::android::ScopedJavaLocalRef<jobject> media_crypto;
364 if (drm_bridge_) 269 if (drm_bridge_)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 302 }
398 303
399 void MediaSourcePlayer::OnDemuxerSeekDone( 304 void MediaSourcePlayer::OnDemuxerSeekDone(
400 base::TimeDelta actual_browser_seek_time) { 305 base::TimeDelta actual_browser_seek_time) {
401 DVLOG(1) << __FUNCTION__; 306 DVLOG(1) << __FUNCTION__;
402 307
403 ClearPendingEvent(SEEK_EVENT_PENDING); 308 ClearPendingEvent(SEEK_EVENT_PENDING);
404 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) 309 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING))
405 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 310 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
406 311
407 next_video_data_is_iframe_ = true;
408
409 if (pending_seek_) { 312 if (pending_seek_) {
410 DVLOG(1) << __FUNCTION__ << "processing pending seek"; 313 DVLOG(1) << __FUNCTION__ << "processing pending seek";
411 DCHECK(doing_browser_seek_); 314 DCHECK(doing_browser_seek_);
412 pending_seek_ = false; 315 pending_seek_ = false;
413 SeekTo(pending_seek_time_); 316 SeekTo(pending_seek_time_);
414 return; 317 return;
415 } 318 }
416 319
417 // It is possible that a browser seek to I-frame had to seek to a buffered 320 // It is possible that a browser seek to I-frame had to seek to a buffered
418 // I-frame later than the requested one due to data removal or GC. Update 321 // I-frame later than the requested one due to data removal or GC. Update
419 // player clock to the actual seek target. 322 // player clock to the actual seek target.
420 if (doing_browser_seek_) { 323 if (doing_browser_seek_) {
421 DCHECK(actual_browser_seek_time != kNoTimestamp()); 324 DCHECK(actual_browser_seek_time != kNoTimestamp());
422 base::TimeDelta seek_time = actual_browser_seek_time; 325 base::TimeDelta seek_time = actual_browser_seek_time;
423 // A browser seek must not jump into the past. Ideally, it seeks to the 326 // A browser seek must not jump into the past. Ideally, it seeks to the
424 // requested time, but it might jump into the future. 327 // requested time, but it might jump into the future.
425 DCHECK(seek_time >= GetCurrentTime()); 328 DCHECK(seek_time >= GetCurrentTime());
426 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " 329 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: "
427 << seek_time.InSecondsF(); 330 << seek_time.InSecondsF();
428 clock_.SetTime(seek_time, seek_time); 331 clock_.SetTime(seek_time, seek_time);
429 if (audio_decoder_job_)
430 audio_decoder_job_->SetBaseTimestamp(seek_time);
431 } else { 332 } else {
432 DCHECK(actual_browser_seek_time == kNoTimestamp()); 333 DCHECK(actual_browser_seek_time == kNoTimestamp());
433 } 334 }
434 335
435 reached_audio_eos_ = false;
436 reached_video_eos_ = false;
437
438 base::TimeDelta current_time = GetCurrentTime(); 336 base::TimeDelta current_time = GetCurrentTime();
439 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| 337 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_|
440 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| 338 // to preroll media decoder jobs. Currently |start_presentation_timestamp_|
441 // is calculated from decoder output, while preroll relies on the access 339 // is calculated from decoder output, while preroll relies on the access
442 // unit's timestamp. There are some differences between the two. 340 // unit's timestamp. There are some differences between the two.
443 preroll_timestamp_ = current_time; 341 preroll_timestamp_ = current_time;
444 if (audio_decoder_job_) 342 if (HasAudio())
445 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); 343 audio_decoder_job_->BeginPrerolling(preroll_timestamp_);
446 if (video_decoder_job_) 344 if (HasVideo())
447 video_decoder_job_->BeginPrerolling(preroll_timestamp_); 345 video_decoder_job_->BeginPrerolling(preroll_timestamp_);
448 346
449 if (!doing_browser_seek_) 347 if (!doing_browser_seek_)
450 manager()->OnSeekComplete(player_id(), current_time); 348 manager()->OnSeekComplete(player_id(), current_time);
451 349
452 ProcessPendingEvents(); 350 ProcessPendingEvents();
453 } 351 }
454 352
455 void MediaSourcePlayer::UpdateTimestamps( 353 void MediaSourcePlayer::UpdateTimestamps(
456 base::TimeDelta current_presentation_timestamp, 354 base::TimeDelta current_presentation_timestamp,
457 base::TimeDelta max_presentation_timestamp) { 355 base::TimeDelta max_presentation_timestamp) {
458 clock_.SetTime(current_presentation_timestamp, max_presentation_timestamp); 356 clock_.SetTime(current_presentation_timestamp, max_presentation_timestamp);
459
460 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); 357 manager()->OnTimeUpdate(player_id(), GetCurrentTime());
461 } 358 }
462 359
463 void MediaSourcePlayer::ProcessPendingEvents() { 360 void MediaSourcePlayer::ProcessPendingEvents() {
464 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; 361 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_;
465 // Wait for all the decoding jobs to finish before processing pending tasks. 362 // Wait for all the decoding jobs to finish before processing pending tasks.
466 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { 363 if (video_decoder_job_->is_decoding()) {
467 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; 364 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding.";
468 return; 365 return;
469 } 366 }
470 367
471 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) { 368 if (audio_decoder_job_->is_decoding()) {
472 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding."; 369 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding.";
473 return; 370 return;
474 } 371 }
475 372
476 if (has_pending_audio_data_request_ || has_pending_video_data_request_) {
477 DVLOG(1) << __FUNCTION__ << " : has pending data request.";
478 return;
479 }
480
481 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { 373 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) {
482 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending."; 374 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending.";
483 return; 375 return;
484 } 376 }
485 377
486 if (IsEventPending(SEEK_EVENT_PENDING)) { 378 if (IsEventPending(SEEK_EVENT_PENDING)) {
487 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT"; 379 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT";
488 ClearDecodingData(); 380 ClearDecodingData();
489 if (audio_decoder_job_) 381 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime());
490 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime());
491 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); 382 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_);
492 return; 383 return;
493 } 384 }
494 385
495 start_time_ticks_ = base::TimeTicks(); 386 if (IsEventPending(DECODER_CREATION_EVENT_PENDING)) {
496 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { 387 // Don't continue if one of the decoder is not created.
497 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; 388 if (is_waiting_for_audio_decoder_ || is_waiting_for_video_decoder_)
498 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_);
499 demuxer_->RequestDemuxerConfigs();
500 return;
501 }
502
503 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) {
504 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT.";
505 // Setting a new surface will require a new MediaCodec to be created.
506 ResetVideoDecoderJob();
507 ConfigureVideoDecoderJob();
508
509 // Return early if we can't successfully configure a new video decoder job
510 // yet.
511 if (HasVideo() && !video_decoder_job_)
512 return; 389 return;
390 ClearPendingEvent(DECODER_CREATION_EVENT_PENDING);
513 } 391 }
514 392
515 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { 393 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) {
516 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; 394 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT.";
517 // If one of the decoder is not initialized, cancel this event as it will be
518 // called later when Start() is called again.
519 if ((HasVideo() && !video_decoder_job_) ||
520 (HasAudio() && !audio_decoder_job_)) {
521 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
522 return;
523 }
524
525 DCHECK(audio_decoder_job_ || AudioFinished());
526 DCHECK(video_decoder_job_ || VideoFinished());
527 395
528 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); 396 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1);
529 397
530 // It is possible that all streams have finished decode, yet starvation 398 // It is possible that all streams have finished decode, yet starvation
531 // occurred during the last stream's EOS decode. In this case, prefetch is a 399 // occurred during the last stream's EOS decode. In this case, prefetch is a
532 // no-op. 400 // no-op.
533 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 401 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
534 if (count == 0) 402 if (count == 0)
535 return; 403 return;
536 404
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of 467 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of
600 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process 468 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process
601 // any other pending events only after handling EOS detection. 469 // any other pending events only after handling EOS detection.
602 if (IsEventPending(SEEK_EVENT_PENDING)) { 470 if (IsEventPending(SEEK_EVENT_PENDING)) {
603 ProcessPendingEvents(); 471 ProcessPendingEvents();
604 return; 472 return;
605 } 473 }
606 474
607 if (status == MEDIA_CODEC_OK && is_clock_manager && 475 if (status == MEDIA_CODEC_OK && is_clock_manager &&
608 current_presentation_timestamp != kNoTimestamp()) { 476 current_presentation_timestamp != kNoTimestamp()) {
609 UpdateTimestamps( 477 UpdateTimestamps(current_presentation_timestamp,
610 current_presentation_timestamp, max_presentation_timestamp); 478 max_presentation_timestamp);
611 } 479 }
612 480
613 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) 481 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM)
614 PlaybackCompleted(is_audio); 482 PlaybackCompleted(is_audio);
615 483
616 if (pending_event_ != NO_EVENT_PENDING) { 484 if (pending_event_ != NO_EVENT_PENDING) {
617 ProcessPendingEvents(); 485 ProcessPendingEvents();
618 return; 486 return;
619 } 487 }
620 488
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 start_time_ticks_, 534 start_time_ticks_,
667 start_presentation_timestamp_, 535 start_presentation_timestamp_,
668 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 536 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
669 weak_factory_.GetWeakPtr(), 537 weak_factory_.GetWeakPtr(),
670 true))) { 538 true))) {
671 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", 539 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio",
672 audio_decoder_job_.get()); 540 audio_decoder_job_.get());
673 return; 541 return;
674 } 542 }
675 543
676 // Failed to start the next decode. 544 is_waiting_for_audio_decoder_ = true;
677 // Wait for demuxer ready message. 545 if (!IsEventPending(DECODER_CREATION_EVENT_PENDING))
678 DCHECK(!reconfig_audio_decoder_); 546 SetPendingEvent(DECODER_CREATION_EVENT_PENDING);
679 reconfig_audio_decoder_ = true;
680
681 // Config change may have just been detected on the other stream. If so,
682 // don't send a duplicate demuxer config request.
683 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) {
684 DCHECK(reconfig_video_decoder_);
685 return;
686 }
687
688 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING);
689 ProcessPendingEvents();
690 } 547 }
691 548
692 void MediaSourcePlayer::DecodeMoreVideo() { 549 void MediaSourcePlayer::DecodeMoreVideo() {
693 DVLOG(1) << __FUNCTION__; 550 DVLOG(1) << __FUNCTION__;
694 DCHECK(!video_decoder_job_->is_decoding()); 551 DCHECK(!video_decoder_job_->is_decoding());
695 DCHECK(!VideoFinished()); 552 DCHECK(!VideoFinished());
696 553
697 if (video_decoder_job_->Decode( 554 if (video_decoder_job_->Decode(
698 start_time_ticks_, 555 start_time_ticks_,
699 start_presentation_timestamp_, 556 start_presentation_timestamp_,
700 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 557 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
701 weak_factory_.GetWeakPtr(), 558 weak_factory_.GetWeakPtr(),
702 false))) { 559 false))) {
703 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", 560 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo",
704 video_decoder_job_.get()); 561 video_decoder_job_.get());
705 return; 562 return;
706 } 563 }
707 564
708 // Failed to start the next decode. 565 // If the decoder is waiting for iframe, trigger a browser seek.
709 // Wait for demuxer ready message. 566 if (!video_decoder_job_->next_video_data_is_iframe()) {
710 567 BrowserSeekToCurrentTime();
711 // After this detection of video config change, next video data received
712 // will begin with I-frame.
713 next_video_data_is_iframe_ = true;
714
715 DCHECK(!reconfig_video_decoder_);
716 reconfig_video_decoder_ = true;
717
718 // Config change may have just been detected on the other stream. If so,
719 // don't send a duplicate demuxer config request.
720 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) {
721 DCHECK(reconfig_audio_decoder_);
722 return; 568 return;
723 } 569 }
724 570
725 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); 571 is_waiting_for_video_decoder_ = true;
726 ProcessPendingEvents(); 572 if (!IsEventPending(DECODER_CREATION_EVENT_PENDING))
573 SetPendingEvent(DECODER_CREATION_EVENT_PENDING);
727 } 574 }
728 575
729 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { 576 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
730 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; 577 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")";
731 if (is_audio)
732 reached_audio_eos_ = true;
733 else
734 reached_video_eos_ = true;
735 578
736 if (AudioFinished() && VideoFinished()) { 579 if (AudioFinished() && VideoFinished()) {
737 playing_ = false; 580 playing_ = false;
738 clock_.Pause(); 581 clock_.Pause();
739 start_time_ticks_ = base::TimeTicks(); 582 start_time_ticks_ = base::TimeTicks();
740 manager()->OnPlaybackComplete(player_id()); 583 manager()->OnPlaybackComplete(player_id());
741 } 584 }
742 } 585 }
743 586
744 void MediaSourcePlayer::ClearDecodingData() { 587 void MediaSourcePlayer::ClearDecodingData() {
745 DVLOG(1) << __FUNCTION__; 588 DVLOG(1) << __FUNCTION__;
746 if (audio_decoder_job_) 589 audio_decoder_job_->Flush();
747 audio_decoder_job_->Flush(); 590 video_decoder_job_->Flush();
748 if (video_decoder_job_)
749 video_decoder_job_->Flush();
750 start_time_ticks_ = base::TimeTicks(); 591 start_time_ticks_ = base::TimeTicks();
751 } 592 }
752 593
753 bool MediaSourcePlayer::HasVideo() { 594 bool MediaSourcePlayer::HasVideo() {
754 return kUnknownVideoCodec != video_codec_; 595 return video_decoder_job_->HasStream();
755 } 596 }
756 597
757 bool MediaSourcePlayer::HasAudio() { 598 bool MediaSourcePlayer::HasAudio() {
758 return kUnknownAudioCodec != audio_codec_; 599 return audio_decoder_job_->HasStream();
759 } 600 }
760 601
761 bool MediaSourcePlayer::AudioFinished() { 602 bool MediaSourcePlayer::AudioFinished() {
762 return reached_audio_eos_ || !HasAudio(); 603 return audio_decoder_job_->OutputEOSReached() || !HasAudio();
763 } 604 }
764 605
765 bool MediaSourcePlayer::VideoFinished() { 606 bool MediaSourcePlayer::VideoFinished() {
766 return reached_video_eos_ || !HasVideo(); 607 return video_decoder_job_->OutputEOSReached() || !HasVideo();
767 }
768
769 void MediaSourcePlayer::ConfigureAudioDecoderJob() {
770 if (!HasAudio()) {
771 ResetAudioDecoderJob();
772 return;
773 }
774
775 // Create audio decoder job only if config changes.
776 if (audio_decoder_job_ && !reconfig_audio_decoder_)
777 return;
778
779 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto();
780 if (is_audio_encrypted_ && media_crypto.is_null())
781 return;
782
783 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding());
784
785 ResetAudioDecoderJob();
786 DVLOG(1) << __FUNCTION__ << " : creating new audio decoder job";
787 audio_decoder_job_.reset(AudioDecoderJob::Create(
788 audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0],
789 audio_extra_data_.size(), media_crypto.obj(),
790 base::Bind(&DemuxerAndroid::RequestDemuxerData,
791 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO)));
792
793 if (audio_decoder_job_) {
794 SetVolumeInternal();
795 // Need to reset the base timestamp in |audio_decoder_job_|.
796 // TODO(qinmin): When reconfiguring the |audio_decoder_job_|, there might
797 // still be some audio frames in the decoder or in AudioTrack. Therefore,
798 // we are losing some time here. http://crbug.com/357726.
799 base::TimeDelta current_time = GetCurrentTime();
800 audio_decoder_job_->SetBaseTimestamp(current_time);
801 clock_.SetTime(current_time, current_time);
802 audio_decoder_job_->BeginPrerolling(preroll_timestamp_);
803 reconfig_audio_decoder_ = false;
804 }
805 }
806
807 void MediaSourcePlayer::ResetVideoDecoderJob() {
808 if (video_decoder_job_) {
809 has_pending_video_data_request_ =
810 video_decoder_job_->is_requesting_demuxer_data();
811 }
812 video_decoder_job_.reset();
813
814 // Any eventual video decoder job re-creation will use the current |surface_|.
815 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING))
816 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING);
817 }
818
819 void MediaSourcePlayer::ResetAudioDecoderJob() {
820 if (audio_decoder_job_) {
821 has_pending_audio_data_request_ =
822 audio_decoder_job_->is_requesting_demuxer_data();
823 }
824 audio_decoder_job_.reset();
825 }
826
827 void MediaSourcePlayer::ConfigureVideoDecoderJob() {
828 if (!HasVideo() || surface_.IsEmpty()) {
829 ResetVideoDecoderJob();
830 return;
831 }
832
833 // Create video decoder job only if config changes or we don't have a job.
834 if (video_decoder_job_ && !reconfig_video_decoder_) {
835 DCHECK(!IsEventPending(SURFACE_CHANGE_EVENT_PENDING));
836 return;
837 }
838
839 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding());
840
841 if (reconfig_video_decoder_) {
842 // No hack browser seek should be required. I-Frame must be next.
843 DCHECK(next_video_data_is_iframe_) << "Received video data between "
844 << "detecting video config change and reconfiguring video decoder";
845 }
846
847 // If uncertain that video I-frame data is next and there is no seek already
848 // in process, request browser demuxer seek so the new decoder will decode
849 // an I-frame first. Otherwise, the new MediaCodec might crash. See b/8950387.
850 // Eventual OnDemuxerSeekDone() will trigger ProcessPendingEvents() and
851 // continue from here.
852 // TODO(wolenetz): Instead of doing hack browser seek, replay cached data
853 // since last keyframe. See http://crbug.com/304234.
854 if (!next_video_data_is_iframe_ && !IsEventPending(SEEK_EVENT_PENDING)) {
855 BrowserSeekToCurrentTime();
856 return;
857 }
858
859 // Release the old VideoDecoderJob first so the surface can get released.
860 // Android does not allow 2 MediaCodec instances use the same surface.
861 ResetVideoDecoderJob();
862
863 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto();
864 if (is_video_encrypted_ && media_crypto.is_null())
865 return;
866
867 DVLOG(1) << __FUNCTION__ << " : creating new video decoder job";
868
869 // Create the new VideoDecoderJob.
870 bool is_secure = IsProtectedSurfaceRequired();
871 video_decoder_job_.reset(
872 VideoDecoderJob::Create(
873 video_codec_,
874 is_secure,
875 gfx::Size(width_, height_),
876 surface_.j_surface().obj(),
877 media_crypto.obj(),
878 base::Bind(&DemuxerAndroid::RequestDemuxerData,
879 base::Unretained(demuxer_.get()),
880 DemuxerStream::VIDEO),
881 base::Bind(request_media_resources_cb_, player_id()),
882 base::Bind(release_media_resources_cb_, player_id())));
883 if (!video_decoder_job_)
884 return;
885
886 video_decoder_job_->BeginPrerolling(preroll_timestamp_);
887 reconfig_video_decoder_ = false;
888
889 // Inform the fullscreen view the player is ready.
890 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
891 // to inform ContentVideoView.
892 manager()->OnMediaMetadataChanged(
893 player_id(), duration_, width_, height_, true);
894 } 608 }
895 609
896 void MediaSourcePlayer::OnDecoderStarved() { 610 void MediaSourcePlayer::OnDecoderStarved() {
897 DVLOG(1) << __FUNCTION__; 611 DVLOG(1) << __FUNCTION__;
898 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 612 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
899 ProcessPendingEvents(); 613 ProcessPendingEvents();
900 } 614 }
901 615
902 void MediaSourcePlayer::StartStarvationCallback( 616 void MediaSourcePlayer::StartStarvationCallback(
903 base::TimeDelta current_presentation_timestamp, 617 base::TimeDelta current_presentation_timestamp,
(...skipping 20 matching lines...) Expand all
924 } 638 }
925 639
926 timeout = std::max(timeout, kMinStarvationTimeout); 640 timeout = std::max(timeout, kMinStarvationTimeout);
927 641
928 decoder_starvation_callback_.Reset(base::Bind( 642 decoder_starvation_callback_.Reset(base::Bind(
929 &MediaSourcePlayer::OnDecoderStarved, weak_factory_.GetWeakPtr())); 643 &MediaSourcePlayer::OnDecoderStarved, weak_factory_.GetWeakPtr()));
930 base::MessageLoop::current()->PostDelayedTask( 644 base::MessageLoop::current()->PostDelayedTask(
931 FROM_HERE, decoder_starvation_callback_.callback(), timeout); 645 FROM_HERE, decoder_starvation_callback_.callback(), timeout);
932 } 646 }
933 647
934 void MediaSourcePlayer::SetVolumeInternal() {
935 if (audio_decoder_job_ && volume_ >= 0)
936 audio_decoder_job_->SetVolume(volume_);
937 }
938
939 bool MediaSourcePlayer::IsProtectedSurfaceRequired() { 648 bool MediaSourcePlayer::IsProtectedSurfaceRequired() {
940 return is_video_encrypted_ && 649 return video_decoder_job_->is_content_encrypted() &&
941 drm_bridge_ && drm_bridge_->IsProtectedSurfaceRequired(); 650 drm_bridge_ && drm_bridge_->IsProtectedSurfaceRequired();
942 } 651 }
943 652
944 void MediaSourcePlayer::OnPrefetchDone() { 653 void MediaSourcePlayer::OnPrefetchDone() {
945 DVLOG(1) << __FUNCTION__; 654 DVLOG(1) << __FUNCTION__;
946 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding()); 655 DCHECK(!audio_decoder_job_->is_decoding());
947 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); 656 DCHECK(!video_decoder_job_->is_decoding());
948 657
949 // A previously posted OnPrefetchDone() could race against a Release(). If 658 // A previously posted OnPrefetchDone() could race against a Release(). If
950 // Release() won the race, we should no longer have decoder jobs. 659 // Release() won the race, we should no longer have decoder jobs.
951 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data 660 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data
952 // or drop data received across Release()+Start(). See http://crbug.com/306314 661 // or drop data received across Release()+Start(). See http://crbug.com/306314
953 // and http://crbug.com/304234. 662 // and http://crbug.com/304234.
954 if (!IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { 663 if (!IsEventPending(PREFETCH_DONE_EVENT_PENDING)) {
955 DVLOG(1) << __FUNCTION__ << " : aborting"; 664 DVLOG(1) << __FUNCTION__ << " : aborting";
956 DCHECK(!audio_decoder_job_ && !video_decoder_job_);
957 return; 665 return;
958 } 666 }
959 667
960 ClearPendingEvent(PREFETCH_DONE_EVENT_PENDING); 668 ClearPendingEvent(PREFETCH_DONE_EVENT_PENDING);
961 669
962 if (pending_event_ != NO_EVENT_PENDING) { 670 if (pending_event_ != NO_EVENT_PENDING) {
963 ProcessPendingEvents(); 671 ProcessPendingEvents();
964 return; 672 return;
965 } 673 }
966 674
675 if (!playing_)
676 return;
677
967 start_time_ticks_ = base::TimeTicks::Now(); 678 start_time_ticks_ = base::TimeTicks::Now();
968 start_presentation_timestamp_ = GetCurrentTime(); 679 start_presentation_timestamp_ = GetCurrentTime();
969 if (!clock_.IsPlaying()) 680 if (!clock_.IsPlaying())
970 clock_.Play(); 681 clock_.Play();
971 682
972 if (!AudioFinished()) 683 if (!AudioFinished())
973 DecodeMoreAudio(); 684 DecodeMoreAudio();
974 685
975 if (!VideoFinished()) 686 if (!VideoFinished())
976 DecodeMoreVideo(); 687 DecodeMoreVideo();
977 } 688 }
978 689
690 void MediaSourcePlayer::OnDemuxerConfigsChanged() {
691 manager()->OnMediaMetadataChanged(
692 player_id(), duration_, GetVideoWidth(), GetVideoHeight(), true);
693 }
694
979 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { 695 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) {
980 static const char* kPendingEventNames[] = { 696 static const char* kPendingEventNames[] = {
981 "SEEK", 697 "SEEK",
982 "SURFACE_CHANGE",
983 "CONFIG_CHANGE",
984 "PREFETCH_REQUEST", 698 "PREFETCH_REQUEST",
985 "PREFETCH_DONE", 699 "PREFETCH_DONE",
700 "DECODER_CREATION_EVENT_PENDING",
986 }; 701 };
987 702
988 int mask = 1; 703 int mask = 1;
989 for (size_t i = 0; i < arraysize(kPendingEventNames); ++i, mask <<= 1) { 704 for (size_t i = 0; i < arraysize(kPendingEventNames); ++i, mask <<= 1) {
990 if (event & mask) 705 if (event & mask)
991 return kPendingEventNames[i]; 706 return kPendingEventNames[i];
992 } 707 }
993 708
994 return "UNKNOWN"; 709 return "UNKNOWN";
995 } 710 }
(...skipping 12 matching lines...) Expand all
1008 723
1009 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { 724 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) {
1010 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; 725 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")";
1011 DCHECK_NE(event, NO_EVENT_PENDING); 726 DCHECK_NE(event, NO_EVENT_PENDING);
1012 DCHECK(IsEventPending(event)) << GetEventName(event); 727 DCHECK(IsEventPending(event)) << GetEventName(event);
1013 728
1014 pending_event_ &= ~event; 729 pending_event_ &= ~event;
1015 } 730 }
1016 731
1017 } // namespace media 732 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698