Merge branch 'main' into ci/gilbok-lee/update_public
[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 #ifndef TIZEN_FEATURE_PUBLIC
22 #include "core/utils/caf_logger.h"
23 #endif
24 #include "core/utils/performance_checker.h"
25 #include "core/utils/plusplayer_cfg.h"
26 #include "core/utils/plusplayer_log.h"
27 #include "core/videoframetypestrategy.h"
28 #include "esplayer/esplayer_drm.h"
29 #include "json/json.h"
30
31 namespace esplusplayer {
32
33 namespace es_conf {
34
35 // get values from /etc/multimedia/esplusplayer.ini
36 static std::once_flag loaded;
37 static std::map<std::string, bool> ini_property;
38
39 bool LoadIniFile();
40 void LoadIniProperty(const Json::Value& root);
41
42 }  // namespace es_conf
43
44 namespace util {
45
46 std::uint64_t ConvertMsToNs(std::uint64_t ms) {
47   constexpr std::uint64_t ns_unit = 1000000;
48   if (ms * ns_unit > G_MAXUINT64) return G_MAXUINT64;
49   return ms * ns_unit;
50 }
51
52 std::uint64_t ConvertNsToMs(std::uint64_t ns) {
53   constexpr std::uint64_t ms_unit = 1000000;
54   return ns / ms_unit;
55 }
56
57 std::int64_t ConvertMsToNs(std::int64_t ms) {
58   constexpr std::int64_t ns_unit = 1000000;
59   if (ms * ns_unit > G_MAXINT64) return G_MAXINT64;
60   return ms * ns_unit;
61 }
62
63 std::int64_t ConvertNsToMs(std::int64_t ns) {
64   constexpr std::int64_t ms_unit = 1000000;
65   return ns / ms_unit;
66 }
67
68 std::uint64_t ConvertUsToNs(std::uint64_t us) {
69   constexpr std::uint64_t ns_unit = 1000;
70   if (us * ns_unit > G_MAXUINT64) return G_MAXUINT64;
71   return us * ns_unit;
72 }
73
74 std::uint64_t ConvertNsToUs(std::uint64_t ns) {
75   constexpr std::uint64_t us_unit = 1000;
76   return ns / us_unit;
77 }
78
79 std::int64_t ConvertUsToNs(std::int64_t us) {
80   constexpr std::int64_t ns_unit = 1000;
81   if (us * ns_unit > G_MAXINT64) return G_MAXINT64;
82   return us * ns_unit;
83 }
84
85 std::int64_t ConvertNsToUs(std::int64_t ns) {
86   constexpr std::int64_t us_unit = 1000;
87   return ns / us_unit;
88 }
89
90 // LCOV_EXCL_START
91 std::string GetStringFromMatroskaColor(const MatroskaColor& color_info) {
92   std::ostringstream oss;
93   oss << "matrixCoefficients:" << color_info.matrix_coefficients
94       << " bitsPerChannel:" << color_info.bits_per_channel
95       << " chromaSubsamplingHorz:" << color_info.chroma_subsampling_horizontal
96       << " chromaSubsamplingVert:" << color_info.chroma_subsampling_vertical
97       << " cbSubsamplingHorz:" << color_info.cb_subsampling_horizontal
98       << " cbSubsamplingVert:" << color_info.cb_subsampling_vertical
99       << " chromaSitingHorz:" << color_info.chroma_siting_horizontal
100       << " chromaSitingVert:" << color_info.chroma_siting_vertical
101       << " range:" << color_info.range
102       << " transferCharacteristics:" << color_info.transfer_characteristics
103       << " primaries:" << color_info.primaries
104       << " maxCLL:" << color_info.max_cll << " maxFALL:" << color_info.max_fall
105       << " RX:" << color_info.metadata.primary_r_chromaticity_x
106       << " RY:" << color_info.metadata.primary_r_chromaticity_y
107       << " GX:" << color_info.metadata.primary_g_chromaticity_x
108       << " GY:" << color_info.metadata.primary_g_chromaticity_y
109       << " BX:" << color_info.metadata.primary_b_chromaticity_x
110       << " BY:" << color_info.metadata.primary_b_chromaticity_y
111       << " wX:" << color_info.metadata.white_point_chromaticity_x
112       << " wY:" << color_info.metadata.white_point_chromaticity_y
113       << " luminanceMax:" << color_info.metadata.luminance_max
114       << " luminanceMin:" << color_info.metadata.luminance_min
115       << " isHDR10p:" << color_info.is_hdr_10p;
116   return oss.str();
117 }
118 // LCOV_EXCL_STOP
119
120 }  // namespace util
121
122 namespace internal {
123 // const std::uint64_t kMaxByteOfVideoSrcQueue = 70 * 1024 * 1024;  // 70 MB
124 // const std::uint64_t kMaxByteOfAudioSrcQueue = 10 * 1024 * 1024;  // 10 MB
125 // const std::uint64_t kMaxTimeOfVideoSrcQueue = 10000000000;       // 10 s
126 // const std::uint64_t kMaxTimeOfAudioSrcQueue = 10000000000;       // 10 s
127
128 constexpr uint32_t kNdecodingMode = 0x04;
129
130 enum VolumeLevel { kVolumeMin = 0, kVolumeMax = 100 };
131 constexpr int kMaxFhdWidth = 1920;
132 constexpr int kMaxFhdHeight = 1080;
133
134 inline bool IsPcmMimeType(const std::string& mimetype) {
135   return (mimetype.find("audio/x-raw") != std::string::npos);
136 }
137 inline bool IsForcedUnsetTz(const Track& track, const std::string& id) {
138   if ((track.type == kTrackTypeAudio) && strstr(id.c_str(), "netflix")) {
139     return true;
140   }
141   return false;
142 }
143 inline bool IsAacCodec(const Track& track) {
144   return (track.mimetype.find("audio/mpeg") != std::string::npos &&
145           track.version == 2);
146 }
147 inline bool IsEac3Codec(const std::string& mimetype) {
148   return mimetype.find("audio/x-eac3") != std::string::npos;
149 }
150 inline bool IsAc3Codec(const std::string& mimetype) {
151   return mimetype.find("audio/x-ac3") != std::string::npos;
152 }
153
154 inline bool IsFlacCodec(const std::string& mimetype) {
155   return mimetype.find("audio/x-ffmpeg-parsed-flac") != std::string::npos;
156 }
157
158 inline bool IsAvailableCodecSwitch(const Track& track) {
159   if (internal::IsAacCodec(track) || internal::IsAc3Codec(track.mimetype) ||
160       internal::IsEac3Codec(track.mimetype))
161     return true;
162   return false;
163 }
164
165 int ResetEosStatus(const TrackType& type, int eos_status) {
166   if (type == kTrackTypeVideo)
167     eos_status &= ~EosStatus::kVideoEos;
168   else if (type == kTrackTypeAudio)
169     eos_status &= ~EosStatus::kAudioEos;
170   return eos_status;
171 }
172
173 // LCOV_EXCL_START
174 void MakeTrustZoneTracks(std::vector<Track>& tracks,
175                          const std::string& app_id) {
176   for (auto& track : tracks) {
177     const bool is_already_tz_type =
178         (track.mimetype.find("_tz", track.mimetype.length() - 3) !=
179          std::string::npos);
180     if (is_already_tz_type) {
181       continue;
182     }
183     track.streamtype = track.mimetype;
184     bool is_flac = internal::IsFlacCodec(track.mimetype);
185     if ((track.use_swdecoder && !is_flac) || IsPcmMimeType(track.mimetype) ||
186         IsForcedUnsetTz(track, app_id))
187       continue;
188     else
189       track.mimetype = track.mimetype + "_tz";
190   }
191 }
192 // LCOV_EXCL_STOP
193
194 void UpdateCodecTypeTracks(std::vector<Track>& tracks,
195                            const PlayerAudioCodecType& audio_codec_type,
196                            const PlayerVideoCodecType& video_codec_type,
197                            bool force_audio_swdecoder_use,
198                            bool force_video_swdecoder_use) {
199   for (auto& track : tracks) {
200     switch (track.type) {
201       case kTrackTypeAudio: {
202         if (audio_codec_type == kPlayerAudioCodecTypeSW ||
203             force_audio_swdecoder_use)
204           track.use_swdecoder = true;
205         else
206           track.use_swdecoder = false;
207         break;
208       }
209       case kTrackTypeVideo: {
210         if (video_codec_type == kPlayerVideoCodecTypeSW ||
211             force_video_swdecoder_use)
212           track.use_swdecoder = true;
213         else
214           track.use_swdecoder = false;
215         break;
216       }
217       default:
218         break;
219     }
220   }
221 }
222 inline bool IsSupportedDrmType(const drm::Type& drm_type) {
223   static const std::map<drm::Type, bool> kSupportedDrmType = {
224       {drm::Type::kPlayready, true},
225   };
226   if (kSupportedDrmType.count(drm_type) == 0) return false;
227   return kSupportedDrmType.at(drm_type);
228 }
229 inline void ResetDrmProperty(drm::Property& drm_property) {
230   drm_property = drm::Property();
231 }
232 inline StreamType ConvertToStreamType(TrackType type) {
233   return (type == kTrackTypeAudio) ? StreamType::kAudio : StreamType::kVideo;
234 }
235 struct AppsrcQueueSizeOption {
236   std::uint64_t current_size = 0;
237   std::uint64_t max_size = 0;
238   std::uint32_t threshold = 0;
239 };
240 inline bool IsUnderRun(AppsrcQueueSizeOption& byte_based,
241                        AppsrcQueueSizeOption& time_based) {
242   bool need_data_by_byte = false, need_data_by_time = false;
243   need_data_by_byte = (byte_based.max_size > 0) &&
244                       (byte_based.current_size * 100 / byte_based.max_size <=
245                        byte_based.threshold);
246   need_data_by_time = (time_based.max_size > 0) &&
247                       (time_based.current_size * 100 / time_based.max_size <=
248                        time_based.threshold);
249   if (need_data_by_byte || need_data_by_time)
250     return true;
251   else
252     return false;
253 }
254 inline bool IsLowLatencyModeDisableAVSync(std::uint32_t mode) {
255   constexpr std::uint32_t kAVSync = kLowLatencyModeDisableAVSync;
256   return (mode & kAVSync) ? true : false;
257 }
258 inline bool IsLowLatencyModeDisablePreroll(std::uint32_t mode) {
259   constexpr std::uint32_t kPreroll = kLowLatencyModeDisablePreroll;
260   return (mode & kPreroll) ? true : false;
261 }
262 inline bool IsLowLatencyMode(std::uint32_t mode) {
263   return (mode != static_cast<std::uint32_t>(kLowLatencyModeNone)) ? true
264                                                                    : false;
265 }
266 inline bool IsSupportedTsOffset(std::uint32_t mode) {
267   return IsLowLatencyMode(mode) && !IsLowLatencyModeDisableAVSync(mode) ? true
268                                                                         : false;
269 }
270
271 inline bool IsLowLatencyModeEnableGameMode(std::uint32_t mode) {
272   constexpr std::uint32_t kGameMode = kLowLatencyModeEnableGameMode ^
273                                       kLowLatencyModeAudio ^
274                                       kLowLatencyModeVideo;
275   return (mode & kGameMode) ? true : false;
276 }
277
278 inline bool IsLowLatencyModeForCatchUp(std::uint32_t mode) {
279   return IsLowLatencyModeDisableAVSync(mode) &&
280                  IsLowLatencyModeEnableGameMode(mode)
281              ? true
282              : false;
283 }
284
285 inline bool IsExclusiveLowLatencyMode(std::uint32_t current_mode,
286                                       std::uint32_t set_mode) {
287   std::uint32_t exclusive_mode = 0;
288   exclusive_mode |= static_cast<std::uint32_t>(kLowLatencyModeEnableGameMode);
289   exclusive_mode |=
290       static_cast<std::uint32_t>(kLowLatencyModeDisableVideoQuality);
291
292   std::uint32_t new_mode = current_mode | set_mode;
293   return (exclusive_mode == (new_mode & exclusive_mode)) ? true : false;
294 }
295 }  // namespace internal
296
297 EsPlayer::EsPlayer() {
298   std::call_once(es_conf::loaded, [this]() { es_conf::LoadIniFile(); });
299 #ifndef TIZEN_FEATURE_PUBLIC
300   if (CafLogger::Initialize() != true) {
301     LOG_INFO("CAF Dbus not connect.");
302   }
303 #endif
304   InitValuesFromIni_();
305 }
306
307 EsPlayer::~EsPlayer() {
308   LOG_ENTER_P(this);
309   Close();
310   LOG_LEAVE_P(this);
311 }
312
313 bool EsPlayer::Open() {
314   LOG_INFO_P(this, "state manager > %p", &state_manager_);
315   Init_();
316   state_manager_.Start();
317   auto op = [this]() noexcept -> bool {
318     const auto start = performance_checker::Start();
319     if (trackrenderer_) {
320       assert(0 && "trackrenderer already exist");
321     }
322     msg_handler_task_ =
323         std::async(std::launch::async, &EsPlayer::MsgTask_, this);
324     trackrenderer_ = TrackRendererAdapter::Create();
325     assert(trackrenderer_);
326
327     trackrenderer_->RegisterListenerForEsplayer(
328         trackrenderer_event_listener_.get());
329     performance_checker::End(start, "Open");
330     return true;
331   };
332
333 #ifndef TIZEN_FEATURE_PUBLIC
334   CafLogger::SetUniqueNumber();
335   caf_unique_number = CafLogger::GetUniqueNumber();
336   CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
337 #endif
338
339   es_event::Open event{op};
340   return state_manager_.ProcessEvent(event);
341 }
342
343 bool EsPlayer::Close() {
344   LOG_ENTER_P(this);
345   std::lock_guard<std::mutex> lk(submit_mutex_);
346   if (state_manager_.GetState() >= EsState::kIdle) {
347     Stop();
348   }
349   auto op = [this]() noexcept {
350     if (is_msg_task_stop_ == false) {
351       {
352         std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
353         is_msg_task_stop_ = true;
354       }
355       msg_task_cv_.notify_one();
356       if (msg_handler_task_.valid()) msg_handler_task_.wait();
357     }
358
359     if (trackrenderer_) trackrenderer_.reset();
360     ResetContextForClose_();
361     LOG_LEAVE_P(this);
362     return true;
363   };
364   es_event::Close event{op};
365   state_manager_.ProcessEvent(event);
366   state_manager_.Stop();
367   return true;
368 }
369
370 bool EsPlayer::Deactivate(const StreamType type) {
371   LOG_ENTER_P(this);
372   if (state_manager_.GetState() < EsState::kReady) {
373     LOG_ERROR_P(this, "Invalid State , current %d",
374                 state_manager_.GetStateEnum());
375     return false;
376   }
377 #ifdef USE_MIXER
378   if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
379     LOG_ERROR_P(
380         this, "can't deactivate audio stream, mixer will control audio stream");
381     return false;
382   }
383 #endif  // USE_MIXER
384   if (!trackrenderer_->Deactivate(static_cast<TrackType>(type))) {
385     return false;
386   }
387   {
388     std::lock_guard<std::mutex> lock(eos_mutex_);
389     switch (type) {
390       case StreamType::kAudio:
391         eos_status_ |= EosStatus::kAudioEos;
392         break;
393       case StreamType::kVideo:
394         eos_status_ |= EosStatus::kVideoEos;
395         break;
396       default:
397         break;
398     }
399   }
400   for (auto& track : track_) {
401     if (track.type == static_cast<TrackType>(type)) {
402       track.active = false;
403     }
404   }
405   return true;
406 }
407
408 bool EsPlayer::Activate(const StreamType type) {
409   LOG_ENTER_P(this);
410   if (state_manager_.GetState() < EsState::kReady) {
411     LOG_ERROR_P(this, "Invalid State , current %d",
412                 state_manager_.GetStateEnum());
413     return false;
414   }
415 #ifdef USE_MIXER
416   if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
417     LOG_ERROR_P(this,
418                 "can't activate audio stream, mixer will control audio stream");
419     return false;
420   }
421 #endif  // USE_MIXER
422   if (!track_.empty()) {
423     auto has_track = [type](const Track& item) -> bool {
424       return item.type == static_cast<TrackType>(type);
425     };
426     auto target = std::find_if(track_.begin(), track_.end(), has_track);
427     if (target == track_.end()) {
428       LOG_ERROR_P(this, "there is no track to activate");
429       return false;
430     }
431     if (target->active != false) {
432       LOG_ERROR_P(this, "The track should be deactivated in advance.");
433       return false;
434     }
435     target->active = true;
436     internal::UpdateCodecTypeTracks(
437         track_, audio_codec_type_, video_codec_type_,
438         force_audio_swdecoder_use_, force_video_swdecoder_use_);
439     if (drm_property_.external_decryption) {
440       internal::MakeTrustZoneTracks(track_, app_info_.id);
441     }
442     SetTrackRendererAttributes_();
443     if (type == StreamType::kVideo) {
444 #ifdef USE_MIXER
445       if (mixer_ticket_)
446         trackrenderer_->SetVideoFrameBufferType(
447             VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
448       else
449 #endif  // USE_MIXER
450         trackrenderer_->SetVideoFrameBufferType(VideoFrameTypeStrategyPtr(
451             new DefaultVideoFrameTypeStrategy(vidoe_frame_buffer_type_)));
452     }
453     if (!trackrenderer_->Activate(target->type, *target)) {
454       target->active = false;
455       return false;
456     }
457     eos_status_ =
458         internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
459     return true;
460   }
461   return false;
462 }
463
464 bool EsPlayer::DeactivateAudio() {
465   LOG_ENTER_P(this);
466   if (state_manager_.GetState() < EsState::kIdle) {
467     LOG_ERROR_P(this, "Invalid State , current %d",
468                 state_manager_.GetStateEnum());
469     return false;
470   }
471 #ifdef USE_MIXER
472   if (!enable_audio_pipeline_handle_) {
473     LOG_ERROR_P(
474         this, "can't deactivate audio stream, mixer will control audio stream");
475     return false;
476   }
477 #endif  // USE_MIXER
478   if (!trackrenderer_->DeactivateAudio()) {
479     return false;
480   }
481   is_audio_stream_info_frozen_ = true;
482   return true;
483 }
484
485 bool EsPlayer::ActivateAudio() {
486   LOG_ENTER_P(this);
487   const StreamType type = StreamType::kAudio;
488   if (state_manager_.GetState() < EsState::kReady) {
489     LOG_ERROR_P(this, "Invalid State , current %d",
490                 state_manager_.GetStateEnum());
491     return false;
492   }
493 #ifdef USE_MIXER
494   if (!enable_audio_pipeline_handle_) {
495     LOG_ERROR_P(this,
496                 "can't activate audio stream, mixer will control audio stream");
497     return false;
498   }
499 #endif  // USE_MIXER
500   if (track_.empty()) {
501     return false;
502   }
503   if (!trackrenderer_->ActivateAudio()) {
504     return false;
505   }
506   eos_status_ =
507       internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
508   return true;
509 }
510
511 bool EsPlayer::Start() {
512   LOG_ENTER_P(this);
513   if (is_stopped_) {
514     LOG_ERROR_P(this, "Stop already, no need to Start,leave...");
515     return false;
516   }
517   auto op = [this]() noexcept {
518     if (!trackrenderer_->Start()) {
519       return false;
520     }
521     return true;
522   };
523
524 #ifndef TIZEN_FEATURE_PUBLIC
525   CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
526 #endif
527
528   es_event::Start event{op};
529   return state_manager_.ProcessEvent(event);
530 }
531
532 bool EsPlayer::Stop() {
533   LOG_ENTER_P(this);
534   is_stopped_ = true;
535   auto stop = [this]() noexcept -> bool {
536     const auto start = performance_checker::Start();
537     if (trackrenderer_) trackrenderer_->Stop();
538     ResetContextForStop_();
539 #ifdef USE_MIXER
540     if (mixer_ticket_) mixer_ticket_.reset();
541 #endif  // USE_MIXER
542     performance_checker::End(start, "Stop");
543     return true;
544   };
545   for (const auto& track : track_) {
546     es_packet_logger_.PrintStoredPacketInfo(
547         internal::ConvertToStreamType(track.type), true);
548   }
549   es_event::Stop event{stop};
550   bool res = state_manager_.ProcessEventStop(event);
551
552   if (preparetask_.valid()) {
553     LOG_INFO_P(this, "Stopped , Wait Prepare() finish...");
554     preparetask_.wait();
555     LOG_INFO_P(this, "Wait , Wait Prepare() Done...");
556   }
557
558 #ifndef TIZEN_FEATURE_PUBLIC
559   CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
560   CafLogger::StopLoggingThread();
561 #endif
562
563   return res;
564 }
565
566 void EsPlayer::SetTrackRendererAttributes_() {
567   if (trackrenderer_ == nullptr) return;
568   trackrenderer_->SetAttribute(
569       TrackRendererAdapter::Attribute::kVideoQueueMaxByte,
570       src_queue_size_.kMaxByteOfVideoSrcQueue);
571   trackrenderer_->SetAttribute(
572       TrackRendererAdapter::Attribute::kAudioQueueMaxByte,
573       src_queue_size_.kMaxByteOfAudioSrcQueue);
574   trackrenderer_->SetAttribute(
575       TrackRendererAdapter::Attribute::kVideoMinByteThreshold,
576       src_queue_size_.kMinByteThresholdOfVideoSrcQueue);
577   trackrenderer_->SetAttribute(
578       TrackRendererAdapter::Attribute::kAudioMinByteThreshold,
579       src_queue_size_.kMinByteThresholdOfAudioSrcQueue);
580   trackrenderer_->SetAttribute(
581       TrackRendererAdapter::Attribute::kVideoQueueMaxTime,
582       util::ConvertMsToNs(src_queue_size_.kMaxTimeOfVideoSrcQueue));
583   trackrenderer_->SetAttribute(
584       TrackRendererAdapter::Attribute::kAudioQueueMaxTime,
585       util::ConvertMsToNs(src_queue_size_.kMaxTimeOfAudioSrcQueue));
586   trackrenderer_->SetAttribute(
587       TrackRendererAdapter::Attribute::kVideoMinTimeThreshold,
588       src_queue_size_.kMinTimeThresholdOfVideoSrcQueue);
589   trackrenderer_->SetAttribute(
590       TrackRendererAdapter::Attribute::kAudioMinTimeThreshold,
591       src_queue_size_.kMinTimeThresholdOfAudioSrcQueue);
592   trackrenderer_->SetAttribute(
593       TrackRendererAdapter::Attribute::kUnlimitedMaxBufferMode,
594       unlimited_max_buffer_mode_);
595   trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kLowLatencyMode,
596                                low_latency_mode_);
597   trackrenderer_->SetAttribute(
598       TrackRendererAdapter::Attribute::kVideoFramePeekMode,
599       video_frame_peek_mode_);
600   trackrenderer_->SetAttribute(
601       TrackRendererAdapter::Attribute::kAccurateSeekMode, accurate_seek_mode_);
602   trackrenderer_->SetAttribute(
603       TrackRendererAdapter::Attribute::kVideoPreDisplayMode,
604       video_pre_display_mode_);
605   if (resume_time_.is_set) {
606     trackrenderer_->SetAttribute(
607         TrackRendererAdapter::Attribute::kStartRenderingTime,
608         resume_time_.time);
609     resume_time_.is_set = false;
610   }
611   trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
612                                fmm_mode_);
613   trackrenderer_->SetAttribute(
614       TrackRendererAdapter::Attribute::kAlternativeVideoResource,
615       alternative_video_resource_);
616   trackrenderer_->SetAttribute(
617       TrackRendererAdapter::Attribute::kVideoDecodingMode,
618       video_decoding_mode_);
619   trackrenderer_->SetAttribute(
620       TrackRendererAdapter::Attribute::kVideoProgressiveMode,
621       set_video_progressive_);
622   trackrenderer_->SetAttribute(
623       TrackRendererAdapter::Attribute::kPlayerTimeUnitType,
624       static_cast<std::uint32_t>(time_unit_type));
625 }
626
627 // LCOV_EXCL_START
628 #ifdef USE_MIXER
629 bool EsPlayer::PrepareVideoMixingMode_(std::vector<Track>* tracks) {
630   LOG_ENTER_P(this);
631   mixer_ticket_->Prepare();
632   if (enable_rsc_alloc_handle_) return true;
633   ResourceType type = ResourceType::kHwMain;
634   if (!mixer_ticket_->GetAvailableResourceType(ResourceCategory::kVideoDecoder,
635                                                &type)) {
636     LOG_ERROR_P(this, "no available resource");
637     return false;
638   }
639   if (!mixer_ticket_->Alloc(ResourceCategory::kVideoDecoder, type)) {
640     LOG_ERROR_P(this, "fail to alloc resource [%d]", static_cast<int>(type));
641     return false;
642   }
643
644   if (type == ResourceType::kHwSub) {
645     alternative_video_resource_ = 1;
646   } else if (type == ResourceType::kSw) {
647     for (auto it = tracks->begin(); it != tracks->end(); ++it) {
648       if (it->type == kTrackTypeVideo) {
649         it->use_swdecoder = true;
650         break;
651       }
652     }
653   } else if (type == ResourceType::kNdecoder) {
654     video_decoding_mode_ = internal::kNdecodingMode;
655   }
656   return true;
657 }
658 #endif  // USE_MIXER
659 // LCOV_EXCL_START
660
661 bool EsPlayer::Prepare_() {
662   LOG_ENTER_P(this);
663   if (is_stopped_) {
664     LOG_ERROR_P(this, "Stop already, no need to prepare,leave...");
665     return false;
666   }
667   auto op = [this]() noexcept -> bool {
668     const auto start = performance_checker::Start();
669
670     internal::UpdateCodecTypeTracks(
671         track_, audio_codec_type_, video_codec_type_,
672         force_audio_swdecoder_use_, force_video_swdecoder_use_);
673     if (drm_property_.external_decryption) {
674       internal::MakeTrustZoneTracks(track_, app_info_.id);
675     }
676     std::vector<Track> active_track;
677     if (!track_util::GetActiveTrackList(track_, active_track)) {
678       return false;
679     }
680     trackrenderer_->SetIniProperty(es_conf::ini_property);
681 #ifdef USE_MIXER
682     if (mixer_ticket_) {
683       trackrenderer_->SetVideoFrameBufferType(
684           VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
685       if (!PrepareVideoMixingMode_(&active_track)) {
686         LOG_ERROR_P(this, "fail to prepare mixing mode");
687         return false;
688       }
689     }
690     std::unique_lock<std::mutex> lock(audio_focus_m_);
691     if (!enable_audio_pipeline_handle_ && !is_audio_focused_) {
692       for (auto it = active_track.begin(); it != active_track.end(); ++it) {
693         if (it->type == kTrackTypeAudio) {
694           active_track.erase(it);
695           LOG_INFO_P(this, "erase audio track is_audio_focused_ [%d]",
696                      is_audio_focused_);
697           break;
698         }
699       }
700     }
701 #endif  // USE_MIXER
702     for (const auto& track : active_track) {
703       switch (track.type) {
704         case kTrackTypeAudio: {
705           std::lock_guard<std::mutex> lock2(eos_mutex_);
706           eos_status_ = internal::ResetEosStatus(kTrackTypeAudio, eos_status_);
707           need_data_[track.type].mask |= kNeedDataMaskByPrepare;
708           break;
709         }
710         case kTrackTypeVideo: {
711           std::lock_guard<std::mutex> lock2(eos_mutex_);
712           eos_status_ = internal::ResetEosStatus(kTrackTypeVideo, eos_status_);
713           need_data_[track.type].mask |= kNeedDataMaskByPrepare;
714           break;
715         }
716         default:
717           break;
718       }
719     }
720     SetTrackRendererAttributes_();
721     trackrenderer_->SetTrack(active_track);
722     if (!trackrenderer_->Prepare()) {
723       return false;
724     }
725     performance_checker::End(start, "Prepare");
726     return true;
727   };
728
729 #ifndef TIZEN_FEATURE_PUBLIC
730   CafLogger::StartLoggingThread();
731   CafLogger::LogMessage(CafEventType::kReady, caf_unique_number);
732 #endif
733
734   es_event::Prepare event{op};
735   if (!state_manager_.ProcessEvent(event)) {
736     return false;
737   }
738   LOG_LEAVE_P(this);
739   return true;
740 }
741
742 void EsPlayer::PrepareTask_() {
743   bool ret = Prepare_();
744
745   state_manager_.SetPreparingState(false);
746   if (eventlistener_) {
747     LOG_INFO_P(this, "Prepare completely, call OnPrepareDone(%d)", ret);
748     eventlistener_->OnPrepareDone(ret, eventlistener_userdata_);
749     LOG_INFO_P(this, "call OnPrepareDone End");
750   }
751
752 #ifndef TIZEN_FEATURE_PUBLIC
753   kpi::CodecLogger logger;
754   kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
755   logger.SendKpi(ret, event_keys);
756 #endif
757   LOG_LEAVE_P(this);
758 }
759
760 bool EsPlayer::PrepareAsync() {
761   LOG_ENTER_P(this);
762   state_manager_.SetPreparingState(true);
763   preparetask_ = std::async(std::launch::async, &EsPlayer::PrepareTask_, this);
764   if (!preparetask_.valid()) {
765     state_manager_.SetPreparingState(false);
766     return false;
767   }
768   return true;
769 }
770
771 bool EsPlayer::Pause() {
772   LOG_ENTER_P(this);
773   if (is_stopped_) {
774     LOG_ERROR_P(this, "Stop already, no need to pause,leave...");
775     return false;
776   }
777   if (state_manager_.GetState() < EsState::kReady) {
778     LOG_ERROR_P(this, "Invalid State , current %d",
779                 state_manager_.GetStateEnum());
780     return false;
781   }
782   auto op = [this]() noexcept -> bool {
783     if (!trackrenderer_) return false;
784     if (!trackrenderer_->Pause()) {
785       return false;
786     }
787     return true;
788   };
789   for (const auto& track : track_) {
790     es_packet_logger_.PrintStoredPacketInfo(
791         internal::ConvertToStreamType(track.type), true);
792   }
793
794 #ifndef TIZEN_FEATURE_PUBLIC
795   CafLogger::LogMessage(CafEventType::kPaused, caf_unique_number);
796 #endif
797
798   es_event::Pause event{op};
799   return state_manager_.ProcessEvent(event);
800 }
801
802 bool EsPlayer::Resume() {
803   LOG_ENTER_P(this);
804   if (is_stopped_) {
805     LOG_ERROR_P(this, "Stop already, no need to Resume,leave...");
806     return false;
807   }
808   if (state_manager_.GetState() <= EsState::kReady) {
809     LOG_ERROR_P(this, "Invalid State , current %d",
810                 state_manager_.GetStateEnum());
811     return false;
812   }
813   if (is_resource_conflicted_) {
814     LOG_ERROR_P(this, "Resuem fail resource conflicted");
815     return false;
816   }
817   auto op = [this]() noexcept -> bool {
818     if (!trackrenderer_) return false;
819     if (!trackrenderer_->Resume()) {
820       return false;
821     }
822     return true;
823   };
824   for (const auto& track : track_) {
825     es_packet_logger_.PrintStoredPacketInfo(
826         internal::ConvertToStreamType(track.type), true);
827   }
828
829 #ifndef TIZEN_FEATURE_PUBLIC
830   CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
831 #endif
832
833   es_event::Resume event{op};
834   return state_manager_.ProcessEvent(event);
835 }
836
837 bool EsPlayer::Seek(const uint64_t time) {
838   if (state_manager_.GetState() < EsState::kIdle) {
839     LOG_ERROR_P(this, "Invalid State , current %d",
840                 state_manager_.GetStateEnum());
841     return false;
842   }
843   if (state_manager_.GetState() == EsState::kIdle) {
844     if (state_manager_.GetPreparingState()) {
845       LOG_ERROR_P(this, "Invalid State , during preparing");
846       return false;
847     }
848     LOG_ERROR("%p resume time [%" PRId64 " ]", this, time);
849     resume_time_.is_set = true;
850     resume_time_.time = time;
851     return true;
852   }
853   is_seek_done_need_drop = true;
854   if (time_unit_type == kPlayerTimeUnitTypeMs)
855     LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " ms]", this, time);
856   else if (time_unit_type == kPlayerTimeUnitTypeUs)
857     LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " us]", this, time);
858   for (const auto& track : track_) {
859     eos_status_ = internal::ResetEosStatus(track.type, eos_status_);
860     es_packet_logger_.PrintStoredPacketInfo(
861         internal::ConvertToStreamType(track.type), true);
862   }
863   auto op = [this, time]() -> bool {
864     if (!trackrenderer_->Seek(time, current_playback_rate_,
865                               current_audio_mute_)) {
866       return false;
867     }
868     return true;
869   };
870   es_event::Seek event{op};
871   bool ret = state_manager_.ProcessEvent(event);
872   is_seek_done_need_drop = false;
873
874   if (eventlistener_) {
875     if (internal::IsLowLatencyModeDisableAVSync(low_latency_mode_) ||
876         internal::IsLowLatencyModeDisablePreroll(low_latency_mode_)) {
877       auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
878                                 eventlistener_, std::placeholders::_1);
879       auto msg = es_msg::Simple::Make(listener, eventlistener_userdata_);
880       std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
881       msg_queue_.push(std::move(msg));
882       msg_mutex.unlock();
883       msg_task_cv_.notify_one();
884     }
885   }
886   LOG_DEBUG("%p, [LEAVE] seek end ", this);
887   return ret;
888 }
889
890 void EsPlayer::SetAppInfo(const PlayerAppInfo& app_info) {
891   LOG_ENTER_P(this);
892   if (state_manager_.GetState() != EsState::kIdle) {
893     LOG_ERROR_P(this, "Invalid State , current %d",
894                 state_manager_.GetStateEnum());
895     return;
896   }
897   app_info_ = app_info;
898   trackrenderer_->SetAppInfo(app_info);
899   LOG_INFO("Appid [%s]", app_info.id.c_str());
900 #ifndef TIZEN_FEATURE_PUBLIC
901   CafLogger::SetAppId(app_info.id);
902 #endif
903 }
904
905 void EsPlayer::SetAppInfoEx(const PlayerAppInfoEx& app_info) {
906   LOG_ENTER_P(this);
907   if (state_manager_.GetState() != EsState::kIdle) {
908     LOG_ERROR_P(this, "Invalid State , current %d",
909                 state_manager_.GetStateEnum());
910     return;
911   }
912   app_info_.id = app_info.id;
913   app_info_.version = app_info.version;
914   app_info_.type = app_info.type;
915   trackrenderer_->SetAppInfoEx(app_info);
916   LOG_INFO("Appid [%s]", app_info_.id.c_str());
917 #ifndef TIZEN_FEATURE_PUBLIC
918   CafLogger::SetAppId(app_info_.id);
919 #endif
920 }
921
922 bool EsPlayer::SetPlaybackRate(const double rate, const bool audio_mute) {
923   LOG_ENTER_P(this);
924
925   if (rate <= 0 || rate > 2.0) {
926     LOG_ERROR_P(this, "Not a valid PlaybackRate");
927     return false;
928   }
929
930   if (state_manager_.GetState() < EsState::kReady) {
931     LOG_ERROR_P(this, "Invalid State , current %d",
932                 state_manager_.GetStateEnum());
933     return false;
934   }
935
936   auto op = [this, rate, audio_mute]() -> bool {
937     if (!trackrenderer_->SetPlaybackRate(rate, audio_mute)) {
938       return false;
939     }
940     current_playback_rate_ = rate;
941     current_audio_mute_ = audio_mute;
942     return true;
943   };
944   es_event::PlaybackRate event{op};
945   return state_manager_.ProcessEvent(event);
946
947   LOG_LEAVE_P(this);
948   return true;
949 }
950
951 bool EsPlayer::SetDisplay(const DisplayType& type, void* obj) {
952   if (state_manager_.GetState() != EsState::kIdle) {
953     LOG_ERROR_P(this, "Invalid State , current %d",
954                 state_manager_.GetStateEnum());
955     return false;
956   }
957 #ifdef USE_MIXER
958   if (mixer_ticket_) mixer_ticket_.reset();
959 #endif  // USE_MIXER
960   return trackrenderer_->SetDisplay(type, obj);
961 }
962
963 // LCOV_EXCL_START
964 #ifdef USE_MIXER
965 bool EsPlayer::SetDisplay(const DisplayType& type, MixerTicket* handle) {
966   if (type == DisplayType::kMixer) {
967     LOG_INFO_P(this, "Create MixerTicket");
968     mixer_ticket_.reset(handle);
969     mixer_ticket_->RegisterListener(mixer_event_listener_.get());
970     if (mixer_ticket_->IsAudioFocusHandler())
971       enable_audio_pipeline_handle_ = false;
972     if (mixer_ticket_->IsRscAllocHandler()) enable_rsc_alloc_handle_ = false;
973     trackrenderer_->SetDisplay(DisplayType::kNone, nullptr);
974   }
975   return true;
976 }
977 #endif  // USE_MIXER
978
979 bool EsPlayer::SetDisplay(const DisplayType& type, void* ecore_wl2_window,
980                           const int x, const int y, const int w, const int h) {
981   if (state_manager_.GetState() != EsState::kIdle) {
982     LOG_ERROR_P(this, "Invalid State , current %d",
983                 state_manager_.GetStateEnum());
984     return false;
985   }
986 #ifdef USE_MIXER
987   if (mixer_ticket_) mixer_ticket_.reset();
988 #endif  // USE_MIXER
989   return trackrenderer_->SetDisplay(type, ecore_wl2_window, x, y, w, h);
990 }
991
992 bool EsPlayer::SetDisplaySubsurface(const DisplayType& type,
993                                     void* ecore_wl2_subsurface, const int x,
994                                     const int y, const int w, const int h) {
995   if (state_manager_.GetState() != EsState::kIdle) {
996     LOG_ERROR_P(this, "Invalid State , current %d",
997                 state_manager_.GetStateEnum());
998     return false;
999   }
1000 #ifdef USE_MIXER
1001   if (mixer_ticket_) mixer_ticket_.reset();
1002 #endif  // USE_MIXER
1003   return trackrenderer_->SetDisplaySubsurface(type, ecore_wl2_subsurface, x, y,
1004                                               w, h);
1005 }
1006
1007 bool EsPlayer::SetDisplay(const DisplayType& type, unsigned int surface_id,
1008                           const int x, const int y, const int w, const int h) {
1009   if (state_manager_.GetState() != EsState::kIdle) {
1010     LOG_ERROR_P(this, "Invalid State , current %d",
1011                 state_manager_.GetStateEnum());
1012     return false;
1013   }
1014 #ifdef USE_MIXER
1015   if (mixer_ticket_) mixer_ticket_.reset();
1016 #endif  // USE_MIXER
1017   return trackrenderer_->SetDisplay(type, surface_id, x, y, w, h);
1018 }
1019 // LCOV_EXCL_START
1020
1021 bool EsPlayer::SetDisplayMode(const DisplayMode& mode) {
1022   if (state_manager_.GetState() < EsState::kIdle) {
1023     LOG_ERROR_P(this, "Invalid State , current %d",
1024                 state_manager_.GetStateEnum());
1025     return false;
1026   }
1027   trackrenderer_->SetDisplayMode(mode);
1028   return true;
1029 }
1030
1031 bool EsPlayer::SetStretchMode(const int& mode) {
1032   if (state_manager_.GetState() < EsState::kIdle) {
1033     LOG_ERROR_P(this, "Invalid State , current %d",
1034                 state_manager_.GetStateEnum());
1035     return false;
1036   }
1037   trackrenderer_->SetStretchMode(mode);
1038   return true;
1039 }
1040
1041 bool EsPlayer::SetDisplayRoi(const Geometry& roi) {
1042   if (state_manager_.GetState() < EsState::kIdle) {
1043     LOG_ERROR_P(this, "Invalid State , current %d",
1044                 state_manager_.GetStateEnum());
1045     return false;
1046   }
1047 #ifdef USE_MIXER
1048   mixerticket_roi_ = roi;
1049   if (mixer_ticket_) return true;
1050 #endif  // USE_MIXER
1051   return trackrenderer_->SetDisplayRoi(roi);
1052 }
1053
1054 bool EsPlayer::SetVideoRoi(const CropArea& area) {
1055   if (state_manager_.GetState() < EsState::kIdle) {
1056     LOG_ERROR_P(this, "Invalid State , current %d",
1057                 state_manager_.GetStateEnum());
1058     return false;
1059   }
1060   return trackrenderer_->SetVideoRoi(area);
1061 }
1062
1063 bool EsPlayer::ResizeRenderRect(const RenderRect& rect) {
1064   if (state_manager_.GetState() < EsState::kIdle) {
1065     LOG_ERROR_P(this, "Invalid State , current %d",
1066                 state_manager_.GetStateEnum());
1067     return false;
1068   }
1069   return trackrenderer_->ResizeRenderRect(rect);
1070 }
1071
1072 bool EsPlayer::SetDisplayRotate(const DisplayRotation& rotate) {
1073   if (state_manager_.GetState() < EsState::kIdle) {
1074     LOG_ERROR_P(this, "Invalid State , current %d",
1075                 state_manager_.GetStateEnum());
1076     return false;
1077   }
1078   return trackrenderer_->SetDisplayRotate(rotate);
1079 }
1080
1081 bool EsPlayer::GetDisplayRotate(DisplayRotation* rotate) {
1082   if (state_manager_.GetState() < EsState::kIdle) {
1083     LOG_ERROR_P(this, "Invalid State , current %d",
1084                 state_manager_.GetStateEnum());
1085     return false;
1086   }
1087   if (trackrenderer_->GetDisplayRotate(rotate)) {
1088     return true;
1089   }
1090   return false;
1091 }
1092
1093 bool EsPlayer::SetDisplayVisible(bool is_visible) {
1094   if (state_manager_.GetState() < EsState::kIdle) {
1095     LOG_ERROR_P(this, "Invalid State , current %d",
1096                 state_manager_.GetStateEnum());
1097     return false;
1098   }
1099 #ifdef USE_MIXER
1100   if (mixer_ticket_) {
1101     LOG_INFO_P(this, "mixed player is_visible [%d] -> [%d]", is_visible_,
1102                is_visible);
1103     is_visible_ = is_visible;
1104     return true;
1105   }
1106 #endif  // USE_MIXER
1107   return trackrenderer_->SetDisplayVisible(is_visible);
1108 }
1109
1110 bool EsPlayer::SetTrustZoneUse(bool is_using_tz) {
1111   if (state_manager_.GetState() != EsState::kIdle) {
1112     LOG_ERROR_P(this, "Invalid State , current %d",
1113                 state_manager_.GetStateEnum());
1114     return false;
1115   }
1116   if (drm_property_.type != drm::Type::kNone) {
1117     LOG_ERROR_P(this, "drm type is already set for sending encrypted packets");
1118     return false;
1119   }
1120   LOG_INFO_P(this, "set trust zone use [%d]", is_using_tz);
1121   drm_property_.external_decryption = is_using_tz;
1122
1123   drm::Property drm_property = drm_property_;
1124   drm_property.type = drm::Type::kPlayready;
1125   trackrenderer_->SetDrm(drm_property);
1126   return true;
1127 }
1128
1129 bool EsPlayer::SetSubmitDataType(SubmitDataType type) {
1130   if (state_manager_.GetState() != EsState::kIdle) {
1131     LOG_ERROR_P(this, "Invalid State , current %d",
1132                 state_manager_.GetStateEnum());
1133     return false;
1134   }
1135   LOG_INFO_P(this, "set submit data type [%d]", static_cast<int>(type));
1136
1137   if (type == SubmitDataType::kCleanData) return true;
1138   submit_data_type_ = type;
1139   drm_property_.type = drm::Type::kPlayready;
1140   // TODO: following SubmitDataType, need to set external_decryption
1141   drm_property_.external_decryption = true;
1142   drm::Property drm_property = drm_property_;
1143   trackrenderer_->SetDrm(drm_property);
1144   return true;
1145 }
1146
1147 bool EsPlayer::SetTrack_(const Track& track) {
1148   LOG_ENTER_P(this);
1149   track_util::ShowTrackInfo(track);
1150   track_.push_back(std::move(track));
1151   return true;
1152 }
1153
1154 bool EsPlayer::ChangeStream_(const Track& track) {
1155   TrackType type = track.type;
1156   if (track_.empty()) return false;
1157   auto has_track = [type](const Track& item) -> bool {
1158     return item.type == type;
1159   };
1160   std::lock_guard<std::mutex> lk(submit_mutex_);
1161   auto target = std::find_if(track_.begin(), track_.end(), has_track);
1162   if (target == track_.end()) {
1163     LOG_ERROR_P(this, "Add a new stream.");
1164     SetTrack_(track);
1165     return true;
1166   }
1167   if (target->active != false) {
1168     LOG_ERROR_P(this, "The track should be deactivated in advance.");
1169     return false;
1170   }
1171   track_.erase(target);
1172   LOG_ERROR_P(this, "previously added %s stream is deleted",
1173               (type == kTrackTypeAudio) ? "audio" : "video");
1174   return SetTrack_(track);
1175 }
1176
1177 bool EsPlayer::SetStream_(const Track& track) {
1178   TrackType type = track.type;
1179   if (!track_.empty()) {
1180     auto has_track = [type](const Track& item) -> bool {
1181       return item.type == type;
1182     };
1183     auto target = std::find_if(track_.begin(), track_.end(), has_track);
1184     if (target != track_.end()) {
1185       LOG_ERROR_P(this, "Stream is already exist");
1186       return false;
1187     }
1188   }
1189   auto op = [this, track]() noexcept {
1190     if (!SetTrack_(track)) {
1191       return false;
1192     }
1193     return true;
1194   };
1195
1196 #ifndef TIZEN_FEATURE_PUBLIC
1197   CafLogger::LogMessage(CafEventType::kStreamReady, caf_unique_number);
1198 #endif
1199
1200   es_event::SetStream event{op};
1201   return state_manager_.ProcessEvent(event);
1202 }
1203
1204 bool EsPlayer::SetStream(const AudioStreamPtr& stream) {
1205   LOG_ENTER_P(this);
1206   bool ret = false;
1207   BOOST_SCOPE_EXIT(&ret, &stream, &force_audio_swdecoder_use_) {
1208     if (ret)
1209       // when force_audio_swdecoder_use_ is already true, ignore stream setting.
1210       // otherwise, it can be true according to the stream setting
1211       force_audio_swdecoder_use_ =
1212           force_audio_swdecoder_use_ || stream->GetForceSwDecoderUse();
1213   }
1214   BOOST_SCOPE_EXIT_END
1215   if (state_manager_.GetState() < EsState::kIdle) {
1216     LOG_ERROR_P(this, "Invalid State , current %d",
1217                 state_manager_.GetStateEnum());
1218     return ret;
1219   }
1220   Track track = stream->GetTrack_();
1221   if (state_manager_.GetState() >= EsState::kReady) {
1222     if (is_audio_stream_info_frozen_) {
1223       LOG_ERROR_P(this, "can't change audio stream in audio deactivate mode");
1224       return ret;
1225     }
1226     track.active = false;
1227     ret = ChangeStream_(track);
1228     return ret;
1229   }
1230   ret = SetStream_(track);
1231   return ret;
1232 }
1233
1234 bool EsPlayer::SetStream(const VideoStreamPtr& stream) {
1235   LOG_ENTER_P(this);
1236   if (state_manager_.GetState() < EsState::kIdle) {
1237     LOG_ERROR_P(this, "Invalid State , current %d",
1238                 state_manager_.GetStateEnum());
1239     return false;
1240   }
1241   Track track = stream->GetTrack_();
1242   if (state_manager_.GetState() >= EsState::kReady) {
1243     track.active = false;
1244     return ChangeStream_(track);
1245   }
1246   return SetStream_(track);
1247 }
1248
1249 bool EsPlayer::SwitchAudioStreamOnTheFly(const AudioStreamPtr& stream) {
1250   LOG_ENTER_P(this);
1251   if (state_manager_.GetState() < EsState::kReady) {
1252     LOG_ERROR_P(this, "Invalid State , current %d",
1253                 state_manager_.GetStateEnum());
1254     return false;
1255   }
1256   Track track = stream->GetTrack_();
1257
1258   if (!internal::IsAvailableCodecSwitch(track)) {
1259     LOG_ERROR_P(this, "Invalid new mimetype [%s][%d]", track.mimetype.c_str(),
1260                 track.version);
1261     return false;
1262   }
1263   for (auto& old_track : track_) {
1264     if (old_track.type == TrackType::kTrackTypeAudio) {
1265       if (!internal::IsAvailableCodecSwitch(old_track)) {
1266         LOG_ERROR_P(this, "Invalid previous mimetype [%s][%d]",
1267                     old_track.mimetype.c_str(), old_track.version);
1268         return false;
1269       }
1270       if (!Flush(StreamType::kAudio)) return false;
1271       old_track.active = false;
1272       break;
1273     }
1274   }
1275   if (!ChangeStream_(track)) return false;
1276
1277   trackrenderer_->SetTrack(track_);
1278   return true;
1279 }
1280
1281 bool EsPlayer::SetAdvancedPictureQualityType(const AdvPictureQualityType type) {
1282   LOG_ENTER_P(this);
1283   if (state_manager_.GetState() != EsState::kIdle) {
1284     LOG_ERROR_P(this, "Invalid State , current %d",
1285                 state_manager_.GetStateEnum());
1286     return false;
1287   }
1288   trackrenderer_->SetAdvancedPictureQualityType(type);
1289   return true;
1290 }
1291
1292 bool EsPlayer::SetResourceAllocatePolicy(const RscAllocPolicy policy) {
1293   LOG_ENTER_P(this);
1294   if (state_manager_.GetState() != EsState::kIdle) {
1295     LOG_ERROR_P(this, "Invalid State , current %d",
1296                 state_manager_.GetStateEnum());
1297     return false;
1298   }
1299   resource_alloc_policy_ = policy;
1300   trackrenderer_->SetResourceAllocatePolicy(policy);
1301   return true;
1302 }
1303
1304 // LCOV_EXCL_START
1305 GetDecodedVideoFrameStatus EsPlayer::GetDecodedPacket(
1306     DecodedVideoPacket& packet) {
1307   if (state_manager_.GetState() < EsState::kReady) {
1308     LOG_ERROR_P(this, "Invalid State , current %d",
1309                 state_manager_.GetStateEnum());
1310     return GetDecodedVideoFrameStatus::kUnknown;
1311   }
1312   return trackrenderer_->GetDecodedPacket(packet);
1313 }
1314
1315 bool EsPlayer::ReturnDecodedPacket(const DecodedVideoPacket& packet) {
1316   if (state_manager_.GetState() < EsState::kReady) {
1317     LOG_ERROR_P(this, "Invalid State , current %d",
1318                 state_manager_.GetStateEnum());
1319     return false;
1320   }
1321   return trackrenderer_->ReturnDecodedPacket(packet);
1322 }
1323 // LCOV_EXCL_STOP
1324
1325 void EsPlayer::ResetContextForClose_() {
1326   internal::ResetDrmProperty(drm_property_);
1327   track_.clear();
1328   submit_data_type_ = SubmitDataType::kCleanData;
1329   low_latency_mode_ = 0;
1330   resume_time_.is_set = false;
1331   video_frame_peek_mode_ = 0;
1332   unlimited_max_buffer_mode_ = 0;
1333   fmm_mode_ = 0;
1334   audio_codec_type_ = kPlayerAudioCodecTypeHW;
1335   video_codec_type_ = kPlayerVideoCodecTypeHW;
1336   is_resource_conflicted_ = false;
1337   app_info_ = PlayerAppInfo();
1338   src_queue_size_ = SrcQueueSize();
1339   is_msg_task_stop_ = false;
1340   key_system_acquired_ = false;
1341 }
1342
1343 void EsPlayer::ResetContextForStop_() {
1344   for (int i = 0; i < kTrackTypeMax; ++i) {
1345     need_data_[i].mask = kNeedDataMaskNone;
1346     need_data_[i].seek_offset = 0;
1347   }
1348   {
1349     std::lock_guard<std::mutex> lock(eos_mutex_);
1350     eos_status_ = EosStatus::kAllEos;
1351   }
1352   current_playback_rate_ = 1.0;
1353   current_audio_mute_ = false;
1354 }
1355
1356 void EsPlayer::GetSrcQueueCurrentSize_(const TrackType& type,
1357                                        uint64_t* byte_size,
1358                                        uint64_t* time_size) {
1359   boost::any byte_size_, time_size_;
1360   if (type == TrackType::kTrackTypeVideo) {
1361     trackrenderer_->GetAttribute(
1362         TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelByte,
1363         &byte_size_);
1364     trackrenderer_->GetAttribute(
1365         TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
1366         &time_size_);
1367   } else if (type == TrackType::kTrackTypeAudio) {
1368     trackrenderer_->GetAttribute(
1369         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
1370         &byte_size_);
1371     trackrenderer_->GetAttribute(
1372         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
1373         &time_size_);
1374   } else
1375     return;
1376   try {
1377     *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
1378     *time_size = boost::any_cast<std::uint64_t>(time_size_);
1379   } catch (...) {
1380     LOG_INFO_P(this, "any_cast failed");
1381   }
1382   if (time_unit_type == kPlayerTimeUnitTypeMs)
1383     *time_size = util::ConvertNsToMs(*time_size);
1384   else if (time_unit_type == kPlayerTimeUnitTypeUs)
1385     *time_size = util::ConvertNsToUs(*time_size);
1386 }
1387
1388 GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
1389                                    MakeBufferStatus* status) {
1390   std::shared_ptr<char> buffer = packet->GetBuffer();
1391   uint32_t size = packet->GetSize();
1392   if (packet->IsEosPacket()) {
1393     *status = MakeBufferStatus::kEos;
1394     return nullptr;
1395   }
1396   GstBuffer* gstbuffer = gst_buffer_new_and_alloc(size);
1397   if (!gstbuffer) {
1398     *status = MakeBufferStatus::kOutOfMemory;
1399     return nullptr;
1400   }
1401   if (buffer != nullptr) {
1402     GstMapInfo map;
1403     gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
1404     memcpy(map.data, buffer.get(), size);
1405     gst_buffer_unmap(gstbuffer, &map);
1406   }
1407
1408   uint64_t pts = packet->GetPts();
1409   uint64_t duration = packet->GetDuration();
1410   /* if pts or duration are -1(=GST_CLOCK_TIME_NONE), some of the elements don't
1411    * adjust the buffer. */
1412   if (time_unit_type == kPlayerTimeUnitTypeMs) {
1413     GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1414                                     ? GST_CLOCK_TIME_NONE
1415                                     : (GstClockTime)util::ConvertMsToNs(pts);
1416     GST_BUFFER_DURATION(gstbuffer) =
1417         (duration == GST_CLOCK_TIME_NONE)
1418             ? GST_CLOCK_TIME_NONE
1419             : (GstClockTime)util::ConvertMsToNs(duration);
1420   } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1421     GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1422                                     ? GST_CLOCK_TIME_NONE
1423                                     : (GstClockTime)util::ConvertUsToNs(pts);
1424     GST_BUFFER_DURATION(gstbuffer) =
1425         (duration == GST_CLOCK_TIME_NONE)
1426             ? GST_CLOCK_TIME_NONE
1427             : (GstClockTime)util::ConvertUsToNs(duration);
1428   }
1429   uint32_t hdr10p_size = packet->GetHdr10pSize();
1430   std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
1431
1432   if (hdr10p_size > 0 && hdr10p_metadata != nullptr) {
1433     guint32* blockadditional_size = (guint32*)g_malloc(sizeof(uint32_t));
1434     *blockadditional_size = hdr10p_size;
1435     gst_mini_object_set_qdata(
1436         GST_MINI_OBJECT(gstbuffer),
1437         g_quark_from_static_string("matroska_blockadditional_size"),
1438         blockadditional_size, g_free);
1439
1440     /* blockadditiona_data : the data sent to omx, size (4 bytes) + metadata */
1441     guint8* blockadditional_data =
1442         (guint8*)g_malloc(((*blockadditional_size) + 4) * sizeof(guint8));
1443     memcpy(blockadditional_data, blockadditional_size, sizeof(uint32_t));
1444     memcpy(blockadditional_data + 4, hdr10p_metadata.get(),
1445            (*blockadditional_size));
1446     gst_mini_object_set_qdata(
1447         GST_MINI_OBJECT(gstbuffer),
1448         g_quark_from_static_string("matroska_blockadditional_info"),
1449         blockadditional_data, g_free);
1450   }
1451   *status = MakeBufferStatus::kSuccess;
1452   return gstbuffer;
1453 }
1454
1455 PacketSubmitStatus EsPlayer::SubmitEosPacket_(const TrackType& type) {
1456   PacketSubmitStatus submitstate = PacketSubmitStatus::kSuccess;
1457   {
1458     std::lock_guard<std::mutex> lock(eos_mutex_);
1459     switch (type) {
1460       case kTrackTypeAudio:
1461         eos_status_ |= EosStatus::kAudioEos;
1462         break;
1463       case kTrackTypeVideo:
1464         eos_status_ |= EosStatus::kVideoEos;
1465         break;
1466       default:
1467         break;
1468     }
1469     if (eos_status_ != EosStatus::kAllEos) {
1470       return submitstate;
1471     }
1472   }
1473   for (int tracktype = kTrackTypeAudio; tracktype < kTrackTypeMax;
1474        ++tracktype) {
1475     auto inbuffer =
1476         DecoderInputBuffer::Create(static_cast<TrackType>(tracktype));
1477     if (!trackrenderer_->SubmitPacket2(inbuffer, nullptr)) {
1478       std::lock_guard<std::mutex> lock(eos_mutex_);
1479       eos_status_ = EosStatus::kAllEos;
1480       submitstate = PacketSubmitStatus::kNotPrepared;
1481       return submitstate;
1482     }
1483   }
1484   return submitstate;
1485 }
1486
1487 void EsPlayer::UnsetTzQdata_(const DecoderInputBufferPtr& buffer) {
1488   const GstBuffer* gstbuf = buffer->Get();
1489   if (!gstbuf) return;
1490   GstStructure* tzqdata = GST_STRUCTURE(gst_mini_object_steal_qdata(
1491       GST_MINI_OBJECT(gstbuf), g_quark_from_static_string("GstTzHandleData")));
1492   if (tzqdata) gst_structure_free(tzqdata);
1493 }
1494
1495 PacketSubmitStatus EsPlayer::SubmitDecoderInputBuffer_(
1496     const DecoderInputBufferPtr& buffer) {
1497   PacketSubmitStatus status = PacketSubmitStatus::kSuccess;
1498   TrackRendererAdapter::SubmitStatus submitstate =
1499       TrackRendererAdapter::SubmitStatus::kSuccess;
1500   trackrenderer_->SubmitPacket2(buffer, &submitstate);
1501
1502   switch (submitstate) {
1503     case TrackRendererAdapter::SubmitStatus::kSuccess:
1504     case TrackRendererAdapter::SubmitStatus::kDrop:
1505       status = PacketSubmitStatus::kSuccess;
1506       break;
1507     case TrackRendererAdapter::SubmitStatus::kFull:
1508       UnsetTzQdata_(buffer);
1509       trackrenderer_event_listener_->OnBufferStatus(buffer->GetType(),
1510                                                     BufferStatus::kOverrun);
1511       status = PacketSubmitStatus::kFull;
1512       break;
1513     default:
1514       UnsetTzQdata_(buffer);
1515       status = PacketSubmitStatus::kNotPrepared;
1516       break;
1517   }
1518   return status;
1519 }
1520
1521 // LCOV_EXCL_START
1522 void EsPlayer::MakeGstBufferForTzHandle_(GstBuffer* gstbuffer,
1523                                          const TrackType& type,
1524                                          const uint32_t& tz_handle,
1525                                          const uint32_t& packet_size) {
1526   GstStructure* gst_tz_handle_data_structure =
1527       gst_structure_new("GstTzHandleData", "packet_handle", G_TYPE_UINT,
1528                         static_cast<guint32>(tz_handle), "packet_size",
1529                         G_TYPE_UINT, static_cast<guint32>(packet_size),
1530                         "secure", G_TYPE_BOOLEAN, true, nullptr);
1531   gst_mini_object_set_qdata(
1532       GST_MINI_OBJECT(gstbuffer), g_quark_from_string("GstTzHandleData"),
1533       gst_tz_handle_data_structure, (GDestroyNotify)gst_structure_free);
1534
1535   if (type == kTrackTypeAudio) {
1536     Track audio_track;
1537     bool has_active_audio_track =
1538         track_util::GetActiveTrack(track_, kTrackTypeAudio, &audio_track);
1539     if (has_active_audio_track) {
1540       GstStructure* audio_info_structure =
1541           gst_structure_new("AudioInfo", "mime_type", G_TYPE_STRING,
1542                             audio_track.mimetype.c_str(), nullptr);
1543       gst_mini_object_set_qdata(
1544           GST_MINI_OBJECT(gstbuffer), g_quark_from_string("AudioInfo"),
1545           audio_info_structure, (GDestroyNotify)gst_structure_free);
1546     }
1547   }
1548 }
1549
1550 void EsPlayer::MakeGstBufferForEncryptedPacket_(
1551     GstBuffer* gstbuffer, const EsPacketPtr& packet,
1552     const drm::EsPlayerEncryptedInfo& drm_info) {
1553   if (drm_info.handle == 0) return;
1554   auto serialized_drm_info_ptr = esplayer_drm::Serialize(packet, drm_info);
1555   GstStructure* gst_drm_info_structure =
1556       gst_structure_new("drm_info", "drm_specific_info", G_TYPE_BYTES,
1557                         serialized_drm_info_ptr.get(), nullptr);
1558   if (gst_drm_info_structure) {
1559     gst_mini_object_set_qdata(
1560         GST_MINI_OBJECT(gstbuffer), g_quark_from_static_string("drm_info"),
1561         gst_drm_info_structure, (GDestroyNotify)gst_structure_free);
1562   }
1563 }
1564 // LCOV_EXCL_STOP
1565
1566 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
1567                                                  SubmitPacketOperator op) {
1568   if (state_manager_.GetState() < EsState::kIdle) {
1569     return PacketSubmitStatus::kNotPrepared;
1570   }
1571   if (!packet) return PacketSubmitStatus::kInvalidPacket;
1572
1573   TrackType type = static_cast<TrackType>(packet->GetType());
1574   Track activated_track;
1575   if (!track_util::GetActiveTrack(track_, type, &activated_track))
1576     return PacketSubmitStatus::kInvalidPacket;
1577
1578   if (state_manager_.GetState() == EsState::kPaused ||
1579       state_manager_.GetState() == EsState::kReady) {
1580     internal::AppsrcQueueSizeOption byte_based, time_based;
1581     switch (type) {
1582       case kTrackTypeAudio:
1583         byte_based.max_size = src_queue_size_.kMaxByteOfAudioSrcQueue;
1584         time_based.max_size = src_queue_size_.kMaxTimeOfAudioSrcQueue;
1585         byte_based.threshold = src_queue_size_.kMinByteThresholdOfAudioSrcQueue;
1586         time_based.threshold = src_queue_size_.kMinTimeThresholdOfAudioSrcQueue;
1587         break;
1588       case kTrackTypeVideo:
1589         byte_based.max_size = src_queue_size_.kMaxByteOfVideoSrcQueue;
1590         time_based.max_size = src_queue_size_.kMaxTimeOfVideoSrcQueue;
1591         byte_based.threshold = src_queue_size_.kMinByteThresholdOfVideoSrcQueue;
1592         time_based.threshold = src_queue_size_.kMinTimeThresholdOfVideoSrcQueue;
1593         break;
1594       default:
1595         break;
1596     }
1597     GetSrcQueueCurrentSize_(type, &(byte_based.current_size),
1598                             &(time_based.current_size));
1599     if (internal::IsUnderRun(byte_based, time_based))
1600       trackrenderer_event_listener_->OnBufferStatus(type,
1601                                                     BufferStatus::kUnderrun);
1602   }
1603
1604   es_packet_logger_.StorePacketInfo(packet);
1605   es_packet_logger_.PrintStoredPacketInfo(packet->GetType());
1606
1607   MakeBufferStatus make_buffer_status;
1608   GstBuffer* gstbuffer = GetGstBuffer_(packet, &make_buffer_status);
1609   if (!gstbuffer) {
1610     if (make_buffer_status == MakeBufferStatus::kEos)
1611       return SubmitEosPacket_(type);
1612     else if (make_buffer_status == MakeBufferStatus::kOutOfMemory)
1613       return PacketSubmitStatus::kOutOfMemory;
1614   }
1615   if (op != nullptr) {
1616     PacketSubmitStatus op_status = op(gstbuffer);
1617     if (op_status != PacketSubmitStatus::kSuccess) {
1618       return op_status;
1619     }
1620   }
1621
1622   auto inbuffer = DecoderInputBuffer::Create(type, 0, gstbuffer);
1623   gst_buffer_unref(gstbuffer);
1624
1625   if (packet->HasMatroskaColorInfo()) {
1626     std::string color_info_str =
1627         util::GetStringFromMatroskaColor(packet->GetMatroskaColorInfo());
1628     if (trackrenderer_->SetMatroskaColorInfo(color_info_str) == false)
1629       return PacketSubmitStatus::kNotPrepared;
1630   }
1631
1632   return SubmitDecoderInputBuffer_(inbuffer);
1633 }
1634
1635 PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
1636   std::lock_guard<std::mutex> lk(submit_mutex_);
1637   return SubmitPacketCommon_(packet, nullptr);
1638 }
1639
1640 // LCOV_EXCL_START
1641 PacketSubmitStatus EsPlayer::SubmitTrustZonePacket(const EsPacketPtr& packet,
1642                                                    uint32_t tz_handle) {
1643   std::lock_guard<std::mutex> lk(submit_mutex_);
1644   if (submit_data_type_ != SubmitDataType::kTrustZoneData)
1645     return PacketSubmitStatus::kInvalidPacket;
1646   auto submitpacket_op = [this, &tz_handle,
1647                           &packet](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1648     if (tz_handle > 0) {
1649       TrackType type = static_cast<TrackType>(packet->GetType());
1650       uint32_t packet_size = packet->GetSize();
1651       MakeGstBufferForTzHandle_(gstbuffer, type, tz_handle, packet_size);
1652     }
1653     return PacketSubmitStatus::kSuccess;
1654   };
1655   return SubmitPacketCommon_(packet, submitpacket_op);
1656 }
1657
1658 PacketSubmitStatus EsPlayer::SubmitEncryptedPacket(
1659     const EsPacketPtr& packet, const drm::EsPlayerEncryptedInfo& drm_info) {
1660   std::lock_guard<std::mutex> lk(submit_mutex_);
1661   if (submit_data_type_ != SubmitDataType::kEncryptedData)
1662     return PacketSubmitStatus::kInvalidPacket;
1663   auto submitpacket_op =
1664       [this, &packet, &drm_info](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1665     MakeGstBufferForEncryptedPacket_(gstbuffer, packet, drm_info);
1666     return PacketSubmitStatus::kSuccess;
1667   };
1668   if (!key_system_acquired_ && drm_info.handle != 0) {
1669     key_system_ = eme::IEME::getKeySystemName(drm_info.handle);
1670     LOG_INFO("KeySystemName :: [%s] ", key_system_.c_str());
1671     if (!state_manager_
1672              .GetPreparingState()) {  // if the stream comes with clean data at
1673                                       // the beginning, re-post kpi when we get
1674                                       // key system.
1675       kpi::CodecLogger logger;
1676       kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
1677       logger.SendKpi(true, event_keys);
1678     }
1679     key_system_acquired_ = true;
1680   }
1681   return SubmitPacketCommon_(packet, submitpacket_op);
1682 }
1683 // LCOV_EXCL_STOP
1684
1685 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
1686
1687 bool EsPlayer::GetPlayingTime(uint64_t* time) {
1688   if (!time) return false;
1689   if (state_manager_.GetState() <= EsState::kReady) {
1690     *time = 0;
1691     return false;
1692   }
1693   return trackrenderer_->GetPlayingTime(time);
1694 }
1695
1696 bool EsPlayer::SetAudioMute(bool is_mute) {
1697   if (state_manager_.GetState() < EsState::kIdle) {
1698     LOG_ERROR_P(this, "Invalid State , current %d",
1699                 state_manager_.GetStateEnum());
1700     return false;
1701   }
1702   return trackrenderer_->SetAudioMute(is_mute);
1703 }
1704
1705 bool EsPlayer::SetVideoFrameBufferType(DecodedVideoFrameBufferType type) {
1706   if ((state_manager_.GetState() != EsState::kIdle &&
1707        type != DecodedVideoFrameBufferType::kScale) ||
1708       (state_manager_.GetState() < EsState::kIdle &&
1709        type == DecodedVideoFrameBufferType::kScale)) {
1710     LOG_ERROR_P(this, "Invalid State , current %d",
1711                 state_manager_.GetStateEnum());
1712     return false;
1713   }
1714   if (type == DecodedVideoFrameBufferType::kScale &&
1715       video_codec_type_ == kPlayerVideoCodecTypeSW) {
1716     LOG_ERROR_P(this, "kScale is not supportted when using sw video decoder");
1717     return false;
1718   }
1719   trackrenderer_->SetVideoFrameBufferType(
1720       VideoFrameTypeStrategyPtr(new DefaultVideoFrameTypeStrategy(type)));
1721   vidoe_frame_buffer_type_ = type;
1722   return true;
1723 }
1724
1725 bool EsPlayer::SetVideoFrameBufferScaleResolution(
1726     const uint32_t& target_width, const uint32_t& target_height) {
1727   if (state_manager_.GetState() < EsState::kIdle) {
1728     LOG_ERROR_P(this, "Invalid State , current %d",
1729                 state_manager_.GetStateEnum());
1730     return false;
1731   }
1732
1733   return trackrenderer_->SetVideoFrameBufferScaleResolution(target_width,
1734                                                             target_height);
1735 }
1736
1737 bool EsPlayer::SetDecodedVideoFrameRate(const Rational& request_framerate) {
1738   if (state_manager_.GetState() < EsState::kIdle) {
1739     LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
1740     return false;
1741   }
1742
1743   return trackrenderer_->SetDecodedVideoFrameRate(request_framerate);
1744 }
1745
1746 void EsPlayer::RegisterListener(EsEventListener* listener,
1747                                 EsEventListener::UserData userdata) {
1748   // assert(listener); // allow unregister by setting nullptr
1749   assert(!eventlistener_);
1750   eventlistener_ = listener;
1751   eventlistener_userdata_ = userdata;
1752 }
1753
1754 bool EsPlayer::GetAdaptiveInfo(void* padaptive_info,
1755                                const PlayerAdaptiveInfo& adaptive_type) {
1756   if (!padaptive_info || adaptive_type <= PlayerAdaptiveInfo::kMinType ||
1757       adaptive_type >= PlayerAdaptiveInfo::kMaxType)
1758     return false;
1759   switch (adaptive_type) {
1760     case PlayerAdaptiveInfo::kVideoDroppedFrames:
1761       if (state_manager_.GetState() < EsState::kReady) {
1762         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1763         return false;
1764       }
1765       return trackrenderer_->GetDroppedFrames(padaptive_info);
1766     case PlayerAdaptiveInfo::kDroppedVideoFramesForCatchup:
1767       if (state_manager_.GetState() < EsState::kReady) {
1768         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1769         return false;
1770       }
1771       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeVideo,
1772                                                         padaptive_info);
1773     case PlayerAdaptiveInfo::kDroppedAudioFramesForCatchup:
1774       if (state_manager_.GetState() < EsState::kReady) {
1775         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1776         return false;
1777       }
1778       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeAudio,
1779                                                         padaptive_info);
1780     default:
1781       break;
1782   }
1783   return false;
1784 }
1785
1786 bool EsPlayer::SetVolume(const int& volume) {
1787   if (volume < internal::kVolumeMin || volume > internal::kVolumeMax) {
1788     LOG_ERROR_P(this, "Invalid volume level %d", volume);
1789     return false;
1790   }
1791   if (state_manager_.GetState() < EsState::kIdle) {
1792     LOG_ERROR_P(this, "Invalid State , current %d",
1793                 state_manager_.GetStateEnum());
1794     return false;
1795   }
1796   return trackrenderer_->SetVolume(volume);
1797 }
1798
1799 bool EsPlayer::GetVolume(int* volume) {
1800   if (state_manager_.GetState() < EsState::kIdle) {
1801     LOG_ERROR_P(this, "Invalid State , current %d",
1802                 state_manager_.GetStateEnum());
1803     return false;
1804   }
1805   return trackrenderer_->GetVolume(volume);
1806 }
1807
1808 bool EsPlayer::Flush(const StreamType& type) {
1809   if (state_manager_.GetState() <= EsState::kIdle) {
1810     LOG_ERROR_P(this, "Invalid State , current %d",
1811                 state_manager_.GetStateEnum());
1812     return false;
1813   }
1814   eos_status_ =
1815       internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
1816   es_packet_logger_.ResetLog(type);
1817   return trackrenderer_->Flush(type);
1818 }
1819
1820 bool EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
1821   TrackType track_type = kTrackTypeMax;
1822   switch (option) {
1823     case BufferOption::kBufferAudioMaxByteSize:      /* FALL THROUGH */
1824     case BufferOption::kBufferAudioMinByteThreshold: /* FALL THROUGH */
1825     case BufferOption::kBufferAudioMaxTimeSize:      /* FALL THROUGH */
1826     case BufferOption::kBufferAudioMinTimeThreshold:
1827       track_type = kTrackTypeAudio;
1828       break;
1829     case BufferOption::kBufferVideoMaxByteSize:      /* FALL THROUGH */
1830     case BufferOption::kBufferVideoMinByteThreshold: /* FALL THROUGH */
1831     case BufferOption::kBufferVideoMaxTimeSize:      /* FALL THROUGH */
1832     case BufferOption::kBufferVideoMinTimeThreshold:
1833       track_type = kTrackTypeVideo;
1834       break;
1835     default:
1836       break;
1837   }
1838   if (track_type == kTrackTypeMax) {
1839     LOG_ERROR_P(this, "Invalid option!!!");
1840     return false;
1841   }
1842
1843   Track activated_track;
1844   bool is_activated =
1845       track_util::GetActiveTrack(track_, track_type, &activated_track);
1846   EsState state = state_manager_.GetState();
1847   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_activated)) {
1848     LOG_ERROR_P(this, "Invalid State [state:%d] or stream is activated [%d],",
1849                 state_manager_.GetStateEnum(), is_activated);
1850     return false;
1851   }
1852
1853   switch (option) {
1854     case BufferOption::kBufferAudioMaxByteSize:
1855       src_queue_size_.kMaxByteOfAudioSrcQueue = size;
1856       break;
1857     case BufferOption::kBufferVideoMaxByteSize:
1858       src_queue_size_.kMaxByteOfVideoSrcQueue = size;
1859       break;
1860     case BufferOption::kBufferAudioMinByteThreshold:
1861       src_queue_size_.kMinByteThresholdOfAudioSrcQueue =
1862           static_cast<uint32_t>(size);
1863       break;
1864     case BufferOption::kBufferVideoMinByteThreshold:
1865       src_queue_size_.kMinByteThresholdOfVideoSrcQueue =
1866           static_cast<uint32_t>(size);
1867       break;
1868     case BufferOption::kBufferAudioMaxTimeSize:
1869       src_queue_size_.kMaxTimeOfAudioSrcQueue = size;
1870       break;
1871     case BufferOption::kBufferVideoMaxTimeSize:
1872       src_queue_size_.kMaxTimeOfVideoSrcQueue = size;
1873       break;
1874     case BufferOption::kBufferAudioMinTimeThreshold:
1875       src_queue_size_.kMinTimeThresholdOfAudioSrcQueue =
1876           static_cast<uint32_t>(size);
1877       break;
1878     case BufferOption::kBufferVideoMinTimeThreshold:
1879       src_queue_size_.kMinTimeThresholdOfVideoSrcQueue =
1880           static_cast<uint32_t>(size);
1881       break;
1882     default:
1883       LOG_ERROR_P(this, "Invalid option!!!");
1884       break;
1885   }
1886   return true;
1887 }
1888
1889 bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
1890   if (state_manager_.GetState() != EsState::kIdle) {
1891     LOG_ERROR_P(this, "Invalid State , current %d",
1892                 state_manager_.GetStateEnum());
1893     return false;
1894   }
1895   if (true == internal::IsExclusiveLowLatencyMode(low_latency_mode_, mode)) {
1896     LOG_ERROR_P(this, "Invalid Mode , current 0x%x, set 0x%x",
1897                 static_cast<std::uint32_t>(low_latency_mode_),
1898                 static_cast<std::uint32_t>(mode));
1899     return false;
1900   }
1901   low_latency_mode_ |= static_cast<std::uint32_t>(mode);
1902   return true;
1903 }
1904
1905 bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
1906   if (state_manager_.GetState() < EsState::kReady) {
1907     LOG_ERROR_P(this, "Invalid State , current %d",
1908                 state_manager_.GetStateEnum());
1909     return false;
1910   }
1911   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1912     LOG_ERROR_P(this,
1913                 "low latency mode have to be set except disable_sync mode");
1914     return false;
1915   }
1916   std::int64_t ns_unit = 0;
1917   if (time_unit_type == kPlayerTimeUnitTypeMs)
1918     ns_unit = 1000000;
1919   else if (time_unit_type == kPlayerTimeUnitTypeUs)
1920     ns_unit = 1000;
1921   if ((offset * ns_unit > G_MAXINT64) || (offset * ns_unit < G_MININT64)) {
1922     LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
1923               "] * 1000000 < G_MAXINT64",
1924               this, offset);
1925     return false;
1926   }
1927   if (type == StreamType::kMax) return false;
1928   if (time_unit_type == kPlayerTimeUnitTypeMs) {
1929     if (type == StreamType::kAudio)
1930       trackrenderer_->SetAttribute(
1931           TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1932           util::ConvertMsToNs(offset));
1933     else if (type == StreamType::kVideo)
1934       trackrenderer_->SetAttribute(
1935           TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1936           util::ConvertMsToNs(offset));
1937   } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1938     if (type == StreamType::kAudio)
1939       trackrenderer_->SetAttribute(
1940           TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1941           util::ConvertUsToNs(offset));
1942     else if (type == StreamType::kVideo)
1943       trackrenderer_->SetAttribute(
1944           TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1945           util::ConvertUsToNs(offset));
1946   }
1947   return true;
1948 }
1949
1950 bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
1951   if (state_manager_.GetState() < EsState::kReady) {
1952     LOG_ERROR_P(this, "Invalid State , current %d",
1953                 state_manager_.GetStateEnum());
1954     return false;
1955   }
1956   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1957     LOG_ERROR_P(this, "low latency mode have to be set");
1958     return false;
1959   }
1960   if (type == StreamType::kMax) return false;
1961   boost::any off_set;
1962   if (type == StreamType::kAudio)
1963     trackrenderer_->GetAttribute(
1964         TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
1965   else if (type == StreamType::kVideo)
1966     trackrenderer_->GetAttribute(
1967         TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
1968
1969   *offset = boost::any_cast<std::int64_t>(off_set);
1970   if (time_unit_type == kPlayerTimeUnitTypeMs)
1971     *offset = util::ConvertNsToMs(*offset);
1972   else if (time_unit_type == kPlayerTimeUnitTypeUs)
1973     *offset = util::ConvertNsToUs(*offset);
1974   return true;
1975 }
1976
1977 bool EsPlayer::SetVideoFramePeekMode() {
1978   if (state_manager_.GetState() != EsState::kIdle) {
1979     LOG_ERROR_P(this, "Invalid State , current %d",
1980                 state_manager_.GetStateEnum());
1981     return false;
1982   }
1983   constexpr std::uint32_t peek_mode_on = 1;
1984   video_frame_peek_mode_ = peek_mode_on;
1985   return true;
1986 }
1987
1988 bool EsPlayer::RenderVideoFrame() {
1989   if (!video_frame_peek_mode_) return false;
1990   if (state_manager_.GetState() == EsState::kReady ||
1991       state_manager_.GetState() == EsState::kPaused) {
1992     trackrenderer_->RenderVideoFrame();
1993     return true;
1994   }
1995   LOG_ERROR_P(this, "Invalid State , current %d",
1996               state_manager_.GetStateEnum());
1997   return false;
1998 }
1999
2000 bool EsPlayer::SetUnlimitedMaxBufferMode() {
2001   if (state_manager_.GetState() != EsState::kIdle) {
2002     LOG_ERROR_P(this, "Invalid State , current %d",
2003                 state_manager_.GetStateEnum());
2004     return false;
2005   }
2006   constexpr std::uint32_t unlimited_max_buffer_mode_on = 1;
2007   unlimited_max_buffer_mode_ = unlimited_max_buffer_mode_on;
2008   return true;
2009 }
2010
2011 ErrorType EsPlayer::SetFmmMode() {
2012   EsState state = state_manager_.GetState();
2013   LOG_ENTER_P(this);
2014   if (state < EsState::kIdle) {
2015     LOG_ERROR_P(this, "Invalid State , current %d",
2016                 state_manager_.GetStateEnum());
2017     return ErrorType::kInvalidState;
2018   }
2019
2020   int onoff = 0;
2021   ErrorType ret = ErrorType::kNone;
2022   if (trackrenderer_->GetFmmAutoMode(&onoff) == false) {
2023     return ErrorType::kInvalidOperation;
2024   }
2025
2026   enum {
2027     FMM_AUTO_OFF = 0,
2028     FMM_AUTO_ON = 1,
2029   };
2030
2031   if (onoff == FMM_AUTO_OFF) ret = ErrorType::kInvalidOperation;
2032
2033   fmm_mode_ = FMM_AUTO_ON;
2034
2035   if (state < EsState::kReady) return ret;
2036
2037   trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
2038                                fmm_mode_);
2039   return ret;
2040 }
2041
2042 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
2043   Track activated_track;
2044   bool is_existed =
2045       track_util::GetActiveTrack(track_, kTrackTypeAudio, &activated_track);
2046   EsState state = state_manager_.GetState();
2047   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2048     LOG_ERROR_P(this,
2049                 "Invalid State [state:%d] or audio stream already exists[%d],",
2050                 state_manager_.GetStateEnum(), is_existed);
2051     return false;
2052   }
2053   if (force_audio_swdecoder_use_ && type == kPlayerAudioCodecTypeHW) {
2054     LOG_ERROR_P(this, "Not support hw decoder");
2055     return false;
2056   }
2057   LOG_INFO_P(this, "PlayerAudioCodecType [%s]",
2058              (type == kPlayerAudioCodecTypeHW) ? "hardware" : "software");
2059   audio_codec_type_ = type;
2060   return true;
2061 }
2062
2063 bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
2064   Track activated_track;
2065   bool is_existed =
2066       track_util::GetActiveTrack(track_, kTrackTypeVideo, &activated_track);
2067   EsState state = state_manager_.GetState();
2068   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2069     LOG_ERROR_P(this,
2070                 "Invalid State [state:%d] or video stream already exists[%d],",
2071                 state_manager_.GetStateEnum(), is_existed);
2072     return false;
2073   }
2074   if (force_video_swdecoder_use_ &&
2075       (type == kPlayerVideoCodecTypeHW ||
2076        type == kPlayerVideoCodecTypeHWNdecoding)) {
2077     LOG_ERROR_P(this, "Not support hw decoder");
2078     return false;
2079   }
2080   if (type == kPlayerVideoCodecTypeSW &&
2081       vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
2082     LOG_ERROR_P(this,
2083                 "sw video decoder is not supportted when video frame buffer "
2084                 "type is scale");
2085     return false;
2086   }
2087 #ifdef USE_MIXER
2088   if (!enable_rsc_alloc_handle_) {
2089     LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2090     return false;
2091   }
2092   if (type == kPlayerVideoCodecTypeHWNdecoding) {
2093     LOG_INFO_P(this, "PlayerVideoCodecType HW N-decoding");
2094     video_decoding_mode_ = internal::kNdecodingMode;
2095     return true;
2096   }
2097 #endif  // USE_MIXER
2098   LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
2099              (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
2100   video_codec_type_ = type;
2101   return true;
2102 }
2103
2104 bool EsPlayer::SetAiFilter(void* aifilter) {
2105   if (state_manager_.GetState() != EsState::kIdle) {
2106     LOG_ERROR_P(this, "Invalid State , current %d",
2107                 state_manager_.GetStateEnum());
2108     return false;
2109   }
2110   trackrenderer_->SetAiFilter(aifilter);
2111   return true;
2112 }
2113
2114 bool EsPlayer::InitAudioEasingInfo(const uint32_t init_volume,
2115                                    const uint32_t init_elapsed_time,
2116                                    const AudioEasingInfo& easing_info) {
2117   if (init_volume > internal::kVolumeMax ||
2118       easing_info.target_volume > internal::kVolumeMax) {
2119     LOG_ERROR_P(this, "Invalid volume: init [%d] target [%d]", init_volume,
2120                 easing_info.target_volume);
2121     return false;
2122   }
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_->InitAudioEasingInfo(init_volume, init_elapsed_time,
2129                                              easing_info);
2130 }
2131
2132 bool EsPlayer::UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) {
2133   if (easing_info.target_volume > internal::kVolumeMax) {
2134     LOG_ERROR_P(this, "Invalid volume level %d", easing_info.target_volume);
2135     return false;
2136   }
2137   if (state_manager_.GetState() < EsState::kIdle) {
2138     LOG_ERROR_P(this, "Invalid State , current %d",
2139                 state_manager_.GetStateEnum());
2140     return false;
2141   }
2142   return trackrenderer_->UpdateAudioEasingInfo(easing_info);
2143 }
2144
2145 bool EsPlayer::GetAudioEasingInfo(uint32_t* current_volume,
2146                                   uint32_t* elapsed_time,
2147                                   AudioEasingInfo* easing_info) {
2148   if (state_manager_.GetState() < EsState::kIdle) {
2149     LOG_ERROR_P(this, "Invalid State , current %d",
2150                 state_manager_.GetStateEnum());
2151     return false;
2152   }
2153   return trackrenderer_->GetAudioEasingInfo(current_volume, elapsed_time,
2154                                             easing_info);
2155 }
2156
2157 bool EsPlayer::StartAudioEasing() {
2158   if (state_manager_.GetState() < EsState::kReady) {
2159     LOG_ERROR_P(this, "Invalid State , current %d",
2160                 state_manager_.GetStateEnum());
2161     return false;
2162   }
2163   return trackrenderer_->StartAudioEasing();
2164 }
2165
2166 bool EsPlayer::StopAudioEasing() {
2167   if (state_manager_.GetState() < EsState::kIdle) {
2168     LOG_ERROR_P(this, "Invalid State , current %d",
2169                 state_manager_.GetStateEnum());
2170     return false;
2171   }
2172   return trackrenderer_->StopAudioEasing();
2173 }
2174
2175 bool EsPlayer::SetAlternativeVideoResource(unsigned int rsc_type) {
2176   if (state_manager_.GetState() == EsState::kNone) {
2177     LOG_ERROR_P(this, "Invalid State");
2178     return false;
2179   }
2180 #ifdef USE_MIXER
2181   if (!enable_rsc_alloc_handle_) {
2182     LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2183     return false;
2184   }
2185 #endif  // USE_MIXER
2186   if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2187     LOG_ERROR_P(this,
2188                 "has set resource allocate policy, the alternative "
2189                 "resource setting will be wrong");
2190     return false;
2191   }
2192   alternative_video_resource_ = static_cast<std::uint32_t>(rsc_type);
2193   return true;
2194 }
2195
2196 bool EsPlayer::SetAlternativeAudioResource(
2197     const PlayerAudioResourceType rsc_type) {
2198   if (state_manager_.GetState() == EsState::kNone) {
2199     LOG_ERROR_P(this, "Invalid State");
2200     return false;
2201   }
2202
2203   if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2204     LOG_ERROR_P(this,
2205                 "has set resource allocate policy, the alternative "
2206                 "resource setting will be wrong");
2207     return false;
2208   }
2209   return trackrenderer_->SetAlternativeAudioResource(rsc_type);
2210 }
2211
2212 bool EsPlayer::SetCatchUpSpeed(const CatchUpSpeed& level) {
2213   if (state_manager_.GetState() < EsState::kIdle) {
2214     LOG_ERROR_P(this, "Invalid State , current %d",
2215                 state_manager_.GetStateEnum());
2216     return false;
2217   }
2218
2219   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2220     LOG_ERROR_P(this, "Do not set low latency mode, current[0x%x]",
2221                 static_cast<std::uint32_t>(low_latency_mode_));
2222     return false;
2223   }
2224
2225   if (trackrenderer_->SetCatchUpSpeed(level)) {
2226     return true;
2227   }
2228   return false;
2229 }
2230
2231 bool EsPlayer::GetVideoLatencyStatus(LatencyStatus* status) {
2232   if (state_manager_.GetState() < EsState::kReady) {
2233     LOG_ERROR_P(this, "Invalid State , current %d",
2234                 state_manager_.GetStateEnum());
2235     return false;
2236   }
2237
2238   if (trackrenderer_->GetVideoLatencyStatus(status)) {
2239     return true;
2240   }
2241   return false;
2242 }
2243
2244 bool EsPlayer::GetAudioLatencyStatus(LatencyStatus* status) {
2245   if (state_manager_.GetState() < EsState::kReady) {
2246     LOG_ERROR_P(this, "Invalid State , current %d",
2247                 state_manager_.GetStateEnum());
2248     return false;
2249   }
2250
2251   if (trackrenderer_->GetAudioLatencyStatus(status)) {
2252     return true;
2253   }
2254   return false;
2255 }
2256
2257 bool EsPlayer::SetVideoMidLatencyThreshold(const unsigned int threshold) {
2258   if (state_manager_.GetState() < EsState::kIdle) {
2259     LOG_ERROR_P(this, "Invalid State , current %d",
2260                 state_manager_.GetStateEnum());
2261     return false;
2262   }
2263
2264   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2265     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2266                 static_cast<std::uint32_t>(low_latency_mode_));
2267     return false;
2268   }
2269
2270   LOG_INFO_P(this, "video_mid_latency_threshold : [%u]", threshold);
2271
2272   trackrenderer_->SetVideoMidLatencyThreshold(threshold);
2273   return true;
2274 }
2275
2276 bool EsPlayer::SetAudioMidLatencyThreshold(const unsigned int threshold) {
2277   if (state_manager_.GetState() < EsState::kIdle) {
2278     LOG_ERROR_P(this, "Invalid State , current %d",
2279                 state_manager_.GetStateEnum());
2280     return false;
2281   }
2282
2283   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2284     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2285                 static_cast<std::uint32_t>(low_latency_mode_));
2286     return false;
2287   }
2288
2289   LOG_INFO_P(this, "audio_mid_latency_threshold : [%u]", threshold);
2290
2291   trackrenderer_->SetAudioMidLatencyThreshold(threshold);
2292   return true;
2293 }
2294
2295 bool EsPlayer::SetVideoHighLatencyThreshold(const unsigned int threshold) {
2296   if (state_manager_.GetState() < EsState::kIdle) {
2297     LOG_ERROR_P(this, "Invalid State , current %d",
2298                 state_manager_.GetStateEnum());
2299     return false;
2300   }
2301
2302   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2303     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2304                 static_cast<std::uint32_t>(low_latency_mode_));
2305     return false;
2306   }
2307
2308   LOG_INFO_P(this, "video_high_latency_threshold : [%u]", threshold);
2309
2310   trackrenderer_->SetVideoHighLatencyThreshold(threshold);
2311   return true;
2312 }
2313
2314 bool EsPlayer::SetAudioHighLatencyThreshold(const unsigned int threshold) {
2315   if (state_manager_.GetState() < EsState::kIdle) {
2316     LOG_ERROR_P(this, "Invalid State , current %d",
2317                 state_manager_.GetStateEnum());
2318     return false;
2319   }
2320
2321   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2322     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2323                 static_cast<std::uint32_t>(low_latency_mode_));
2324     return false;
2325   }
2326
2327   LOG_INFO_P(this, "audio_high_latency_threshold : [%u]", threshold);
2328
2329   trackrenderer_->SetAudioHighLatencyThreshold(threshold);
2330   return true;
2331 }
2332
2333 bool EsPlayer::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
2334   if (frame_count == nullptr) {
2335     LOG_ERROR_P(this, "frame count is nullptr");
2336     return false;
2337   }
2338   if (state_manager_.GetState() < EsState::kReady) {
2339     LOG_ERROR_P(this, "Invalid State , current %d",
2340                 state_manager_.GetStateEnum());
2341     return false;
2342   }
2343
2344   if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2345     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2346                 static_cast<std::uint32_t>(low_latency_mode_));
2347     return false;
2348   }
2349
2350   return trackrenderer_->GetLowLatencyPcmBufferSize(frame_count);
2351 }
2352
2353 bool EsPlayer::GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
2354   if (frame_count == nullptr) {
2355     LOG_ERROR_P(this, "frame count is nullptr");
2356     return false;
2357   }
2358   if (state_manager_.GetState() < EsState::kReady) {
2359     LOG_ERROR_P(this, "Invalid State , current %d",
2360                 state_manager_.GetStateEnum());
2361     return false;
2362   }
2363
2364   if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2365     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2366                 static_cast<std::uint32_t>(low_latency_mode_));
2367     return false;
2368   }
2369
2370   return trackrenderer_->GetLowLatencyPcmCurrentBufferLevel(frame_count);
2371 }
2372
2373 bool EsPlayer::GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
2374   if (underrun_count == nullptr) {
2375     LOG_ERROR_P(this, "underrun count is nullptr");
2376     return false;
2377   }
2378   if (state_manager_.GetState() < EsState::kReady) {
2379     LOG_ERROR_P(this, "Invalid State , current %d",
2380                 state_manager_.GetStateEnum());
2381     return false;
2382   }
2383
2384   if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2385     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2386                 static_cast<std::uint32_t>(low_latency_mode_));
2387     return false;
2388   }
2389
2390   return trackrenderer_->GetLowLatencyPcmUnderrunCount(underrun_count);
2391 }
2392
2393 bool EsPlayer::GetVirtualRscId(const RscType type, int* virtual_id) {
2394   if (virtual_id == nullptr) return false;
2395   if (state_manager_.GetState() < EsState::kReady) {
2396     LOG_ERROR_P(this, "Invalid State , current %d",
2397                 state_manager_.GetStateEnum());
2398     *virtual_id = -1;
2399     return false;
2400   }
2401   return trackrenderer_->GetVirtualRscId(type, virtual_id);
2402 }
2403
2404 bool EsPlayer::SetAudioPreloading() {
2405   if (state_manager_.GetState() != EsState::kIdle) {
2406     LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
2407     return false;
2408   }
2409   return trackrenderer_->SetAudioPreloading();
2410 }
2411
2412 void EsPlayer::Init_() {
2413   track_.clear();
2414   is_stopped_ = false;
2415   LOG_LEAVE_P(this);
2416 }
2417
2418 void EsPlayer::MsgTask_() {
2419   std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
2420   while (!is_msg_task_stop_) {
2421     if (msg_queue_.empty()) {
2422       msg_task_cv_.wait(msg_mutex);
2423     } else {
2424       msg_mutex.unlock();
2425       msg_queue_.front()->Execute();
2426       msg_mutex.lock();
2427       msg_queue_.pop();
2428     }
2429   }
2430   while (!msg_queue_.empty()) {
2431     msg_queue_.pop();
2432   }
2433   LOG_INFO_P(this, "Stop MsgTask");
2434 }
2435
2436 void EsPlayer::TrackRendererEventListener::OnEos() {
2437   LOG_ENTER_P(handler_);
2438   if (!handler_->eventlistener_) return;
2439   auto listener = std::bind(&esplusplayer::EsEventListener::OnEos,
2440                             handler_->eventlistener_, std::placeholders::_1);
2441   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2442   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2443   handler_->msg_queue_.push(std::move(msg));
2444   msg_mutex.unlock();
2445   handler_->msg_task_cv_.notify_one();
2446   LOG_LEAVE_P(handler_);
2447 }
2448
2449 // LCOV_EXCL_START
2450 void EsPlayer::TrackRendererEventListener::OnSeekDone() {
2451   LOG_ENTER_P(handler_);
2452   if (!handler_->eventlistener_) return;
2453   if (handler_->is_seek_done_need_drop == true) return;
2454   auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
2455                             handler_->eventlistener_, std::placeholders::_1);
2456   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2457   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2458   handler_->msg_queue_.push(std::move(msg));
2459   msg_mutex.unlock();
2460   handler_->msg_task_cv_.notify_one();
2461   LOG_LEAVE_P(handler_);
2462 }
2463
2464 void EsPlayer::TrackRendererEventListener::OnResourceConflicted() {
2465   LOG_ENTER_P(handler_);
2466   if (handler_->is_stopped_) {
2467     LOG_INFO_P(handler_, "LEAVE ~ Stop is called already");
2468     return;
2469   }
2470   LOG_INFO_P(handler_, "Handling resource conflict...");
2471   handler_->is_resource_conflicted_ = true;
2472   handler_->trackrenderer_->Stop();
2473   if (!handler_->eventlistener_ || handler_->is_stopped_) return;
2474   auto listener =
2475       std::bind(&esplusplayer::EsEventListener::OnResourceConflicted,
2476                 handler_->eventlistener_, std::placeholders::_1);
2477   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2478   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2479   handler_->msg_queue_.push(std::move(msg));
2480   msg_mutex.unlock();
2481   if (handler_->is_stopped_) {
2482     LOG_LEAVE_P(handler_);
2483     return;
2484   }
2485   handler_->msg_task_cv_.notify_one();
2486   LOG_LEAVE_P(handler_);
2487 }
2488
2489 void EsPlayer::TrackRendererEventListener::OnError(
2490     const ErrorType& error_code) {
2491   if (!handler_->eventlistener_) return;
2492   if (error_code == ErrorType::kResourceLimit) return;
2493   auto listener = std::bind(&esplusplayer::EsEventListener::OnError,
2494                             handler_->eventlistener_, std::placeholders::_1,
2495                             std::placeholders::_2);
2496   auto msg = es_msg::Error::Make(error_code, listener,
2497                                  handler_->eventlistener_userdata_);
2498
2499   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2500   handler_->msg_queue_.push(std::move(msg));
2501   msg_mutex.unlock();
2502   handler_->msg_task_cv_.notify_one();
2503 }
2504
2505 void EsPlayer::TrackRendererEventListener::OnErrorMsg(
2506     const ErrorType& error_code, char* error_msg) {
2507   if (!handler_->eventlistener_) return;
2508   if (error_code == ErrorType::kResourceLimit) return;
2509
2510   std::vector<Track> activeTracks;
2511   track_util::GetActiveTrackList(handler_->track_, activeTracks);
2512
2513   Json::Value message;
2514   message["error_code"] = (int)error_code;
2515
2516   switch (error_code) {
2517     case ErrorType::kNotSupportedVideoCodec:
2518       for (const auto& track : activeTracks) {
2519         if (track.type == kTrackTypeVideo) {
2520           message["codec"] = track.mimetype.c_str();
2521           message["demux"] = track.container_type.c_str();
2522           char json_string[20] = {0};
2523           int nLen = 19;
2524           strncat(json_string, std::to_string(track.width).c_str(), nLen);
2525           nLen = sizeof(json_string) - strlen(json_string) - 1;
2526           if (nLen < 0) nLen = 0;
2527           strncat(json_string, "*", nLen);
2528           nLen = sizeof(json_string) - strlen(json_string) - 1;
2529           if (nLen < 0) nLen = 0;
2530           strncat(json_string, std::to_string(track.height).c_str(), nLen);
2531           message["resolution"] = json_string;
2532           memset(json_string, 0, sizeof(json_string));
2533           nLen = 19;
2534           strncat(json_string, std::to_string(track.framerate_num).c_str(),
2535                   nLen);
2536           nLen = sizeof(json_string) - strlen(json_string) - 1;
2537           if (nLen < 0) nLen = 0;
2538           strncat(json_string, "/", nLen);
2539           nLen = sizeof(json_string) - strlen(json_string) - 1;
2540           if (nLen < 0) nLen = 0;
2541           strncat(json_string, std::to_string(track.framerate_den).c_str(),
2542                   nLen);
2543           message["fps"] = json_string;
2544           message["detail_info"] = error_msg;
2545           break;
2546         }
2547       }
2548       break;
2549     case ErrorType::kNotSupportedAudioCodec:
2550
2551       break;
2552     default:
2553       break;
2554   }
2555
2556   Json::FastWriter writer;
2557   std::string str = writer.write(message);
2558   LOG_INFO_P(handler_, "error message: %s", str.c_str());
2559
2560   auto listener = std::bind(&esplusplayer::EsEventListener::OnErrorMsg,
2561                             handler_->eventlistener_, std::placeholders::_1,
2562                             std::placeholders::_2, std::placeholders::_3);
2563   auto msg =
2564       es_msg::ErrorMsg::Make(error_code, str.c_str(), str.size(), listener,
2565                              handler_->eventlistener_userdata_);
2566
2567   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2568   handler_->msg_queue_.push(std::move(msg));
2569   msg_mutex.unlock();
2570   handler_->msg_task_cv_.notify_one();
2571 }
2572 // LCOV_EXCL_STOP
2573
2574 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
2575     const TrackType& type) {
2576   LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
2577              (type == kTrackTypeAudio) ? "audio" : "video");
2578
2579   handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
2580
2581   auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToPrepare,
2582                             handler_->eventlistener_, std::placeholders::_1,
2583                             std::placeholders::_2);
2584   StreamType stream_type = internal::ConvertToStreamType(type);
2585   auto msg = es_msg::ReadyToPrepare::Make(stream_type, listener,
2586                                           handler_->eventlistener_userdata_);
2587   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2588   handler_->msg_queue_.push(std::move(msg));
2589   msg_mutex.unlock();
2590   handler_->msg_task_cv_.notify_one();
2591 }
2592
2593 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
2594   uint64_t offset = handler_->need_data_[type].seek_offset;
2595
2596   LOG_INFO("%p, OnReadyToSeek [%s] offset [%" PRId64 "]", handler_,
2597            (type == kTrackTypeAudio) ? "audio" : "video", offset);
2598
2599   handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
2600   handler_->need_data_[type].seek_offset = 0;
2601
2602   auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToSeek,
2603                             handler_->eventlistener_, std::placeholders::_1,
2604                             std::placeholders::_2, std::placeholders::_3);
2605   StreamType stream_type = internal::ConvertToStreamType(type);
2606   handler_->es_packet_logger_.ResetLog(stream_type);
2607   auto msg = es_msg::ReadyToSeek::Make(stream_type, offset, listener,
2608                                        handler_->eventlistener_userdata_);
2609   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2610   handler_->msg_queue_.push(std::move(msg));
2611   msg_mutex.unlock();
2612   handler_->msg_task_cv_.notify_one();
2613 }
2614
2615 void EsPlayer::TrackRendererEventListener::BufferStatus_(
2616     const TrackType& type, const BufferStatus& status) {
2617   uint64_t byte_size, time_size;
2618   // LOG_INFO_P(handler_, "OnBufferStatus [%s] [%s]",
2619   //        (type == kTrackTypeAudio) ? "audio" : "video",
2620   //        (status == BufferStatus::kUnderrun) ? "underrun" : "overrun");
2621   handler_->GetSrcQueueCurrentSize_(type, &byte_size, &time_size);
2622   auto listener = std::bind(&esplusplayer::EsEventListener::OnBufferStatus,
2623                             handler_->eventlistener_, std::placeholders::_1,
2624                             std::placeholders::_2, std::placeholders::_3,
2625                             std::placeholders::_4, std::placeholders::_5);
2626   StreamType stream_type = internal::ConvertToStreamType(type);
2627   auto msg =
2628       es_msg::Bufferstatus::Make(stream_type, status, byte_size, time_size,
2629                                  listener, handler_->eventlistener_userdata_);
2630   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2631   handler_->msg_queue_.push(std::move(msg));
2632   msg_mutex.unlock();
2633   handler_->msg_task_cv_.notify_one();
2634 }
2635
2636 void EsPlayer::TrackRendererEventListener::OnBufferStatus(
2637     const TrackType& type, const BufferStatus& status) {
2638   if (!handler_->eventlistener_) return;
2639   if (internal::IsLowLatencyModeDisableAVSync(handler_->low_latency_mode_))
2640     return;
2641
2642   if (handler_->need_data_[type].mask == kNeedDataMaskByPrepare &&
2643       status == BufferStatus::kUnderrun) {
2644     ReadyToPrepare_(type);
2645   } else if (handler_->need_data_[type].mask == kNeedDataMaskBySeek &&
2646              status == BufferStatus::kUnderrun) {
2647     ReadyToSeek_(type);
2648   } else {
2649     BufferStatus_(type, status);
2650   }
2651 }
2652
2653 // LCOV_EXCL_START
2654 void EsPlayer::TrackRendererEventListener::OnMediaPacketGetTbmBufPtr(
2655     void** tbm_ptr, bool is_scale_change) {
2656   if (!handler_->eventlistener_) return;
2657
2658   handler_->eventlistener_->OnMediaPacketGetTbmBufPtr(tbm_ptr, is_scale_change);
2659 }
2660
2661 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
2662     const DecodedVideoPacket& packet) {
2663   if (!handler_->eventlistener_) return;
2664
2665   handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
2666 }
2667
2668 #ifdef USE_MIXER
2669 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoRawDecoded(
2670     const DecodedVideoRawModePacket& packet) {
2671   if (handler_->mixer_ticket_ == nullptr) return;
2672   const auto& data = packet.data;
2673   if (packet.type == DecodedVideoRawModePacketType::kPhysicalAddress) {
2674     DecodedRawInfo info;
2675     info.width = packet.width;
2676     info.height = packet.height;
2677     info.y_info.phyaddr = data.raw.y_phyaddr;
2678     info.y_info.viraddr = data.raw.y_viraddr;
2679     info.y_info.linesize = data.raw.y_linesize;
2680     info.uv_info.phyaddr = data.raw.uv_phyaddr;
2681     info.uv_info.viraddr = data.raw.uv_viraddr;
2682     info.uv_info.linesize = data.raw.uv_linesize;
2683     handler_->mixer_ticket_->Render(info);
2684   } else if (packet.type == DecodedVideoRawModePacketType::kTizenBuffer) {
2685     DecodedVideoKeyTypeInfo info;
2686     info.width = packet.width;
2687     info.height = packet.height;
2688     info.key = packet.data.tbm.key;
2689     handler_->mixer_ticket_->Render(info);
2690   }
2691 }
2692
2693 bool EsPlayer::MixerListener::OnAudioFocusChanged(bool active) {
2694   LOG_INFO_P(handler_, "focused [%d]", active);
2695   std::unique_lock<std::mutex> lock(handler_->audio_focus_m_);
2696   if (handler_->state_manager_.GetState() < EsState::kReady) {
2697     handler_->is_audio_focused_ = active;
2698     return true;
2699   }
2700   if (active) {
2701     Track activated_track;
2702     track_util::GetActiveTrack(handler_->track_, kTrackTypeAudio,
2703                                &activated_track);
2704     LOG_INFO_P(handler_, "Activate audio track");
2705     {
2706       std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2707       handler_->eos_status_ =
2708           internal::ResetEosStatus(kTrackTypeAudio, handler_->eos_status_);
2709     }
2710     return handler_->trackrenderer_->Activate(kTrackTypeAudio, activated_track);
2711   }
2712   LOG_INFO_P(handler_, "Deactivate audio track");
2713   handler_->is_audio_focused_ = false;
2714   {
2715     std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2716     handler_->eos_status_ |= EosStatus::kAudioEos;
2717   }
2718   return handler_->trackrenderer_->Deactivate(kTrackTypeAudio);
2719 }
2720
2721 bool EsPlayer::MixerListener::OnUpdateDisplayInfo(const DisplayInfo& cur_info,
2722                                                   DisplayInfo* new_info) {
2723   new_info->geometry = handler_->mixerticket_roi_;
2724   new_info->visible_status =
2725       handler_->is_visible_ ? VisibleStatus::kVisible : VisibleStatus::kHide;
2726   return true;
2727 }
2728 #endif  // USE_MIXER
2729 // LCOV_EXCL_STOP
2730
2731 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
2732                                                       const uint64_t offset) {
2733   if (!handler_->eventlistener_) return;
2734
2735   if (handler_->need_data_[type].mask != kNeedDataMaskByPrepare) {
2736     handler_->need_data_[type].mask |= kNeedDataMaskBySeek;
2737     handler_->need_data_[type].seek_offset = offset;
2738   }
2739 }
2740
2741 // LCOV_EXCL_START
2742 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
2743                                                                const int size) {
2744   if (size <= 0) return;
2745   if (!handler_->eventlistener_) return;
2746   auto listener = std::bind(&esplusplayer::EsEventListener::OnClosedCaptionData,
2747                             handler_->eventlistener_, std::placeholders::_1,
2748                             std::placeholders::_2, std::placeholders::_3);
2749   auto msg = es_msg::ClosedCaption::Make(data, size, listener,
2750                                          handler_->eventlistener_userdata_);
2751   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2752   handler_->msg_queue_.push(std::move(msg));
2753   msg_mutex.unlock();
2754   handler_->msg_task_cv_.notify_one();
2755 }
2756
2757 void EsPlayer::TrackRendererEventListener::OnFlushDone() {
2758   LOG_ENTER_P(handler_);
2759   if (!handler_->eventlistener_) return;
2760
2761   auto listener = std::bind(&esplusplayer::EsEventListener::OnFlushDone,
2762                             handler_->eventlistener_, std::placeholders::_1);
2763   auto msg =
2764       es_msg::FlushDone::Make(listener, handler_->eventlistener_userdata_);
2765   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2766   handler_->msg_queue_.push(std::move(msg));
2767   msg_mutex.unlock();
2768   handler_->msg_task_cv_.notify_one();
2769   LOG_LEAVE_P(handler_);
2770 }
2771
2772 void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
2773                                                    const EventMsg& msg_data) {
2774   if (!handler_->eventlistener_) return;
2775
2776   auto listener = std::bind(&esplusplayer::EsEventListener::OnEvent,
2777                             handler_->eventlistener_, std::placeholders::_1,
2778                             std::placeholders::_2, std::placeholders::_3);
2779   auto msg = es_msg::OnEvent::Make(event, msg_data, listener,
2780                                    handler_->eventlistener_userdata_);
2781   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2782   handler_->msg_queue_.push(std::move(msg));
2783   msg_mutex.unlock();
2784   handler_->msg_task_cv_.notify_one();
2785   LOG_LEAVE_P(handler_);
2786 }
2787 // LCOV_EXCL_STOP
2788
2789 void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
2790   LOG_ENTER_P(handler_);
2791   if (!handler_->eventlistener_) return;
2792   auto listener = std::bind(&esplusplayer::EsEventListener::OnFirstDecodingDone,
2793                             handler_->eventlistener_, std::placeholders::_1);
2794   auto msg = es_msg::FirstDecodingDone::Make(listener,
2795                                              handler_->eventlistener_userdata_);
2796   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2797   handler_->msg_queue_.push(std::move(msg));
2798   msg_mutex.unlock();
2799   handler_->msg_task_cv_.notify_one();
2800   LOG_LEAVE_P(handler_);
2801 }
2802
2803 void EsPlayer::TrackRendererEventListener::OnVideoDecoderUnderrun() {
2804   LOG_ENTER_P(handler_);
2805   if (!handler_->eventlistener_) return;
2806
2807   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2808       handler_->state_manager_.GetState() != EsState::kPaused) {
2809     return;
2810   }
2811
2812   auto listener =
2813       std::bind(&esplusplayer::EsEventListener::OnVideoDecoderUnderrun,
2814                 handler_->eventlistener_, std::placeholders::_1);
2815   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2816   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2817   handler_->msg_queue_.push(std::move(msg));
2818   msg_mutex.unlock();
2819   handler_->msg_task_cv_.notify_one();
2820   LOG_LEAVE_P(handler_);
2821 }
2822
2823 void EsPlayer::TrackRendererEventListener::OnVideoLatencyStatus(
2824     const LatencyStatus& latency_status) {
2825   LOG_ENTER_P(handler_);
2826   if (!handler_->eventlistener_) return;
2827
2828   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2829       handler_->state_manager_.GetState() != EsState::kPaused) {
2830     return;
2831   }
2832
2833   auto listener = std::bind(
2834       &esplusplayer::EsEventListener::OnVideoLatencyStatus,
2835       handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2836
2837   auto msg = es_msg::PacketLatencyStatus::Make(
2838       latency_status, listener, handler_->eventlistener_userdata_);
2839
2840   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2841   handler_->msg_queue_.push(std::move(msg));
2842   msg_mutex.unlock();
2843   handler_->msg_task_cv_.notify_one();
2844   LOG_LEAVE_P(handler_);
2845 }
2846
2847 void EsPlayer::TrackRendererEventListener::OnAudioLatencyStatus(
2848     const LatencyStatus& latency_status) {
2849   LOG_ENTER_P(handler_);
2850   if (!handler_->eventlistener_) return;
2851
2852   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2853       handler_->state_manager_.GetState() != EsState::kPaused) {
2854     return;
2855   }
2856
2857   auto listener = std::bind(
2858       &esplusplayer::EsEventListener::OnAudioLatencyStatus,
2859       handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2860
2861   auto msg = es_msg::PacketLatencyStatus::Make(
2862       latency_status, listener, handler_->eventlistener_userdata_);
2863
2864   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2865   handler_->msg_queue_.push(std::move(msg));
2866   msg_mutex.unlock();
2867   handler_->msg_task_cv_.notify_one();
2868   LOG_LEAVE_P(handler_);
2869 }
2870
2871 void EsPlayer::TrackRendererEventListener::OnVideoHighLatency() {
2872   LOG_ENTER_P(handler_);
2873   if (!handler_->eventlistener_) return;
2874
2875   auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoHighLatency,
2876                             handler_->eventlistener_, std::placeholders::_1);
2877
2878   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2879
2880   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2881   handler_->msg_queue_.push(std::move(msg));
2882   msg_mutex.unlock();
2883   handler_->msg_task_cv_.notify_one();
2884   LOG_LEAVE_P(handler_);
2885 }
2886
2887 // LCOV_EXCL_START
2888 void EsPlayer::TrackRendererEventListener::OnAudioHighLatency() {
2889   LOG_ENTER_P(handler_);
2890   if (!handler_->eventlistener_) return;
2891
2892   auto listener = std::bind(&esplusplayer::EsEventListener::OnAudioHighLatency,
2893                             handler_->eventlistener_, std::placeholders::_1);
2894
2895   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2896
2897   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2898   handler_->msg_queue_.push(std::move(msg));
2899   msg_mutex.unlock();
2900   handler_->msg_task_cv_.notify_one();
2901   LOG_LEAVE_P(handler_);
2902 }
2903
2904 void EsPlayer::TrackRendererEventListener::OnVideoFrameDropped(
2905     const uint64_t& count) {
2906   if (!handler_->eventlistener_) return;
2907
2908   handler_->eventlistener_->OnVideoFrameDropped(
2909       count, handler_->eventlistener_userdata_);
2910
2911 #if 0
2912
2913   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2914       handler_->state_manager_.GetState() != EsState::kPaused) {
2915     return;
2916   }
2917
2918   auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoFrameDropped,
2919                             handler_->eventlistener_, std::placeholders::_1,
2920                             std::placeholders::_2);
2921
2922   auto msg = es_msg::FrameDroppedCount::Make(
2923       count, listener, handler_->eventlistener_userdata_);
2924
2925   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2926   handler_->msg_queue_.push(std::move(msg));
2927   msg_mutex.unlock();
2928   handler_->msg_task_cv_.notify_one();
2929   LOG_LEAVE_P(handler_);
2930 #endif
2931 }
2932
2933 void EsPlayer::TrackRendererEventListener::OnDecoderInputBufferTime(
2934     const TrackType& type, const DecoderBufferTime& time) {
2935   if (!handler_->eventlistener_) return;
2936
2937   StreamType stream_type = internal::ConvertToStreamType(type);
2938   handler_->eventlistener_->OnDecoderInputBufferTime(stream_type, time);
2939 }
2940
2941 void EsPlayer::TrackRendererEventListener::OnDecoderOutputBufferTime(
2942     const TrackType& type, const DecoderBufferTime& time) {
2943   if (!handler_->eventlistener_) return;
2944
2945   StreamType stream_type = internal::ConvertToStreamType(type);
2946   handler_->eventlistener_->OnDecoderOutputBufferTime(stream_type, time);
2947 }
2948
2949 // LCOV_EXCL_STOP
2950
2951 bool EsPlayer::SetVideoScanType(const PlayerVideoScanType type) {
2952   LOG_ENTER_P(this);
2953   if (state_manager_.GetState() != EsState::kIdle) {
2954     LOG_ERROR_P(this, "Invalid State , current %d",
2955                 state_manager_.GetStateEnum());
2956     return false;
2957   }
2958   if (type == kPlayerVideoScanTypeProgressive) set_video_progressive_ = 1;
2959   return true;
2960 }
2961 bool EsPlayer::SetTimeUnitType(const PlayerTimeUnitType type) {
2962   LOG_ENTER_P(this);
2963   if (state_manager_.GetState() != EsState::kIdle) {
2964     LOG_ERROR_P(this, "Invalid State , current %d",
2965                 state_manager_.GetStateEnum());
2966     return false;
2967   }
2968   LOG_INFO_P(this, "PlayerTimeUnitType [%s]",
2969              (type == kPlayerTimeUnitTypeMs) ? "Ms" : "Us");
2970   time_unit_type = type;
2971   return true;
2972 }
2973
2974 bool EsPlayer::GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) {
2975   if (!time_in_milliseconds) return false;
2976   if (state_manager_.GetState() <= EsState::kReady) {
2977     *time_in_milliseconds = 0;
2978     return false;
2979   }
2980   return trackrenderer_->GetDecodingTime(type, time_in_milliseconds);
2981 }
2982
2983 bool EsPlayer::SetVideoStreamRotationInfo(const VideoRotation& rotation) {
2984   LOG_ENTER_P(this);
2985   if (state_manager_.GetState() < EsState::kIdle) {
2986     LOG_ERROR_P(this, "Invalid State , current %d",
2987                 state_manager_.GetStateEnum());
2988     return false;
2989   }
2990   video_rotate_ = rotation;
2991   return trackrenderer_->SetVideoStreamRotationInfo(rotation);
2992 }
2993
2994 bool EsPlayer::GetVideoStreamRotationInfo(VideoRotation* rotation) {
2995   LOG_ENTER_P(this);
2996   if (state_manager_.GetState() < EsState::kIdle) {
2997     LOG_ERROR_P(this, "Invalid State , current %d",
2998                 state_manager_.GetStateEnum());
2999     return false;
3000   }
3001   *rotation = video_rotate_;
3002   return true;
3003 }
3004
3005 bool EsPlayer::SetSimpleMixOutBufferLevel(
3006     const PlayerSimpleMixOutBufferLevel level) {
3007   if (state_manager_.GetState() == EsState::kNone) {
3008     LOG_ERROR_P(this, "Invalid State");
3009     return false;
3010   }
3011   int converted_level = 1;
3012   if (level == kPlayerSimpleMixOutBufferLow) {
3013     converted_level = 0;
3014   } else if (level == kPlayerSimpleMixOutBufferMid) {
3015     converted_level = 1;
3016   } else if (level == kPlayerSimpleMixOutBufferHigh) {
3017     converted_level = 2;
3018   }
3019
3020   return trackrenderer_->SetSimpleMixOutBufferLevel(converted_level);
3021 }
3022
3023 #ifndef TIZEN_FEATURE_PUBLIC
3024 kpi::EsCodecLoggerKeys EsPlayer::MakeKpiKeys_() {
3025   kpi::EsCodecLoggerKeys event_info;
3026   event_info.app_id = app_info_.id;
3027   if (submit_data_type_ == SubmitDataType::kCleanData) {
3028     event_info.is_clean = true;
3029   } else {
3030     event_info.is_clean = false;
3031     event_info.key_system = key_system_;
3032   }
3033
3034   for (const auto& track : track_) {
3035     if (track.type == kTrackTypeVideo) {
3036       event_info.v_codec = track.mimetype;
3037       event_info.v_codec_version = track.version;
3038       event_info.width = track.maxwidth;
3039       event_info.height = track.maxheight;
3040     } else if (track.type == kTrackTypeAudio) {
3041       event_info.a_codec = track.mimetype;
3042     }
3043   }
3044   return event_info;
3045 }
3046 #endif
3047
3048 void EsPlayer::InitValuesFromIni_() {
3049   force_audio_swdecoder_use_ = es_conf::ini_property["force_sw_audio_codec"];
3050   force_video_swdecoder_use_ = es_conf::ini_property["force_sw_video_codec"];
3051 }
3052
3053 #ifdef TIZEN_FEATURE_PUBLIC
3054 bool EsPlayer::EnableVideoHole(bool value) {
3055   if (state_manager_.GetState() < EsState::kIdle) {
3056     LOG_ERROR_P(this, "Invalid State , current %d",
3057                 state_manager_.GetStateEnum());
3058     return false;
3059   }
3060   return trackrenderer_->EnableVideoHole(value);
3061 }
3062
3063 bool EsPlayer::SetSoundStreamInfo(const sound_stream_info_h stream_info) {
3064   if (state_manager_.GetState() != EsState::kIdle) {
3065     LOG_ERROR_P(this, "Invalid State , current %d",
3066                 state_manager_.GetStateEnum());
3067     return false;
3068   }
3069   if (!stream_info) {
3070     LOG_ERROR_P(this, "stream_info is null");
3071     return false;
3072   }
3073   return trackrenderer_->SetSoundStreamInfo(stream_info);
3074 }
3075 #endif
3076
3077 namespace es_conf {
3078
3079 void LoadIniProperty(const Json::Value& root) {
3080   // clang-format off
3081   std::vector<std::string> booleanKeys {
3082       "generate_dot",
3083       "force_sw_audio_codec",
3084       "force_sw_video_codec",
3085       "fallback_to_sw_audio_codec",
3086       "fallback_to_sw_video_codec"
3087   };
3088   // clang-format on
3089   gst_util::GstInit(root);
3090   std::for_each(booleanKeys.begin(), booleanKeys.end(), [&](const auto& key) {
3091     es_conf::ini_property[key] = root.get(key, "").asBool();
3092     LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
3093   });
3094 }
3095
3096 bool LoadIniFile() {
3097   const char* path = esplusplayer_cfg::GetIniPath();
3098   LOG_INFO("path : %s", path);
3099   std::streampos size;
3100   char* buf = nullptr;
3101   std::ifstream file(path, std::ios::binary | std::ios::ate);
3102   if (file.is_open() == false) {
3103     gst_util::GstInit();
3104     LOG_ERROR("Can't open file !!");
3105     return false;
3106   }
3107   BOOST_SCOPE_EXIT(&file) { file.close(); }
3108   BOOST_SCOPE_EXIT_END
3109
3110   size = file.tellg();
3111   if (size <= 0) {
3112     LOG_ERROR("Wrong file size");
3113     return false;
3114   }
3115   size += 1;
3116   buf = static_cast<char*>(calloc(size, sizeof(char)));
3117   if (buf == nullptr) {
3118     LOG_ERROR("Fail to calloc buf");
3119     return false;
3120   }
3121   BOOST_SCOPE_EXIT(&buf) {
3122     if (buf) free(buf);
3123   }
3124   BOOST_SCOPE_EXIT_END
3125
3126   file.seekg(0, std::ios::beg);
3127   file.read(buf, size);
3128
3129   std::string config = buf;
3130   Json::Value root;
3131   Json::Reader reader;
3132   if (!reader.parse(config, root)) {
3133     LOG_ERROR("Fail to parse configuration file %s",
3134               (reader.getFormatedErrorMessages()).c_str());
3135     return false;
3136   }
3137
3138   es_conf::LoadIniProperty(root);
3139   return true;
3140 }
3141
3142 }  // namespace es_conf
3143
3144 }  // namespace esplusplayer