Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: media/base/android/media_source_player.cc

Issue 79283006: Let only seeks reset Android MSE stream playback completion (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, LOG(INFO)->VLOG(0), and spot-check in tests that decoder doesn't resume after EOS processed Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 scoped_ptr<DemuxerAndroid> demuxer) 66 scoped_ptr<DemuxerAndroid> demuxer)
67 : MediaPlayerAndroid(player_id, manager), 67 : MediaPlayerAndroid(player_id, manager),
68 demuxer_(demuxer.Pass()), 68 demuxer_(demuxer.Pass()),
69 pending_event_(NO_EVENT_PENDING), 69 pending_event_(NO_EVENT_PENDING),
70 width_(0), 70 width_(0),
71 height_(0), 71 height_(0),
72 audio_codec_(kUnknownAudioCodec), 72 audio_codec_(kUnknownAudioCodec),
73 video_codec_(kUnknownVideoCodec), 73 video_codec_(kUnknownVideoCodec),
74 num_channels_(0), 74 num_channels_(0),
75 sampling_rate_(0), 75 sampling_rate_(0),
76 audio_finished_(true), 76 audio_finished_(false),
77 video_finished_(true), 77 video_finished_(false),
78 playing_(false), 78 playing_(false),
79 is_audio_encrypted_(false), 79 is_audio_encrypted_(false),
80 is_video_encrypted_(false), 80 is_video_encrypted_(false),
81 volume_(-1.0), 81 volume_(-1.0),
82 clock_(&default_tick_clock_), 82 clock_(&default_tick_clock_),
83 next_video_data_is_iframe_(true), 83 next_video_data_is_iframe_(true),
84 doing_browser_seek_(false), 84 doing_browser_seek_(false),
85 pending_seek_(false), 85 pending_seek_(false),
86 reconfig_audio_decoder_(false), 86 reconfig_audio_decoder_(false),
87 reconfig_video_decoder_(false), 87 reconfig_video_decoder_(false),
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 // Create decoder jobs if they are not created 311 // Create decoder jobs if they are not created
312 ConfigureAudioDecoderJob(); 312 ConfigureAudioDecoderJob();
313 ConfigureVideoDecoderJob(); 313 ConfigureVideoDecoderJob();
314 314
315 // If one of the decoder job is not ready, do nothing. 315 // If one of the decoder job is not ready, do nothing.
316 if ((HasAudio() && !audio_decoder_job_) || 316 if ((HasAudio() && !audio_decoder_job_) ||
317 (HasVideo() && !video_decoder_job_)) { 317 (HasVideo() && !video_decoder_job_)) {
318 return; 318 return;
319 } 319 }
320 320
321 audio_finished_ = false;
322 video_finished_ = false;
323 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 321 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
324 ProcessPendingEvents(); 322 ProcessPendingEvents();
325 } 323 }
326 324
327 void MediaSourcePlayer::OnDemuxerConfigsAvailable( 325 void MediaSourcePlayer::OnDemuxerConfigsAvailable(
328 const DemuxerConfigs& configs) { 326 const DemuxerConfigs& configs) {
329 DVLOG(1) << __FUNCTION__; 327 DVLOG(1) << __FUNCTION__;
330 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms); 328 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms);
331 clock_.SetDuration(duration_); 329 clock_.SetDuration(duration_);
332 330
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 if (playing_) 395 if (playing_)
398 StartInternal(); 396 StartInternal();
399 } 397 }
400 398
401 void MediaSourcePlayer::SetDrmBridge(MediaDrmBridge* drm_bridge) { 399 void MediaSourcePlayer::SetDrmBridge(MediaDrmBridge* drm_bridge) {
402 // Currently we don't support DRM change during the middle of playback, even 400 // Currently we don't support DRM change during the middle of playback, even
403 // if the player is paused. 401 // if the player is paused.
404 // TODO(qinmin): support DRM change after playback has started. 402 // TODO(qinmin): support DRM change after playback has started.
405 // http://crbug.com/253792. 403 // http://crbug.com/253792.
406 if (GetCurrentTime() > base::TimeDelta()) { 404 if (GetCurrentTime() > base::TimeDelta()) {
407 LOG(INFO) << "Setting DRM bridge after playback has started. " 405 VLOG(0) << "Setting DRM bridge after playback has started. "
408 << "This is not well supported!"; 406 << "This is not well supported!";
409 } 407 }
410 408
411 drm_bridge_ = drm_bridge; 409 drm_bridge_ = drm_bridge;
412 410
413 if (drm_bridge_->GetMediaCrypto().is_null()) { 411 if (drm_bridge_->GetMediaCrypto().is_null()) {
414 drm_bridge_->SetMediaCryptoReadyCB(base::Bind( 412 drm_bridge_->SetMediaCryptoReadyCB(base::Bind(
415 &MediaSourcePlayer::OnMediaCryptoReady, weak_this_.GetWeakPtr())); 413 &MediaSourcePlayer::OnMediaCryptoReady, weak_this_.GetWeakPtr()));
416 return; 414 return;
417 } 415 }
418 416
(...skipping 25 matching lines...) Expand all
444 // A browser seek must not jump into the past. Ideally, it seeks to the 442 // A browser seek must not jump into the past. Ideally, it seeks to the
445 // requested time, but it might jump into the future. 443 // requested time, but it might jump into the future.
446 DCHECK(actual_browser_seek_time >= GetCurrentTime()); 444 DCHECK(actual_browser_seek_time >= GetCurrentTime());
447 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " 445 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: "
448 << actual_browser_seek_time.InSecondsF(); 446 << actual_browser_seek_time.InSecondsF();
449 clock_.SetTime(actual_browser_seek_time, actual_browser_seek_time); 447 clock_.SetTime(actual_browser_seek_time, actual_browser_seek_time);
450 if (audio_timestamp_helper_) 448 if (audio_timestamp_helper_)
451 audio_timestamp_helper_->SetBaseTimestamp(actual_browser_seek_time); 449 audio_timestamp_helper_->SetBaseTimestamp(actual_browser_seek_time);
452 } 450 }
453 451
452 audio_finished_ = false;
453 video_finished_ = false;
454
454 base::TimeDelta current_time = GetCurrentTime(); 455 base::TimeDelta current_time = GetCurrentTime();
455 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| 456 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_|
456 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| 457 // to preroll media decoder jobs. Currently |start_presentation_timestamp_|
457 // is calculated from decoder output, while preroll relies on the access 458 // is calculated from decoder output, while preroll relies on the access
458 // unit's timestamp. There are some differences between the two. 459 // unit's timestamp. There are some differences between the two.
459 preroll_timestamp_ = current_time; 460 preroll_timestamp_ = current_time;
460 if (audio_decoder_job_) 461 if (audio_decoder_job_)
461 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); 462 audio_decoder_job_->BeginPrerolling(preroll_timestamp_);
462 if (video_decoder_job_) 463 if (video_decoder_job_)
463 video_decoder_job_->BeginPrerolling(preroll_timestamp_); 464 video_decoder_job_->BeginPrerolling(preroll_timestamp_);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 524
524 // Return early if we can't successfully configure a new video decoder job 525 // Return early if we can't successfully configure a new video decoder job
525 // yet, except continue processing other pending events if |surface_| is 526 // yet, except continue processing other pending events if |surface_| is
526 // empty. 527 // empty.
527 if (!video_decoder_job_ && !surface_.IsEmpty()) 528 if (!video_decoder_job_ && !surface_.IsEmpty())
528 return; 529 return;
529 } 530 }
530 531
531 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { 532 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) {
532 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; 533 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT.";
533 int count = (audio_decoder_job_ ? 1 : 0) + (video_decoder_job_ ? 1 : 0); 534 int count = ((audio_decoder_job_ && !audio_finished_) ? 1 : 0) +
acolwell GONE FROM CHROMIUM 2013/11/25 21:43:59 I think the audio_decoder_ && !audio_finished_ con
wolenetz 2013/12/04 00:13:29 Done, with ternary swapped, as AudioFinishedOrNoAu
535 ((video_decoder_job_ && !video_finished_) ? 1 : 0);
534 536
535 base::Closure barrier = BarrierClosure(count, base::Bind( 537 base::Closure barrier = BarrierClosure(count, base::Bind(
536 &MediaSourcePlayer::OnPrefetchDone, weak_this_.GetWeakPtr())); 538 &MediaSourcePlayer::OnPrefetchDone, weak_this_.GetWeakPtr()));
537 539
538 if (audio_decoder_job_) 540 if (audio_decoder_job_ && !audio_finished_)
539 audio_decoder_job_->Prefetch(barrier); 541 audio_decoder_job_->Prefetch(barrier);
540 542
541 if (video_decoder_job_) 543 if (video_decoder_job_ && !video_finished_)
542 video_decoder_job_->Prefetch(barrier); 544 video_decoder_job_->Prefetch(barrier);
543 545
544 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); 546 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING);
545 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 547 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
546 return; 548 return;
547 } 549 }
548 550
549 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); 551 DCHECK_EQ(pending_event_, NO_EVENT_PENDING);
550 552
551 // Now that all pending events have been handled, resume decoding if we are 553 // Now that all pending events have been handled, resume decoding if we are
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); 591 manager()->OnError(player_id(), MEDIA_ERROR_DECODE);
590 return; 592 return;
591 } 593 }
592 594
593 if (pending_event_ != NO_EVENT_PENDING) { 595 if (pending_event_ != NO_EVENT_PENDING) {
594 ProcessPendingEvents(); 596 ProcessPendingEvents();
595 return; 597 return;
596 } 598 }
597 599
598 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { 600 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) {
599 PlaybackCompleted(is_audio); 601 PlaybackCompleted(is_audio);
qinmin 2013/11/26 23:49:47 PlaybackCommpleted is executed after ProcessPendin
qinmin 2013/12/03 23:45:16 Pending seek is the reason processPendingEvents sh
wolenetz 2013/12/04 00:13:29 Done per the original comment, not the one from 12
600 return; 602 return;
601 } 603 }
602 604
603 if (status == MEDIA_CODEC_OK && is_clock_manager && 605 if (status == MEDIA_CODEC_OK && is_clock_manager &&
604 presentation_timestamp != kNoTimestamp()) { 606 presentation_timestamp != kNoTimestamp()) {
605 UpdateTimestamps(presentation_timestamp, audio_output_bytes); 607 UpdateTimestamps(presentation_timestamp, audio_output_bytes);
606 } 608 }
607 609
608 if (!playing_) { 610 if (!playing_) {
609 if (is_clock_manager) 611 if (is_clock_manager)
(...skipping 26 matching lines...) Expand all
636 DecodeMoreAudio(); 638 DecodeMoreAudio();
637 return; 639 return;
638 } 640 }
639 641
640 DecodeMoreVideo(); 642 DecodeMoreVideo();
641 } 643 }
642 644
643 void MediaSourcePlayer::DecodeMoreAudio() { 645 void MediaSourcePlayer::DecodeMoreAudio() {
644 DVLOG(1) << __FUNCTION__; 646 DVLOG(1) << __FUNCTION__;
645 DCHECK(!audio_decoder_job_->is_decoding()); 647 DCHECK(!audio_decoder_job_->is_decoding());
648 DCHECK(!audio_finished_);
646 649
647 if (audio_decoder_job_->Decode( 650 if (audio_decoder_job_->Decode(
648 start_time_ticks_, start_presentation_timestamp_, base::Bind( 651 start_time_ticks_, start_presentation_timestamp_, base::Bind(
649 &MediaSourcePlayer::MediaDecoderCallback, 652 &MediaSourcePlayer::MediaDecoderCallback,
650 weak_this_.GetWeakPtr(), true))) { 653 weak_this_.GetWeakPtr(), true))) {
651 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", 654 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio",
652 audio_decoder_job_.get()); 655 audio_decoder_job_.get());
653 return; 656 return;
654 } 657 }
655 658
656 // Failed to start the next decode. 659 // Failed to start the next decode.
657 // Wait for demuxer ready message. 660 // Wait for demuxer ready message.
658 DCHECK(!reconfig_audio_decoder_); 661 DCHECK(!reconfig_audio_decoder_);
659 reconfig_audio_decoder_ = true; 662 reconfig_audio_decoder_ = true;
660 663
661 // Config change may have just been detected on the other stream. If so, 664 // Config change may have just been detected on the other stream. If so,
662 // don't send a duplicate demuxer config request. 665 // don't send a duplicate demuxer config request.
663 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { 666 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) {
664 DCHECK(reconfig_video_decoder_); 667 DCHECK(reconfig_video_decoder_);
665 return; 668 return;
666 } 669 }
667 670
668 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); 671 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING);
669 ProcessPendingEvents(); 672 ProcessPendingEvents();
670 } 673 }
671 674
672 void MediaSourcePlayer::DecodeMoreVideo() { 675 void MediaSourcePlayer::DecodeMoreVideo() {
673 DVLOG(1) << __FUNCTION__; 676 DVLOG(1) << __FUNCTION__;
674 DCHECK(!video_decoder_job_->is_decoding()); 677 DCHECK(!video_decoder_job_->is_decoding());
678 DCHECK(!video_finished_);
675 679
676 if (video_decoder_job_->Decode( 680 if (video_decoder_job_->Decode(
677 start_time_ticks_, start_presentation_timestamp_, base::Bind( 681 start_time_ticks_, start_presentation_timestamp_, base::Bind(
678 &MediaSourcePlayer::MediaDecoderCallback, 682 &MediaSourcePlayer::MediaDecoderCallback,
679 weak_this_.GetWeakPtr(), false))) { 683 weak_this_.GetWeakPtr(), false))) {
680 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", 684 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo",
681 video_decoder_job_.get()); 685 video_decoder_job_.get());
682 return; 686 return;
683 } 687 }
684 688
(...skipping 18 matching lines...) Expand all
703 ProcessPendingEvents(); 707 ProcessPendingEvents();
704 } 708 }
705 709
706 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { 710 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
707 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; 711 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")";
708 if (is_audio) 712 if (is_audio)
709 audio_finished_ = true; 713 audio_finished_ = true;
710 else 714 else
711 video_finished_ = true; 715 video_finished_ = true;
712 716
713 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) { 717 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) {
acolwell GONE FROM CHROMIUM 2013/11/25 21:43:59 This makes me wonder whether audio_decoder_job_ &&
wolenetz 2013/12/04 00:13:29 Done, following the latter option in 3, with a lit
714 playing_ = false; 718 playing_ = false;
715 clock_.Pause(); 719 clock_.Pause();
716 start_time_ticks_ = base::TimeTicks(); 720 start_time_ticks_ = base::TimeTicks();
717 manager()->OnPlaybackComplete(player_id()); 721 manager()->OnPlaybackComplete(player_id());
718 } 722 }
719 } 723 }
720 724
721 void MediaSourcePlayer::ClearDecodingData() { 725 void MediaSourcePlayer::ClearDecodingData() {
722 DVLOG(1) << __FUNCTION__; 726 DVLOG(1) << __FUNCTION__;
723 if (audio_decoder_job_) 727 if (audio_decoder_job_)
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 if (pending_event_ != NO_EVENT_PENDING) { 913 if (pending_event_ != NO_EVENT_PENDING) {
910 ProcessPendingEvents(); 914 ProcessPendingEvents();
911 return; 915 return;
912 } 916 }
913 917
914 start_time_ticks_ = base::TimeTicks::Now(); 918 start_time_ticks_ = base::TimeTicks::Now();
915 start_presentation_timestamp_ = GetCurrentTime(); 919 start_presentation_timestamp_ = GetCurrentTime();
916 if (!clock_.IsPlaying()) 920 if (!clock_.IsPlaying())
917 clock_.Play(); 921 clock_.Play();
918 922
919 if (audio_decoder_job_) 923 if (audio_decoder_job_ && !audio_finished_)
920 DecodeMoreAudio(); 924 DecodeMoreAudio();
921 if (video_decoder_job_) 925 if (video_decoder_job_ && !video_finished_)
922 DecodeMoreVideo(); 926 DecodeMoreVideo();
923 } 927 }
924 928
925 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { 929 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) {
926 static const char* kPendingEventNames[] = { 930 static const char* kPendingEventNames[] = {
927 "SEEK", 931 "SEEK",
928 "SURFACE_CHANGE", 932 "SURFACE_CHANGE",
929 "CONFIG_CHANGE", 933 "CONFIG_CHANGE",
930 "PREFETCH_REQUEST", 934 "PREFETCH_REQUEST",
931 "PREFETCH_DONE", 935 "PREFETCH_DONE",
(...skipping 22 matching lines...) Expand all
954 958
955 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { 959 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) {
956 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; 960 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")";
957 DCHECK_NE(event, NO_EVENT_PENDING); 961 DCHECK_NE(event, NO_EVENT_PENDING);
958 DCHECK(IsEventPending(event)) << GetEventName(event); 962 DCHECK(IsEventPending(event)) << GetEventName(event);
959 963
960 pending_event_ &= ~event; 964 pending_event_ &= ~event;
961 } 965 }
962 966
963 } // namespace media 967 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/base/android/media_source_player_unittest.cc » ('j') | media/base/android/media_source_player_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698