add for type com.youtube.playready (#149)
[platform/core/multimedia/esplusplayer.git] / src / esplusplayer / src / esplayer.cpp
1 //
2 // @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
3 //
4 // to manipulate TrackRenderer objects
5 // to provide optimized control of TrackRenderer
6
7 #include "esplayer/esplayer.h"
8
9 #include <boost/scope_exit.hpp>
10 #include <cassert>
11 #include <chrono>
12 #include <cinttypes>
13 #include <fstream>
14 #include <functional>
15 #include <memory>
16 #include <sstream>
17 #include <thread>
18
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"
28
29 namespace esplusplayer {
30
31 namespace es_conf {
32
33 // get values from /etc/multimedia/esplusplayer.ini
34 static std::once_flag loaded;
35 static std::map<std::string, bool> ini_property;
36
37 bool LoadIniFile();
38 void LoadIniProperty(const Json::Value& root);
39
40 }  // namespace es_conf
41
42 namespace util {
43
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;
47   return ms * ns_unit;
48 }
49
50 std::uint64_t ConvertNsToMs(std::uint64_t ns) {
51   constexpr std::uint64_t ms_unit = 1000000;
52   return ns / ms_unit;
53 }
54
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;
58   return ms * ns_unit;
59 }
60
61 std::int64_t ConvertNsToMs(std::int64_t ns) {
62   constexpr std::int64_t ms_unit = 1000000;
63   return ns / ms_unit;
64 }
65
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;
69   return us * ns_unit;
70 }
71
72 std::uint64_t ConvertNsToUs(std::uint64_t ns) {
73   constexpr std::uint64_t us_unit = 1000;
74   return ns / us_unit;
75 }
76
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;
80   return us * ns_unit;
81 }
82
83 std::int64_t ConvertNsToUs(std::int64_t ns) {
84   constexpr std::int64_t us_unit = 1000;
85   return ns / us_unit;
86 }
87
88 // LCOV_EXCL_START
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;
114   return oss.str();
115 }
116 // LCOV_EXCL_STOP
117
118 }  // namespace util
119
120 namespace internal {
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
125
126 constexpr uint32_t kNdecodingMode = 0x04;
127
128 enum VolumeLevel { kVolumeMin = 0, kVolumeMax = 100 };
129 constexpr int kMaxFhdWidth = 1920;
130 constexpr int kMaxFhdHeight = 1080;
131
132 inline bool IsPcmMimeType(const std::string& mimetype) {
133   return (mimetype.find("audio/x-raw") != std::string::npos);
134 }
135 inline bool IsForcedUnsetTz(const Track& track, const std::string& id) {
136   if ((track.type == kTrackTypeAudio) && strstr(id.c_str(), "netflix")) {
137     return true;
138   }
139   return false;
140 }
141 inline bool IsAacCodec(const Track& track) {
142   return (track.mimetype.find("audio/mpeg") != std::string::npos &&
143           track.version == 2);
144 }
145 inline bool IsEac3Codec(const std::string& mimetype) {
146   return mimetype.find("audio/x-eac3") != std::string::npos;
147 }
148 inline bool IsAc3Codec(const std::string& mimetype) {
149   return mimetype.find("audio/x-ac3") != std::string::npos;
150 }
151
152 inline bool IsFlacCodec(const std::string& mimetype) {
153   return mimetype.find("audio/x-ffmpeg-parsed-flac") != std::string::npos;
154 }
155
156 inline bool IsAvailableCodecSwitch(const Track& track) {
157   if (internal::IsAacCodec(track) || internal::IsAc3Codec(track.mimetype) ||
158       internal::IsEac3Codec(track.mimetype))
159     return true;
160   return false;
161 }
162
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;
168   return eos_status;
169 }
170
171 // LCOV_EXCL_START
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) !=
177          std::string::npos);
178     if (is_already_tz_type) {
179       continue;
180     }
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))
185       continue;
186     else
187       track.mimetype = track.mimetype + "_tz";
188   }
189 }
190 // LCOV_EXCL_STOP
191
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;
203         else
204           track.use_swdecoder = false;
205         break;
206       }
207       case kTrackTypeVideo: {
208         if (video_codec_type == kPlayerVideoCodecTypeSW ||
209             force_video_swdecoder_use)
210           track.use_swdecoder = true;
211         else
212           track.use_swdecoder = false;
213         break;
214       }
215       default:
216         break;
217     }
218   }
219 }
220 inline bool IsSupportedDrmType(const drm::Type& drm_type) {
221   static const std::map<drm::Type, bool> kSupportedDrmType = {
222       {drm::Type::kPlayready, true},
223   };
224   if (kSupportedDrmType.count(drm_type) == 0) return false;
225   return kSupportedDrmType.at(drm_type);
226 }
227 inline void ResetDrmProperty(drm::Property& drm_property) {
228   drm_property = drm::Property();
229 }
230 inline StreamType ConvertToStreamType(TrackType type) {
231   return (type == kTrackTypeAudio) ? StreamType::kAudio : StreamType::kVideo;
232 }
233 struct AppsrcQueueSizeOption {
234   std::uint64_t current_size = 0;
235   std::uint64_t max_size = 0;
236   std::uint32_t threshold = 0;
237 };
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)
248     return true;
249   else
250     return false;
251 }
252 inline bool IsLowLatencyModeDisableAVSync(std::uint32_t mode) {
253   constexpr std::uint32_t kAVSync = kLowLatencyModeDisableAVSync;
254   return (mode & kAVSync) ? true : false;
255 }
256 inline bool IsLowLatencyModeDisablePreroll(std::uint32_t mode) {
257   constexpr std::uint32_t kPreroll = kLowLatencyModeDisablePreroll;
258   return (mode & kPreroll) ? true : false;
259 }
260 inline bool IsLowLatencyMode(std::uint32_t mode) {
261   return (mode != static_cast<std::uint32_t>(kLowLatencyModeNone)) ? true
262                                                                    : false;
263 }
264 inline bool IsSupportedTsOffset(std::uint32_t mode) {
265   return IsLowLatencyMode(mode) && !IsLowLatencyModeDisableAVSync(mode) ? true
266                                                                         : false;
267 }
268
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;
274 }
275
276 inline bool IsLowLatencyModeForCatchUp(std::uint32_t mode) {
277   return IsLowLatencyModeDisableAVSync(mode) &&
278                  IsLowLatencyModeEnableGameMode(mode)
279              ? true
280              : false;
281 }
282
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);
287   exclusive_mode |=
288       static_cast<std::uint32_t>(kLowLatencyModeDisableVideoQuality);
289
290   std::uint32_t new_mode = current_mode | set_mode;
291   return (exclusive_mode == (new_mode & exclusive_mode)) ? true : false;
292 }
293 }  // namespace internal
294
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.");
299   }
300   InitValuesFromIni_();
301 }
302
303 EsPlayer::~EsPlayer() {
304   LOG_ENTER_P(this);
305   Close();
306   LOG_LEAVE_P(this);
307 }
308
309 bool EsPlayer::Open() {
310   LOG_INFO_P(this, "state manager > %p", &state_manager_);
311   Init_();
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");
317     }
318     msg_handler_task_ =
319         std::async(std::launch::async, &EsPlayer::MsgTask_, this);
320     trackrenderer_ = TrackRendererAdapter::Create();
321     assert(trackrenderer_);
322
323     trackrenderer_->RegisterListenerForEsplayer(
324         trackrenderer_event_listener_.get());
325     performance_checker::End(start, "Open");
326     return true;
327   };
328   CafLogger::SetUniqueNumber();
329   caf_unique_number = CafLogger::GetUniqueNumber();
330   CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
331
332   es_event::Open event{op};
333   return state_manager_.ProcessEvent(event);
334 }
335
336 bool EsPlayer::Close() {
337   LOG_ENTER_P(this);
338   std::lock_guard<std::mutex> lk(submit_mutex_);
339   if (state_manager_.GetState() >= EsState::kIdle) {
340     Stop();
341   }
342   auto op = [this]() noexcept {
343     if (is_msg_task_stop_ == false) {
344       {
345         std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
346         is_msg_task_stop_ = true;
347       }
348       msg_task_cv_.notify_one();
349       if (msg_handler_task_.valid()) msg_handler_task_.wait();
350     }
351
352     if (trackrenderer_) trackrenderer_.reset();
353     ResetContextForClose_();
354     LOG_LEAVE_P(this);
355     return true;
356   };
357   es_event::Close event{op};
358   state_manager_.ProcessEvent(event);
359   state_manager_.Stop();
360   return true;
361 }
362
363 bool EsPlayer::Deactivate(const StreamType type) {
364   LOG_ENTER_P(this);
365   if (state_manager_.GetState() < EsState::kReady) {
366     LOG_ERROR_P(this, "Invalid State , current %d",
367                 state_manager_.GetStateEnum());
368     return false;
369   }
370 #ifdef USE_MIXER
371   if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
372     LOG_ERROR_P(
373         this, "can't deactivate audio stream, mixer will control audio stream");
374     return false;
375   }
376 #endif  // USE_MIXER
377   if (!trackrenderer_->Deactivate(static_cast<TrackType>(type))) {
378     return false;
379   }
380   {
381     std::lock_guard<std::mutex> lock(eos_mutex_);
382     switch (type) {
383       case StreamType::kAudio:
384         eos_status_ |= EosStatus::kAudioEos;
385         break;
386       case StreamType::kVideo:
387         eos_status_ |= EosStatus::kVideoEos;
388         break;
389       default:
390         break;
391     }
392   }
393   for (auto& track : track_) {
394     if (track.type == static_cast<TrackType>(type)) {
395       track.active = false;
396     }
397   }
398   return true;
399 }
400
401 bool EsPlayer::Activate(const StreamType type) {
402   LOG_ENTER_P(this);
403   if (state_manager_.GetState() < EsState::kReady) {
404     LOG_ERROR_P(this, "Invalid State , current %d",
405                 state_manager_.GetStateEnum());
406     return false;
407   }
408 #ifdef USE_MIXER
409   if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
410     LOG_ERROR_P(this,
411                 "can't activate audio stream, mixer will control audio stream");
412     return false;
413   }
414 #endif  // USE_MIXER
415   if (!track_.empty()) {
416     auto has_track = [type](const Track& item) -> bool {
417       return item.type == static_cast<TrackType>(type);
418     };
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");
422       return false;
423     }
424     if (target->active != false) {
425       LOG_ERROR_P(this, "The track should be deactivated in advance.");
426       return false;
427     }
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);
434     }
435     SetTrackRendererAttributes_();
436     if (type == StreamType::kVideo) {
437 #ifdef USE_MIXER
438       if (mixer_ticket_)
439         trackrenderer_->SetVideoFrameBufferType(
440             VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
441       else
442 #endif  // USE_MIXER
443         trackrenderer_->SetVideoFrameBufferType(VideoFrameTypeStrategyPtr(
444             new DefaultVideoFrameTypeStrategy(vidoe_frame_buffer_type_)));
445     }
446     if (!trackrenderer_->Activate(target->type, *target)) {
447       target->active = false;
448       return false;
449     }
450     eos_status_ =
451         internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
452     return true;
453   }
454   return false;
455 }
456
457 bool EsPlayer::DeactivateAudio() {
458   LOG_ENTER_P(this);
459   if (state_manager_.GetState() < EsState::kIdle) {
460     LOG_ERROR_P(this, "Invalid State , current %d",
461                 state_manager_.GetStateEnum());
462     return false;
463   }
464 #ifdef USE_MIXER
465   if (!enable_audio_pipeline_handle_) {
466     LOG_ERROR_P(
467         this, "can't deactivate audio stream, mixer will control audio stream");
468     return false;
469   }
470 #endif  // USE_MIXER
471   if (!trackrenderer_->DeactivateAudio()) {
472     return false;
473   }
474   is_audio_stream_info_frozen_ = true;
475   return true;
476 }
477
478 bool EsPlayer::ActivateAudio() {
479   LOG_ENTER_P(this);
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());
484     return false;
485   }
486 #ifdef USE_MIXER
487   if (!enable_audio_pipeline_handle_) {
488     LOG_ERROR_P(this,
489                 "can't activate audio stream, mixer will control audio stream");
490     return false;
491   }
492 #endif  // USE_MIXER
493   if (track_.empty()) {
494     return false;
495   }
496   if (!trackrenderer_->ActivateAudio()) {
497     return false;
498   }
499   eos_status_ =
500       internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
501   return true;
502 }
503
504 bool EsPlayer::Start() {
505   LOG_ENTER_P(this);
506   if (is_stopped_) {
507     LOG_ERROR_P(this, "Stop already, no need to Start,leave...");
508     return false;
509   }
510   auto op = [this]() noexcept {
511     if (!trackrenderer_->Start()) {
512       return false;
513     }
514     return true;
515   };
516
517   CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
518
519   es_event::Start event{op};
520   return state_manager_.ProcessEvent(event);
521 }
522
523 bool EsPlayer::Stop() {
524   LOG_ENTER_P(this);
525   is_stopped_ = true;
526   auto stop = [this]() noexcept -> bool {
527     const auto start = performance_checker::Start();
528     if (trackrenderer_) trackrenderer_->Stop();
529     ResetContextForStop_();
530 #ifdef USE_MIXER
531     if (mixer_ticket_) mixer_ticket_.reset();
532 #endif  // USE_MIXER
533     performance_checker::End(start, "Stop");
534     return true;
535   };
536   for (const auto& track : track_) {
537     es_packet_logger_.PrintStoredPacketInfo(
538         internal::ConvertToStreamType(track.type), true);
539   }
540   es_event::Stop event{stop};
541   bool res = state_manager_.ProcessEventStop(event);
542
543   if (preparetask_.valid()) {
544     LOG_INFO_P(this, "Stopped , Wait Prepare() finish...");
545     preparetask_.wait();
546     LOG_INFO_P(this, "Wait , Wait Prepare() Done...");
547   }
548
549   CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
550   CafLogger::StopLoggingThread();
551
552   return res;
553 }
554
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,
585                                low_latency_mode_);
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,
597         resume_time_.time);
598     resume_time_.is_set = false;
599   }
600   trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
601                                fmm_mode_);
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));
614 }
615
616 // LCOV_EXCL_START
617 #ifdef USE_MIXER
618 bool EsPlayer::PrepareVideoMixingMode_(std::vector<Track>* tracks) {
619   LOG_ENTER_P(this);
620   mixer_ticket_->Prepare();
621   if (enable_rsc_alloc_handle_) return true;
622   ResourceType type = ResourceType::kHwMain;
623   if (!mixer_ticket_->GetAvailableResourceType(ResourceCategory::kVideoDecoder,
624                                                &type)) {
625     LOG_ERROR_P(this, "no available resource");
626     return false;
627   }
628   if (!mixer_ticket_->Alloc(ResourceCategory::kVideoDecoder, type)) {
629     LOG_ERROR_P(this, "fail to alloc resource [%d]", static_cast<int>(type));
630     return false;
631   }
632
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;
639         break;
640       }
641     }
642   } else if (type == ResourceType::kNdecoder) {
643     video_decoding_mode_ = internal::kNdecodingMode;
644   }
645   return true;
646 }
647 #endif  // USE_MIXER
648 // LCOV_EXCL_START
649
650 bool EsPlayer::Prepare_() {
651   LOG_ENTER_P(this);
652   if (is_stopped_) {
653     LOG_ERROR_P(this, "Stop already, no need to prepare,leave...");
654     return false;
655   }
656   auto op = [this]() noexcept -> bool {
657     const auto start = performance_checker::Start();
658
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);
664     }
665     std::vector<Track> active_track;
666     if (!track_util::GetActiveTrackList(track_, active_track)) {
667       return false;
668     }
669     trackrenderer_->SetIniProperty(es_conf::ini_property);
670 #ifdef USE_MIXER
671     if (mixer_ticket_) {
672       trackrenderer_->SetVideoFrameBufferType(
673           VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
674       if (!PrepareVideoMixingMode_(&active_track)) {
675         LOG_ERROR_P(this, "fail to prepare mixing mode");
676         return false;
677       }
678     }
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]",
685                      is_audio_focused_);
686           break;
687         }
688       }
689     }
690 #endif  // USE_MIXER
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;
697           break;
698         }
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;
703           break;
704         }
705         default:
706           break;
707       }
708     }
709     SetTrackRendererAttributes_();
710     trackrenderer_->SetTrack(active_track);
711     if (!trackrenderer_->Prepare()) {
712       return false;
713     }
714     performance_checker::End(start, "Prepare");
715     return true;
716   };
717
718   CafLogger::StartLoggingThread();
719   CafLogger::LogMessage(CafEventType::kReady, caf_unique_number);
720
721   es_event::Prepare event{op};
722   if (!state_manager_.ProcessEvent(event)) {
723     return false;
724   }
725   LOG_LEAVE_P(this);
726   return true;
727 }
728
729 void EsPlayer::PrepareTask_() {
730   bool ret = Prepare_();
731
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");
737   }
738
739   kpi::CodecLogger logger;
740   kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
741   logger.SendKpi(ret, event_keys);
742   LOG_LEAVE_P(this);
743 }
744
745 bool EsPlayer::PrepareAsync() {
746   LOG_ENTER_P(this);
747   state_manager_.SetPreparingState(true);
748   preparetask_ = std::async(std::launch::async, &EsPlayer::PrepareTask_, this);
749   if (!preparetask_.valid()) {
750     state_manager_.SetPreparingState(false);
751     return false;
752   }
753   return true;
754 }
755
756 bool EsPlayer::Pause() {
757   LOG_ENTER_P(this);
758   if (is_stopped_) {
759     LOG_ERROR_P(this, "Stop already, no need to pause,leave...");
760     return false;
761   }
762   if (state_manager_.GetState() < EsState::kReady) {
763     LOG_ERROR_P(this, "Invalid State , current %d",
764                 state_manager_.GetStateEnum());
765     return false;
766   }
767   auto op = [this]() noexcept -> bool {
768     if (!trackrenderer_) return false;
769     if (!trackrenderer_->Pause()) {
770       return false;
771     }
772     return true;
773   };
774   for (const auto& track : track_) {
775     es_packet_logger_.PrintStoredPacketInfo(
776         internal::ConvertToStreamType(track.type), true);
777   }
778
779   CafLogger::LogMessage(CafEventType::kPaused, caf_unique_number);
780
781   es_event::Pause event{op};
782   return state_manager_.ProcessEvent(event);
783 }
784
785 bool EsPlayer::Resume() {
786   LOG_ENTER_P(this);
787   if (is_stopped_) {
788     LOG_ERROR_P(this, "Stop already, no need to Resume,leave...");
789     return false;
790   }
791   if (state_manager_.GetState() <= EsState::kReady) {
792     LOG_ERROR_P(this, "Invalid State , current %d",
793                 state_manager_.GetStateEnum());
794     return false;
795   }
796   if (is_resource_conflicted_) {
797     LOG_ERROR_P(this, "Resuem fail resource conflicted");
798     return false;
799   }
800   auto op = [this]() noexcept -> bool {
801     if (!trackrenderer_) return false;
802     if (!trackrenderer_->Resume()) {
803       return false;
804     }
805     return true;
806   };
807   for (const auto& track : track_) {
808     es_packet_logger_.PrintStoredPacketInfo(
809         internal::ConvertToStreamType(track.type), true);
810   }
811
812   CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
813
814   es_event::Resume event{op};
815   return state_manager_.ProcessEvent(event);
816 }
817
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());
822     return false;
823   }
824   if (state_manager_.GetState() == EsState::kIdle) {
825     if (state_manager_.GetPreparingState()) {
826       LOG_ERROR_P(this, "Invalid State , during preparing");
827       return false;
828     }
829     LOG_ERROR("%p resume time [%" PRId64 " ]", this, time);
830     resume_time_.is_set = true;
831     resume_time_.time = time;
832     return true;
833   }
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);
843   }
844   auto op = [this, time]() -> bool {
845     if (!trackrenderer_->Seek(time, current_playback_rate_,
846                               current_audio_mute_)) {
847       return false;
848     }
849     return true;
850   };
851   es_event::Seek event{op};
852   bool ret = state_manager_.ProcessEvent(event);
853   is_seek_done_need_drop = false;
854
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));
863       msg_mutex.unlock();
864       msg_task_cv_.notify_one();
865     }
866   }
867   LOG_DEBUG("%p, [LEAVE] seek end ", this);
868   return ret;
869 }
870
871 void EsPlayer::SetAppInfo(const PlayerAppInfo& app_info) {
872   LOG_ENTER_P(this);
873   if (state_manager_.GetState() != EsState::kIdle) {
874     LOG_ERROR_P(this, "Invalid State , current %d",
875                 state_manager_.GetStateEnum());
876     return;
877   }
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);
882 }
883
884 void EsPlayer::SetAppInfoEx(const PlayerAppInfoEx& app_info) {
885   LOG_ENTER_P(this);
886   if (state_manager_.GetState() != EsState::kIdle) {
887     LOG_ERROR_P(this, "Invalid State , current %d",
888                 state_manager_.GetStateEnum());
889     return;
890   }
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);
897 }
898
899 bool EsPlayer::SetPlaybackRate(const double rate, const bool audio_mute) {
900   LOG_ENTER_P(this);
901
902   if (rate <= 0 || rate > 2.0) {
903     LOG_ERROR_P(this, "Not a valid PlaybackRate");
904     return false;
905   }
906
907   if (state_manager_.GetState() < EsState::kReady) {
908     LOG_ERROR_P(this, "Invalid State , current %d",
909                 state_manager_.GetStateEnum());
910     return false;
911   }
912
913   auto op = [this, rate, audio_mute]() -> bool {
914     if (!trackrenderer_->SetPlaybackRate(rate, audio_mute)) {
915       return false;
916     }
917     current_playback_rate_ = rate;
918     current_audio_mute_ = audio_mute;
919     return true;
920   };
921   es_event::PlaybackRate event{op};
922   return state_manager_.ProcessEvent(event);
923
924   LOG_LEAVE_P(this);
925   return true;
926 }
927
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());
932     return false;
933   }
934 #ifdef USE_MIXER
935   if (mixer_ticket_) mixer_ticket_.reset();
936 #endif  // USE_MIXER
937   return trackrenderer_->SetDisplay(type, obj);
938 }
939
940 // LCOV_EXCL_START
941 #ifdef USE_MIXER
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);
951   }
952   return true;
953 }
954 #endif  // USE_MIXER
955
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());
961     return false;
962   }
963 #ifdef USE_MIXER
964   if (mixer_ticket_) mixer_ticket_.reset();
965 #endif  // USE_MIXER
966   return trackrenderer_->SetDisplay(type, ecore_wl2_window, x, y, w, h);
967 }
968
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());
975     return false;
976   }
977 #ifdef USE_MIXER
978   if (mixer_ticket_) mixer_ticket_.reset();
979 #endif  // USE_MIXER
980   return trackrenderer_->SetDisplaySubsurface(type, ecore_wl2_subsurface, x, y,
981                                               w, h);
982 }
983
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());
989     return false;
990   }
991 #ifdef USE_MIXER
992   if (mixer_ticket_) mixer_ticket_.reset();
993 #endif  // USE_MIXER
994   return trackrenderer_->SetDisplay(type, surface_id, x, y, w, h);
995 }
996 // LCOV_EXCL_START
997
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());
1002     return false;
1003   }
1004   trackrenderer_->SetDisplayMode(mode);
1005   return true;
1006 }
1007
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());
1012     return false;
1013   }
1014   trackrenderer_->SetStretchMode(mode);
1015   return true;
1016 }
1017
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());
1022     return false;
1023   }
1024 #ifdef USE_MIXER
1025   mixerticket_roi_ = roi;
1026   if (mixer_ticket_) return true;
1027 #endif  // USE_MIXER
1028   return trackrenderer_->SetDisplayRoi(roi);
1029 }
1030
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());
1035     return false;
1036   }
1037   return trackrenderer_->SetVideoRoi(area);
1038 }
1039
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());
1044     return false;
1045   }
1046   return trackrenderer_->ResizeRenderRect(rect);
1047 }
1048
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());
1053     return false;
1054   }
1055   return trackrenderer_->SetDisplayRotate(rotate);
1056 }
1057
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());
1062     return false;
1063   }
1064   if (trackrenderer_->GetDisplayRotate(rotate)) {
1065     return true;
1066   }
1067   return false;
1068 }
1069
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());
1074     return false;
1075   }
1076 #ifdef USE_MIXER
1077   if (mixer_ticket_) {
1078     LOG_INFO_P(this, "mixed player is_visible [%d] -> [%d]", is_visible_,
1079                is_visible);
1080     is_visible_ = is_visible;
1081     return true;
1082   }
1083 #endif  // USE_MIXER
1084   return trackrenderer_->SetDisplayVisible(is_visible);
1085 }
1086
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());
1091     return false;
1092   }
1093   if (drm_property_.type != drm::Type::kNone) {
1094     LOG_ERROR_P(this, "drm type is already set for sending encrypted packets");
1095     return false;
1096   }
1097   LOG_INFO_P(this, "set trust zone use [%d]", is_using_tz);
1098   drm_property_.external_decryption = is_using_tz;
1099
1100   drm::Property drm_property = drm_property_;
1101   drm_property.type = drm::Type::kPlayready;
1102   trackrenderer_->SetDrm(drm_property);
1103   return true;
1104 }
1105
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());
1110     return false;
1111   }
1112   LOG_INFO_P(this, "set submit data type [%d]", static_cast<int>(type));
1113
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);
1121   return true;
1122 }
1123
1124 bool EsPlayer::SetTrack_(const Track& track) {
1125   LOG_ENTER_P(this);
1126   track_util::ShowTrackInfo(track);
1127   track_.push_back(std::move(track));
1128   return true;
1129 }
1130
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;
1136   };
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.");
1141     SetTrack_(track);
1142     return true;
1143   }
1144   if (target->active != false) {
1145     LOG_ERROR_P(this, "The track should be deactivated in advance.");
1146     return false;
1147   }
1148   track_.erase(target);
1149   LOG_ERROR_P(this, "previously added %s stream is deleted",
1150               (type == kTrackTypeAudio) ? "audio" : "video");
1151   return SetTrack_(track);
1152 }
1153
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;
1159     };
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");
1163       return false;
1164     }
1165   }
1166   auto op = [this, track]() noexcept {
1167     if (!SetTrack_(track)) {
1168       return false;
1169     }
1170     return true;
1171   };
1172
1173   CafLogger::LogMessage(CafEventType::kStreamReady, caf_unique_number);
1174
1175   es_event::SetStream event{op};
1176   return state_manager_.ProcessEvent(event);
1177 }
1178
1179 bool EsPlayer::SetStream(const AudioStreamPtr& stream) {
1180   LOG_ENTER_P(this);
1181   bool ret = false;
1182   BOOST_SCOPE_EXIT(&ret, &stream, &force_audio_swdecoder_use_) {
1183     if (ret)
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();
1188   }
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());
1193     return ret;
1194   }
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");
1199       return ret;
1200     }
1201     track.active = false;
1202     ret = ChangeStream_(track);
1203     return ret;
1204   }
1205   ret = SetStream_(track);
1206   return ret;
1207 }
1208
1209 bool EsPlayer::SetStream(const VideoStreamPtr& stream) {
1210   LOG_ENTER_P(this);
1211   if (state_manager_.GetState() < EsState::kIdle) {
1212     LOG_ERROR_P(this, "Invalid State , current %d",
1213                 state_manager_.GetStateEnum());
1214     return false;
1215   }
1216   Track track = stream->GetTrack_();
1217   if (state_manager_.GetState() >= EsState::kReady) {
1218     track.active = false;
1219     return ChangeStream_(track);
1220   }
1221   return SetStream_(track);
1222 }
1223
1224 bool EsPlayer::SwitchAudioStreamOnTheFly(const AudioStreamPtr& stream) {
1225   LOG_ENTER_P(this);
1226   if (state_manager_.GetState() < EsState::kReady) {
1227     LOG_ERROR_P(this, "Invalid State , current %d",
1228                 state_manager_.GetStateEnum());
1229     return false;
1230   }
1231   Track track = stream->GetTrack_();
1232
1233   if (!internal::IsAvailableCodecSwitch(track)) {
1234     LOG_ERROR_P(this, "Invalid new mimetype [%s][%d]", track.mimetype.c_str(),
1235                 track.version);
1236     return false;
1237   }
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);
1243         return false;
1244       }
1245       if (!Flush(StreamType::kAudio)) return false;
1246       old_track.active = false;
1247       break;
1248     }
1249   }
1250   if (!ChangeStream_(track)) return false;
1251
1252   trackrenderer_->SetTrack(track_);
1253   return true;
1254 }
1255
1256 bool EsPlayer::SetAdvancedPictureQualityType(const AdvPictureQualityType type) {
1257   LOG_ENTER_P(this);
1258   if (state_manager_.GetState() != EsState::kIdle) {
1259     LOG_ERROR_P(this, "Invalid State , current %d",
1260                 state_manager_.GetStateEnum());
1261     return false;
1262   }
1263   trackrenderer_->SetAdvancedPictureQualityType(type);
1264   return true;
1265 }
1266
1267 bool EsPlayer::SetResourceAllocatePolicy(const RscAllocPolicy policy) {
1268   LOG_ENTER_P(this);
1269   if (state_manager_.GetState() != EsState::kIdle) {
1270     LOG_ERROR_P(this, "Invalid State , current %d",
1271                 state_manager_.GetStateEnum());
1272     return false;
1273   }
1274   resource_alloc_policy_ = policy;
1275   trackrenderer_->SetResourceAllocatePolicy(policy);
1276   return true;
1277 }
1278
1279 // LCOV_EXCL_START
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;
1286   }
1287   return trackrenderer_->GetDecodedPacket(packet);
1288 }
1289
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());
1294     return false;
1295   }
1296   return trackrenderer_->ReturnDecodedPacket(packet);
1297 }
1298 // LCOV_EXCL_STOP
1299
1300 void EsPlayer::ResetContextForClose_() {
1301   internal::ResetDrmProperty(drm_property_);
1302   track_.clear();
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;
1308   fmm_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;
1316 }
1317
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;
1322   }
1323   {
1324     std::lock_guard<std::mutex> lock(eos_mutex_);
1325     eos_status_ = EosStatus::kAllEos;
1326   }
1327   current_playback_rate_ = 1.0;
1328   current_audio_mute_ = false;
1329 }
1330
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,
1338         &byte_size_);
1339     trackrenderer_->GetAttribute(
1340         TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
1341         &time_size_);
1342   } else if (type == TrackType::kTrackTypeAudio) {
1343     trackrenderer_->GetAttribute(
1344         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
1345         &byte_size_);
1346     trackrenderer_->GetAttribute(
1347         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
1348         &time_size_);
1349   } else
1350     return;
1351   try {
1352     *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
1353     *time_size = boost::any_cast<std::uint64_t>(time_size_);
1354   } catch (...) {
1355     LOG_INFO_P(this, "any_cast failed");
1356   }
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);
1361 }
1362
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;
1369     return nullptr;
1370   }
1371   GstBuffer* gstbuffer = gst_buffer_new_and_alloc(size);
1372   if (!gstbuffer) {
1373     *status = MakeBufferStatus::kOutOfMemory;
1374     return nullptr;
1375   }
1376   if (buffer != nullptr) {
1377     GstMapInfo map;
1378     gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
1379     memcpy(map.data, buffer.get(), size);
1380     gst_buffer_unmap(gstbuffer, &map);
1381   }
1382
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);
1403   }
1404   uint32_t hdr10p_size = packet->GetHdr10pSize();
1405   std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
1406
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);
1414
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);
1425   }
1426   *status = MakeBufferStatus::kSuccess;
1427   return gstbuffer;
1428 }
1429
1430 PacketSubmitStatus EsPlayer::SubmitEosPacket_(const TrackType& type) {
1431   PacketSubmitStatus submitstate = PacketSubmitStatus::kSuccess;
1432   {
1433     std::lock_guard<std::mutex> lock(eos_mutex_);
1434     switch (type) {
1435       case kTrackTypeAudio:
1436         eos_status_ |= EosStatus::kAudioEos;
1437         break;
1438       case kTrackTypeVideo:
1439         eos_status_ |= EosStatus::kVideoEos;
1440         break;
1441       default:
1442         break;
1443     }
1444     if (eos_status_ != EosStatus::kAllEos) {
1445       return submitstate;
1446     }
1447   }
1448   for (int tracktype = kTrackTypeAudio; tracktype < kTrackTypeMax;
1449        ++tracktype) {
1450     auto inbuffer =
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;
1456       return submitstate;
1457     }
1458   }
1459   return submitstate;
1460 }
1461
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);
1468 }
1469
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);
1476
1477   switch (submitstate) {
1478     case TrackRendererAdapter::SubmitStatus::kSuccess:
1479     case TrackRendererAdapter::SubmitStatus::kDrop:
1480       status = PacketSubmitStatus::kSuccess;
1481       break;
1482     case TrackRendererAdapter::SubmitStatus::kFull:
1483       UnsetTzQdata_(buffer);
1484       trackrenderer_event_listener_->OnBufferStatus(buffer->GetType(),
1485                                                     BufferStatus::kOverrun);
1486       status = PacketSubmitStatus::kFull;
1487       break;
1488     default:
1489       UnsetTzQdata_(buffer);
1490       status = PacketSubmitStatus::kNotPrepared;
1491       break;
1492   }
1493   return status;
1494 }
1495
1496 // LCOV_EXCL_START
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);
1509
1510   if (type == kTrackTypeAudio) {
1511     Track audio_track;
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);
1521     }
1522   }
1523 }
1524
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);
1537   }
1538 }
1539 // LCOV_EXCL_STOP
1540
1541 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
1542                                                  SubmitPacketOperator op) {
1543   if (state_manager_.GetState() < EsState::kIdle) {
1544     return PacketSubmitStatus::kNotPrepared;
1545   }
1546   if (!packet) return PacketSubmitStatus::kInvalidPacket;
1547
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;
1552
1553   if (state_manager_.GetState() == EsState::kPaused ||
1554       state_manager_.GetState() == EsState::kReady) {
1555     internal::AppsrcQueueSizeOption byte_based, time_based;
1556     switch (type) {
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;
1562         break;
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;
1568         break;
1569       default:
1570         break;
1571     }
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);
1577   }
1578
1579   es_packet_logger_.StorePacketInfo(packet);
1580   es_packet_logger_.PrintStoredPacketInfo(packet->GetType());
1581
1582   MakeBufferStatus make_buffer_status;
1583   GstBuffer* gstbuffer = GetGstBuffer_(packet, &make_buffer_status);
1584   if (!gstbuffer) {
1585     if (make_buffer_status == MakeBufferStatus::kEos)
1586       return SubmitEosPacket_(type);
1587     else if (make_buffer_status == MakeBufferStatus::kOutOfMemory)
1588       return PacketSubmitStatus::kOutOfMemory;
1589   }
1590   if (op != nullptr) {
1591     PacketSubmitStatus op_status = op(gstbuffer);
1592     if (op_status != PacketSubmitStatus::kSuccess) {
1593       return op_status;
1594     }
1595   }
1596
1597   auto inbuffer = DecoderInputBuffer::Create(type, 0, gstbuffer);
1598   gst_buffer_unref(gstbuffer);
1599
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;
1605   }
1606
1607   return SubmitDecoderInputBuffer_(inbuffer);
1608 }
1609
1610 PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
1611   std::lock_guard<std::mutex> lk(submit_mutex_);
1612   return SubmitPacketCommon_(packet, nullptr);
1613 }
1614
1615 // LCOV_EXCL_START
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);
1627     }
1628     return PacketSubmitStatus::kSuccess;
1629   };
1630   return SubmitPacketCommon_(packet, submitpacket_op);
1631 }
1632
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;
1642   };
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());
1646     if (!state_manager_
1647              .GetPreparingState()) {  // if the stream comes with clean data at
1648                                       // the beginning, re-post kpi when we get
1649                                       // key system.
1650       kpi::CodecLogger logger;
1651       kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
1652       logger.SendKpi(true, event_keys);
1653     }
1654     key_system_acquired_ = true;
1655   }
1656   return SubmitPacketCommon_(packet, submitpacket_op);
1657 }
1658 // LCOV_EXCL_STOP
1659
1660 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
1661
1662 bool EsPlayer::GetPlayingTime(uint64_t* time) {
1663   if (!time) return false;
1664   if (state_manager_.GetState() <= EsState::kReady) {
1665     *time = 0;
1666     return false;
1667   }
1668   return trackrenderer_->GetPlayingTime(time);
1669 }
1670
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());
1675     return false;
1676   }
1677   return trackrenderer_->SetAudioMute(is_mute);
1678 }
1679
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());
1687     return false;
1688   }
1689   if (type == DecodedVideoFrameBufferType::kScale &&
1690       video_codec_type_ == kPlayerVideoCodecTypeSW) {
1691     LOG_ERROR_P(this, "kScale is not supportted when using sw video decoder");
1692     return false;
1693   }
1694   trackrenderer_->SetVideoFrameBufferType(
1695       VideoFrameTypeStrategyPtr(new DefaultVideoFrameTypeStrategy(type)));
1696   vidoe_frame_buffer_type_ = type;
1697   return true;
1698 }
1699
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());
1705     return false;
1706   }
1707
1708   return trackrenderer_->SetVideoFrameBufferScaleResolution(target_width,
1709                                                             target_height);
1710 }
1711
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());
1715     return false;
1716   }
1717
1718   return trackrenderer_->SetDecodedVideoFrameRate(request_framerate);
1719 }
1720
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;
1727 }
1728
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)
1733     return false;
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");
1738         return false;
1739       }
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");
1744         return false;
1745       }
1746       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeVideo,
1747                                                         padaptive_info);
1748     case PlayerAdaptiveInfo::kDroppedAudioFramesForCatchup:
1749       if (state_manager_.GetState() < EsState::kReady) {
1750         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1751         return false;
1752       }
1753       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeAudio,
1754                                                         padaptive_info);
1755     default:
1756       break;
1757   }
1758   return false;
1759 }
1760
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);
1764     return false;
1765   }
1766   if (state_manager_.GetState() < EsState::kIdle) {
1767     LOG_ERROR_P(this, "Invalid State , current %d",
1768                 state_manager_.GetStateEnum());
1769     return false;
1770   }
1771   return trackrenderer_->SetVolume(volume);
1772 }
1773
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());
1778     return false;
1779   }
1780   return trackrenderer_->GetVolume(volume);
1781 }
1782
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());
1787     return false;
1788   }
1789   eos_status_ =
1790       internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
1791   es_packet_logger_.ResetLog(type);
1792   return trackrenderer_->Flush(type);
1793 }
1794
1795 bool EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
1796   TrackType track_type = kTrackTypeMax;
1797   switch (option) {
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;
1803       break;
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;
1809       break;
1810     default:
1811       break;
1812   }
1813   if (track_type == kTrackTypeMax) {
1814     LOG_ERROR_P(this, "Invalid option!!!");
1815     return false;
1816   }
1817
1818   Track activated_track;
1819   bool is_activated =
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);
1825     return false;
1826   }
1827
1828   switch (option) {
1829     case BufferOption::kBufferAudioMaxByteSize:
1830       src_queue_size_.kMaxByteOfAudioSrcQueue = size;
1831       break;
1832     case BufferOption::kBufferVideoMaxByteSize:
1833       src_queue_size_.kMaxByteOfVideoSrcQueue = size;
1834       break;
1835     case BufferOption::kBufferAudioMinByteThreshold:
1836       src_queue_size_.kMinByteThresholdOfAudioSrcQueue =
1837           static_cast<uint32_t>(size);
1838       break;
1839     case BufferOption::kBufferVideoMinByteThreshold:
1840       src_queue_size_.kMinByteThresholdOfVideoSrcQueue =
1841           static_cast<uint32_t>(size);
1842       break;
1843     case BufferOption::kBufferAudioMaxTimeSize:
1844       src_queue_size_.kMaxTimeOfAudioSrcQueue = size;
1845       break;
1846     case BufferOption::kBufferVideoMaxTimeSize:
1847       src_queue_size_.kMaxTimeOfVideoSrcQueue = size;
1848       break;
1849     case BufferOption::kBufferAudioMinTimeThreshold:
1850       src_queue_size_.kMinTimeThresholdOfAudioSrcQueue =
1851           static_cast<uint32_t>(size);
1852       break;
1853     case BufferOption::kBufferVideoMinTimeThreshold:
1854       src_queue_size_.kMinTimeThresholdOfVideoSrcQueue =
1855           static_cast<uint32_t>(size);
1856       break;
1857     default:
1858       LOG_ERROR_P(this, "Invalid option!!!");
1859       break;
1860   }
1861   return true;
1862 }
1863
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());
1868     return false;
1869   }
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));
1874     return false;
1875   }
1876   low_latency_mode_ |= static_cast<std::uint32_t>(mode);
1877   return true;
1878 }
1879
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());
1884     return false;
1885   }
1886   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1887     LOG_ERROR_P(this,
1888                 "low latency mode have to be set except disable_sync mode");
1889     return false;
1890   }
1891   std::int64_t ns_unit = 0;
1892   if (time_unit_type == kPlayerTimeUnitTypeMs)
1893     ns_unit = 1000000;
1894   else if (time_unit_type == kPlayerTimeUnitTypeUs)
1895     ns_unit = 1000;
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",
1899               this, offset);
1900     return false;
1901   }
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));
1921   }
1922   return true;
1923 }
1924
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());
1929     return false;
1930   }
1931   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1932     LOG_ERROR_P(this, "low latency mode have to be set");
1933     return false;
1934   }
1935   if (type == StreamType::kMax) return false;
1936   boost::any off_set;
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);
1943
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);
1949   return true;
1950 }
1951
1952 bool EsPlayer::SetVideoFramePeekMode() {
1953   if (state_manager_.GetState() != EsState::kIdle) {
1954     LOG_ERROR_P(this, "Invalid State , current %d",
1955                 state_manager_.GetStateEnum());
1956     return false;
1957   }
1958   constexpr std::uint32_t peek_mode_on = 1;
1959   video_frame_peek_mode_ = peek_mode_on;
1960   return true;
1961 }
1962
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();
1968     return true;
1969   }
1970   LOG_ERROR_P(this, "Invalid State , current %d",
1971               state_manager_.GetStateEnum());
1972   return false;
1973 }
1974
1975 bool EsPlayer::SetUnlimitedMaxBufferMode() {
1976   if (state_manager_.GetState() != EsState::kIdle) {
1977     LOG_ERROR_P(this, "Invalid State , current %d",
1978                 state_manager_.GetStateEnum());
1979     return false;
1980   }
1981   constexpr std::uint32_t unlimited_max_buffer_mode_on = 1;
1982   unlimited_max_buffer_mode_ = unlimited_max_buffer_mode_on;
1983   return true;
1984 }
1985
1986 ErrorType EsPlayer::SetFmmMode() {
1987   EsState state = state_manager_.GetState();
1988   LOG_ENTER_P(this);
1989   if (state < EsState::kIdle) {
1990     LOG_ERROR_P(this, "Invalid State , current %d",
1991                 state_manager_.GetStateEnum());
1992     return ErrorType::kInvalidState;
1993   }
1994
1995   int onoff = 0;
1996   ErrorType ret = ErrorType::kNone;
1997   if (trackrenderer_->GetFmmAutoMode(&onoff) == false) {
1998     return ErrorType::kInvalidOperation;
1999   }
2000
2001   enum {
2002     FMM_AUTO_OFF = 0,
2003     FMM_AUTO_ON = 1,
2004   };
2005
2006   if (onoff == FMM_AUTO_OFF) ret = ErrorType::kInvalidOperation;
2007
2008   fmm_mode_ = FMM_AUTO_ON;
2009
2010   if (state < EsState::kReady) return ret;
2011
2012   trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
2013                                fmm_mode_);
2014   return ret;
2015 }
2016
2017 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
2018   Track activated_track;
2019   bool is_existed =
2020       track_util::GetActiveTrack(track_, kTrackTypeAudio, &activated_track);
2021   EsState state = state_manager_.GetState();
2022   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2023     LOG_ERROR_P(this,
2024                 "Invalid State [state:%d] or audio stream already exists[%d],",
2025                 state_manager_.GetStateEnum(), is_existed);
2026     return false;
2027   }
2028   if (force_audio_swdecoder_use_ && type == kPlayerAudioCodecTypeHW) {
2029     LOG_ERROR_P(this, "Not support hw decoder");
2030     return false;
2031   }
2032   LOG_INFO_P(this, "PlayerAudioCodecType [%s]",
2033              (type == kPlayerAudioCodecTypeHW) ? "hardware" : "software");
2034   audio_codec_type_ = type;
2035   return true;
2036 }
2037
2038 bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
2039   Track activated_track;
2040   bool is_existed =
2041       track_util::GetActiveTrack(track_, kTrackTypeVideo, &activated_track);
2042   EsState state = state_manager_.GetState();
2043   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2044     LOG_ERROR_P(this,
2045                 "Invalid State [state:%d] or video stream already exists[%d],",
2046                 state_manager_.GetStateEnum(), is_existed);
2047     return false;
2048   }
2049   if (force_video_swdecoder_use_ &&
2050       (type == kPlayerVideoCodecTypeHW ||
2051        type == kPlayerVideoCodecTypeHWNdecoding)) {
2052     LOG_ERROR_P(this, "Not support hw decoder");
2053     return false;
2054   }
2055   if (type == kPlayerVideoCodecTypeSW &&
2056       vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
2057     LOG_ERROR_P(this,
2058                 "sw video decoder is not supportted when video frame buffer "
2059                 "type is scale");
2060     return false;
2061   }
2062 #ifdef USE_MIXER
2063   if (!enable_rsc_alloc_handle_) {
2064     LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2065     return false;
2066   }
2067   if (type == kPlayerVideoCodecTypeHWNdecoding) {
2068     LOG_INFO_P(this, "PlayerVideoCodecType HW N-decoding");
2069     video_decoding_mode_ = internal::kNdecodingMode;
2070     return true;
2071   }
2072 #endif  // USE_MIXER
2073   LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
2074              (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
2075   video_codec_type_ = type;
2076   return true;
2077 }
2078
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());
2083     return false;
2084   }
2085   trackrenderer_->SetAiFilter(aifilter);
2086   return true;
2087 }
2088
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);
2096     return false;
2097   }
2098   if (state_manager_.GetState() < EsState::kIdle) {
2099     LOG_ERROR_P(this, "Invalid State , current %d",
2100                 state_manager_.GetStateEnum());
2101     return false;
2102   }
2103   return trackrenderer_->InitAudioEasingInfo(init_volume, init_elapsed_time,
2104                                              easing_info);
2105 }
2106
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);
2110     return false;
2111   }
2112   if (state_manager_.GetState() < EsState::kIdle) {
2113     LOG_ERROR_P(this, "Invalid State , current %d",
2114                 state_manager_.GetStateEnum());
2115     return false;
2116   }
2117   return trackrenderer_->UpdateAudioEasingInfo(easing_info);
2118 }
2119
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());
2126     return false;
2127   }
2128   return trackrenderer_->GetAudioEasingInfo(current_volume, elapsed_time,
2129                                             easing_info);
2130 }
2131
2132 bool EsPlayer::StartAudioEasing() {
2133   if (state_manager_.GetState() < EsState::kReady) {
2134     LOG_ERROR_P(this, "Invalid State , current %d",
2135                 state_manager_.GetStateEnum());
2136     return false;
2137   }
2138   return trackrenderer_->StartAudioEasing();
2139 }
2140
2141 bool EsPlayer::StopAudioEasing() {
2142   if (state_manager_.GetState() < EsState::kIdle) {
2143     LOG_ERROR_P(this, "Invalid State , current %d",
2144                 state_manager_.GetStateEnum());
2145     return false;
2146   }
2147   return trackrenderer_->StopAudioEasing();
2148 }
2149
2150 bool EsPlayer::SetAlternativeVideoResource(unsigned int rsc_type) {
2151   if (state_manager_.GetState() == EsState::kNone) {
2152     LOG_ERROR_P(this, "Invalid State");
2153     return false;
2154   }
2155 #ifdef USE_MIXER
2156   if (!enable_rsc_alloc_handle_) {
2157     LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2158     return false;
2159   }
2160 #endif  // USE_MIXER
2161   if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2162     LOG_ERROR_P(this,
2163                 "has set resource allocate policy, the alternative "
2164                 "resource setting will be wrong");
2165     return false;
2166   }
2167   alternative_video_resource_ = static_cast<std::uint32_t>(rsc_type);
2168   return true;
2169 }
2170
2171 bool EsPlayer::SetAlternativeAudioResource(
2172     const PlayerAudioResourceType rsc_type) {
2173   if (state_manager_.GetState() == EsState::kNone) {
2174     LOG_ERROR_P(this, "Invalid State");
2175     return false;
2176   }
2177
2178   if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2179     LOG_ERROR_P(this,
2180                 "has set resource allocate policy, the alternative "
2181                 "resource setting will be wrong");
2182     return false;
2183   }
2184   return trackrenderer_->SetAlternativeAudioResource(rsc_type);
2185 }
2186
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());
2191     return false;
2192   }
2193
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_));
2197     return false;
2198   }
2199
2200   if (trackrenderer_->SetCatchUpSpeed(level)) {
2201     return true;
2202   }
2203   return false;
2204 }
2205
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());
2210     return false;
2211   }
2212
2213   if (trackrenderer_->GetVideoLatencyStatus(status)) {
2214     return true;
2215   }
2216   return false;
2217 }
2218
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());
2223     return false;
2224   }
2225
2226   if (trackrenderer_->GetAudioLatencyStatus(status)) {
2227     return true;
2228   }
2229   return false;
2230 }
2231
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());
2236     return false;
2237   }
2238
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_));
2242     return false;
2243   }
2244
2245   LOG_INFO_P(this, "video_mid_latency_threshold : [%u]", threshold);
2246
2247   trackrenderer_->SetVideoMidLatencyThreshold(threshold);
2248   return true;
2249 }
2250
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());
2255     return false;
2256   }
2257
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_));
2261     return false;
2262   }
2263
2264   LOG_INFO_P(this, "audio_mid_latency_threshold : [%u]", threshold);
2265
2266   trackrenderer_->SetAudioMidLatencyThreshold(threshold);
2267   return true;
2268 }
2269
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());
2274     return false;
2275   }
2276
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_));
2280     return false;
2281   }
2282
2283   LOG_INFO_P(this, "video_high_latency_threshold : [%u]", threshold);
2284
2285   trackrenderer_->SetVideoHighLatencyThreshold(threshold);
2286   return true;
2287 }
2288
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());
2293     return false;
2294   }
2295
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_));
2299     return false;
2300   }
2301
2302   LOG_INFO_P(this, "audio_high_latency_threshold : [%u]", threshold);
2303
2304   trackrenderer_->SetAudioHighLatencyThreshold(threshold);
2305   return true;
2306 }
2307
2308 bool EsPlayer::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
2309   if (frame_count == nullptr) {
2310     LOG_ERROR_P(this, "frame count is nullptr");
2311     return false;
2312   }
2313   if (state_manager_.GetState() < EsState::kReady) {
2314     LOG_ERROR_P(this, "Invalid State , current %d",
2315                 state_manager_.GetStateEnum());
2316     return false;
2317   }
2318
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_));
2322     return false;
2323   }
2324
2325   return trackrenderer_->GetLowLatencyPcmBufferSize(frame_count);
2326 }
2327
2328 bool EsPlayer::GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
2329   if (frame_count == nullptr) {
2330     LOG_ERROR_P(this, "frame count is nullptr");
2331     return false;
2332   }
2333   if (state_manager_.GetState() < EsState::kReady) {
2334     LOG_ERROR_P(this, "Invalid State , current %d",
2335                 state_manager_.GetStateEnum());
2336     return false;
2337   }
2338
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_));
2342     return false;
2343   }
2344
2345   return trackrenderer_->GetLowLatencyPcmCurrentBufferLevel(frame_count);
2346 }
2347
2348 bool EsPlayer::GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
2349   if (underrun_count == nullptr) {
2350     LOG_ERROR_P(this, "underrun count is nullptr");
2351     return false;
2352   }
2353   if (state_manager_.GetState() < EsState::kReady) {
2354     LOG_ERROR_P(this, "Invalid State , current %d",
2355                 state_manager_.GetStateEnum());
2356     return false;
2357   }
2358
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_));
2362     return false;
2363   }
2364
2365   return trackrenderer_->GetLowLatencyPcmUnderrunCount(underrun_count);
2366 }
2367
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());
2373     *virtual_id = -1;
2374     return false;
2375   }
2376   return trackrenderer_->GetVirtualRscId(type, virtual_id);
2377 }
2378
2379 bool EsPlayer::SetAudioPreloading() {
2380   if (state_manager_.GetState() != EsState::kIdle) {
2381     LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
2382     return false;
2383   }
2384   return trackrenderer_->SetAudioPreloading();
2385 }
2386
2387 void EsPlayer::Init_() {
2388   track_.clear();
2389   is_stopped_ = false;
2390   LOG_LEAVE_P(this);
2391 }
2392
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);
2398     } else {
2399       msg_mutex.unlock();
2400       msg_queue_.front()->Execute();
2401       msg_mutex.lock();
2402       msg_queue_.pop();
2403     }
2404   }
2405   while (!msg_queue_.empty()) {
2406     msg_queue_.pop();
2407   }
2408   LOG_INFO_P(this, "Stop MsgTask");
2409 }
2410
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));
2419   msg_mutex.unlock();
2420   handler_->msg_task_cv_.notify_one();
2421   LOG_LEAVE_P(handler_);
2422 }
2423
2424 // LCOV_EXCL_START
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));
2434   msg_mutex.unlock();
2435   handler_->msg_task_cv_.notify_one();
2436   LOG_LEAVE_P(handler_);
2437 }
2438
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");
2443     return;
2444   }
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;
2449   auto listener =
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));
2455   msg_mutex.unlock();
2456   if (handler_->is_stopped_) {
2457     LOG_LEAVE_P(handler_);
2458     return;
2459   }
2460   handler_->msg_task_cv_.notify_one();
2461   LOG_LEAVE_P(handler_);
2462 }
2463
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_);
2473
2474   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2475   handler_->msg_queue_.push(std::move(msg));
2476   msg_mutex.unlock();
2477   handler_->msg_task_cv_.notify_one();
2478 }
2479
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;
2484
2485   std::vector<Track> activeTracks;
2486   track_util::GetActiveTrackList(handler_->track_, activeTracks);
2487
2488   Json::Value message;
2489   message["error_code"] = (int)error_code;
2490
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};
2498           int nLen = 19;
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));
2508           nLen = 19;
2509           strncat(json_string, std::to_string(track.framerate_num).c_str(),
2510                   nLen);
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(),
2517                   nLen);
2518           message["fps"] = json_string;
2519           message["detail_info"] = error_msg;
2520           break;
2521         }
2522       }
2523       break;
2524     case ErrorType::kNotSupportedAudioCodec:
2525
2526       break;
2527     default:
2528       break;
2529   }
2530
2531   Json::FastWriter writer;
2532   std::string str = writer.write(message);
2533   LOG_INFO_P(handler_, "error message: %s", str.c_str());
2534
2535   auto listener = std::bind(&esplusplayer::EsEventListener::OnErrorMsg,
2536                             handler_->eventlistener_, std::placeholders::_1,
2537                             std::placeholders::_2, std::placeholders::_3);
2538   auto msg =
2539       es_msg::ErrorMsg::Make(error_code, str.c_str(), str.size(), listener,
2540                              handler_->eventlistener_userdata_);
2541
2542   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2543   handler_->msg_queue_.push(std::move(msg));
2544   msg_mutex.unlock();
2545   handler_->msg_task_cv_.notify_one();
2546 }
2547 // LCOV_EXCL_STOP
2548
2549 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
2550     const TrackType& type) {
2551   LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
2552              (type == kTrackTypeAudio) ? "audio" : "video");
2553
2554   handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
2555
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));
2564   msg_mutex.unlock();
2565   handler_->msg_task_cv_.notify_one();
2566 }
2567
2568 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
2569   uint64_t offset = handler_->need_data_[type].seek_offset;
2570
2571   LOG_INFO("%p, OnReadyToSeek [%s] offset [%" PRId64 "]", handler_,
2572            (type == kTrackTypeAudio) ? "audio" : "video", offset);
2573
2574   handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
2575   handler_->need_data_[type].seek_offset = 0;
2576
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));
2586   msg_mutex.unlock();
2587   handler_->msg_task_cv_.notify_one();
2588 }
2589
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);
2602   auto msg =
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));
2607   msg_mutex.unlock();
2608   handler_->msg_task_cv_.notify_one();
2609 }
2610
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_))
2615     return;
2616
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) {
2622     ReadyToSeek_(type);
2623   } else {
2624     BufferStatus_(type, status);
2625   }
2626 }
2627
2628 // LCOV_EXCL_START
2629 void EsPlayer::TrackRendererEventListener::OnMediaPacketGetTbmBufPtr(
2630     void** tbm_ptr, bool is_scale_change) {
2631   if (!handler_->eventlistener_) return;
2632
2633   handler_->eventlistener_->OnMediaPacketGetTbmBufPtr(tbm_ptr, is_scale_change);
2634 }
2635
2636 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
2637     const DecodedVideoPacket& packet) {
2638   if (!handler_->eventlistener_) return;
2639
2640   handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
2641 }
2642
2643 #ifdef USE_MIXER
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);
2665   }
2666 }
2667
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;
2673     return true;
2674   }
2675   if (active) {
2676     Track activated_track;
2677     track_util::GetActiveTrack(handler_->track_, kTrackTypeAudio,
2678                                &activated_track);
2679     LOG_INFO_P(handler_, "Activate audio track");
2680     {
2681       std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2682       handler_->eos_status_ =
2683           internal::ResetEosStatus(kTrackTypeAudio, handler_->eos_status_);
2684     }
2685     return handler_->trackrenderer_->Activate(kTrackTypeAudio, activated_track);
2686   }
2687   LOG_INFO_P(handler_, "Deactivate audio track");
2688   handler_->is_audio_focused_ = false;
2689   {
2690     std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2691     handler_->eos_status_ |= EosStatus::kAudioEos;
2692   }
2693   return handler_->trackrenderer_->Deactivate(kTrackTypeAudio);
2694 }
2695
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;
2701   return true;
2702 }
2703 #endif  // USE_MIXER
2704 // LCOV_EXCL_STOP
2705
2706 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
2707                                                       const uint64_t offset) {
2708   if (!handler_->eventlistener_) return;
2709
2710   if (handler_->need_data_[type].mask != kNeedDataMaskByPrepare) {
2711     handler_->need_data_[type].mask |= kNeedDataMaskBySeek;
2712     handler_->need_data_[type].seek_offset = offset;
2713   }
2714 }
2715
2716 // LCOV_EXCL_START
2717 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
2718                                                                const int size) {
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));
2728   msg_mutex.unlock();
2729   handler_->msg_task_cv_.notify_one();
2730 }
2731
2732 void EsPlayer::TrackRendererEventListener::OnFlushDone() {
2733   LOG_ENTER_P(handler_);
2734   if (!handler_->eventlistener_) return;
2735
2736   auto listener = std::bind(&esplusplayer::EsEventListener::OnFlushDone,
2737                             handler_->eventlistener_, std::placeholders::_1);
2738   auto msg =
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));
2742   msg_mutex.unlock();
2743   handler_->msg_task_cv_.notify_one();
2744   LOG_LEAVE_P(handler_);
2745 }
2746
2747 void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
2748                                                    const EventMsg& msg_data) {
2749   if (!handler_->eventlistener_) return;
2750
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));
2758   msg_mutex.unlock();
2759   handler_->msg_task_cv_.notify_one();
2760   LOG_LEAVE_P(handler_);
2761 }
2762 // LCOV_EXCL_STOP
2763
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));
2773   msg_mutex.unlock();
2774   handler_->msg_task_cv_.notify_one();
2775   LOG_LEAVE_P(handler_);
2776 }
2777
2778 void EsPlayer::TrackRendererEventListener::OnVideoDecoderUnderrun() {
2779   LOG_ENTER_P(handler_);
2780   if (!handler_->eventlistener_) return;
2781
2782   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2783       handler_->state_manager_.GetState() != EsState::kPaused) {
2784     return;
2785   }
2786
2787   auto listener =
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));
2793   msg_mutex.unlock();
2794   handler_->msg_task_cv_.notify_one();
2795   LOG_LEAVE_P(handler_);
2796 }
2797
2798 void EsPlayer::TrackRendererEventListener::OnVideoLatencyStatus(
2799     const LatencyStatus& latency_status) {
2800   LOG_ENTER_P(handler_);
2801   if (!handler_->eventlistener_) return;
2802
2803   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2804       handler_->state_manager_.GetState() != EsState::kPaused) {
2805     return;
2806   }
2807
2808   auto listener = std::bind(
2809       &esplusplayer::EsEventListener::OnVideoLatencyStatus,
2810       handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2811
2812   auto msg = es_msg::PacketLatencyStatus::Make(
2813       latency_status, listener, handler_->eventlistener_userdata_);
2814
2815   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2816   handler_->msg_queue_.push(std::move(msg));
2817   msg_mutex.unlock();
2818   handler_->msg_task_cv_.notify_one();
2819   LOG_LEAVE_P(handler_);
2820 }
2821
2822 void EsPlayer::TrackRendererEventListener::OnAudioLatencyStatus(
2823     const LatencyStatus& latency_status) {
2824   LOG_ENTER_P(handler_);
2825   if (!handler_->eventlistener_) return;
2826
2827   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2828       handler_->state_manager_.GetState() != EsState::kPaused) {
2829     return;
2830   }
2831
2832   auto listener = std::bind(
2833       &esplusplayer::EsEventListener::OnAudioLatencyStatus,
2834       handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2835
2836   auto msg = es_msg::PacketLatencyStatus::Make(
2837       latency_status, listener, handler_->eventlistener_userdata_);
2838
2839   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2840   handler_->msg_queue_.push(std::move(msg));
2841   msg_mutex.unlock();
2842   handler_->msg_task_cv_.notify_one();
2843   LOG_LEAVE_P(handler_);
2844 }
2845
2846 void EsPlayer::TrackRendererEventListener::OnVideoHighLatency() {
2847   LOG_ENTER_P(handler_);
2848   if (!handler_->eventlistener_) return;
2849
2850   auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoHighLatency,
2851                             handler_->eventlistener_, std::placeholders::_1);
2852
2853   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2854
2855   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2856   handler_->msg_queue_.push(std::move(msg));
2857   msg_mutex.unlock();
2858   handler_->msg_task_cv_.notify_one();
2859   LOG_LEAVE_P(handler_);
2860 }
2861
2862 // LCOV_EXCL_START
2863 void EsPlayer::TrackRendererEventListener::OnAudioHighLatency() {
2864   LOG_ENTER_P(handler_);
2865   if (!handler_->eventlistener_) return;
2866
2867   auto listener = std::bind(&esplusplayer::EsEventListener::OnAudioHighLatency,
2868                             handler_->eventlistener_, std::placeholders::_1);
2869
2870   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2871
2872   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2873   handler_->msg_queue_.push(std::move(msg));
2874   msg_mutex.unlock();
2875   handler_->msg_task_cv_.notify_one();
2876   LOG_LEAVE_P(handler_);
2877 }
2878
2879 void EsPlayer::TrackRendererEventListener::OnVideoFrameDropped(
2880     const uint64_t& count) {
2881   if (!handler_->eventlistener_) return;
2882
2883   handler_->eventlistener_->OnVideoFrameDropped(
2884       count, handler_->eventlistener_userdata_);
2885
2886 #if 0
2887
2888   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2889       handler_->state_manager_.GetState() != EsState::kPaused) {
2890     return;
2891   }
2892
2893   auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoFrameDropped,
2894                             handler_->eventlistener_, std::placeholders::_1,
2895                             std::placeholders::_2);
2896
2897   auto msg = es_msg::FrameDroppedCount::Make(
2898       count, listener, handler_->eventlistener_userdata_);
2899
2900   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2901   handler_->msg_queue_.push(std::move(msg));
2902   msg_mutex.unlock();
2903   handler_->msg_task_cv_.notify_one();
2904   LOG_LEAVE_P(handler_);
2905 #endif
2906 }
2907
2908 void EsPlayer::TrackRendererEventListener::OnDecoderInputBufferTime(
2909     const TrackType& type, const DecoderBufferTime& time) {
2910   if (!handler_->eventlistener_) return;
2911
2912   StreamType stream_type = internal::ConvertToStreamType(type);
2913   handler_->eventlistener_->OnDecoderInputBufferTime(stream_type, time);
2914 }
2915
2916 void EsPlayer::TrackRendererEventListener::OnDecoderOutputBufferTime(
2917     const TrackType& type, const DecoderBufferTime& time) {
2918   if (!handler_->eventlistener_) return;
2919
2920   StreamType stream_type = internal::ConvertToStreamType(type);
2921   handler_->eventlistener_->OnDecoderOutputBufferTime(stream_type, time);
2922 }
2923
2924 // LCOV_EXCL_STOP
2925
2926 bool EsPlayer::SetVideoScanType(const PlayerVideoScanType type) {
2927   LOG_ENTER_P(this);
2928   if (state_manager_.GetState() != EsState::kIdle) {
2929     LOG_ERROR_P(this, "Invalid State , current %d",
2930                 state_manager_.GetStateEnum());
2931     return false;
2932   }
2933   if (type == kPlayerVideoScanTypeProgressive) set_video_progressive_ = 1;
2934   return true;
2935 }
2936 bool EsPlayer::SetTimeUnitType(const PlayerTimeUnitType type) {
2937   LOG_ENTER_P(this);
2938   if (state_manager_.GetState() != EsState::kIdle) {
2939     LOG_ERROR_P(this, "Invalid State , current %d",
2940                 state_manager_.GetStateEnum());
2941     return false;
2942   }
2943   LOG_INFO_P(this, "PlayerTimeUnitType [%s]",
2944              (type == kPlayerTimeUnitTypeMs) ? "Ms" : "Us");
2945   time_unit_type = type;
2946   return true;
2947 }
2948
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;
2953     return false;
2954   }
2955   return trackrenderer_->GetDecodingTime(type, time_in_milliseconds);
2956 }
2957
2958 bool EsPlayer::SetVideoStreamRotationInfo(const VideoRotation& rotation) {
2959   LOG_ENTER_P(this);
2960   if (state_manager_.GetState() < EsState::kIdle) {
2961     LOG_ERROR_P(this, "Invalid State , current %d",
2962                 state_manager_.GetStateEnum());
2963     return false;
2964   }
2965   video_rotate_ = rotation;
2966   return trackrenderer_->SetVideoStreamRotationInfo(rotation);
2967 }
2968
2969 bool EsPlayer::GetVideoStreamRotationInfo(VideoRotation* rotation) {
2970   LOG_ENTER_P(this);
2971   if (state_manager_.GetState() < EsState::kIdle) {
2972     LOG_ERROR_P(this, "Invalid State , current %d",
2973                 state_manager_.GetStateEnum());
2974     return false;
2975   }
2976   *rotation = video_rotate_;
2977   return true;
2978 }
2979
2980 bool EsPlayer::SetSimpleMixOutBufferLevel(
2981     const PlayerSimpleMixOutBufferLevel level) {
2982   if (state_manager_.GetState() == EsState::kNone) {
2983     LOG_ERROR_P(this, "Invalid State");
2984     return false;
2985   }
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;
2993   }
2994
2995   return trackrenderer_->SetSimpleMixOutBufferLevel(converted_level);
2996 }
2997
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;
3003   } else {
3004     event_info.is_clean = false;
3005     event_info.key_system = key_system_;
3006   }
3007
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;
3016     }
3017   }
3018   return event_info;
3019 }
3020
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"];
3024 }
3025
3026 namespace es_conf {
3027
3028 void LoadIniProperty(const Json::Value& root) {
3029   // clang-format off
3030   std::vector<std::string> booleanKeys {
3031       "generate_dot",
3032       "force_sw_audio_codec",
3033       "force_sw_video_codec",
3034       "fallback_to_sw_audio_codec",
3035       "fallback_to_sw_video_codec"
3036   };
3037   // clang-format on
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]);
3042   });
3043 }
3044
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 !!");
3054     return false;
3055   }
3056   BOOST_SCOPE_EXIT(&file) { file.close(); }
3057   BOOST_SCOPE_EXIT_END
3058
3059   size = file.tellg();
3060   if (size <= 0) {
3061     LOG_ERROR("Wrong file size");
3062     return false;
3063   }
3064   size += 1;
3065   buf = static_cast<char*>(calloc(size, sizeof(char)));
3066   if (buf == nullptr) {
3067     LOG_ERROR("Fail to calloc buf");
3068     return false;
3069   }
3070   BOOST_SCOPE_EXIT(&buf) {
3071     if (buf) free(buf);
3072   }
3073   BOOST_SCOPE_EXIT_END
3074
3075   file.seekg(0, std::ios::beg);
3076   file.read(buf, size);
3077
3078   std::string config = buf;
3079   Json::Value root;
3080   Json::Reader reader;
3081   if (!reader.parse(config, root)) {
3082     LOG_ERROR("Fail to parse configuration file %s",
3083               (reader.getFormatedErrorMessages()).c_str());
3084     return false;
3085   }
3086
3087   es_conf::LoadIniProperty(root);
3088   return true;
3089 }
3090
3091 }  // namespace es_conf
3092
3093 }  // namespace esplusplayer