1 // Copyright 2022 Samsung Electronics Inc. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h"
7 #include <esplusplayer_internal.h>
8 #include <tbm_surface.h>
10 #include "base/functional/bind.h"
11 #include "base/functional/callback.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "media/base/decoder_buffer.h"
15 #include "third_party/libyuv/include/libyuv/convert.h"
16 #include "tizen_src/chromium_impl/media/filters/esplusplayer_buffer_observer_impl.h"
17 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
19 #if defined(TIZEN_VIDEO_HOLE)
20 #include <Ecore_Wl2.h>
21 #include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller_esplusplayer.h"
26 // The delay time before retrying ReadBuffer.
27 // Wait until there is space in the buffer.
28 const base::TimeDelta kBufferQueueReadDelay = base::Milliseconds(100);
30 // The difference between the played timestamp and
31 // the time stamp of the buffered data.
32 const base::TimeDelta kMinWaitTimeForPlayback = base::Milliseconds(500);
34 // The delay time to check buffering and decide operations.
35 const base::TimeDelta kOperationDecisionDelay = base::Milliseconds(500);
37 player_buffer_size_t GetMaxAudioBufferSize() {
38 return kPlayerAudioBufferSize;
41 void ReadyToPrepareCallback(const esplusplayer_stream_type stream_type,
43 MediaPlayerESPlusPlayer* player =
44 static_cast<MediaPlayerESPlusPlayer*>(user_data);
48 player->OnReadyToPrepare(stream_type);
51 void PrepareCompleteCallback(bool result, void* user_data) {
52 MediaPlayerESPlusPlayer* player =
53 static_cast<MediaPlayerESPlusPlayer*>(user_data);
57 player->OnPrepareComplete(result);
60 void EosCallback(void* user_data) {
61 MediaPlayerESPlusPlayer* player =
62 static_cast<MediaPlayerESPlusPlayer*>(user_data);
69 void FrameReadyCallback(const esplusplayer_decoded_video_packet* packet,
71 MediaPlayerESPlusPlayer* player =
72 static_cast<MediaPlayerESPlusPlayer*>(user_data);
76 player->OnFrameReady(packet);
79 void FlushCompleteCallback(void* user_data) {
80 MediaPlayerESPlusPlayer* player =
81 static_cast<MediaPlayerESPlusPlayer*>(user_data);
85 player->OnFlushComplete();
88 void ReadyToSeekCallback(const esplusplayer_stream_type stream_type,
89 const uint64_t seek_time,
91 MediaPlayerESPlusPlayer* player =
92 static_cast<MediaPlayerESPlusPlayer*>(user_data);
96 player->OnReadyToSeek(stream_type, seek_time);
99 void SeekCompleteCallback(void* user_data) {
100 MediaPlayerESPlusPlayer* player =
101 static_cast<MediaPlayerESPlusPlayer*>(user_data);
105 player->OnSeekComplete();
108 void ResourceConflictCallback(void* user_data) {
109 MediaPlayerESPlusPlayer* player =
110 static_cast<MediaPlayerESPlusPlayer*>(user_data);
114 player->OnResourceConflict();
117 void ErrorCallback(const esplusplayer_error_type error_type, void* user_data) {
118 MediaPlayerESPlusPlayer* player =
119 static_cast<MediaPlayerESPlusPlayer*>(user_data);
123 player->OnError(error_type);
126 MediaPlayerESPlusPlayer::MediaPlayerESPlusPlayer() {
127 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
130 MediaPlayerESPlusPlayer::~MediaPlayerESPlusPlayer() {
131 #if BUILDFLAG(IS_TIZEN_TV)
133 LOG_ID(INFO, player_id_) << "player is already destroyed:" << (void*)this;
138 LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
140 weak_factory_.InvalidateWeakPtrs();
142 // Player should be released before destroyed.
145 int error = esplusplayer_destroy(esplayer_);
146 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE)
147 LOG(ERROR) << "esplusplayer_destroy failed, error #"
148 << esplusplayer_get_error_string(
149 static_cast<esplusplayer_error_type>(error));
153 #if BUILDFLAG(IS_TIZEN_TV)
154 void MediaPlayerESPlusPlayer::DestroyPlayerSync(base::OnceClosure destroy_cb) {
156 LOG_ID(INFO, player_id_) << "player is already destroyed:" << (void*)this;
157 std::move(destroy_cb).Run();
161 LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
163 weak_factory_.InvalidateWeakPtrs();
167 int error = esplusplayer_destroy(esplayer_);
168 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE)
169 LOG_ID(ERROR, player_id_)
170 << "esplusplayer_destroy failed, error #"
171 << esplusplayer_get_error_string(
172 static_cast<esplusplayer_error_type>(error));
175 std::move(destroy_cb).Run();
179 bool MediaPlayerESPlusPlayer::CreatePlayer(int player_id) {
180 player_id_ = player_id;
185 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
186 esplayer_ = esplusplayer_create();
188 LOG(ERROR) << "Cannot create esplus player!";
192 last_frames_.get<DemuxerStream::AUDIO>().first = media::kNoTimestamp;
193 last_frames_.get<DemuxerStream::AUDIO>().second = media::kNoTimestamp;
194 last_frames_.get<DemuxerStream::VIDEO>().first = media::kNoTimestamp;
195 last_frames_.get<DemuxerStream::VIDEO>().second = media::kNoTimestamp;
197 buffer_observer_.reset(new ESPlusPlayerBufferObserverImpl(esplayer_));
199 #if defined(TIZEN_VIDEO_HOLE)
200 LOG(INFO) << __func__ << " is_video_hole_: " << is_video_hole_;
201 if (is_video_hole_) {
202 video_plane_controller_.reset(
203 new VideoPlaneControllerESPlusPlayer(esplayer_));
210 void MediaPlayerESPlusPlayer::Initialize(VideoRendererSink* sink) {
211 LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
215 LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
216 << "esplayer is null.";
220 esplusplayer_set_ready_to_prepare_cb(esplayer_, &ReadyToPrepareCallback,
222 esplusplayer_set_prepare_async_done_cb(esplayer_, &PrepareCompleteCallback,
224 esplusplayer_set_eos_cb(esplayer_, &EosCallback, this);
225 esplusplayer_set_media_packet_video_decoded_cb(esplayer_, &FrameReadyCallback,
227 esplusplayer_set_flush_done_cb(esplayer_, &FlushCompleteCallback, this);
228 esplusplayer_set_ready_to_seek_cb(esplayer_, &ReadyToSeekCallback, this);
229 esplusplayer_set_seek_done_cb(esplayer_, &SeekCompleteCallback, this);
230 esplusplayer_set_resource_conflicted_cb(esplayer_, &ResourceConflictCallback,
232 esplusplayer_set_error_cb(esplayer_, &ErrorCallback, this);
233 buffer_observer_->SetBufferingCallback(
234 base::BindRepeating(&MediaPlayerESPlusPlayer::OnBufferingStatusChanged,
235 weak_factory_.GetWeakPtr()));
237 int error = esplusplayer_open(esplayer_);
238 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
239 LOG(ERROR) << "esplusplayer_open failed. error #"
240 << esplusplayer_get_error_string(
241 static_cast<esplusplayer_error_type>(error));
245 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
246 << " state:" << GetString(GetPlayerState());
248 if (!SetBufferType(VideoDecoderConfig{}))
254 bool MediaPlayerESPlusPlayer::IsInitialized() {
255 return (GetPlayerState() >= ESPLUSPLAYER_STATE_IDLE);
258 void MediaPlayerESPlusPlayer::SetTaskRunner(
259 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
260 task_runner_ = task_runner.get();
263 void MediaPlayerESPlusPlayer::SetStreamInfo(DemuxerStream::Type type,
264 DemuxerStream* stream) {
266 LOG(ERROR) << "Invalid player handle. Send error to client.";
267 GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
271 SetDemuxerStream(type, stream);
272 InitializeStreamConfig(type);
275 void MediaPlayerESPlusPlayer::Prepare() {
276 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
277 if (!esplayer_ || is_prepared_ || is_preparing_) {
278 LOG_ID(ERROR, player_id_)
279 << "(" << static_cast<void*>(this) << ") " << __func__
280 << ", esplayer_: " << static_cast<void*>(esplayer_)
281 << ", is_prepared_: " << is_prepared_
282 << ", is_preparing_: " << is_preparing_;
286 if (GetPlayerState() != ESPLUSPLAYER_STATE_IDLE) {
287 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
288 << " Prepare called on invalid state : "
289 << GetString(GetPlayerState());
293 int error = esplusplayer_set_display_visible(esplayer_, true);
294 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
296 << "esplusplayer_set_display_visible failed! error #"
297 << esplusplayer_get_error_string(
298 static_cast<esplusplayer_error_type>(error));
301 error = esplusplayer_prepare_async(esplayer_);
302 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
303 LOG(ERROR) << "player prepare failed! error #"
304 << esplusplayer_get_error_string(
305 static_cast<esplusplayer_error_type>(error));
307 GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
310 is_preparing_ = true;
313 bool MediaPlayerESPlusPlayer::IsPrepared() {
314 return (GetPlayerState() >= ESPLUSPLAYER_STATE_READY);
317 bool MediaPlayerESPlusPlayer::CanPrepare() {
318 return esplayer_ && !IsPrepared() && !is_preparing_;
321 void MediaPlayerESPlusPlayer::Release() {
325 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
326 if (GetPlayerState() != ESPLUSPLAYER_STATE_NONE)
327 esplusplayer_stop(esplayer_);
329 SetIsEos(DemuxerStream::AUDIO, false);
330 SetShouldFeed(DemuxerStream::AUDIO, false);
331 SetIsValid(DemuxerStream::AUDIO, false);
332 SetReadRequested(DemuxerStream::AUDIO, false);
334 SetIsEos(DemuxerStream::VIDEO, false);
335 SetShouldFeed(DemuxerStream::VIDEO, false);
336 SetIsValid(DemuxerStream::VIDEO, false);
337 SetReadRequested(DemuxerStream::VIDEO, false);
339 esplusplayer_set_ready_to_prepare_cb(esplayer_, nullptr, this);
340 esplusplayer_set_prepare_async_done_cb(esplayer_, nullptr, this);
341 esplusplayer_set_eos_cb(esplayer_, nullptr, this);
342 esplusplayer_set_media_packet_video_decoded_cb(esplayer_, nullptr, this);
343 esplusplayer_set_flush_done_cb(esplayer_, nullptr, this);
344 esplusplayer_set_ready_to_seek_cb(esplayer_, nullptr, this);
345 esplusplayer_set_seek_done_cb(esplayer_, nullptr, this);
346 esplusplayer_set_resource_conflicted_cb(esplayer_, nullptr, this);
347 esplusplayer_set_error_cb(esplayer_, nullptr, this);
349 buffer_observer_->ResetBufferStatus();
350 buffer_observer_->ResetBufferStatusCallbacks();
352 reported_buffering_state_ = BUFFERING_HAVE_NOTHING;
355 playback_rate_ = 0.0;
356 is_prepared_ = false;
357 is_preparing_ = false;
359 is_buffering_ = false;
360 current_position_ = base::TimeDelta();
362 expected_seek_ = false;
363 seek_position_ = base::TimeDelta();
364 pending_seek_ = false;
365 pending_seek_position_ = base::TimeDelta();
366 should_set_playback_rate_ = false;
368 GetBufferQueue(DemuxerStream::VIDEO).clear();
369 GetBufferQueue(DemuxerStream::AUDIO).clear();
372 StopOperationForDataTimer();
374 if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE) {
375 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
376 << " Release called on invalid state : "
377 << GetString(GetPlayerState());
381 esplusplayer_close(esplayer_);
384 bool MediaPlayerESPlusPlayer::Play() {
385 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
386 int error = ESPLUSPLAYER_ERROR_TYPE_NONE;
387 esplusplayer_state state = GetPlayerState();
390 if ((state < ESPLUSPLAYER_STATE_READY) || !is_prepared_ || is_seeking_) {
391 LOG(INFO) << "state : " << GetString(state)
392 << " is_prepared : " << is_prepared_
393 << " is_seeking : " << is_seeking_
394 << " is_buffering : " << is_buffering_;
399 LOG(INFO) << "state : " << GetString(state) << " is_paused : " << is_paused_
400 << " is_buffering : " << is_buffering_;
405 if (should_set_playback_rate_)
406 SetRate(playback_rate_);
408 if (state == ESPLUSPLAYER_STATE_READY)
409 error = esplusplayer_start(esplayer_);
410 else if ((state == ESPLUSPLAYER_STATE_PAUSED) ||
411 (state == ESPLUSPLAYER_STATE_PLAYING))
412 error = esplusplayer_resume(esplayer_);
414 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
415 LOG(ERROR) << "player play failed! state #" << GetString(state)
417 << esplusplayer_get_error_string(
418 static_cast<esplusplayer_error_type>(error));
419 // TODO: handle error!
423 // To submit packets when playback starts.
424 if (IsValid(DemuxerStream::VIDEO))
425 ReadBuffer(DemuxerStream::VIDEO);
426 if (IsValid(DemuxerStream::AUDIO))
427 ReadBuffer(DemuxerStream::AUDIO);
432 void MediaPlayerESPlusPlayer::Pause(bool is_media_related_action) {
434 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
435 << " already paused";
439 if (!is_media_related_action)
442 // To decide operation is not needed in pause.
443 StopOperationForDataTimer();
445 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
446 << " is_buffering : " << is_buffering_
447 << " is_media_action : " << is_media_related_action;
448 esplusplayer_state state = GetPlayerState();
449 if (state != ESPLUSPLAYER_STATE_PLAYING) {
450 LOG(WARNING) << "Cannot pause in " << GetString(state) << " state";
454 int error = esplusplayer_pause(esplayer_);
455 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
456 LOG(ERROR) << "player pause failed! error #"
457 << esplusplayer_get_error_string(
458 static_cast<esplusplayer_error_type>(error));
459 // TODO: handle error!
464 void MediaPlayerESPlusPlayer::SetRate(double rate) {
465 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " : "
468 // the playback rate from 0.0 to 2.0 in esplusplayer.
470 LOG(WARNING) << __func__ << " The playback rate value in esplusplayer "
471 << " cannot exceed 2.0.";
475 if (playback_rate_ == rate)
478 playback_rate_ = rate;
479 if (GetPlayerState() < ESPLUSPLAYER_STATE_READY) {
480 should_set_playback_rate_ = true;
484 int error = esplusplayer_set_playback_rate(esplayer_, playback_rate_, false);
485 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
486 LOG(ERROR) << "player set playback rate failed! error #"
487 << esplusplayer_get_error_string(
488 static_cast<esplusplayer_error_type>(error));
491 should_set_playback_rate_ = false;
494 void MediaPlayerESPlusPlayer::Seek(base::TimeDelta time,
495 base::OnceClosure seek_cb) {
496 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " :"
499 expected_seek_ = false;
500 // Ignore seek in release state. Will catch-up later.
501 if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE) {
502 LOG(INFO) << __func__ << " Ignore seek in release state.";
504 std::move(seek_cb).Run();
508 if ((GetPlayerState() < ESPLUSPLAYER_STATE_READY) || !is_prepared_) {
509 // Prevent to set the same pending seek position and
510 // stop pushing again from 0sec when media starts 0.
511 if (time == pending_seek_position_) {
513 std::move(seek_cb).Run();
517 LOG(INFO) << "Add to pending seek ("
518 << ") state: " << GetString(GetPlayerState())
519 << " is_prepared : " << is_prepared_;
520 pending_seek_ = true;
521 pending_seek_position_ = time;
524 std::move(seek_cb).Run();
528 if (is_seeking_ && seek_position_ == time) {
529 LOG(INFO) << __func__ << " Seeking the same position.";
531 std::move(seek_cb).Run();
535 seek_cb_ = std::move(seek_cb);
540 void MediaPlayerESPlusPlayer::SeekInternal(base::TimeDelta time) {
541 int error = esplusplayer_seek(esplayer_, time.InMilliseconds());
542 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
543 LOG(ERROR) << "Seek failed. Current time : " << time.InSecondsF()
545 << esplusplayer_get_error_string(
546 static_cast<esplusplayer_error_type>(error));
551 seek_position_ = time;
552 pending_seek_ = false;
553 pending_seek_position_ = base::TimeDelta();
555 std::move(seek_cb_).Run();
558 void MediaPlayerESPlusPlayer::Flush(base::OnceClosure flush_cb) {
559 // Ignore Flush before prepared state.
560 if (GetPlayerState() < ESPLUSPLAYER_STATE_READY) {
561 LOG(INFO) << "player is not ready, state:" << GetString(GetPlayerState());
563 std::move(flush_cb).Run();
566 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
568 ReportBufferingStateIfNeeded(BUFFERING_HAVE_NOTHING,
569 BUFFERING_CHANGE_REASON_UNKNOWN);
571 last_frames_.get<DemuxerStream::AUDIO>().first = media::kNoTimestamp;
572 last_frames_.get<DemuxerStream::VIDEO>().first = media::kNoTimestamp;
574 UpdateBufferedDtsDifference();
576 expected_seek_ = true;
577 SetShouldFeed(DemuxerStream::AUDIO, false);
578 SetShouldFeed(DemuxerStream::VIDEO, false);
579 GetBufferQueue(DemuxerStream::VIDEO).clear();
580 GetBufferQueue(DemuxerStream::AUDIO).clear();
581 buffer_observer_->ResetBufferStatus();
583 std::move(flush_cb).Run();
586 void MediaPlayerESPlusPlayer::SetVolume(double volume) {
587 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " :"
590 if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE)
593 int error = esplusplayer_set_volume(esplayer_, 100 * volume_);
594 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE)
595 LOG(ERROR) << "esplusplayer_set_volume failed, error #"
596 << esplusplayer_get_error_string(
597 static_cast<esplusplayer_error_type>(error));
600 base::TimeDelta MediaPlayerESPlusPlayer::GetCurrentTime() {
602 return pending_seek_position_;
605 return seek_position_;
607 // Seek can be called before PLAY / PAUSE. Return last known time.
608 if (GetPlayerState() < ESPLUSPLAYER_STATE_PLAYING)
609 return current_position_;
611 // esplusplayer_get_playing_time is sync api, need called after prepared.
612 // Otherwise will block browser process.
614 return base::TimeDelta();
616 uint64_t time = 0; // In milliseconds.
617 int error = esplusplayer_get_playing_time(esplayer_, &time);
618 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
619 LOG(ERROR) << "esplusplayer_get_playing_time failed. error #"
620 << esplusplayer_get_error_string(
621 static_cast<esplusplayer_error_type>(error));
622 return base::TimeDelta();
625 current_position_ = base::Milliseconds(time);
626 return current_position_;
629 #if defined(TIZEN_TBM_SUPPORT)
630 void MediaPlayerESPlusPlayer::DestroyMediaPacket(void* media_packet) {
631 if (!task_runner_->BelongsToCurrentThread()) {
632 task_runner_->PostTask(
633 FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::DestroyMediaPacket,
634 weak_factory_.GetWeakPtr(), media_packet));
638 esplusplayer_decoded_buffer_destroy(
639 esplayer_, static_cast<esplusplayer_decoded_video_packet*>(media_packet));
643 esplusplayer_state MediaPlayerESPlusPlayer::GetPlayerState() {
644 return (esplayer_ ? esplusplayer_get_state(esplayer_)
645 : ESPLUSPLAYER_STATE_NONE);
648 player_buffer_size_t MediaPlayerESPlusPlayer::GetMaxVideoBufferSize(
649 const media::VideoDecoderConfig& video_config) {
650 return kPlayerTotalBufferSize - kPlayerAudioBufferSize;
653 int MediaPlayerESPlusPlayer::SetVideoStreamInfo(
654 const media::VideoDecoderConfig& video_config,
655 esplusplayer_video_stream_info& video_stream_info) {
656 if (!SetBufferType(video_config)) {
657 LOG_ID(ERROR, player_id_) << "SetBufferType failed.";
658 return ESPLUSPLAYER_ERROR_TYPE_UNKNOWN;
661 video_stream_info.mime_type =
662 ConvertToESPlusVideoMimeType(video_config.codec());
664 // TODO: Fetch frame rate from demuxer?
665 video_stream_info.framerate_num = kVideoFramerateNum;
666 video_stream_info.framerate_den = kVideoFramerateDen;
667 video_stream_info.codec_data_length = video_config.extra_data().size();
668 if (video_stream_info.codec_data_length > 0) {
669 video_stream_info.codec_data =
670 (char*)(const_cast<unsigned char*>(video_config.extra_data().data()));
672 video_stream_info.codec_data = nullptr;
674 auto ri_max_resolution =
675 GetMaxResolution(video_stream_info.mime_type, is_video_hole_);
676 // |video_resolution| is the current video size, |video_max_resolution|
677 // is the potential max video size, it to say that the video source
678 // size may be changed to that size in playback state dynamically.
679 // for every video playback scenarios, the caller should set it to a
680 // suitable value to |video_max_resolution| to avoid decoder resource
681 // waste or resource conflicts.
682 auto video_max_resolution = video_config.max_coded_size();
683 auto video_resolution = video_config.coded_size();
684 LOG_ID(INFO, player_id_) << "Available max resolution from resource manager:"
685 << ri_max_resolution.ToString()
686 << " video max resolution:"
687 << video_max_resolution.ToString()
688 << " video resolution:"
689 << video_resolution.ToString();
691 // Correct the video max resolution if it is smaller than video resolution.
692 video_max_resolution.SetToMax(video_resolution);
694 // Constrain the video resolution within the ri max resolution.
695 video_resolution.SetToMin(ri_max_resolution);
697 // Constrain the video max resolution within the ri max resolution.
698 video_max_resolution.SetToMin(ri_max_resolution);
700 video_stream_info.max_width = video_max_resolution.width();
701 video_stream_info.max_height = video_max_resolution.height();
702 video_stream_info.width = video_resolution.width();
703 video_stream_info.height = video_resolution.height();
705 return ESPLUSPLAYER_ERROR_TYPE_NONE;
708 void MediaPlayerESPlusPlayer::SetAudioStreamInfo(
709 const media::AudioDecoderConfig& audio_config,
710 esplusplayer_audio_stream_info* audio_stream_info) {
711 audio_stream_info->mime_type =
712 ConvertToESPlusAudioMimeType(audio_config.codec());
713 audio_stream_info->bitrate =
714 audio_config.bytes_per_channel() * audio_config.samples_per_second() * 8;
715 audio_stream_info->channels =
716 media::ChannelLayoutToChannelCount(audio_config.channel_layout());
717 audio_stream_info->sample_rate = audio_config.samples_per_second();
718 audio_stream_info->codec_data_length = audio_config.extra_data().size();
720 if (audio_stream_info->codec_data_length > 0) {
721 audio_stream_info->codec_data =
722 (char*)(const_cast<unsigned char*>(audio_config.extra_data().data()));
724 audio_stream_info->codec_data = nullptr;
728 void MediaPlayerESPlusPlayer::InitializeStreamConfig(DemuxerStream::Type type) {
729 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
730 DemuxerStream* stream = GetDemuxerStream(type);
733 int error = ESPLUSPLAYER_ERROR_TYPE_NONE;
734 if (type == DemuxerStream::AUDIO) {
735 media::AudioDecoderConfig audio_config = stream->audio_decoder_config();
736 if (!audio_config.IsValidConfig()) {
737 LOG(INFO) << "Invalid audio config";
741 LOG(INFO) << "Audio config : " << audio_config.AsHumanReadableString();
742 esplusplayer_audio_stream_info audio_stream_info;
743 memset(&audio_stream_info, 0, sizeof(esplusplayer_audio_stream_info));
745 SetAudioStreamInfo(audio_config, &audio_stream_info);
746 if (!IsValid(type)) {
747 error = esplusplayer_set_audio_stream_info(esplayer_, &audio_stream_info);
748 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
749 LOG(ERROR) << "esplusplayer_set_audio_stream_info failed. error code "
751 GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
754 buffer_observer_->SetMediaStreamStatusCallback(DemuxerStream::AUDIO);
757 player_buffer_size_t max_buffer_size = GetMaxAudioBufferSize();
758 buffer_observer_->SetBufferSize(type, max_buffer_size);
759 LOG(INFO) << "Audio Max buffer size " << max_buffer_size;
760 error = esplusplayer_set_buffer_size(
761 esplayer_, ESPLUSPLAYER_BUFFER_AUDIO_MAX_BYTE_SIZE, max_buffer_size);
762 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE)
763 LOG(WARNING) << "Failed to set audio buffer to " << max_buffer_size / 1024
766 SetMediaType(GetMediaType() | MediaType::Audio);
768 SetIsValid(type, true);
769 GetMediaPlayerClient()->OnAudioConfigChange(audio_config);
772 if (type == DemuxerStream::VIDEO) {
773 media::VideoDecoderConfig video_config = stream->video_decoder_config();
774 if (!video_config.IsValidConfig()) {
775 LOG(ERROR) << "Invalid video config.";
779 LOG(INFO) << "Video config : " << video_config.AsHumanReadableString();
780 esplusplayer_video_stream_info video_stream_info;
781 memset(&video_stream_info, 0, sizeof(esplusplayer_video_stream_info));
783 error = SetVideoStreamInfo(video_config, video_stream_info);
784 if (!IsValid(type)) {
785 error = esplusplayer_set_video_stream_info(esplayer_, &video_stream_info);
786 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
787 LOG(ERROR) << "esplusplayer_set_video_stream_info failed. error code "
789 GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
792 buffer_observer_->SetMediaStreamStatusCallback(DemuxerStream::VIDEO);
795 player_buffer_size_t max_buffer_size = GetMaxVideoBufferSize(video_config);
796 buffer_observer_->SetBufferSize(type, max_buffer_size);
797 LOG(INFO) << "Video Max buffer size " << max_buffer_size;
798 error = esplusplayer_set_buffer_size(
799 esplayer_, ESPLUSPLAYER_BUFFER_VIDEO_MAX_BYTE_SIZE, max_buffer_size);
800 if (error != ESPLUSPLAYER_ERROR_TYPE_NONE)
801 LOG(WARNING) << "Failed to set video buffer to " << max_buffer_size / 1024
804 SetMediaType(GetMediaType() | MediaType::Video);
806 SetIsValid(type, true);
807 GetMediaPlayerClient()->OnVideoConfigChange(video_config);
811 void MediaPlayerESPlusPlayer::ReadBuffer(DemuxerStream::Type type) {
812 if (!ReadFromBufferQueue(type))
815 // Avoid unnecessary or redundant read requests.
816 if (!ShouldFeed(type) || ReadRequested(type) || IsEos(type) ||
817 (is_prepared_ && is_paused_ && !is_seeking_)) {
821 // If the playing statue is expected,
822 // keep running a timer to decide play or pause with data.
824 StartOperationForDataTimer();
827 SetReadRequested(type, true);
828 uint32_t buffer_read_count = 1;
829 // TODO: Set correct buffer read count.
830 GetDemuxerStream(type)->Read(buffer_read_count,
831 base::BindOnce(&MediaPlayerESPlusPlayer::OnBufferReady,
832 weak_factory_.GetWeakPtr(), type));
835 void MediaPlayerESPlusPlayer::PostReadBuffer(DemuxerStream::Type type) {
836 task_runner_->PostDelayedTask(
838 base::BindOnce(&MediaPlayerESPlusPlayer::ReadBuffer,
839 weak_factory_.GetWeakPtr(), type),
840 kBufferQueueReadDelay);
843 void MediaPlayerESPlusPlayer::OnBufferReady(
844 DemuxerStream::Type type,
845 DemuxerStream::Status status,
846 DemuxerStream::DecoderBufferVector buffers) {
847 bool should_delay_read = false;
849 case DemuxerStream::kAborted:
850 case DemuxerStream::kError:
851 GetBufferQueue(type).clear();
853 case DemuxerStream::kNeedBuffer:
854 should_delay_read = true;
856 case DemuxerStream::kConfigChanged:
857 // Clear pending buffer of older config
858 GetBufferQueue(type).clear();
859 InitializeStreamConfig(type);
861 case DemuxerStream::kOk: {
862 GetBufferQueue(type).push_back(buffers[0]);
867 SetReadRequested(type, false);
868 if (should_delay_read)
869 PostReadBuffer(type);
874 bool MediaPlayerESPlusPlayer::ReadFromBufferQueue(DemuxerStream::Type type) {
875 if (!GetBufferQueue(type).size())
878 esplusplayer_submit_status status = ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS;
879 scoped_refptr<DecoderBuffer> buffer = GetBufferQueue(type).front();
880 if (buffer.get()->end_of_stream())
881 status = SubmitEosPacket(type);
883 status = SubmitEsPacket(type, buffer);
885 if (status == ESPLUSPLAYER_SUBMIT_STATUS_FULL) {
886 // If buffer is full, try again after a while.
887 PostReadBuffer(type);
891 if ((status == ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED) ||
892 (status == ESPLUSPLAYER_SUBMIT_STATUS_OUT_OF_MEMORY))
895 UpdateBufferedDtsDifference();
896 GetBufferQueue(type).pop_front();
900 esplusplayer_submit_status MediaPlayerESPlusPlayer::SubmitEosPacket(
901 DemuxerStream::Type type) {
903 return ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS;
905 last_frames_[type].first = base::TimeDelta::Max();
907 esplusplayer_submit_status status = esplusplayer_submit_eos_packet(
908 esplayer_, GetESPlusPlayerStreamType(type));
909 if (status != ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS) {
910 LOG(ERROR) << "Submit Eos (" << DemuxerStream::GetTypeName(type)
911 << ") Packet failed, ret:" << GetString(status);
914 buffer_observer_->SetEos(type);
915 SetIsEos(type, true);
919 esplusplayer_submit_status MediaPlayerESPlusPlayer::SubmitEsPacket(
920 DemuxerStream::Type type,
921 scoped_refptr<DecoderBuffer> buffer) {
922 esplusplayer_es_packet packet;
923 memset(&packet, 0, sizeof(esplusplayer_es_packet));
924 packet.type = GetESPlusPlayerStreamType(type);
926 packet.buffer = (char*)(const_cast<unsigned char*>(buffer->data()));
927 packet.buffer_size = buffer->data_size();
928 packet.pts = buffer->timestamp().InMilliseconds();
929 packet.duration = buffer->duration().InMilliseconds();
931 LOG(INFO) << __func__ << " " << DemuxerStream::GetTypeName(type) << " : "
932 << "Pushing esplus timestamp: " << packet.pts
933 << ", duration: " << packet.duration
934 << ", size: " << packet.buffer_size
935 << ", is_key_frame: " << buffer->is_key_frame()
936 << ", this: " << this;
938 // This filed only set when PushMediaPacket
939 packet.matroska_color_info = nullptr;
940 esplusplayer_submit_status status =
941 esplusplayer_submit_packet(esplayer_, &packet);
942 if (status != ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS) {
943 LOG(WARNING) << "submit " << DemuxerStream::GetTypeName(type)
944 << " packet : " << GetString(status);
947 last_frames_[type].first = base::Milliseconds(packet.pts);
948 last_frames_[type].second = base::Milliseconds(packet.duration);
952 void MediaPlayerESPlusPlayer::UpdateBufferedDtsDifference() {
953 // Ignore unless audio and video streams are valid.
954 if (!IsValid(DemuxerStream::AUDIO) || !IsValid(DemuxerStream::VIDEO))
957 const auto& audio_ts = last_frames_.get<DemuxerStream::AUDIO>().first;
958 const auto& video_ts = last_frames_.get<DemuxerStream::VIDEO>().first;
960 if ((audio_ts != media::kNoTimestamp) && (video_ts != media::kNoTimestamp) &&
961 (audio_ts != base::TimeDelta::Max()) &&
962 (video_ts != base::TimeDelta::Max())) {
963 const auto av_diff = (audio_ts - video_ts).InMilliseconds();
964 buffer_observer_->SetAudioVideoDtsDifference(av_diff);
966 buffer_observer_->SetAudioVideoDtsDifference(0);
970 void MediaPlayerESPlusPlayer::OnBufferingStatusChanged(DemuxerStream::Type type,
971 BufferStatus status) {
972 LOG(INFO) << __func__ << " " << DemuxerStream::GetTypeName(type) << " : "
973 << GetString(status);
974 if (expected_seek_ && is_prepared_) {
975 LOG(INFO) << "Ignore the buffer updates while seek";
980 case kBufferUnderrun:
981 case kBufferMinThreshold:
983 is_buffering_ = true;
984 SetShouldFeed(type, true);
987 case kBufferMaxThreshold:
988 case kBufferOverflow:
991 is_buffering_ = false;
992 SetShouldFeed(type, false);
998 if (status != kBufferNone) {
999 if (GetOperationForData() == OperationForData::PLAY)
1000 ReportBufferingStateIfNeeded(BUFFERING_HAVE_ENOUGH,
1001 BUFFERING_CHANGE_REASON_UNKNOWN);
1003 ReportBufferingStateIfNeeded(BUFFERING_HAVE_NOTHING,
1004 BUFFERING_CHANGE_REASON_UNKNOWN);
1008 void MediaPlayerESPlusPlayer::ReportBufferingStateIfNeeded(
1009 BufferingState buffering_state,
1010 BufferingStateChangeReason reason) {
1011 if (reported_buffering_state_ != buffering_state) {
1012 LOG(INFO) << __func__ << " Report BufferingState : " << buffering_state
1013 << ", reason : " << reason;
1014 reported_buffering_state_ = buffering_state;
1015 GetMediaPlayerClient()->OnBufferingStateChange(buffering_state, reason);
1019 void MediaPlayerESPlusPlayer::PerformOperationForData() {
1020 // The low latency mode doesn't buffer packets. It decodes and renders
1021 // a packet at once. WebRtc uses this feature.
1022 if (is_video_low_latency_)
1025 if (is_seeking_ || is_preparing_)
1028 OperationForData operation = GetOperationForData();
1029 switch (operation) {
1030 case OperationForData::PLAY:
1031 is_paused_by_buffering_ = false;
1034 case OperationForData::PAUSE:
1035 is_paused_by_buffering_ = true;
1041 MediaPlayerESPlusPlayer::OperationForData
1042 MediaPlayerESPlusPlayer::GetOperationForData() {
1043 bool has_video_media_type = GetMediaType() & MediaType::Video;
1044 bool has_audio_media_type = GetMediaType() & MediaType::Audio;
1046 bool has_video_data =
1047 !has_video_media_type ||
1048 (last_frames_.get<DemuxerStream::VIDEO>().first != media::kNoTimestamp);
1049 bool has_audio_data =
1050 !has_audio_media_type ||
1051 (last_frames_.get<DemuxerStream::AUDIO>().first != media::kNoTimestamp);
1052 if (!has_video_data || !has_audio_data) {
1053 LOG(INFO) << __func__
1054 << " Video or audio data has not yet been pushed. video "
1055 << has_video_data << ", audio " << has_audio_data;
1056 return OperationForData::NONE;
1059 base::TimeDelta current_position = GetCurrentTime();
1061 if (is_paused_by_buffering_) {
1062 // Get the end position of pushed data.
1063 base::TimeDelta pushed_end_position =
1064 std::min(has_video_media_type
1065 ? last_frames_.get<DemuxerStream::VIDEO>().first +
1066 last_frames_.get<DemuxerStream::VIDEO>().second
1067 : base::TimeDelta::Max(),
1068 has_audio_media_type
1069 ? last_frames_.get<DemuxerStream::AUDIO>().first +
1070 last_frames_.get<DemuxerStream::AUDIO>().second
1071 : base::TimeDelta::Max());
1072 base::TimeDelta time_diff = pushed_end_position - current_position;
1074 // If data has been pushed enough (>= kMinWaitTimeForPlayback)
1075 if (time_diff >= kMinWaitTimeForPlayback) {
1076 LOG(INFO) << __func__ << " Data is enough to play,";
1077 ReportBufferingStateIfNeeded(BUFFERING_HAVE_ENOUGH,
1078 BUFFERING_CHANGE_REASON_UNKNOWN);
1079 return OperationForData::PLAY;
1082 bool should_pause = false;
1083 if (has_video_media_type &&
1084 current_position >= last_frames_.get<DemuxerStream::VIDEO>().first) {
1085 should_pause = true;
1087 if (has_audio_media_type &&
1088 current_position >= last_frames_.get<DemuxerStream::AUDIO>().first) {
1089 should_pause = true;
1093 LOG(INFO) << __func__ << " Not enough data to play.";
1094 // If pushing pts smaller than current_position, should report
1095 // BUFFERING_HAVE_NOTHING to replace BUFFERING_HAVE_ENOUGH
1096 ReportBufferingStateIfNeeded(BUFFERING_HAVE_NOTHING,
1097 BUFFERING_CHANGE_REASON_UNKNOWN);
1098 return OperationForData::PAUSE;
1102 return OperationForData::NONE;
1105 void MediaPlayerESPlusPlayer::StartOperationForDataTimer() {
1106 if (!operation_for_data_timer_.IsRunning()) {
1107 operation_for_data_timer_.Start(
1108 FROM_HERE, kOperationDecisionDelay, this,
1109 &MediaPlayerESPlusPlayer::PerformOperationForData);
1113 void MediaPlayerESPlusPlayer::StopOperationForDataTimer() {
1114 if (operation_for_data_timer_.IsRunning()) {
1115 operation_for_data_timer_.Stop();
1119 void MediaPlayerESPlusPlayer::OnReadyToPrepare(
1120 const esplusplayer_stream_type stream_type) {
1121 if (!task_runner_->BelongsToCurrentThread()) {
1122 task_runner_->PostTask(
1123 FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::OnReadyToPrepare,
1124 weak_factory_.GetWeakPtr(), stream_type));
1128 LOG(INFO) << "OnReadyToPrepare : "
1129 << DemuxerStream::GetTypeName(GetDemuxerStreamType(stream_type));
1130 if ((stream_type != ESPLUSPLAYER_STREAM_TYPE_AUDIO) &&
1131 (stream_type != ESPLUSPLAYER_STREAM_TYPE_VIDEO))
1134 DemuxerStream::Type type = GetDemuxerStreamType(stream_type);
1135 if (IsValid(type)) {
1136 SetShouldFeed(type, true);
1141 void MediaPlayerESPlusPlayer::OnPrepareComplete(bool result) {
1142 if (!task_runner_->BelongsToCurrentThread()) {
1143 task_runner_->PostTask(
1144 FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::OnPrepareComplete,
1145 weak_factory_.GetWeakPtr(), result));
1150 LOG(ERROR) << "OnPrepareComplete prepare_async failed.";
1151 GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
1155 if (GetPlayerState() != ESPLUSPLAYER_STATE_READY) {
1156 LOG(ERROR) << "Invalid state (" << GetString(GetPlayerState())
1157 << ") change during prepare. Returning.";
1161 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
1162 << " is_paused_ : " << is_paused_
1163 << " seek_position : " << seek_position_
1164 << " pending_seek_ : " << pending_seek_
1165 << " pending_seek_position_ : " << pending_seek_position_;
1167 PostPrepareComplete();
1170 void MediaPlayerESPlusPlayer::PostPrepareComplete() {
1171 #if defined(TIZEN_VIDEO_HOLE)
1173 video_plane_controller_->ApplyDeferredVideoRectIfNeeded();
1176 is_prepared_ = true;
1177 is_preparing_ = false;
1178 if (pending_seek_) {
1179 GetMediaPlayerClient()->OnRequestSeek(pending_seek_position_);
1180 } else if (!is_paused_) {
1185 void MediaPlayerESPlusPlayer::OnEos() {
1186 if (!task_runner_->BelongsToCurrentThread()) {
1187 task_runner_->PostTask(FROM_HERE,
1188 base::BindOnce(&MediaPlayerESPlusPlayer::OnEos,
1189 weak_factory_.GetWeakPtr()));
1193 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
1194 GetMediaPlayerClient()->OnEnded();
1197 void MediaPlayerESPlusPlayer::OnFrameReady(
1198 const esplusplayer_decoded_video_packet* packet) {
1199 if (!task_runner_->BelongsToCurrentThread()) {
1200 task_runner_->PostTask(
1201 FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::OnFrameReady,
1202 weak_factory_.GetWeakPtr(), packet));
1205 tbm_surface_info_s suf_info = {
1208 tbm_surface_h tbm_surface = static_cast<tbm_surface_h>(packet->surface_data);
1210 if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &suf_info)) {
1211 LOG(ERROR) << "|tbm_surface_get_info| failed";
1215 int width = static_cast<int>(suf_info.width);
1216 int height = static_cast<int>(suf_info.height);
1217 gfx::Size size(width, height);
1219 base::TimeDelta timestamp = base::Milliseconds(packet->pts);
1220 DLOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
1221 << " size:" << size.ToString()
1222 << ", timestamp:" << timestamp.InMilliseconds()
1223 << ", duration:" << packet->duration << ", Player(" << esplayer_
1224 << ", state:" << GetString(GetPlayerState());
1226 #if defined(TIZEN_TBM_SUPPORT)
1227 gfx::TbmBufferHandle tbm_handle;
1228 tbm_handle.tbm_surface = reinterpret_cast<uint64_t>(tbm_surface);
1229 tbm_handle.media_packet = reinterpret_cast<uint64_t>(packet);
1230 tbm_handle.player_id = player_id_;
1231 tbm_handle.width = width;
1232 tbm_handle.height = height;
1234 GetMediaPlayerClient()->OnNewTbmFrameAvailable(0, tbm_handle, timestamp);
1236 base::UnsafeSharedMemoryRegion shared_memory;
1237 uint32_t shared_memory_size =
1238 suf_info.planes[0].size + (suf_info.planes[0].size / 2);
1239 shared_memory = base::UnsafeSharedMemoryRegion::Create(shared_memory_size);
1240 if (!shared_memory.IsValid()) {
1241 LOG(ERROR) << "Shared Memory creation failed.";
1245 base::WritableSharedMemoryMapping memory_mapping;
1246 memory_mapping = shared_memory.Map();
1247 if (!memory_mapping.IsValid()) {
1248 LOG(ERROR) << "Shared Memory handle could not be obtained";
1252 unsigned char* y_ptr = static_cast<unsigned char*>(memory_mapping.memory());
1254 // Video format will always be converted to I420
1255 switch (suf_info.format) {
1256 case TBM_FORMAT_NV12: {
1257 unsigned char* u_ptr = y_ptr + suf_info.planes[0].size;
1258 unsigned char* v_ptr = u_ptr + (suf_info.planes[0].size / 4);
1259 libyuv::NV12ToI420(suf_info.planes[0].ptr, suf_info.planes[0].stride,
1260 suf_info.planes[1].ptr, suf_info.planes[1].stride,
1261 y_ptr, suf_info.planes[0].stride, u_ptr,
1262 suf_info.planes[1].stride / 2, v_ptr,
1263 suf_info.planes[1].stride / 2, suf_info.width,
1267 case TBM_FORMAT_YUV420: {
1268 unsigned char* u_ptr = y_ptr + suf_info.planes[0].size;
1269 unsigned char* v_ptr = u_ptr + suf_info.planes[1].size;
1271 suf_info.planes[0].ptr, suf_info.planes[0].stride,
1272 suf_info.planes[1].ptr, suf_info.planes[1].stride,
1273 suf_info.planes[2].ptr, suf_info.planes[2].stride, y_ptr,
1274 suf_info.planes[0].stride, u_ptr, suf_info.planes[1].stride, v_ptr,
1275 suf_info.planes[2].stride, suf_info.width, suf_info.height);
1280 LOG(WARNING) << "Not supported format";
1285 esplusplayer_decoded_buffer_destroy(
1286 esplayer_, const_cast<esplusplayer_decoded_video_packet*>(packet));
1287 GetMediaPlayerClient()->OnNewFrameAvailable(0, std::move(shared_memory),
1288 shared_memory_size, timestamp,
1291 uint8_t* const yuv_buffer = static_cast<uint8_t*>(memory_mapping.memory());
1292 scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateFrame(
1293 media::PIXEL_FORMAT_I420, size, gfx::Rect(size), size, timestamp);
1295 uint8_t* video_buf = yuv_buffer;
1296 const uint c_frm_size = shared_memory_size / 6;
1297 const uint y_frm_size = c_frm_size << 2; // * 4;
1300 uint8_t* video_buf_u = video_buf + y_frm_size;
1303 uint8_t* video_buf_v = video_buf_u + c_frm_size;
1306 video_buf, video_frame.get()->stride(VideoFrame::kYPlane), video_buf_u,
1307 video_frame.get()->stride(VideoFrame::kYPlane) / 2, video_buf_v,
1308 video_frame.get()->stride(VideoFrame::kYPlane) / 2,
1309 video_frame.get()->GetWritableVisibleData(VideoFrame::kYPlane),
1310 video_frame.get()->stride(VideoFrame::kYPlane),
1311 video_frame.get()->GetWritableVisibleData(VideoFrame::kUPlane),
1312 video_frame.get()->stride(VideoFrame::kUPlane),
1313 video_frame.get()->GetWritableVisibleData(VideoFrame::kVPlane),
1314 video_frame.get()->stride(VideoFrame::kVPlane), width, height);
1315 esplusplayer_decoded_buffer_destroy(
1316 esplayer_, const_cast<esplusplayer_decoded_video_packet*>(packet));
1318 sink_->PaintSingleFrame(video_frame);
1323 void MediaPlayerESPlusPlayer::OnFlushComplete() {
1327 void MediaPlayerESPlusPlayer::OnReadyToSeek(
1328 const esplusplayer_stream_type stream_type,
1329 const uint64_t seek_time) {
1330 if (!task_runner_->BelongsToCurrentThread()) {
1331 task_runner_->PostTask(
1333 base::BindOnce(&MediaPlayerESPlusPlayer::OnReadyToSeek,
1334 weak_factory_.GetWeakPtr(), stream_type, seek_time));
1337 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " : "
1338 << DemuxerStream::GetTypeName(GetDemuxerStreamType(stream_type))
1339 << " : " << seek_time;
1342 LOG(INFO) << "player is destroyed:" << (void*)this;
1346 SetShouldFeed(GetDemuxerStreamType(stream_type), true);
1347 SetIsEos(GetDemuxerStreamType(stream_type), false);
1348 ReadBuffer(GetDemuxerStreamType(stream_type));
1351 void MediaPlayerESPlusPlayer::OnSeekComplete() {
1352 if (!task_runner_->BelongsToCurrentThread()) {
1353 task_runner_->PostTask(
1354 FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::OnSeekComplete,
1355 weak_factory_.GetWeakPtr()));
1359 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
1360 << " is_paused:" << is_paused_;
1362 current_position_ = seek_position_;
1363 is_seeking_ = false;
1364 expected_seek_ = false;
1365 seek_position_ = base::TimeDelta();
1371 void MediaPlayerESPlusPlayer::OnResourceConflict() {
1372 if (!task_runner_->BelongsToCurrentThread()) {
1373 task_runner_->PostTask(
1374 FROM_HERE, base::BindOnce(&MediaPlayerESPlusPlayer::OnResourceConflict,
1375 weak_factory_.GetWeakPtr()));
1379 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
1380 RequestSuspend(true);
1383 void MediaPlayerESPlusPlayer::OnError(const esplusplayer_error_type error) {
1384 if (!task_runner_->BelongsToCurrentThread()) {
1385 task_runner_->PostTask(FROM_HERE,
1386 base::BindOnce(&MediaPlayerESPlusPlayer::OnError,
1387 weak_factory_.GetWeakPtr(), error));
1391 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__ << " : "
1392 << esplusplayer_get_error_string(
1393 static_cast<esplusplayer_error_type>(error));
1395 GetMediaPlayerClient()->OnError(GetPipelineError(error));
1399 MediaPlayerESPlusPlayer::ElementryStream&
1400 MediaPlayerESPlusPlayer::GetElementryStream(DemuxerStream::Type type) {
1401 return elementry_stream_[GetElementryStreamIndex(type)];
1404 const MediaPlayerESPlusPlayer::ElementryStream&
1405 MediaPlayerESPlusPlayer::GetElementryStream(DemuxerStream::Type type) const {
1406 return elementry_stream_[GetElementryStreamIndex(type)];
1409 bool MediaPlayerESPlusPlayer::IsValid(DemuxerStream::Type type) const {
1410 return GetElementryStream(type).is_valid_;
1413 void MediaPlayerESPlusPlayer::SetIsValid(DemuxerStream::Type type, bool value) {
1414 GetElementryStream(type).is_valid_ = value;
1417 bool MediaPlayerESPlusPlayer::IsEos(DemuxerStream::Type type) const {
1418 return GetElementryStream(type).is_eos_;
1421 void MediaPlayerESPlusPlayer::SetIsEos(DemuxerStream::Type type, bool value) {
1422 GetElementryStream(type).is_eos_ = value;
1425 bool MediaPlayerESPlusPlayer::ShouldFeed(DemuxerStream::Type type) const {
1426 return GetElementryStream(type).should_feed_;
1429 void MediaPlayerESPlusPlayer::SetShouldFeed(DemuxerStream::Type type,
1431 GetElementryStream(type).should_feed_ = value;
1434 bool MediaPlayerESPlusPlayer::ReadRequested(DemuxerStream::Type type) const {
1435 return GetElementryStream(type).read_requested_;
1438 void MediaPlayerESPlusPlayer::SetReadRequested(DemuxerStream::Type type,
1440 GetElementryStream(type).read_requested_ = value;
1443 DemuxerStream* MediaPlayerESPlusPlayer::GetDemuxerStream(
1444 DemuxerStream::Type type) const {
1445 return GetElementryStream(type).input_stream_;
1448 void MediaPlayerESPlusPlayer::SetDemuxerStream(DemuxerStream::Type type,
1449 DemuxerStream* stream) {
1450 GetElementryStream(type).input_stream_ = stream;
1453 Queue& MediaPlayerESPlusPlayer::GetBufferQueue(DemuxerStream::Type type) {
1454 return GetElementryStream(type).pending_buffers_;
1457 #if defined(TIZEN_VIDEO_HOLE)
1458 void MediaPlayerESPlusPlayer::SetVideoHole(bool is_video_hole) {
1459 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
1460 << " is_video_hole : " << is_video_hole;
1461 is_video_hole_ = is_video_hole;
1462 if (is_video_hole_ && esplayer_ && !video_plane_controller_) {
1463 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
1464 << " pended set video_plane_controller";
1465 video_plane_controller_.reset(
1466 new VideoPlaneControllerESPlusPlayer(esplayer_));
1470 void MediaPlayerESPlusPlayer::SetMediaGeometry(const gfx::Rect& viewport_rect,
1471 const gfx::RectF& rect) {
1472 if (!is_video_hole_)
1475 LOG(INFO) << __func__ << " viewport_rect: " << viewport_rect.ToString()
1476 << " rect : " << rect.ToString();
1478 if (!esplayer_ || !video_plane_controller_) {
1479 LOG_ID(INFO, player_id_)
1480 << "(" << static_cast<void*>(this) << ") "
1481 << "player is destroyed, or video plane controller not exist.";
1485 video_plane_controller_->SetMediaGeometry(viewport_rect, rect);
1488 void MediaPlayerESPlusPlayer::PrepareVideoHole() {
1489 LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
1491 if (!esplayer_ || is_prepared_ || is_preparing_) {
1492 LOG_ID(ERROR, player_id_)
1493 << "(" << static_cast<void*>(this) << ") " << __func__
1494 << ", esplayer_: " << static_cast<void*>(esplayer_)
1495 << ", is_prepared_: " << is_prepared_
1496 << ", is_preparing_: " << is_preparing_;
1499 if (GetPlayerState() != ESPLUSPLAYER_STATE_IDLE) {
1500 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
1501 << " Prepare called on invalid state : "
1502 << GetString(GetPlayerState());
1506 if (!is_video_hole_ || !video_plane_controller_)
1509 if (video_plane_controller_->Initialize() != TIZEN_ERROR_NONE) {
1510 LOG(ERROR) << "video_plane_controller init error";
1514 LOG(INFO) << __func__ << " set ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY";
1515 int player_error = ESPLUSPLAYER_ERROR_TYPE_NONE;
1516 if (video_plane_controller_->rendering_mode() ==
1517 VideoPlaneController::RenderingMode::OFFSCREEN &&
1518 !video_plane_controller_->get_use_wayland_window()) {
1519 player_error = esplusplayer_set_display(
1520 esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
1521 video_plane_controller_->GetVideoPlaneHandle());
1523 int wl_w, wl_h, wl_x, wl_y;
1524 ecore_wl2_window_geometry_get(
1525 static_cast<Ecore_Wl2_Window*>(
1526 video_plane_controller_->GetVideoPlaneHandle()),
1527 &wl_x, &wl_y, &wl_w, &wl_h);
1529 player_error = esplusplayer_set_ecore_display(
1530 esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
1531 static_cast<Ecore_Wl2_Window*>(
1532 video_plane_controller_->GetVideoPlaneHandle()),
1533 wl_x, wl_y, wl_w, wl_h);
1535 if (player_error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
1536 LOG(ERROR) << "player_error #"
1537 << esplusplayer_get_error_string(
1538 static_cast<esplusplayer_error_type>(player_error));
1544 void MediaPlayerESPlusPlayer::RequestSuspend(bool resource_conflicted) {
1545 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
1546 GetMediaPlayerClient()->OnRequestSuspend(resource_conflicted);
1550 void MediaPlayerESPlusPlayer::SetMediaType(DemuxerStream::Type type) {
1551 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
1552 if (type == DemuxerStream::AUDIO)
1553 SetMediaType(GetMediaType() | MediaType::Audio);
1554 else if (type == DemuxerStream::VIDEO)
1555 SetMediaType(GetMediaType() | MediaType::Video);
1558 PlayerRoleFlags MediaPlayerESPlusPlayer::GetRoles() const noexcept {
1559 return PlayerRole::ElementaryStreamBased;
1562 } // namespace media