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_.SetUpperBound(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_.SetBounds(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_.SetBounds(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_.SetBounds(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 interpolator_.StartInterpolating(); |
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 |