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 #include "core/utils/caf_logger.h"
22 #include "core/utils/performance_checker.h"
23 #include "core/utils/plusplayer_cfg.h"
24 #include "core/utils/plusplayer_log.h"
25 #include "core/videoframetypestrategy.h"
26 #include "esplayer/esplayer_drm.h"
27 #include "json/json.h"
29 namespace esplusplayer {
33 // get values from /etc/multimedia/esplusplayer.ini
34 static std::once_flag loaded;
35 static std::map<std::string, bool> ini_property;
38 void LoadIniProperty(const Json::Value& root);
40 } // namespace es_conf
44 std::uint64_t ConvertMsToNs(std::uint64_t ms) {
45 constexpr std::uint64_t ns_unit = 1000000;
46 if (ms * ns_unit > G_MAXUINT64) return G_MAXUINT64;
50 std::uint64_t ConvertNsToMs(std::uint64_t ns) {
51 constexpr std::uint64_t ms_unit = 1000000;
55 std::int64_t ConvertMsToNs(std::int64_t ms) {
56 constexpr std::int64_t ns_unit = 1000000;
57 if (ms * ns_unit > G_MAXINT64) return G_MAXINT64;
61 std::int64_t ConvertNsToMs(std::int64_t ns) {
62 constexpr std::int64_t ms_unit = 1000000;
66 std::uint64_t ConvertUsToNs(std::uint64_t us) {
67 constexpr std::uint64_t ns_unit = 1000;
68 if (us * ns_unit > G_MAXUINT64) return G_MAXUINT64;
72 std::uint64_t ConvertNsToUs(std::uint64_t ns) {
73 constexpr std::uint64_t us_unit = 1000;
77 std::int64_t ConvertUsToNs(std::int64_t us) {
78 constexpr std::int64_t ns_unit = 1000;
79 if (us * ns_unit > G_MAXINT64) return G_MAXINT64;
83 std::int64_t ConvertNsToUs(std::int64_t ns) {
84 constexpr std::int64_t us_unit = 1000;
89 std::string GetStringFromMatroskaColor(const MatroskaColor& color_info) {
90 std::ostringstream oss;
91 oss << "matrixCoefficients:" << color_info.matrix_coefficients
92 << " bitsPerChannel:" << color_info.bits_per_channel
93 << " chromaSubsamplingHorz:" << color_info.chroma_subsampling_horizontal
94 << " chromaSubsamplingVert:" << color_info.chroma_subsampling_vertical
95 << " cbSubsamplingHorz:" << color_info.cb_subsampling_horizontal
96 << " cbSubsamplingVert:" << color_info.cb_subsampling_vertical
97 << " chromaSitingHorz:" << color_info.chroma_siting_horizontal
98 << " chromaSitingVert:" << color_info.chroma_siting_vertical
99 << " range:" << color_info.range
100 << " transferCharacteristics:" << color_info.transfer_characteristics
101 << " primaries:" << color_info.primaries
102 << " maxCLL:" << color_info.max_cll << " maxFALL:" << color_info.max_fall
103 << " RX:" << color_info.metadata.primary_r_chromaticity_x
104 << " RY:" << color_info.metadata.primary_r_chromaticity_y
105 << " GX:" << color_info.metadata.primary_g_chromaticity_x
106 << " GY:" << color_info.metadata.primary_g_chromaticity_y
107 << " BX:" << color_info.metadata.primary_b_chromaticity_x
108 << " BY:" << color_info.metadata.primary_b_chromaticity_y
109 << " wX:" << color_info.metadata.white_point_chromaticity_x
110 << " wY:" << color_info.metadata.white_point_chromaticity_y
111 << " luminanceMax:" << color_info.metadata.luminance_max
112 << " luminanceMin:" << color_info.metadata.luminance_min
113 << " isHDR10p:" << color_info.is_hdr_10p;
121 // const std::uint64_t kMaxByteOfVideoSrcQueue = 70 * 1024 * 1024; // 70 MB
122 // const std::uint64_t kMaxByteOfAudioSrcQueue = 10 * 1024 * 1024; // 10 MB
123 // const std::uint64_t kMaxTimeOfVideoSrcQueue = 10000000000; // 10 s
124 // const std::uint64_t kMaxTimeOfAudioSrcQueue = 10000000000; // 10 s
126 constexpr uint32_t kNdecodingMode = 0x04;
128 enum VolumeLevel { kVolumeMin = 0, kVolumeMax = 100 };
129 constexpr int kMaxFhdWidth = 1920;
130 constexpr int kMaxFhdHeight = 1080;
132 inline bool IsPcmMimeType(const std::string& mimetype) {
133 return (mimetype.find("audio/x-raw") != std::string::npos);
135 inline bool IsForcedUnsetTz(const Track& track, const std::string& id) {
136 if ((track.type == kTrackTypeAudio) && strstr(id.c_str(), "netflix")) {
141 inline bool IsAacCodec(const Track& track) {
142 return (track.mimetype.find("audio/mpeg") != std::string::npos &&
145 inline bool IsEac3Codec(const std::string& mimetype) {
146 return mimetype.find("audio/x-eac3") != std::string::npos;
148 inline bool IsAc3Codec(const std::string& mimetype) {
149 return mimetype.find("audio/x-ac3") != std::string::npos;
152 inline bool IsFlacCodec(const std::string& mimetype) {
153 return mimetype.find("audio/x-ffmpeg-parsed-flac") != std::string::npos;
156 inline bool IsAvailableCodecSwitch(const Track& track) {
157 if (internal::IsAacCodec(track) || internal::IsAc3Codec(track.mimetype) ||
158 internal::IsEac3Codec(track.mimetype))
163 int ResetEosStatus(const TrackType& type, int eos_status) {
164 if (type == kTrackTypeVideo)
165 eos_status &= ~EosStatus::kVideoEos;
166 else if (type == kTrackTypeAudio)
167 eos_status &= ~EosStatus::kAudioEos;
172 void MakeTrustZoneTracks(std::vector<Track>& tracks,
173 const std::string& app_id) {
174 for (auto& track : tracks) {
175 const bool is_already_tz_type =
176 (track.mimetype.find("_tz", track.mimetype.length() - 3) !=
178 if (is_already_tz_type) {
181 track.streamtype = track.mimetype;
182 bool is_flac = internal::IsFlacCodec(track.mimetype);
183 if ((track.use_swdecoder && !is_flac) || IsPcmMimeType(track.mimetype) ||
184 IsForcedUnsetTz(track, app_id))
187 track.mimetype = track.mimetype + "_tz";
192 void UpdateCodecTypeTracks(std::vector<Track>& tracks,
193 const PlayerAudioCodecType& audio_codec_type,
194 const PlayerVideoCodecType& video_codec_type,
195 bool force_audio_swdecoder_use,
196 bool force_video_swdecoder_use) {
197 for (auto& track : tracks) {
198 switch (track.type) {
199 case kTrackTypeAudio: {
200 if (audio_codec_type == kPlayerAudioCodecTypeSW ||
201 force_audio_swdecoder_use)
202 track.use_swdecoder = true;
204 track.use_swdecoder = false;
207 case kTrackTypeVideo: {
208 if (video_codec_type == kPlayerVideoCodecTypeSW ||
209 force_video_swdecoder_use)
210 track.use_swdecoder = true;
212 track.use_swdecoder = false;
220 inline bool IsSupportedDrmType(const drm::Type& drm_type) {
221 static const std::map<drm::Type, bool> kSupportedDrmType = {
222 {drm::Type::kPlayready, true},
224 if (kSupportedDrmType.count(drm_type) == 0) return false;
225 return kSupportedDrmType.at(drm_type);
227 inline void ResetDrmProperty(drm::Property& drm_property) {
228 drm_property = drm::Property();
230 inline StreamType ConvertToStreamType(TrackType type) {
231 return (type == kTrackTypeAudio) ? StreamType::kAudio : StreamType::kVideo;
233 struct AppsrcQueueSizeOption {
234 std::uint64_t current_size = 0;
235 std::uint64_t max_size = 0;
236 std::uint32_t threshold = 0;
238 inline bool IsUnderRun(AppsrcQueueSizeOption& byte_based,
239 AppsrcQueueSizeOption& time_based) {
240 bool need_data_by_byte = false, need_data_by_time = false;
241 need_data_by_byte = (byte_based.max_size > 0) &&
242 (byte_based.current_size * 100 / byte_based.max_size <=
243 byte_based.threshold);
244 need_data_by_time = (time_based.max_size > 0) &&
245 (time_based.current_size * 100 / time_based.max_size <=
246 time_based.threshold);
247 if (need_data_by_byte || need_data_by_time)
252 inline bool IsLowLatencyModeDisableAVSync(std::uint32_t mode) {
253 constexpr std::uint32_t kAVSync = kLowLatencyModeDisableAVSync;
254 return (mode & kAVSync) ? true : false;
256 inline bool IsLowLatencyModeDisablePreroll(std::uint32_t mode) {
257 constexpr std::uint32_t kPreroll = kLowLatencyModeDisablePreroll;
258 return (mode & kPreroll) ? true : false;
260 inline bool IsLowLatencyMode(std::uint32_t mode) {
261 return (mode != static_cast<std::uint32_t>(kLowLatencyModeNone)) ? true
264 inline bool IsSupportedTsOffset(std::uint32_t mode) {
265 return IsLowLatencyMode(mode) && !IsLowLatencyModeDisableAVSync(mode) ? true
269 inline bool IsLowLatencyModeEnableGameMode(std::uint32_t mode) {
270 constexpr std::uint32_t kGameMode = kLowLatencyModeEnableGameMode ^
271 kLowLatencyModeAudio ^
272 kLowLatencyModeVideo;
273 return (mode & kGameMode) ? true : false;
276 inline bool IsLowLatencyModeForCatchUp(std::uint32_t mode) {
277 return IsLowLatencyModeDisableAVSync(mode) &&
278 IsLowLatencyModeEnableGameMode(mode)
283 inline bool IsExclusiveLowLatencyMode(std::uint32_t current_mode,
284 std::uint32_t set_mode) {
285 std::uint32_t exclusive_mode = 0;
286 exclusive_mode |= static_cast<std::uint32_t>(kLowLatencyModeEnableGameMode);
288 static_cast<std::uint32_t>(kLowLatencyModeDisableVideoQuality);
290 std::uint32_t new_mode = current_mode | set_mode;
291 return (exclusive_mode == (new_mode & exclusive_mode)) ? true : false;
293 } // namespace internal
295 EsPlayer::EsPlayer() {
296 std::call_once(es_conf::loaded, [this]() { es_conf::LoadIniFile(); });
297 if (CafLogger::Initialize() != true) {
298 LOG_INFO("CAF Dbus not connect.");
300 InitValuesFromIni_();
303 EsPlayer::~EsPlayer() {
309 bool EsPlayer::Open() {
310 LOG_INFO_P(this, "state manager > %p", &state_manager_);
312 state_manager_.Start();
313 auto op = [this]() noexcept -> bool {
314 const auto start = performance_checker::Start();
315 if (trackrenderer_) {
316 assert(0 && "trackrenderer already exist");
319 std::async(std::launch::async, &EsPlayer::MsgTask_, this);
320 trackrenderer_ = TrackRendererAdapter::Create();
321 assert(trackrenderer_);
323 trackrenderer_->RegisterListenerForEsplayer(
324 trackrenderer_event_listener_.get());
325 performance_checker::End(start, "Open");
328 CafLogger::SetUniqueNumber();
329 caf_unique_number = CafLogger::GetUniqueNumber();
330 CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
332 es_event::Open event{op};
333 return state_manager_.ProcessEvent(event);
336 bool EsPlayer::Close() {
338 std::lock_guard<std::mutex> lk(submit_mutex_);
339 if (state_manager_.GetState() >= EsState::kIdle) {
342 auto op = [this]() noexcept {
343 if (is_msg_task_stop_ == false) {
345 std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
346 is_msg_task_stop_ = true;
348 msg_task_cv_.notify_one();
349 if (msg_handler_task_.valid()) msg_handler_task_.wait();
352 if (trackrenderer_) trackrenderer_.reset();
353 ResetContextForClose_();
357 es_event::Close event{op};
358 state_manager_.ProcessEvent(event);
359 state_manager_.Stop();
363 bool EsPlayer::Deactivate(const StreamType type) {
365 if (state_manager_.GetState() < EsState::kReady) {
366 LOG_ERROR_P(this, "Invalid State , current %d",
367 state_manager_.GetStateEnum());
371 if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
373 this, "can't deactivate audio stream, mixer will control audio stream");
377 if (!trackrenderer_->Deactivate(static_cast<TrackType>(type))) {
381 std::lock_guard<std::mutex> lock(eos_mutex_);
383 case StreamType::kAudio:
384 eos_status_ |= EosStatus::kAudioEos;
386 case StreamType::kVideo:
387 eos_status_ |= EosStatus::kVideoEos;
393 for (auto& track : track_) {
394 if (track.type == static_cast<TrackType>(type)) {
395 track.active = false;
401 bool EsPlayer::Activate(const StreamType type) {
403 if (state_manager_.GetState() < EsState::kReady) {
404 LOG_ERROR_P(this, "Invalid State , current %d",
405 state_manager_.GetStateEnum());
409 if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
411 "can't activate audio stream, mixer will control audio stream");
415 if (!track_.empty()) {
416 auto has_track = [type](const Track& item) -> bool {
417 return item.type == static_cast<TrackType>(type);
419 auto target = std::find_if(track_.begin(), track_.end(), has_track);
420 if (target == track_.end()) {
421 LOG_ERROR_P(this, "there is no track to activate");
424 if (target->active != false) {
425 LOG_ERROR_P(this, "The track should be deactivated in advance.");
428 target->active = true;
429 internal::UpdateCodecTypeTracks(
430 track_, audio_codec_type_, video_codec_type_,
431 force_audio_swdecoder_use_, force_video_swdecoder_use_);
432 if (drm_property_.external_decryption) {
433 internal::MakeTrustZoneTracks(track_, app_info_.id);
435 SetTrackRendererAttributes_();
436 if (type == StreamType::kVideo) {
439 trackrenderer_->SetVideoFrameBufferType(
440 VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
443 trackrenderer_->SetVideoFrameBufferType(VideoFrameTypeStrategyPtr(
444 new DefaultVideoFrameTypeStrategy(vidoe_frame_buffer_type_)));
446 if (!trackrenderer_->Activate(target->type, *target)) {
447 target->active = false;
451 internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
457 bool EsPlayer::DeactivateAudio() {
459 if (state_manager_.GetState() < EsState::kIdle) {
460 LOG_ERROR_P(this, "Invalid State , current %d",
461 state_manager_.GetStateEnum());
465 if (!enable_audio_pipeline_handle_) {
467 this, "can't deactivate audio stream, mixer will control audio stream");
471 if (!trackrenderer_->DeactivateAudio()) {
474 is_audio_stream_info_frozen_ = true;
478 bool EsPlayer::ActivateAudio() {
480 const StreamType type = StreamType::kAudio;
481 if (state_manager_.GetState() < EsState::kReady) {
482 LOG_ERROR_P(this, "Invalid State , current %d",
483 state_manager_.GetStateEnum());
487 if (!enable_audio_pipeline_handle_) {
489 "can't activate audio stream, mixer will control audio stream");
493 if (track_.empty()) {
496 if (!trackrenderer_->ActivateAudio()) {
500 internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
504 bool EsPlayer::Start() {
507 LOG_ERROR_P(this, "Stop already, no need to Start,leave...");
510 auto op = [this]() noexcept {
511 if (!trackrenderer_->Start()) {
517 CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
519 es_event::Start event{op};
520 return state_manager_.ProcessEvent(event);
523 bool EsPlayer::Stop() {
526 auto stop = [this]() noexcept -> bool {
527 const auto start = performance_checker::Start();
528 if (trackrenderer_) trackrenderer_->Stop();
529 ResetContextForStop_();
531 if (mixer_ticket_) mixer_ticket_.reset();
533 performance_checker::End(start, "Stop");
536 for (const auto& track : track_) {
537 es_packet_logger_.PrintStoredPacketInfo(
538 internal::ConvertToStreamType(track.type), true);
540 es_event::Stop event{stop};
541 bool res = state_manager_.ProcessEventStop(event);
543 if (preparetask_.valid()) {
544 LOG_INFO_P(this, "Stopped , Wait Prepare() finish...");
546 LOG_INFO_P(this, "Wait , Wait Prepare() Done...");
549 CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
550 CafLogger::StopLoggingThread();
555 void EsPlayer::SetTrackRendererAttributes_() {
556 if (trackrenderer_ == nullptr) return;
557 trackrenderer_->SetAttribute(
558 TrackRendererAdapter::Attribute::kVideoQueueMaxByte,
559 src_queue_size_.kMaxByteOfVideoSrcQueue);
560 trackrenderer_->SetAttribute(
561 TrackRendererAdapter::Attribute::kAudioQueueMaxByte,
562 src_queue_size_.kMaxByteOfAudioSrcQueue);
563 trackrenderer_->SetAttribute(
564 TrackRendererAdapter::Attribute::kVideoMinByteThreshold,
565 src_queue_size_.kMinByteThresholdOfVideoSrcQueue);
566 trackrenderer_->SetAttribute(
567 TrackRendererAdapter::Attribute::kAudioMinByteThreshold,
568 src_queue_size_.kMinByteThresholdOfAudioSrcQueue);
569 trackrenderer_->SetAttribute(
570 TrackRendererAdapter::Attribute::kVideoQueueMaxTime,
571 util::ConvertMsToNs(src_queue_size_.kMaxTimeOfVideoSrcQueue));
572 trackrenderer_->SetAttribute(
573 TrackRendererAdapter::Attribute::kAudioQueueMaxTime,
574 util::ConvertMsToNs(src_queue_size_.kMaxTimeOfAudioSrcQueue));
575 trackrenderer_->SetAttribute(
576 TrackRendererAdapter::Attribute::kVideoMinTimeThreshold,
577 src_queue_size_.kMinTimeThresholdOfVideoSrcQueue);
578 trackrenderer_->SetAttribute(
579 TrackRendererAdapter::Attribute::kAudioMinTimeThreshold,
580 src_queue_size_.kMinTimeThresholdOfAudioSrcQueue);
581 trackrenderer_->SetAttribute(
582 TrackRendererAdapter::Attribute::kUnlimitedMaxBufferMode,
583 unlimited_max_buffer_mode_);
584 trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kLowLatencyMode,
586 trackrenderer_->SetAttribute(
587 TrackRendererAdapter::Attribute::kVideoFramePeekMode,
588 video_frame_peek_mode_);
589 trackrenderer_->SetAttribute(
590 TrackRendererAdapter::Attribute::kAccurateSeekMode, accurate_seek_mode_);
591 trackrenderer_->SetAttribute(
592 TrackRendererAdapter::Attribute::kVideoPreDisplayMode,
593 video_pre_display_mode_);
594 if (resume_time_.is_set) {
595 trackrenderer_->SetAttribute(
596 TrackRendererAdapter::Attribute::kStartRenderingTime,
598 resume_time_.is_set = false;
600 trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
602 trackrenderer_->SetAttribute(
603 TrackRendererAdapter::Attribute::kAlternativeVideoResource,
604 alternative_video_resource_);
605 trackrenderer_->SetAttribute(
606 TrackRendererAdapter::Attribute::kVideoDecodingMode,
607 video_decoding_mode_);
608 trackrenderer_->SetAttribute(
609 TrackRendererAdapter::Attribute::kVideoProgressiveMode,
610 set_video_progressive_);
611 trackrenderer_->SetAttribute(
612 TrackRendererAdapter::Attribute::kPlayerTimeUnitType,
613 static_cast<std::uint32_t>(time_unit_type));
618 bool EsPlayer::PrepareVideoMixingMode_(std::vector<Track>* tracks) {
620 mixer_ticket_->Prepare();
621 if (enable_rsc_alloc_handle_) return true;
622 ResourceType type = ResourceType::kHwMain;
623 if (!mixer_ticket_->GetAvailableResourceType(ResourceCategory::kVideoDecoder,
625 LOG_ERROR_P(this, "no available resource");
628 if (!mixer_ticket_->Alloc(ResourceCategory::kVideoDecoder, type)) {
629 LOG_ERROR_P(this, "fail to alloc resource [%d]", static_cast<int>(type));
633 if (type == ResourceType::kHwSub) {
634 alternative_video_resource_ = 1;
635 } else if (type == ResourceType::kSw) {
636 for (auto it = tracks->begin(); it != tracks->end(); ++it) {
637 if (it->type == kTrackTypeVideo) {
638 it->use_swdecoder = true;
642 } else if (type == ResourceType::kNdecoder) {
643 video_decoding_mode_ = internal::kNdecodingMode;
650 bool EsPlayer::Prepare_() {
653 LOG_ERROR_P(this, "Stop already, no need to prepare,leave...");
656 auto op = [this]() noexcept -> bool {
657 const auto start = performance_checker::Start();
659 internal::UpdateCodecTypeTracks(
660 track_, audio_codec_type_, video_codec_type_,
661 force_audio_swdecoder_use_, force_video_swdecoder_use_);
662 if (drm_property_.external_decryption) {
663 internal::MakeTrustZoneTracks(track_, app_info_.id);
665 std::vector<Track> active_track;
666 if (!track_util::GetActiveTrackList(track_, active_track)) {
669 trackrenderer_->SetIniProperty(es_conf::ini_property);
672 trackrenderer_->SetVideoFrameBufferType(
673 VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
674 if (!PrepareVideoMixingMode_(&active_track)) {
675 LOG_ERROR_P(this, "fail to prepare mixing mode");
679 std::unique_lock<std::mutex> lock(audio_focus_m_);
680 if (!enable_audio_pipeline_handle_ && !is_audio_focused_) {
681 for (auto it = active_track.begin(); it != active_track.end(); ++it) {
682 if (it->type == kTrackTypeAudio) {
683 active_track.erase(it);
684 LOG_INFO_P(this, "erase audio track is_audio_focused_ [%d]",
691 for (const auto& track : active_track) {
692 switch (track.type) {
693 case kTrackTypeAudio: {
694 std::lock_guard<std::mutex> lock2(eos_mutex_);
695 eos_status_ = internal::ResetEosStatus(kTrackTypeAudio, eos_status_);
696 need_data_[track.type].mask |= kNeedDataMaskByPrepare;
699 case kTrackTypeVideo: {
700 std::lock_guard<std::mutex> lock2(eos_mutex_);
701 eos_status_ = internal::ResetEosStatus(kTrackTypeVideo, eos_status_);
702 need_data_[track.type].mask |= kNeedDataMaskByPrepare;
709 SetTrackRendererAttributes_();
710 trackrenderer_->SetTrack(active_track);
711 if (!trackrenderer_->Prepare()) {
714 performance_checker::End(start, "Prepare");
718 CafLogger::StartLoggingThread();
719 CafLogger::LogMessage(CafEventType::kReady, caf_unique_number);
721 es_event::Prepare event{op};
722 if (!state_manager_.ProcessEvent(event)) {
729 void EsPlayer::PrepareTask_() {
730 bool ret = Prepare_();
732 state_manager_.SetPreparingState(false);
733 if (eventlistener_) {
734 LOG_INFO_P(this, "Prepare completely, call OnPrepareDone(%d)", ret);
735 eventlistener_->OnPrepareDone(ret, eventlistener_userdata_);
736 LOG_INFO_P(this, "call OnPrepareDone End");
739 kpi::CodecLogger logger;
740 kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
741 logger.SendKpi(ret, event_keys);
745 bool EsPlayer::PrepareAsync() {
747 state_manager_.SetPreparingState(true);
748 preparetask_ = std::async(std::launch::async, &EsPlayer::PrepareTask_, this);
749 if (!preparetask_.valid()) {
750 state_manager_.SetPreparingState(false);
756 bool EsPlayer::Pause() {
759 LOG_ERROR_P(this, "Stop already, no need to pause,leave...");
762 if (state_manager_.GetState() < EsState::kReady) {
763 LOG_ERROR_P(this, "Invalid State , current %d",
764 state_manager_.GetStateEnum());
767 auto op = [this]() noexcept -> bool {
768 if (!trackrenderer_) return false;
769 if (!trackrenderer_->Pause()) {
774 for (const auto& track : track_) {
775 es_packet_logger_.PrintStoredPacketInfo(
776 internal::ConvertToStreamType(track.type), true);
779 CafLogger::LogMessage(CafEventType::kPaused, caf_unique_number);
781 es_event::Pause event{op};
782 return state_manager_.ProcessEvent(event);
785 bool EsPlayer::Resume() {
788 LOG_ERROR_P(this, "Stop already, no need to Resume,leave...");
791 if (state_manager_.GetState() <= EsState::kReady) {
792 LOG_ERROR_P(this, "Invalid State , current %d",
793 state_manager_.GetStateEnum());
796 if (is_resource_conflicted_) {
797 LOG_ERROR_P(this, "Resuem fail resource conflicted");
800 auto op = [this]() noexcept -> bool {
801 if (!trackrenderer_) return false;
802 if (!trackrenderer_->Resume()) {
807 for (const auto& track : track_) {
808 es_packet_logger_.PrintStoredPacketInfo(
809 internal::ConvertToStreamType(track.type), true);
812 CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
814 es_event::Resume event{op};
815 return state_manager_.ProcessEvent(event);
818 bool EsPlayer::Seek(const uint64_t time) {
819 if (state_manager_.GetState() < EsState::kIdle) {
820 LOG_ERROR_P(this, "Invalid State , current %d",
821 state_manager_.GetStateEnum());
824 if (state_manager_.GetState() == EsState::kIdle) {
825 if (state_manager_.GetPreparingState()) {
826 LOG_ERROR_P(this, "Invalid State , during preparing");
829 LOG_ERROR("%p resume time [%" PRId64 " ]", this, time);
830 resume_time_.is_set = true;
831 resume_time_.time = time;
834 is_seek_done_need_drop = true;
835 if (time_unit_type == kPlayerTimeUnitTypeMs)
836 LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " ms]", this, time);
837 else if (time_unit_type == kPlayerTimeUnitTypeUs)
838 LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " us]", this, time);
839 for (const auto& track : track_) {
840 eos_status_ = internal::ResetEosStatus(track.type, eos_status_);
841 es_packet_logger_.PrintStoredPacketInfo(
842 internal::ConvertToStreamType(track.type), true);
844 auto op = [this, time]() -> bool {
845 if (!trackrenderer_->Seek(time, current_playback_rate_,
846 current_audio_mute_)) {
851 es_event::Seek event{op};
852 bool ret = state_manager_.ProcessEvent(event);
853 is_seek_done_need_drop = false;
855 if (eventlistener_) {
856 if (internal::IsLowLatencyModeDisableAVSync(low_latency_mode_) ||
857 internal::IsLowLatencyModeDisablePreroll(low_latency_mode_)) {
858 auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
859 eventlistener_, std::placeholders::_1);
860 auto msg = es_msg::Simple::Make(listener, eventlistener_userdata_);
861 std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
862 msg_queue_.push(std::move(msg));
864 msg_task_cv_.notify_one();
867 LOG_DEBUG("%p, [LEAVE] seek end ", this);
871 void EsPlayer::SetAppInfo(const PlayerAppInfo& app_info) {
873 if (state_manager_.GetState() != EsState::kIdle) {
874 LOG_ERROR_P(this, "Invalid State , current %d",
875 state_manager_.GetStateEnum());
878 app_info_ = app_info;
879 trackrenderer_->SetAppInfo(app_info);
880 LOG_INFO("Appid [%s]", app_info.id.c_str());
881 CafLogger::SetAppId(app_info.id);
884 void EsPlayer::SetAppInfoEx(const PlayerAppInfoEx& app_info) {
886 if (state_manager_.GetState() != EsState::kIdle) {
887 LOG_ERROR_P(this, "Invalid State , current %d",
888 state_manager_.GetStateEnum());
891 app_info_.id = app_info.id;
892 app_info_.version = app_info.version;
893 app_info_.type = app_info.type;
894 trackrenderer_->SetAppInfoEx(app_info);
895 LOG_INFO("Appid [%s]", app_info_.id.c_str());
896 CafLogger::SetAppId(app_info_.id);
899 bool EsPlayer::SetPlaybackRate(const double rate, const bool audio_mute) {
902 if (rate <= 0 || rate > 2.0) {
903 LOG_ERROR_P(this, "Not a valid PlaybackRate");
907 if (state_manager_.GetState() < EsState::kReady) {
908 LOG_ERROR_P(this, "Invalid State , current %d",
909 state_manager_.GetStateEnum());
913 auto op = [this, rate, audio_mute]() -> bool {
914 if (!trackrenderer_->SetPlaybackRate(rate, audio_mute)) {
917 current_playback_rate_ = rate;
918 current_audio_mute_ = audio_mute;
921 es_event::PlaybackRate event{op};
922 return state_manager_.ProcessEvent(event);
928 bool EsPlayer::SetDisplay(const DisplayType& type, void* obj) {
929 if (state_manager_.GetState() != EsState::kIdle) {
930 LOG_ERROR_P(this, "Invalid State , current %d",
931 state_manager_.GetStateEnum());
935 if (mixer_ticket_) mixer_ticket_.reset();
937 return trackrenderer_->SetDisplay(type, obj);
942 bool EsPlayer::SetDisplay(const DisplayType& type, MixerTicket* handle) {
943 if (type == DisplayType::kMixer) {
944 LOG_INFO_P(this, "Create MixerTicket");
945 mixer_ticket_.reset(handle);
946 mixer_ticket_->RegisterListener(mixer_event_listener_.get());
947 if (mixer_ticket_->IsAudioFocusHandler())
948 enable_audio_pipeline_handle_ = false;
949 if (mixer_ticket_->IsRscAllocHandler()) enable_rsc_alloc_handle_ = false;
950 trackrenderer_->SetDisplay(DisplayType::kNone, nullptr);
956 bool EsPlayer::SetDisplay(const DisplayType& type, void* ecore_wl2_window,
957 const int x, const int y, const int w, const int h) {
958 if (state_manager_.GetState() != EsState::kIdle) {
959 LOG_ERROR_P(this, "Invalid State , current %d",
960 state_manager_.GetStateEnum());
964 if (mixer_ticket_) mixer_ticket_.reset();
966 return trackrenderer_->SetDisplay(type, ecore_wl2_window, x, y, w, h);
969 bool EsPlayer::SetDisplaySubsurface(const DisplayType& type,
970 void* ecore_wl2_subsurface, const int x,
971 const int y, const int w, const int h) {
972 if (state_manager_.GetState() != EsState::kIdle) {
973 LOG_ERROR_P(this, "Invalid State , current %d",
974 state_manager_.GetStateEnum());
978 if (mixer_ticket_) mixer_ticket_.reset();
980 return trackrenderer_->SetDisplaySubsurface(type, ecore_wl2_subsurface, x, y,
984 bool EsPlayer::SetDisplay(const DisplayType& type, unsigned int surface_id,
985 const int x, const int y, const int w, const int h) {
986 if (state_manager_.GetState() != EsState::kIdle) {
987 LOG_ERROR_P(this, "Invalid State , current %d",
988 state_manager_.GetStateEnum());
992 if (mixer_ticket_) mixer_ticket_.reset();
994 return trackrenderer_->SetDisplay(type, surface_id, x, y, w, h);
998 bool EsPlayer::SetDisplayMode(const DisplayMode& mode) {
999 if (state_manager_.GetState() < EsState::kIdle) {
1000 LOG_ERROR_P(this, "Invalid State , current %d",
1001 state_manager_.GetStateEnum());
1004 trackrenderer_->SetDisplayMode(mode);
1008 bool EsPlayer::SetStretchMode(const int& mode) {
1009 if (state_manager_.GetState() < EsState::kIdle) {
1010 LOG_ERROR_P(this, "Invalid State , current %d",
1011 state_manager_.GetStateEnum());
1014 trackrenderer_->SetStretchMode(mode);
1018 bool EsPlayer::SetDisplayRoi(const Geometry& roi) {
1019 if (state_manager_.GetState() < EsState::kIdle) {
1020 LOG_ERROR_P(this, "Invalid State , current %d",
1021 state_manager_.GetStateEnum());
1025 mixerticket_roi_ = roi;
1026 if (mixer_ticket_) return true;
1028 return trackrenderer_->SetDisplayRoi(roi);
1031 bool EsPlayer::SetVideoRoi(const CropArea& area) {
1032 if (state_manager_.GetState() < EsState::kIdle) {
1033 LOG_ERROR_P(this, "Invalid State , current %d",
1034 state_manager_.GetStateEnum());
1037 return trackrenderer_->SetVideoRoi(area);
1040 bool EsPlayer::ResizeRenderRect(const RenderRect& rect) {
1041 if (state_manager_.GetState() < EsState::kIdle) {
1042 LOG_ERROR_P(this, "Invalid State , current %d",
1043 state_manager_.GetStateEnum());
1046 return trackrenderer_->ResizeRenderRect(rect);
1049 bool EsPlayer::SetDisplayRotate(const DisplayRotation& rotate) {
1050 if (state_manager_.GetState() < EsState::kIdle) {
1051 LOG_ERROR_P(this, "Invalid State , current %d",
1052 state_manager_.GetStateEnum());
1055 return trackrenderer_->SetDisplayRotate(rotate);
1058 bool EsPlayer::GetDisplayRotate(DisplayRotation* rotate) {
1059 if (state_manager_.GetState() < EsState::kIdle) {
1060 LOG_ERROR_P(this, "Invalid State , current %d",
1061 state_manager_.GetStateEnum());
1064 if (trackrenderer_->GetDisplayRotate(rotate)) {
1070 bool EsPlayer::SetDisplayVisible(bool is_visible) {
1071 if (state_manager_.GetState() < EsState::kIdle) {
1072 LOG_ERROR_P(this, "Invalid State , current %d",
1073 state_manager_.GetStateEnum());
1077 if (mixer_ticket_) {
1078 LOG_INFO_P(this, "mixed player is_visible [%d] -> [%d]", is_visible_,
1080 is_visible_ = is_visible;
1084 return trackrenderer_->SetDisplayVisible(is_visible);
1087 bool EsPlayer::SetTrustZoneUse(bool is_using_tz) {
1088 if (state_manager_.GetState() != EsState::kIdle) {
1089 LOG_ERROR_P(this, "Invalid State , current %d",
1090 state_manager_.GetStateEnum());
1093 if (drm_property_.type != drm::Type::kNone) {
1094 LOG_ERROR_P(this, "drm type is already set for sending encrypted packets");
1097 LOG_INFO_P(this, "set trust zone use [%d]", is_using_tz);
1098 drm_property_.external_decryption = is_using_tz;
1100 drm::Property drm_property = drm_property_;
1101 drm_property.type = drm::Type::kPlayready;
1102 trackrenderer_->SetDrm(drm_property);
1106 bool EsPlayer::SetSubmitDataType(SubmitDataType type) {
1107 if (state_manager_.GetState() != EsState::kIdle) {
1108 LOG_ERROR_P(this, "Invalid State , current %d",
1109 state_manager_.GetStateEnum());
1112 LOG_INFO_P(this, "set submit data type [%d]", static_cast<int>(type));
1114 if (type == SubmitDataType::kCleanData) return true;
1115 submit_data_type_ = type;
1116 drm_property_.type = drm::Type::kPlayready;
1117 // TODO: following SubmitDataType, need to set external_decryption
1118 drm_property_.external_decryption = true;
1119 drm::Property drm_property = drm_property_;
1120 trackrenderer_->SetDrm(drm_property);
1124 bool EsPlayer::SetTrack_(const Track& track) {
1126 track_util::ShowTrackInfo(track);
1127 track_.push_back(std::move(track));
1131 bool EsPlayer::ChangeStream_(const Track& track) {
1132 TrackType type = track.type;
1133 if (track_.empty()) return false;
1134 auto has_track = [type](const Track& item) -> bool {
1135 return item.type == type;
1137 std::lock_guard<std::mutex> lk(submit_mutex_);
1138 auto target = std::find_if(track_.begin(), track_.end(), has_track);
1139 if (target == track_.end()) {
1140 LOG_ERROR_P(this, "Add a new stream.");
1144 if (target->active != false) {
1145 LOG_ERROR_P(this, "The track should be deactivated in advance.");
1148 track_.erase(target);
1149 LOG_ERROR_P(this, "previously added %s stream is deleted",
1150 (type == kTrackTypeAudio) ? "audio" : "video");
1151 return SetTrack_(track);
1154 bool EsPlayer::SetStream_(const Track& track) {
1155 TrackType type = track.type;
1156 if (!track_.empty()) {
1157 auto has_track = [type](const Track& item) -> bool {
1158 return item.type == type;
1160 auto target = std::find_if(track_.begin(), track_.end(), has_track);
1161 if (target != track_.end()) {
1162 LOG_ERROR_P(this, "Stream is already exist");
1166 auto op = [this, track]() noexcept {
1167 if (!SetTrack_(track)) {
1173 CafLogger::LogMessage(CafEventType::kStreamReady, caf_unique_number);
1175 es_event::SetStream event{op};
1176 return state_manager_.ProcessEvent(event);
1179 bool EsPlayer::SetStream(const AudioStreamPtr& stream) {
1182 BOOST_SCOPE_EXIT(&ret, &stream, &force_audio_swdecoder_use_) {
1184 // when force_audio_swdecoder_use_ is already true, ignore stream setting.
1185 // otherwise, it can be true according to the stream setting
1186 force_audio_swdecoder_use_ =
1187 force_audio_swdecoder_use_ || stream->GetForceSwDecoderUse();
1189 BOOST_SCOPE_EXIT_END
1190 if (state_manager_.GetState() < EsState::kIdle) {
1191 LOG_ERROR_P(this, "Invalid State , current %d",
1192 state_manager_.GetStateEnum());
1195 Track track = stream->GetTrack_();
1196 if (state_manager_.GetState() >= EsState::kReady) {
1197 if (is_audio_stream_info_frozen_) {
1198 LOG_ERROR_P(this, "can't change audio stream in audio deactivate mode");
1201 track.active = false;
1202 ret = ChangeStream_(track);
1205 ret = SetStream_(track);
1209 bool EsPlayer::SetStream(const VideoStreamPtr& stream) {
1211 if (state_manager_.GetState() < EsState::kIdle) {
1212 LOG_ERROR_P(this, "Invalid State , current %d",
1213 state_manager_.GetStateEnum());
1216 Track track = stream->GetTrack_();
1217 if (state_manager_.GetState() >= EsState::kReady) {
1218 track.active = false;
1219 return ChangeStream_(track);
1221 return SetStream_(track);
1224 bool EsPlayer::SwitchAudioStreamOnTheFly(const AudioStreamPtr& stream) {
1226 if (state_manager_.GetState() < EsState::kReady) {
1227 LOG_ERROR_P(this, "Invalid State , current %d",
1228 state_manager_.GetStateEnum());
1231 Track track = stream->GetTrack_();
1233 if (!internal::IsAvailableCodecSwitch(track)) {
1234 LOG_ERROR_P(this, "Invalid new mimetype [%s][%d]", track.mimetype.c_str(),
1238 for (auto& old_track : track_) {
1239 if (old_track.type == TrackType::kTrackTypeAudio) {
1240 if (!internal::IsAvailableCodecSwitch(old_track)) {
1241 LOG_ERROR_P(this, "Invalid previous mimetype [%s][%d]",
1242 old_track.mimetype.c_str(), old_track.version);
1245 if (!Flush(StreamType::kAudio)) return false;
1246 old_track.active = false;
1250 if (!ChangeStream_(track)) return false;
1252 trackrenderer_->SetTrack(track_);
1256 bool EsPlayer::SetAdvancedPictureQualityType(const AdvPictureQualityType type) {
1258 if (state_manager_.GetState() != EsState::kIdle) {
1259 LOG_ERROR_P(this, "Invalid State , current %d",
1260 state_manager_.GetStateEnum());
1263 trackrenderer_->SetAdvancedPictureQualityType(type);
1267 bool EsPlayer::SetResourceAllocatePolicy(const RscAllocPolicy policy) {
1269 if (state_manager_.GetState() != EsState::kIdle) {
1270 LOG_ERROR_P(this, "Invalid State , current %d",
1271 state_manager_.GetStateEnum());
1274 resource_alloc_policy_ = policy;
1275 trackrenderer_->SetResourceAllocatePolicy(policy);
1280 GetDecodedVideoFrameStatus EsPlayer::GetDecodedPacket(
1281 DecodedVideoPacket& packet) {
1282 if (state_manager_.GetState() < EsState::kReady) {
1283 LOG_ERROR_P(this, "Invalid State , current %d",
1284 state_manager_.GetStateEnum());
1285 return GetDecodedVideoFrameStatus::kUnknown;
1287 return trackrenderer_->GetDecodedPacket(packet);
1290 bool EsPlayer::ReturnDecodedPacket(const DecodedVideoPacket& packet) {
1291 if (state_manager_.GetState() < EsState::kReady) {
1292 LOG_ERROR_P(this, "Invalid State , current %d",
1293 state_manager_.GetStateEnum());
1296 return trackrenderer_->ReturnDecodedPacket(packet);
1300 void EsPlayer::ResetContextForClose_() {
1301 internal::ResetDrmProperty(drm_property_);
1303 submit_data_type_ = SubmitDataType::kCleanData;
1304 low_latency_mode_ = 0;
1305 resume_time_.is_set = false;
1306 video_frame_peek_mode_ = 0;
1307 unlimited_max_buffer_mode_ = 0;
1309 audio_codec_type_ = kPlayerAudioCodecTypeHW;
1310 video_codec_type_ = kPlayerVideoCodecTypeHW;
1311 is_resource_conflicted_ = false;
1312 app_info_ = PlayerAppInfo();
1313 src_queue_size_ = SrcQueueSize();
1314 is_msg_task_stop_ = false;
1315 key_system_acquired_ = false;
1318 void EsPlayer::ResetContextForStop_() {
1319 for (int i = 0; i < kTrackTypeMax; ++i) {
1320 need_data_[i].mask = kNeedDataMaskNone;
1321 need_data_[i].seek_offset = 0;
1324 std::lock_guard<std::mutex> lock(eos_mutex_);
1325 eos_status_ = EosStatus::kAllEos;
1327 current_playback_rate_ = 1.0;
1328 current_audio_mute_ = false;
1331 void EsPlayer::GetSrcQueueCurrentSize_(const TrackType& type,
1332 uint64_t* byte_size,
1333 uint64_t* time_size) {
1334 boost::any byte_size_, time_size_;
1335 if (type == TrackType::kTrackTypeVideo) {
1336 trackrenderer_->GetAttribute(
1337 TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelByte,
1339 trackrenderer_->GetAttribute(
1340 TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
1342 } else if (type == TrackType::kTrackTypeAudio) {
1343 trackrenderer_->GetAttribute(
1344 TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
1346 trackrenderer_->GetAttribute(
1347 TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
1352 *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
1353 *time_size = boost::any_cast<std::uint64_t>(time_size_);
1355 LOG_INFO_P(this, "any_cast failed");
1357 if (time_unit_type == kPlayerTimeUnitTypeMs)
1358 *time_size = util::ConvertNsToMs(*time_size);
1359 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1360 *time_size = util::ConvertNsToUs(*time_size);
1363 GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
1364 MakeBufferStatus* status) {
1365 std::shared_ptr<char> buffer = packet->GetBuffer();
1366 uint32_t size = packet->GetSize();
1367 if (packet->IsEosPacket()) {
1368 *status = MakeBufferStatus::kEos;
1371 GstBuffer* gstbuffer = gst_buffer_new_and_alloc(size);
1373 *status = MakeBufferStatus::kOutOfMemory;
1376 if (buffer != nullptr) {
1378 gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
1379 memcpy(map.data, buffer.get(), size);
1380 gst_buffer_unmap(gstbuffer, &map);
1383 uint64_t pts = packet->GetPts();
1384 uint64_t duration = packet->GetDuration();
1385 /* if pts or duration are -1(=GST_CLOCK_TIME_NONE), some of the elements don't
1386 * adjust the buffer. */
1387 if (time_unit_type == kPlayerTimeUnitTypeMs) {
1388 GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1389 ? GST_CLOCK_TIME_NONE
1390 : (GstClockTime)util::ConvertMsToNs(pts);
1391 GST_BUFFER_DURATION(gstbuffer) =
1392 (duration == GST_CLOCK_TIME_NONE)
1393 ? GST_CLOCK_TIME_NONE
1394 : (GstClockTime)util::ConvertMsToNs(duration);
1395 } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1396 GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1397 ? GST_CLOCK_TIME_NONE
1398 : (GstClockTime)util::ConvertUsToNs(pts);
1399 GST_BUFFER_DURATION(gstbuffer) =
1400 (duration == GST_CLOCK_TIME_NONE)
1401 ? GST_CLOCK_TIME_NONE
1402 : (GstClockTime)util::ConvertUsToNs(duration);
1404 uint32_t hdr10p_size = packet->GetHdr10pSize();
1405 std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
1407 if (hdr10p_size > 0 && hdr10p_metadata != nullptr) {
1408 guint32* blockadditional_size = (guint32*)g_malloc(sizeof(uint32_t));
1409 *blockadditional_size = hdr10p_size;
1410 gst_mini_object_set_qdata(
1411 GST_MINI_OBJECT(gstbuffer),
1412 g_quark_from_static_string("matroska_blockadditional_size"),
1413 blockadditional_size, g_free);
1415 /* blockadditiona_data : the data sent to omx, size (4 bytes) + metadata */
1416 guint8* blockadditional_data =
1417 (guint8*)g_malloc(((*blockadditional_size) + 4) * sizeof(guint8));
1418 memcpy(blockadditional_data, blockadditional_size, sizeof(uint32_t));
1419 memcpy(blockadditional_data + 4, hdr10p_metadata.get(),
1420 (*blockadditional_size));
1421 gst_mini_object_set_qdata(
1422 GST_MINI_OBJECT(gstbuffer),
1423 g_quark_from_static_string("matroska_blockadditional_info"),
1424 blockadditional_data, g_free);
1426 *status = MakeBufferStatus::kSuccess;
1430 PacketSubmitStatus EsPlayer::SubmitEosPacket_(const TrackType& type) {
1431 PacketSubmitStatus submitstate = PacketSubmitStatus::kSuccess;
1433 std::lock_guard<std::mutex> lock(eos_mutex_);
1435 case kTrackTypeAudio:
1436 eos_status_ |= EosStatus::kAudioEos;
1438 case kTrackTypeVideo:
1439 eos_status_ |= EosStatus::kVideoEos;
1444 if (eos_status_ != EosStatus::kAllEos) {
1448 for (int tracktype = kTrackTypeAudio; tracktype < kTrackTypeMax;
1451 DecoderInputBuffer::Create(static_cast<TrackType>(tracktype));
1452 if (!trackrenderer_->SubmitPacket2(inbuffer, nullptr)) {
1453 std::lock_guard<std::mutex> lock(eos_mutex_);
1454 eos_status_ = EosStatus::kAllEos;
1455 submitstate = PacketSubmitStatus::kNotPrepared;
1462 void EsPlayer::UnsetTzQdata_(const DecoderInputBufferPtr& buffer) {
1463 const GstBuffer* gstbuf = buffer->Get();
1464 if (!gstbuf) return;
1465 GstStructure* tzqdata = GST_STRUCTURE(gst_mini_object_steal_qdata(
1466 GST_MINI_OBJECT(gstbuf), g_quark_from_static_string("GstTzHandleData")));
1467 if (tzqdata) gst_structure_free(tzqdata);
1470 PacketSubmitStatus EsPlayer::SubmitDecoderInputBuffer_(
1471 const DecoderInputBufferPtr& buffer) {
1472 PacketSubmitStatus status = PacketSubmitStatus::kSuccess;
1473 TrackRendererAdapter::SubmitStatus submitstate =
1474 TrackRendererAdapter::SubmitStatus::kSuccess;
1475 trackrenderer_->SubmitPacket2(buffer, &submitstate);
1477 switch (submitstate) {
1478 case TrackRendererAdapter::SubmitStatus::kSuccess:
1479 case TrackRendererAdapter::SubmitStatus::kDrop:
1480 status = PacketSubmitStatus::kSuccess;
1482 case TrackRendererAdapter::SubmitStatus::kFull:
1483 UnsetTzQdata_(buffer);
1484 trackrenderer_event_listener_->OnBufferStatus(buffer->GetType(),
1485 BufferStatus::kOverrun);
1486 status = PacketSubmitStatus::kFull;
1489 UnsetTzQdata_(buffer);
1490 status = PacketSubmitStatus::kNotPrepared;
1497 void EsPlayer::MakeGstBufferForTzHandle_(GstBuffer* gstbuffer,
1498 const TrackType& type,
1499 const uint32_t& tz_handle,
1500 const uint32_t& packet_size) {
1501 GstStructure* gst_tz_handle_data_structure =
1502 gst_structure_new("GstTzHandleData", "packet_handle", G_TYPE_UINT,
1503 static_cast<guint32>(tz_handle), "packet_size",
1504 G_TYPE_UINT, static_cast<guint32>(packet_size),
1505 "secure", G_TYPE_BOOLEAN, true, nullptr);
1506 gst_mini_object_set_qdata(
1507 GST_MINI_OBJECT(gstbuffer), g_quark_from_string("GstTzHandleData"),
1508 gst_tz_handle_data_structure, (GDestroyNotify)gst_structure_free);
1510 if (type == kTrackTypeAudio) {
1512 bool has_active_audio_track =
1513 track_util::GetActiveTrack(track_, kTrackTypeAudio, &audio_track);
1514 if (has_active_audio_track) {
1515 GstStructure* audio_info_structure =
1516 gst_structure_new("AudioInfo", "mime_type", G_TYPE_STRING,
1517 audio_track.mimetype.c_str(), nullptr);
1518 gst_mini_object_set_qdata(
1519 GST_MINI_OBJECT(gstbuffer), g_quark_from_string("AudioInfo"),
1520 audio_info_structure, (GDestroyNotify)gst_structure_free);
1525 void EsPlayer::MakeGstBufferForEncryptedPacket_(
1526 GstBuffer* gstbuffer, const EsPacketPtr& packet,
1527 const drm::EsPlayerEncryptedInfo& drm_info) {
1528 if (drm_info.handle == 0) return;
1529 auto serialized_drm_info_ptr = esplayer_drm::Serialize(packet, drm_info);
1530 GstStructure* gst_drm_info_structure =
1531 gst_structure_new("drm_info", "drm_specific_info", G_TYPE_BYTES,
1532 serialized_drm_info_ptr.get(), nullptr);
1533 if (gst_drm_info_structure) {
1534 gst_mini_object_set_qdata(
1535 GST_MINI_OBJECT(gstbuffer), g_quark_from_static_string("drm_info"),
1536 gst_drm_info_structure, (GDestroyNotify)gst_structure_free);
1541 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
1542 SubmitPacketOperator op) {
1543 if (state_manager_.GetState() < EsState::kIdle) {
1544 return PacketSubmitStatus::kNotPrepared;
1546 if (!packet) return PacketSubmitStatus::kInvalidPacket;
1548 TrackType type = static_cast<TrackType>(packet->GetType());
1549 Track activated_track;
1550 if (!track_util::GetActiveTrack(track_, type, &activated_track))
1551 return PacketSubmitStatus::kInvalidPacket;
1553 if (state_manager_.GetState() == EsState::kPaused ||
1554 state_manager_.GetState() == EsState::kReady) {
1555 internal::AppsrcQueueSizeOption byte_based, time_based;
1557 case kTrackTypeAudio:
1558 byte_based.max_size = src_queue_size_.kMaxByteOfAudioSrcQueue;
1559 time_based.max_size = src_queue_size_.kMaxTimeOfAudioSrcQueue;
1560 byte_based.threshold = src_queue_size_.kMinByteThresholdOfAudioSrcQueue;
1561 time_based.threshold = src_queue_size_.kMinTimeThresholdOfAudioSrcQueue;
1563 case kTrackTypeVideo:
1564 byte_based.max_size = src_queue_size_.kMaxByteOfVideoSrcQueue;
1565 time_based.max_size = src_queue_size_.kMaxTimeOfVideoSrcQueue;
1566 byte_based.threshold = src_queue_size_.kMinByteThresholdOfVideoSrcQueue;
1567 time_based.threshold = src_queue_size_.kMinTimeThresholdOfVideoSrcQueue;
1572 GetSrcQueueCurrentSize_(type, &(byte_based.current_size),
1573 &(time_based.current_size));
1574 if (internal::IsUnderRun(byte_based, time_based))
1575 trackrenderer_event_listener_->OnBufferStatus(type,
1576 BufferStatus::kUnderrun);
1579 es_packet_logger_.StorePacketInfo(packet);
1580 es_packet_logger_.PrintStoredPacketInfo(packet->GetType());
1582 MakeBufferStatus make_buffer_status;
1583 GstBuffer* gstbuffer = GetGstBuffer_(packet, &make_buffer_status);
1585 if (make_buffer_status == MakeBufferStatus::kEos)
1586 return SubmitEosPacket_(type);
1587 else if (make_buffer_status == MakeBufferStatus::kOutOfMemory)
1588 return PacketSubmitStatus::kOutOfMemory;
1590 if (op != nullptr) {
1591 PacketSubmitStatus op_status = op(gstbuffer);
1592 if (op_status != PacketSubmitStatus::kSuccess) {
1597 auto inbuffer = DecoderInputBuffer::Create(type, 0, gstbuffer);
1598 gst_buffer_unref(gstbuffer);
1600 if (packet->HasMatroskaColorInfo()) {
1601 std::string color_info_str =
1602 util::GetStringFromMatroskaColor(packet->GetMatroskaColorInfo());
1603 if (trackrenderer_->SetMatroskaColorInfo(color_info_str) == false)
1604 return PacketSubmitStatus::kNotPrepared;
1607 return SubmitDecoderInputBuffer_(inbuffer);
1610 PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
1611 std::lock_guard<std::mutex> lk(submit_mutex_);
1612 return SubmitPacketCommon_(packet, nullptr);
1616 PacketSubmitStatus EsPlayer::SubmitTrustZonePacket(const EsPacketPtr& packet,
1617 uint32_t tz_handle) {
1618 std::lock_guard<std::mutex> lk(submit_mutex_);
1619 if (submit_data_type_ != SubmitDataType::kTrustZoneData)
1620 return PacketSubmitStatus::kInvalidPacket;
1621 auto submitpacket_op = [this, &tz_handle,
1622 &packet](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1623 if (tz_handle > 0) {
1624 TrackType type = static_cast<TrackType>(packet->GetType());
1625 uint32_t packet_size = packet->GetSize();
1626 MakeGstBufferForTzHandle_(gstbuffer, type, tz_handle, packet_size);
1628 return PacketSubmitStatus::kSuccess;
1630 return SubmitPacketCommon_(packet, submitpacket_op);
1633 PacketSubmitStatus EsPlayer::SubmitEncryptedPacket(
1634 const EsPacketPtr& packet, const drm::EsPlayerEncryptedInfo& drm_info) {
1635 std::lock_guard<std::mutex> lk(submit_mutex_);
1636 if (submit_data_type_ != SubmitDataType::kEncryptedData)
1637 return PacketSubmitStatus::kInvalidPacket;
1638 auto submitpacket_op =
1639 [this, &packet, &drm_info](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1640 MakeGstBufferForEncryptedPacket_(gstbuffer, packet, drm_info);
1641 return PacketSubmitStatus::kSuccess;
1643 if (!key_system_acquired_ && drm_info.handle != 0) {
1644 key_system_ = eme::IEME::getKeySystemName(drm_info.handle);
1645 LOG_INFO("KeySystemName :: [%s] ", key_system_.c_str());
1647 .GetPreparingState()) { // if the stream comes with clean data at
1648 // the beginning, re-post kpi when we get
1650 kpi::CodecLogger logger;
1651 kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
1652 logger.SendKpi(true, event_keys);
1654 key_system_acquired_ = true;
1656 return SubmitPacketCommon_(packet, submitpacket_op);
1660 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
1662 bool EsPlayer::GetPlayingTime(uint64_t* time) {
1663 if (!time) return false;
1664 if (state_manager_.GetState() <= EsState::kReady) {
1668 return trackrenderer_->GetPlayingTime(time);
1671 bool EsPlayer::SetAudioMute(bool is_mute) {
1672 if (state_manager_.GetState() < EsState::kIdle) {
1673 LOG_ERROR_P(this, "Invalid State , current %d",
1674 state_manager_.GetStateEnum());
1677 return trackrenderer_->SetAudioMute(is_mute);
1680 bool EsPlayer::SetVideoFrameBufferType(DecodedVideoFrameBufferType type) {
1681 if ((state_manager_.GetState() != EsState::kIdle &&
1682 type != DecodedVideoFrameBufferType::kScale) ||
1683 (state_manager_.GetState() < EsState::kIdle &&
1684 type == DecodedVideoFrameBufferType::kScale)) {
1685 LOG_ERROR_P(this, "Invalid State , current %d",
1686 state_manager_.GetStateEnum());
1689 if (type == DecodedVideoFrameBufferType::kScale &&
1690 video_codec_type_ == kPlayerVideoCodecTypeSW) {
1691 LOG_ERROR_P(this, "kScale is not supportted when using sw video decoder");
1694 trackrenderer_->SetVideoFrameBufferType(
1695 VideoFrameTypeStrategyPtr(new DefaultVideoFrameTypeStrategy(type)));
1696 vidoe_frame_buffer_type_ = type;
1700 bool EsPlayer::SetVideoFrameBufferScaleResolution(
1701 const uint32_t& target_width, const uint32_t& target_height) {
1702 if (state_manager_.GetState() < EsState::kIdle) {
1703 LOG_ERROR_P(this, "Invalid State , current %d",
1704 state_manager_.GetStateEnum());
1708 return trackrenderer_->SetVideoFrameBufferScaleResolution(target_width,
1712 bool EsPlayer::SetDecodedVideoFrameRate(const Rational& request_framerate) {
1713 if (state_manager_.GetState() < EsState::kIdle) {
1714 LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
1718 return trackrenderer_->SetDecodedVideoFrameRate(request_framerate);
1721 void EsPlayer::RegisterListener(EsEventListener* listener,
1722 EsEventListener::UserData userdata) {
1723 // assert(listener); // allow unregister by setting nullptr
1724 assert(!eventlistener_);
1725 eventlistener_ = listener;
1726 eventlistener_userdata_ = userdata;
1729 bool EsPlayer::GetAdaptiveInfo(void* padaptive_info,
1730 const PlayerAdaptiveInfo& adaptive_type) {
1731 if (!padaptive_info || adaptive_type <= PlayerAdaptiveInfo::kMinType ||
1732 adaptive_type >= PlayerAdaptiveInfo::kMaxType)
1734 switch (adaptive_type) {
1735 case PlayerAdaptiveInfo::kVideoDroppedFrames:
1736 if (state_manager_.GetState() < EsState::kReady) {
1737 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1740 return trackrenderer_->GetDroppedFrames(padaptive_info);
1741 case PlayerAdaptiveInfo::kDroppedVideoFramesForCatchup:
1742 if (state_manager_.GetState() < EsState::kReady) {
1743 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1746 return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeVideo,
1748 case PlayerAdaptiveInfo::kDroppedAudioFramesForCatchup:
1749 if (state_manager_.GetState() < EsState::kReady) {
1750 LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1753 return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeAudio,
1761 bool EsPlayer::SetVolume(const int& volume) {
1762 if (volume < internal::kVolumeMin || volume > internal::kVolumeMax) {
1763 LOG_ERROR_P(this, "Invalid volume level %d", volume);
1766 if (state_manager_.GetState() < EsState::kIdle) {
1767 LOG_ERROR_P(this, "Invalid State , current %d",
1768 state_manager_.GetStateEnum());
1771 return trackrenderer_->SetVolume(volume);
1774 bool EsPlayer::GetVolume(int* volume) {
1775 if (state_manager_.GetState() < EsState::kIdle) {
1776 LOG_ERROR_P(this, "Invalid State , current %d",
1777 state_manager_.GetStateEnum());
1780 return trackrenderer_->GetVolume(volume);
1783 bool EsPlayer::Flush(const StreamType& type) {
1784 if (state_manager_.GetState() <= EsState::kIdle) {
1785 LOG_ERROR_P(this, "Invalid State , current %d",
1786 state_manager_.GetStateEnum());
1790 internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
1791 es_packet_logger_.ResetLog(type);
1792 return trackrenderer_->Flush(type);
1795 bool EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
1796 TrackType track_type = kTrackTypeMax;
1798 case BufferOption::kBufferAudioMaxByteSize: /* FALL THROUGH */
1799 case BufferOption::kBufferAudioMinByteThreshold: /* FALL THROUGH */
1800 case BufferOption::kBufferAudioMaxTimeSize: /* FALL THROUGH */
1801 case BufferOption::kBufferAudioMinTimeThreshold:
1802 track_type = kTrackTypeAudio;
1804 case BufferOption::kBufferVideoMaxByteSize: /* FALL THROUGH */
1805 case BufferOption::kBufferVideoMinByteThreshold: /* FALL THROUGH */
1806 case BufferOption::kBufferVideoMaxTimeSize: /* FALL THROUGH */
1807 case BufferOption::kBufferVideoMinTimeThreshold:
1808 track_type = kTrackTypeVideo;
1813 if (track_type == kTrackTypeMax) {
1814 LOG_ERROR_P(this, "Invalid option!!!");
1818 Track activated_track;
1820 track_util::GetActiveTrack(track_, track_type, &activated_track);
1821 EsState state = state_manager_.GetState();
1822 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_activated)) {
1823 LOG_ERROR_P(this, "Invalid State [state:%d] or stream is activated [%d],",
1824 state_manager_.GetStateEnum(), is_activated);
1829 case BufferOption::kBufferAudioMaxByteSize:
1830 src_queue_size_.kMaxByteOfAudioSrcQueue = size;
1832 case BufferOption::kBufferVideoMaxByteSize:
1833 src_queue_size_.kMaxByteOfVideoSrcQueue = size;
1835 case BufferOption::kBufferAudioMinByteThreshold:
1836 src_queue_size_.kMinByteThresholdOfAudioSrcQueue =
1837 static_cast<uint32_t>(size);
1839 case BufferOption::kBufferVideoMinByteThreshold:
1840 src_queue_size_.kMinByteThresholdOfVideoSrcQueue =
1841 static_cast<uint32_t>(size);
1843 case BufferOption::kBufferAudioMaxTimeSize:
1844 src_queue_size_.kMaxTimeOfAudioSrcQueue = size;
1846 case BufferOption::kBufferVideoMaxTimeSize:
1847 src_queue_size_.kMaxTimeOfVideoSrcQueue = size;
1849 case BufferOption::kBufferAudioMinTimeThreshold:
1850 src_queue_size_.kMinTimeThresholdOfAudioSrcQueue =
1851 static_cast<uint32_t>(size);
1853 case BufferOption::kBufferVideoMinTimeThreshold:
1854 src_queue_size_.kMinTimeThresholdOfVideoSrcQueue =
1855 static_cast<uint32_t>(size);
1858 LOG_ERROR_P(this, "Invalid option!!!");
1864 bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
1865 if (state_manager_.GetState() != EsState::kIdle) {
1866 LOG_ERROR_P(this, "Invalid State , current %d",
1867 state_manager_.GetStateEnum());
1870 if (true == internal::IsExclusiveLowLatencyMode(low_latency_mode_, mode)) {
1871 LOG_ERROR_P(this, "Invalid Mode , current 0x%x, set 0x%x",
1872 static_cast<std::uint32_t>(low_latency_mode_),
1873 static_cast<std::uint32_t>(mode));
1876 low_latency_mode_ |= static_cast<std::uint32_t>(mode);
1880 bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
1881 if (state_manager_.GetState() < EsState::kReady) {
1882 LOG_ERROR_P(this, "Invalid State , current %d",
1883 state_manager_.GetStateEnum());
1886 if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1888 "low latency mode have to be set except disable_sync mode");
1891 std::int64_t ns_unit = 0;
1892 if (time_unit_type == kPlayerTimeUnitTypeMs)
1894 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1896 if ((offset * ns_unit > G_MAXINT64) || (offset * ns_unit < G_MININT64)) {
1897 LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
1898 "] * 1000000 < G_MAXINT64",
1902 if (type == StreamType::kMax) return false;
1903 if (time_unit_type == kPlayerTimeUnitTypeMs) {
1904 if (type == StreamType::kAudio)
1905 trackrenderer_->SetAttribute(
1906 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1907 util::ConvertMsToNs(offset));
1908 else if (type == StreamType::kVideo)
1909 trackrenderer_->SetAttribute(
1910 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1911 util::ConvertMsToNs(offset));
1912 } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1913 if (type == StreamType::kAudio)
1914 trackrenderer_->SetAttribute(
1915 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1916 util::ConvertUsToNs(offset));
1917 else if (type == StreamType::kVideo)
1918 trackrenderer_->SetAttribute(
1919 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1920 util::ConvertUsToNs(offset));
1925 bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
1926 if (state_manager_.GetState() < EsState::kReady) {
1927 LOG_ERROR_P(this, "Invalid State , current %d",
1928 state_manager_.GetStateEnum());
1931 if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1932 LOG_ERROR_P(this, "low latency mode have to be set");
1935 if (type == StreamType::kMax) return false;
1937 if (type == StreamType::kAudio)
1938 trackrenderer_->GetAttribute(
1939 TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
1940 else if (type == StreamType::kVideo)
1941 trackrenderer_->GetAttribute(
1942 TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
1944 *offset = boost::any_cast<std::int64_t>(off_set);
1945 if (time_unit_type == kPlayerTimeUnitTypeMs)
1946 *offset = util::ConvertNsToMs(*offset);
1947 else if (time_unit_type == kPlayerTimeUnitTypeUs)
1948 *offset = util::ConvertNsToUs(*offset);
1952 bool EsPlayer::SetVideoFramePeekMode() {
1953 if (state_manager_.GetState() != EsState::kIdle) {
1954 LOG_ERROR_P(this, "Invalid State , current %d",
1955 state_manager_.GetStateEnum());
1958 constexpr std::uint32_t peek_mode_on = 1;
1959 video_frame_peek_mode_ = peek_mode_on;
1963 bool EsPlayer::RenderVideoFrame() {
1964 if (!video_frame_peek_mode_) return false;
1965 if (state_manager_.GetState() == EsState::kReady ||
1966 state_manager_.GetState() == EsState::kPaused) {
1967 trackrenderer_->RenderVideoFrame();
1970 LOG_ERROR_P(this, "Invalid State , current %d",
1971 state_manager_.GetStateEnum());
1975 bool EsPlayer::SetUnlimitedMaxBufferMode() {
1976 if (state_manager_.GetState() != EsState::kIdle) {
1977 LOG_ERROR_P(this, "Invalid State , current %d",
1978 state_manager_.GetStateEnum());
1981 constexpr std::uint32_t unlimited_max_buffer_mode_on = 1;
1982 unlimited_max_buffer_mode_ = unlimited_max_buffer_mode_on;
1986 ErrorType EsPlayer::SetFmmMode() {
1987 EsState state = state_manager_.GetState();
1989 if (state < EsState::kIdle) {
1990 LOG_ERROR_P(this, "Invalid State , current %d",
1991 state_manager_.GetStateEnum());
1992 return ErrorType::kInvalidState;
1996 ErrorType ret = ErrorType::kNone;
1997 if (trackrenderer_->GetFmmAutoMode(&onoff) == false) {
1998 return ErrorType::kInvalidOperation;
2006 if (onoff == FMM_AUTO_OFF) ret = ErrorType::kInvalidOperation;
2008 fmm_mode_ = FMM_AUTO_ON;
2010 if (state < EsState::kReady) return ret;
2012 trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
2017 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
2018 Track activated_track;
2020 track_util::GetActiveTrack(track_, kTrackTypeAudio, &activated_track);
2021 EsState state = state_manager_.GetState();
2022 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2024 "Invalid State [state:%d] or audio stream already exists[%d],",
2025 state_manager_.GetStateEnum(), is_existed);
2028 if (force_audio_swdecoder_use_ && type == kPlayerAudioCodecTypeHW) {
2029 LOG_ERROR_P(this, "Not support hw decoder");
2032 LOG_INFO_P(this, "PlayerAudioCodecType [%s]",
2033 (type == kPlayerAudioCodecTypeHW) ? "hardware" : "software");
2034 audio_codec_type_ = type;
2038 bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
2039 Track activated_track;
2041 track_util::GetActiveTrack(track_, kTrackTypeVideo, &activated_track);
2042 EsState state = state_manager_.GetState();
2043 if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2045 "Invalid State [state:%d] or video stream already exists[%d],",
2046 state_manager_.GetStateEnum(), is_existed);
2049 if (force_video_swdecoder_use_ &&
2050 (type == kPlayerVideoCodecTypeHW ||
2051 type == kPlayerVideoCodecTypeHWNdecoding)) {
2052 LOG_ERROR_P(this, "Not support hw decoder");
2055 if (type == kPlayerVideoCodecTypeSW &&
2056 vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
2058 "sw video decoder is not supportted when video frame buffer "
2063 if (!enable_rsc_alloc_handle_) {
2064 LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2067 if (type == kPlayerVideoCodecTypeHWNdecoding) {
2068 LOG_INFO_P(this, "PlayerVideoCodecType HW N-decoding");
2069 video_decoding_mode_ = internal::kNdecodingMode;
2073 LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
2074 (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
2075 video_codec_type_ = type;
2079 bool EsPlayer::SetAiFilter(void* aifilter) {
2080 if (state_manager_.GetState() != EsState::kIdle) {
2081 LOG_ERROR_P(this, "Invalid State , current %d",
2082 state_manager_.GetStateEnum());
2085 trackrenderer_->SetAiFilter(aifilter);
2089 bool EsPlayer::InitAudioEasingInfo(const uint32_t init_volume,
2090 const uint32_t init_elapsed_time,
2091 const AudioEasingInfo& easing_info) {
2092 if (init_volume > internal::kVolumeMax ||
2093 easing_info.target_volume > internal::kVolumeMax) {
2094 LOG_ERROR_P(this, "Invalid volume: init [%d] target [%d]", init_volume,
2095 easing_info.target_volume);
2098 if (state_manager_.GetState() < EsState::kIdle) {
2099 LOG_ERROR_P(this, "Invalid State , current %d",
2100 state_manager_.GetStateEnum());
2103 return trackrenderer_->InitAudioEasingInfo(init_volume, init_elapsed_time,
2107 bool EsPlayer::UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) {
2108 if (easing_info.target_volume > internal::kVolumeMax) {
2109 LOG_ERROR_P(this, "Invalid volume level %d", easing_info.target_volume);
2112 if (state_manager_.GetState() < EsState::kIdle) {
2113 LOG_ERROR_P(this, "Invalid State , current %d",
2114 state_manager_.GetStateEnum());
2117 return trackrenderer_->UpdateAudioEasingInfo(easing_info);
2120 bool EsPlayer::GetAudioEasingInfo(uint32_t* current_volume,
2121 uint32_t* elapsed_time,
2122 AudioEasingInfo* easing_info) {
2123 if (state_manager_.GetState() < EsState::kIdle) {
2124 LOG_ERROR_P(this, "Invalid State , current %d",
2125 state_manager_.GetStateEnum());
2128 return trackrenderer_->GetAudioEasingInfo(current_volume, elapsed_time,
2132 bool EsPlayer::StartAudioEasing() {
2133 if (state_manager_.GetState() < EsState::kReady) {
2134 LOG_ERROR_P(this, "Invalid State , current %d",
2135 state_manager_.GetStateEnum());
2138 return trackrenderer_->StartAudioEasing();
2141 bool EsPlayer::StopAudioEasing() {
2142 if (state_manager_.GetState() < EsState::kIdle) {
2143 LOG_ERROR_P(this, "Invalid State , current %d",
2144 state_manager_.GetStateEnum());
2147 return trackrenderer_->StopAudioEasing();
2150 bool EsPlayer::SetAlternativeVideoResource(unsigned int rsc_type) {
2151 if (state_manager_.GetState() == EsState::kNone) {
2152 LOG_ERROR_P(this, "Invalid State");
2156 if (!enable_rsc_alloc_handle_) {
2157 LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2161 if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2163 "has set resource allocate policy, the alternative "
2164 "resource setting will be wrong");
2167 alternative_video_resource_ = static_cast<std::uint32_t>(rsc_type);
2171 bool EsPlayer::SetAlternativeAudioResource(
2172 const PlayerAudioResourceType rsc_type) {
2173 if (state_manager_.GetState() == EsState::kNone) {
2174 LOG_ERROR_P(this, "Invalid State");
2178 if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2180 "has set resource allocate policy, the alternative "
2181 "resource setting will be wrong");
2184 return trackrenderer_->SetAlternativeAudioResource(rsc_type);
2187 bool EsPlayer::SetCatchUpSpeed(const CatchUpSpeed& level) {
2188 if (state_manager_.GetState() < EsState::kIdle) {
2189 LOG_ERROR_P(this, "Invalid State , current %d",
2190 state_manager_.GetStateEnum());
2194 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2195 LOG_ERROR_P(this, "Do not set low latency mode, current[0x%x]",
2196 static_cast<std::uint32_t>(low_latency_mode_));
2200 if (trackrenderer_->SetCatchUpSpeed(level)) {
2206 bool EsPlayer::GetVideoLatencyStatus(LatencyStatus* status) {
2207 if (state_manager_.GetState() < EsState::kReady) {
2208 LOG_ERROR_P(this, "Invalid State , current %d",
2209 state_manager_.GetStateEnum());
2213 if (trackrenderer_->GetVideoLatencyStatus(status)) {
2219 bool EsPlayer::GetAudioLatencyStatus(LatencyStatus* status) {
2220 if (state_manager_.GetState() < EsState::kReady) {
2221 LOG_ERROR_P(this, "Invalid State , current %d",
2222 state_manager_.GetStateEnum());
2226 if (trackrenderer_->GetAudioLatencyStatus(status)) {
2232 bool EsPlayer::SetVideoMidLatencyThreshold(const unsigned int threshold) {
2233 if (state_manager_.GetState() < EsState::kIdle) {
2234 LOG_ERROR_P(this, "Invalid State , current %d",
2235 state_manager_.GetStateEnum());
2239 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2240 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2241 static_cast<std::uint32_t>(low_latency_mode_));
2245 LOG_INFO_P(this, "video_mid_latency_threshold : [%u]", threshold);
2247 trackrenderer_->SetVideoMidLatencyThreshold(threshold);
2251 bool EsPlayer::SetAudioMidLatencyThreshold(const unsigned int threshold) {
2252 if (state_manager_.GetState() < EsState::kIdle) {
2253 LOG_ERROR_P(this, "Invalid State , current %d",
2254 state_manager_.GetStateEnum());
2258 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2259 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2260 static_cast<std::uint32_t>(low_latency_mode_));
2264 LOG_INFO_P(this, "audio_mid_latency_threshold : [%u]", threshold);
2266 trackrenderer_->SetAudioMidLatencyThreshold(threshold);
2270 bool EsPlayer::SetVideoHighLatencyThreshold(const unsigned int threshold) {
2271 if (state_manager_.GetState() < EsState::kIdle) {
2272 LOG_ERROR_P(this, "Invalid State , current %d",
2273 state_manager_.GetStateEnum());
2277 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2278 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2279 static_cast<std::uint32_t>(low_latency_mode_));
2283 LOG_INFO_P(this, "video_high_latency_threshold : [%u]", threshold);
2285 trackrenderer_->SetVideoHighLatencyThreshold(threshold);
2289 bool EsPlayer::SetAudioHighLatencyThreshold(const unsigned int threshold) {
2290 if (state_manager_.GetState() < EsState::kIdle) {
2291 LOG_ERROR_P(this, "Invalid State , current %d",
2292 state_manager_.GetStateEnum());
2296 if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2297 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2298 static_cast<std::uint32_t>(low_latency_mode_));
2302 LOG_INFO_P(this, "audio_high_latency_threshold : [%u]", threshold);
2304 trackrenderer_->SetAudioHighLatencyThreshold(threshold);
2308 bool EsPlayer::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
2309 if (frame_count == nullptr) {
2310 LOG_ERROR_P(this, "frame count is nullptr");
2313 if (state_manager_.GetState() < EsState::kReady) {
2314 LOG_ERROR_P(this, "Invalid State , current %d",
2315 state_manager_.GetStateEnum());
2319 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2320 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2321 static_cast<std::uint32_t>(low_latency_mode_));
2325 return trackrenderer_->GetLowLatencyPcmBufferSize(frame_count);
2328 bool EsPlayer::GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
2329 if (frame_count == nullptr) {
2330 LOG_ERROR_P(this, "frame count is nullptr");
2333 if (state_manager_.GetState() < EsState::kReady) {
2334 LOG_ERROR_P(this, "Invalid State , current %d",
2335 state_manager_.GetStateEnum());
2339 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2340 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2341 static_cast<std::uint32_t>(low_latency_mode_));
2345 return trackrenderer_->GetLowLatencyPcmCurrentBufferLevel(frame_count);
2348 bool EsPlayer::GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
2349 if (underrun_count == nullptr) {
2350 LOG_ERROR_P(this, "underrun count is nullptr");
2353 if (state_manager_.GetState() < EsState::kReady) {
2354 LOG_ERROR_P(this, "Invalid State , current %d",
2355 state_manager_.GetStateEnum());
2359 if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2360 LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2361 static_cast<std::uint32_t>(low_latency_mode_));
2365 return trackrenderer_->GetLowLatencyPcmUnderrunCount(underrun_count);
2368 bool EsPlayer::GetVirtualRscId(const RscType type, int* virtual_id) {
2369 if (virtual_id == nullptr) return false;
2370 if (state_manager_.GetState() < EsState::kReady) {
2371 LOG_ERROR_P(this, "Invalid State , current %d",
2372 state_manager_.GetStateEnum());
2376 return trackrenderer_->GetVirtualRscId(type, virtual_id);
2379 bool EsPlayer::SetAudioPreloading() {
2380 if (state_manager_.GetState() != EsState::kIdle) {
2381 LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
2384 return trackrenderer_->SetAudioPreloading();
2387 void EsPlayer::Init_() {
2389 is_stopped_ = false;
2393 void EsPlayer::MsgTask_() {
2394 std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
2395 while (!is_msg_task_stop_) {
2396 if (msg_queue_.empty()) {
2397 msg_task_cv_.wait(msg_mutex);
2400 msg_queue_.front()->Execute();
2405 while (!msg_queue_.empty()) {
2408 LOG_INFO_P(this, "Stop MsgTask");
2411 void EsPlayer::TrackRendererEventListener::OnEos() {
2412 LOG_ENTER_P(handler_);
2413 if (!handler_->eventlistener_) return;
2414 auto listener = std::bind(&esplusplayer::EsEventListener::OnEos,
2415 handler_->eventlistener_, std::placeholders::_1);
2416 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2417 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2418 handler_->msg_queue_.push(std::move(msg));
2420 handler_->msg_task_cv_.notify_one();
2421 LOG_LEAVE_P(handler_);
2425 void EsPlayer::TrackRendererEventListener::OnSeekDone() {
2426 LOG_ENTER_P(handler_);
2427 if (!handler_->eventlistener_) return;
2428 if (handler_->is_seek_done_need_drop == true) return;
2429 auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
2430 handler_->eventlistener_, std::placeholders::_1);
2431 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2432 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2433 handler_->msg_queue_.push(std::move(msg));
2435 handler_->msg_task_cv_.notify_one();
2436 LOG_LEAVE_P(handler_);
2439 void EsPlayer::TrackRendererEventListener::OnResourceConflicted() {
2440 LOG_ENTER_P(handler_);
2441 if (handler_->is_stopped_) {
2442 LOG_INFO_P(handler_, "LEAVE ~ Stop is called already");
2445 LOG_INFO_P(handler_, "Handling resource conflict...");
2446 handler_->is_resource_conflicted_ = true;
2447 handler_->trackrenderer_->Stop();
2448 if (!handler_->eventlistener_ || handler_->is_stopped_) return;
2450 std::bind(&esplusplayer::EsEventListener::OnResourceConflicted,
2451 handler_->eventlistener_, std::placeholders::_1);
2452 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2453 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2454 handler_->msg_queue_.push(std::move(msg));
2456 if (handler_->is_stopped_) {
2457 LOG_LEAVE_P(handler_);
2460 handler_->msg_task_cv_.notify_one();
2461 LOG_LEAVE_P(handler_);
2464 void EsPlayer::TrackRendererEventListener::OnError(
2465 const ErrorType& error_code) {
2466 if (!handler_->eventlistener_) return;
2467 if (error_code == ErrorType::kResourceLimit) return;
2468 auto listener = std::bind(&esplusplayer::EsEventListener::OnError,
2469 handler_->eventlistener_, std::placeholders::_1,
2470 std::placeholders::_2);
2471 auto msg = es_msg::Error::Make(error_code, listener,
2472 handler_->eventlistener_userdata_);
2474 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2475 handler_->msg_queue_.push(std::move(msg));
2477 handler_->msg_task_cv_.notify_one();
2480 void EsPlayer::TrackRendererEventListener::OnErrorMsg(
2481 const ErrorType& error_code, char* error_msg) {
2482 if (!handler_->eventlistener_) return;
2483 if (error_code == ErrorType::kResourceLimit) return;
2485 std::vector<Track> activeTracks;
2486 track_util::GetActiveTrackList(handler_->track_, activeTracks);
2488 Json::Value message;
2489 message["error_code"] = (int)error_code;
2491 switch (error_code) {
2492 case ErrorType::kNotSupportedVideoCodec:
2493 for (const auto& track : activeTracks) {
2494 if (track.type == kTrackTypeVideo) {
2495 message["codec"] = track.mimetype.c_str();
2496 message["demux"] = track.container_type.c_str();
2497 char json_string[20] = {0};
2499 strncat(json_string, std::to_string(track.width).c_str(), nLen);
2500 nLen = sizeof(json_string) - strlen(json_string) - 1;
2501 if (nLen < 0) nLen = 0;
2502 strncat(json_string, "*", nLen);
2503 nLen = sizeof(json_string) - strlen(json_string) - 1;
2504 if (nLen < 0) nLen = 0;
2505 strncat(json_string, std::to_string(track.height).c_str(), nLen);
2506 message["resolution"] = json_string;
2507 memset(json_string, 0, sizeof(json_string));
2509 strncat(json_string, std::to_string(track.framerate_num).c_str(),
2511 nLen = sizeof(json_string) - strlen(json_string) - 1;
2512 if (nLen < 0) nLen = 0;
2513 strncat(json_string, "/", nLen);
2514 nLen = sizeof(json_string) - strlen(json_string) - 1;
2515 if (nLen < 0) nLen = 0;
2516 strncat(json_string, std::to_string(track.framerate_den).c_str(),
2518 message["fps"] = json_string;
2519 message["detail_info"] = error_msg;
2524 case ErrorType::kNotSupportedAudioCodec:
2531 Json::FastWriter writer;
2532 std::string str = writer.write(message);
2533 LOG_INFO_P(handler_, "error message: %s", str.c_str());
2535 auto listener = std::bind(&esplusplayer::EsEventListener::OnErrorMsg,
2536 handler_->eventlistener_, std::placeholders::_1,
2537 std::placeholders::_2, std::placeholders::_3);
2539 es_msg::ErrorMsg::Make(error_code, str.c_str(), str.size(), listener,
2540 handler_->eventlistener_userdata_);
2542 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2543 handler_->msg_queue_.push(std::move(msg));
2545 handler_->msg_task_cv_.notify_one();
2549 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
2550 const TrackType& type) {
2551 LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
2552 (type == kTrackTypeAudio) ? "audio" : "video");
2554 handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
2556 auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToPrepare,
2557 handler_->eventlistener_, std::placeholders::_1,
2558 std::placeholders::_2);
2559 StreamType stream_type = internal::ConvertToStreamType(type);
2560 auto msg = es_msg::ReadyToPrepare::Make(stream_type, listener,
2561 handler_->eventlistener_userdata_);
2562 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2563 handler_->msg_queue_.push(std::move(msg));
2565 handler_->msg_task_cv_.notify_one();
2568 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
2569 uint64_t offset = handler_->need_data_[type].seek_offset;
2571 LOG_INFO("%p, OnReadyToSeek [%s] offset [%" PRId64 "]", handler_,
2572 (type == kTrackTypeAudio) ? "audio" : "video", offset);
2574 handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
2575 handler_->need_data_[type].seek_offset = 0;
2577 auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToSeek,
2578 handler_->eventlistener_, std::placeholders::_1,
2579 std::placeholders::_2, std::placeholders::_3);
2580 StreamType stream_type = internal::ConvertToStreamType(type);
2581 handler_->es_packet_logger_.ResetLog(stream_type);
2582 auto msg = es_msg::ReadyToSeek::Make(stream_type, offset, listener,
2583 handler_->eventlistener_userdata_);
2584 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2585 handler_->msg_queue_.push(std::move(msg));
2587 handler_->msg_task_cv_.notify_one();
2590 void EsPlayer::TrackRendererEventListener::BufferStatus_(
2591 const TrackType& type, const BufferStatus& status) {
2592 uint64_t byte_size, time_size;
2593 // LOG_INFO_P(handler_, "OnBufferStatus [%s] [%s]",
2594 // (type == kTrackTypeAudio) ? "audio" : "video",
2595 // (status == BufferStatus::kUnderrun) ? "underrun" : "overrun");
2596 handler_->GetSrcQueueCurrentSize_(type, &byte_size, &time_size);
2597 auto listener = std::bind(&esplusplayer::EsEventListener::OnBufferStatus,
2598 handler_->eventlistener_, std::placeholders::_1,
2599 std::placeholders::_2, std::placeholders::_3,
2600 std::placeholders::_4, std::placeholders::_5);
2601 StreamType stream_type = internal::ConvertToStreamType(type);
2603 es_msg::Bufferstatus::Make(stream_type, status, byte_size, time_size,
2604 listener, handler_->eventlistener_userdata_);
2605 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2606 handler_->msg_queue_.push(std::move(msg));
2608 handler_->msg_task_cv_.notify_one();
2611 void EsPlayer::TrackRendererEventListener::OnBufferStatus(
2612 const TrackType& type, const BufferStatus& status) {
2613 if (!handler_->eventlistener_) return;
2614 if (internal::IsLowLatencyModeDisableAVSync(handler_->low_latency_mode_))
2617 if (handler_->need_data_[type].mask == kNeedDataMaskByPrepare &&
2618 status == BufferStatus::kUnderrun) {
2619 ReadyToPrepare_(type);
2620 } else if (handler_->need_data_[type].mask == kNeedDataMaskBySeek &&
2621 status == BufferStatus::kUnderrun) {
2624 BufferStatus_(type, status);
2629 void EsPlayer::TrackRendererEventListener::OnMediaPacketGetTbmBufPtr(
2630 void** tbm_ptr, bool is_scale_change) {
2631 if (!handler_->eventlistener_) return;
2633 handler_->eventlistener_->OnMediaPacketGetTbmBufPtr(tbm_ptr, is_scale_change);
2636 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
2637 const DecodedVideoPacket& packet) {
2638 if (!handler_->eventlistener_) return;
2640 handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
2644 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoRawDecoded(
2645 const DecodedVideoRawModePacket& packet) {
2646 if (handler_->mixer_ticket_ == nullptr) return;
2647 const auto& data = packet.data;
2648 if (packet.type == DecodedVideoRawModePacketType::kPhysicalAddress) {
2649 DecodedRawInfo info;
2650 info.width = packet.width;
2651 info.height = packet.height;
2652 info.y_info.phyaddr = data.raw.y_phyaddr;
2653 info.y_info.viraddr = data.raw.y_viraddr;
2654 info.y_info.linesize = data.raw.y_linesize;
2655 info.uv_info.phyaddr = data.raw.uv_phyaddr;
2656 info.uv_info.viraddr = data.raw.uv_viraddr;
2657 info.uv_info.linesize = data.raw.uv_linesize;
2658 handler_->mixer_ticket_->Render(info);
2659 } else if (packet.type == DecodedVideoRawModePacketType::kTizenBuffer) {
2660 DecodedVideoKeyTypeInfo info;
2661 info.width = packet.width;
2662 info.height = packet.height;
2663 info.key = packet.data.tbm.key;
2664 handler_->mixer_ticket_->Render(info);
2668 bool EsPlayer::MixerListener::OnAudioFocusChanged(bool active) {
2669 LOG_INFO_P(handler_, "focused [%d]", active);
2670 std::unique_lock<std::mutex> lock(handler_->audio_focus_m_);
2671 if (handler_->state_manager_.GetState() < EsState::kReady) {
2672 handler_->is_audio_focused_ = active;
2676 Track activated_track;
2677 track_util::GetActiveTrack(handler_->track_, kTrackTypeAudio,
2679 LOG_INFO_P(handler_, "Activate audio track");
2681 std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2682 handler_->eos_status_ =
2683 internal::ResetEosStatus(kTrackTypeAudio, handler_->eos_status_);
2685 return handler_->trackrenderer_->Activate(kTrackTypeAudio, activated_track);
2687 LOG_INFO_P(handler_, "Deactivate audio track");
2688 handler_->is_audio_focused_ = false;
2690 std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2691 handler_->eos_status_ |= EosStatus::kAudioEos;
2693 return handler_->trackrenderer_->Deactivate(kTrackTypeAudio);
2696 bool EsPlayer::MixerListener::OnUpdateDisplayInfo(const DisplayInfo& cur_info,
2697 DisplayInfo* new_info) {
2698 new_info->geometry = handler_->mixerticket_roi_;
2699 new_info->visible_status =
2700 handler_->is_visible_ ? VisibleStatus::kVisible : VisibleStatus::kHide;
2706 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
2707 const uint64_t offset) {
2708 if (!handler_->eventlistener_) return;
2710 if (handler_->need_data_[type].mask != kNeedDataMaskByPrepare) {
2711 handler_->need_data_[type].mask |= kNeedDataMaskBySeek;
2712 handler_->need_data_[type].seek_offset = offset;
2717 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
2719 if (size <= 0) return;
2720 if (!handler_->eventlistener_) return;
2721 auto listener = std::bind(&esplusplayer::EsEventListener::OnClosedCaptionData,
2722 handler_->eventlistener_, std::placeholders::_1,
2723 std::placeholders::_2, std::placeholders::_3);
2724 auto msg = es_msg::ClosedCaption::Make(data, size, listener,
2725 handler_->eventlistener_userdata_);
2726 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2727 handler_->msg_queue_.push(std::move(msg));
2729 handler_->msg_task_cv_.notify_one();
2732 void EsPlayer::TrackRendererEventListener::OnFlushDone() {
2733 LOG_ENTER_P(handler_);
2734 if (!handler_->eventlistener_) return;
2736 auto listener = std::bind(&esplusplayer::EsEventListener::OnFlushDone,
2737 handler_->eventlistener_, std::placeholders::_1);
2739 es_msg::FlushDone::Make(listener, handler_->eventlistener_userdata_);
2740 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2741 handler_->msg_queue_.push(std::move(msg));
2743 handler_->msg_task_cv_.notify_one();
2744 LOG_LEAVE_P(handler_);
2747 void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
2748 const EventMsg& msg_data) {
2749 if (!handler_->eventlistener_) return;
2751 auto listener = std::bind(&esplusplayer::EsEventListener::OnEvent,
2752 handler_->eventlistener_, std::placeholders::_1,
2753 std::placeholders::_2, std::placeholders::_3);
2754 auto msg = es_msg::OnEvent::Make(event, msg_data, listener,
2755 handler_->eventlistener_userdata_);
2756 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2757 handler_->msg_queue_.push(std::move(msg));
2759 handler_->msg_task_cv_.notify_one();
2760 LOG_LEAVE_P(handler_);
2764 void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
2765 LOG_ENTER_P(handler_);
2766 if (!handler_->eventlistener_) return;
2767 auto listener = std::bind(&esplusplayer::EsEventListener::OnFirstDecodingDone,
2768 handler_->eventlistener_, std::placeholders::_1);
2769 auto msg = es_msg::FirstDecodingDone::Make(listener,
2770 handler_->eventlistener_userdata_);
2771 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2772 handler_->msg_queue_.push(std::move(msg));
2774 handler_->msg_task_cv_.notify_one();
2775 LOG_LEAVE_P(handler_);
2778 void EsPlayer::TrackRendererEventListener::OnVideoDecoderUnderrun() {
2779 LOG_ENTER_P(handler_);
2780 if (!handler_->eventlistener_) return;
2782 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2783 handler_->state_manager_.GetState() != EsState::kPaused) {
2788 std::bind(&esplusplayer::EsEventListener::OnVideoDecoderUnderrun,
2789 handler_->eventlistener_, std::placeholders::_1);
2790 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2791 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2792 handler_->msg_queue_.push(std::move(msg));
2794 handler_->msg_task_cv_.notify_one();
2795 LOG_LEAVE_P(handler_);
2798 void EsPlayer::TrackRendererEventListener::OnVideoLatencyStatus(
2799 const LatencyStatus& latency_status) {
2800 LOG_ENTER_P(handler_);
2801 if (!handler_->eventlistener_) return;
2803 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2804 handler_->state_manager_.GetState() != EsState::kPaused) {
2808 auto listener = std::bind(
2809 &esplusplayer::EsEventListener::OnVideoLatencyStatus,
2810 handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2812 auto msg = es_msg::PacketLatencyStatus::Make(
2813 latency_status, listener, handler_->eventlistener_userdata_);
2815 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2816 handler_->msg_queue_.push(std::move(msg));
2818 handler_->msg_task_cv_.notify_one();
2819 LOG_LEAVE_P(handler_);
2822 void EsPlayer::TrackRendererEventListener::OnAudioLatencyStatus(
2823 const LatencyStatus& latency_status) {
2824 LOG_ENTER_P(handler_);
2825 if (!handler_->eventlistener_) return;
2827 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2828 handler_->state_manager_.GetState() != EsState::kPaused) {
2832 auto listener = std::bind(
2833 &esplusplayer::EsEventListener::OnAudioLatencyStatus,
2834 handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2836 auto msg = es_msg::PacketLatencyStatus::Make(
2837 latency_status, listener, handler_->eventlistener_userdata_);
2839 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2840 handler_->msg_queue_.push(std::move(msg));
2842 handler_->msg_task_cv_.notify_one();
2843 LOG_LEAVE_P(handler_);
2846 void EsPlayer::TrackRendererEventListener::OnVideoHighLatency() {
2847 LOG_ENTER_P(handler_);
2848 if (!handler_->eventlistener_) return;
2850 auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoHighLatency,
2851 handler_->eventlistener_, std::placeholders::_1);
2853 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2855 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2856 handler_->msg_queue_.push(std::move(msg));
2858 handler_->msg_task_cv_.notify_one();
2859 LOG_LEAVE_P(handler_);
2863 void EsPlayer::TrackRendererEventListener::OnAudioHighLatency() {
2864 LOG_ENTER_P(handler_);
2865 if (!handler_->eventlistener_) return;
2867 auto listener = std::bind(&esplusplayer::EsEventListener::OnAudioHighLatency,
2868 handler_->eventlistener_, std::placeholders::_1);
2870 auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2872 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2873 handler_->msg_queue_.push(std::move(msg));
2875 handler_->msg_task_cv_.notify_one();
2876 LOG_LEAVE_P(handler_);
2879 void EsPlayer::TrackRendererEventListener::OnVideoFrameDropped(
2880 const uint64_t& count) {
2881 if (!handler_->eventlistener_) return;
2883 handler_->eventlistener_->OnVideoFrameDropped(
2884 count, handler_->eventlistener_userdata_);
2888 if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2889 handler_->state_manager_.GetState() != EsState::kPaused) {
2893 auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoFrameDropped,
2894 handler_->eventlistener_, std::placeholders::_1,
2895 std::placeholders::_2);
2897 auto msg = es_msg::FrameDroppedCount::Make(
2898 count, listener, handler_->eventlistener_userdata_);
2900 std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2901 handler_->msg_queue_.push(std::move(msg));
2903 handler_->msg_task_cv_.notify_one();
2904 LOG_LEAVE_P(handler_);
2908 void EsPlayer::TrackRendererEventListener::OnDecoderInputBufferTime(
2909 const TrackType& type, const DecoderBufferTime& time) {
2910 if (!handler_->eventlistener_) return;
2912 StreamType stream_type = internal::ConvertToStreamType(type);
2913 handler_->eventlistener_->OnDecoderInputBufferTime(stream_type, time);
2916 void EsPlayer::TrackRendererEventListener::OnDecoderOutputBufferTime(
2917 const TrackType& type, const DecoderBufferTime& time) {
2918 if (!handler_->eventlistener_) return;
2920 StreamType stream_type = internal::ConvertToStreamType(type);
2921 handler_->eventlistener_->OnDecoderOutputBufferTime(stream_type, time);
2926 bool EsPlayer::SetVideoScanType(const PlayerVideoScanType type) {
2928 if (state_manager_.GetState() != EsState::kIdle) {
2929 LOG_ERROR_P(this, "Invalid State , current %d",
2930 state_manager_.GetStateEnum());
2933 if (type == kPlayerVideoScanTypeProgressive) set_video_progressive_ = 1;
2936 bool EsPlayer::SetTimeUnitType(const PlayerTimeUnitType type) {
2938 if (state_manager_.GetState() != EsState::kIdle) {
2939 LOG_ERROR_P(this, "Invalid State , current %d",
2940 state_manager_.GetStateEnum());
2943 LOG_INFO_P(this, "PlayerTimeUnitType [%s]",
2944 (type == kPlayerTimeUnitTypeMs) ? "Ms" : "Us");
2945 time_unit_type = type;
2949 bool EsPlayer::GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) {
2950 if (!time_in_milliseconds) return false;
2951 if (state_manager_.GetState() <= EsState::kReady) {
2952 *time_in_milliseconds = 0;
2955 return trackrenderer_->GetDecodingTime(type, time_in_milliseconds);
2958 bool EsPlayer::SetVideoStreamRotationInfo(const VideoRotation& rotation) {
2960 if (state_manager_.GetState() < EsState::kIdle) {
2961 LOG_ERROR_P(this, "Invalid State , current %d",
2962 state_manager_.GetStateEnum());
2965 video_rotate_ = rotation;
2966 return trackrenderer_->SetVideoStreamRotationInfo(rotation);
2969 bool EsPlayer::GetVideoStreamRotationInfo(VideoRotation* rotation) {
2971 if (state_manager_.GetState() < EsState::kIdle) {
2972 LOG_ERROR_P(this, "Invalid State , current %d",
2973 state_manager_.GetStateEnum());
2976 *rotation = video_rotate_;
2980 bool EsPlayer::SetSimpleMixOutBufferLevel(
2981 const PlayerSimpleMixOutBufferLevel level) {
2982 if (state_manager_.GetState() == EsState::kNone) {
2983 LOG_ERROR_P(this, "Invalid State");
2986 int converted_level = 1;
2987 if (level == kPlayerSimpleMixOutBufferLow) {
2988 converted_level = 0;
2989 } else if (level == kPlayerSimpleMixOutBufferMid) {
2990 converted_level = 1;
2991 } else if (level == kPlayerSimpleMixOutBufferHigh) {
2992 converted_level = 2;
2995 return trackrenderer_->SetSimpleMixOutBufferLevel(converted_level);
2998 kpi::EsCodecLoggerKeys EsPlayer::MakeKpiKeys_() {
2999 kpi::EsCodecLoggerKeys event_info;
3000 event_info.app_id = app_info_.id;
3001 if (submit_data_type_ == SubmitDataType::kCleanData) {
3002 event_info.is_clean = true;
3004 event_info.is_clean = false;
3005 event_info.key_system = key_system_;
3008 for (const auto& track : track_) {
3009 if (track.type == kTrackTypeVideo) {
3010 event_info.v_codec = track.mimetype;
3011 event_info.v_codec_version = track.version;
3012 event_info.width = track.maxwidth;
3013 event_info.height = track.maxheight;
3014 } else if (track.type == kTrackTypeAudio) {
3015 event_info.a_codec = track.mimetype;
3021 void EsPlayer::InitValuesFromIni_() {
3022 force_audio_swdecoder_use_ = es_conf::ini_property["force_sw_audio_codec"];
3023 force_video_swdecoder_use_ = es_conf::ini_property["force_sw_video_codec"];
3028 void LoadIniProperty(const Json::Value& root) {
3030 std::vector<std::string> booleanKeys {
3032 "force_sw_audio_codec",
3033 "force_sw_video_codec",
3034 "fallback_to_sw_audio_codec",
3035 "fallback_to_sw_video_codec"
3038 gst_util::GstInit(root);
3039 std::for_each(booleanKeys.begin(), booleanKeys.end(), [&](const auto& key) {
3040 es_conf::ini_property[key] = root.get(key, "").asBool();
3041 LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
3045 bool LoadIniFile() {
3046 const char* path = esplusplayer_cfg::GetIniPath();
3047 LOG_INFO("path : %s", path);
3048 std::streampos size;
3049 char* buf = nullptr;
3050 std::ifstream file(path, std::ios::binary | std::ios::ate);
3051 if (file.is_open() == false) {
3052 gst_util::GstInit();
3053 LOG_ERROR("Can't open file !!");
3056 BOOST_SCOPE_EXIT(&file) { file.close(); }
3057 BOOST_SCOPE_EXIT_END
3059 size = file.tellg();
3061 LOG_ERROR("Wrong file size");
3065 buf = static_cast<char*>(calloc(size, sizeof(char)));
3066 if (buf == nullptr) {
3067 LOG_ERROR("Fail to calloc buf");
3070 BOOST_SCOPE_EXIT(&buf) {
3073 BOOST_SCOPE_EXIT_END
3075 file.seekg(0, std::ios::beg);
3076 file.read(buf, size);
3078 std::string config = buf;
3080 Json::Reader reader;
3081 if (!reader.parse(config, root)) {
3082 LOG_ERROR("Fail to parse configuration file %s",
3083 (reader.getFormatedErrorMessages()).c_str());
3087 es_conf::LoadIniProperty(root);
3091 } // namespace es_conf
3093 } // namespace esplusplayer