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;
1340 key_system_acquired_ = false;
1343 void EsPlayer::ResetContextForStop_() {
1344 for (int i = 0; i < kTrackTypeMax; ++i) {
1345 need_data_[i].mask = kNeedDataMaskNone;
1346 need_data_[i].seek_offset = 0;
1349 std::lock_guard<std::mutex> lock(eos_mutex_);
1350 eos_status_ = EosStatus::kAllEos;
1352 current_playback_rate_ = 1.0;
1353 current_audio_mute_ = false;
1356 void EsPlayer::GetSrcQueueCurrentSize_(const TrackType& type,
1357 uint64_t* byte_size,
1358 uint64_t* time_size) {
1359 boost::any byte_size_, time_size_;
1360 if (type == TrackType::kTrackTypeVideo) {
1361 trackrenderer_->GetAttribute(
1362 TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelByte,
1364 trackrenderer_->GetAttribute(
1365 TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
1367 } else if (type == TrackType::kTrackTypeAudio) {
1368 trackrenderer_->GetAttribute(
1369 TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
1371 trackrenderer_->GetAttribute(
1372 TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
1377 *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
1378 *time_size = boost::any_cast<std::uint64_t>(time_size_);
1380 LOG_INFO_P(this, "any_cast failed");
1382 if (time_unit_type == kPlayerTimeUnitTypeMs)
1383 *time_size = util::ConvertNsToMs(*time_size);
1384 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1385 *time_size = util::ConvertNsToUs(*time_size);
1388 GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
1389 MakeBufferStatus* status) {
1390 std::shared_ptr<char> buffer = packet->GetBuffer();
1391 uint32_t size = packet->GetSize();
1392 if (packet->IsEosPacket()) {
1393 *status = MakeBufferStatus::kEos;
1396 GstBuffer* gstbuffer = gst_buffer_new_and_alloc(size);
1398 *status = MakeBufferStatus::kOutOfMemory;
1401 if (buffer != nullptr) {
1403 gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
1404 memcpy(map.data, buffer.get(), size);
1405 gst_buffer_unmap(gstbuffer, &map);
1408 uint64_t pts = packet->GetPts();
1409 uint64_t duration = packet->GetDuration();
1410 /* if pts or duration are -1(=GST_CLOCK_TIME_NONE), some of the elements don't
1411 * adjust the buffer. */
1412 if (time_unit_type == kPlayerTimeUnitTypeMs) {
1413 GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1414 ? GST_CLOCK_TIME_NONE
1415 : (GstClockTime)util::ConvertMsToNs(pts);
1416 GST_BUFFER_DURATION(gstbuffer) =
1417 (duration == GST_CLOCK_TIME_NONE)
1418 ? GST_CLOCK_TIME_NONE
1419 : (GstClockTime)util::ConvertMsToNs(duration);
1420 } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1421 GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1422 ? GST_CLOCK_TIME_NONE
1423 : (GstClockTime)util::ConvertUsToNs(pts);
1424 GST_BUFFER_DURATION(gstbuffer) =
1425 (duration == GST_CLOCK_TIME_NONE)
1426 ? GST_CLOCK_TIME_NONE
1427 : (GstClockTime)util::ConvertUsToNs(duration);
1429 uint32_t hdr10p_size = packet->GetHdr10pSize();
1430 std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
1432 if (hdr10p_size > 0 && hdr10p_metadata != nullptr) {
1433 guint32* blockadditional_size = (guint32*)g_malloc(sizeof(uint32_t));
1434 *blockadditional_size = hdr10p_size;
1435 gst_mini_object_set_qdata(
1436 GST_MINI_OBJECT(gstbuffer),
1437 g_quark_from_static_string("matroska_blockadditional_size"),
1438 blockadditional_size, g_free);
1440 /* blockadditiona_data : the data sent to omx, size (4 bytes) + metadata */
1441 guint8* blockadditional_data =
1442 (guint8*)g_malloc(((*blockadditional_size) + 4) * sizeof(guint8));
1443 memcpy(blockadditional_data, blockadditional_size, sizeof(uint32_t));
1444 memcpy(blockadditional_data + 4, hdr10p_metadata.get(),
1445 (*blockadditional_size));
1446 gst_mini_object_set_qdata(
1447 GST_MINI_OBJECT(gstbuffer),
1448 g_quark_from_static_string("matroska_blockadditional_info"),
1449 blockadditional_data, g_free);
1451 *status = MakeBufferStatus::kSuccess;
1455 PacketSubmitStatus EsPlayer::SubmitEosPacket_(const TrackType& type) {
1456 PacketSubmitStatus submitstate = PacketSubmitStatus::kSuccess;
1458 std::lock_guard<std::mutex> lock(eos_mutex_);
1460 case kTrackTypeAudio:
1461 eos_status_ |= EosStatus::kAudioEos;
1463 case kTrackTypeVideo:
1464 eos_status_ |= EosStatus::kVideoEos;
1469 if (eos_status_ != EosStatus::kAllEos) {
1473 for (int tracktype = kTrackTypeAudio; tracktype < kTrackTypeMax;
1476 DecoderInputBuffer::Create(static_cast<TrackType>(tracktype));
1477 if (!trackrenderer_->SubmitPacket2(inbuffer, nullptr)) {
1478 std::lock_guard<std::mutex> lock(eos_mutex_);
1479 eos_status_ = EosStatus::kAllEos;
1480 submitstate = PacketSubmitStatus::kNotPrepared;
1487 void EsPlayer::UnsetTzQdata_(const DecoderInputBufferPtr& buffer) {
1488 const GstBuffer* gstbuf = buffer->Get();
1489 if (!gstbuf) return;
1490 GstStructure* tzqdata = GST_STRUCTURE(gst_mini_object_steal_qdata(
1491 GST_MINI_OBJECT(gstbuf), g_quark_from_static_string("GstTzHandleData")));
1492 if (tzqdata) gst_structure_free(tzqdata);
1495 PacketSubmitStatus EsPlayer::SubmitDecoderInputBuffer_(
1496 const DecoderInputBufferPtr& buffer) {
1497 PacketSubmitStatus status = PacketSubmitStatus::kSuccess;
1498 TrackRendererAdapter::SubmitStatus submitstate =
1499 TrackRendererAdapter::SubmitStatus::kSuccess;
1500 trackrenderer_->SubmitPacket2(buffer, &submitstate);
1502 switch (submitstate) {
1503 case TrackRendererAdapter::SubmitStatus::kSuccess:
1504 case TrackRendererAdapter::SubmitStatus::kDrop:
1505 status = PacketSubmitStatus::kSuccess;
1507 case TrackRendererAdapter::SubmitStatus::kFull:
1508 UnsetTzQdata_(buffer);
1509 trackrenderer_event_listener_->OnBufferStatus(buffer->GetType(),
1510 BufferStatus::kOverrun);
1511 status = PacketSubmitStatus::kFull;
1514 UnsetTzQdata_(buffer);
1515 status = PacketSubmitStatus::kNotPrepared;
1522 void EsPlayer::MakeGstBufferForTzHandle_(GstBuffer* gstbuffer,
1523 const TrackType& type,
1524 const uint32_t& tz_handle,
1525 const uint32_t& packet_size) {
1526 GstStructure* gst_tz_handle_data_structure =
1527 gst_structure_new("GstTzHandleData", "packet_handle", G_TYPE_UINT,
1528 static_cast<guint32>(tz_handle), "packet_size",
1529 G_TYPE_UINT, static_cast<guint32>(packet_size),
1530 "secure", G_TYPE_BOOLEAN, true, nullptr);
1531 gst_mini_object_set_qdata(
1532 GST_MINI_OBJECT(gstbuffer), g_quark_from_string("GstTzHandleData"),
1533 gst_tz_handle_data_structure, (GDestroyNotify)gst_structure_free);
1535 if (type == kTrackTypeAudio) {
1537 bool has_active_audio_track =
1538 track_util::GetActiveTrack(track_, kTrackTypeAudio, &audio_track);
1539 if (has_active_audio_track) {
1540 GstStructure* audio_info_structure =
1541 gst_structure_new("AudioInfo", "mime_type", G_TYPE_STRING,
1542 audio_track.mimetype.c_str(), nullptr);
1543 gst_mini_object_set_qdata(
1544 GST_MINI_OBJECT(gstbuffer), g_quark_from_string("AudioInfo"),
1545 audio_info_structure, (GDestroyNotify)gst_structure_free);
1550 void EsPlayer::MakeGstBufferForEncryptedPacket_(
1551 GstBuffer* gstbuffer, const EsPacketPtr& packet,
1552 const drm::EsPlayerEncryptedInfo& drm_info) {
1553 if (drm_info.handle == 0) return;
1554 auto serialized_drm_info_ptr = esplayer_drm::Serialize(packet, drm_info);
1555 GstStructure* gst_drm_info_structure =
1556 gst_structure_new("drm_info", "drm_specific_info", G_TYPE_BYTES,
1557 serialized_drm_info_ptr.get(), nullptr);
1558 if (gst_drm_info_structure) {
1559 gst_mini_object_set_qdata(
1560 GST_MINI_OBJECT(gstbuffer), g_quark_from_static_string("drm_info"),
1561 gst_drm_info_structure, (GDestroyNotify)gst_structure_free);
1566 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
1567 SubmitPacketOperator op) {
1568 if (state_manager_.GetState() < EsState::kIdle) {
1569 return PacketSubmitStatus::kNotPrepared;
1571 if (!packet) return PacketSubmitStatus::kInvalidPacket;
1573 TrackType type = static_cast<TrackType>(packet->GetType());
1574 Track activated_track;
1575 if (!track_util::GetActiveTrack(track_, type, &activated_track))
1576 return PacketSubmitStatus::kInvalidPacket;
1578 if (state_manager_.GetState() == EsState::kPaused ||
1579 state_manager_.GetState() == EsState::kReady) {
1580 internal::AppsrcQueueSizeOption byte_based, time_based;
1582 case kTrackTypeAudio:
1583 byte_based.max_size = src_queue_size_.kMaxByteOfAudioSrcQueue;
1584 time_based.max_size = src_queue_size_.kMaxTimeOfAudioSrcQueue;
1585 byte_based.threshold = src_queue_size_.kMinByteThresholdOfAudioSrcQueue;
1586 time_based.threshold = src_queue_size_.kMinTimeThresholdOfAudioSrcQueue;
1588 case kTrackTypeVideo:
1589 byte_based.max_size = src_queue_size_.kMaxByteOfVideoSrcQueue;
1590 time_based.max_size = src_queue_size_.kMaxTimeOfVideoSrcQueue;
1591 byte_based.threshold = src_queue_size_.kMinByteThresholdOfVideoSrcQueue;
1592 time_based.threshold = src_queue_size_.kMinTimeThresholdOfVideoSrcQueue;
1597 GetSrcQueueCurrentSize_(type, &(byte_based.current_size),
1598 &(time_based.current_size));
1599 if (internal::IsUnderRun(byte_based, time_based))
1600 trackrenderer_event_listener_->OnBufferStatus(type,
1601 BufferStatus::kUnderrun);
1604 es_packet_logger_.StorePacketInfo(packet);
1605 es_packet_logger_.PrintStoredPacketInfo(packet->GetType());
1607 MakeBufferStatus make_buffer_status;
1608 GstBuffer* gstbuffer = GetGstBuffer_(packet, &make_buffer_status);
1610 if (make_buffer_status == MakeBufferStatus::kEos)
1611 return SubmitEosPacket_(type);
1612 else if (make_buffer_status == MakeBufferStatus::kOutOfMemory)
1613 return PacketSubmitStatus::kOutOfMemory;
1615 if (op != nullptr) {
1616 PacketSubmitStatus op_status = op(gstbuffer);
1617 if (op_status != PacketSubmitStatus::kSuccess) {
1622 auto inbuffer = DecoderInputBuffer::Create(type, 0, gstbuffer);
1623 gst_buffer_unref(gstbuffer);
1625 if (packet->HasMatroskaColorInfo()) {
1626 std::string color_info_str =
1627 util::GetStringFromMatroskaColor(packet->GetMatroskaColorInfo());
1628 if (trackrenderer_->SetMatroskaColorInfo(color_info_str) == false)
1629 return PacketSubmitStatus::kNotPrepared;
1632 return SubmitDecoderInputBuffer_(inbuffer);
1635 PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
1636 std::lock_guard<std::mutex> lk(submit_mutex_);
1637 return SubmitPacketCommon_(packet, nullptr);
1641 PacketSubmitStatus EsPlayer::SubmitTrustZonePacket(const EsPacketPtr& packet,
1642 uint32_t tz_handle) {
1643 std::lock_guard<std::mutex> lk(submit_mutex_);
1644 if (submit_data_type_ != SubmitDataType::kTrustZoneData)
1645 return PacketSubmitStatus::kInvalidPacket;
1646 auto submitpacket_op = [this, &tz_handle,
1647 &packet](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1648 if (tz_handle > 0) {
1649 TrackType type = static_cast<TrackType>(packet->GetType());
1650 uint32_t packet_size = packet->GetSize();
1651 MakeGstBufferForTzHandle_(gstbuffer, type, tz_handle, packet_size);
1653 return PacketSubmitStatus::kSuccess;
1655 return SubmitPacketCommon_(packet, submitpacket_op);
1658 PacketSubmitStatus EsPlayer::SubmitEncryptedPacket(
1659 const EsPacketPtr& packet, const drm::EsPlayerEncryptedInfo& drm_info) {
1660 std::lock_guard<std::mutex> lk(submit_mutex_);
1661 if (submit_data_type_ != SubmitDataType::kEncryptedData)
1662 return PacketSubmitStatus::kInvalidPacket;
1663 auto submitpacket_op =
1664 [this, &packet, &drm_info](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1665 MakeGstBufferForEncryptedPacket_(gstbuffer, packet, drm_info);
1666 return PacketSubmitStatus::kSuccess;
1668 if (!key_system_acquired_ && drm_info.handle != 0) {
1669 key_system_ = eme::IEME::getKeySystemName(drm_info.handle);
1670 LOG_INFO("KeySystemName :: [%s] ", key_system_.c_str());
1672 .GetPreparingState()) { // if the stream comes with clean data at
1673 // the beginning, re-post kpi when we get
1675 kpi::CodecLogger logger;
1676 kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
1677 logger.SendKpi(true, event_keys);
1679 key_system_acquired_ = true;
1681 return SubmitPacketCommon_(packet, submitpacket_op);
1685 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
1687 bool EsPlayer::GetPlayingTime(uint64_t* time) {
1688 if (!time) return false;
1689 if (state_manager_.GetState() <= EsState::kReady) {
1693 return trackrenderer_->GetPlayingTime(time);
1696 bool EsPlayer::SetAudioMute(bool is_mute) {
1697 if (state_manager_.GetState() < EsState::kIdle) {
1698 LOG_ERROR_P(this, "Invalid State , current %d",
1699 state_manager_.GetStateEnum());
1702 return trackrenderer_->SetAudioMute(is_mute);
1705 bool EsPlayer::SetVideoFrameBufferType(DecodedVideoFrameBufferType type) {
1706 if ((state_manager_.GetState() != EsState::kIdle &&
1707 type != DecodedVideoFrameBufferType::kScale) ||
1708 (state_manager_.GetState() < EsState::kIdle &&
1709 type == DecodedVideoFrameBufferType::kScale)) {
1710 LOG_ERROR_P(this, "Invalid State , current %d",
1711 state_manager_.GetStateEnum());
1714 if (type == DecodedVideoFrameBufferType::kScale &&
1715 video_codec_type_ == kPlayerVideoCodecTypeSW) {
1716 LOG_ERROR_P(this, "kScale is not supportted when using sw video decoder");
1719 trackrenderer_->SetVideoFrameBufferType(
1720 VideoFrameTypeStrategyPtr(new DefaultVideoFrameTypeStrategy(type)));
1721 vidoe_frame_buffer_type_ = type;
1725 bool EsPlayer::SetVideoFrameBufferScaleResolution(
1726 const uint32_t& target_width, const uint32_t& target_height) {
1727 if (state_manager_.GetState() < EsState::kIdle) {
1728 LOG_ERROR_P(this, "Invalid State , current %d",
1729 state_manager_.GetStateEnum());
1733 return trackrenderer_->SetVideoFrameBufferScaleResolution(target_width,
1737 bool EsPlayer::SetDecodedVideoFrameRate(const Rational& request_framerate) {
1738 if (state_manager_.GetState() < EsState::kIdle) {
1739 LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
1743 return trackrenderer_->SetDecodedVideoFrameRate(request_framerate);
1746 void EsPlayer::RegisterListener(EsEventListener* listener,
1747 EsEventListener::UserData userdata) {
1748 // assert(listener); // allow unregister by setting nullptr
1749 assert(!eventlistener_);
1750 eventlistener_ = listener;
1751 eventlistener_userdata_ = userdata;
1754 bool EsPlayer::GetAdaptiveInfo(void* padaptive_info,
1755 const PlayerAdaptiveInfo& adaptive_type) {
1756 if (!padaptive_info || adaptive_type <= PlayerAdaptiveInfo::kMinType ||
1757 adaptive_type >= PlayerAdaptiveInfo::kMaxType)
1759 switch (adaptive_type) {
1760 case PlayerAdaptiveInfo::kVideoDroppedFrames:
1761 if (state_manager_.GetState() < EsState::kReady) {
1762 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1765 return trackrenderer_->GetDroppedFrames(padaptive_info);
1766 case PlayerAdaptiveInfo::kDroppedVideoFramesForCatchup:
1767 if (state_manager_.GetState() < EsState::kReady) {
1768 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1771 return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeVideo,
1773 case PlayerAdaptiveInfo::kDroppedAudioFramesForCatchup:
1774 if (state_manager_.GetState() < EsState::kReady) {
1775 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1778 return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeAudio,
1786 bool EsPlayer::SetVolume(const int& volume) {
1787 if (volume < internal::kVolumeMin || volume > internal::kVolumeMax) {
1788 LOG_ERROR_P(this, "Invalid volume level %d", volume);
1791 if (state_manager_.GetState() < EsState::kIdle) {
1792 LOG_ERROR_P(this, "Invalid State , current %d",
1793 state_manager_.GetStateEnum());
1796 return trackrenderer_->SetVolume(volume);
1799 bool EsPlayer::GetVolume(int* volume) {
1800 if (state_manager_.GetState() < EsState::kIdle) {
1801 LOG_ERROR_P(this, "Invalid State , current %d",
1802 state_manager_.GetStateEnum());
1805 return trackrenderer_->GetVolume(volume);
1808 bool EsPlayer::Flush(const StreamType& type) {
1809 if (state_manager_.GetState() <= EsState::kIdle) {
1810 LOG_ERROR_P(this, "Invalid State , current %d",
1811 state_manager_.GetStateEnum());
1815 internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
1816 es_packet_logger_.ResetLog(type);
1817 return trackrenderer_->Flush(type);
1820 bool EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
1821 TrackType track_type = kTrackTypeMax;
1823 case BufferOption::kBufferAudioMaxByteSize: /* FALL THROUGH */
1824 case BufferOption::kBufferAudioMinByteThreshold: /* FALL THROUGH */
1825 case BufferOption::kBufferAudioMaxTimeSize: /* FALL THROUGH */
1826 case BufferOption::kBufferAudioMinTimeThreshold:
1827 track_type = kTrackTypeAudio;
1829 case BufferOption::kBufferVideoMaxByteSize: /* FALL THROUGH */
1830 case BufferOption::kBufferVideoMinByteThreshold: /* FALL THROUGH */
1831 case BufferOption::kBufferVideoMaxTimeSize: /* FALL THROUGH */
1832 case BufferOption::kBufferVideoMinTimeThreshold:
1833 track_type = kTrackTypeVideo;
1838 if (track_type == kTrackTypeMax) {
1839 LOG_ERROR_P(this, "Invalid option!!!");
1843 Track activated_track;
1845 track_util::GetActiveTrack(track_, track_type, &activated_track);
1846 EsState state = state_manager_.GetState();
1847 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_activated)) {
1848 LOG_ERROR_P(this, "Invalid State [state:%d] or stream is activated [%d],",
1849 state_manager_.GetStateEnum(), is_activated);
1854 case BufferOption::kBufferAudioMaxByteSize:
1855 src_queue_size_.kMaxByteOfAudioSrcQueue = size;
1857 case BufferOption::kBufferVideoMaxByteSize:
1858 src_queue_size_.kMaxByteOfVideoSrcQueue = size;
1860 case BufferOption::kBufferAudioMinByteThreshold:
1861 src_queue_size_.kMinByteThresholdOfAudioSrcQueue =
1862 static_cast<uint32_t>(size);
1864 case BufferOption::kBufferVideoMinByteThreshold:
1865 src_queue_size_.kMinByteThresholdOfVideoSrcQueue =
1866 static_cast<uint32_t>(size);
1868 case BufferOption::kBufferAudioMaxTimeSize:
1869 src_queue_size_.kMaxTimeOfAudioSrcQueue = size;
1871 case BufferOption::kBufferVideoMaxTimeSize:
1872 src_queue_size_.kMaxTimeOfVideoSrcQueue = size;
1874 case BufferOption::kBufferAudioMinTimeThreshold:
1875 src_queue_size_.kMinTimeThresholdOfAudioSrcQueue =
1876 static_cast<uint32_t>(size);
1878 case BufferOption::kBufferVideoMinTimeThreshold:
1879 src_queue_size_.kMinTimeThresholdOfVideoSrcQueue =
1880 static_cast<uint32_t>(size);
1883 LOG_ERROR_P(this, "Invalid option!!!");
1889 bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
1890 if (state_manager_.GetState() != EsState::kIdle) {
1891 LOG_ERROR_P(this, "Invalid State , current %d",
1892 state_manager_.GetStateEnum());
1895 if (true == internal::IsExclusiveLowLatencyMode(low_latency_mode_, mode)) {
1896 LOG_ERROR_P(this, "Invalid Mode , current 0x%x, set 0x%x",
1897 static_cast<std::uint32_t>(low_latency_mode_),
1898 static_cast<std::uint32_t>(mode));
1901 low_latency_mode_ |= static_cast<std::uint32_t>(mode);
1905 bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
1906 if (state_manager_.GetState() < EsState::kReady) {
1907 LOG_ERROR_P(this, "Invalid State , current %d",
1908 state_manager_.GetStateEnum());
1911 if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1913 "low latency mode have to be set except disable_sync mode");
1916 std::int64_t ns_unit = 0;
1917 if (time_unit_type == kPlayerTimeUnitTypeMs)
1919 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1921 if ((offset * ns_unit > G_MAXINT64) || (offset * ns_unit < G_MININT64)) {
1922 LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
1923 "] * 1000000 < G_MAXINT64",
1927 if (type == StreamType::kMax) return false;
1928 if (time_unit_type == kPlayerTimeUnitTypeMs) {
1929 if (type == StreamType::kAudio)
1930 trackrenderer_->SetAttribute(
1931 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1932 util::ConvertMsToNs(offset));
1933 else if (type == StreamType::kVideo)
1934 trackrenderer_->SetAttribute(
1935 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1936 util::ConvertMsToNs(offset));
1937 } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1938 if (type == StreamType::kAudio)
1939 trackrenderer_->SetAttribute(
1940 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1941 util::ConvertUsToNs(offset));
1942 else if (type == StreamType::kVideo)
1943 trackrenderer_->SetAttribute(
1944 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1945 util::ConvertUsToNs(offset));
1950 bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
1951 if (state_manager_.GetState() < EsState::kReady) {
1952 LOG_ERROR_P(this, "Invalid State , current %d",
1953 state_manager_.GetStateEnum());
1956 if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1957 LOG_ERROR_P(this, "low latency mode have to be set");
1960 if (type == StreamType::kMax) return false;
1962 if (type == StreamType::kAudio)
1963 trackrenderer_->GetAttribute(
1964 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
1965 else if (type == StreamType::kVideo)
1966 trackrenderer_->GetAttribute(
1967 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
1969 *offset = boost::any_cast<std::int64_t>(off_set);
1970 if (time_unit_type == kPlayerTimeUnitTypeMs)
1971 *offset = util::ConvertNsToMs(*offset);
1972 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1973 *offset = util::ConvertNsToUs(*offset);
1977 bool EsPlayer::SetVideoFramePeekMode() {
1978 if (state_manager_.GetState() != EsState::kIdle) {
1979 LOG_ERROR_P(this, "Invalid State , current %d",
1980 state_manager_.GetStateEnum());
1983 constexpr std::uint32_t peek_mode_on = 1;
1984 video_frame_peek_mode_ = peek_mode_on;
1988 bool EsPlayer::RenderVideoFrame() {
1989 if (!video_frame_peek_mode_) return false;
1990 if (state_manager_.GetState() == EsState::kReady ||
1991 state_manager_.GetState() == EsState::kPaused) {
1992 trackrenderer_->RenderVideoFrame();
1995 LOG_ERROR_P(this, "Invalid State , current %d",
1996 state_manager_.GetStateEnum());
2000 bool EsPlayer::SetUnlimitedMaxBufferMode() {
2001 if (state_manager_.GetState() != EsState::kIdle) {
2002 LOG_ERROR_P(this, "Invalid State , current %d",
2003 state_manager_.GetStateEnum());
2006 constexpr std::uint32_t unlimited_max_buffer_mode_on = 1;
2007 unlimited_max_buffer_mode_ = unlimited_max_buffer_mode_on;
2011 ErrorType EsPlayer::SetFmmMode() {
2012 EsState state = state_manager_.GetState();
2014 if (state < EsState::kIdle) {
2015 LOG_ERROR_P(this, "Invalid State , current %d",
2016 state_manager_.GetStateEnum());
2017 return ErrorType::kInvalidState;
2021 ErrorType ret = ErrorType::kNone;
2022 if (trackrenderer_->GetFmmAutoMode(&onoff) == false) {
2023 return ErrorType::kInvalidOperation;
2031 if (onoff == FMM_AUTO_OFF) ret = ErrorType::kInvalidOperation;
2033 fmm_mode_ = FMM_AUTO_ON;
2035 if (state < EsState::kReady) return ret;
2037 trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
2042 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
2043 Track activated_track;
2045 track_util::GetActiveTrack(track_, kTrackTypeAudio, &activated_track);
2046 EsState state = state_manager_.GetState();
2047 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2049 "Invalid State [state:%d] or audio stream already exists[%d],",
2050 state_manager_.GetStateEnum(), is_existed);
2053 if (force_audio_swdecoder_use_ && type == kPlayerAudioCodecTypeHW) {
2054 LOG_ERROR_P(this, "Not support hw decoder");
2057 LOG_INFO_P(this, "PlayerAudioCodecType [%s]",
2058 (type == kPlayerAudioCodecTypeHW) ? "hardware" : "software");
2059 audio_codec_type_ = type;
2063 bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
2064 Track activated_track;
2066 track_util::GetActiveTrack(track_, kTrackTypeVideo, &activated_track);
2067 EsState state = state_manager_.GetState();
2068 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2070 "Invalid State [state:%d] or video stream already exists[%d],",
2071 state_manager_.GetStateEnum(), is_existed);
2074 if (force_video_swdecoder_use_ &&
2075 (type == kPlayerVideoCodecTypeHW ||
2076 type == kPlayerVideoCodecTypeHWNdecoding)) {
2077 LOG_ERROR_P(this, "Not support hw decoder");
2080 if (type == kPlayerVideoCodecTypeSW &&
2081 vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
2083 "sw video decoder is not supportted when video frame buffer "
2088 if (!enable_rsc_alloc_handle_) {
2089 LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2092 if (type == kPlayerVideoCodecTypeHWNdecoding) {
2093 LOG_INFO_P(this, "PlayerVideoCodecType HW N-decoding");
2094 video_decoding_mode_ = internal::kNdecodingMode;
2098 LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
2099 (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
2100 video_codec_type_ = type;
2104 bool EsPlayer::SetAiFilter(void* aifilter) {
2105 if (state_manager_.GetState() != EsState::kIdle) {
2106 LOG_ERROR_P(this, "Invalid State , current %d",
2107 state_manager_.GetStateEnum());
2110 trackrenderer_->SetAiFilter(aifilter);
2114 bool EsPlayer::InitAudioEasingInfo(const uint32_t init_volume,
2115 const uint32_t init_elapsed_time,
2116 const AudioEasingInfo& easing_info) {
2117 if (init_volume > internal::kVolumeMax ||
2118 easing_info.target_volume > internal::kVolumeMax) {
2119 LOG_ERROR_P(this, "Invalid volume: init [%d] target [%d]", init_volume,
2120 easing_info.target_volume);
2123 if (state_manager_.GetState() < EsState::kIdle) {
2124 LOG_ERROR_P(this, "Invalid State , current %d",
2125 state_manager_.GetStateEnum());
2128 return trackrenderer_->InitAudioEasingInfo(init_volume, init_elapsed_time,
2132 bool EsPlayer::UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) {
2133 if (easing_info.target_volume > internal::kVolumeMax) {
2134 LOG_ERROR_P(this, "Invalid volume level %d", easing_info.target_volume);
2137 if (state_manager_.GetState() < EsState::kIdle) {
2138 LOG_ERROR_P(this, "Invalid State , current %d",
2139 state_manager_.GetStateEnum());
2142 return trackrenderer_->UpdateAudioEasingInfo(easing_info);
2145 bool EsPlayer::GetAudioEasingInfo(uint32_t* current_volume,
2146 uint32_t* elapsed_time,
2147 AudioEasingInfo* easing_info) {
2148 if (state_manager_.GetState() < EsState::kIdle) {
2149 LOG_ERROR_P(this, "Invalid State , current %d",
2150 state_manager_.GetStateEnum());
2153 return trackrenderer_->GetAudioEasingInfo(current_volume, elapsed_time,
2157 bool EsPlayer::StartAudioEasing() {
2158 if (state_manager_.GetState() < EsState::kReady) {
2159 LOG_ERROR_P(this, "Invalid State , current %d",
2160 state_manager_.GetStateEnum());
2163 return trackrenderer_->StartAudioEasing();
2166 bool EsPlayer::StopAudioEasing() {
2167 if (state_manager_.GetState() < EsState::kIdle) {
2168 LOG_ERROR_P(this, "Invalid State , current %d",
2169 state_manager_.GetStateEnum());
2172 return trackrenderer_->StopAudioEasing();
2175 bool EsPlayer::SetAlternativeVideoResource(unsigned int rsc_type) {
2176 if (state_manager_.GetState() == EsState::kNone) {
2177 LOG_ERROR_P(this, "Invalid State");
2181 if (!enable_rsc_alloc_handle_) {
2182 LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2186 if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2188 "has set resource allocate policy, the alternative "
2189 "resource setting will be wrong");
2192 alternative_video_resource_ = static_cast<std::uint32_t>(rsc_type);
2196 bool EsPlayer::SetAlternativeAudioResource(
2197 const PlayerAudioResourceType rsc_type) {
2198 if (state_manager_.GetState() == EsState::kNone) {
2199 LOG_ERROR_P(this, "Invalid State");
2203 if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2205 "has set resource allocate policy, the alternative "
2206 "resource setting will be wrong");
2209 return trackrenderer_->SetAlternativeAudioResource(rsc_type);
2212 bool EsPlayer::SetCatchUpSpeed(const CatchUpSpeed& level) {
2213 if (state_manager_.GetState() < EsState::kIdle) {
2214 LOG_ERROR_P(this, "Invalid State , current %d",
2215 state_manager_.GetStateEnum());
2219 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2220 LOG_ERROR_P(this, "Do not set low latency mode, current[0x%x]",
2221 static_cast<std::uint32_t>(low_latency_mode_));
2225 if (trackrenderer_->SetCatchUpSpeed(level)) {
2231 bool EsPlayer::GetVideoLatencyStatus(LatencyStatus* status) {
2232 if (state_manager_.GetState() < EsState::kReady) {
2233 LOG_ERROR_P(this, "Invalid State , current %d",
2234 state_manager_.GetStateEnum());
2238 if (trackrenderer_->GetVideoLatencyStatus(status)) {
2244 bool EsPlayer::GetAudioLatencyStatus(LatencyStatus* status) {
2245 if (state_manager_.GetState() < EsState::kReady) {
2246 LOG_ERROR_P(this, "Invalid State , current %d",
2247 state_manager_.GetStateEnum());
2251 if (trackrenderer_->GetAudioLatencyStatus(status)) {
2257 bool EsPlayer::SetVideoMidLatencyThreshold(const unsigned int threshold) {
2258 if (state_manager_.GetState() < EsState::kIdle) {
2259 LOG_ERROR_P(this, "Invalid State , current %d",
2260 state_manager_.GetStateEnum());
2264 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2265 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2266 static_cast<std::uint32_t>(low_latency_mode_));
2270 LOG_INFO_P(this, "video_mid_latency_threshold : [%u]", threshold);
2272 trackrenderer_->SetVideoMidLatencyThreshold(threshold);
2276 bool EsPlayer::SetAudioMidLatencyThreshold(const unsigned int threshold) {
2277 if (state_manager_.GetState() < EsState::kIdle) {
2278 LOG_ERROR_P(this, "Invalid State , current %d",
2279 state_manager_.GetStateEnum());
2283 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2284 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2285 static_cast<std::uint32_t>(low_latency_mode_));
2289 LOG_INFO_P(this, "audio_mid_latency_threshold : [%u]", threshold);
2291 trackrenderer_->SetAudioMidLatencyThreshold(threshold);
2295 bool EsPlayer::SetVideoHighLatencyThreshold(const unsigned int threshold) {
2296 if (state_manager_.GetState() < EsState::kIdle) {
2297 LOG_ERROR_P(this, "Invalid State , current %d",
2298 state_manager_.GetStateEnum());
2302 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2303 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2304 static_cast<std::uint32_t>(low_latency_mode_));
2308 LOG_INFO_P(this, "video_high_latency_threshold : [%u]", threshold);
2310 trackrenderer_->SetVideoHighLatencyThreshold(threshold);
2314 bool EsPlayer::SetAudioHighLatencyThreshold(const unsigned int threshold) {
2315 if (state_manager_.GetState() < EsState::kIdle) {
2316 LOG_ERROR_P(this, "Invalid State , current %d",
2317 state_manager_.GetStateEnum());
2321 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2322 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2323 static_cast<std::uint32_t>(low_latency_mode_));
2327 LOG_INFO_P(this, "audio_high_latency_threshold : [%u]", threshold);
2329 trackrenderer_->SetAudioHighLatencyThreshold(threshold);
2333 bool EsPlayer::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
2334 if (frame_count == nullptr) {
2335 LOG_ERROR_P(this, "frame count is nullptr");
2338 if (state_manager_.GetState() < EsState::kReady) {
2339 LOG_ERROR_P(this, "Invalid State , current %d",
2340 state_manager_.GetStateEnum());
2344 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2345 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2346 static_cast<std::uint32_t>(low_latency_mode_));
2350 return trackrenderer_->GetLowLatencyPcmBufferSize(frame_count);
2353 bool EsPlayer::GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
2354 if (frame_count == nullptr) {
2355 LOG_ERROR_P(this, "frame count is nullptr");
2358 if (state_manager_.GetState() < EsState::kReady) {
2359 LOG_ERROR_P(this, "Invalid State , current %d",
2360 state_manager_.GetStateEnum());
2364 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2365 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2366 static_cast<std::uint32_t>(low_latency_mode_));
2370 return trackrenderer_->GetLowLatencyPcmCurrentBufferLevel(frame_count);
2373 bool EsPlayer::GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
2374 if (underrun_count == nullptr) {
2375 LOG_ERROR_P(this, "underrun count is nullptr");
2378 if (state_manager_.GetState() < EsState::kReady) {
2379 LOG_ERROR_P(this, "Invalid State , current %d",
2380 state_manager_.GetStateEnum());
2384 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2385 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2386 static_cast<std::uint32_t>(low_latency_mode_));
2390 return trackrenderer_->GetLowLatencyPcmUnderrunCount(underrun_count);
2393 bool EsPlayer::GetVirtualRscId(const RscType type, int* virtual_id) {
2394 if (virtual_id == nullptr) return false;
2395 if (state_manager_.GetState() < EsState::kReady) {
2396 LOG_ERROR_P(this, "Invalid State , current %d",
2397 state_manager_.GetStateEnum());
2401 return trackrenderer_->GetVirtualRscId(type, virtual_id);
2404 bool EsPlayer::SetAudioPreloading() {
2405 if (state_manager_.GetState() != EsState::kIdle) {
2406 LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
2409 return trackrenderer_->SetAudioPreloading();
2412 void EsPlayer::Init_() {
2414 is_stopped_ = false;
2418 void EsPlayer::MsgTask_() {
2419 std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
2420 while (!is_msg_task_stop_) {
2421 if (msg_queue_.empty()) {
2422 msg_task_cv_.wait(msg_mutex);
2425 msg_queue_.front()->Execute();
2430 while (!msg_queue_.empty()) {
2433 LOG_INFO_P(this, "Stop MsgTask");
2436 void EsPlayer::TrackRendererEventListener::OnEos() {
2437 LOG_ENTER_P(handler_);
2438 if (!handler_->eventlistener_) return;
2439 auto listener = std::bind(&esplusplayer::EsEventListener::OnEos,
2440 handler_->eventlistener_, std::placeholders::_1);
2441 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2442 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2443 handler_->msg_queue_.push(std::move(msg));
2445 handler_->msg_task_cv_.notify_one();
2446 LOG_LEAVE_P(handler_);
2450 void EsPlayer::TrackRendererEventListener::OnSeekDone() {
2451 LOG_ENTER_P(handler_);
2452 if (!handler_->eventlistener_) return;
2453 if (handler_->is_seek_done_need_drop == true) return;
2454 auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
2455 handler_->eventlistener_, std::placeholders::_1);
2456 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2457 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2458 handler_->msg_queue_.push(std::move(msg));
2460 handler_->msg_task_cv_.notify_one();
2461 LOG_LEAVE_P(handler_);
2464 void EsPlayer::TrackRendererEventListener::OnResourceConflicted() {
2465 LOG_ENTER_P(handler_);
2466 if (handler_->is_stopped_) {
2467 LOG_INFO_P(handler_, "LEAVE ~ Stop is called already");
2470 LOG_INFO_P(handler_, "Handling resource conflict...");
2471 handler_->is_resource_conflicted_ = true;
2472 handler_->trackrenderer_->Stop();
2473 if (!handler_->eventlistener_ || handler_->is_stopped_) return;
2475 std::bind(&esplusplayer::EsEventListener::OnResourceConflicted,
2476 handler_->eventlistener_, std::placeholders::_1);
2477 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2478 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2479 handler_->msg_queue_.push(std::move(msg));
2481 if (handler_->is_stopped_) {
2482 LOG_LEAVE_P(handler_);
2485 handler_->msg_task_cv_.notify_one();
2486 LOG_LEAVE_P(handler_);
2489 void EsPlayer::TrackRendererEventListener::OnError(
2490 const ErrorType& error_code) {
2491 if (!handler_->eventlistener_) return;
2492 if (error_code == ErrorType::kResourceLimit) return;
2493 auto listener = std::bind(&esplusplayer::EsEventListener::OnError,
2494 handler_->eventlistener_, std::placeholders::_1,
2495 std::placeholders::_2);
2496 auto msg = es_msg::Error::Make(error_code, listener,
2497 handler_->eventlistener_userdata_);
2499 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2500 handler_->msg_queue_.push(std::move(msg));
2502 handler_->msg_task_cv_.notify_one();
2505 void EsPlayer::TrackRendererEventListener::OnErrorMsg(
2506 const ErrorType& error_code, char* error_msg) {
2507 if (!handler_->eventlistener_) return;
2508 if (error_code == ErrorType::kResourceLimit) return;
2510 std::vector<Track> activeTracks;
2511 track_util::GetActiveTrackList(handler_->track_, activeTracks);
2513 Json::Value message;
2514 message["error_code"] = (int)error_code;
2516 switch (error_code) {
2517 case ErrorType::kNotSupportedVideoCodec:
2518 for (const auto& track : activeTracks) {
2519 if (track.type == kTrackTypeVideo) {
2520 message["codec"] = track.mimetype.c_str();
2521 message["demux"] = track.container_type.c_str();
2522 char json_string[20] = {0};
2524 strncat(json_string, std::to_string(track.width).c_str(), nLen);
2525 nLen = sizeof(json_string) - strlen(json_string) - 1;
2526 if (nLen < 0) nLen = 0;
2527 strncat(json_string, "*", nLen);
2528 nLen = sizeof(json_string) - strlen(json_string) - 1;
2529 if (nLen < 0) nLen = 0;
2530 strncat(json_string, std::to_string(track.height).c_str(), nLen);
2531 message["resolution"] = json_string;
2532 memset(json_string, 0, sizeof(json_string));
2534 strncat(json_string, std::to_string(track.framerate_num).c_str(),
2536 nLen = sizeof(json_string) - strlen(json_string) - 1;
2537 if (nLen < 0) nLen = 0;
2538 strncat(json_string, "/", nLen);
2539 nLen = sizeof(json_string) - strlen(json_string) - 1;
2540 if (nLen < 0) nLen = 0;
2541 strncat(json_string, std::to_string(track.framerate_den).c_str(),
2543 message["fps"] = json_string;
2544 message["detail_info"] = error_msg;
2549 case ErrorType::kNotSupportedAudioCodec:
2556 Json::FastWriter writer;
2557 std::string str = writer.write(message);
2558 LOG_INFO_P(handler_, "error message: %s", str.c_str());
2560 auto listener = std::bind(&esplusplayer::EsEventListener::OnErrorMsg,
2561 handler_->eventlistener_, std::placeholders::_1,
2562 std::placeholders::_2, std::placeholders::_3);
2564 es_msg::ErrorMsg::Make(error_code, str.c_str(), str.size(), listener,
2565 handler_->eventlistener_userdata_);
2567 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2568 handler_->msg_queue_.push(std::move(msg));
2570 handler_->msg_task_cv_.notify_one();
2574 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
2575 const TrackType& type) {
2576 LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
2577 (type == kTrackTypeAudio) ? "audio" : "video");
2579 handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
2581 auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToPrepare,
2582 handler_->eventlistener_, std::placeholders::_1,
2583 std::placeholders::_2);
2584 StreamType stream_type = internal::ConvertToStreamType(type);
2585 auto msg = es_msg::ReadyToPrepare::Make(stream_type, listener,
2586 handler_->eventlistener_userdata_);
2587 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2588 handler_->msg_queue_.push(std::move(msg));
2590 handler_->msg_task_cv_.notify_one();
2593 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
2594 uint64_t offset = handler_->need_data_[type].seek_offset;
2596 LOG_INFO("%p, OnReadyToSeek [%s] offset [%" PRId64 "]", handler_,
2597 (type == kTrackTypeAudio) ? "audio" : "video", offset);
2599 handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
2600 handler_->need_data_[type].seek_offset = 0;
2602 auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToSeek,
2603 handler_->eventlistener_, std::placeholders::_1,
2604 std::placeholders::_2, std::placeholders::_3);
2605 StreamType stream_type = internal::ConvertToStreamType(type);
2606 handler_->es_packet_logger_.ResetLog(stream_type);
2607 auto msg = es_msg::ReadyToSeek::Make(stream_type, offset, listener,
2608 handler_->eventlistener_userdata_);
2609 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2610 handler_->msg_queue_.push(std::move(msg));
2612 handler_->msg_task_cv_.notify_one();
2615 void EsPlayer::TrackRendererEventListener::BufferStatus_(
2616 const TrackType& type, const BufferStatus& status) {
2617 uint64_t byte_size, time_size;
2618 // LOG_INFO_P(handler_, "OnBufferStatus [%s] [%s]",
2619 // (type == kTrackTypeAudio) ? "audio" : "video",
2620 // (status == BufferStatus::kUnderrun) ? "underrun" : "overrun");
2621 handler_->GetSrcQueueCurrentSize_(type, &byte_size, &time_size);
2622 auto listener = std::bind(&esplusplayer::EsEventListener::OnBufferStatus,
2623 handler_->eventlistener_, std::placeholders::_1,
2624 std::placeholders::_2, std::placeholders::_3,
2625 std::placeholders::_4, std::placeholders::_5);
2626 StreamType stream_type = internal::ConvertToStreamType(type);
2628 es_msg::Bufferstatus::Make(stream_type, status, byte_size, time_size,
2629 listener, handler_->eventlistener_userdata_);
2630 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2631 handler_->msg_queue_.push(std::move(msg));
2633 handler_->msg_task_cv_.notify_one();
2636 void EsPlayer::TrackRendererEventListener::OnBufferStatus(
2637 const TrackType& type, const BufferStatus& status) {
2638 if (!handler_->eventlistener_) return;
2639 if (internal::IsLowLatencyModeDisableAVSync(handler_->low_latency_mode_))
2642 if (handler_->need_data_[type].mask == kNeedDataMaskByPrepare &&
2643 status == BufferStatus::kUnderrun) {
2644 ReadyToPrepare_(type);
2645 } else if (handler_->need_data_[type].mask == kNeedDataMaskBySeek &&
2646 status == BufferStatus::kUnderrun) {
2649 BufferStatus_(type, status);
2654 void EsPlayer::TrackRendererEventListener::OnMediaPacketGetTbmBufPtr(
2655 void** tbm_ptr, bool is_scale_change) {
2656 if (!handler_->eventlistener_) return;
2658 handler_->eventlistener_->OnMediaPacketGetTbmBufPtr(tbm_ptr, is_scale_change);
2661 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
2662 const DecodedVideoPacket& packet) {
2663 if (!handler_->eventlistener_) return;
2665 handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
2669 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoRawDecoded(
2670 const DecodedVideoRawModePacket& packet) {
2671 if (handler_->mixer_ticket_ == nullptr) return;
2672 const auto& data = packet.data;
2673 if (packet.type == DecodedVideoRawModePacketType::kPhysicalAddress) {
2674 DecodedRawInfo info;
2675 info.width = packet.width;
2676 info.height = packet.height;
2677 info.y_info.phyaddr = data.raw.y_phyaddr;
2678 info.y_info.viraddr = data.raw.y_viraddr;
2679 info.y_info.linesize = data.raw.y_linesize;
2680 info.uv_info.phyaddr = data.raw.uv_phyaddr;
2681 info.uv_info.viraddr = data.raw.uv_viraddr;
2682 info.uv_info.linesize = data.raw.uv_linesize;
2683 handler_->mixer_ticket_->Render(info);
2684 } else if (packet.type == DecodedVideoRawModePacketType::kTizenBuffer) {
2685 DecodedVideoKeyTypeInfo info;
2686 info.width = packet.width;
2687 info.height = packet.height;
2688 info.key = packet.data.tbm.key;
2689 handler_->mixer_ticket_->Render(info);
2693 bool EsPlayer::MixerListener::OnAudioFocusChanged(bool active) {
2694 LOG_INFO_P(handler_, "focused [%d]", active);
2695 std::unique_lock<std::mutex> lock(handler_->audio_focus_m_);
2696 if (handler_->state_manager_.GetState() < EsState::kReady) {
2697 handler_->is_audio_focused_ = active;
2701 Track activated_track;
2702 track_util::GetActiveTrack(handler_->track_, kTrackTypeAudio,
2704 LOG_INFO_P(handler_, "Activate audio track");
2706 std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2707 handler_->eos_status_ =
2708 internal::ResetEosStatus(kTrackTypeAudio, handler_->eos_status_);
2710 return handler_->trackrenderer_->Activate(kTrackTypeAudio, activated_track);
2712 LOG_INFO_P(handler_, "Deactivate audio track");
2713 handler_->is_audio_focused_ = false;
2715 std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2716 handler_->eos_status_ |= EosStatus::kAudioEos;
2718 return handler_->trackrenderer_->Deactivate(kTrackTypeAudio);
2721 bool EsPlayer::MixerListener::OnUpdateDisplayInfo(const DisplayInfo& cur_info,
2722 DisplayInfo* new_info) {
2723 new_info->geometry = handler_->mixerticket_roi_;
2724 new_info->visible_status =
2725 handler_->is_visible_ ? VisibleStatus::kVisible : VisibleStatus::kHide;
2731 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
2732 const uint64_t offset) {
2733 if (!handler_->eventlistener_) return;
2735 if (handler_->need_data_[type].mask != kNeedDataMaskByPrepare) {
2736 handler_->need_data_[type].mask |= kNeedDataMaskBySeek;
2737 handler_->need_data_[type].seek_offset = offset;
2742 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
2744 if (size <= 0) return;
2745 if (!handler_->eventlistener_) return;
2746 auto listener = std::bind(&esplusplayer::EsEventListener::OnClosedCaptionData,
2747 handler_->eventlistener_, std::placeholders::_1,
2748 std::placeholders::_2, std::placeholders::_3);
2749 auto msg = es_msg::ClosedCaption::Make(data, size, listener,
2750 handler_->eventlistener_userdata_);
2751 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2752 handler_->msg_queue_.push(std::move(msg));
2754 handler_->msg_task_cv_.notify_one();
2757 void EsPlayer::TrackRendererEventListener::OnFlushDone() {
2758 LOG_ENTER_P(handler_);
2759 if (!handler_->eventlistener_) return;
2761 auto listener = std::bind(&esplusplayer::EsEventListener::OnFlushDone,
2762 handler_->eventlistener_, std::placeholders::_1);
2764 es_msg::FlushDone::Make(listener, handler_->eventlistener_userdata_);
2765 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2766 handler_->msg_queue_.push(std::move(msg));
2768 handler_->msg_task_cv_.notify_one();
2769 LOG_LEAVE_P(handler_);
2772 void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
2773 const EventMsg& msg_data) {
2774 if (!handler_->eventlistener_) return;
2776 auto listener = std::bind(&esplusplayer::EsEventListener::OnEvent,
2777 handler_->eventlistener_, std::placeholders::_1,
2778 std::placeholders::_2, std::placeholders::_3);
2779 auto msg = es_msg::OnEvent::Make(event, msg_data, listener,
2780 handler_->eventlistener_userdata_);
2781 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2782 handler_->msg_queue_.push(std::move(msg));
2784 handler_->msg_task_cv_.notify_one();
2785 LOG_LEAVE_P(handler_);
2789 void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
2790 LOG_ENTER_P(handler_);
2791 if (!handler_->eventlistener_) return;
2792 auto listener = std::bind(&esplusplayer::EsEventListener::OnFirstDecodingDone,
2793 handler_->eventlistener_, std::placeholders::_1);
2794 auto msg = es_msg::FirstDecodingDone::Make(listener,
2795 handler_->eventlistener_userdata_);
2796 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2797 handler_->msg_queue_.push(std::move(msg));
2799 handler_->msg_task_cv_.notify_one();
2800 LOG_LEAVE_P(handler_);
2803 void EsPlayer::TrackRendererEventListener::OnVideoDecoderUnderrun() {
2804 LOG_ENTER_P(handler_);
2805 if (!handler_->eventlistener_) return;
2807 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2808 handler_->state_manager_.GetState() != EsState::kPaused) {
2813 std::bind(&esplusplayer::EsEventListener::OnVideoDecoderUnderrun,
2814 handler_->eventlistener_, std::placeholders::_1);
2815 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2816 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2817 handler_->msg_queue_.push(std::move(msg));
2819 handler_->msg_task_cv_.notify_one();
2820 LOG_LEAVE_P(handler_);
2823 void EsPlayer::TrackRendererEventListener::OnVideoLatencyStatus(
2824 const LatencyStatus& latency_status) {
2825 LOG_ENTER_P(handler_);
2826 if (!handler_->eventlistener_) return;
2828 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2829 handler_->state_manager_.GetState() != EsState::kPaused) {
2833 auto listener = std::bind(
2834 &esplusplayer::EsEventListener::OnVideoLatencyStatus,
2835 handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2837 auto msg = es_msg::PacketLatencyStatus::Make(
2838 latency_status, listener, handler_->eventlistener_userdata_);
2840 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2841 handler_->msg_queue_.push(std::move(msg));
2843 handler_->msg_task_cv_.notify_one();
2844 LOG_LEAVE_P(handler_);
2847 void EsPlayer::TrackRendererEventListener::OnAudioLatencyStatus(
2848 const LatencyStatus& latency_status) {
2849 LOG_ENTER_P(handler_);
2850 if (!handler_->eventlistener_) return;
2852 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2853 handler_->state_manager_.GetState() != EsState::kPaused) {
2857 auto listener = std::bind(
2858 &esplusplayer::EsEventListener::OnAudioLatencyStatus,
2859 handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2861 auto msg = es_msg::PacketLatencyStatus::Make(
2862 latency_status, listener, handler_->eventlistener_userdata_);
2864 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2865 handler_->msg_queue_.push(std::move(msg));
2867 handler_->msg_task_cv_.notify_one();
2868 LOG_LEAVE_P(handler_);
2871 void EsPlayer::TrackRendererEventListener::OnVideoHighLatency() {
2872 LOG_ENTER_P(handler_);
2873 if (!handler_->eventlistener_) return;
2875 auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoHighLatency,
2876 handler_->eventlistener_, std::placeholders::_1);
2878 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2880 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2881 handler_->msg_queue_.push(std::move(msg));
2883 handler_->msg_task_cv_.notify_one();
2884 LOG_LEAVE_P(handler_);
2888 void EsPlayer::TrackRendererEventListener::OnAudioHighLatency() {
2889 LOG_ENTER_P(handler_);
2890 if (!handler_->eventlistener_) return;
2892 auto listener = std::bind(&esplusplayer::EsEventListener::OnAudioHighLatency,
2893 handler_->eventlistener_, std::placeholders::_1);
2895 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2897 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2898 handler_->msg_queue_.push(std::move(msg));
2900 handler_->msg_task_cv_.notify_one();
2901 LOG_LEAVE_P(handler_);
2904 void EsPlayer::TrackRendererEventListener::OnVideoFrameDropped(
2905 const uint64_t& count) {
2906 if (!handler_->eventlistener_) return;
2908 handler_->eventlistener_->OnVideoFrameDropped(
2909 count, handler_->eventlistener_userdata_);
2913 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2914 handler_->state_manager_.GetState() != EsState::kPaused) {
2918 auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoFrameDropped,
2919 handler_->eventlistener_, std::placeholders::_1,
2920 std::placeholders::_2);
2922 auto msg = es_msg::FrameDroppedCount::Make(
2923 count, listener, handler_->eventlistener_userdata_);
2925 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2926 handler_->msg_queue_.push(std::move(msg));
2928 handler_->msg_task_cv_.notify_one();
2929 LOG_LEAVE_P(handler_);
2933 void EsPlayer::TrackRendererEventListener::OnDecoderInputBufferTime(
2934 const TrackType& type, const DecoderBufferTime& time) {
2935 if (!handler_->eventlistener_) return;
2937 StreamType stream_type = internal::ConvertToStreamType(type);
2938 handler_->eventlistener_->OnDecoderInputBufferTime(stream_type, time);
2941 void EsPlayer::TrackRendererEventListener::OnDecoderOutputBufferTime(
2942 const TrackType& type, const DecoderBufferTime& time) {
2943 if (!handler_->eventlistener_) return;
2945 StreamType stream_type = internal::ConvertToStreamType(type);
2946 handler_->eventlistener_->OnDecoderOutputBufferTime(stream_type, time);
2951 bool EsPlayer::SetVideoScanType(const PlayerVideoScanType type) {
2953 if (state_manager_.GetState() != EsState::kIdle) {
2954 LOG_ERROR_P(this, "Invalid State , current %d",
2955 state_manager_.GetStateEnum());
2958 if (type == kPlayerVideoScanTypeProgressive) set_video_progressive_ = 1;
2961 bool EsPlayer::SetTimeUnitType(const PlayerTimeUnitType type) {
2963 if (state_manager_.GetState() != EsState::kIdle) {
2964 LOG_ERROR_P(this, "Invalid State , current %d",
2965 state_manager_.GetStateEnum());
2968 LOG_INFO_P(this, "PlayerTimeUnitType [%s]",
2969 (type == kPlayerTimeUnitTypeMs) ? "Ms" : "Us");
2970 time_unit_type = type;
2974 bool EsPlayer::GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) {
2975 if (!time_in_milliseconds) return false;
2976 if (state_manager_.GetState() <= EsState::kReady) {
2977 *time_in_milliseconds = 0;
2980 return trackrenderer_->GetDecodingTime(type, time_in_milliseconds);
2983 bool EsPlayer::SetVideoStreamRotationInfo(const VideoRotation& rotation) {
2985 if (state_manager_.GetState() < EsState::kIdle) {
2986 LOG_ERROR_P(this, "Invalid State , current %d",
2987 state_manager_.GetStateEnum());
2990 video_rotate_ = rotation;
2991 return trackrenderer_->SetVideoStreamRotationInfo(rotation);
2994 bool EsPlayer::GetVideoStreamRotationInfo(VideoRotation* rotation) {
2996 if (state_manager_.GetState() < EsState::kIdle) {
2997 LOG_ERROR_P(this, "Invalid State , current %d",
2998 state_manager_.GetStateEnum());
3001 *rotation = video_rotate_;
3005 bool EsPlayer::SetSimpleMixOutBufferLevel(
3006 const PlayerSimpleMixOutBufferLevel level) {
3007 if (state_manager_.GetState() == EsState::kNone) {
3008 LOG_ERROR_P(this, "Invalid State");
3011 int converted_level = 1;
3012 if (level == kPlayerSimpleMixOutBufferLow) {
3013 converted_level = 0;
3014 } else if (level == kPlayerSimpleMixOutBufferMid) {
3015 converted_level = 1;
3016 } else if (level == kPlayerSimpleMixOutBufferHigh) {
3017 converted_level = 2;
3020 return trackrenderer_->SetSimpleMixOutBufferLevel(converted_level);
3023 #ifndef TIZEN_FEATURE_PUBLIC
3024 kpi::EsCodecLoggerKeys EsPlayer::MakeKpiKeys_() {
3025 kpi::EsCodecLoggerKeys event_info;
3026 event_info.app_id = app_info_.id;
3027 if (submit_data_type_ == SubmitDataType::kCleanData) {
3028 event_info.is_clean = true;
3030 event_info.is_clean = false;
3031 event_info.key_system = key_system_;
3034 for (const auto& track : track_) {
3035 if (track.type == kTrackTypeVideo) {
3036 event_info.v_codec = track.mimetype;
3037 event_info.v_codec_version = track.version;
3038 event_info.width = track.maxwidth;
3039 event_info.height = track.maxheight;
3040 } else if (track.type == kTrackTypeAudio) {
3041 event_info.a_codec = track.mimetype;
3048 void EsPlayer::InitValuesFromIni_() {
3049 force_audio_swdecoder_use_ = es_conf::ini_property["force_sw_audio_codec"];
3050 force_video_swdecoder_use_ = es_conf::ini_property["force_sw_video_codec"];
3053 #ifdef TIZEN_FEATURE_PUBLIC
3054 bool EsPlayer::EnableVideoHole(bool value) {
3055 if (state_manager_.GetState() < EsState::kIdle) {
3056 LOG_ERROR_P(this, "Invalid State , current %d",
3057 state_manager_.GetStateEnum());
3060 return trackrenderer_->EnableVideoHole(value);
3063 bool EsPlayer::SetSoundStreamInfo(const sound_stream_info_h stream_info) {
3064 if (state_manager_.GetState() != EsState::kIdle) {
3065 LOG_ERROR_P(this, "Invalid State , current %d",
3066 state_manager_.GetStateEnum());
3070 LOG_ERROR_P(this, "stream_info is null");
3073 return trackrenderer_->SetSoundStreamInfo(stream_info);
3079 void LoadIniProperty(const Json::Value& root) {
3081 std::vector<std::string> booleanKeys {
3083 "force_sw_audio_codec",
3084 "force_sw_video_codec",
3085 "fallback_to_sw_audio_codec",
3086 "fallback_to_sw_video_codec"
3089 gst_util::GstInit(root);
3090 std::for_each(booleanKeys.begin(), booleanKeys.end(), [&](const auto& key) {
3091 es_conf::ini_property[key] = root.get(key, "").asBool();
3092 LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
3096 bool LoadIniFile() {
3097 const char* path = esplusplayer_cfg::GetIniPath();
3098 LOG_INFO("path : %s", path);
3099 std::streampos size;
3100 char* buf = nullptr;
3101 std::ifstream file(path, std::ios::binary | std::ios::ate);
3102 if (file.is_open() == false) {
3103 gst_util::GstInit();
3104 LOG_ERROR("Can't open file !!");
3107 BOOST_SCOPE_EXIT(&file) { file.close(); }
3108 BOOST_SCOPE_EXIT_END
3110 size = file.tellg();
3112 LOG_ERROR("Wrong file size");
3116 buf = static_cast<char*>(calloc(size, sizeof(char)));
3117 if (buf == nullptr) {
3118 LOG_ERROR("Fail to calloc buf");
3121 BOOST_SCOPE_EXIT(&buf) {
3124 BOOST_SCOPE_EXIT_END
3126 file.seekg(0, std::ios::beg);
3127 file.read(buf, size);
3129 std::string config = buf;
3131 Json::Reader reader;
3132 if (!reader.parse(config, root)) {
3133 LOG_ERROR("Fail to parse configuration file %s",
3134 (reader.getFormatedErrorMessages()).c_str());
3138 es_conf::LoadIniProperty(root);
3142 } // namespace es_conf
3144 } // namespace esplusplayer