2 // @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
4 // to manipulate TrackRenderer objects
5 // to provide optimized control of TrackRenderer
7 #include "esplayer/esplayer.h"
9 #include <boost/scope_exit.hpp>
19 #include "core/gst_utils.h"
20 #include "core/track_util.h"
21 #ifndef TIZEN_FEATURE_PUBLIC
22 #include "core/utils/caf_logger.h"
24 #include "core/utils/performance_checker.h"
25 #include "core/utils/plusplayer_cfg.h"
26 #include "core/utils/plusplayer_log.h"
27 #include "core/videoframetypestrategy.h"
28 #include "esplayer/esplayer_drm.h"
29 #include "json/json.h"
31 namespace esplusplayer {
35 // get values from /etc/multimedia/esplusplayer.ini
36 static std::once_flag loaded;
37 static std::map<std::string, bool> ini_property;
40 void LoadIniProperty(const Json::Value& root);
42 } // namespace es_conf
46 std::uint64_t ConvertMsToNs(std::uint64_t ms) {
47 constexpr std::uint64_t ns_unit = 1000000;
48 if (ms * ns_unit > G_MAXUINT64) return G_MAXUINT64;
52 std::uint64_t ConvertNsToMs(std::uint64_t ns) {
53 constexpr std::uint64_t ms_unit = 1000000;
57 std::int64_t ConvertMsToNs(std::int64_t ms) {
58 constexpr std::int64_t ns_unit = 1000000;
59 if (ms * ns_unit > G_MAXINT64) return G_MAXINT64;
63 std::int64_t ConvertNsToMs(std::int64_t ns) {
64 constexpr std::int64_t ms_unit = 1000000;
68 std::uint64_t ConvertUsToNs(std::uint64_t us) {
69 constexpr std::uint64_t ns_unit = 1000;
70 if (us * ns_unit > G_MAXUINT64) return G_MAXUINT64;
74 std::uint64_t ConvertNsToUs(std::uint64_t ns) {
75 constexpr std::uint64_t us_unit = 1000;
79 std::int64_t ConvertUsToNs(std::int64_t us) {
80 constexpr std::int64_t ns_unit = 1000;
81 if (us * ns_unit > G_MAXINT64) return G_MAXINT64;
85 std::int64_t ConvertNsToUs(std::int64_t ns) {
86 constexpr std::int64_t us_unit = 1000;
91 std::string GetStringFromMatroskaColor(const MatroskaColor& color_info) {
92 std::ostringstream oss;
93 oss << "matrixCoefficients:" << color_info.matrix_coefficients
94 << " bitsPerChannel:" << color_info.bits_per_channel
95 << " chromaSubsamplingHorz:" << color_info.chroma_subsampling_horizontal
96 << " chromaSubsamplingVert:" << color_info.chroma_subsampling_vertical
97 << " cbSubsamplingHorz:" << color_info.cb_subsampling_horizontal
98 << " cbSubsamplingVert:" << color_info.cb_subsampling_vertical
99 << " chromaSitingHorz:" << color_info.chroma_siting_horizontal
100 << " chromaSitingVert:" << color_info.chroma_siting_vertical
101 << " range:" << color_info.range
102 << " transferCharacteristics:" << color_info.transfer_characteristics
103 << " primaries:" << color_info.primaries
104 << " maxCLL:" << color_info.max_cll << " maxFALL:" << color_info.max_fall
105 << " RX:" << color_info.metadata.primary_r_chromaticity_x
106 << " RY:" << color_info.metadata.primary_r_chromaticity_y
107 << " GX:" << color_info.metadata.primary_g_chromaticity_x
108 << " GY:" << color_info.metadata.primary_g_chromaticity_y
109 << " BX:" << color_info.metadata.primary_b_chromaticity_x
110 << " BY:" << color_info.metadata.primary_b_chromaticity_y
111 << " wX:" << color_info.metadata.white_point_chromaticity_x
112 << " wY:" << color_info.metadata.white_point_chromaticity_y
113 << " luminanceMax:" << color_info.metadata.luminance_max
114 << " luminanceMin:" << color_info.metadata.luminance_min
115 << " isHDR10p:" << color_info.is_hdr_10p;
123 // const std::uint64_t kMaxByteOfVideoSrcQueue = 70 * 1024 * 1024; // 70 MB
124 // const std::uint64_t kMaxByteOfAudioSrcQueue = 10 * 1024 * 1024; // 10 MB
125 // const std::uint64_t kMaxTimeOfVideoSrcQueue = 10000000000; // 10 s
126 // const std::uint64_t kMaxTimeOfAudioSrcQueue = 10000000000; // 10 s
128 constexpr uint32_t kNdecodingMode = 0x04;
130 enum VolumeLevel { kVolumeMin = 0, kVolumeMax = 100 };
131 constexpr int kMaxFhdWidth = 1920;
132 constexpr int kMaxFhdHeight = 1080;
134 inline bool IsPcmMimeType(const std::string& mimetype) {
135 return (mimetype.find("audio/x-raw") != std::string::npos);
137 inline bool IsForcedUnsetTz(const Track& track, const std::string& id) {
138 if ((track.type == kTrackTypeAudio) && strstr(id.c_str(), "netflix")) {
143 inline bool IsAacCodec(const Track& track) {
144 return (track.mimetype.find("audio/mpeg") != std::string::npos &&
147 inline bool IsEac3Codec(const std::string& mimetype) {
148 return mimetype.find("audio/x-eac3") != std::string::npos;
150 inline bool IsAc3Codec(const std::string& mimetype) {
151 return mimetype.find("audio/x-ac3") != std::string::npos;
154 inline bool IsFlacCodec(const std::string& mimetype) {
155 return mimetype.find("audio/x-ffmpeg-parsed-flac") != std::string::npos;
158 inline bool IsAvailableCodecSwitch(const Track& track) {
159 if (internal::IsAacCodec(track) || internal::IsAc3Codec(track.mimetype) ||
160 internal::IsEac3Codec(track.mimetype))
165 int ResetEosStatus(const TrackType& type, int eos_status) {
166 if (type == kTrackTypeVideo)
167 eos_status &= ~EosStatus::kVideoEos;
168 else if (type == kTrackTypeAudio)
169 eos_status &= ~EosStatus::kAudioEos;
174 void MakeTrustZoneTracks(std::vector<Track>& tracks,
175 const std::string& app_id) {
176 for (auto& track : tracks) {
177 const bool is_already_tz_type =
178 (track.mimetype.find("_tz", track.mimetype.length() - 3) !=
180 if (is_already_tz_type) {
183 track.streamtype = track.mimetype;
184 bool is_flac = internal::IsFlacCodec(track.mimetype);
185 if ((track.use_swdecoder && !is_flac) || IsPcmMimeType(track.mimetype) ||
186 IsForcedUnsetTz(track, app_id))
189 track.mimetype = track.mimetype + "_tz";
194 void UpdateCodecTypeTracks(std::vector<Track>& tracks,
195 const PlayerAudioCodecType& audio_codec_type,
196 const PlayerVideoCodecType& video_codec_type,
197 bool force_audio_swdecoder_use,
198 bool force_video_swdecoder_use) {
199 for (auto& track : tracks) {
200 switch (track.type) {
201 case kTrackTypeAudio: {
202 if (audio_codec_type == kPlayerAudioCodecTypeSW ||
203 force_audio_swdecoder_use)
204 track.use_swdecoder = true;
206 track.use_swdecoder = false;
209 case kTrackTypeVideo: {
210 if (video_codec_type == kPlayerVideoCodecTypeSW ||
211 force_video_swdecoder_use)
212 track.use_swdecoder = true;
214 track.use_swdecoder = false;
222 inline bool IsSupportedDrmType(const drm::Type& drm_type) {
223 static const std::map<drm::Type, bool> kSupportedDrmType = {
224 {drm::Type::kPlayready, true},
226 if (kSupportedDrmType.count(drm_type) == 0) return false;
227 return kSupportedDrmType.at(drm_type);
229 inline void ResetDrmProperty(drm::Property& drm_property) {
230 drm_property = drm::Property();
232 inline StreamType ConvertToStreamType(TrackType type) {
233 return (type == kTrackTypeAudio) ? StreamType::kAudio : StreamType::kVideo;
235 struct AppsrcQueueSizeOption {
236 std::uint64_t current_size = 0;
237 std::uint64_t max_size = 0;
238 std::uint32_t threshold = 0;
240 inline bool IsUnderRun(AppsrcQueueSizeOption& byte_based,
241 AppsrcQueueSizeOption& time_based) {
242 bool need_data_by_byte = false, need_data_by_time = false;
243 need_data_by_byte = (byte_based.max_size > 0) &&
244 (byte_based.current_size * 100 / byte_based.max_size <=
245 byte_based.threshold);
246 need_data_by_time = (time_based.max_size > 0) &&
247 (time_based.current_size * 100 / time_based.max_size <=
248 time_based.threshold);
249 if (need_data_by_byte || need_data_by_time)
254 inline bool IsLowLatencyModeDisableAVSync(std::uint32_t mode) {
255 constexpr std::uint32_t kAVSync = kLowLatencyModeDisableAVSync;
256 return (mode & kAVSync) ? true : false;
258 inline bool IsLowLatencyModeDisablePreroll(std::uint32_t mode) {
259 constexpr std::uint32_t kPreroll = kLowLatencyModeDisablePreroll;
260 return (mode & kPreroll) ? true : false;
262 inline bool IsLowLatencyMode(std::uint32_t mode) {
263 return (mode != static_cast<std::uint32_t>(kLowLatencyModeNone)) ? true
266 inline bool IsSupportedTsOffset(std::uint32_t mode) {
267 return IsLowLatencyMode(mode) && !IsLowLatencyModeDisableAVSync(mode) ? true
271 inline bool IsLowLatencyModeEnableGameMode(std::uint32_t mode) {
272 constexpr std::uint32_t kGameMode = kLowLatencyModeEnableGameMode ^
273 kLowLatencyModeAudio ^
274 kLowLatencyModeVideo;
275 return (mode & kGameMode) ? true : false;
278 inline bool IsLowLatencyModeForCatchUp(std::uint32_t mode) {
279 return IsLowLatencyModeDisableAVSync(mode) &&
280 IsLowLatencyModeEnableGameMode(mode)
285 inline bool IsExclusiveLowLatencyMode(std::uint32_t current_mode,
286 std::uint32_t set_mode) {
287 std::uint32_t exclusive_mode = 0;
288 exclusive_mode |= static_cast<std::uint32_t>(kLowLatencyModeEnableGameMode);
290 static_cast<std::uint32_t>(kLowLatencyModeDisableVideoQuality);
292 std::uint32_t new_mode = current_mode | set_mode;
293 return (exclusive_mode == (new_mode & exclusive_mode)) ? true : false;
295 } // namespace internal
297 EsPlayer::EsPlayer() {
298 std::call_once(es_conf::loaded, [this]() { es_conf::LoadIniFile(); });
299 #ifndef TIZEN_FEATURE_PUBLIC
300 if (CafLogger::Initialize() != true) {
301 LOG_INFO("CAF Dbus not connect.");
304 InitValuesFromIni_();
307 EsPlayer::~EsPlayer() {
313 bool EsPlayer::Open() {
314 LOG_INFO_P(this, "state manager > %p", &state_manager_);
316 state_manager_.Start();
317 auto op = [this]() noexcept -> bool {
318 const auto start = performance_checker::Start();
319 if (trackrenderer_) {
320 assert(0 && "trackrenderer already exist");
323 std::async(std::launch::async, &EsPlayer::MsgTask_, this);
324 trackrenderer_ = TrackRendererAdapter::Create();
325 assert(trackrenderer_);
327 trackrenderer_->RegisterListenerForEsplayer(
328 trackrenderer_event_listener_.get());
329 performance_checker::End(start, "Open");
333 #ifndef TIZEN_FEATURE_PUBLIC
334 CafLogger::SetUniqueNumber();
335 caf_unique_number = CafLogger::GetUniqueNumber();
336 CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
339 es_event::Open event{op};
340 return state_manager_.ProcessEvent(event);
343 bool EsPlayer::Close() {
345 std::lock_guard<std::mutex> lk(submit_mutex_);
346 if (state_manager_.GetState() >= EsState::kIdle) {
349 auto op = [this]() noexcept {
350 if (is_msg_task_stop_ == false) {
352 std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
353 is_msg_task_stop_ = true;
355 msg_task_cv_.notify_one();
356 if (msg_handler_task_.valid()) msg_handler_task_.wait();
359 if (trackrenderer_) trackrenderer_.reset();
360 ResetContextForClose_();
364 es_event::Close event{op};
365 state_manager_.ProcessEvent(event);
366 state_manager_.Stop();
370 bool EsPlayer::Deactivate(const StreamType type) {
372 if (state_manager_.GetState() < EsState::kReady) {
373 LOG_ERROR_P(this, "Invalid State , current %d",
374 state_manager_.GetStateEnum());
378 if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
380 this, "can't deactivate audio stream, mixer will control audio stream");
384 if (!trackrenderer_->Deactivate(static_cast<TrackType>(type))) {
388 std::lock_guard<std::mutex> lock(eos_mutex_);
390 case StreamType::kAudio:
391 eos_status_ |= EosStatus::kAudioEos;
393 case StreamType::kVideo:
394 eos_status_ |= EosStatus::kVideoEos;
400 for (auto& track : track_) {
401 if (track.type == static_cast<TrackType>(type)) {
402 track.active = false;
408 bool EsPlayer::Activate(const StreamType type) {
410 if (state_manager_.GetState() < EsState::kReady) {
411 LOG_ERROR_P(this, "Invalid State , current %d",
412 state_manager_.GetStateEnum());
416 if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
418 "can't activate audio stream, mixer will control audio stream");
422 if (!track_.empty()) {
423 auto has_track = [type](const Track& item) -> bool {
424 return item.type == static_cast<TrackType>(type);
426 auto target = std::find_if(track_.begin(), track_.end(), has_track);
427 if (target == track_.end()) {
428 LOG_ERROR_P(this, "there is no track to activate");
431 if (target->active != false) {
432 LOG_ERROR_P(this, "The track should be deactivated in advance.");
435 target->active = true;
436 internal::UpdateCodecTypeTracks(
437 track_, audio_codec_type_, video_codec_type_,
438 force_audio_swdecoder_use_, force_video_swdecoder_use_);
439 if (drm_property_.external_decryption) {
440 internal::MakeTrustZoneTracks(track_, app_info_.id);
442 SetTrackRendererAttributes_();
443 if (type == StreamType::kVideo) {
446 trackrenderer_->SetVideoFrameBufferType(
447 VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
450 trackrenderer_->SetVideoFrameBufferType(VideoFrameTypeStrategyPtr(
451 new DefaultVideoFrameTypeStrategy(vidoe_frame_buffer_type_)));
453 if (!trackrenderer_->Activate(target->type, *target)) {
454 target->active = false;
458 internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
464 bool EsPlayer::DeactivateAudio() {
466 if (state_manager_.GetState() < EsState::kIdle) {
467 LOG_ERROR_P(this, "Invalid State , current %d",
468 state_manager_.GetStateEnum());
472 if (!enable_audio_pipeline_handle_) {
474 this, "can't deactivate audio stream, mixer will control audio stream");
478 if (!trackrenderer_->DeactivateAudio()) {
481 is_audio_stream_info_frozen_ = true;
485 bool EsPlayer::ActivateAudio() {
487 const StreamType type = StreamType::kAudio;
488 if (state_manager_.GetState() < EsState::kReady) {
489 LOG_ERROR_P(this, "Invalid State , current %d",
490 state_manager_.GetStateEnum());
494 if (!enable_audio_pipeline_handle_) {
496 "can't activate audio stream, mixer will control audio stream");
500 if (track_.empty()) {
503 if (!trackrenderer_->ActivateAudio()) {
507 internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
511 bool EsPlayer::Start() {
514 LOG_ERROR_P(this, "Stop already, no need to Start,leave...");
517 auto op = [this]() noexcept {
518 if (!trackrenderer_->Start()) {
524 #ifndef TIZEN_FEATURE_PUBLIC
525 CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
528 es_event::Start event{op};
529 return state_manager_.ProcessEvent(event);
532 bool EsPlayer::Stop() {
535 auto stop = [this]() noexcept -> bool {
536 const auto start = performance_checker::Start();
537 if (trackrenderer_) trackrenderer_->Stop();
538 ResetContextForStop_();
540 if (mixer_ticket_) mixer_ticket_.reset();
542 performance_checker::End(start, "Stop");
545 for (const auto& track : track_) {
546 es_packet_logger_.PrintStoredPacketInfo(
547 internal::ConvertToStreamType(track.type), true);
549 es_event::Stop event{stop};
550 bool res = state_manager_.ProcessEventStop(event);
552 if (preparetask_.valid()) {
553 LOG_INFO_P(this, "Stopped , Wait Prepare() finish...");
555 LOG_INFO_P(this, "Wait , Wait Prepare() Done...");
558 #ifndef TIZEN_FEATURE_PUBLIC
559 CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
560 CafLogger::StopLoggingThread();
566 void EsPlayer::SetTrackRendererAttributes_() {
567 if (trackrenderer_ == nullptr) return;
568 trackrenderer_->SetAttribute(
569 TrackRendererAdapter::Attribute::kVideoQueueMaxByte,
570 src_queue_size_.kMaxByteOfVideoSrcQueue);
571 trackrenderer_->SetAttribute(
572 TrackRendererAdapter::Attribute::kAudioQueueMaxByte,
573 src_queue_size_.kMaxByteOfAudioSrcQueue);
574 trackrenderer_->SetAttribute(
575 TrackRendererAdapter::Attribute::kVideoMinByteThreshold,
576 src_queue_size_.kMinByteThresholdOfVideoSrcQueue);
577 trackrenderer_->SetAttribute(
578 TrackRendererAdapter::Attribute::kAudioMinByteThreshold,
579 src_queue_size_.kMinByteThresholdOfAudioSrcQueue);
580 trackrenderer_->SetAttribute(
581 TrackRendererAdapter::Attribute::kVideoQueueMaxTime,
582 util::ConvertMsToNs(src_queue_size_.kMaxTimeOfVideoSrcQueue));
583 trackrenderer_->SetAttribute(
584 TrackRendererAdapter::Attribute::kAudioQueueMaxTime,
585 util::ConvertMsToNs(src_queue_size_.kMaxTimeOfAudioSrcQueue));
586 trackrenderer_->SetAttribute(
587 TrackRendererAdapter::Attribute::kVideoMinTimeThreshold,
588 src_queue_size_.kMinTimeThresholdOfVideoSrcQueue);
589 trackrenderer_->SetAttribute(
590 TrackRendererAdapter::Attribute::kAudioMinTimeThreshold,
591 src_queue_size_.kMinTimeThresholdOfAudioSrcQueue);
592 trackrenderer_->SetAttribute(
593 TrackRendererAdapter::Attribute::kUnlimitedMaxBufferMode,
594 unlimited_max_buffer_mode_);
595 trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kLowLatencyMode,
597 trackrenderer_->SetAttribute(
598 TrackRendererAdapter::Attribute::kVideoFramePeekMode,
599 video_frame_peek_mode_);
600 trackrenderer_->SetAttribute(
601 TrackRendererAdapter::Attribute::kAccurateSeekMode, accurate_seek_mode_);
602 trackrenderer_->SetAttribute(
603 TrackRendererAdapter::Attribute::kVideoPreDisplayMode,
604 video_pre_display_mode_);
605 if (resume_time_.is_set) {
606 trackrenderer_->SetAttribute(
607 TrackRendererAdapter::Attribute::kStartRenderingTime,
609 resume_time_.is_set = false;
611 trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
613 trackrenderer_->SetAttribute(
614 TrackRendererAdapter::Attribute::kAlternativeVideoResource,
615 alternative_video_resource_);
616 trackrenderer_->SetAttribute(
617 TrackRendererAdapter::Attribute::kVideoDecodingMode,
618 video_decoding_mode_);
619 trackrenderer_->SetAttribute(
620 TrackRendererAdapter::Attribute::kVideoProgressiveMode,
621 set_video_progressive_);
622 trackrenderer_->SetAttribute(
623 TrackRendererAdapter::Attribute::kPlayerTimeUnitType,
624 static_cast<std::uint32_t>(time_unit_type));
629 bool EsPlayer::PrepareVideoMixingMode_(std::vector<Track>* tracks) {
631 mixer_ticket_->Prepare();
632 if (enable_rsc_alloc_handle_) return true;
633 ResourceType type = ResourceType::kHwMain;
634 if (!mixer_ticket_->GetAvailableResourceType(ResourceCategory::kVideoDecoder,
636 LOG_ERROR_P(this, "no available resource");
639 if (!mixer_ticket_->Alloc(ResourceCategory::kVideoDecoder, type)) {
640 LOG_ERROR_P(this, "fail to alloc resource [%d]", static_cast<int>(type));
644 if (type == ResourceType::kHwSub) {
645 alternative_video_resource_ = 1;
646 } else if (type == ResourceType::kSw) {
647 for (auto it = tracks->begin(); it != tracks->end(); ++it) {
648 if (it->type == kTrackTypeVideo) {
649 it->use_swdecoder = true;
653 } else if (type == ResourceType::kNdecoder) {
654 video_decoding_mode_ = internal::kNdecodingMode;
661 bool EsPlayer::Prepare_() {
664 LOG_ERROR_P(this, "Stop already, no need to prepare,leave...");
667 auto op = [this]() noexcept -> bool {
668 const auto start = performance_checker::Start();
670 internal::UpdateCodecTypeTracks(
671 track_, audio_codec_type_, video_codec_type_,
672 force_audio_swdecoder_use_, force_video_swdecoder_use_);
673 if (drm_property_.external_decryption) {
674 internal::MakeTrustZoneTracks(track_, app_info_.id);
676 std::vector<Track> active_track;
677 if (!track_util::GetActiveTrackList(track_, active_track)) {
680 trackrenderer_->SetIniProperty(es_conf::ini_property);
683 trackrenderer_->SetVideoFrameBufferType(
684 VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
685 if (!PrepareVideoMixingMode_(&active_track)) {
686 LOG_ERROR_P(this, "fail to prepare mixing mode");
690 std::unique_lock<std::mutex> lock(audio_focus_m_);
691 if (!enable_audio_pipeline_handle_ && !is_audio_focused_) {
692 for (auto it = active_track.begin(); it != active_track.end(); ++it) {
693 if (it->type == kTrackTypeAudio) {
694 active_track.erase(it);
695 LOG_INFO_P(this, "erase audio track is_audio_focused_ [%d]",
702 for (const auto& track : active_track) {
703 switch (track.type) {
704 case kTrackTypeAudio: {
705 std::lock_guard<std::mutex> lock2(eos_mutex_);
706 eos_status_ = internal::ResetEosStatus(kTrackTypeAudio, eos_status_);
707 need_data_[track.type].mask |= kNeedDataMaskByPrepare;
710 case kTrackTypeVideo: {
711 std::lock_guard<std::mutex> lock2(eos_mutex_);
712 eos_status_ = internal::ResetEosStatus(kTrackTypeVideo, eos_status_);
713 need_data_[track.type].mask |= kNeedDataMaskByPrepare;
720 SetTrackRendererAttributes_();
721 trackrenderer_->SetTrack(active_track);
722 if (!trackrenderer_->Prepare()) {
725 performance_checker::End(start, "Prepare");
729 #ifndef TIZEN_FEATURE_PUBLIC
730 CafLogger::StartLoggingThread();
731 CafLogger::LogMessage(CafEventType::kReady, caf_unique_number);
734 es_event::Prepare event{op};
735 if (!state_manager_.ProcessEvent(event)) {
742 void EsPlayer::PrepareTask_() {
743 bool ret = Prepare_();
745 state_manager_.SetPreparingState(false);
746 if (eventlistener_) {
747 LOG_INFO_P(this, "Prepare completely, call OnPrepareDone(%d)", ret);
748 eventlistener_->OnPrepareDone(ret, eventlistener_userdata_);
749 LOG_INFO_P(this, "call OnPrepareDone End");
752 #ifndef TIZEN_FEATURE_PUBLIC
753 kpi::CodecLogger logger;
754 kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
755 logger.SendKpi(ret, event_keys);
760 bool EsPlayer::PrepareAsync() {
762 state_manager_.SetPreparingState(true);
763 preparetask_ = std::async(std::launch::async, &EsPlayer::PrepareTask_, this);
764 if (!preparetask_.valid()) {
765 state_manager_.SetPreparingState(false);
771 bool EsPlayer::Pause() {
774 LOG_ERROR_P(this, "Stop already, no need to pause,leave...");
777 if (state_manager_.GetState() < EsState::kReady) {
778 LOG_ERROR_P(this, "Invalid State , current %d",
779 state_manager_.GetStateEnum());
782 auto op = [this]() noexcept -> bool {
783 if (!trackrenderer_) return false;
784 if (!trackrenderer_->Pause()) {
789 for (const auto& track : track_) {
790 es_packet_logger_.PrintStoredPacketInfo(
791 internal::ConvertToStreamType(track.type), true);
794 #ifndef TIZEN_FEATURE_PUBLIC
795 CafLogger::LogMessage(CafEventType::kPaused, caf_unique_number);
798 es_event::Pause event{op};
799 return state_manager_.ProcessEvent(event);
802 bool EsPlayer::Resume() {
805 LOG_ERROR_P(this, "Stop already, no need to Resume,leave...");
808 if (state_manager_.GetState() <= EsState::kReady) {
809 LOG_ERROR_P(this, "Invalid State , current %d",
810 state_manager_.GetStateEnum());
813 if (is_resource_conflicted_) {
814 LOG_ERROR_P(this, "Resuem fail resource conflicted");
817 auto op = [this]() noexcept -> bool {
818 if (!trackrenderer_) return false;
819 if (!trackrenderer_->Resume()) {
824 for (const auto& track : track_) {
825 es_packet_logger_.PrintStoredPacketInfo(
826 internal::ConvertToStreamType(track.type), true);
829 #ifndef TIZEN_FEATURE_PUBLIC
830 CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
833 es_event::Resume event{op};
834 return state_manager_.ProcessEvent(event);
837 bool EsPlayer::Seek(const uint64_t time) {
838 if (state_manager_.GetState() < EsState::kIdle) {
839 LOG_ERROR_P(this, "Invalid State , current %d",
840 state_manager_.GetStateEnum());
843 if (state_manager_.GetState() == EsState::kIdle) {
844 if (state_manager_.GetPreparingState()) {
845 LOG_ERROR_P(this, "Invalid State , during preparing");
848 LOG_ERROR("%p resume time [%" PRId64 " ]", this, time);
849 resume_time_.is_set = true;
850 resume_time_.time = time;
853 is_seek_done_need_drop = true;
854 if (time_unit_type == kPlayerTimeUnitTypeMs)
855 LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " ms]", this, time);
856 else if (time_unit_type == kPlayerTimeUnitTypeUs)
857 LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " us]", this, time);
858 for (const auto& track : track_) {
859 eos_status_ = internal::ResetEosStatus(track.type, eos_status_);
860 es_packet_logger_.PrintStoredPacketInfo(
861 internal::ConvertToStreamType(track.type), true);
863 auto op = [this, time]() -> bool {
864 if (!trackrenderer_->Seek(time, current_playback_rate_,
865 current_audio_mute_)) {
870 es_event::Seek event{op};
871 bool ret = state_manager_.ProcessEvent(event);
872 is_seek_done_need_drop = false;
874 if (eventlistener_) {
875 if (internal::IsLowLatencyModeDisableAVSync(low_latency_mode_) ||
876 internal::IsLowLatencyModeDisablePreroll(low_latency_mode_)) {
877 auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
878 eventlistener_, std::placeholders::_1);
879 auto msg = es_msg::Simple::Make(listener, eventlistener_userdata_);
880 std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
881 msg_queue_.push(std::move(msg));
883 msg_task_cv_.notify_one();
886 LOG_DEBUG("%p, [LEAVE] seek end ", this);
890 void EsPlayer::SetAppInfo(const PlayerAppInfo& app_info) {
892 if (state_manager_.GetState() != EsState::kIdle) {
893 LOG_ERROR_P(this, "Invalid State , current %d",
894 state_manager_.GetStateEnum());
897 app_info_ = app_info;
898 trackrenderer_->SetAppInfo(app_info);
899 LOG_INFO("Appid [%s]", app_info.id.c_str());
900 #ifndef TIZEN_FEATURE_PUBLIC
901 CafLogger::SetAppId(app_info.id);
905 void EsPlayer::SetAppInfoEx(const PlayerAppInfoEx& app_info) {
907 if (state_manager_.GetState() != EsState::kIdle) {
908 LOG_ERROR_P(this, "Invalid State , current %d",
909 state_manager_.GetStateEnum());
912 app_info_.id = app_info.id;
913 app_info_.version = app_info.version;
914 app_info_.type = app_info.type;
915 trackrenderer_->SetAppInfoEx(app_info);
916 LOG_INFO("Appid [%s]", app_info_.id.c_str());
917 #ifndef TIZEN_FEATURE_PUBLIC
918 CafLogger::SetAppId(app_info_.id);
922 bool EsPlayer::SetPlaybackRate(const double rate, const bool audio_mute) {
925 if (rate <= 0 || rate > 2.0) {
926 LOG_ERROR_P(this, "Not a valid PlaybackRate");
930 if (state_manager_.GetState() < EsState::kReady) {
931 LOG_ERROR_P(this, "Invalid State , current %d",
932 state_manager_.GetStateEnum());
936 auto op = [this, rate, audio_mute]() -> bool {
937 if (!trackrenderer_->SetPlaybackRate(rate, audio_mute)) {
940 current_playback_rate_ = rate;
941 current_audio_mute_ = audio_mute;
944 es_event::PlaybackRate event{op};
945 return state_manager_.ProcessEvent(event);
951 bool EsPlayer::SetDisplay(const DisplayType& type, void* obj) {
952 if (state_manager_.GetState() != EsState::kIdle) {
953 LOG_ERROR_P(this, "Invalid State , current %d",
954 state_manager_.GetStateEnum());
958 if (mixer_ticket_) mixer_ticket_.reset();
960 return trackrenderer_->SetDisplay(type, obj);
965 bool EsPlayer::SetDisplay(const DisplayType& type, MixerTicket* handle) {
966 if (type == DisplayType::kMixer) {
967 LOG_INFO_P(this, "Create MixerTicket");
968 mixer_ticket_.reset(handle);
969 mixer_ticket_->RegisterListener(mixer_event_listener_.get());
970 if (mixer_ticket_->IsAudioFocusHandler())
971 enable_audio_pipeline_handle_ = false;
972 if (mixer_ticket_->IsRscAllocHandler()) enable_rsc_alloc_handle_ = false;
973 trackrenderer_->SetDisplay(DisplayType::kNone, nullptr);
979 bool EsPlayer::SetDisplay(const DisplayType& type, void* ecore_wl2_window,
980 const int x, const int y, const int w, const int h) {
981 if (state_manager_.GetState() != EsState::kIdle) {
982 LOG_ERROR_P(this, "Invalid State , current %d",
983 state_manager_.GetStateEnum());
987 if (mixer_ticket_) mixer_ticket_.reset();
989 return trackrenderer_->SetDisplay(type, ecore_wl2_window, x, y, w, h);
992 bool EsPlayer::SetDisplaySubsurface(const DisplayType& type,
993 void* ecore_wl2_subsurface, const int x,
994 const int y, const int w, const int h) {
995 if (state_manager_.GetState() != EsState::kIdle) {
996 LOG_ERROR_P(this, "Invalid State , current %d",
997 state_manager_.GetStateEnum());
1001 if (mixer_ticket_) mixer_ticket_.reset();
1003 return trackrenderer_->SetDisplaySubsurface(type, ecore_wl2_subsurface, x, y,
1007 bool EsPlayer::SetDisplay(const DisplayType& type, unsigned int surface_id,
1008 const int x, const int y, const int w, const int h) {
1009 if (state_manager_.GetState() != EsState::kIdle) {
1010 LOG_ERROR_P(this, "Invalid State , current %d",
1011 state_manager_.GetStateEnum());
1015 if (mixer_ticket_) mixer_ticket_.reset();
1017 return trackrenderer_->SetDisplay(type, surface_id, x, y, w, h);
1021 bool EsPlayer::SetDisplayMode(const DisplayMode& mode) {
1022 if (state_manager_.GetState() < EsState::kIdle) {
1023 LOG_ERROR_P(this, "Invalid State , current %d",
1024 state_manager_.GetStateEnum());
1027 trackrenderer_->SetDisplayMode(mode);
1031 bool EsPlayer::SetStretchMode(const int& mode) {
1032 if (state_manager_.GetState() < EsState::kIdle) {
1033 LOG_ERROR_P(this, "Invalid State , current %d",
1034 state_manager_.GetStateEnum());
1037 trackrenderer_->SetStretchMode(mode);
1041 bool EsPlayer::SetDisplayRoi(const Geometry& roi) {
1042 if (state_manager_.GetState() < EsState::kIdle) {
1043 LOG_ERROR_P(this, "Invalid State , current %d",
1044 state_manager_.GetStateEnum());
1048 mixerticket_roi_ = roi;
1049 if (mixer_ticket_) return true;
1051 return trackrenderer_->SetDisplayRoi(roi);
1054 bool EsPlayer::SetVideoRoi(const CropArea& area) {
1055 if (state_manager_.GetState() < EsState::kIdle) {
1056 LOG_ERROR_P(this, "Invalid State , current %d",
1057 state_manager_.GetStateEnum());
1060 return trackrenderer_->SetVideoRoi(area);
1063 bool EsPlayer::ResizeRenderRect(const RenderRect& rect) {
1064 if (state_manager_.GetState() < EsState::kIdle) {
1065 LOG_ERROR_P(this, "Invalid State , current %d",
1066 state_manager_.GetStateEnum());
1069 return trackrenderer_->ResizeRenderRect(rect);
1072 bool EsPlayer::SetDisplayRotate(const DisplayRotation& rotate) {
1073 if (state_manager_.GetState() < EsState::kIdle) {
1074 LOG_ERROR_P(this, "Invalid State , current %d",
1075 state_manager_.GetStateEnum());
1078 return trackrenderer_->SetDisplayRotate(rotate);
1081 bool EsPlayer::GetDisplayRotate(DisplayRotation* rotate) {
1082 if (state_manager_.GetState() < EsState::kIdle) {
1083 LOG_ERROR_P(this, "Invalid State , current %d",
1084 state_manager_.GetStateEnum());
1087 if (trackrenderer_->GetDisplayRotate(rotate)) {
1093 bool EsPlayer::SetDisplayVisible(bool is_visible) {
1094 if (state_manager_.GetState() < EsState::kIdle) {
1095 LOG_ERROR_P(this, "Invalid State , current %d",
1096 state_manager_.GetStateEnum());
1100 if (mixer_ticket_) {
1101 LOG_INFO_P(this, "mixed player is_visible [%d] -> [%d]", is_visible_,
1103 is_visible_ = is_visible;
1107 return trackrenderer_->SetDisplayVisible(is_visible);
1110 bool EsPlayer::SetTrustZoneUse(bool is_using_tz) {
1111 if (state_manager_.GetState() != EsState::kIdle) {
1112 LOG_ERROR_P(this, "Invalid State , current %d",
1113 state_manager_.GetStateEnum());
1116 if (drm_property_.type != drm::Type::kNone) {
1117 LOG_ERROR_P(this, "drm type is already set for sending encrypted packets");
1120 LOG_INFO_P(this, "set trust zone use [%d]", is_using_tz);
1121 drm_property_.external_decryption = is_using_tz;
1123 drm::Property drm_property = drm_property_;
1124 drm_property.type = drm::Type::kPlayready;
1125 trackrenderer_->SetDrm(drm_property);
1129 bool EsPlayer::SetSubmitDataType(SubmitDataType type) {
1130 if (state_manager_.GetState() != EsState::kIdle) {
1131 LOG_ERROR_P(this, "Invalid State , current %d",
1132 state_manager_.GetStateEnum());
1135 LOG_INFO_P(this, "set submit data type [%d]", static_cast<int>(type));
1137 if (type == SubmitDataType::kCleanData) return true;
1138 submit_data_type_ = type;
1139 drm_property_.type = drm::Type::kPlayready;
1140 // TODO: following SubmitDataType, need to set external_decryption
1141 drm_property_.external_decryption = true;
1142 drm::Property drm_property = drm_property_;
1143 trackrenderer_->SetDrm(drm_property);
1147 bool EsPlayer::SetTrack_(const Track& track) {
1149 track_util::ShowTrackInfo(track);
1150 track_.push_back(std::move(track));
1154 bool EsPlayer::ChangeStream_(const Track& track) {
1155 TrackType type = track.type;
1156 if (track_.empty()) return false;
1157 auto has_track = [type](const Track& item) -> bool {
1158 return item.type == type;
1160 std::lock_guard<std::mutex> lk(submit_mutex_);
1161 auto target = std::find_if(track_.begin(), track_.end(), has_track);
1162 if (target == track_.end()) {
1163 LOG_ERROR_P(this, "Add a new stream.");
1167 if (target->active != false) {
1168 LOG_ERROR_P(this, "The track should be deactivated in advance.");
1171 track_.erase(target);
1172 LOG_ERROR_P(this, "previously added %s stream is deleted",
1173 (type == kTrackTypeAudio) ? "audio" : "video");
1174 return SetTrack_(track);
1177 bool EsPlayer::SetStream_(const Track& track) {
1178 TrackType type = track.type;
1179 if (!track_.empty()) {
1180 auto has_track = [type](const Track& item) -> bool {
1181 return item.type == type;
1183 auto target = std::find_if(track_.begin(), track_.end(), has_track);
1184 if (target != track_.end()) {
1185 LOG_ERROR_P(this, "Stream is already exist");
1189 auto op = [this, track]() noexcept {
1190 if (!SetTrack_(track)) {
1196 #ifndef TIZEN_FEATURE_PUBLIC
1197 CafLogger::LogMessage(CafEventType::kStreamReady, caf_unique_number);
1200 es_event::SetStream event{op};
1201 return state_manager_.ProcessEvent(event);
1204 bool EsPlayer::SetStream(const AudioStreamPtr& stream) {
1207 BOOST_SCOPE_EXIT(&ret, &stream, &force_audio_swdecoder_use_) {
1209 // when force_audio_swdecoder_use_ is already true, ignore stream setting.
1210 // otherwise, it can be true according to the stream setting
1211 force_audio_swdecoder_use_ =
1212 force_audio_swdecoder_use_ || stream->GetForceSwDecoderUse();
1214 BOOST_SCOPE_EXIT_END
1215 if (state_manager_.GetState() < EsState::kIdle) {
1216 LOG_ERROR_P(this, "Invalid State , current %d",
1217 state_manager_.GetStateEnum());
1220 Track track = stream->GetTrack_();
1221 if (state_manager_.GetState() >= EsState::kReady) {
1222 if (is_audio_stream_info_frozen_) {
1223 LOG_ERROR_P(this, "can't change audio stream in audio deactivate mode");
1226 track.active = false;
1227 ret = ChangeStream_(track);
1230 ret = SetStream_(track);
1234 bool EsPlayer::SetStream(const VideoStreamPtr& stream) {
1236 if (state_manager_.GetState() < EsState::kIdle) {
1237 LOG_ERROR_P(this, "Invalid State , current %d",
1238 state_manager_.GetStateEnum());
1241 Track track = stream->GetTrack_();
1242 if (state_manager_.GetState() >= EsState::kReady) {
1243 track.active = false;
1244 return ChangeStream_(track);
1246 return SetStream_(track);
1249 bool EsPlayer::SwitchAudioStreamOnTheFly(const AudioStreamPtr& stream) {
1251 if (state_manager_.GetState() < EsState::kReady) {
1252 LOG_ERROR_P(this, "Invalid State , current %d",
1253 state_manager_.GetStateEnum());
1256 Track track = stream->GetTrack_();
1258 if (!internal::IsAvailableCodecSwitch(track)) {
1259 LOG_ERROR_P(this, "Invalid new mimetype [%s][%d]", track.mimetype.c_str(),
1263 for (auto& old_track : track_) {
1264 if (old_track.type == TrackType::kTrackTypeAudio) {
1265 if (!internal::IsAvailableCodecSwitch(old_track)) {
1266 LOG_ERROR_P(this, "Invalid previous mimetype [%s][%d]",
1267 old_track.mimetype.c_str(), old_track.version);
1270 if (!Flush(StreamType::kAudio)) return false;
1271 old_track.active = false;
1275 if (!ChangeStream_(track)) return false;
1277 trackrenderer_->SetTrack(track_);
1281 bool EsPlayer::SetAdvancedPictureQualityType(const AdvPictureQualityType type) {
1283 if (state_manager_.GetState() != EsState::kIdle) {
1284 LOG_ERROR_P(this, "Invalid State , current %d",
1285 state_manager_.GetStateEnum());
1288 trackrenderer_->SetAdvancedPictureQualityType(type);
1292 bool EsPlayer::SetResourceAllocatePolicy(const RscAllocPolicy policy) {
1294 if (state_manager_.GetState() != EsState::kIdle) {
1295 LOG_ERROR_P(this, "Invalid State , current %d",
1296 state_manager_.GetStateEnum());
1299 resource_alloc_policy_ = policy;
1300 trackrenderer_->SetResourceAllocatePolicy(policy);
1305 GetDecodedVideoFrameStatus EsPlayer::GetDecodedPacket(
1306 DecodedVideoPacket& packet) {
1307 if (state_manager_.GetState() < EsState::kReady) {
1308 LOG_ERROR_P(this, "Invalid State , current %d",
1309 state_manager_.GetStateEnum());
1310 return GetDecodedVideoFrameStatus::kUnknown;
1312 return trackrenderer_->GetDecodedPacket(packet);
1315 bool EsPlayer::ReturnDecodedPacket(const DecodedVideoPacket& packet) {
1316 if (state_manager_.GetState() < EsState::kReady) {
1317 LOG_ERROR_P(this, "Invalid State , current %d",
1318 state_manager_.GetStateEnum());
1321 return trackrenderer_->ReturnDecodedPacket(packet);
1325 void EsPlayer::ResetContextForClose_() {
1326 internal::ResetDrmProperty(drm_property_);
1328 submit_data_type_ = SubmitDataType::kCleanData;
1329 low_latency_mode_ = 0;
1330 resume_time_.is_set = false;
1331 video_frame_peek_mode_ = 0;
1332 unlimited_max_buffer_mode_ = 0;
1334 audio_codec_type_ = kPlayerAudioCodecTypeHW;
1335 video_codec_type_ = kPlayerVideoCodecTypeHW;
1336 is_resource_conflicted_ = false;
1337 app_info_ = PlayerAppInfo();
1338 src_queue_size_ = SrcQueueSize();
1339 is_msg_task_stop_ = false;
1342 void EsPlayer::ResetContextForStop_() {
1343 for (int i = 0; i < kTrackTypeMax; ++i) {
1344 need_data_[i].mask = kNeedDataMaskNone;
1345 need_data_[i].seek_offset = 0;
1348 std::lock_guard<std::mutex> lock(eos_mutex_);
1349 eos_status_ = EosStatus::kAllEos;
1351 current_playback_rate_ = 1.0;
1352 current_audio_mute_ = false;
1355 void EsPlayer::GetSrcQueueCurrentSize_(const TrackType& type,
1356 uint64_t* byte_size,
1357 uint64_t* time_size) {
1358 boost::any byte_size_, time_size_;
1359 if (type == TrackType::kTrackTypeVideo) {
1360 trackrenderer_->GetAttribute(
1361 TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelByte,
1363 trackrenderer_->GetAttribute(
1364 TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
1366 } else if (type == TrackType::kTrackTypeAudio) {
1367 trackrenderer_->GetAttribute(
1368 TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
1370 trackrenderer_->GetAttribute(
1371 TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
1375 *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
1376 *time_size = boost::any_cast<std::uint64_t>(time_size_);
1377 if (time_unit_type == kPlayerTimeUnitTypeMs)
1378 *time_size = util::ConvertNsToMs(*time_size);
1379 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1380 *time_size = util::ConvertNsToUs(*time_size);
1383 GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
1384 MakeBufferStatus* status) {
1385 std::shared_ptr<char> buffer = packet->GetBuffer();
1386 uint32_t size = packet->GetSize();
1387 if (packet->IsEosPacket()) {
1388 *status = MakeBufferStatus::kEos;
1391 GstBuffer* gstbuffer = gst_buffer_new_and_alloc(size);
1393 *status = MakeBufferStatus::kOutOfMemory;
1396 if (buffer != nullptr) {
1398 gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
1399 memcpy(map.data, buffer.get(), size);
1400 gst_buffer_unmap(gstbuffer, &map);
1403 uint64_t pts = packet->GetPts();
1404 uint64_t duration = packet->GetDuration();
1405 /* if pts or duration are -1(=GST_CLOCK_TIME_NONE), some of the elements don't
1406 * adjust the buffer. */
1407 if (time_unit_type == kPlayerTimeUnitTypeMs) {
1408 GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1409 ? GST_CLOCK_TIME_NONE
1410 : (GstClockTime)util::ConvertMsToNs(pts);
1411 GST_BUFFER_DURATION(gstbuffer) =
1412 (duration == GST_CLOCK_TIME_NONE)
1413 ? GST_CLOCK_TIME_NONE
1414 : (GstClockTime)util::ConvertMsToNs(duration);
1415 } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1416 GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1417 ? GST_CLOCK_TIME_NONE
1418 : (GstClockTime)util::ConvertUsToNs(pts);
1419 GST_BUFFER_DURATION(gstbuffer) =
1420 (duration == GST_CLOCK_TIME_NONE)
1421 ? GST_CLOCK_TIME_NONE
1422 : (GstClockTime)util::ConvertUsToNs(duration);
1424 uint32_t hdr10p_size = packet->GetHdr10pSize();
1425 std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
1427 if (hdr10p_size > 0 && hdr10p_metadata != nullptr) {
1428 guint32* blockadditional_size = (guint32*)g_malloc(sizeof(uint32_t));
1429 *blockadditional_size = hdr10p_size;
1430 gst_mini_object_set_qdata(
1431 GST_MINI_OBJECT(gstbuffer),
1432 g_quark_from_static_string("matroska_blockadditional_size"),
1433 blockadditional_size, g_free);
1435 /* blockadditiona_data : the data sent to omx, size (4 bytes) + metadata */
1436 guint8* blockadditional_data =
1437 (guint8*)g_malloc(((*blockadditional_size) + 4) * sizeof(guint8));
1438 memcpy(blockadditional_data, blockadditional_size, sizeof(uint32_t));
1439 memcpy(blockadditional_data + 4, hdr10p_metadata.get(),
1440 (*blockadditional_size));
1441 gst_mini_object_set_qdata(
1442 GST_MINI_OBJECT(gstbuffer),
1443 g_quark_from_static_string("matroska_blockadditional_info"),
1444 blockadditional_data, g_free);
1446 *status = MakeBufferStatus::kSuccess;
1450 PacketSubmitStatus EsPlayer::SubmitEosPacket_(const TrackType& type) {
1451 PacketSubmitStatus submitstate = PacketSubmitStatus::kSuccess;
1453 std::lock_guard<std::mutex> lock(eos_mutex_);
1455 case kTrackTypeAudio:
1456 eos_status_ |= EosStatus::kAudioEos;
1458 case kTrackTypeVideo:
1459 eos_status_ |= EosStatus::kVideoEos;
1464 if (eos_status_ != EosStatus::kAllEos) {
1468 for (int tracktype = kTrackTypeAudio; tracktype < kTrackTypeMax;
1471 DecoderInputBuffer::Create(static_cast<TrackType>(tracktype));
1472 if (!trackrenderer_->SubmitPacket2(inbuffer, nullptr)) {
1473 std::lock_guard<std::mutex> lock(eos_mutex_);
1474 eos_status_ = EosStatus::kAllEos;
1475 submitstate = PacketSubmitStatus::kNotPrepared;
1482 void EsPlayer::UnsetTzQdata_(const DecoderInputBufferPtr& buffer) {
1483 const GstBuffer* gstbuf = buffer->Get();
1484 if (!gstbuf) return;
1485 GstStructure* tzqdata = GST_STRUCTURE(gst_mini_object_steal_qdata(
1486 GST_MINI_OBJECT(gstbuf), g_quark_from_static_string("GstTzHandleData")));
1487 if (tzqdata) gst_structure_free(tzqdata);
1490 PacketSubmitStatus EsPlayer::SubmitDecoderInputBuffer_(
1491 const DecoderInputBufferPtr& buffer) {
1492 PacketSubmitStatus status = PacketSubmitStatus::kSuccess;
1493 TrackRendererAdapter::SubmitStatus submitstate =
1494 TrackRendererAdapter::SubmitStatus::kSuccess;
1495 trackrenderer_->SubmitPacket2(buffer, &submitstate);
1497 switch (submitstate) {
1498 case TrackRendererAdapter::SubmitStatus::kSuccess:
1499 case TrackRendererAdapter::SubmitStatus::kDrop:
1500 status = PacketSubmitStatus::kSuccess;
1502 case TrackRendererAdapter::SubmitStatus::kFull:
1503 UnsetTzQdata_(buffer);
1504 trackrenderer_event_listener_->OnBufferStatus(buffer->GetType(),
1505 BufferStatus::kOverrun);
1506 status = PacketSubmitStatus::kFull;
1509 UnsetTzQdata_(buffer);
1510 status = PacketSubmitStatus::kNotPrepared;
1517 void EsPlayer::MakeGstBufferForTzHandle_(GstBuffer* gstbuffer,
1518 const TrackType& type,
1519 const uint32_t& tz_handle,
1520 const uint32_t& packet_size) {
1521 GstStructure* gst_tz_handle_data_structure =
1522 gst_structure_new("GstTzHandleData", "packet_handle", G_TYPE_UINT,
1523 static_cast<guint32>(tz_handle), "packet_size",
1524 G_TYPE_UINT, static_cast<guint32>(packet_size),
1525 "secure", G_TYPE_BOOLEAN, true, nullptr);
1526 gst_mini_object_set_qdata(
1527 GST_MINI_OBJECT(gstbuffer), g_quark_from_string("GstTzHandleData"),
1528 gst_tz_handle_data_structure, (GDestroyNotify)gst_structure_free);
1530 if (type == kTrackTypeAudio) {
1532 bool has_active_audio_track =
1533 track_util::GetActiveTrack(track_, kTrackTypeAudio, &audio_track);
1534 if (has_active_audio_track) {
1535 GstStructure* audio_info_structure =
1536 gst_structure_new("AudioInfo", "mime_type", G_TYPE_STRING,
1537 audio_track.mimetype.c_str(), nullptr);
1538 gst_mini_object_set_qdata(
1539 GST_MINI_OBJECT(gstbuffer), g_quark_from_string("AudioInfo"),
1540 audio_info_structure, (GDestroyNotify)gst_structure_free);
1545 void EsPlayer::MakeGstBufferForEncryptedPacket_(
1546 GstBuffer* gstbuffer, const EsPacketPtr& packet,
1547 const drm::EsPlayerEncryptedInfo& drm_info) {
1548 if (drm_info.handle == 0) return;
1549 auto serialized_drm_info_ptr = esplayer_drm::Serialize(packet, drm_info);
1550 GstStructure* gst_drm_info_structure =
1551 gst_structure_new("drm_info", "drm_specific_info", G_TYPE_BYTES,
1552 serialized_drm_info_ptr.get(), nullptr);
1553 if (gst_drm_info_structure) {
1554 gst_mini_object_set_qdata(
1555 GST_MINI_OBJECT(gstbuffer), g_quark_from_static_string("drm_info"),
1556 gst_drm_info_structure, (GDestroyNotify)gst_structure_free);
1561 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
1562 SubmitPacketOperator op) {
1563 if (state_manager_.GetState() < EsState::kIdle) {
1564 return PacketSubmitStatus::kNotPrepared;
1566 if (!packet) return PacketSubmitStatus::kInvalidPacket;
1568 TrackType type = static_cast<TrackType>(packet->GetType());
1569 Track activated_track;
1570 if (!track_util::GetActiveTrack(track_, type, &activated_track))
1571 return PacketSubmitStatus::kInvalidPacket;
1573 if (state_manager_.GetState() == EsState::kPaused ||
1574 state_manager_.GetState() == EsState::kReady) {
1575 internal::AppsrcQueueSizeOption byte_based, time_based;
1577 case kTrackTypeAudio:
1578 byte_based.max_size = src_queue_size_.kMaxByteOfAudioSrcQueue;
1579 time_based.max_size = src_queue_size_.kMaxTimeOfAudioSrcQueue;
1580 byte_based.threshold = src_queue_size_.kMinByteThresholdOfAudioSrcQueue;
1581 time_based.threshold = src_queue_size_.kMinTimeThresholdOfAudioSrcQueue;
1583 case kTrackTypeVideo:
1584 byte_based.max_size = src_queue_size_.kMaxByteOfVideoSrcQueue;
1585 time_based.max_size = src_queue_size_.kMaxTimeOfVideoSrcQueue;
1586 byte_based.threshold = src_queue_size_.kMinByteThresholdOfVideoSrcQueue;
1587 time_based.threshold = src_queue_size_.kMinTimeThresholdOfVideoSrcQueue;
1592 GetSrcQueueCurrentSize_(type, &(byte_based.current_size),
1593 &(time_based.current_size));
1594 if (internal::IsUnderRun(byte_based, time_based))
1595 trackrenderer_event_listener_->OnBufferStatus(type,
1596 BufferStatus::kUnderrun);
1599 es_packet_logger_.StorePacketInfo(packet);
1600 es_packet_logger_.PrintStoredPacketInfo(packet->GetType());
1602 MakeBufferStatus make_buffer_status;
1603 GstBuffer* gstbuffer = GetGstBuffer_(packet, &make_buffer_status);
1605 if (make_buffer_status == MakeBufferStatus::kEos)
1606 return SubmitEosPacket_(type);
1607 else if (make_buffer_status == MakeBufferStatus::kOutOfMemory)
1608 return PacketSubmitStatus::kOutOfMemory;
1610 if (op != nullptr) {
1611 PacketSubmitStatus op_status = op(gstbuffer);
1612 if (op_status != PacketSubmitStatus::kSuccess) {
1617 auto inbuffer = DecoderInputBuffer::Create(type, 0, gstbuffer);
1618 gst_buffer_unref(gstbuffer);
1620 if (packet->HasMatroskaColorInfo()) {
1621 std::string color_info_str =
1622 util::GetStringFromMatroskaColor(packet->GetMatroskaColorInfo());
1623 if (trackrenderer_->SetMatroskaColorInfo(color_info_str) == false)
1624 return PacketSubmitStatus::kNotPrepared;
1627 return SubmitDecoderInputBuffer_(inbuffer);
1630 PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
1631 std::lock_guard<std::mutex> lk(submit_mutex_);
1632 return SubmitPacketCommon_(packet, nullptr);
1636 PacketSubmitStatus EsPlayer::SubmitTrustZonePacket(const EsPacketPtr& packet,
1637 uint32_t tz_handle) {
1638 std::lock_guard<std::mutex> lk(submit_mutex_);
1639 if (submit_data_type_ != SubmitDataType::kTrustZoneData)
1640 return PacketSubmitStatus::kInvalidPacket;
1641 auto submitpacket_op = [this, &tz_handle,
1642 &packet](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1643 if (tz_handle > 0) {
1644 TrackType type = static_cast<TrackType>(packet->GetType());
1645 uint32_t packet_size = packet->GetSize();
1646 MakeGstBufferForTzHandle_(gstbuffer, type, tz_handle, packet_size);
1648 return PacketSubmitStatus::kSuccess;
1650 return SubmitPacketCommon_(packet, submitpacket_op);
1653 PacketSubmitStatus EsPlayer::SubmitEncryptedPacket(
1654 const EsPacketPtr& packet, const drm::EsPlayerEncryptedInfo& drm_info) {
1655 std::lock_guard<std::mutex> lk(submit_mutex_);
1656 if (submit_data_type_ != SubmitDataType::kEncryptedData)
1657 return PacketSubmitStatus::kInvalidPacket;
1658 auto submitpacket_op =
1659 [this, &packet, &drm_info](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1660 MakeGstBufferForEncryptedPacket_(gstbuffer, packet, drm_info);
1661 return PacketSubmitStatus::kSuccess;
1663 return SubmitPacketCommon_(packet, submitpacket_op);
1667 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
1669 bool EsPlayer::GetPlayingTime(uint64_t* time) {
1670 if (!time) return false;
1671 if (state_manager_.GetState() <= EsState::kReady) {
1675 return trackrenderer_->GetPlayingTime(time);
1678 bool EsPlayer::SetAudioMute(bool is_mute) {
1679 if (state_manager_.GetState() < EsState::kIdle) {
1680 LOG_ERROR_P(this, "Invalid State , current %d",
1681 state_manager_.GetStateEnum());
1684 return trackrenderer_->SetAudioMute(is_mute);
1687 bool EsPlayer::SetVideoFrameBufferType(DecodedVideoFrameBufferType type) {
1688 if ((state_manager_.GetState() != EsState::kIdle &&
1689 type != DecodedVideoFrameBufferType::kScale) ||
1690 (state_manager_.GetState() < EsState::kIdle &&
1691 type == DecodedVideoFrameBufferType::kScale)) {
1692 LOG_ERROR_P(this, "Invalid State , current %d",
1693 state_manager_.GetStateEnum());
1696 if (type == DecodedVideoFrameBufferType::kScale &&
1697 video_codec_type_ == kPlayerVideoCodecTypeSW) {
1698 LOG_ERROR_P(this, "kScale is not supportted when using sw video decoder");
1701 trackrenderer_->SetVideoFrameBufferType(
1702 VideoFrameTypeStrategyPtr(new DefaultVideoFrameTypeStrategy(type)));
1703 vidoe_frame_buffer_type_ = type;
1707 bool EsPlayer::SetVideoFrameBufferScaleResolution(
1708 const uint32_t& target_width, const uint32_t& target_height) {
1709 if (state_manager_.GetState() < EsState::kIdle) {
1710 LOG_ERROR_P(this, "Invalid State , current %d",
1711 state_manager_.GetStateEnum());
1715 return trackrenderer_->SetVideoFrameBufferScaleResolution(target_width,
1719 bool EsPlayer::SetDecodedVideoFrameRate(const Rational& request_framerate) {
1720 if (state_manager_.GetState() < EsState::kIdle) {
1721 LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
1725 return trackrenderer_->SetDecodedVideoFrameRate(request_framerate);
1728 void EsPlayer::RegisterListener(EsEventListener* listener,
1729 EsEventListener::UserData userdata) {
1730 // assert(listener); // allow unregister by setting nullptr
1731 assert(!eventlistener_);
1732 eventlistener_ = listener;
1733 eventlistener_userdata_ = userdata;
1736 bool EsPlayer::GetAdaptiveInfo(void* padaptive_info,
1737 const PlayerAdaptiveInfo& adaptive_type) {
1738 if (!padaptive_info || adaptive_type <= PlayerAdaptiveInfo::kMinType ||
1739 adaptive_type >= PlayerAdaptiveInfo::kMaxType)
1741 switch (adaptive_type) {
1742 case PlayerAdaptiveInfo::kVideoDroppedFrames:
1743 if (state_manager_.GetState() < EsState::kReady) {
1744 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1747 return trackrenderer_->GetDroppedFrames(padaptive_info);
1748 case PlayerAdaptiveInfo::kDroppedVideoFramesForCatchup:
1749 if (state_manager_.GetState() < EsState::kReady) {
1750 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1753 return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeVideo,
1755 case PlayerAdaptiveInfo::kDroppedAudioFramesForCatchup:
1756 if (state_manager_.GetState() < EsState::kReady) {
1757 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1760 return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeAudio,
1768 bool EsPlayer::SetVolume(const int& volume) {
1769 if (volume < internal::kVolumeMin || volume > internal::kVolumeMax) {
1770 LOG_ERROR_P(this, "Invalid volume level %d", volume);
1773 if (state_manager_.GetState() < EsState::kIdle) {
1774 LOG_ERROR_P(this, "Invalid State , current %d",
1775 state_manager_.GetStateEnum());
1778 return trackrenderer_->SetVolume(volume);
1781 bool EsPlayer::GetVolume(int* volume) {
1782 if (state_manager_.GetState() < EsState::kIdle) {
1783 LOG_ERROR_P(this, "Invalid State , current %d",
1784 state_manager_.GetStateEnum());
1787 return trackrenderer_->GetVolume(volume);
1790 bool EsPlayer::Flush(const StreamType& type) {
1791 if (state_manager_.GetState() <= EsState::kIdle) {
1792 LOG_ERROR_P(this, "Invalid State , current %d",
1793 state_manager_.GetStateEnum());
1797 internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
1798 es_packet_logger_.ResetLog(type);
1799 return trackrenderer_->Flush(type);
1802 bool EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
1803 TrackType track_type = kTrackTypeMax;
1805 case BufferOption::kBufferAudioMaxByteSize: /* FALL THROUGH */
1806 case BufferOption::kBufferAudioMinByteThreshold: /* FALL THROUGH */
1807 case BufferOption::kBufferAudioMaxTimeSize: /* FALL THROUGH */
1808 case BufferOption::kBufferAudioMinTimeThreshold:
1809 track_type = kTrackTypeAudio;
1811 case BufferOption::kBufferVideoMaxByteSize: /* FALL THROUGH */
1812 case BufferOption::kBufferVideoMinByteThreshold: /* FALL THROUGH */
1813 case BufferOption::kBufferVideoMaxTimeSize: /* FALL THROUGH */
1814 case BufferOption::kBufferVideoMinTimeThreshold:
1815 track_type = kTrackTypeVideo;
1820 if (track_type == kTrackTypeMax) {
1821 LOG_ERROR_P(this, "Invalid option!!!");
1825 Track activated_track;
1827 track_util::GetActiveTrack(track_, track_type, &activated_track);
1828 EsState state = state_manager_.GetState();
1829 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_activated)) {
1830 LOG_ERROR_P(this, "Invalid State [state:%d] or stream is activated [%d],",
1831 state_manager_.GetStateEnum(), is_activated);
1836 case BufferOption::kBufferAudioMaxByteSize:
1837 src_queue_size_.kMaxByteOfAudioSrcQueue = size;
1839 case BufferOption::kBufferVideoMaxByteSize:
1840 src_queue_size_.kMaxByteOfVideoSrcQueue = size;
1842 case BufferOption::kBufferAudioMinByteThreshold:
1843 src_queue_size_.kMinByteThresholdOfAudioSrcQueue =
1844 static_cast<uint32_t>(size);
1846 case BufferOption::kBufferVideoMinByteThreshold:
1847 src_queue_size_.kMinByteThresholdOfVideoSrcQueue =
1848 static_cast<uint32_t>(size);
1850 case BufferOption::kBufferAudioMaxTimeSize:
1851 src_queue_size_.kMaxTimeOfAudioSrcQueue = size;
1853 case BufferOption::kBufferVideoMaxTimeSize:
1854 src_queue_size_.kMaxTimeOfVideoSrcQueue = size;
1856 case BufferOption::kBufferAudioMinTimeThreshold:
1857 src_queue_size_.kMinTimeThresholdOfAudioSrcQueue =
1858 static_cast<uint32_t>(size);
1860 case BufferOption::kBufferVideoMinTimeThreshold:
1861 src_queue_size_.kMinTimeThresholdOfVideoSrcQueue =
1862 static_cast<uint32_t>(size);
1865 LOG_ERROR_P(this, "Invalid option!!!");
1871 bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
1872 if (state_manager_.GetState() != EsState::kIdle) {
1873 LOG_ERROR_P(this, "Invalid State , current %d",
1874 state_manager_.GetStateEnum());
1877 if (true == internal::IsExclusiveLowLatencyMode(low_latency_mode_, mode)) {
1878 LOG_ERROR_P(this, "Invalid Mode , current 0x%x, set 0x%x",
1879 static_cast<std::uint32_t>(low_latency_mode_),
1880 static_cast<std::uint32_t>(mode));
1883 low_latency_mode_ |= static_cast<std::uint32_t>(mode);
1887 bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
1888 if (state_manager_.GetState() < EsState::kReady) {
1889 LOG_ERROR_P(this, "Invalid State , current %d",
1890 state_manager_.GetStateEnum());
1893 if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1895 "low latency mode have to be set except disable_sync mode");
1898 std::int64_t ns_unit = 0;
1899 if (time_unit_type == kPlayerTimeUnitTypeMs)
1901 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1903 if ((offset * ns_unit > G_MAXINT64) || (offset * ns_unit < G_MININT64)) {
1904 LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
1905 "] * 1000000 < G_MAXINT64",
1909 if (type == StreamType::kMax) return false;
1910 if (time_unit_type == kPlayerTimeUnitTypeMs) {
1911 if (type == StreamType::kAudio)
1912 trackrenderer_->SetAttribute(
1913 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1914 util::ConvertMsToNs(offset));
1915 else if (type == StreamType::kVideo)
1916 trackrenderer_->SetAttribute(
1917 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1918 util::ConvertMsToNs(offset));
1919 } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1920 if (type == StreamType::kAudio)
1921 trackrenderer_->SetAttribute(
1922 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1923 util::ConvertUsToNs(offset));
1924 else if (type == StreamType::kVideo)
1925 trackrenderer_->SetAttribute(
1926 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1927 util::ConvertUsToNs(offset));
1932 bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
1933 if (state_manager_.GetState() < EsState::kReady) {
1934 LOG_ERROR_P(this, "Invalid State , current %d",
1935 state_manager_.GetStateEnum());
1938 if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1939 LOG_ERROR_P(this, "low latency mode have to be set");
1942 if (type == StreamType::kMax) return false;
1944 if (type == StreamType::kAudio)
1945 trackrenderer_->GetAttribute(
1946 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
1947 else if (type == StreamType::kVideo)
1948 trackrenderer_->GetAttribute(
1949 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
1951 *offset = boost::any_cast<std::int64_t>(off_set);
1952 if (time_unit_type == kPlayerTimeUnitTypeMs)
1953 *offset = util::ConvertNsToMs(*offset);
1954 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1955 *offset = util::ConvertNsToUs(*offset);
1959 bool EsPlayer::SetVideoFramePeekMode() {
1960 if (state_manager_.GetState() != EsState::kIdle) {
1961 LOG_ERROR_P(this, "Invalid State , current %d",
1962 state_manager_.GetStateEnum());
1965 constexpr std::uint32_t peek_mode_on = 1;
1966 video_frame_peek_mode_ = peek_mode_on;
1970 bool EsPlayer::RenderVideoFrame() {
1971 if (!video_frame_peek_mode_) return false;
1972 if (state_manager_.GetState() == EsState::kReady ||
1973 state_manager_.GetState() == EsState::kPaused) {
1974 trackrenderer_->RenderVideoFrame();
1977 LOG_ERROR_P(this, "Invalid State , current %d",
1978 state_manager_.GetStateEnum());
1982 bool EsPlayer::SetUnlimitedMaxBufferMode() {
1983 if (state_manager_.GetState() != EsState::kIdle) {
1984 LOG_ERROR_P(this, "Invalid State , current %d",
1985 state_manager_.GetStateEnum());
1988 constexpr std::uint32_t unlimited_max_buffer_mode_on = 1;
1989 unlimited_max_buffer_mode_ = unlimited_max_buffer_mode_on;
1993 ErrorType EsPlayer::SetFmmMode() {
1994 EsState state = state_manager_.GetState();
1996 if (state < EsState::kIdle) {
1997 LOG_ERROR_P(this, "Invalid State , current %d",
1998 state_manager_.GetStateEnum());
1999 return ErrorType::kInvalidState;
2003 ErrorType ret = ErrorType::kNone;
2004 if (trackrenderer_->GetFmmAutoMode(&onoff) == false) {
2005 return ErrorType::kInvalidOperation;
2013 if (onoff == FMM_AUTO_OFF) ret = ErrorType::kInvalidOperation;
2015 fmm_mode_ = FMM_AUTO_ON;
2017 if (state < EsState::kReady) return ret;
2019 trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
2024 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
2025 Track activated_track;
2027 track_util::GetActiveTrack(track_, kTrackTypeAudio, &activated_track);
2028 EsState state = state_manager_.GetState();
2029 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2031 "Invalid State [state:%d] or audio stream already exists[%d],",
2032 state_manager_.GetStateEnum(), is_existed);
2035 if (force_audio_swdecoder_use_ && type == kPlayerAudioCodecTypeHW) {
2036 LOG_ERROR_P(this, "Not support hw decoder");
2039 LOG_INFO_P(this, "PlayerAudioCodecType [%s]",
2040 (type == kPlayerAudioCodecTypeHW) ? "hardware" : "software");
2041 audio_codec_type_ = type;
2045 bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
2046 Track activated_track;
2048 track_util::GetActiveTrack(track_, kTrackTypeVideo, &activated_track);
2049 EsState state = state_manager_.GetState();
2050 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2052 "Invalid State [state:%d] or video stream already exists[%d],",
2053 state_manager_.GetStateEnum(), is_existed);
2056 if (force_video_swdecoder_use_ &&
2057 (type == kPlayerVideoCodecTypeHW ||
2058 type == kPlayerVideoCodecTypeHWNdecoding)) {
2059 LOG_ERROR_P(this, "Not support hw decoder");
2062 if (type == kPlayerVideoCodecTypeSW &&
2063 vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
2065 "sw video decoder is not supportted when video frame buffer "
2070 if (!enable_rsc_alloc_handle_) {
2071 LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2074 if (type == kPlayerVideoCodecTypeHWNdecoding) {
2075 LOG_INFO_P(this, "PlayerVideoCodecType HW N-decoding");
2076 video_decoding_mode_ = internal::kNdecodingMode;
2080 LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
2081 (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
2082 video_codec_type_ = type;
2086 bool EsPlayer::SetAiFilter(void* aifilter) {
2087 if (state_manager_.GetState() != EsState::kIdle) {
2088 LOG_ERROR_P(this, "Invalid State , current %d",
2089 state_manager_.GetStateEnum());
2092 trackrenderer_->SetAiFilter(aifilter);
2096 bool EsPlayer::InitAudioEasingInfo(const uint32_t init_volume,
2097 const uint32_t init_elapsed_time,
2098 const AudioEasingInfo& easing_info) {
2099 if (init_volume > internal::kVolumeMax ||
2100 easing_info.target_volume > internal::kVolumeMax) {
2101 LOG_ERROR_P(this, "Invalid volume: init [%d] target [%d]", init_volume,
2102 easing_info.target_volume);
2105 if (state_manager_.GetState() < EsState::kIdle) {
2106 LOG_ERROR_P(this, "Invalid State , current %d",
2107 state_manager_.GetStateEnum());
2110 return trackrenderer_->InitAudioEasingInfo(init_volume, init_elapsed_time,
2114 bool EsPlayer::UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) {
2115 if (easing_info.target_volume > internal::kVolumeMax) {
2116 LOG_ERROR_P(this, "Invalid volume level %d", easing_info.target_volume);
2119 if (state_manager_.GetState() < EsState::kIdle) {
2120 LOG_ERROR_P(this, "Invalid State , current %d",
2121 state_manager_.GetStateEnum());
2124 return trackrenderer_->UpdateAudioEasingInfo(easing_info);
2127 bool EsPlayer::GetAudioEasingInfo(uint32_t* current_volume,
2128 uint32_t* elapsed_time,
2129 AudioEasingInfo* easing_info) {
2130 if (state_manager_.GetState() < EsState::kIdle) {
2131 LOG_ERROR_P(this, "Invalid State , current %d",
2132 state_manager_.GetStateEnum());
2135 return trackrenderer_->GetAudioEasingInfo(current_volume, elapsed_time,
2139 bool EsPlayer::StartAudioEasing() {
2140 if (state_manager_.GetState() < EsState::kReady) {
2141 LOG_ERROR_P(this, "Invalid State , current %d",
2142 state_manager_.GetStateEnum());
2145 return trackrenderer_->StartAudioEasing();
2148 bool EsPlayer::StopAudioEasing() {
2149 if (state_manager_.GetState() < EsState::kIdle) {
2150 LOG_ERROR_P(this, "Invalid State , current %d",
2151 state_manager_.GetStateEnum());
2154 return trackrenderer_->StopAudioEasing();
2157 bool EsPlayer::SetAlternativeVideoResource(unsigned int rsc_type) {
2158 if (state_manager_.GetState() == EsState::kNone) {
2159 LOG_ERROR_P(this, "Invalid State");
2163 if (!enable_rsc_alloc_handle_) {
2164 LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2168 if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2170 "has set resource allocate policy, the alternative "
2171 "resource setting will be wrong");
2174 alternative_video_resource_ = static_cast<std::uint32_t>(rsc_type);
2178 bool EsPlayer::SetAlternativeAudioResource(
2179 const PlayerAudioResourceType rsc_type) {
2180 if (state_manager_.GetState() == EsState::kNone) {
2181 LOG_ERROR_P(this, "Invalid State");
2185 if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2187 "has set resource allocate policy, the alternative "
2188 "resource setting will be wrong");
2191 return trackrenderer_->SetAlternativeAudioResource(rsc_type);
2194 bool EsPlayer::SetCatchUpSpeed(const CatchUpSpeed& level) {
2195 if (state_manager_.GetState() < EsState::kIdle) {
2196 LOG_ERROR_P(this, "Invalid State , current %d",
2197 state_manager_.GetStateEnum());
2201 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2202 LOG_ERROR_P(this, "Do not set low latency mode, current[0x%x]",
2203 static_cast<std::uint32_t>(low_latency_mode_));
2207 if (trackrenderer_->SetCatchUpSpeed(level)) {
2213 bool EsPlayer::GetVideoLatencyStatus(LatencyStatus* status) {
2214 if (state_manager_.GetState() < EsState::kReady) {
2215 LOG_ERROR_P(this, "Invalid State , current %d",
2216 state_manager_.GetStateEnum());
2220 if (trackrenderer_->GetVideoLatencyStatus(status)) {
2226 bool EsPlayer::GetAudioLatencyStatus(LatencyStatus* status) {
2227 if (state_manager_.GetState() < EsState::kReady) {
2228 LOG_ERROR_P(this, "Invalid State , current %d",
2229 state_manager_.GetStateEnum());
2233 if (trackrenderer_->GetAudioLatencyStatus(status)) {
2239 bool EsPlayer::SetVideoMidLatencyThreshold(const unsigned int threshold) {
2240 if (state_manager_.GetState() < EsState::kIdle) {
2241 LOG_ERROR_P(this, "Invalid State , current %d",
2242 state_manager_.GetStateEnum());
2246 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2247 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2248 static_cast<std::uint32_t>(low_latency_mode_));
2252 LOG_INFO_P(this, "video_mid_latency_threshold : [%u]", threshold);
2254 trackrenderer_->SetVideoMidLatencyThreshold(threshold);
2258 bool EsPlayer::SetAudioMidLatencyThreshold(const unsigned int threshold) {
2259 if (state_manager_.GetState() < EsState::kIdle) {
2260 LOG_ERROR_P(this, "Invalid State , current %d",
2261 state_manager_.GetStateEnum());
2265 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2266 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2267 static_cast<std::uint32_t>(low_latency_mode_));
2271 LOG_INFO_P(this, "audio_mid_latency_threshold : [%u]", threshold);
2273 trackrenderer_->SetAudioMidLatencyThreshold(threshold);
2277 bool EsPlayer::SetVideoHighLatencyThreshold(const unsigned int threshold) {
2278 if (state_manager_.GetState() < EsState::kIdle) {
2279 LOG_ERROR_P(this, "Invalid State , current %d",
2280 state_manager_.GetStateEnum());
2284 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2285 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2286 static_cast<std::uint32_t>(low_latency_mode_));
2290 LOG_INFO_P(this, "video_high_latency_threshold : [%u]", threshold);
2292 trackrenderer_->SetVideoHighLatencyThreshold(threshold);
2296 bool EsPlayer::SetAudioHighLatencyThreshold(const unsigned int threshold) {
2297 if (state_manager_.GetState() < EsState::kIdle) {
2298 LOG_ERROR_P(this, "Invalid State , current %d",
2299 state_manager_.GetStateEnum());
2303 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2304 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2305 static_cast<std::uint32_t>(low_latency_mode_));
2309 LOG_INFO_P(this, "audio_high_latency_threshold : [%u]", threshold);
2311 trackrenderer_->SetAudioHighLatencyThreshold(threshold);
2315 bool EsPlayer::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
2316 if (frame_count == nullptr) {
2317 LOG_ERROR_P(this, "frame count is nullptr");
2320 if (state_manager_.GetState() < EsState::kReady) {
2321 LOG_ERROR_P(this, "Invalid State , current %d",
2322 state_manager_.GetStateEnum());
2326 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2327 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2328 static_cast<std::uint32_t>(low_latency_mode_));
2332 return trackrenderer_->GetLowLatencyPcmBufferSize(frame_count);
2335 bool EsPlayer::GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
2336 if (frame_count == nullptr) {
2337 LOG_ERROR_P(this, "frame count is nullptr");
2340 if (state_manager_.GetState() < EsState::kReady) {
2341 LOG_ERROR_P(this, "Invalid State , current %d",
2342 state_manager_.GetStateEnum());
2346 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2347 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2348 static_cast<std::uint32_t>(low_latency_mode_));
2352 return trackrenderer_->GetLowLatencyPcmCurrentBufferLevel(frame_count);
2355 bool EsPlayer::GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
2356 if (underrun_count == nullptr) {
2357 LOG_ERROR_P(this, "underrun count is nullptr");
2360 if (state_manager_.GetState() < EsState::kReady) {
2361 LOG_ERROR_P(this, "Invalid State , current %d",
2362 state_manager_.GetStateEnum());
2366 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2367 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2368 static_cast<std::uint32_t>(low_latency_mode_));
2372 return trackrenderer_->GetLowLatencyPcmUnderrunCount(underrun_count);
2375 bool EsPlayer::GetVirtualRscId(const RscType type, int* virtual_id) {
2376 if (virtual_id == nullptr) return false;
2377 if (state_manager_.GetState() < EsState::kReady) {
2378 LOG_ERROR_P(this, "Invalid State , current %d",
2379 state_manager_.GetStateEnum());
2383 return trackrenderer_->GetVirtualRscId(type, virtual_id);
2386 bool EsPlayer::SetAudioPreloading() {
2387 if (state_manager_.GetState() != EsState::kIdle) {
2388 LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
2391 return trackrenderer_->SetAudioPreloading();
2394 void EsPlayer::Init_() {
2396 is_stopped_ = false;
2400 void EsPlayer::MsgTask_() {
2401 std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
2402 while (!is_msg_task_stop_) {
2403 if (msg_queue_.empty()) {
2404 msg_task_cv_.wait(msg_mutex);
2407 msg_queue_.front()->Execute();
2412 while (!msg_queue_.empty()) {
2415 LOG_INFO_P(this, "Stop MsgTask");
2418 void EsPlayer::TrackRendererEventListener::OnEos() {
2419 LOG_ENTER_P(handler_);
2420 if (!handler_->eventlistener_) return;
2421 auto listener = std::bind(&esplusplayer::EsEventListener::OnEos,
2422 handler_->eventlistener_, std::placeholders::_1);
2423 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2424 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2425 handler_->msg_queue_.push(std::move(msg));
2427 handler_->msg_task_cv_.notify_one();
2428 LOG_LEAVE_P(handler_);
2432 void EsPlayer::TrackRendererEventListener::OnSeekDone() {
2433 LOG_ENTER_P(handler_);
2434 if (!handler_->eventlistener_) return;
2435 if (handler_->is_seek_done_need_drop == true) return;
2436 auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
2437 handler_->eventlistener_, std::placeholders::_1);
2438 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2439 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2440 handler_->msg_queue_.push(std::move(msg));
2442 handler_->msg_task_cv_.notify_one();
2443 LOG_LEAVE_P(handler_);
2446 void EsPlayer::TrackRendererEventListener::OnResourceConflicted() {
2447 LOG_ENTER_P(handler_);
2448 if (handler_->is_stopped_) {
2449 LOG_INFO_P(handler_, "LEAVE ~ Stop is called already");
2452 LOG_INFO_P(handler_, "Handling resource conflict...");
2453 handler_->is_resource_conflicted_ = true;
2454 handler_->trackrenderer_->Stop();
2455 if (!handler_->eventlistener_ || handler_->is_stopped_) return;
2457 std::bind(&esplusplayer::EsEventListener::OnResourceConflicted,
2458 handler_->eventlistener_, std::placeholders::_1);
2459 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2460 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2461 handler_->msg_queue_.push(std::move(msg));
2463 if (handler_->is_stopped_) {
2464 LOG_LEAVE_P(handler_);
2467 handler_->msg_task_cv_.notify_one();
2468 LOG_LEAVE_P(handler_);
2471 void EsPlayer::TrackRendererEventListener::OnError(
2472 const ErrorType& error_code) {
2473 if (!handler_->eventlistener_) return;
2474 if (error_code == ErrorType::kResourceLimit) return;
2475 auto listener = std::bind(&esplusplayer::EsEventListener::OnError,
2476 handler_->eventlistener_, std::placeholders::_1,
2477 std::placeholders::_2);
2478 auto msg = es_msg::Error::Make(error_code, listener,
2479 handler_->eventlistener_userdata_);
2481 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2482 handler_->msg_queue_.push(std::move(msg));
2484 handler_->msg_task_cv_.notify_one();
2487 void EsPlayer::TrackRendererEventListener::OnErrorMsg(
2488 const ErrorType& error_code, char* error_msg) {
2489 if (!handler_->eventlistener_) return;
2490 if (error_code == ErrorType::kResourceLimit) return;
2492 std::vector<Track> activeTracks;
2493 track_util::GetActiveTrackList(handler_->track_, activeTracks);
2495 Json::Value message;
2496 message["error_code"] = (int)error_code;
2498 switch (error_code) {
2499 case ErrorType::kNotSupportedVideoCodec:
2500 for (const auto& track : activeTracks) {
2501 if (track.type == kTrackTypeVideo) {
2502 message["codec"] = track.mimetype.c_str();
2503 message["demux"] = track.container_type.c_str();
2504 char json_string[20] = {0};
2506 strncat(json_string, std::to_string(track.width).c_str(), nLen);
2507 nLen = sizeof(json_string) - strlen(json_string) - 1;
2508 if (nLen < 0) nLen = 0;
2509 strncat(json_string, "*", nLen);
2510 nLen = sizeof(json_string) - strlen(json_string) - 1;
2511 if (nLen < 0) nLen = 0;
2512 strncat(json_string, std::to_string(track.height).c_str(), nLen);
2513 message["resolution"] = json_string;
2514 memset(json_string, 0, sizeof(json_string));
2516 strncat(json_string, std::to_string(track.framerate_num).c_str(),
2518 nLen = sizeof(json_string) - strlen(json_string) - 1;
2519 if (nLen < 0) nLen = 0;
2520 strncat(json_string, "/", nLen);
2521 nLen = sizeof(json_string) - strlen(json_string) - 1;
2522 if (nLen < 0) nLen = 0;
2523 strncat(json_string, std::to_string(track.framerate_den).c_str(),
2525 message["fps"] = json_string;
2526 message["detail_info"] = error_msg;
2531 case ErrorType::kNotSupportedAudioCodec:
2538 Json::FastWriter writer;
2539 std::string str = writer.write(message);
2540 LOG_INFO_P(handler_, "error message: %s", str.c_str());
2542 auto listener = std::bind(&esplusplayer::EsEventListener::OnErrorMsg,
2543 handler_->eventlistener_, std::placeholders::_1,
2544 std::placeholders::_2, std::placeholders::_3);
2546 es_msg::ErrorMsg::Make(error_code, str.c_str(), str.size(), listener,
2547 handler_->eventlistener_userdata_);
2549 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2550 handler_->msg_queue_.push(std::move(msg));
2552 handler_->msg_task_cv_.notify_one();
2556 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
2557 const TrackType& type) {
2558 LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
2559 (type == kTrackTypeAudio) ? "audio" : "video");
2561 handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
2563 auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToPrepare,
2564 handler_->eventlistener_, std::placeholders::_1,
2565 std::placeholders::_2);
2566 StreamType stream_type = internal::ConvertToStreamType(type);
2567 auto msg = es_msg::ReadyToPrepare::Make(stream_type, listener,
2568 handler_->eventlistener_userdata_);
2569 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2570 handler_->msg_queue_.push(std::move(msg));
2572 handler_->msg_task_cv_.notify_one();
2575 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
2576 uint64_t offset = handler_->need_data_[type].seek_offset;
2578 LOG_INFO("%p, OnReadyToSeek [%s] offset [%" PRId64 "]", handler_,
2579 (type == kTrackTypeAudio) ? "audio" : "video", offset);
2581 handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
2582 handler_->need_data_[type].seek_offset = 0;
2584 auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToSeek,
2585 handler_->eventlistener_, std::placeholders::_1,
2586 std::placeholders::_2, std::placeholders::_3);
2587 StreamType stream_type = internal::ConvertToStreamType(type);
2588 handler_->es_packet_logger_.ResetLog(stream_type);
2589 auto msg = es_msg::ReadyToSeek::Make(stream_type, offset, listener,
2590 handler_->eventlistener_userdata_);
2591 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2592 handler_->msg_queue_.push(std::move(msg));
2594 handler_->msg_task_cv_.notify_one();
2597 void EsPlayer::TrackRendererEventListener::BufferStatus_(
2598 const TrackType& type, const BufferStatus& status) {
2599 uint64_t byte_size, time_size;
2600 // LOG_INFO_P(handler_, "OnBufferStatus [%s] [%s]",
2601 // (type == kTrackTypeAudio) ? "audio" : "video",
2602 // (status == BufferStatus::kUnderrun) ? "underrun" : "overrun");
2603 handler_->GetSrcQueueCurrentSize_(type, &byte_size, &time_size);
2604 auto listener = std::bind(&esplusplayer::EsEventListener::OnBufferStatus,
2605 handler_->eventlistener_, std::placeholders::_1,
2606 std::placeholders::_2, std::placeholders::_3,
2607 std::placeholders::_4, std::placeholders::_5);
2608 StreamType stream_type = internal::ConvertToStreamType(type);
2610 es_msg::Bufferstatus::Make(stream_type, status, byte_size, time_size,
2611 listener, handler_->eventlistener_userdata_);
2612 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2613 handler_->msg_queue_.push(std::move(msg));
2615 handler_->msg_task_cv_.notify_one();
2618 void EsPlayer::TrackRendererEventListener::OnBufferStatus(
2619 const TrackType& type, const BufferStatus& status) {
2620 if (!handler_->eventlistener_) return;
2621 if (internal::IsLowLatencyModeDisableAVSync(handler_->low_latency_mode_))
2624 if (handler_->need_data_[type].mask == kNeedDataMaskByPrepare &&
2625 status == BufferStatus::kUnderrun) {
2626 ReadyToPrepare_(type);
2627 } else if (handler_->need_data_[type].mask == kNeedDataMaskBySeek &&
2628 status == BufferStatus::kUnderrun) {
2631 BufferStatus_(type, status);
2636 void EsPlayer::TrackRendererEventListener::OnMediaPacketGetTbmBufPtr(
2637 void** tbm_ptr, bool is_scale_change) {
2638 if (!handler_->eventlistener_) return;
2640 handler_->eventlistener_->OnMediaPacketGetTbmBufPtr(tbm_ptr, is_scale_change);
2643 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
2644 const DecodedVideoPacket& packet) {
2645 if (!handler_->eventlistener_) return;
2647 handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
2651 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoRawDecoded(
2652 const DecodedVideoRawModePacket& packet) {
2653 if (handler_->mixer_ticket_ == nullptr) return;
2654 const auto& data = packet.data;
2655 if (packet.type == DecodedVideoRawModePacketType::kPhysicalAddress) {
2656 DecodedRawInfo info;
2657 info.width = packet.width;
2658 info.height = packet.height;
2659 info.y_info.phyaddr = data.raw.y_phyaddr;
2660 info.y_info.viraddr = data.raw.y_viraddr;
2661 info.y_info.linesize = data.raw.y_linesize;
2662 info.uv_info.phyaddr = data.raw.uv_phyaddr;
2663 info.uv_info.viraddr = data.raw.uv_viraddr;
2664 info.uv_info.linesize = data.raw.uv_linesize;
2665 handler_->mixer_ticket_->Render(info);
2666 } else if (packet.type == DecodedVideoRawModePacketType::kTizenBuffer) {
2667 DecodedVideoKeyTypeInfo info;
2668 info.width = packet.width;
2669 info.height = packet.height;
2670 info.key = packet.data.tbm.key;
2671 handler_->mixer_ticket_->Render(info);
2675 bool EsPlayer::MixerListener::OnAudioFocusChanged(bool active) {
2676 LOG_INFO_P(handler_, "focused [%d]", active);
2677 std::unique_lock<std::mutex> lock(handler_->audio_focus_m_);
2678 if (handler_->state_manager_.GetState() < EsState::kReady) {
2679 handler_->is_audio_focused_ = active;
2683 Track activated_track;
2684 track_util::GetActiveTrack(handler_->track_, kTrackTypeAudio,
2686 LOG_INFO_P(handler_, "Activate audio track");
2688 std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2689 handler_->eos_status_ =
2690 internal::ResetEosStatus(kTrackTypeAudio, handler_->eos_status_);
2692 return handler_->trackrenderer_->Activate(kTrackTypeAudio, activated_track);
2694 LOG_INFO_P(handler_, "Deactivate audio track");
2695 handler_->is_audio_focused_ = false;
2697 std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2698 handler_->eos_status_ |= EosStatus::kAudioEos;
2700 return handler_->trackrenderer_->Deactivate(kTrackTypeAudio);
2703 bool EsPlayer::MixerListener::OnUpdateDisplayInfo(const DisplayInfo& cur_info,
2704 DisplayInfo* new_info) {
2705 new_info->geometry = handler_->mixerticket_roi_;
2706 new_info->visible_status =
2707 handler_->is_visible_ ? VisibleStatus::kVisible : VisibleStatus::kHide;
2713 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
2714 const uint64_t offset) {
2715 if (!handler_->eventlistener_) return;
2717 if (handler_->need_data_[type].mask != kNeedDataMaskByPrepare) {
2718 handler_->need_data_[type].mask |= kNeedDataMaskBySeek;
2719 handler_->need_data_[type].seek_offset = offset;
2724 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
2726 if (size <= 0) return;
2727 if (!handler_->eventlistener_) return;
2728 auto listener = std::bind(&esplusplayer::EsEventListener::OnClosedCaptionData,
2729 handler_->eventlistener_, std::placeholders::_1,
2730 std::placeholders::_2, std::placeholders::_3);
2731 auto msg = es_msg::ClosedCaption::Make(data, size, listener,
2732 handler_->eventlistener_userdata_);
2733 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2734 handler_->msg_queue_.push(std::move(msg));
2736 handler_->msg_task_cv_.notify_one();
2739 void EsPlayer::TrackRendererEventListener::OnFlushDone() {
2740 LOG_ENTER_P(handler_);
2741 if (!handler_->eventlistener_) return;
2743 auto listener = std::bind(&esplusplayer::EsEventListener::OnFlushDone,
2744 handler_->eventlistener_, std::placeholders::_1);
2746 es_msg::FlushDone::Make(listener, handler_->eventlistener_userdata_);
2747 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2748 handler_->msg_queue_.push(std::move(msg));
2750 handler_->msg_task_cv_.notify_one();
2751 LOG_LEAVE_P(handler_);
2754 void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
2755 const EventMsg& msg_data) {
2756 if (!handler_->eventlistener_) return;
2758 auto listener = std::bind(&esplusplayer::EsEventListener::OnEvent,
2759 handler_->eventlistener_, std::placeholders::_1,
2760 std::placeholders::_2, std::placeholders::_3);
2761 auto msg = es_msg::OnEvent::Make(event, msg_data, listener,
2762 handler_->eventlistener_userdata_);
2763 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2764 handler_->msg_queue_.push(std::move(msg));
2766 handler_->msg_task_cv_.notify_one();
2767 LOG_LEAVE_P(handler_);
2771 void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
2772 LOG_ENTER_P(handler_);
2773 if (!handler_->eventlistener_) return;
2774 auto listener = std::bind(&esplusplayer::EsEventListener::OnFirstDecodingDone,
2775 handler_->eventlistener_, std::placeholders::_1);
2776 auto msg = es_msg::FirstDecodingDone::Make(listener,
2777 handler_->eventlistener_userdata_);
2778 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2779 handler_->msg_queue_.push(std::move(msg));
2781 handler_->msg_task_cv_.notify_one();
2782 LOG_LEAVE_P(handler_);
2785 void EsPlayer::TrackRendererEventListener::OnVideoDecoderUnderrun() {
2786 LOG_ENTER_P(handler_);
2787 if (!handler_->eventlistener_) return;
2789 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2790 handler_->state_manager_.GetState() != EsState::kPaused) {
2795 std::bind(&esplusplayer::EsEventListener::OnVideoDecoderUnderrun,
2796 handler_->eventlistener_, std::placeholders::_1);
2797 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2798 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2799 handler_->msg_queue_.push(std::move(msg));
2801 handler_->msg_task_cv_.notify_one();
2802 LOG_LEAVE_P(handler_);
2805 void EsPlayer::TrackRendererEventListener::OnVideoLatencyStatus(
2806 const LatencyStatus& latency_status) {
2807 LOG_ENTER_P(handler_);
2808 if (!handler_->eventlistener_) return;
2810 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2811 handler_->state_manager_.GetState() != EsState::kPaused) {
2815 auto listener = std::bind(
2816 &esplusplayer::EsEventListener::OnVideoLatencyStatus,
2817 handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2819 auto msg = es_msg::PacketLatencyStatus::Make(
2820 latency_status, listener, handler_->eventlistener_userdata_);
2822 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2823 handler_->msg_queue_.push(std::move(msg));
2825 handler_->msg_task_cv_.notify_one();
2826 LOG_LEAVE_P(handler_);
2829 void EsPlayer::TrackRendererEventListener::OnAudioLatencyStatus(
2830 const LatencyStatus& latency_status) {
2831 LOG_ENTER_P(handler_);
2832 if (!handler_->eventlistener_) return;
2834 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2835 handler_->state_manager_.GetState() != EsState::kPaused) {
2839 auto listener = std::bind(
2840 &esplusplayer::EsEventListener::OnAudioLatencyStatus,
2841 handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2843 auto msg = es_msg::PacketLatencyStatus::Make(
2844 latency_status, listener, handler_->eventlistener_userdata_);
2846 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2847 handler_->msg_queue_.push(std::move(msg));
2849 handler_->msg_task_cv_.notify_one();
2850 LOG_LEAVE_P(handler_);
2853 void EsPlayer::TrackRendererEventListener::OnVideoHighLatency() {
2854 LOG_ENTER_P(handler_);
2855 if (!handler_->eventlistener_) return;
2857 auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoHighLatency,
2858 handler_->eventlistener_, std::placeholders::_1);
2860 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2862 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2863 handler_->msg_queue_.push(std::move(msg));
2865 handler_->msg_task_cv_.notify_one();
2866 LOG_LEAVE_P(handler_);
2870 void EsPlayer::TrackRendererEventListener::OnAudioHighLatency() {
2871 LOG_ENTER_P(handler_);
2872 if (!handler_->eventlistener_) return;
2874 auto listener = std::bind(&esplusplayer::EsEventListener::OnAudioHighLatency,
2875 handler_->eventlistener_, std::placeholders::_1);
2877 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2879 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2880 handler_->msg_queue_.push(std::move(msg));
2882 handler_->msg_task_cv_.notify_one();
2883 LOG_LEAVE_P(handler_);
2886 void EsPlayer::TrackRendererEventListener::OnVideoFrameDropped(
2887 const uint64_t& count) {
2888 if (!handler_->eventlistener_) return;
2890 handler_->eventlistener_->OnVideoFrameDropped(
2891 count, handler_->eventlistener_userdata_);
2895 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2896 handler_->state_manager_.GetState() != EsState::kPaused) {
2900 auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoFrameDropped,
2901 handler_->eventlistener_, std::placeholders::_1,
2902 std::placeholders::_2);
2904 auto msg = es_msg::FrameDroppedCount::Make(
2905 count, listener, handler_->eventlistener_userdata_);
2907 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2908 handler_->msg_queue_.push(std::move(msg));
2910 handler_->msg_task_cv_.notify_one();
2911 LOG_LEAVE_P(handler_);
2915 void EsPlayer::TrackRendererEventListener::OnDecoderInputBufferTime(
2916 const TrackType& type, const DecoderBufferTime& time) {
2917 if (!handler_->eventlistener_) return;
2919 StreamType stream_type = internal::ConvertToStreamType(type);
2920 handler_->eventlistener_->OnDecoderInputBufferTime(stream_type, time);
2923 void EsPlayer::TrackRendererEventListener::OnDecoderOutputBufferTime(
2924 const TrackType& type, const DecoderBufferTime& time) {
2925 if (!handler_->eventlistener_) return;
2927 StreamType stream_type = internal::ConvertToStreamType(type);
2928 handler_->eventlistener_->OnDecoderOutputBufferTime(stream_type, time);
2933 bool EsPlayer::SetVideoScanType(const PlayerVideoScanType type) {
2935 if (state_manager_.GetState() != EsState::kIdle) {
2936 LOG_ERROR_P(this, "Invalid State , current %d",
2937 state_manager_.GetStateEnum());
2940 if (type == kPlayerVideoScanTypeProgressive) set_video_progressive_ = 1;
2943 bool EsPlayer::SetTimeUnitType(const PlayerTimeUnitType type) {
2945 if (state_manager_.GetState() != EsState::kIdle) {
2946 LOG_ERROR_P(this, "Invalid State , current %d",
2947 state_manager_.GetStateEnum());
2950 LOG_INFO_P(this, "PlayerTimeUnitType [%s]",
2951 (type == kPlayerTimeUnitTypeMs) ? "Ms" : "Us");
2952 time_unit_type = type;
2956 bool EsPlayer::GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) {
2957 if (!time_in_milliseconds) return false;
2958 if (state_manager_.GetState() <= EsState::kReady) {
2959 *time_in_milliseconds = 0;
2962 return trackrenderer_->GetDecodingTime(type, time_in_milliseconds);
2965 bool EsPlayer::SetVideoStreamRotationInfo(const VideoRotation& rotation) {
2967 if (state_manager_.GetState() < EsState::kIdle) {
2968 LOG_ERROR_P(this, "Invalid State , current %d",
2969 state_manager_.GetStateEnum());
2972 video_rotate_ = rotation;
2973 return trackrenderer_->SetVideoStreamRotationInfo(rotation);
2976 bool EsPlayer::GetVideoStreamRotationInfo(VideoRotation* rotation) {
2978 if (state_manager_.GetState() < EsState::kIdle) {
2979 LOG_ERROR_P(this, "Invalid State , current %d",
2980 state_manager_.GetStateEnum());
2983 *rotation = video_rotate_;
2987 bool EsPlayer::SetSimpleMixOutBufferLevel(
2988 const PlayerSimpleMixOutBufferLevel level) {
2989 if (state_manager_.GetState() == EsState::kNone) {
2990 LOG_ERROR_P(this, "Invalid State");
2993 int converted_level = 1;
2994 if (level == kPlayerSimpleMixOutBufferLow) {
2995 converted_level = 0;
2996 } else if (level == kPlayerSimpleMixOutBufferMid) {
2997 converted_level = 1;
2998 } else if (level == kPlayerSimpleMixOutBufferHigh) {
2999 converted_level = 2;
3002 return trackrenderer_->SetSimpleMixOutBufferLevel(converted_level);
3005 #ifndef TIZEN_FEATURE_PUBLIC
3006 kpi::EsCodecLoggerKeys EsPlayer::MakeKpiKeys_() {
3007 kpi::EsCodecLoggerKeys event_info;
3008 event_info.app_id = app_info_.id;
3009 if (submit_data_type_ == SubmitDataType::kCleanData) {
3010 event_info.is_clean = true;
3012 event_info.is_clean = false;
3015 for (const auto& track : track_) {
3016 if (track.type == kTrackTypeVideo) {
3017 event_info.v_codec = track.mimetype;
3018 event_info.v_codec_version = track.version;
3019 event_info.width = track.maxwidth;
3020 event_info.height = track.maxheight;
3021 } else if (track.type == kTrackTypeAudio) {
3022 event_info.a_codec = track.mimetype;
3029 void EsPlayer::InitValuesFromIni_() {
3030 force_audio_swdecoder_use_ = es_conf::ini_property["force_sw_audio_codec"];
3031 force_video_swdecoder_use_ = es_conf::ini_property["force_sw_video_codec"];
3034 #ifdef TIZEN_FEATURE_PUBLIC
3035 bool EsPlayer::EnableVideoHole(bool value) {
3036 if (state_manager_.GetState() < EsState::kIdle) {
3037 LOG_ERROR_P(this, "Invalid State , current %d",
3038 state_manager_.GetStateEnum());
3041 return trackrenderer_->EnableVideoHole(value);
3044 bool EsPlayer::SetSoundStreamInfo(const sound_stream_info_h stream_info) {
3045 if (state_manager_.GetState() != EsState::kIdle) {
3046 LOG_ERROR_P(this, "Invalid State , current %d",
3047 state_manager_.GetStateEnum());
3051 LOG_ERROR_P(this, "stream_info is null");
3054 return trackrenderer_->SetSoundStreamInfo(stream_info);
3060 void LoadIniProperty(const Json::Value& root) {
3062 std::vector<std::string> booleanKeys {
3064 "force_sw_audio_codec",
3065 "force_sw_video_codec",
3066 "fallback_to_sw_audio_codec",
3067 "fallback_to_sw_video_codec"
3070 gst_util::GstInit(root);
3071 std::for_each(booleanKeys.begin(), booleanKeys.end(), [&](const auto& key) {
3072 es_conf::ini_property[key] = root.get(key, "").asBool();
3073 LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
3077 bool LoadIniFile() {
3078 const char* path = esplusplayer_cfg::GetIniPath();
3079 LOG_INFO("path : %s", path);
3080 std::streampos size;
3081 char* buf = nullptr;
3082 std::ifstream file(path, std::ios::binary | std::ios::ate);
3083 if (file.is_open() == false) {
3084 gst_util::GstInit();
3085 LOG_ERROR("Can't open file !!");
3088 BOOST_SCOPE_EXIT(&file) { file.close(); }
3089 BOOST_SCOPE_EXIT_END
3091 size = file.tellg();
3093 LOG_ERROR("Wrong file size");
3097 buf = static_cast<char*>(calloc(size, sizeof(char)));
3098 if (buf == nullptr) {
3099 LOG_ERROR("Fail to calloc buf");
3102 BOOST_SCOPE_EXIT(&buf) {
3105 BOOST_SCOPE_EXIT_END
3107 file.seekg(0, std::ios::beg);
3108 file.read(buf, size);
3110 std::string config = buf;
3112 Json::Reader reader;
3113 if (!reader.parse(config, root)) {
3114 LOG_ERROR("Fail to parse configuration file %s",
3115 (reader.getFormatedErrorMessages()).c_str());
3119 es_conf::LoadIniProperty(root);
3123 } // namespace es_conf
3125 } // namespace esplusplayer