OLD | NEW |
---|---|
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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 is_video_encrypted_(false), | 54 is_video_encrypted_(false), |
55 volume_(-1.0), | 55 volume_(-1.0), |
56 clock_(&default_tick_clock_), | 56 clock_(&default_tick_clock_), |
57 next_video_data_is_iframe_(true), | 57 next_video_data_is_iframe_(true), |
58 doing_browser_seek_(false), | 58 doing_browser_seek_(false), |
59 pending_seek_(false), | 59 pending_seek_(false), |
60 reconfig_audio_decoder_(false), | 60 reconfig_audio_decoder_(false), |
61 reconfig_video_decoder_(false), | 61 reconfig_video_decoder_(false), |
62 weak_this_(this), | 62 weak_this_(this), |
63 drm_bridge_(NULL), | 63 drm_bridge_(NULL), |
64 is_waiting_for_key_(false) { | 64 is_waiting_for_key_(false), |
65 has_pending_audio_data_request_(false), | |
66 has_pending_video_data_request_(false) { | |
65 demuxer_->Initialize(this); | 67 demuxer_->Initialize(this); |
66 clock_.SetMaxTime(base::TimeDelta()); | 68 clock_.SetMaxTime(base::TimeDelta()); |
67 } | 69 } |
68 | 70 |
69 MediaSourcePlayer::~MediaSourcePlayer() { | 71 MediaSourcePlayer::~MediaSourcePlayer() { |
70 Release(); | 72 Release(); |
71 } | 73 } |
72 | 74 |
73 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { | 75 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
74 // For an empty surface, always pass it to the decoder job so that it | 76 // For an empty surface, always pass it to the decoder job so that it |
(...skipping 24 matching lines...) Expand all Loading... | |
99 // If video config change is already pending, processing of the pending | 101 // If video config change is already pending, processing of the pending |
100 // surface change event will occur in OnDemuxerConfigsAvailable(). | 102 // surface change event will occur in OnDemuxerConfigsAvailable(). |
101 if (reconfig_video_decoder_ && IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) | 103 if (reconfig_video_decoder_ && IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) |
102 return; | 104 return; |
103 | 105 |
104 // Otherwise we need to trigger pending event processing now. | 106 // Otherwise we need to trigger pending event processing now. |
105 ProcessPendingEvents(); | 107 ProcessPendingEvents(); |
106 } | 108 } |
107 | 109 |
108 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( | 110 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( |
109 const base::TimeDelta& seek_time) { | 111 base::TimeDelta seek_time) { |
110 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; | 112 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; |
111 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); | 113 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); |
112 | 114 |
113 pending_seek_ = false; | 115 pending_seek_ = false; |
114 | 116 |
115 clock_.SetTime(seek_time, seek_time); | 117 clock_.SetTime(seek_time, seek_time); |
116 if (audio_timestamp_helper_) | 118 if (audio_timestamp_helper_) |
117 audio_timestamp_helper_->SetBaseTimestamp(seek_time); | 119 audio_timestamp_helper_->SetBaseTimestamp(seek_time); |
118 | 120 |
119 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) | 121 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 } | 172 } |
171 | 173 |
172 int MediaSourcePlayer::GetVideoWidth() { | 174 int MediaSourcePlayer::GetVideoWidth() { |
173 return width_; | 175 return width_; |
174 } | 176 } |
175 | 177 |
176 int MediaSourcePlayer::GetVideoHeight() { | 178 int MediaSourcePlayer::GetVideoHeight() { |
177 return height_; | 179 return height_; |
178 } | 180 } |
179 | 181 |
180 void MediaSourcePlayer::SeekTo(const base::TimeDelta& timestamp) { | 182 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { |
181 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")"; | 183 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")"; |
182 | 184 |
183 if (IsEventPending(SEEK_EVENT_PENDING)) { | 185 if (IsEventPending(SEEK_EVENT_PENDING)) { |
184 DCHECK(doing_browser_seek_) << "SeekTo while SeekTo in progress"; | 186 DCHECK(doing_browser_seek_) << "SeekTo while SeekTo in progress"; |
185 DCHECK(!pending_seek_) << "SeekTo while SeekTo pending browser seek"; | 187 DCHECK(!pending_seek_) << "SeekTo while SeekTo pending browser seek"; |
186 | 188 |
187 // There is a browser seek currently in progress to obtain I-frame to feed | 189 // There is a browser seek currently in progress to obtain I-frame to feed |
188 // a newly constructed video decoder. Remember this real seek request so | 190 // a newly constructed video decoder. Remember this real seek request so |
189 // it can be initiated once OnDemuxerSeekDone() occurs for the browser seek. | 191 // it can be initiated once OnDemuxerSeekDone() occurs for the browser seek. |
190 pending_seek_ = true; | 192 pending_seek_ = true; |
(...skipping 24 matching lines...) Expand all Loading... | |
215 // or drop data received across Release()+Start(). See http://crbug.com/306314 | 217 // or drop data received across Release()+Start(). See http://crbug.com/306314 |
216 // and http://crbug.com/304234. | 218 // and http://crbug.com/304234. |
217 bool process_pending_events = false; | 219 bool process_pending_events = false; |
218 process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) || | 220 process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) || |
219 (audio_decoder_job_ && audio_decoder_job_->is_decoding()) || | 221 (audio_decoder_job_ && audio_decoder_job_->is_decoding()) || |
220 (video_decoder_job_ && video_decoder_job_->is_decoding()); | 222 (video_decoder_job_ && video_decoder_job_->is_decoding()); |
221 | 223 |
222 // Clear all the pending events except seeks and config changes. | 224 // Clear all the pending events except seeks and config changes. |
223 pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING); | 225 pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING); |
224 is_surface_in_use_ = false; | 226 is_surface_in_use_ = false; |
225 audio_decoder_job_.reset(); | 227 ResetAudioDecoderJob(); |
226 ResetVideoDecoderJob(); | 228 ResetVideoDecoderJob(); |
227 | 229 |
228 // Prevent job re-creation attempts in OnDemuxerConfigsAvailable() | 230 // Prevent job re-creation attempts in OnDemuxerConfigsAvailable() |
229 reconfig_audio_decoder_ = false; | 231 reconfig_audio_decoder_ = false; |
230 reconfig_video_decoder_ = false; | 232 reconfig_video_decoder_ = false; |
231 | 233 |
232 // Prevent player restart, including job re-creation attempts. | 234 // Prevent player restart, including job re-creation attempts. |
233 playing_ = false; | 235 playing_ = false; |
234 | 236 |
235 decoder_starvation_callback_.Cancel(); | 237 decoder_starvation_callback_.Cancel(); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
338 | 340 |
339 // Resume decoding after the config change if we are still playing. | 341 // Resume decoding after the config change if we are still playing. |
340 if (playing_) | 342 if (playing_) |
341 StartInternal(); | 343 StartInternal(); |
342 } | 344 } |
343 } | 345 } |
344 | 346 |
345 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { | 347 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { |
346 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")"; | 348 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")"; |
347 DCHECK_LT(0u, data.access_units.size()); | 349 DCHECK_LT(0u, data.access_units.size()); |
350 | |
351 if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { | |
352 has_pending_audio_data_request_ = false; | |
353 ProcessPendingEvents(); | |
354 return; | |
355 } | |
356 | |
357 if (has_pending_video_data_request_ && data.type == DemuxerStream::VIDEO) { | |
358 next_video_data_is_iframe_ = false; | |
359 has_pending_video_data_request_ = false; | |
360 ProcessPendingEvents(); | |
361 return; | |
362 } | |
363 | |
348 if (data.type == DemuxerStream::AUDIO && audio_decoder_job_) { | 364 if (data.type == DemuxerStream::AUDIO && audio_decoder_job_) { |
349 audio_decoder_job_->OnDataReceived(data); | 365 audio_decoder_job_->OnDataReceived(data); |
350 } else if (data.type == DemuxerStream::VIDEO) { | 366 } else if (data.type == DemuxerStream::VIDEO) { |
351 next_video_data_is_iframe_ = false; | 367 next_video_data_is_iframe_ = false; |
352 if (video_decoder_job_) | 368 if (video_decoder_job_) |
353 video_decoder_job_->OnDataReceived(data); | 369 video_decoder_job_->OnDataReceived(data); |
354 } | 370 } |
355 } | 371 } |
356 | 372 |
357 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) { | 373 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 drm_bridge_->SetMediaCryptoReadyCB(base::Bind( | 406 drm_bridge_->SetMediaCryptoReadyCB(base::Bind( |
391 &MediaSourcePlayer::OnMediaCryptoReady, weak_this_.GetWeakPtr())); | 407 &MediaSourcePlayer::OnMediaCryptoReady, weak_this_.GetWeakPtr())); |
392 return; | 408 return; |
393 } | 409 } |
394 | 410 |
395 if (playing_) | 411 if (playing_) |
396 StartInternal(); | 412 StartInternal(); |
397 } | 413 } |
398 | 414 |
399 void MediaSourcePlayer::OnDemuxerSeekDone( | 415 void MediaSourcePlayer::OnDemuxerSeekDone( |
400 const base::TimeDelta& actual_browser_seek_time) { | 416 base::TimeDelta actual_browser_seek_time) { |
401 DVLOG(1) << __FUNCTION__; | 417 DVLOG(1) << __FUNCTION__; |
402 | 418 |
403 ClearPendingEvent(SEEK_EVENT_PENDING); | 419 ClearPendingEvent(SEEK_EVENT_PENDING); |
404 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) | 420 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) |
405 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 421 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
406 | 422 |
407 next_video_data_is_iframe_ = true; | 423 next_video_data_is_iframe_ = true; |
408 | 424 |
409 if (pending_seek_) { | 425 if (pending_seek_) { |
410 DVLOG(1) << __FUNCTION__ << "processing pending seek"; | 426 DVLOG(1) << __FUNCTION__ << "processing pending seek"; |
411 DCHECK(doing_browser_seek_); | 427 DCHECK(doing_browser_seek_); |
412 pending_seek_ = false; | 428 pending_seek_ = false; |
413 SeekTo(pending_seek_time_); | 429 SeekTo(pending_seek_time_); |
414 return; | 430 return; |
415 } | 431 } |
416 | 432 |
417 // It is possible that a browser seek to I-frame had to seek to a buffered | 433 // 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 | 434 // I-frame later than the requested one due to data removal or GC. Update |
419 // player clock to the actual seek target. | 435 // player clock to the actual seek target. |
420 if (doing_browser_seek_) { | 436 if (doing_browser_seek_) { |
421 DCHECK(actual_browser_seek_time != kNoTimestamp()); | 437 DCHECK(actual_browser_seek_time != kNoTimestamp()); |
438 base::TimeDelta seek_time = actual_browser_seek_time; | |
422 // A browser seek must not jump into the past. Ideally, it seeks to the | 439 // A browser seek must not jump into the past. Ideally, it seeks to the |
423 // requested time, but it might jump into the future. | 440 // requested time, but it might jump into the future. |
424 DCHECK(actual_browser_seek_time >= GetCurrentTime()); | 441 DCHECK(seek_time >= GetCurrentTime()); |
425 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " | 442 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " |
426 << actual_browser_seek_time.InSecondsF(); | 443 << seek_time.InSecondsF(); |
427 clock_.SetTime(actual_browser_seek_time, actual_browser_seek_time); | 444 clock_.SetTime(seek_time, seek_time); |
428 if (audio_timestamp_helper_) | 445 if (audio_timestamp_helper_) |
429 audio_timestamp_helper_->SetBaseTimestamp(actual_browser_seek_time); | 446 audio_timestamp_helper_->SetBaseTimestamp(seek_time); |
430 } | 447 } |
431 | 448 |
wolenetz
2014/03/19 17:26:05
nit: Due to confusion in |actual_browser_seek_time
qinmin
2014/03/19 19:24:55
Done.
| |
432 reached_audio_eos_ = false; | 449 reached_audio_eos_ = false; |
433 reached_video_eos_ = false; | 450 reached_video_eos_ = false; |
434 | 451 |
435 base::TimeDelta current_time = GetCurrentTime(); | 452 base::TimeDelta current_time = GetCurrentTime(); |
436 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| | 453 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| |
437 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| | 454 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| |
438 // is calculated from decoder output, while preroll relies on the access | 455 // is calculated from decoder output, while preroll relies on the access |
439 // unit's timestamp. There are some differences between the two. | 456 // unit's timestamp. There are some differences between the two. |
440 preroll_timestamp_ = current_time; | 457 preroll_timestamp_ = current_time; |
441 if (audio_decoder_job_) | 458 if (audio_decoder_job_) |
442 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 459 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
443 if (video_decoder_job_) | 460 if (video_decoder_job_) |
444 video_decoder_job_->BeginPrerolling(preroll_timestamp_); | 461 video_decoder_job_->BeginPrerolling(preroll_timestamp_); |
445 | 462 |
446 if (!doing_browser_seek_) | 463 if (!doing_browser_seek_) |
447 manager()->OnSeekComplete(player_id(), current_time); | 464 manager()->OnSeekComplete(player_id(), current_time); |
448 | 465 |
449 ProcessPendingEvents(); | 466 ProcessPendingEvents(); |
450 } | 467 } |
451 | 468 |
452 void MediaSourcePlayer::UpdateTimestamps( | 469 void MediaSourcePlayer::UpdateTimestamps( |
453 const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) { | 470 base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { |
454 base::TimeDelta new_max_time = presentation_timestamp; | 471 base::TimeDelta new_max_time = presentation_timestamp; |
455 | 472 |
456 if (audio_output_bytes > 0) { | 473 if (audio_output_bytes > 0) { |
457 audio_timestamp_helper_->AddFrames( | 474 audio_timestamp_helper_->AddFrames( |
458 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_)); | 475 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_)); |
459 new_max_time = audio_timestamp_helper_->GetTimestamp(); | 476 new_max_time = audio_timestamp_helper_->GetTimestamp(); |
460 } | 477 } |
461 | 478 |
462 clock_.SetMaxTime(new_max_time); | 479 clock_.SetMaxTime(new_max_time); |
463 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); | 480 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); |
464 } | 481 } |
465 | 482 |
466 void MediaSourcePlayer::ProcessPendingEvents() { | 483 void MediaSourcePlayer::ProcessPendingEvents() { |
467 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; | 484 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; |
468 // Wait for all the decoding jobs to finish before processing pending tasks. | 485 // Wait for all the decoding jobs to finish before processing pending tasks. |
469 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { | 486 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { |
470 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; | 487 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; |
471 return; | 488 return; |
472 } | 489 } |
473 | 490 |
474 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) { | 491 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) { |
475 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding."; | 492 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding."; |
476 return; | 493 return; |
477 } | 494 } |
478 | 495 |
496 if (has_pending_audio_data_request_ || has_pending_video_data_request_) { | |
497 DVLOG(1) << __FUNCTION__ << " : has pending data request."; | |
498 return; | |
499 } | |
500 | |
479 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { | 501 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { |
480 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending."; | 502 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending."; |
481 return; | 503 return; |
482 } | 504 } |
483 | 505 |
484 if (IsEventPending(SEEK_EVENT_PENDING)) { | 506 if (IsEventPending(SEEK_EVENT_PENDING)) { |
485 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT"; | 507 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT"; |
486 ClearDecodingData(); | 508 ClearDecodingData(); |
487 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); | 509 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); |
488 return; | 510 return; |
(...skipping 14 matching lines...) Expand all Loading... | |
503 ConfigureVideoDecoderJob(); | 525 ConfigureVideoDecoderJob(); |
504 | 526 |
505 // Return early if we can't successfully configure a new video decoder job | 527 // Return early if we can't successfully configure a new video decoder job |
506 // yet. | 528 // yet. |
507 if (HasVideo() && !video_decoder_job_) | 529 if (HasVideo() && !video_decoder_job_) |
508 return; | 530 return; |
509 } | 531 } |
510 | 532 |
511 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { | 533 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { |
512 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; | 534 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; |
535 // If one of the decoder is not initialized, cancel this event as it will be | |
536 // called later when Start() is called again. | |
537 if ((HasVideo() && !video_decoder_job_) || | |
538 (HasAudio() && !audio_decoder_job_)) { | |
539 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | |
540 return; | |
541 } | |
542 | |
513 DCHECK(audio_decoder_job_ || AudioFinished()); | 543 DCHECK(audio_decoder_job_ || AudioFinished()); |
514 DCHECK(video_decoder_job_ || VideoFinished()); | 544 DCHECK(video_decoder_job_ || VideoFinished()); |
515 | 545 |
516 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); | 546 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); |
517 | 547 |
518 // It is possible that all streams have finished decode, yet starvation | 548 // It is possible that all streams have finished decode, yet starvation |
519 // occurred during the last stream's EOS decode. In this case, prefetch is a | 549 // occurred during the last stream's EOS decode. In this case, prefetch is a |
520 // no-op. | 550 // no-op. |
521 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 551 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
522 if (count == 0) | 552 if (count == 0) |
(...skipping 15 matching lines...) Expand all Loading... | |
538 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); | 568 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); |
539 | 569 |
540 // Now that all pending events have been handled, resume decoding if we are | 570 // Now that all pending events have been handled, resume decoding if we are |
541 // still playing. | 571 // still playing. |
542 if (playing_) | 572 if (playing_) |
543 StartInternal(); | 573 StartInternal(); |
544 } | 574 } |
545 | 575 |
546 void MediaSourcePlayer::MediaDecoderCallback( | 576 void MediaSourcePlayer::MediaDecoderCallback( |
547 bool is_audio, MediaCodecStatus status, | 577 bool is_audio, MediaCodecStatus status, |
548 const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) { | 578 base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { |
549 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; | 579 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; |
550 | 580 |
551 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. | 581 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. |
552 if (is_audio) { | 582 if (is_audio) { |
553 TRACE_EVENT_ASYNC_END1("media", | 583 TRACE_EVENT_ASYNC_END1("media", |
554 "MediaSourcePlayer::DecodeMoreAudio", | 584 "MediaSourcePlayer::DecodeMoreAudio", |
555 audio_decoder_job_.get(), | 585 audio_decoder_job_.get(), |
556 "MediaCodecStatus", | 586 "MediaCodecStatus", |
557 base::IntToString(status)); | 587 base::IntToString(status)); |
558 } else { | 588 } else { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
740 bool MediaSourcePlayer::AudioFinished() { | 770 bool MediaSourcePlayer::AudioFinished() { |
741 return reached_audio_eos_ || !HasAudio(); | 771 return reached_audio_eos_ || !HasAudio(); |
742 } | 772 } |
743 | 773 |
744 bool MediaSourcePlayer::VideoFinished() { | 774 bool MediaSourcePlayer::VideoFinished() { |
745 return reached_video_eos_ || !HasVideo(); | 775 return reached_video_eos_ || !HasVideo(); |
746 } | 776 } |
747 | 777 |
748 void MediaSourcePlayer::ConfigureAudioDecoderJob() { | 778 void MediaSourcePlayer::ConfigureAudioDecoderJob() { |
749 if (!HasAudio()) { | 779 if (!HasAudio()) { |
750 audio_decoder_job_.reset(); | 780 ResetAudioDecoderJob(); |
751 return; | 781 return; |
752 } | 782 } |
753 | 783 |
754 // Create audio decoder job only if config changes. | 784 // Create audio decoder job only if config changes. |
755 if (audio_decoder_job_ && !reconfig_audio_decoder_) | 785 if (audio_decoder_job_ && !reconfig_audio_decoder_) |
756 return; | 786 return; |
757 | 787 |
758 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); | 788 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); |
759 if (is_audio_encrypted_ && media_crypto.is_null()) | 789 if (is_audio_encrypted_ && media_crypto.is_null()) |
760 return; | 790 return; |
761 | 791 |
762 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding()); | 792 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding()); |
763 | 793 |
794 ResetAudioDecoderJob(); | |
764 DVLOG(1) << __FUNCTION__ << " : creating new audio decoder job"; | 795 DVLOG(1) << __FUNCTION__ << " : creating new audio decoder job"; |
765 | |
766 audio_decoder_job_.reset(AudioDecoderJob::Create( | 796 audio_decoder_job_.reset(AudioDecoderJob::Create( |
767 audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0], | 797 audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0], |
768 audio_extra_data_.size(), media_crypto.obj(), | 798 audio_extra_data_.size(), media_crypto.obj(), |
769 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 799 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
770 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); | 800 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); |
771 | 801 |
772 if (audio_decoder_job_) { | 802 if (audio_decoder_job_) { |
773 SetVolumeInternal(); | 803 SetVolumeInternal(); |
774 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 804 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
775 reconfig_audio_decoder_ = false; | 805 reconfig_audio_decoder_ = false; |
776 } | 806 } |
777 } | 807 } |
778 | 808 |
779 void MediaSourcePlayer::ResetVideoDecoderJob() { | 809 void MediaSourcePlayer::ResetVideoDecoderJob() { |
810 if (video_decoder_job_) { | |
811 has_pending_video_data_request_ = | |
812 video_decoder_job_->is_requesting_demuxer_data(); | |
813 } | |
780 video_decoder_job_.reset(); | 814 video_decoder_job_.reset(); |
781 | 815 |
782 // Any eventual video decoder job re-creation will use the current |surface_|. | 816 // Any eventual video decoder job re-creation will use the current |surface_|. |
783 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) | 817 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) |
784 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); | 818 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); |
785 } | 819 } |
786 | 820 |
821 void MediaSourcePlayer::ResetAudioDecoderJob() { | |
822 if (audio_decoder_job_) { | |
823 has_pending_audio_data_request_ = | |
824 audio_decoder_job_->is_requesting_demuxer_data(); | |
825 } | |
826 audio_decoder_job_.reset(); | |
827 } | |
828 | |
787 void MediaSourcePlayer::ConfigureVideoDecoderJob() { | 829 void MediaSourcePlayer::ConfigureVideoDecoderJob() { |
788 if (!HasVideo() || surface_.IsEmpty()) { | 830 if (!HasVideo() || surface_.IsEmpty()) { |
789 ResetVideoDecoderJob(); | 831 ResetVideoDecoderJob(); |
790 return; | 832 return; |
791 } | 833 } |
792 | 834 |
793 // Create video decoder job only if config changes or we don't have a job. | 835 // Create video decoder job only if config changes or we don't have a job. |
794 if (video_decoder_job_ && !reconfig_video_decoder_) { | 836 if (video_decoder_job_ && !reconfig_video_decoder_) { |
795 DCHECK(!IsEventPending(SURFACE_CHANGE_EVENT_PENDING)); | 837 DCHECK(!IsEventPending(SURFACE_CHANGE_EVENT_PENDING)); |
796 return; | 838 return; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
853 player_id(), duration_, width_, height_, true); | 895 player_id(), duration_, width_, height_, true); |
854 } | 896 } |
855 | 897 |
856 void MediaSourcePlayer::OnDecoderStarved() { | 898 void MediaSourcePlayer::OnDecoderStarved() { |
857 DVLOG(1) << __FUNCTION__; | 899 DVLOG(1) << __FUNCTION__; |
858 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 900 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
859 ProcessPendingEvents(); | 901 ProcessPendingEvents(); |
860 } | 902 } |
861 | 903 |
862 void MediaSourcePlayer::StartStarvationCallback( | 904 void MediaSourcePlayer::StartStarvationCallback( |
863 const base::TimeDelta& presentation_timestamp) { | 905 base::TimeDelta presentation_timestamp) { |
864 // 20ms was chosen because it is the typical size of a compressed audio frame. | 906 // 20ms was chosen because it is the typical size of a compressed audio frame. |
865 // Anything smaller than this would likely cause unnecessary cycling in and | 907 // Anything smaller than this would likely cause unnecessary cycling in and |
866 // out of the prefetch state. | 908 // out of the prefetch state. |
867 const base::TimeDelta kMinStarvationTimeout = | 909 const base::TimeDelta kMinStarvationTimeout = |
868 base::TimeDelta::FromMilliseconds(20); | 910 base::TimeDelta::FromMilliseconds(20); |
869 | 911 |
870 base::TimeDelta current_timestamp = GetCurrentTime(); | 912 base::TimeDelta current_timestamp = GetCurrentTime(); |
871 base::TimeDelta timeout; | 913 base::TimeDelta timeout; |
872 if (HasAudio()) { | 914 if (HasAudio()) { |
873 timeout = audio_timestamp_helper_->GetTimestamp() - current_timestamp; | 915 timeout = audio_timestamp_helper_->GetTimestamp() - current_timestamp; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
968 | 1010 |
969 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 1011 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
970 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 1012 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
971 DCHECK_NE(event, NO_EVENT_PENDING); | 1013 DCHECK_NE(event, NO_EVENT_PENDING); |
972 DCHECK(IsEventPending(event)) << GetEventName(event); | 1014 DCHECK(IsEventPending(event)) << GetEventName(event); |
973 | 1015 |
974 pending_event_ &= ~event; | 1016 pending_event_ &= ~event; |
975 } | 1017 } |
976 | 1018 |
977 } // namespace media | 1019 } // namespace media |
OLD | NEW |