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

Unified Diff: media/base/android/media_source_player.cc

Issue 15499006: Enable seek in fullscreen mode for MSE impl on android (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 7 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/android/media_source_player.h ('k') | webkit/media/android/media_source_delegate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/android/media_source_player.cc
diff --git a/media/base/android/media_source_player.cc b/media/base/android/media_source_player.cc
index f6cbd48a2d8ed45de5c0ab768555af0882bc4c0d..00cddb75bd3982a2c2538ac1a4a5404ecbdf19fa 100644
--- a/media/base/android/media_source_player.cc
+++ b/media/base/android/media_source_player.cc
@@ -192,7 +192,8 @@ MediaSourcePlayer::MediaSourcePlayer(
int player_id,
MediaPlayerManager* manager)
: MediaPlayerAndroid(player_id, manager),
- pending_play_(false),
+ pending_event_(NO_EVENT_PENDING),
+ active_decoding_tasks_(0),
width_(0),
height_(0),
audio_codec_(kUnknownAudioCodec),
@@ -207,6 +208,7 @@ MediaSourcePlayer::MediaSourcePlayer(
video_access_unit_index_(0),
waiting_for_audio_data_(false),
waiting_for_video_data_(false),
+ use_empty_surface_(true),
weak_this_(this) {
}
@@ -215,8 +217,15 @@ MediaSourcePlayer::~MediaSourcePlayer() {
}
void MediaSourcePlayer::SetVideoSurface(jobject surface) {
- video_decoder_job_.reset();
- if (!surface) {
+ use_empty_surface_ = surface ? false : true;
+
+ // If we haven't processed a surface change event, do so now.
+ if (active_decoding_tasks_ > 0) {
+ pending_event_ |= SURFACE_CHANGE_EVENT_PENDING;
+ // Request a seek so that the next decoder will decode an I-frame first.
+ // Or otherwise, MediaCodec might crash. See b/8950387.
+ pending_event_ |= SEEK_EVENT_PENDING;
+ ProcessPendingEvents();
return;
}
@@ -226,16 +235,27 @@ void MediaSourcePlayer::SetVideoSurface(jobject surface) {
gfx::Size(width_, height_), surface));
}
- if (pending_play_)
- StartInternal();
-
// Inform the fullscreen view the player is ready.
// TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
// to inform ContentVideoView.
OnMediaMetadataChanged(duration_, width_, height_, true);
+
+ if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
+ // We should already requested a seek in this case.
+ pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
+ } else {
+ // Perform a seek so the new decoder can get the I-frame first.
+ pending_event_ |= SEEK_EVENT_PENDING;
+ ProcessPendingEvents();
+ return;
+ }
+
+ if (playing_)
+ StartInternal();
}
void MediaSourcePlayer::Start() {
+ playing_ = true;
if (HasAudio() && !audio_decoder_job_) {
audio_decoder_job_.reset(new AudioDecoderJob(
base::MessageLoopProxy::current(), audio_codec_, sampling_rate_,
@@ -244,7 +264,6 @@ void MediaSourcePlayer::Start() {
if (HasVideo() && !video_decoder_job_) {
// StartInternal() will be delayed until SetVideoSurface() gets called.
- pending_play_ = true;
return;
}
@@ -252,13 +271,12 @@ void MediaSourcePlayer::Start() {
}
void MediaSourcePlayer::Pause() {
- pending_play_ = false;
playing_ = false;
start_wallclock_time_ = base::Time();
}
bool MediaSourcePlayer::IsPlaying() {
- return pending_play_ || playing_;
+ return playing_;
}
int MediaSourcePlayer::GetVideoWidth() {
@@ -271,17 +289,8 @@ int MediaSourcePlayer::GetVideoHeight() {
void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
last_presentation_timestamp_ = timestamp;
- start_wallclock_time_ = base::Time();
- last_seek_time_ = base::Time::Now();
- if (audio_decoder_job_)
- audio_decoder_job_->Flush();
- if (video_decoder_job_)
- video_decoder_job_->Flush();
- received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
- received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
- audio_access_unit_index_ = 0;
- video_access_unit_index_ = 0;
- OnSeekComplete();
+ pending_event_ |= SEEK_EVENT_PENDING;
+ ProcessPendingEvents();
}
base::TimeDelta MediaSourcePlayer::GetCurrentTime() {
@@ -293,8 +302,12 @@ base::TimeDelta MediaSourcePlayer::GetDuration() {
}
void MediaSourcePlayer::Release() {
+ ClearDecodingData();
audio_decoder_job_.reset();
video_decoder_job_.reset();
+ active_decoding_tasks_ = 0;
+ playing_ = false;
+ pending_event_ = NO_EVENT_PENDING;
ReleaseMediaResourcesFromManager();
}
@@ -318,9 +331,9 @@ bool MediaSourcePlayer::IsPlayerReady() {
}
void MediaSourcePlayer::StartInternal() {
- if (playing_)
+ // Do nothing if the decoders are already running.
+ if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING)
return;
- playing_ = true;
if (HasAudio()) {
audio_finished_ = false;
@@ -349,41 +362,77 @@ void MediaSourcePlayer::DemuxerReady(
void MediaSourcePlayer::ReadFromDemuxerAck(
const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
+ if (params.type == DemuxerStream::AUDIO)
+ waiting_for_audio_data_ = false;
+ else
+ waiting_for_video_data_ = false;
+
+ // If there is a pending seek request, ignore the data from the chunk demuxer.
+ // The data will be requested later when OnSeekRequestAck() is called.
+ if (pending_event_ & SEEK_EVENT_PENDING)
+ return;
+
if (params.type == DemuxerStream::AUDIO) {
DCHECK_EQ(0u, audio_access_unit_index_);
received_audio_ = params;
- waiting_for_audio_data_ = false;
- DecodeMoreAudio();
+ if (!pending_event_)
+ DecodeMoreAudio();
} else {
DCHECK_EQ(0u, video_access_unit_index_);
received_video_ = params;
- waiting_for_video_data_ = false;
- DecodeMoreVideo();
+ if (!pending_event_)
+ DecodeMoreVideo();
}
}
+void MediaSourcePlayer::OnSeekRequestAck() {
+ pending_event_ &= ~SEEK_EVENT_PENDING;
+ OnSeekComplete();
+ if (playing_)
+ StartInternal();
+}
+
void MediaSourcePlayer::UpdateTimestamps(
- const base::Time& kickoff_time,
const base::TimeDelta& presentation_timestamp,
const base::Time& wallclock_time) {
- // If the job was posted after last seek, update the presentation time.
- // Otherwise, ignore it.
- if (kickoff_time > last_seek_time_) {
- last_presentation_timestamp_ = presentation_timestamp;
- OnTimeUpdated();
- if (start_wallclock_time_.is_null() && playing_) {
- start_wallclock_time_ = wallclock_time;
- start_presentation_timestamp_ = last_presentation_timestamp_;
- }
+ last_presentation_timestamp_ = presentation_timestamp;
+ OnTimeUpdated();
+ if (start_wallclock_time_.is_null() && playing_) {
+ start_wallclock_time_ = wallclock_time;
+ start_presentation_timestamp_ = last_presentation_timestamp_;
+ }
+}
+
+void MediaSourcePlayer::ProcessPendingEvents() {
+ // Wait for all the decoding jobs to finish before sending a seek request.
+ if (active_decoding_tasks_ > 0)
+ return;
+
+ DCHECK(pending_event_ != NO_EVENT_PENDING);
+ if (use_empty_surface_ && (pending_event_ & SURFACE_CHANGE_EVENT_PENDING)) {
+ video_decoder_job_.reset();
+ pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
}
+
+ ClearDecodingData();
+ manager()->OnMediaSeekRequest(player_id(),
+ last_presentation_timestamp_,
+ pending_event_ & SURFACE_CHANGE_EVENT_PENDING);
}
void MediaSourcePlayer::MediaDecoderCallback(
- bool is_audio, const base::Time& kickoff_time,
- const base::TimeDelta& presentation_timestamp,
+ bool is_audio, const base::TimeDelta& presentation_timestamp,
const base::Time& wallclock_time, bool end_of_stream) {
+ if (active_decoding_tasks_ > 0)
+ active_decoding_tasks_--;
+
+ if (pending_event_ != NO_EVENT_PENDING) {
+ ProcessPendingEvents();
+ return;
+ }
+
if (is_audio || !HasAudio())
- UpdateTimestamps(kickoff_time, presentation_timestamp, wallclock_time);
+ UpdateTimestamps(presentation_timestamp, wallclock_time);
if (end_of_stream) {
PlaybackCompleted(is_audio);
@@ -414,8 +463,9 @@ void MediaSourcePlayer::DecodeMoreAudio() {
received_audio_.access_units[audio_access_unit_index_],
start_wallclock_time_, start_presentation_timestamp_,
base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
- weak_this_.GetWeakPtr(), true, base::Time::Now()));
- ++audio_access_unit_index_;
+ weak_this_.GetWeakPtr(), true));
+ active_decoding_tasks_++;
+ audio_access_unit_index_++;
}
void MediaSourcePlayer::DecodeMoreVideo() {
@@ -433,8 +483,9 @@ void MediaSourcePlayer::DecodeMoreVideo() {
received_video_.access_units[video_access_unit_index_],
start_wallclock_time_, start_presentation_timestamp_,
base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
- weak_this_.GetWeakPtr(), false, base::Time::Now()));
- ++video_access_unit_index_;
+ weak_this_.GetWeakPtr(), false));
+ active_decoding_tasks_++;
+ video_access_unit_index_++;
}
@@ -451,6 +502,18 @@ void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
}
}
+void MediaSourcePlayer::ClearDecodingData() {
+ if (audio_decoder_job_)
+ audio_decoder_job_->Flush();
+ if (video_decoder_job_)
+ video_decoder_job_->Flush();
+ start_wallclock_time_ = base::Time();
+ received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
+ received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
+ audio_access_unit_index_ = 0;
+ video_access_unit_index_ = 0;
+}
+
bool MediaSourcePlayer::HasVideo() {
return kUnknownVideoCodec != video_codec_;
}
« no previous file with comments | « media/base/android/media_source_player.h ('k') | webkit/media/android/media_source_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698