Chromium Code Reviews| 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 20 matching lines...) Expand all Loading... | |
| 31 scoped_ptr<DemuxerAndroid> demuxer, | 31 scoped_ptr<DemuxerAndroid> demuxer, |
| 32 const GURL& frame_url) | 32 const GURL& frame_url) |
| 33 : MediaPlayerAndroid(player_id, | 33 : MediaPlayerAndroid(player_id, |
| 34 manager, | 34 manager, |
| 35 request_media_resources_cb, | 35 request_media_resources_cb, |
| 36 release_media_resources_cb, | 36 release_media_resources_cb, |
| 37 frame_url), | 37 frame_url), |
| 38 demuxer_(demuxer.Pass()), | 38 demuxer_(demuxer.Pass()), |
| 39 pending_event_(NO_EVENT_PENDING), | 39 pending_event_(NO_EVENT_PENDING), |
| 40 playing_(false), | 40 playing_(false), |
| 41 clock_(&default_tick_clock_), | 41 interpolator_(&default_tick_clock_), |
| 42 doing_browser_seek_(false), | 42 doing_browser_seek_(false), |
| 43 pending_seek_(false), | 43 pending_seek_(false), |
| 44 drm_bridge_(NULL), | 44 drm_bridge_(NULL), |
| 45 cdm_registration_id_(0), | 45 cdm_registration_id_(0), |
| 46 is_waiting_for_key_(false), | 46 is_waiting_for_key_(false), |
| 47 is_waiting_for_audio_decoder_(false), | 47 is_waiting_for_audio_decoder_(false), |
| 48 is_waiting_for_video_decoder_(false), | 48 is_waiting_for_video_decoder_(false), |
| 49 weak_factory_(this) { | 49 weak_factory_(this) { |
| 50 audio_decoder_job_.reset(new AudioDecoderJob( | 50 audio_decoder_job_.reset(new AudioDecoderJob( |
| 51 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 51 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
| 52 base::Unretained(demuxer_.get()), | 52 base::Unretained(demuxer_.get()), |
| 53 DemuxerStream::AUDIO), | 53 DemuxerStream::AUDIO), |
| 54 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, | 54 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, |
| 55 weak_factory_.GetWeakPtr()))); | 55 weak_factory_.GetWeakPtr()))); |
| 56 video_decoder_job_.reset(new VideoDecoderJob( | 56 video_decoder_job_.reset(new VideoDecoderJob( |
| 57 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 57 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
| 58 base::Unretained(demuxer_.get()), | 58 base::Unretained(demuxer_.get()), |
| 59 DemuxerStream::VIDEO), | 59 DemuxerStream::VIDEO), |
| 60 base::Bind(request_media_resources_cb_, player_id), | 60 base::Bind(request_media_resources_cb_, player_id), |
| 61 base::Bind(release_media_resources_cb_, player_id), | 61 base::Bind(release_media_resources_cb_, player_id), |
| 62 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, | 62 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, |
| 63 weak_factory_.GetWeakPtr()))); | 63 weak_factory_.GetWeakPtr()))); |
| 64 demuxer_->Initialize(this); | 64 demuxer_->Initialize(this); |
| 65 clock_.SetMaxTime(base::TimeDelta()); | 65 interpolator_.SetMaxTime(base::TimeDelta()); |
| 66 weak_this_ = weak_factory_.GetWeakPtr(); | 66 weak_this_ = weak_factory_.GetWeakPtr(); |
| 67 } | 67 } |
| 68 | 68 |
| 69 MediaSourcePlayer::~MediaSourcePlayer() { | 69 MediaSourcePlayer::~MediaSourcePlayer() { |
| 70 Release(); | 70 Release(); |
| 71 DCHECK_EQ(!drm_bridge_, !cdm_registration_id_); | 71 DCHECK_EQ(!drm_bridge_, !cdm_registration_id_); |
| 72 if (drm_bridge_) { | 72 if (drm_bridge_) { |
| 73 drm_bridge_->UnregisterPlayer(cdm_registration_id_); | 73 drm_bridge_->UnregisterPlayer(cdm_registration_id_); |
| 74 cdm_registration_id_ = 0; | 74 cdm_registration_id_ = 0; |
| 75 } | 75 } |
| 76 } | 76 } |
| 77 | 77 |
| 78 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { | 78 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
| 79 DVLOG(1) << __FUNCTION__; | 79 DVLOG(1) << __FUNCTION__; |
| 80 if (!video_decoder_job_->SetVideoSurface(surface.Pass())) | 80 if (!video_decoder_job_->SetVideoSurface(surface.Pass())) |
| 81 return; | 81 return; |
| 82 // Retry video decoder creation. | 82 // Retry video decoder creation. |
| 83 RetryDecoderCreation(false, true); | 83 RetryDecoderCreation(false, true); |
| 84 } | 84 } |
| 85 | 85 |
| 86 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( | 86 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( |
| 87 base::TimeDelta seek_time) { | 87 base::TimeDelta seek_time) { |
| 88 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; | 88 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; |
| 89 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); | 89 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); |
| 90 | 90 |
| 91 pending_seek_ = false; | 91 pending_seek_ = false; |
| 92 | 92 |
| 93 clock_.SetTime(seek_time, seek_time); | 93 interpolator_.SetTime(seek_time, seek_time); |
| 94 | 94 |
| 95 if (audio_decoder_job_->is_decoding()) | 95 if (audio_decoder_job_->is_decoding()) |
| 96 audio_decoder_job_->StopDecode(); | 96 audio_decoder_job_->StopDecode(); |
| 97 if (video_decoder_job_->is_decoding()) | 97 if (video_decoder_job_->is_decoding()) |
| 98 video_decoder_job_->StopDecode(); | 98 video_decoder_job_->StopDecode(); |
| 99 | 99 |
| 100 SetPendingEvent(SEEK_EVENT_PENDING); | 100 SetPendingEvent(SEEK_EVENT_PENDING); |
| 101 ProcessPendingEvents(); | 101 ProcessPendingEvents(); |
| 102 } | 102 } |
| 103 | 103 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 pending_seek_ = true; | 166 pending_seek_ = true; |
| 167 pending_seek_time_ = timestamp; | 167 pending_seek_time_ = timestamp; |
| 168 return; | 168 return; |
| 169 } | 169 } |
| 170 | 170 |
| 171 doing_browser_seek_ = false; | 171 doing_browser_seek_ = false; |
| 172 ScheduleSeekEventAndStopDecoding(timestamp); | 172 ScheduleSeekEventAndStopDecoding(timestamp); |
| 173 } | 173 } |
| 174 | 174 |
| 175 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { | 175 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { |
| 176 return std::min(clock_.Elapsed(), duration_); | 176 return std::min(interpolator_.GetInterpolatedTime(), duration_); |
| 177 } | 177 } |
| 178 | 178 |
| 179 base::TimeDelta MediaSourcePlayer::GetDuration() { | 179 base::TimeDelta MediaSourcePlayer::GetDuration() { |
| 180 return duration_; | 180 return duration_; |
| 181 } | 181 } |
| 182 | 182 |
| 183 void MediaSourcePlayer::Release() { | 183 void MediaSourcePlayer::Release() { |
| 184 DVLOG(1) << __FUNCTION__; | 184 DVLOG(1) << __FUNCTION__; |
| 185 | 185 |
| 186 is_surface_in_use_ = false; | 186 is_surface_in_use_ = false; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 // 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 |
| 322 // player clock to the actual seek target. | 322 // player clock to the actual seek target. |
| 323 if (doing_browser_seek_) { | 323 if (doing_browser_seek_) { |
| 324 DCHECK(actual_browser_seek_time != kNoTimestamp()); | 324 DCHECK(actual_browser_seek_time != kNoTimestamp()); |
| 325 base::TimeDelta seek_time = actual_browser_seek_time; | 325 base::TimeDelta seek_time = actual_browser_seek_time; |
| 326 // 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 |
| 327 // requested time, but it might jump into the future. | 327 // requested time, but it might jump into the future. |
| 328 DCHECK(seek_time >= GetCurrentTime()); | 328 DCHECK(seek_time >= GetCurrentTime()); |
| 329 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " | 329 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " |
| 330 << seek_time.InSecondsF(); | 330 << seek_time.InSecondsF(); |
| 331 clock_.SetTime(seek_time, seek_time); | 331 interpolator_.SetTime(seek_time, seek_time); |
| 332 audio_decoder_job_->SetBaseTimestamp(seek_time); | 332 audio_decoder_job_->SetBaseTimestamp(seek_time); |
| 333 } else { | 333 } else { |
| 334 DCHECK(actual_browser_seek_time == kNoTimestamp()); | 334 DCHECK(actual_browser_seek_time == kNoTimestamp()); |
| 335 } | 335 } |
| 336 | 336 |
| 337 base::TimeDelta current_time = GetCurrentTime(); | 337 base::TimeDelta current_time = GetCurrentTime(); |
| 338 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| | 338 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| |
| 339 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| | 339 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| |
| 340 // is calculated from decoder output, while preroll relies on the access | 340 // is calculated from decoder output, while preroll relies on the access |
| 341 // unit's timestamp. There are some differences between the two. | 341 // unit's timestamp. There are some differences between the two. |
| 342 preroll_timestamp_ = current_time; | 342 preroll_timestamp_ = current_time; |
| 343 if (HasAudio()) | 343 if (HasAudio()) |
| 344 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 344 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 345 if (HasVideo()) | 345 if (HasVideo()) |
| 346 video_decoder_job_->BeginPrerolling(preroll_timestamp_); | 346 video_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 347 | 347 |
| 348 if (!doing_browser_seek_) | 348 if (!doing_browser_seek_) |
| 349 manager()->OnSeekComplete(player_id(), current_time); | 349 manager()->OnSeekComplete(player_id(), current_time); |
| 350 | 350 |
| 351 ProcessPendingEvents(); | 351 ProcessPendingEvents(); |
| 352 } | 352 } |
| 353 | 353 |
| 354 void MediaSourcePlayer::UpdateTimestamps( | 354 void MediaSourcePlayer::UpdateTimestamps( |
| 355 base::TimeDelta current_presentation_timestamp, | 355 base::TimeDelta current_presentation_timestamp, |
| 356 base::TimeDelta max_presentation_timestamp) { | 356 base::TimeDelta max_presentation_timestamp) { |
| 357 clock_.SetTime(current_presentation_timestamp, max_presentation_timestamp); | 357 interpolator_.SetTime(current_presentation_timestamp, |
| 358 max_presentation_timestamp); | |
| 358 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); | 359 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); |
| 359 } | 360 } |
| 360 | 361 |
| 361 void MediaSourcePlayer::ProcessPendingEvents() { | 362 void MediaSourcePlayer::ProcessPendingEvents() { |
| 362 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; | 363 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; |
| 363 // Wait for all the decoding jobs to finish before processing pending tasks. | 364 // Wait for all the decoding jobs to finish before processing pending tasks. |
| 364 if (video_decoder_job_->is_decoding()) { | 365 if (video_decoder_job_->is_decoding()) { |
| 365 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; | 366 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; |
| 366 return; | 367 return; |
| 367 } | 368 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 if (pending_event_ != NO_EVENT_PENDING) { | 483 if (pending_event_ != NO_EVENT_PENDING) { |
| 483 ProcessPendingEvents(); | 484 ProcessPendingEvents(); |
| 484 return; | 485 return; |
| 485 } | 486 } |
| 486 | 487 |
| 487 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) | 488 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
| 488 return; | 489 return; |
| 489 | 490 |
| 490 if (!playing_) { | 491 if (!playing_) { |
| 491 if (is_clock_manager) | 492 if (is_clock_manager) |
| 492 clock_.Pause(); | 493 interpolator_.StopInterpolating(); |
| 493 return; | 494 return; |
| 494 } | 495 } |
| 495 | 496 |
| 496 if (status == MEDIA_CODEC_NO_KEY) { | 497 if (status == MEDIA_CODEC_NO_KEY) { |
| 497 is_waiting_for_key_ = true; | 498 is_waiting_for_key_ = true; |
| 498 return; | 499 return; |
| 499 } | 500 } |
| 500 | 501 |
| 501 // If the status is MEDIA_CODEC_STOPPED, stop decoding new data. The player is | 502 // If the status is MEDIA_CODEC_STOPPED, stop decoding new data. The player is |
| 502 // in the middle of a seek or stop event and needs to wait for the IPCs to | 503 // in the middle of a seek or stop event and needs to wait for the IPCs to |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 is_waiting_for_video_decoder_ = true; | 565 is_waiting_for_video_decoder_ = true; |
| 565 if (!IsEventPending(DECODER_CREATION_EVENT_PENDING)) | 566 if (!IsEventPending(DECODER_CREATION_EVENT_PENDING)) |
| 566 SetPendingEvent(DECODER_CREATION_EVENT_PENDING); | 567 SetPendingEvent(DECODER_CREATION_EVENT_PENDING); |
| 567 } | 568 } |
| 568 | 569 |
| 569 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { | 570 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { |
| 570 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; | 571 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; |
| 571 | 572 |
| 572 if (AudioFinished() && VideoFinished()) { | 573 if (AudioFinished() && VideoFinished()) { |
| 573 playing_ = false; | 574 playing_ = false; |
| 574 clock_.Pause(); | 575 interpolator_.StopInterpolating(); |
| 575 start_time_ticks_ = base::TimeTicks(); | 576 start_time_ticks_ = base::TimeTicks(); |
| 576 manager()->OnPlaybackComplete(player_id()); | 577 manager()->OnPlaybackComplete(player_id()); |
| 577 } | 578 } |
| 578 } | 579 } |
| 579 | 580 |
| 580 void MediaSourcePlayer::ClearDecodingData() { | 581 void MediaSourcePlayer::ClearDecodingData() { |
| 581 DVLOG(1) << __FUNCTION__; | 582 DVLOG(1) << __FUNCTION__; |
| 582 audio_decoder_job_->Flush(); | 583 audio_decoder_job_->Flush(); |
| 583 video_decoder_job_->Flush(); | 584 video_decoder_job_->Flush(); |
| 584 start_time_ticks_ = base::TimeTicks(); | 585 start_time_ticks_ = base::TimeTicks(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 663 if (pending_event_ != NO_EVENT_PENDING) { | 664 if (pending_event_ != NO_EVENT_PENDING) { |
| 664 ProcessPendingEvents(); | 665 ProcessPendingEvents(); |
| 665 return; | 666 return; |
| 666 } | 667 } |
| 667 | 668 |
| 668 if (!playing_) | 669 if (!playing_) |
| 669 return; | 670 return; |
| 670 | 671 |
| 671 start_time_ticks_ = base::TimeTicks::Now(); | 672 start_time_ticks_ = base::TimeTicks::Now(); |
| 672 start_presentation_timestamp_ = GetCurrentTime(); | 673 start_presentation_timestamp_ = GetCurrentTime(); |
| 673 if (!clock_.IsPlaying()) | 674 if (!interpolator_.interpolating()) |
| 674 clock_.Play(); | 675 interpoatlor_.StartInterpolating(); |
|
acolwell GONE FROM CHROMIUM
2014/07/09 00:42:46
s/poatl/polat/
scherkus (not reviewing)
2014/07/09 01:54:31
Done.
| |
| 675 | 676 |
| 676 if (!AudioFinished()) | 677 if (!AudioFinished()) |
| 677 DecodeMoreAudio(); | 678 DecodeMoreAudio(); |
| 678 | 679 |
| 679 if (!VideoFinished()) | 680 if (!VideoFinished()) |
| 680 DecodeMoreVideo(); | 681 DecodeMoreVideo(); |
| 681 } | 682 } |
| 682 | 683 |
| 683 void MediaSourcePlayer::OnDemuxerConfigsChanged() { | 684 void MediaSourcePlayer::OnDemuxerConfigsChanged() { |
| 684 manager()->OnMediaMetadataChanged( | 685 manager()->OnMediaMetadataChanged( |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 // release MediaDrm when the video is paused, or when the device goes to | 750 // release MediaDrm when the video is paused, or when the device goes to |
| 750 // sleep (see http://crbug.com/272421). | 751 // sleep (see http://crbug.com/272421). |
| 751 NOTREACHED() << "CDM detachment not supported."; | 752 NOTREACHED() << "CDM detachment not supported."; |
| 752 DCHECK(drm_bridge_); | 753 DCHECK(drm_bridge_); |
| 753 audio_decoder_job_->SetDrmBridge(NULL); | 754 audio_decoder_job_->SetDrmBridge(NULL); |
| 754 video_decoder_job_->SetDrmBridge(NULL); | 755 video_decoder_job_->SetDrmBridge(NULL); |
| 755 drm_bridge_ = NULL; | 756 drm_bridge_ = NULL; |
| 756 } | 757 } |
| 757 | 758 |
| 758 } // namespace media | 759 } // namespace media |
| OLD | NEW |