// the time stamp of the buffered data.
const base::TimeDelta kMinWaitTimeForPlayback = base::Milliseconds(500);
-// The value above which packets will be discarded if they're too far away from
-// the seek position.
-const base::TimeDelta kMaxSeekDiff = base::Milliseconds(2000);
+// The delay time to check buffering and decide operations.
+const base::TimeDelta kOperationDecisionDelay = base::Milliseconds(500);
player_buffer_size_t GetMaxAudioBufferSize() {
return kPlayerAudioBufferSize;
expected_seek_ = false;
seek_position_ = base::TimeDelta();
pending_seek_ = false;
- pending_seek_position_ = base::TimeDelta::Max();
+ pending_seek_position_ = base::TimeDelta();
should_set_playback_rate_ = false;
ClearBufferQueue(DemuxerStream::VIDEO);
ClearBufferQueue(DemuxerStream::AUDIO);
sink_ = nullptr;
+ StopOperationForDataTimer();
+
if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE) {
LOG_ID(ERROR, player_id_)
<< "(" << static_cast<void*>(this) << ") " << __func__
if (!is_media_related_action)
is_paused_ = true;
+ // To decide operation is not needed in pause.
+ StopOperationForDataTimer();
+
LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
<< __func__ << " is_buffering : " << is_buffering_
<< " is_media_action : " << is_media_related_action;
ClearBufferQueue(DemuxerStream::VIDEO);
ClearBufferQueue(DemuxerStream::AUDIO);
- buffer_observer_->ResetBufferStatus();
seek_cb_ = std::move(seek_cb);
SeekInternal(time);
is_readytoseek_ = false;
seek_position_ = time;
pending_seek_ = false;
- pending_seek_position_ = base::TimeDelta::Max();
+ pending_seek_position_ = base::TimeDelta();
if (seek_cb_)
std::move(seek_cb_).Run();
}
if (GetPlayerState() < ESPLUSPLAYER_STATE_READY) {
LOG_ID(INFO, player_id_)
<< "player is not ready, state:" << GetString(GetPlayerState());
-
- ReportBufferingStateIfNeeded(BUFFERING_HAVE_NOTHING,
- BUFFERING_CHANGE_REASON_UNKNOWN);
-
if (flush_cb)
std::move(flush_cb).Run();
return;
UpdateBufferedDtsDifference();
expected_seek_ = true;
-
buffer_observer_->ResetBufferStatus();
std::move(flush_cb).Run();
if (!ReadFromBufferQueue(type))
return;
- PerformOperationForData();
-
// Avoid unnecessary or redundant read requests.
if (!ShouldFeed(type) || ReadRequested(type) || IsEos(type) ||
(is_prepared_ && is_paused_ && !is_seeking_)) {
return;
}
- // If there are more packets in the queue, process them...
+ // If the playing statue is expected,
+ // keep running a timer to decide play or pause with data.
+ if (!is_paused_) {
+ StartOperationForDataTimer();
+ }
+
if (!GetBufferQueue(type).empty()) {
ReadBuffer(type);
return;
<< ") player is not prepared ignore eos";
} else
status = SubmitEosPacket(type);
- } else {
- // If we're expecting a seek (i.e. we've received a Flush()), then we need
- // to discard buffers, otherwise there is a chance that the demux buffer
- // is filled and the new data required to seek is not received.
- if (expected_seek_ && is_prepared_) {
- LOG_ID(INFO, player_id_) << "Discard buffers while expected_seek_";
- GetBufferQueue(type).pop_front();
- PostReadBuffer(type);
- return true;
- }
-
- if (is_seeking_) {
- // If we're seeking, and the data received is *not* for the current seek
- // point, then discard it, or it can throw an error in the lower levels
- // (causing an OnError() callback and video to stop).
- base::TimeDelta diff = buffer->timestamp() - seek_position_;
-
- if (diff.magnitude() > kMaxSeekDiff) {
- LOG_ID(WARNING, player_id_) << "is_seeking_ buffer timestamp too far "
- << "from seek position, discarding";
- GetBufferQueue(type).pop_front();
- PostReadBuffer(type);
- return true;
- }
- }
-
+ } else
status = SubmitEsPacket(type, buffer);
- }
if (status == ESPLUSPLAYER_SUBMIT_STATUS_FULL) {
// If buffer is full, try again after a while.
<< ", is_key_frame: " << buffer->is_key_frame()
<< ", this: " << this;
- // This filled only set when PushMediaPacket
+ // This filed only set when PushMediaPacket
packet.matroska_color_info = nullptr;
esplusplayer_submit_status status =
esplusplayer_submit_packet(esplayer_, &packet);
LOG_ID(INFO, player_id_) << __func__ << " "
<< DemuxerStream::GetTypeName(type) << " : "
<< GetString(status);
-
if (expected_seek_ && is_prepared_) {
- // We need to wait for the Seek() call before we start processing buffers...
- LOG_ID(INFO, player_id_) << "Ignore the buffer updates while expected seek";
- if (GetBufferQueue(type).size()) {
- GetBufferQueue(type).pop_front();
- }
+ LOG_ID(INFO, player_id_) << "Ignore the buffer updates while seek";
return;
}
case kBufferNormal:
if (is_seeking_ && is_readytoseek_ == false) {
LOG_ID(INFO, player_id_)
- << "Ignore the buffer status before ready to seek";
+ << "Ignore the buffer status before read to seek";
} else {
is_buffering_ = true;
SetShouldFeed(type, true);
ReportBufferingStateIfNeeded(BUFFERING_HAVE_ENOUGH,
BUFFERING_CHANGE_REASON_UNKNOWN);
is_paused_by_buffering_ = false;
- if (!is_paused_) {
- Play();
- }
+ Play();
break;
case OperationForData::PAUSE:
ReportBufferingStateIfNeeded(BUFFERING_HAVE_NOTHING,
is_paused_by_buffering_ = true;
Pause(true);
break;
- default:
- break;
}
}
bool should_pause = false;
if (has_video_media_type &&
current_position >= last_frames_.get<DemuxerStream::VIDEO>().first) {
- ReportBufferingStateIfNeeded(BUFFERING_HAVE_NOTHING,
- BUFFERING_CHANGE_REASON_UNKNOWN);
should_pause = true;
}
if (has_audio_media_type &&
current_position >= last_frames_.get<DemuxerStream::AUDIO>().first) {
- ReportBufferingStateIfNeeded(BUFFERING_HAVE_NOTHING,
- BUFFERING_CHANGE_REASON_UNKNOWN);
should_pause = true;
}
return OperationForData::NONE;
}
+void MediaPlayerESPlusPlayer::StartOperationForDataTimer() {
+ if (!operation_for_data_timer_.IsRunning()) {
+ operation_for_data_timer_.Start(
+ FROM_HERE, kOperationDecisionDelay, this,
+ &MediaPlayerESPlusPlayer::PerformOperationForData);
+ }
+}
+
+void MediaPlayerESPlusPlayer::StopOperationForDataTimer() {
+ if (operation_for_data_timer_.IsRunning()) {
+ operation_for_data_timer_.Stop();
+ }
+}
+
void MediaPlayerESPlusPlayer::OnReadyToPrepare(
const esplusplayer_stream_type stream_type) {
if (!task_runner_->BelongsToCurrentThread()) {