#include "base/functional/callback.h"
#include "base/location.h"
#include "base/logging.h"
-#include "media/base/buffering_state.h"
#include "media/base/decoder_buffer.h"
#include "third_party/libyuv/include/libyuv/convert.h"
#include "tizen_src/chromium_impl/media/filters/esplusplayer_buffer_observer_impl.h"
void MediaPlayerESPlusPlayer::Initialize(VideoRendererSink* sink) {
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
+
+ if (!esplayer_) {
+ LOG(INFO) << "(" << static_cast<void*>(this) << ") "
+ << "esplayer is null.";
+ return;
+ }
+
esplusplayer_set_ready_to_prepare_cb(esplayer_, &ReadyToPrepareCallback,
this);
esplusplayer_set_prepare_async_done_cb(esplayer_, &PrepareCompleteCallback,
void MediaPlayerESPlusPlayer::Prepare() {
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
- if (is_prepared_ || is_preparing_)
+ if (!esplayer_ || is_prepared_ || is_preparing_)
return;
if (GetPlayerState() != ESPLUSPLAYER_STATE_IDLE) {
return;
}
- int error = esplusplayer_prepare_async(esplayer_);
+ int error = esplusplayer_set_display_visible(esplayer_, true);
+ if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+ LOG(ERROR)
+ << "esplusplayer_set_display_visible failed! error #"
+ << esplusplayer_get_error_string(
+ static_cast<esplusplayer_error_type>(error));
+ }
+
+ error = esplusplayer_prepare_async(esplayer_);
if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
LOG(ERROR) << "player prepare failed! error #"
<< esplusplayer_get_error_string(
SetShouldFeed(DemuxerStream::AUDIO, false);
SetIsValid(DemuxerStream::AUDIO, false);
SetReadRequested(DemuxerStream::AUDIO, false);
+ SetBufferingState(DemuxerStream::AUDIO, BUFFERING_HAVE_NOTHING);
SetIsEos(DemuxerStream::VIDEO, false);
SetShouldFeed(DemuxerStream::VIDEO, false);
SetIsValid(DemuxerStream::VIDEO, false);
SetReadRequested(DemuxerStream::VIDEO, false);
+ SetBufferingState(DemuxerStream::VIDEO, BUFFERING_HAVE_NOTHING);
esplusplayer_set_ready_to_prepare_cb(esplayer_, nullptr, this);
esplusplayer_set_prepare_async_done_cb(esplayer_, nullptr, this);
// TODO: handle error!
return false;
}
+
+ // To submit packets when playback starts.
+ if (IsValid(DemuxerStream::VIDEO))
+ ReadBuffer(DemuxerStream::VIDEO);
+ if (IsValid(DemuxerStream::AUDIO))
+ ReadBuffer(DemuxerStream::AUDIO);
+
return true;
}
void MediaPlayerESPlusPlayer::SetRate(double rate) {
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " : "
<< rate;
+
+ // the playback rate from 0.0 to 2.0 in esplusplayer.
+ if (rate > 2.0) {
+ LOG(WARNING) << __func__ << " The playback rate value in esplusplayer "
+ << " cannot exceed 2.0.";
+ rate = 2.0;
+ }
+
if (playback_rate_ == rate)
return;
return;
}
- bool should_mute = rate >= 2.0;
- int error =
- esplusplayer_set_playback_rate(esplayer_, playback_rate_, should_mute);
+ int error = esplusplayer_set_playback_rate(esplayer_, playback_rate_, false);
if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
LOG(ERROR) << "player set playback rate failed! error #"
<< esplusplayer_get_error_string(
void MediaPlayerESPlusPlayer::Seek(base::TimeDelta time,
base::OnceClosure seek_cb) {
+ LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " :"
+ << time;
+
+ expected_seek_ = false;
// Ignore seek in release state. Will catch-up later.
if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE) {
LOG(INFO) << __func__ << " Ignore seek in release state.";
return;
}
- // Ignore seek to 0 during initialization.
- if (GetPlayerState() < ESPLUSPLAYER_STATE_READY && time.InSecondsF() == 00) {
- LOG(INFO) << __func__ << " Ignore seek to 0 during initialization.";
- if (seek_cb)
- std::move(seek_cb).Run();
- return;
- }
-
- LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " :"
- << time;
-
if (GetPlayerState() < ESPLUSPLAYER_STATE_READY || !is_prepared_) {
+ // Prevent to set the same pending seek position and
+ // stop pushing again from 0sec when media starts 0.
+ if (time == pending_seek_position_) {
+ if (seek_cb)
+ std::move(seek_cb).Run();
+ return;
+ }
+
LOG(INFO) << "Add to pending seek ("
<< ") state: " << GetString(GetPlayerState())
<< " is_prepared : " << is_prepared_;
std::move(seek_cb).Run();
return;
}
+
+ if (is_seeking_ && seek_position_ == time) {
+ LOG(INFO) << __func__ << " Seeking the same position.";
+ if (seek_cb)
+ std::move(seek_cb).Run();
+ return;
+ }
+
seek_cb_ = std::move(seek_cb);
SeekInternal(time);
}
void MediaPlayerESPlusPlayer::Flush(base::OnceClosure flush_cb) {
- // Ignore Flush in release state.
- if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE) {
+ // Ignore Flush before prepared state.
+ if (GetPlayerState() < ESPLUSPLAYER_STATE_READY) {
+ LOG(INFO) << "player is not ready, state:" << GetString(GetPlayerState());
if (flush_cb)
std::move(flush_cb).Run();
return;
SetShouldFeed(DemuxerStream::VIDEO, false);
GetBufferQueue(DemuxerStream::VIDEO).clear();
GetBufferQueue(DemuxerStream::AUDIO).clear();
+ SetBufferingState(DemuxerStream::AUDIO, BUFFERING_HAVE_NOTHING);
+ SetBufferingState(DemuxerStream::VIDEO, BUFFERING_HAVE_NOTHING);
buffer_observer_->ResetBufferStatus();
std::move(flush_cb).Run();
if (GetPlayerState() < ESPLUSPLAYER_STATE_PLAYING)
return current_position_;
+ // esplusplayer_get_playing_time is sync api, need called after prepared.
+ // Otherwise will block browser process.
+ if (!is_prepared_)
+ return base::TimeDelta();
+
uint64_t time = 0; // In milliseconds.
int error = esplusplayer_get_playing_time(esplayer_, &time);
if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
}
player_buffer_size_t MediaPlayerESPlusPlayer::GetMaxVideoBufferSize(
- media::VideoDecoderConfig video_config) {
+ const media::VideoDecoderConfig& video_config) {
return kPlayerTotalBufferSize - kPlayerAudioBufferSize;
}
int MediaPlayerESPlusPlayer::SetVideoStreamInfo(
- media::VideoDecoderConfig& video_config,
+ const media::VideoDecoderConfig& video_config,
esplusplayer_video_stream_info& video_stream_info) {
video_stream_info.width = video_config.coded_size().width();
video_stream_info.height = video_config.coded_size().height();
return;
// Avoid unnecessary or redundant read requests.
- if (!ShouldFeed(type) || ReadRequested(type) || IsEos(type))
+ if (!ShouldFeed(type) || ReadRequested(type) || IsEos(type) ||
+ (is_prepared_ && is_paused_ && !is_seeking_)) {
return;
+ }
SetReadRequested(type, true);
uint32_t buffer_read_count = 1;
BufferStatus status) {
DVLOG(INFO) << __func__ << " " << DemuxerStream::GetTypeName(type) << " : "
<< GetString(status);
- const auto RequestStateChange = [this](esplusplayer_state state) {
- LOG(INFO) << __func__ << " req. change state : " << GetString(state);
- switch (state) {
- case ESPLUSPLAYER_STATE_PLAYING:
- Play();
- break;
- case ESPLUSPLAYER_STATE_PAUSED:
- Pause(true);
- break;
- default:
- NOTREACHED();
- }
- };
- if (expected_seek_) {
+ if (expected_seek_ && is_prepared_) {
LOG(INFO) << "Ignore the buffer updates while seek";
return;
}
- SetBufferStatus(type, status);
switch (status) {
case kBufferUnderrun:
- // RequestStateChange(ESPLUSPLAYER_STATE_PAUSED);
- [[fallthrough]];
case kBufferMinThreshold:
case kBufferNormal:
is_buffering_ = true;
case kBufferAhead:
is_buffering_ = false;
SetShouldFeed(type, false);
- // if (!is_paused_)
- // RequestStateChange(ESPLUSPLAYER_STATE_PLAYING);
break;
case kBufferNone:
NOTREACHED();
}
- // TODO: Check if controller can control underflow. Currently buffering
- // related state changes are commented for the same (in Play and
- // RequestStateChange).
if (status != kBufferNone) {
- GetMediaPlayerClient()->OnBufferingStateChange(
- BUFFERING_HAVE_ENOUGH, BUFFERING_CHANGE_REASON_UNKNOWN);
+ if (GetBufferingState(type) != BUFFERING_HAVE_ENOUGH) {
+ SetBufferingState(type, BUFFERING_HAVE_ENOUGH);
+ GetMediaPlayerClient()->OnBufferingStateChange(
+ BUFFERING_HAVE_ENOUGH, BUFFERING_CHANGE_REASON_UNKNOWN);
+ }
+ } else {
+ SetBufferingState(type, BUFFERING_HAVE_NOTHING);
}
}
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
GetMediaPlayerClient()->OnEnded();
- Release();
}
void MediaPlayerESPlusPlayer::OnFrameReady(
<< DemuxerStream::GetTypeName(GetDemuxerStreamType(stream_type))
<< " : " << seek_time;
+ if (!esplayer_) {
+ LOG(INFO) << "player is destroyed:" << (void*)this;
+ return;
+ }
+
SetShouldFeed(GetDemuxerStreamType(stream_type), true);
SetIsEos(GetDemuxerStreamType(stream_type), false);
ReadBuffer(GetDemuxerStreamType(stream_type));
GetElementryStream(type).read_requested_ = value;
}
-BufferStatus MediaPlayerESPlusPlayer::GetBufferStatus(
+BufferingState MediaPlayerESPlusPlayer::GetBufferingState(
DemuxerStream::Type type) {
- return GetElementryStream(type).buffer_status_;
+ return GetElementryStream(type).buffering_state_;
}
-void MediaPlayerESPlusPlayer::SetBufferStatus(DemuxerStream::Type type,
- BufferStatus status) {
- GetElementryStream(type).buffer_status_ = status;
+void MediaPlayerESPlusPlayer::SetBufferingState(DemuxerStream::Type type,
+ BufferingState state) {
+ GetElementryStream(type).buffering_state_ = state;
}
DemuxerStream* MediaPlayerESPlusPlayer::GetDemuxerStream(
LOG(INFO) << __func__ << " viewport_rect: " << viewport_rect.ToString()
<< " rect : " << rect.ToString();
+
+ if (!esplayer_ || !video_plane_controller_) {
+ LOG(INFO)
+ << "(" << static_cast<void*>(this) << ") "
+ << "player is destroyed, or video plane controller not exist.";
+ return;
+ }
+
video_plane_controller_->SetMediaGeometry(viewport_rect, rect);
}
void MediaPlayerESPlusPlayer::PrepareVideoHole() {
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
- if (is_prepared_ || is_preparing_)
+ if (!esplayer_ || is_prepared_ || is_preparing_)
return;
if (GetPlayerState() != ESPLUSPLAYER_STATE_IDLE) {
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
+#include "media/base/buffering_state.h"
#include "media/base/demuxer_stream.h"
#include "media/base/video_renderer_sink.h"
#include "tizen_src/chromium_impl/base/tizen/static_map.h"
// Callback handler
void OnReadyToPrepare(const esplusplayer_stream_type stream_type);
virtual void OnPrepareComplete(bool result);
- void OnEos();
+ virtual void OnEos();
void OnFrameReady(const esplusplayer_decoded_video_packet* packet);
void OnFlushComplete();
void OnReadyToSeek(const esplusplayer_stream_type stream_type,
protected:
// Product sepecific implementation.
virtual int SetVideoStreamInfo(
- media::VideoDecoderConfig& video_config,
+ const media::VideoDecoderConfig& video_config,
esplusplayer_video_stream_info& video_stream_info);
virtual void SetAudioStreamInfo(
const media::AudioDecoderConfig& audio_config,
scoped_refptr<DecoderBuffer> buffer);
virtual void PostPrepareComplete();
virtual player_buffer_size_t GetMaxVideoBufferSize(
- media::VideoDecoderConfig video_config);
+ const media::VideoDecoderConfig& video_config);
virtual void InitializeStreamConfig(DemuxerStream::Type type);
esplusplayer_state GetPlayerState();
bool IsValid(DemuxerStream::Type type) const;
bool is_eos_ = false;
bool should_feed_ = false;
bool read_requested_ = false;
- BufferStatus buffer_status_ = kBufferNone; // Not used!
+ BufferingState buffering_state_ = BUFFERING_HAVE_NOTHING;
DemuxerStream* input_stream_ = nullptr;
base::circular_deque<scoped_refptr<DecoderBuffer>> pending_buffers_;
};
ElementryStream& GetElementryStream(DemuxerStream::Type type);
const ElementryStream& GetElementryStream(DemuxerStream::Type type) const;
void SetReadRequested(DemuxerStream::Type type, bool value);
- BufferStatus GetBufferStatus(DemuxerStream::Type type);
- void SetBufferStatus(DemuxerStream::Type type, BufferStatus status);
+ BufferingState GetBufferingState(DemuxerStream::Type type);
+ void SetBufferingState(DemuxerStream::Type type, BufferingState state);
DemuxerStream* GetDemuxerStream(DemuxerStream::Type type) const;
void SetDemuxerStream(DemuxerStream::Type type, DemuxerStream* stream);
Queue& GetBufferQueue(DemuxerStream::Type type);