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