OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_codec_player.h" | 5 #include "media/base/android/media_codec_player.h" |
6 | 6 |
7 #include "base/barrier_closure.h" | 7 #include "base/barrier_closure.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 66 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
67 | 67 |
68 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; | 68 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; |
69 | 69 |
70 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); | 70 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); |
71 | 71 |
72 completion_cb_ = | 72 completion_cb_ = |
73 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); | 73 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); |
74 seek_done_cb_ = | 74 seek_done_cb_ = |
75 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); | 75 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); |
76 error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); | |
76 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, | 77 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, |
77 WeakPtrForUIThread(), nullptr); | 78 WeakPtrForUIThread(), nullptr); |
78 detach_listener_cb_ = | 79 detach_listener_cb_ = |
79 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); | 80 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); |
80 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, | 81 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, |
81 WeakPtrForUIThread()); | 82 WeakPtrForUIThread()); |
82 time_update_cb_ = | 83 time_update_cb_ = |
83 base::Bind(&MediaPlayerAndroid::OnTimeUpdate, WeakPtrForUIThread()); | 84 base::Bind(&MediaPlayerAndroid::OnTimeUpdate, WeakPtrForUIThread()); |
84 | 85 |
85 media_weak_this_ = media_weak_factory_.GetWeakPtr(); | 86 media_weak_this_ = media_weak_factory_.GetWeakPtr(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 | 124 |
124 // Post deletion onto Media thread | 125 // Post deletion onto Media thread |
125 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); | 126 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); |
126 } | 127 } |
127 | 128 |
128 void MediaCodecPlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { | 129 void MediaCodecPlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
129 RUN_ON_MEDIA_THREAD(SetVideoSurface, base::Passed(&surface)); | 130 RUN_ON_MEDIA_THREAD(SetVideoSurface, base::Passed(&surface)); |
130 | 131 |
131 DVLOG(1) << __FUNCTION__ << (surface.IsEmpty() ? " empty" : " non-empty"); | 132 DVLOG(1) << __FUNCTION__ << (surface.IsEmpty() ? " empty" : " non-empty"); |
132 | 133 |
133 // I assume that if video decoder already has the surface, | 134 // Save the empty-ness before we pass the surface to the decoder. |
134 // there will be two calls: | 135 bool surface_is_empty = surface.IsEmpty(); |
135 // (1) SetVideoSurface(0) | |
136 // (2) SetVideoSurface(new_surface) | |
137 video_decoder_->SetPendingSurface(surface.Pass()); | |
138 | 136 |
139 if (video_decoder_->HasPendingSurface() && | 137 // Apparently RemoveVideoSurface() can be called several times in a row, |
140 state_ == STATE_WAITING_FOR_SURFACE) { | 138 // ignore the second and subsequent calls. |
141 SetState(STATE_PLAYING); | 139 if (surface_is_empty && !video_decoder_->HasVideoSurface()) { |
142 StartPlaybackDecoders(); | 140 DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; |
141 return; | |
142 } | |
143 | |
144 video_decoder_->SetVideoSurface(surface.Pass()); | |
145 | |
146 if (surface_is_empty) { | |
147 // Remove video surface. | |
148 switch (state_) { | |
149 case STATE_PLAYING: | |
150 if (VideoFinished()) | |
151 break; | |
152 | |
153 DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; | |
154 // Stop decoders as quickly as possible. | |
155 StopDecoders(); // synchronous stop | |
156 | |
157 // Prefetch or wait for initial configuration. | |
158 if (HasAudio() || HasVideo()) { | |
159 SetState(STATE_PREFETCHING); | |
160 StartPrefetchDecoders(); | |
161 } else { | |
162 SetState(STATE_WAITING_FOR_CONFIG); | |
163 } | |
164 break; | |
165 | |
166 default: | |
167 break; // ignore | |
168 } | |
169 } else { | |
170 // Replace video surface. | |
171 switch (state_) { | |
172 case STATE_WAITING_FOR_SURFACE: | |
173 SetState(STATE_PLAYING); | |
174 StartPlaybackOrBrowserSeek(); | |
175 break; | |
176 | |
177 case STATE_PLAYING: | |
178 if (VideoFinished()) | |
179 break; | |
180 | |
181 DVLOG(1) << __FUNCTION__ << ": requesting to stop and restart"; | |
182 SetState(STATE_STOPPING); | |
183 RequestToStopDecoders(); | |
184 SetPendingStart(true); | |
185 break; | |
186 | |
187 default: | |
188 break; // ignore | |
189 } | |
143 } | 190 } |
144 } | 191 } |
145 | 192 |
146 void MediaCodecPlayer::Start() { | 193 void MediaCodecPlayer::Start() { |
147 RUN_ON_MEDIA_THREAD(Start); | 194 RUN_ON_MEDIA_THREAD(Start); |
148 | 195 |
149 DVLOG(1) << __FUNCTION__; | 196 DVLOG(1) << __FUNCTION__; |
150 | 197 |
151 switch (state_) { | 198 switch (state_) { |
152 case STATE_PAUSED: | 199 case STATE_PAUSED: |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 NOTREACHED(); | 286 NOTREACHED(); |
240 break; | 287 break; |
241 } | 288 } |
242 } | 289 } |
243 | 290 |
244 void MediaCodecPlayer::Release() { | 291 void MediaCodecPlayer::Release() { |
245 RUN_ON_MEDIA_THREAD(Release); | 292 RUN_ON_MEDIA_THREAD(Release); |
246 | 293 |
247 DVLOG(1) << __FUNCTION__; | 294 DVLOG(1) << __FUNCTION__; |
248 | 295 |
249 SetState(STATE_PAUSED); | 296 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser |
Tima Vaisburd
2015/07/28 22:56:44
Changed this Release().
| |
297 // and renderer processes going. Seek should work across and after Release(). | |
298 | |
250 ReleaseDecoderResources(); | 299 ReleaseDecoderResources(); |
300 | |
301 SetPendingStart(false); | |
302 | |
303 if (state_ != STATE_WAITING_FOR_SEEK) | |
304 SetState(STATE_PAUSED); | |
305 | |
306 base::TimeDelta pending_seek_time = GetPendingSeek(); | |
307 if (pending_seek_time != kNoTimestamp()) { | |
308 SetPendingSeek(kNoTimestamp()); | |
309 SetState(STATE_WAITING_FOR_SEEK); | |
310 RequestDemuxerSeek(pending_seek_time); | |
311 } | |
251 } | 312 } |
252 | 313 |
253 void MediaCodecPlayer::SetVolume(double volume) { | 314 void MediaCodecPlayer::SetVolume(double volume) { |
254 RUN_ON_MEDIA_THREAD(SetVolume, volume); | 315 RUN_ON_MEDIA_THREAD(SetVolume, volume); |
255 | 316 |
256 DVLOG(1) << __FUNCTION__ << " " << volume; | 317 DVLOG(1) << __FUNCTION__ << " " << volume; |
257 audio_decoder_->SetVolume(volume); | 318 audio_decoder_->SetVolume(volume); |
258 } | 319 } |
259 | 320 |
260 int MediaCodecPlayer::GetVideoWidth() { | 321 int MediaCodecPlayer::GetVideoWidth() { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
347 if (data.type == DemuxerStream::VIDEO) | 408 if (data.type == DemuxerStream::VIDEO) |
348 video_decoder_->OnDemuxerDataAvailable(data); | 409 video_decoder_->OnDemuxerDataAvailable(data); |
349 } | 410 } |
350 | 411 |
351 void MediaCodecPlayer::OnDemuxerSeekDone( | 412 void MediaCodecPlayer::OnDemuxerSeekDone( |
352 base::TimeDelta actual_browser_seek_time) { | 413 base::TimeDelta actual_browser_seek_time) { |
353 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 414 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
354 | 415 |
355 DVLOG(1) << __FUNCTION__ << " actual_time:" << actual_browser_seek_time; | 416 DVLOG(1) << __FUNCTION__ << " actual_time:" << actual_browser_seek_time; |
356 | 417 |
357 if (state_ != STATE_WAITING_FOR_SEEK) | 418 DCHECK(state_ == STATE_WAITING_FOR_SEEK); |
Tima Vaisburd
2015/07/28 22:56:44
Added this DCHECK instead of ignoring the signal i
| |
358 return; // ignore | |
359 | |
360 DCHECK(seek_info_.get()); | 419 DCHECK(seek_info_.get()); |
361 DCHECK(seek_info_->seek_time != kNoTimestamp()); | 420 DCHECK(seek_info_->seek_time != kNoTimestamp()); |
362 | 421 |
363 // A browser seek must not jump into the past. Ideally, it seeks to the | 422 // A browser seek must not jump into the past. Ideally, it seeks to the |
364 // requested time, but it might jump into the future. | 423 // requested time, but it might jump into the future. |
365 DCHECK(!seek_info_->is_browser_seek || | 424 DCHECK(!seek_info_->is_browser_seek || |
366 seek_info_->seek_time <= actual_browser_seek_time); | 425 seek_info_->seek_time <= actual_browser_seek_time); |
367 | 426 |
368 // Restrict the current time to be equal to seek_time | 427 // Restrict the current time to be equal to seek_time |
369 // for the next StartPlaybackDecoders() call. | 428 // for the next StartPlaybackDecoders() call. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
461 if (state_ != STATE_PREFETCHING) { | 520 if (state_ != STATE_PREFETCHING) { |
462 DVLOG(1) << __FUNCTION__ << " wrong state " << AsString(state_) | 521 DVLOG(1) << __FUNCTION__ << " wrong state " << AsString(state_) |
463 << " ignoring"; | 522 << " ignoring"; |
464 return; // Ignore | 523 return; // Ignore |
465 } | 524 } |
466 | 525 |
467 DVLOG(1) << __FUNCTION__; | 526 DVLOG(1) << __FUNCTION__; |
468 | 527 |
469 if (!HasAudio() && !HasVideo()) { | 528 if (!HasAudio() && !HasVideo()) { |
470 // No configuration at all after prefetching. | 529 // No configuration at all after prefetching. |
471 // This is an error, initial configuration is expected | 530 // This is an error, initial configuration is expected |
wolenetz
2015/07/29 22:37:03
nit: we might want to DCHECK that internal_error_c
Tima Vaisburd
2015/07/30 20:28:35
Done.
| |
472 // before the first data chunk. | 531 // before the first data chunk. |
473 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 532 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
474 return; | 533 return; |
475 } | 534 } |
476 | 535 |
477 if (HasVideo() && !HasPendingSurface()) { | 536 if (HasVideo() && !video_decoder_->HasVideoSurface()) { |
478 SetState(STATE_WAITING_FOR_SURFACE); | 537 SetState(STATE_WAITING_FOR_SURFACE); |
479 return; | 538 return; |
480 } | 539 } |
481 | 540 |
482 SetState(STATE_PLAYING); | 541 SetState(STATE_PLAYING); |
483 StartPlaybackDecoders(); | 542 StartPlaybackOrBrowserSeek(); |
484 } | 543 } |
485 | 544 |
486 void MediaCodecPlayer::OnStopDone() { | 545 void MediaCodecPlayer::OnStopDone() { |
487 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 546 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
488 DVLOG(1) << __FUNCTION__; | 547 DVLOG(1) << __FUNCTION__; |
489 | 548 |
490 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) | 549 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) |
491 return; // Wait until other stream is stopped | 550 return; // Wait until other stream is stopped |
492 | 551 |
493 // At this point decoder threads should not be running | 552 // At this point decoder threads should not be running |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 } | 591 } |
533 | 592 |
534 void MediaCodecPlayer::OnError() { | 593 void MediaCodecPlayer::OnError() { |
535 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 594 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
536 DVLOG(1) << __FUNCTION__; | 595 DVLOG(1) << __FUNCTION__; |
537 | 596 |
538 // STATE_ERROR blocks all events | 597 // STATE_ERROR blocks all events |
539 SetState(STATE_ERROR); | 598 SetState(STATE_ERROR); |
540 | 599 |
541 ReleaseDecoderResources(); | 600 ReleaseDecoderResources(); |
601 | |
602 ui_task_runner_->PostTask(FROM_HERE, | |
603 base::Bind(error_cb_, MEDIA_ERROR_DECODE)); | |
542 } | 604 } |
543 | 605 |
544 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { | 606 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { |
545 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 607 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
546 DVLOG(1) << __FUNCTION__ << " stream type:" << type; | 608 DVLOG(1) << __FUNCTION__ << " stream type:" << type; |
547 | 609 |
548 if (state_ != STATE_PLAYING) | 610 if (state_ != STATE_PLAYING) |
549 return; // Ignore | 611 return; // Ignore |
550 | 612 |
551 SetState(STATE_STOPPING); | 613 SetState(STATE_STOPPING); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
598 | 660 |
599 // State machine operations, called on Media thread | 661 // State machine operations, called on Media thread |
600 | 662 |
601 void MediaCodecPlayer::SetState(PlayerState new_state) { | 663 void MediaCodecPlayer::SetState(PlayerState new_state) { |
602 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 664 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
603 | 665 |
604 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); | 666 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); |
605 state_ = new_state; | 667 state_ = new_state; |
606 } | 668 } |
607 | 669 |
608 void MediaCodecPlayer::SetPendingSurface(gfx::ScopedJavaSurface surface) { | |
609 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | |
610 DVLOG(1) << __FUNCTION__; | |
611 | |
612 video_decoder_->SetPendingSurface(surface.Pass()); | |
613 } | |
614 | |
615 bool MediaCodecPlayer::HasPendingSurface() const { | |
616 return video_decoder_->HasPendingSurface(); | |
617 } | |
618 | |
619 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { | 670 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { |
620 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 671 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
621 DVLOG(1) << __FUNCTION__ << ": " << need_to_start; | 672 DVLOG(1) << __FUNCTION__ << ": " << need_to_start; |
622 pending_start_ = need_to_start; | 673 pending_start_ = need_to_start; |
623 } | 674 } |
624 | 675 |
625 bool MediaCodecPlayer::HasPendingStart() const { | 676 bool MediaCodecPlayer::HasPendingStart() const { |
626 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 677 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
627 return pending_start_; | 678 return pending_start_; |
628 } | 679 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
692 base::Closure prefetch_cb = base::BarrierClosure( | 743 base::Closure prefetch_cb = base::BarrierClosure( |
693 count, base::Bind(&MediaCodecPlayer::OnPrefetchDone, media_weak_this_)); | 744 count, base::Bind(&MediaCodecPlayer::OnPrefetchDone, media_weak_this_)); |
694 | 745 |
695 if (do_audio) | 746 if (do_audio) |
696 audio_decoder_->Prefetch(prefetch_cb); | 747 audio_decoder_->Prefetch(prefetch_cb); |
697 | 748 |
698 if (do_video) | 749 if (do_video) |
699 video_decoder_->Prefetch(prefetch_cb); | 750 video_decoder_->Prefetch(prefetch_cb); |
700 } | 751 } |
701 | 752 |
702 void MediaCodecPlayer::StartPlaybackDecoders() { | 753 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { |
703 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 754 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
704 DVLOG(1) << __FUNCTION__; | 755 DVLOG(1) << __FUNCTION__; |
705 | 756 |
706 // Configure all streams before the start since | 757 // TODO(timav): consider replacing this method with posting a |
707 // we may discover that browser seek is required. | 758 // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). |
759 | |
760 StartStatus status = StartPlaybackDecoders(); | |
761 | |
762 switch (status) { | |
763 case START_BROWSER_SEEK_REQUIRED: | |
764 // Browser seek | |
765 SetState(STATE_WAITING_FOR_SEEK); | |
766 SetPendingStart(true); | |
767 StopDecoders(); | |
768 RequestDemuxerSeek(GetInterpolatedTime(), true); | |
769 break; | |
770 case START_FAILED: | |
771 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | |
772 break; | |
773 case START_OK: | |
774 break; | |
775 } | |
776 } | |
777 | |
778 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { | |
779 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | |
780 DVLOG(1) << __FUNCTION__; | |
708 | 781 |
709 bool do_audio = !AudioFinished(); | 782 bool do_audio = !AudioFinished(); |
710 bool do_video = !VideoFinished(); | 783 bool do_video = !VideoFinished(); |
711 | 784 |
712 // If there is nothing to play, the state machine should determine | 785 // If there is nothing to play, the state machine should determine this at the |
713 // this at the prefetch state and never call this method. | 786 // prefetch state and never call this method. |
714 DCHECK(do_audio || do_video); | 787 DCHECK(do_audio || do_video); |
715 | 788 |
789 // Configure all streams before the start since we may discover that browser | |
790 // seek is required. Start with video: if browser seek is required it would | |
791 // not make sense to configure audio. | |
792 | |
793 if (do_video) { | |
794 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); | |
795 switch (status) { | |
796 case MediaCodecDecoder::CONFIG_OK: | |
797 break; | |
798 case MediaCodecDecoder::CONFIG_KEY_FRAME_REQUIRED: | |
799 // TODO(timav): post a task or return the status? | |
800 return START_BROWSER_SEEK_REQUIRED; | |
801 case MediaCodecDecoder::CONFIG_FAILURE: | |
802 return START_FAILED; | |
803 } | |
804 } | |
805 | |
716 if (do_audio) { | 806 if (do_audio) { |
717 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); | 807 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); |
718 if (status != MediaCodecDecoder::CONFIG_OK) { | 808 if (status != MediaCodecDecoder::CONFIG_OK) { |
719 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 809 return START_FAILED; |
720 return; | |
721 } | 810 } |
722 } | 811 } |
723 | 812 |
724 if (do_video) { | |
725 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); | |
726 if (status != MediaCodecDecoder::CONFIG_OK) { | |
727 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | |
728 return; | |
729 } | |
730 } | |
731 | |
732 // At this point decoder threads should not be running. | 813 // At this point decoder threads should not be running. |
733 if (!interpolator_.interpolating()) | 814 if (!interpolator_.interpolating()) |
734 interpolator_.StartInterpolating(); | 815 interpolator_.StartInterpolating(); |
735 | 816 |
736 base::TimeDelta current_time = GetInterpolatedTime(); | 817 base::TimeDelta current_time = GetInterpolatedTime(); |
737 | 818 |
738 if (do_audio) { | 819 if (do_audio) { |
739 if (!audio_decoder_->Start(current_time)) { | 820 if (!audio_decoder_->Start(current_time)) { |
740 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 821 return START_FAILED; |
741 return; | |
742 } | 822 } |
743 | 823 |
744 // Attach listener on UI thread | 824 // Attach listener on UI thread |
745 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); | 825 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); |
746 } | 826 } |
747 | 827 |
748 if (do_video) { | 828 if (do_video) { |
749 if (!video_decoder_->Start(current_time)) { | 829 if (!video_decoder_->Start(current_time)) { |
750 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 830 return START_FAILED; |
751 return; | |
752 } | 831 } |
753 } | 832 } |
833 | |
834 return START_OK; | |
754 } | 835 } |
755 | 836 |
756 void MediaCodecPlayer::StopDecoders() { | 837 void MediaCodecPlayer::StopDecoders() { |
757 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 838 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
758 DVLOG(1) << __FUNCTION__; | 839 DVLOG(1) << __FUNCTION__; |
759 | 840 |
841 video_decoder_->SyncStop(); | |
760 audio_decoder_->SyncStop(); | 842 audio_decoder_->SyncStop(); |
761 video_decoder_->SyncStop(); | |
762 } | 843 } |
763 | 844 |
764 void MediaCodecPlayer::RequestToStopDecoders() { | 845 void MediaCodecPlayer::RequestToStopDecoders() { |
765 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 846 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
766 DVLOG(1) << __FUNCTION__; | 847 DVLOG(1) << __FUNCTION__; |
767 | 848 |
768 bool do_audio = false; | 849 bool do_audio = false; |
769 bool do_video = false; | 850 bool do_video = false; |
770 | 851 |
771 if (audio_decoder_->IsPrefetchingOrPlaying()) | 852 if (audio_decoder_->IsPrefetchingOrPlaying()) |
(...skipping 10 matching lines...) Expand all Loading... | |
782 if (do_audio) | 863 if (do_audio) |
783 audio_decoder_->RequestToStop(); | 864 audio_decoder_->RequestToStop(); |
784 if (do_video) | 865 if (do_video) |
785 video_decoder_->RequestToStop(); | 866 video_decoder_->RequestToStop(); |
786 } | 867 } |
787 | 868 |
788 void MediaCodecPlayer::RequestDemuxerSeek(base::TimeDelta seek_time, | 869 void MediaCodecPlayer::RequestDemuxerSeek(base::TimeDelta seek_time, |
789 bool is_browser_seek) { | 870 bool is_browser_seek) { |
790 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 871 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
791 DVLOG(1) << __FUNCTION__ << " " << seek_time | 872 DVLOG(1) << __FUNCTION__ << " " << seek_time |
792 << (is_browser_seek ? " browser_seek" : ""); | 873 << (is_browser_seek ? " BROWSER_SEEK" : ""); |
793 | 874 |
794 // Flush decoders before requesting demuxer. | 875 // Flush decoders before requesting demuxer. |
795 audio_decoder_->Flush(); | 876 audio_decoder_->Flush(); |
796 video_decoder_->Flush(); | 877 video_decoder_->Flush(); |
797 | 878 |
798 // Save active seek data. Logically it is attached to STATE_WAITING_FOR_SEEK. | 879 // Save active seek data. Logically it is attached to STATE_WAITING_FOR_SEEK. |
799 DCHECK(state_ == STATE_WAITING_FOR_SEEK); | 880 DCHECK(state_ == STATE_WAITING_FOR_SEEK); |
800 seek_info_.reset(new SeekInfo(seek_time, is_browser_seek)); | 881 seek_info_.reset(new SeekInfo(seek_time, is_browser_seek)); |
801 | 882 |
802 demuxer_->RequestDemuxerSeek(seek_time, is_browser_seek); | 883 demuxer_->RequestDemuxerSeek(seek_time, is_browser_seek); |
(...skipping 11 matching lines...) Expand all Loading... | |
814 | 895 |
815 // At this point decoder threads should not be running | 896 // At this point decoder threads should not be running |
816 if (interpolator_.interpolating()) | 897 if (interpolator_.interpolating()) |
817 interpolator_.StopInterpolating(); | 898 interpolator_.StopInterpolating(); |
818 } | 899 } |
819 | 900 |
820 void MediaCodecPlayer::CreateDecoders() { | 901 void MediaCodecPlayer::CreateDecoders() { |
821 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 902 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
822 DVLOG(1) << __FUNCTION__; | 903 DVLOG(1) << __FUNCTION__; |
823 | 904 |
824 error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); | 905 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); |
825 | 906 |
826 audio_decoder_.reset(new MediaCodecAudioDecoder( | 907 audio_decoder_.reset(new MediaCodecAudioDecoder( |
827 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 908 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
828 media_weak_this_, DemuxerStream::AUDIO), | 909 media_weak_this_, DemuxerStream::AUDIO), |
829 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 910 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
830 DemuxerStream::AUDIO), | 911 DemuxerStream::AUDIO), |
831 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), error_cb_, | 912 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), |
913 internal_error_cb_, | |
832 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 914 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
833 DemuxerStream::AUDIO))); | 915 DemuxerStream::AUDIO))); |
834 | 916 |
835 video_decoder_.reset(new MediaCodecVideoDecoder( | 917 video_decoder_.reset(new MediaCodecVideoDecoder( |
836 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 918 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
837 media_weak_this_, DemuxerStream::VIDEO), | 919 media_weak_this_, DemuxerStream::VIDEO), |
838 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 920 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
839 DemuxerStream::VIDEO), | 921 DemuxerStream::VIDEO), |
840 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), error_cb_, | 922 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), |
923 internal_error_cb_, | |
841 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 924 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
842 DemuxerStream::VIDEO), | 925 DemuxerStream::VIDEO), |
843 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), | 926 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), |
844 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); | 927 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); |
845 } | 928 } |
846 | 929 |
847 bool MediaCodecPlayer::AudioFinished() const { | 930 bool MediaCodecPlayer::AudioFinished() const { |
848 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); | 931 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); |
849 } | 932 } |
850 | 933 |
(...skipping 23 matching lines...) Expand all Loading... | |
874 RETURN_STRING(STATE_WAITING_FOR_SURFACE); | 957 RETURN_STRING(STATE_WAITING_FOR_SURFACE); |
875 RETURN_STRING(STATE_WAITING_FOR_SEEK); | 958 RETURN_STRING(STATE_WAITING_FOR_SEEK); |
876 RETURN_STRING(STATE_ERROR); | 959 RETURN_STRING(STATE_ERROR); |
877 } | 960 } |
878 return nullptr; // crash early | 961 return nullptr; // crash early |
879 } | 962 } |
880 | 963 |
881 #undef RETURN_STRING | 964 #undef RETURN_STRING |
882 | 965 |
883 } // namespace media | 966 } // namespace media |
OLD | NEW |