Merge pull request #111 from review-bot/reform/tizen-vault-esplusplayer-c/c++-default...
[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 }
1341
1342 void EsPlayer::ResetContextForStop_() {
1343   for (int i = 0; i < kTrackTypeMax; ++i) {
1344     need_data_[i].mask = kNeedDataMaskNone;
1345     need_data_[i].seek_offset = 0;
1346   }
1347   {
1348     std::lock_guard<std::mutex> lock(eos_mutex_);
1349     eos_status_ = EosStatus::kAllEos;
1350   }
1351   current_playback_rate_ = 1.0;
1352   current_audio_mute_ = false;
1353 }
1354
1355 void EsPlayer::GetSrcQueueCurrentSize_(const TrackType& type,
1356                                        uint64_t* byte_size,
1357                                        uint64_t* time_size) {
1358   boost::any byte_size_, time_size_;
1359   if (type == TrackType::kTrackTypeVideo) {
1360     trackrenderer_->GetAttribute(
1361         TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelByte,
1362         &byte_size_);
1363     trackrenderer_->GetAttribute(
1364         TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
1365         &time_size_);
1366   } else if (type == TrackType::kTrackTypeAudio) {
1367     trackrenderer_->GetAttribute(
1368         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
1369         &byte_size_);
1370     trackrenderer_->GetAttribute(
1371         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
1372         &time_size_);
1373   } else
1374     return;
1375   *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
1376   *time_size = boost::any_cast<std::uint64_t>(time_size_);
1377   if (time_unit_type == kPlayerTimeUnitTypeMs)
1378     *time_size = util::ConvertNsToMs(*time_size);
1379   else if (time_unit_type == kPlayerTimeUnitTypeUs)
1380     *time_size = util::ConvertNsToUs(*time_size);
1381 }
1382
1383 GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
1384                                    MakeBufferStatus* status) {
1385   std::shared_ptr<char> buffer = packet->GetBuffer();
1386   uint32_t size = packet->GetSize();
1387   if (packet->IsEosPacket()) {
1388     *status = MakeBufferStatus::kEos;
1389     return nullptr;
1390   }
1391   GstBuffer* gstbuffer = gst_buffer_new_and_alloc(size);
1392   if (!gstbuffer) {
1393     *status = MakeBufferStatus::kOutOfMemory;
1394     return nullptr;
1395   }
1396   if (buffer != nullptr) {
1397     GstMapInfo map;
1398     gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
1399     memcpy(map.data, buffer.get(), size);
1400     gst_buffer_unmap(gstbuffer, &map);
1401   }
1402
1403   uint64_t pts = packet->GetPts();
1404   uint64_t duration = packet->GetDuration();
1405   /* if pts or duration are -1(=GST_CLOCK_TIME_NONE), some of the elements don't
1406    * adjust the buffer. */
1407   if (time_unit_type == kPlayerTimeUnitTypeMs) {
1408     GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1409                                     ? GST_CLOCK_TIME_NONE
1410                                     : (GstClockTime)util::ConvertMsToNs(pts);
1411     GST_BUFFER_DURATION(gstbuffer) =
1412         (duration == GST_CLOCK_TIME_NONE)
1413             ? GST_CLOCK_TIME_NONE
1414             : (GstClockTime)util::ConvertMsToNs(duration);
1415   } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1416     GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
1417                                     ? GST_CLOCK_TIME_NONE
1418                                     : (GstClockTime)util::ConvertUsToNs(pts);
1419     GST_BUFFER_DURATION(gstbuffer) =
1420         (duration == GST_CLOCK_TIME_NONE)
1421             ? GST_CLOCK_TIME_NONE
1422             : (GstClockTime)util::ConvertUsToNs(duration);
1423   }
1424   uint32_t hdr10p_size = packet->GetHdr10pSize();
1425   std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
1426
1427   if (hdr10p_size > 0 && hdr10p_metadata != nullptr) {
1428     guint32* blockadditional_size = (guint32*)g_malloc(sizeof(uint32_t));
1429     *blockadditional_size = hdr10p_size;
1430     gst_mini_object_set_qdata(
1431         GST_MINI_OBJECT(gstbuffer),
1432         g_quark_from_static_string("matroska_blockadditional_size"),
1433         blockadditional_size, g_free);
1434
1435     /* blockadditiona_data : the data sent to omx, size (4 bytes) + metadata */
1436     guint8* blockadditional_data =
1437         (guint8*)g_malloc(((*blockadditional_size) + 4) * sizeof(guint8));
1438     memcpy(blockadditional_data, blockadditional_size, sizeof(uint32_t));
1439     memcpy(blockadditional_data + 4, hdr10p_metadata.get(),
1440            (*blockadditional_size));
1441     gst_mini_object_set_qdata(
1442         GST_MINI_OBJECT(gstbuffer),
1443         g_quark_from_static_string("matroska_blockadditional_info"),
1444         blockadditional_data, g_free);
1445   }
1446   *status = MakeBufferStatus::kSuccess;
1447   return gstbuffer;
1448 }
1449
1450 PacketSubmitStatus EsPlayer::SubmitEosPacket_(const TrackType& type) {
1451   PacketSubmitStatus submitstate = PacketSubmitStatus::kSuccess;
1452   {
1453     std::lock_guard<std::mutex> lock(eos_mutex_);
1454     switch (type) {
1455       case kTrackTypeAudio:
1456         eos_status_ |= EosStatus::kAudioEos;
1457         break;
1458       case kTrackTypeVideo:
1459         eos_status_ |= EosStatus::kVideoEos;
1460         break;
1461       default:
1462         break;
1463     }
1464     if (eos_status_ != EosStatus::kAllEos) {
1465       return submitstate;
1466     }
1467   }
1468   for (int tracktype = kTrackTypeAudio; tracktype < kTrackTypeMax;
1469        ++tracktype) {
1470     auto inbuffer =
1471         DecoderInputBuffer::Create(static_cast<TrackType>(tracktype));
1472     if (!trackrenderer_->SubmitPacket2(inbuffer, nullptr)) {
1473       std::lock_guard<std::mutex> lock(eos_mutex_);
1474       eos_status_ = EosStatus::kAllEos;
1475       submitstate = PacketSubmitStatus::kNotPrepared;
1476       return submitstate;
1477     }
1478   }
1479   return submitstate;
1480 }
1481
1482 void EsPlayer::UnsetTzQdata_(const DecoderInputBufferPtr& buffer) {
1483   const GstBuffer* gstbuf = buffer->Get();
1484   if (!gstbuf) return;
1485   GstStructure* tzqdata = GST_STRUCTURE(gst_mini_object_steal_qdata(
1486       GST_MINI_OBJECT(gstbuf), g_quark_from_static_string("GstTzHandleData")));
1487   if (tzqdata) gst_structure_free(tzqdata);
1488 }
1489
1490 PacketSubmitStatus EsPlayer::SubmitDecoderInputBuffer_(
1491     const DecoderInputBufferPtr& buffer) {
1492   PacketSubmitStatus status = PacketSubmitStatus::kSuccess;
1493   TrackRendererAdapter::SubmitStatus submitstate =
1494       TrackRendererAdapter::SubmitStatus::kSuccess;
1495   trackrenderer_->SubmitPacket2(buffer, &submitstate);
1496
1497   switch (submitstate) {
1498     case TrackRendererAdapter::SubmitStatus::kSuccess:
1499     case TrackRendererAdapter::SubmitStatus::kDrop:
1500       status = PacketSubmitStatus::kSuccess;
1501       break;
1502     case TrackRendererAdapter::SubmitStatus::kFull:
1503       UnsetTzQdata_(buffer);
1504       trackrenderer_event_listener_->OnBufferStatus(buffer->GetType(),
1505                                                     BufferStatus::kOverrun);
1506       status = PacketSubmitStatus::kFull;
1507       break;
1508     default:
1509       UnsetTzQdata_(buffer);
1510       status = PacketSubmitStatus::kNotPrepared;
1511       break;
1512   }
1513   return status;
1514 }
1515
1516 // LCOV_EXCL_START
1517 void EsPlayer::MakeGstBufferForTzHandle_(GstBuffer* gstbuffer,
1518                                          const TrackType& type,
1519                                          const uint32_t& tz_handle,
1520                                          const uint32_t& packet_size) {
1521   GstStructure* gst_tz_handle_data_structure =
1522       gst_structure_new("GstTzHandleData", "packet_handle", G_TYPE_UINT,
1523                         static_cast<guint32>(tz_handle), "packet_size",
1524                         G_TYPE_UINT, static_cast<guint32>(packet_size),
1525                         "secure", G_TYPE_BOOLEAN, true, nullptr);
1526   gst_mini_object_set_qdata(
1527       GST_MINI_OBJECT(gstbuffer), g_quark_from_string("GstTzHandleData"),
1528       gst_tz_handle_data_structure, (GDestroyNotify)gst_structure_free);
1529
1530   if (type == kTrackTypeAudio) {
1531     Track audio_track;
1532     bool has_active_audio_track =
1533         track_util::GetActiveTrack(track_, kTrackTypeAudio, &audio_track);
1534     if (has_active_audio_track) {
1535       GstStructure* audio_info_structure =
1536           gst_structure_new("AudioInfo", "mime_type", G_TYPE_STRING,
1537                             audio_track.mimetype.c_str(), nullptr);
1538       gst_mini_object_set_qdata(
1539           GST_MINI_OBJECT(gstbuffer), g_quark_from_string("AudioInfo"),
1540           audio_info_structure, (GDestroyNotify)gst_structure_free);
1541     }
1542   }
1543 }
1544
1545 void EsPlayer::MakeGstBufferForEncryptedPacket_(
1546     GstBuffer* gstbuffer, const EsPacketPtr& packet,
1547     const drm::EsPlayerEncryptedInfo& drm_info) {
1548   if (drm_info.handle == 0) return;
1549   auto serialized_drm_info_ptr = esplayer_drm::Serialize(packet, drm_info);
1550   GstStructure* gst_drm_info_structure =
1551       gst_structure_new("drm_info", "drm_specific_info", G_TYPE_BYTES,
1552                         serialized_drm_info_ptr.get(), nullptr);
1553   if (gst_drm_info_structure) {
1554     gst_mini_object_set_qdata(
1555         GST_MINI_OBJECT(gstbuffer), g_quark_from_static_string("drm_info"),
1556         gst_drm_info_structure, (GDestroyNotify)gst_structure_free);
1557   }
1558 }
1559 // LCOV_EXCL_STOP
1560
1561 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
1562                                                  SubmitPacketOperator op) {
1563   if (state_manager_.GetState() < EsState::kIdle) {
1564     return PacketSubmitStatus::kNotPrepared;
1565   }
1566   if (!packet) return PacketSubmitStatus::kInvalidPacket;
1567
1568   TrackType type = static_cast<TrackType>(packet->GetType());
1569   Track activated_track;
1570   if (!track_util::GetActiveTrack(track_, type, &activated_track))
1571     return PacketSubmitStatus::kInvalidPacket;
1572
1573   if (state_manager_.GetState() == EsState::kPaused ||
1574       state_manager_.GetState() == EsState::kReady) {
1575     internal::AppsrcQueueSizeOption byte_based, time_based;
1576     switch (type) {
1577       case kTrackTypeAudio:
1578         byte_based.max_size = src_queue_size_.kMaxByteOfAudioSrcQueue;
1579         time_based.max_size = src_queue_size_.kMaxTimeOfAudioSrcQueue;
1580         byte_based.threshold = src_queue_size_.kMinByteThresholdOfAudioSrcQueue;
1581         time_based.threshold = src_queue_size_.kMinTimeThresholdOfAudioSrcQueue;
1582         break;
1583       case kTrackTypeVideo:
1584         byte_based.max_size = src_queue_size_.kMaxByteOfVideoSrcQueue;
1585         time_based.max_size = src_queue_size_.kMaxTimeOfVideoSrcQueue;
1586         byte_based.threshold = src_queue_size_.kMinByteThresholdOfVideoSrcQueue;
1587         time_based.threshold = src_queue_size_.kMinTimeThresholdOfVideoSrcQueue;
1588         break;
1589       default:
1590         break;
1591     }
1592     GetSrcQueueCurrentSize_(type, &(byte_based.current_size),
1593                             &(time_based.current_size));
1594     if (internal::IsUnderRun(byte_based, time_based))
1595       trackrenderer_event_listener_->OnBufferStatus(type,
1596                                                     BufferStatus::kUnderrun);
1597   }
1598
1599   es_packet_logger_.StorePacketInfo(packet);
1600   es_packet_logger_.PrintStoredPacketInfo(packet->GetType());
1601
1602   MakeBufferStatus make_buffer_status;
1603   GstBuffer* gstbuffer = GetGstBuffer_(packet, &make_buffer_status);
1604   if (!gstbuffer) {
1605     if (make_buffer_status == MakeBufferStatus::kEos)
1606       return SubmitEosPacket_(type);
1607     else if (make_buffer_status == MakeBufferStatus::kOutOfMemory)
1608       return PacketSubmitStatus::kOutOfMemory;
1609   }
1610   if (op != nullptr) {
1611     PacketSubmitStatus op_status = op(gstbuffer);
1612     if (op_status != PacketSubmitStatus::kSuccess) {
1613       return op_status;
1614     }
1615   }
1616
1617   auto inbuffer = DecoderInputBuffer::Create(type, 0, gstbuffer);
1618   gst_buffer_unref(gstbuffer);
1619
1620   if (packet->HasMatroskaColorInfo()) {
1621     std::string color_info_str =
1622         util::GetStringFromMatroskaColor(packet->GetMatroskaColorInfo());
1623     if (trackrenderer_->SetMatroskaColorInfo(color_info_str) == false)
1624       return PacketSubmitStatus::kNotPrepared;
1625   }
1626
1627   return SubmitDecoderInputBuffer_(inbuffer);
1628 }
1629
1630 PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
1631   std::lock_guard<std::mutex> lk(submit_mutex_);
1632   return SubmitPacketCommon_(packet, nullptr);
1633 }
1634
1635 // LCOV_EXCL_START
1636 PacketSubmitStatus EsPlayer::SubmitTrustZonePacket(const EsPacketPtr& packet,
1637                                                    uint32_t tz_handle) {
1638   std::lock_guard<std::mutex> lk(submit_mutex_);
1639   if (submit_data_type_ != SubmitDataType::kTrustZoneData)
1640     return PacketSubmitStatus::kInvalidPacket;
1641   auto submitpacket_op = [this, &tz_handle,
1642                           &packet](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1643     if (tz_handle > 0) {
1644       TrackType type = static_cast<TrackType>(packet->GetType());
1645       uint32_t packet_size = packet->GetSize();
1646       MakeGstBufferForTzHandle_(gstbuffer, type, tz_handle, packet_size);
1647     }
1648     return PacketSubmitStatus::kSuccess;
1649   };
1650   return SubmitPacketCommon_(packet, submitpacket_op);
1651 }
1652
1653 PacketSubmitStatus EsPlayer::SubmitEncryptedPacket(
1654     const EsPacketPtr& packet, const drm::EsPlayerEncryptedInfo& drm_info) {
1655   std::lock_guard<std::mutex> lk(submit_mutex_);
1656   if (submit_data_type_ != SubmitDataType::kEncryptedData)
1657     return PacketSubmitStatus::kInvalidPacket;
1658   auto submitpacket_op =
1659       [this, &packet, &drm_info](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1660     MakeGstBufferForEncryptedPacket_(gstbuffer, packet, drm_info);
1661     return PacketSubmitStatus::kSuccess;
1662   };
1663   return SubmitPacketCommon_(packet, submitpacket_op);
1664 }
1665 // LCOV_EXCL_STOP
1666
1667 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
1668
1669 bool EsPlayer::GetPlayingTime(uint64_t* time) {
1670   if (!time) return false;
1671   if (state_manager_.GetState() <= EsState::kReady) {
1672     *time = 0;
1673     return false;
1674   }
1675   return trackrenderer_->GetPlayingTime(time);
1676 }
1677
1678 bool EsPlayer::SetAudioMute(bool is_mute) {
1679   if (state_manager_.GetState() < EsState::kIdle) {
1680     LOG_ERROR_P(this, "Invalid State , current %d",
1681                 state_manager_.GetStateEnum());
1682     return false;
1683   }
1684   return trackrenderer_->SetAudioMute(is_mute);
1685 }
1686
1687 bool EsPlayer::SetVideoFrameBufferType(DecodedVideoFrameBufferType type) {
1688   if ((state_manager_.GetState() != EsState::kIdle &&
1689        type != DecodedVideoFrameBufferType::kScale) ||
1690       (state_manager_.GetState() < EsState::kIdle &&
1691        type == DecodedVideoFrameBufferType::kScale)) {
1692     LOG_ERROR_P(this, "Invalid State , current %d",
1693                 state_manager_.GetStateEnum());
1694     return false;
1695   }
1696   if (type == DecodedVideoFrameBufferType::kScale &&
1697       video_codec_type_ == kPlayerVideoCodecTypeSW) {
1698     LOG_ERROR_P(this, "kScale is not supportted when using sw video decoder");
1699     return false;
1700   }
1701   trackrenderer_->SetVideoFrameBufferType(
1702       VideoFrameTypeStrategyPtr(new DefaultVideoFrameTypeStrategy(type)));
1703   vidoe_frame_buffer_type_ = type;
1704   return true;
1705 }
1706
1707 bool EsPlayer::SetVideoFrameBufferScaleResolution(
1708     const uint32_t& target_width, const uint32_t& target_height) {
1709   if (state_manager_.GetState() < EsState::kIdle) {
1710     LOG_ERROR_P(this, "Invalid State , current %d",
1711                 state_manager_.GetStateEnum());
1712     return false;
1713   }
1714
1715   return trackrenderer_->SetVideoFrameBufferScaleResolution(target_width,
1716                                                             target_height);
1717 }
1718
1719 bool EsPlayer::SetDecodedVideoFrameRate(const Rational& request_framerate) {
1720   if (state_manager_.GetState() < EsState::kIdle) {
1721     LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
1722     return false;
1723   }
1724
1725   return trackrenderer_->SetDecodedVideoFrameRate(request_framerate);
1726 }
1727
1728 void EsPlayer::RegisterListener(EsEventListener* listener,
1729                                 EsEventListener::UserData userdata) {
1730   // assert(listener); // allow unregister by setting nullptr
1731   assert(!eventlistener_);
1732   eventlistener_ = listener;
1733   eventlistener_userdata_ = userdata;
1734 }
1735
1736 bool EsPlayer::GetAdaptiveInfo(void* padaptive_info,
1737                                const PlayerAdaptiveInfo& adaptive_type) {
1738   if (!padaptive_info || adaptive_type <= PlayerAdaptiveInfo::kMinType ||
1739       adaptive_type >= PlayerAdaptiveInfo::kMaxType)
1740     return false;
1741   switch (adaptive_type) {
1742     case PlayerAdaptiveInfo::kVideoDroppedFrames:
1743       if (state_manager_.GetState() < EsState::kReady) {
1744         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1745         return false;
1746       }
1747       return trackrenderer_->GetDroppedFrames(padaptive_info);
1748     case PlayerAdaptiveInfo::kDroppedVideoFramesForCatchup:
1749       if (state_manager_.GetState() < EsState::kReady) {
1750         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1751         return false;
1752       }
1753       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeVideo,
1754                                                         padaptive_info);
1755     case PlayerAdaptiveInfo::kDroppedAudioFramesForCatchup:
1756       if (state_manager_.GetState() < EsState::kReady) {
1757         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1758         return false;
1759       }
1760       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeAudio,
1761                                                         padaptive_info);
1762     default:
1763       break;
1764   }
1765   return false;
1766 }
1767
1768 bool EsPlayer::SetVolume(const int& volume) {
1769   if (volume < internal::kVolumeMin || volume > internal::kVolumeMax) {
1770     LOG_ERROR_P(this, "Invalid volume level %d", volume);
1771     return false;
1772   }
1773   if (state_manager_.GetState() < EsState::kIdle) {
1774     LOG_ERROR_P(this, "Invalid State , current %d",
1775                 state_manager_.GetStateEnum());
1776     return false;
1777   }
1778   return trackrenderer_->SetVolume(volume);
1779 }
1780
1781 bool EsPlayer::GetVolume(int* volume) {
1782   if (state_manager_.GetState() < EsState::kIdle) {
1783     LOG_ERROR_P(this, "Invalid State , current %d",
1784                 state_manager_.GetStateEnum());
1785     return false;
1786   }
1787   return trackrenderer_->GetVolume(volume);
1788 }
1789
1790 bool EsPlayer::Flush(const StreamType& type) {
1791   if (state_manager_.GetState() <= EsState::kIdle) {
1792     LOG_ERROR_P(this, "Invalid State , current %d",
1793                 state_manager_.GetStateEnum());
1794     return false;
1795   }
1796   eos_status_ =
1797       internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
1798   es_packet_logger_.ResetLog(type);
1799   return trackrenderer_->Flush(type);
1800 }
1801
1802 bool EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
1803   TrackType track_type = kTrackTypeMax;
1804   switch (option) {
1805     case BufferOption::kBufferAudioMaxByteSize:      /* FALL THROUGH */
1806     case BufferOption::kBufferAudioMinByteThreshold: /* FALL THROUGH */
1807     case BufferOption::kBufferAudioMaxTimeSize:      /* FALL THROUGH */
1808     case BufferOption::kBufferAudioMinTimeThreshold:
1809       track_type = kTrackTypeAudio;
1810       break;
1811     case BufferOption::kBufferVideoMaxByteSize:      /* FALL THROUGH */
1812     case BufferOption::kBufferVideoMinByteThreshold: /* FALL THROUGH */
1813     case BufferOption::kBufferVideoMaxTimeSize:      /* FALL THROUGH */
1814     case BufferOption::kBufferVideoMinTimeThreshold:
1815       track_type = kTrackTypeVideo;
1816       break;
1817     default:
1818       break;
1819   }
1820   if (track_type == kTrackTypeMax) {
1821     LOG_ERROR_P(this, "Invalid option!!!");
1822     return false;
1823   }
1824
1825   Track activated_track;
1826   bool is_activated =
1827       track_util::GetActiveTrack(track_, track_type, &activated_track);
1828   EsState state = state_manager_.GetState();
1829   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_activated)) {
1830     LOG_ERROR_P(this, "Invalid State [state:%d] or stream is activated [%d],",
1831                 state_manager_.GetStateEnum(), is_activated);
1832     return false;
1833   }
1834
1835   switch (option) {
1836     case BufferOption::kBufferAudioMaxByteSize:
1837       src_queue_size_.kMaxByteOfAudioSrcQueue = size;
1838       break;
1839     case BufferOption::kBufferVideoMaxByteSize:
1840       src_queue_size_.kMaxByteOfVideoSrcQueue = size;
1841       break;
1842     case BufferOption::kBufferAudioMinByteThreshold:
1843       src_queue_size_.kMinByteThresholdOfAudioSrcQueue =
1844           static_cast<uint32_t>(size);
1845       break;
1846     case BufferOption::kBufferVideoMinByteThreshold:
1847       src_queue_size_.kMinByteThresholdOfVideoSrcQueue =
1848           static_cast<uint32_t>(size);
1849       break;
1850     case BufferOption::kBufferAudioMaxTimeSize:
1851       src_queue_size_.kMaxTimeOfAudioSrcQueue = size;
1852       break;
1853     case BufferOption::kBufferVideoMaxTimeSize:
1854       src_queue_size_.kMaxTimeOfVideoSrcQueue = size;
1855       break;
1856     case BufferOption::kBufferAudioMinTimeThreshold:
1857       src_queue_size_.kMinTimeThresholdOfAudioSrcQueue =
1858           static_cast<uint32_t>(size);
1859       break;
1860     case BufferOption::kBufferVideoMinTimeThreshold:
1861       src_queue_size_.kMinTimeThresholdOfVideoSrcQueue =
1862           static_cast<uint32_t>(size);
1863       break;
1864     default:
1865       LOG_ERROR_P(this, "Invalid option!!!");
1866       break;
1867   }
1868   return true;
1869 }
1870
1871 bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
1872   if (state_manager_.GetState() != EsState::kIdle) {
1873     LOG_ERROR_P(this, "Invalid State , current %d",
1874                 state_manager_.GetStateEnum());
1875     return false;
1876   }
1877   if (true == internal::IsExclusiveLowLatencyMode(low_latency_mode_, mode)) {
1878     LOG_ERROR_P(this, "Invalid Mode , current 0x%x, set 0x%x",
1879                 static_cast<std::uint32_t>(low_latency_mode_),
1880                 static_cast<std::uint32_t>(mode));
1881     return false;
1882   }
1883   low_latency_mode_ |= static_cast<std::uint32_t>(mode);
1884   return true;
1885 }
1886
1887 bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
1888   if (state_manager_.GetState() < EsState::kReady) {
1889     LOG_ERROR_P(this, "Invalid State , current %d",
1890                 state_manager_.GetStateEnum());
1891     return false;
1892   }
1893   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1894     LOG_ERROR_P(this,
1895                 "low latency mode have to be set except disable_sync mode");
1896     return false;
1897   }
1898   std::int64_t ns_unit = 0;
1899   if (time_unit_type == kPlayerTimeUnitTypeMs)
1900     ns_unit = 1000000;
1901   else if (time_unit_type == kPlayerTimeUnitTypeUs)
1902     ns_unit = 1000;
1903   if ((offset * ns_unit > G_MAXINT64) || (offset * ns_unit < G_MININT64)) {
1904     LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
1905               "] * 1000000 < G_MAXINT64",
1906               this, offset);
1907     return false;
1908   }
1909   if (type == StreamType::kMax) return false;
1910   if (time_unit_type == kPlayerTimeUnitTypeMs) {
1911     if (type == StreamType::kAudio)
1912       trackrenderer_->SetAttribute(
1913           TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1914           util::ConvertMsToNs(offset));
1915     else if (type == StreamType::kVideo)
1916       trackrenderer_->SetAttribute(
1917           TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1918           util::ConvertMsToNs(offset));
1919   } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
1920     if (type == StreamType::kAudio)
1921       trackrenderer_->SetAttribute(
1922           TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1923           util::ConvertUsToNs(offset));
1924     else if (type == StreamType::kVideo)
1925       trackrenderer_->SetAttribute(
1926           TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1927           util::ConvertUsToNs(offset));
1928   }
1929   return true;
1930 }
1931
1932 bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
1933   if (state_manager_.GetState() < EsState::kReady) {
1934     LOG_ERROR_P(this, "Invalid State , current %d",
1935                 state_manager_.GetStateEnum());
1936     return false;
1937   }
1938   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1939     LOG_ERROR_P(this, "low latency mode have to be set");
1940     return false;
1941   }
1942   if (type == StreamType::kMax) return false;
1943   boost::any off_set;
1944   if (type == StreamType::kAudio)
1945     trackrenderer_->GetAttribute(
1946         TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
1947   else if (type == StreamType::kVideo)
1948     trackrenderer_->GetAttribute(
1949         TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
1950
1951   *offset = boost::any_cast<std::int64_t>(off_set);
1952   if (time_unit_type == kPlayerTimeUnitTypeMs)
1953     *offset = util::ConvertNsToMs(*offset);
1954   else if (time_unit_type == kPlayerTimeUnitTypeUs)
1955     *offset = util::ConvertNsToUs(*offset);
1956   return true;
1957 }
1958
1959 bool EsPlayer::SetVideoFramePeekMode() {
1960   if (state_manager_.GetState() != EsState::kIdle) {
1961     LOG_ERROR_P(this, "Invalid State , current %d",
1962                 state_manager_.GetStateEnum());
1963     return false;
1964   }
1965   constexpr std::uint32_t peek_mode_on = 1;
1966   video_frame_peek_mode_ = peek_mode_on;
1967   return true;
1968 }
1969
1970 bool EsPlayer::RenderVideoFrame() {
1971   if (!video_frame_peek_mode_) return false;
1972   if (state_manager_.GetState() == EsState::kReady ||
1973       state_manager_.GetState() == EsState::kPaused) {
1974     trackrenderer_->RenderVideoFrame();
1975     return true;
1976   }
1977   LOG_ERROR_P(this, "Invalid State , current %d",
1978               state_manager_.GetStateEnum());
1979   return false;
1980 }
1981
1982 bool EsPlayer::SetUnlimitedMaxBufferMode() {
1983   if (state_manager_.GetState() != EsState::kIdle) {
1984     LOG_ERROR_P(this, "Invalid State , current %d",
1985                 state_manager_.GetStateEnum());
1986     return false;
1987   }
1988   constexpr std::uint32_t unlimited_max_buffer_mode_on = 1;
1989   unlimited_max_buffer_mode_ = unlimited_max_buffer_mode_on;
1990   return true;
1991 }
1992
1993 ErrorType EsPlayer::SetFmmMode() {
1994   EsState state = state_manager_.GetState();
1995   LOG_ENTER_P(this);
1996   if (state < EsState::kIdle) {
1997     LOG_ERROR_P(this, "Invalid State , current %d",
1998                 state_manager_.GetStateEnum());
1999     return ErrorType::kInvalidState;
2000   }
2001
2002   int onoff = 0;
2003   ErrorType ret = ErrorType::kNone;
2004   if (trackrenderer_->GetFmmAutoMode(&onoff) == false) {
2005     return ErrorType::kInvalidOperation;
2006   }
2007
2008   enum {
2009     FMM_AUTO_OFF = 0,
2010     FMM_AUTO_ON = 1,
2011   };
2012
2013   if (onoff == FMM_AUTO_OFF) ret = ErrorType::kInvalidOperation;
2014
2015   fmm_mode_ = FMM_AUTO_ON;
2016
2017   if (state < EsState::kReady) return ret;
2018
2019   trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
2020                                fmm_mode_);
2021   return ret;
2022 }
2023
2024 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
2025   Track activated_track;
2026   bool is_existed =
2027       track_util::GetActiveTrack(track_, kTrackTypeAudio, &activated_track);
2028   EsState state = state_manager_.GetState();
2029   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2030     LOG_ERROR_P(this,
2031                 "Invalid State [state:%d] or audio stream already exists[%d],",
2032                 state_manager_.GetStateEnum(), is_existed);
2033     return false;
2034   }
2035   if (force_audio_swdecoder_use_ && type == kPlayerAudioCodecTypeHW) {
2036     LOG_ERROR_P(this, "Not support hw decoder");
2037     return false;
2038   }
2039   LOG_INFO_P(this, "PlayerAudioCodecType [%s]",
2040              (type == kPlayerAudioCodecTypeHW) ? "hardware" : "software");
2041   audio_codec_type_ = type;
2042   return true;
2043 }
2044
2045 bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
2046   Track activated_track;
2047   bool is_existed =
2048       track_util::GetActiveTrack(track_, kTrackTypeVideo, &activated_track);
2049   EsState state = state_manager_.GetState();
2050   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
2051     LOG_ERROR_P(this,
2052                 "Invalid State [state:%d] or video stream already exists[%d],",
2053                 state_manager_.GetStateEnum(), is_existed);
2054     return false;
2055   }
2056   if (force_video_swdecoder_use_ &&
2057       (type == kPlayerVideoCodecTypeHW ||
2058        type == kPlayerVideoCodecTypeHWNdecoding)) {
2059     LOG_ERROR_P(this, "Not support hw decoder");
2060     return false;
2061   }
2062   if (type == kPlayerVideoCodecTypeSW &&
2063       vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
2064     LOG_ERROR_P(this,
2065                 "sw video decoder is not supportted when video frame buffer "
2066                 "type is scale");
2067     return false;
2068   }
2069 #ifdef USE_MIXER
2070   if (!enable_rsc_alloc_handle_) {
2071     LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2072     return false;
2073   }
2074   if (type == kPlayerVideoCodecTypeHWNdecoding) {
2075     LOG_INFO_P(this, "PlayerVideoCodecType HW N-decoding");
2076     video_decoding_mode_ = internal::kNdecodingMode;
2077     return true;
2078   }
2079 #endif  // USE_MIXER
2080   LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
2081              (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
2082   video_codec_type_ = type;
2083   return true;
2084 }
2085
2086 bool EsPlayer::SetAiFilter(void* aifilter) {
2087   if (state_manager_.GetState() != EsState::kIdle) {
2088     LOG_ERROR_P(this, "Invalid State , current %d",
2089                 state_manager_.GetStateEnum());
2090     return false;
2091   }
2092   trackrenderer_->SetAiFilter(aifilter);
2093   return true;
2094 }
2095
2096 bool EsPlayer::InitAudioEasingInfo(const uint32_t init_volume,
2097                                    const uint32_t init_elapsed_time,
2098                                    const AudioEasingInfo& easing_info) {
2099   if (init_volume > internal::kVolumeMax ||
2100       easing_info.target_volume > internal::kVolumeMax) {
2101     LOG_ERROR_P(this, "Invalid volume: init [%d] target [%d]", init_volume,
2102                 easing_info.target_volume);
2103     return false;
2104   }
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   return trackrenderer_->InitAudioEasingInfo(init_volume, init_elapsed_time,
2111                                              easing_info);
2112 }
2113
2114 bool EsPlayer::UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) {
2115   if (easing_info.target_volume > internal::kVolumeMax) {
2116     LOG_ERROR_P(this, "Invalid volume level %d", easing_info.target_volume);
2117     return false;
2118   }
2119   if (state_manager_.GetState() < EsState::kIdle) {
2120     LOG_ERROR_P(this, "Invalid State , current %d",
2121                 state_manager_.GetStateEnum());
2122     return false;
2123   }
2124   return trackrenderer_->UpdateAudioEasingInfo(easing_info);
2125 }
2126
2127 bool EsPlayer::GetAudioEasingInfo(uint32_t* current_volume,
2128                                   uint32_t* elapsed_time,
2129                                   AudioEasingInfo* easing_info) {
2130   if (state_manager_.GetState() < EsState::kIdle) {
2131     LOG_ERROR_P(this, "Invalid State , current %d",
2132                 state_manager_.GetStateEnum());
2133     return false;
2134   }
2135   return trackrenderer_->GetAudioEasingInfo(current_volume, elapsed_time,
2136                                             easing_info);
2137 }
2138
2139 bool EsPlayer::StartAudioEasing() {
2140   if (state_manager_.GetState() < EsState::kReady) {
2141     LOG_ERROR_P(this, "Invalid State , current %d",
2142                 state_manager_.GetStateEnum());
2143     return false;
2144   }
2145   return trackrenderer_->StartAudioEasing();
2146 }
2147
2148 bool EsPlayer::StopAudioEasing() {
2149   if (state_manager_.GetState() < EsState::kIdle) {
2150     LOG_ERROR_P(this, "Invalid State , current %d",
2151                 state_manager_.GetStateEnum());
2152     return false;
2153   }
2154   return trackrenderer_->StopAudioEasing();
2155 }
2156
2157 bool EsPlayer::SetAlternativeVideoResource(unsigned int rsc_type) {
2158   if (state_manager_.GetState() == EsState::kNone) {
2159     LOG_ERROR_P(this, "Invalid State");
2160     return false;
2161   }
2162 #ifdef USE_MIXER
2163   if (!enable_rsc_alloc_handle_) {
2164     LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
2165     return false;
2166   }
2167 #endif  // USE_MIXER
2168   if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2169     LOG_ERROR_P(this,
2170                 "has set resource allocate policy, the alternative "
2171                 "resource setting will be wrong");
2172     return false;
2173   }
2174   alternative_video_resource_ = static_cast<std::uint32_t>(rsc_type);
2175   return true;
2176 }
2177
2178 bool EsPlayer::SetAlternativeAudioResource(
2179     const PlayerAudioResourceType rsc_type) {
2180   if (state_manager_.GetState() == EsState::kNone) {
2181     LOG_ERROR_P(this, "Invalid State");
2182     return false;
2183   }
2184
2185   if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
2186     LOG_ERROR_P(this,
2187                 "has set resource allocate policy, the alternative "
2188                 "resource setting will be wrong");
2189     return false;
2190   }
2191   return trackrenderer_->SetAlternativeAudioResource(rsc_type);
2192 }
2193
2194 bool EsPlayer::SetCatchUpSpeed(const CatchUpSpeed& level) {
2195   if (state_manager_.GetState() < EsState::kIdle) {
2196     LOG_ERROR_P(this, "Invalid State , current %d",
2197                 state_manager_.GetStateEnum());
2198     return false;
2199   }
2200
2201   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2202     LOG_ERROR_P(this, "Do not set low latency mode, current[0x%x]",
2203                 static_cast<std::uint32_t>(low_latency_mode_));
2204     return false;
2205   }
2206
2207   if (trackrenderer_->SetCatchUpSpeed(level)) {
2208     return true;
2209   }
2210   return false;
2211 }
2212
2213 bool EsPlayer::GetVideoLatencyStatus(LatencyStatus* status) {
2214   if (state_manager_.GetState() < EsState::kReady) {
2215     LOG_ERROR_P(this, "Invalid State , current %d",
2216                 state_manager_.GetStateEnum());
2217     return false;
2218   }
2219
2220   if (trackrenderer_->GetVideoLatencyStatus(status)) {
2221     return true;
2222   }
2223   return false;
2224 }
2225
2226 bool EsPlayer::GetAudioLatencyStatus(LatencyStatus* status) {
2227   if (state_manager_.GetState() < EsState::kReady) {
2228     LOG_ERROR_P(this, "Invalid State , current %d",
2229                 state_manager_.GetStateEnum());
2230     return false;
2231   }
2232
2233   if (trackrenderer_->GetAudioLatencyStatus(status)) {
2234     return true;
2235   }
2236   return false;
2237 }
2238
2239 bool EsPlayer::SetVideoMidLatencyThreshold(const unsigned int threshold) {
2240   if (state_manager_.GetState() < EsState::kIdle) {
2241     LOG_ERROR_P(this, "Invalid State , current %d",
2242                 state_manager_.GetStateEnum());
2243     return false;
2244   }
2245
2246   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2247     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2248                 static_cast<std::uint32_t>(low_latency_mode_));
2249     return false;
2250   }
2251
2252   LOG_INFO_P(this, "video_mid_latency_threshold : [%u]", threshold);
2253
2254   trackrenderer_->SetVideoMidLatencyThreshold(threshold);
2255   return true;
2256 }
2257
2258 bool EsPlayer::SetAudioMidLatencyThreshold(const unsigned int threshold) {
2259   if (state_manager_.GetState() < EsState::kIdle) {
2260     LOG_ERROR_P(this, "Invalid State , current %d",
2261                 state_manager_.GetStateEnum());
2262     return false;
2263   }
2264
2265   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2266     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2267                 static_cast<std::uint32_t>(low_latency_mode_));
2268     return false;
2269   }
2270
2271   LOG_INFO_P(this, "audio_mid_latency_threshold : [%u]", threshold);
2272
2273   trackrenderer_->SetAudioMidLatencyThreshold(threshold);
2274   return true;
2275 }
2276
2277 bool EsPlayer::SetVideoHighLatencyThreshold(const unsigned int threshold) {
2278   if (state_manager_.GetState() < EsState::kIdle) {
2279     LOG_ERROR_P(this, "Invalid State , current %d",
2280                 state_manager_.GetStateEnum());
2281     return false;
2282   }
2283
2284   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2285     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2286                 static_cast<std::uint32_t>(low_latency_mode_));
2287     return false;
2288   }
2289
2290   LOG_INFO_P(this, "video_high_latency_threshold : [%u]", threshold);
2291
2292   trackrenderer_->SetVideoHighLatencyThreshold(threshold);
2293   return true;
2294 }
2295
2296 bool EsPlayer::SetAudioHighLatencyThreshold(const unsigned int threshold) {
2297   if (state_manager_.GetState() < EsState::kIdle) {
2298     LOG_ERROR_P(this, "Invalid State , current %d",
2299                 state_manager_.GetStateEnum());
2300     return false;
2301   }
2302
2303   if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
2304     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2305                 static_cast<std::uint32_t>(low_latency_mode_));
2306     return false;
2307   }
2308
2309   LOG_INFO_P(this, "audio_high_latency_threshold : [%u]", threshold);
2310
2311   trackrenderer_->SetAudioHighLatencyThreshold(threshold);
2312   return true;
2313 }
2314
2315 bool EsPlayer::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
2316   if (frame_count == nullptr) {
2317     LOG_ERROR_P(this, "frame count is nullptr");
2318     return false;
2319   }
2320   if (state_manager_.GetState() < EsState::kReady) {
2321     LOG_ERROR_P(this, "Invalid State , current %d",
2322                 state_manager_.GetStateEnum());
2323     return false;
2324   }
2325
2326   if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2327     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2328                 static_cast<std::uint32_t>(low_latency_mode_));
2329     return false;
2330   }
2331
2332   return trackrenderer_->GetLowLatencyPcmBufferSize(frame_count);
2333 }
2334
2335 bool EsPlayer::GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
2336   if (frame_count == nullptr) {
2337     LOG_ERROR_P(this, "frame count is nullptr");
2338     return false;
2339   }
2340   if (state_manager_.GetState() < EsState::kReady) {
2341     LOG_ERROR_P(this, "Invalid State , current %d",
2342                 state_manager_.GetStateEnum());
2343     return false;
2344   }
2345
2346   if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2347     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2348                 static_cast<std::uint32_t>(low_latency_mode_));
2349     return false;
2350   }
2351
2352   return trackrenderer_->GetLowLatencyPcmCurrentBufferLevel(frame_count);
2353 }
2354
2355 bool EsPlayer::GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
2356   if (underrun_count == nullptr) {
2357     LOG_ERROR_P(this, "underrun count is nullptr");
2358     return false;
2359   }
2360   if (state_manager_.GetState() < EsState::kReady) {
2361     LOG_ERROR_P(this, "Invalid State , current %d",
2362                 state_manager_.GetStateEnum());
2363     return false;
2364   }
2365
2366   if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
2367     LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
2368                 static_cast<std::uint32_t>(low_latency_mode_));
2369     return false;
2370   }
2371
2372   return trackrenderer_->GetLowLatencyPcmUnderrunCount(underrun_count);
2373 }
2374
2375 bool EsPlayer::GetVirtualRscId(const RscType type, int* virtual_id) {
2376   if (virtual_id == nullptr) return false;
2377   if (state_manager_.GetState() < EsState::kReady) {
2378     LOG_ERROR_P(this, "Invalid State , current %d",
2379                 state_manager_.GetStateEnum());
2380     *virtual_id = -1;
2381     return false;
2382   }
2383   return trackrenderer_->GetVirtualRscId(type, virtual_id);
2384 }
2385
2386 bool EsPlayer::SetAudioPreloading() {
2387   if (state_manager_.GetState() != EsState::kIdle) {
2388     LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
2389     return false;
2390   }
2391   return trackrenderer_->SetAudioPreloading();
2392 }
2393
2394 void EsPlayer::Init_() {
2395   track_.clear();
2396   is_stopped_ = false;
2397   LOG_LEAVE_P(this);
2398 }
2399
2400 void EsPlayer::MsgTask_() {
2401   std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
2402   while (!is_msg_task_stop_) {
2403     if (msg_queue_.empty()) {
2404       msg_task_cv_.wait(msg_mutex);
2405     } else {
2406       msg_mutex.unlock();
2407       msg_queue_.front()->Execute();
2408       msg_mutex.lock();
2409       msg_queue_.pop();
2410     }
2411   }
2412   while (!msg_queue_.empty()) {
2413     msg_queue_.pop();
2414   }
2415   LOG_INFO_P(this, "Stop MsgTask");
2416 }
2417
2418 void EsPlayer::TrackRendererEventListener::OnEos() {
2419   LOG_ENTER_P(handler_);
2420   if (!handler_->eventlistener_) return;
2421   auto listener = std::bind(&esplusplayer::EsEventListener::OnEos,
2422                             handler_->eventlistener_, std::placeholders::_1);
2423   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2424   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2425   handler_->msg_queue_.push(std::move(msg));
2426   msg_mutex.unlock();
2427   handler_->msg_task_cv_.notify_one();
2428   LOG_LEAVE_P(handler_);
2429 }
2430
2431 // LCOV_EXCL_START
2432 void EsPlayer::TrackRendererEventListener::OnSeekDone() {
2433   LOG_ENTER_P(handler_);
2434   if (!handler_->eventlistener_) return;
2435   if (handler_->is_seek_done_need_drop == true) return;
2436   auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
2437                             handler_->eventlistener_, std::placeholders::_1);
2438   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2439   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2440   handler_->msg_queue_.push(std::move(msg));
2441   msg_mutex.unlock();
2442   handler_->msg_task_cv_.notify_one();
2443   LOG_LEAVE_P(handler_);
2444 }
2445
2446 void EsPlayer::TrackRendererEventListener::OnResourceConflicted() {
2447   LOG_ENTER_P(handler_);
2448   if (handler_->is_stopped_) {
2449     LOG_INFO_P(handler_, "LEAVE ~ Stop is called already");
2450     return;
2451   }
2452   LOG_INFO_P(handler_, "Handling resource conflict...");
2453   handler_->is_resource_conflicted_ = true;
2454   handler_->trackrenderer_->Stop();
2455   if (!handler_->eventlistener_ || handler_->is_stopped_) return;
2456   auto listener =
2457       std::bind(&esplusplayer::EsEventListener::OnResourceConflicted,
2458                 handler_->eventlistener_, std::placeholders::_1);
2459   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2460   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2461   handler_->msg_queue_.push(std::move(msg));
2462   msg_mutex.unlock();
2463   if (handler_->is_stopped_) {
2464     LOG_LEAVE_P(handler_);
2465     return;
2466   }
2467   handler_->msg_task_cv_.notify_one();
2468   LOG_LEAVE_P(handler_);
2469 }
2470
2471 void EsPlayer::TrackRendererEventListener::OnError(
2472     const ErrorType& error_code) {
2473   if (!handler_->eventlistener_) return;
2474   if (error_code == ErrorType::kResourceLimit) return;
2475   auto listener = std::bind(&esplusplayer::EsEventListener::OnError,
2476                             handler_->eventlistener_, std::placeholders::_1,
2477                             std::placeholders::_2);
2478   auto msg = es_msg::Error::Make(error_code, listener,
2479                                  handler_->eventlistener_userdata_);
2480
2481   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2482   handler_->msg_queue_.push(std::move(msg));
2483   msg_mutex.unlock();
2484   handler_->msg_task_cv_.notify_one();
2485 }
2486
2487 void EsPlayer::TrackRendererEventListener::OnErrorMsg(
2488     const ErrorType& error_code, char* error_msg) {
2489   if (!handler_->eventlistener_) return;
2490   if (error_code == ErrorType::kResourceLimit) return;
2491
2492   std::vector<Track> activeTracks;
2493   track_util::GetActiveTrackList(handler_->track_, activeTracks);
2494
2495   Json::Value message;
2496   message["error_code"] = (int)error_code;
2497
2498   switch (error_code) {
2499     case ErrorType::kNotSupportedVideoCodec:
2500       for (const auto& track : activeTracks) {
2501         if (track.type == kTrackTypeVideo) {
2502           message["codec"] = track.mimetype.c_str();
2503           message["demux"] = track.container_type.c_str();
2504           char json_string[20] = {0};
2505           int nLen = 19;
2506           strncat(json_string, std::to_string(track.width).c_str(), nLen);
2507           nLen = sizeof(json_string) - strlen(json_string) - 1;
2508           if (nLen < 0) nLen = 0;
2509           strncat(json_string, "*", nLen);
2510           nLen = sizeof(json_string) - strlen(json_string) - 1;
2511           if (nLen < 0) nLen = 0;
2512           strncat(json_string, std::to_string(track.height).c_str(), nLen);
2513           message["resolution"] = json_string;
2514           memset(json_string, 0, sizeof(json_string));
2515           nLen = 19;
2516           strncat(json_string, std::to_string(track.framerate_num).c_str(),
2517                   nLen);
2518           nLen = sizeof(json_string) - strlen(json_string) - 1;
2519           if (nLen < 0) nLen = 0;
2520           strncat(json_string, "/", nLen);
2521           nLen = sizeof(json_string) - strlen(json_string) - 1;
2522           if (nLen < 0) nLen = 0;
2523           strncat(json_string, std::to_string(track.framerate_den).c_str(),
2524                   nLen);
2525           message["fps"] = json_string;
2526           message["detail_info"] = error_msg;
2527           break;
2528         }
2529       }
2530       break;
2531     case ErrorType::kNotSupportedAudioCodec:
2532
2533       break;
2534     default:
2535       break;
2536   }
2537
2538   Json::FastWriter writer;
2539   std::string str = writer.write(message);
2540   LOG_INFO_P(handler_, "error message: %s", str.c_str());
2541
2542   auto listener = std::bind(&esplusplayer::EsEventListener::OnErrorMsg,
2543                             handler_->eventlistener_, std::placeholders::_1,
2544                             std::placeholders::_2, std::placeholders::_3);
2545   auto msg =
2546       es_msg::ErrorMsg::Make(error_code, str.c_str(), str.size(), listener,
2547                              handler_->eventlistener_userdata_);
2548
2549   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2550   handler_->msg_queue_.push(std::move(msg));
2551   msg_mutex.unlock();
2552   handler_->msg_task_cv_.notify_one();
2553 }
2554 // LCOV_EXCL_STOP
2555
2556 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
2557     const TrackType& type) {
2558   LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
2559              (type == kTrackTypeAudio) ? "audio" : "video");
2560
2561   handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
2562
2563   auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToPrepare,
2564                             handler_->eventlistener_, std::placeholders::_1,
2565                             std::placeholders::_2);
2566   StreamType stream_type = internal::ConvertToStreamType(type);
2567   auto msg = es_msg::ReadyToPrepare::Make(stream_type, listener,
2568                                           handler_->eventlistener_userdata_);
2569   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2570   handler_->msg_queue_.push(std::move(msg));
2571   msg_mutex.unlock();
2572   handler_->msg_task_cv_.notify_one();
2573 }
2574
2575 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
2576   uint64_t offset = handler_->need_data_[type].seek_offset;
2577
2578   LOG_INFO("%p, OnReadyToSeek [%s] offset [%" PRId64 "]", handler_,
2579            (type == kTrackTypeAudio) ? "audio" : "video", offset);
2580
2581   handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
2582   handler_->need_data_[type].seek_offset = 0;
2583
2584   auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToSeek,
2585                             handler_->eventlistener_, std::placeholders::_1,
2586                             std::placeholders::_2, std::placeholders::_3);
2587   StreamType stream_type = internal::ConvertToStreamType(type);
2588   handler_->es_packet_logger_.ResetLog(stream_type);
2589   auto msg = es_msg::ReadyToSeek::Make(stream_type, offset, listener,
2590                                        handler_->eventlistener_userdata_);
2591   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2592   handler_->msg_queue_.push(std::move(msg));
2593   msg_mutex.unlock();
2594   handler_->msg_task_cv_.notify_one();
2595 }
2596
2597 void EsPlayer::TrackRendererEventListener::BufferStatus_(
2598     const TrackType& type, const BufferStatus& status) {
2599   uint64_t byte_size, time_size;
2600   // LOG_INFO_P(handler_, "OnBufferStatus [%s] [%s]",
2601   //        (type == kTrackTypeAudio) ? "audio" : "video",
2602   //        (status == BufferStatus::kUnderrun) ? "underrun" : "overrun");
2603   handler_->GetSrcQueueCurrentSize_(type, &byte_size, &time_size);
2604   auto listener = std::bind(&esplusplayer::EsEventListener::OnBufferStatus,
2605                             handler_->eventlistener_, std::placeholders::_1,
2606                             std::placeholders::_2, std::placeholders::_3,
2607                             std::placeholders::_4, std::placeholders::_5);
2608   StreamType stream_type = internal::ConvertToStreamType(type);
2609   auto msg =
2610       es_msg::Bufferstatus::Make(stream_type, status, byte_size, time_size,
2611                                  listener, handler_->eventlistener_userdata_);
2612   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2613   handler_->msg_queue_.push(std::move(msg));
2614   msg_mutex.unlock();
2615   handler_->msg_task_cv_.notify_one();
2616 }
2617
2618 void EsPlayer::TrackRendererEventListener::OnBufferStatus(
2619     const TrackType& type, const BufferStatus& status) {
2620   if (!handler_->eventlistener_) return;
2621   if (internal::IsLowLatencyModeDisableAVSync(handler_->low_latency_mode_))
2622     return;
2623
2624   if (handler_->need_data_[type].mask == kNeedDataMaskByPrepare &&
2625       status == BufferStatus::kUnderrun) {
2626     ReadyToPrepare_(type);
2627   } else if (handler_->need_data_[type].mask == kNeedDataMaskBySeek &&
2628              status == BufferStatus::kUnderrun) {
2629     ReadyToSeek_(type);
2630   } else {
2631     BufferStatus_(type, status);
2632   }
2633 }
2634
2635 // LCOV_EXCL_START
2636 void EsPlayer::TrackRendererEventListener::OnMediaPacketGetTbmBufPtr(
2637     void** tbm_ptr, bool is_scale_change) {
2638   if (!handler_->eventlistener_) return;
2639
2640   handler_->eventlistener_->OnMediaPacketGetTbmBufPtr(tbm_ptr, is_scale_change);
2641 }
2642
2643 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
2644     const DecodedVideoPacket& packet) {
2645   if (!handler_->eventlistener_) return;
2646
2647   handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
2648 }
2649
2650 #ifdef USE_MIXER
2651 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoRawDecoded(
2652     const DecodedVideoRawModePacket& packet) {
2653   if (handler_->mixer_ticket_ == nullptr) return;
2654   const auto& data = packet.data;
2655   if (packet.type == DecodedVideoRawModePacketType::kPhysicalAddress) {
2656     DecodedRawInfo info;
2657     info.width = packet.width;
2658     info.height = packet.height;
2659     info.y_info.phyaddr = data.raw.y_phyaddr;
2660     info.y_info.viraddr = data.raw.y_viraddr;
2661     info.y_info.linesize = data.raw.y_linesize;
2662     info.uv_info.phyaddr = data.raw.uv_phyaddr;
2663     info.uv_info.viraddr = data.raw.uv_viraddr;
2664     info.uv_info.linesize = data.raw.uv_linesize;
2665     handler_->mixer_ticket_->Render(info);
2666   } else if (packet.type == DecodedVideoRawModePacketType::kTizenBuffer) {
2667     DecodedVideoKeyTypeInfo info;
2668     info.width = packet.width;
2669     info.height = packet.height;
2670     info.key = packet.data.tbm.key;
2671     handler_->mixer_ticket_->Render(info);
2672   }
2673 }
2674
2675 bool EsPlayer::MixerListener::OnAudioFocusChanged(bool active) {
2676   LOG_INFO_P(handler_, "focused [%d]", active);
2677   std::unique_lock<std::mutex> lock(handler_->audio_focus_m_);
2678   if (handler_->state_manager_.GetState() < EsState::kReady) {
2679     handler_->is_audio_focused_ = active;
2680     return true;
2681   }
2682   if (active) {
2683     Track activated_track;
2684     track_util::GetActiveTrack(handler_->track_, kTrackTypeAudio,
2685                                &activated_track);
2686     LOG_INFO_P(handler_, "Activate audio track");
2687     {
2688       std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2689       handler_->eos_status_ =
2690           internal::ResetEosStatus(kTrackTypeAudio, handler_->eos_status_);
2691     }
2692     return handler_->trackrenderer_->Activate(kTrackTypeAudio, activated_track);
2693   }
2694   LOG_INFO_P(handler_, "Deactivate audio track");
2695   handler_->is_audio_focused_ = false;
2696   {
2697     std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
2698     handler_->eos_status_ |= EosStatus::kAudioEos;
2699   }
2700   return handler_->trackrenderer_->Deactivate(kTrackTypeAudio);
2701 }
2702
2703 bool EsPlayer::MixerListener::OnUpdateDisplayInfo(const DisplayInfo& cur_info,
2704                                                   DisplayInfo* new_info) {
2705   new_info->geometry = handler_->mixerticket_roi_;
2706   new_info->visible_status =
2707       handler_->is_visible_ ? VisibleStatus::kVisible : VisibleStatus::kHide;
2708   return true;
2709 }
2710 #endif  // USE_MIXER
2711 // LCOV_EXCL_STOP
2712
2713 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
2714                                                       const uint64_t offset) {
2715   if (!handler_->eventlistener_) return;
2716
2717   if (handler_->need_data_[type].mask != kNeedDataMaskByPrepare) {
2718     handler_->need_data_[type].mask |= kNeedDataMaskBySeek;
2719     handler_->need_data_[type].seek_offset = offset;
2720   }
2721 }
2722
2723 // LCOV_EXCL_START
2724 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
2725                                                                const int size) {
2726   if (size <= 0) return;
2727   if (!handler_->eventlistener_) return;
2728   auto listener = std::bind(&esplusplayer::EsEventListener::OnClosedCaptionData,
2729                             handler_->eventlistener_, std::placeholders::_1,
2730                             std::placeholders::_2, std::placeholders::_3);
2731   auto msg = es_msg::ClosedCaption::Make(data, size, listener,
2732                                          handler_->eventlistener_userdata_);
2733   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2734   handler_->msg_queue_.push(std::move(msg));
2735   msg_mutex.unlock();
2736   handler_->msg_task_cv_.notify_one();
2737 }
2738
2739 void EsPlayer::TrackRendererEventListener::OnFlushDone() {
2740   LOG_ENTER_P(handler_);
2741   if (!handler_->eventlistener_) return;
2742
2743   auto listener = std::bind(&esplusplayer::EsEventListener::OnFlushDone,
2744                             handler_->eventlistener_, std::placeholders::_1);
2745   auto msg =
2746       es_msg::FlushDone::Make(listener, handler_->eventlistener_userdata_);
2747   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2748   handler_->msg_queue_.push(std::move(msg));
2749   msg_mutex.unlock();
2750   handler_->msg_task_cv_.notify_one();
2751   LOG_LEAVE_P(handler_);
2752 }
2753
2754 void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
2755                                                    const EventMsg& msg_data) {
2756   if (!handler_->eventlistener_) return;
2757
2758   auto listener = std::bind(&esplusplayer::EsEventListener::OnEvent,
2759                             handler_->eventlistener_, std::placeholders::_1,
2760                             std::placeholders::_2, std::placeholders::_3);
2761   auto msg = es_msg::OnEvent::Make(event, msg_data, listener,
2762                                    handler_->eventlistener_userdata_);
2763   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2764   handler_->msg_queue_.push(std::move(msg));
2765   msg_mutex.unlock();
2766   handler_->msg_task_cv_.notify_one();
2767   LOG_LEAVE_P(handler_);
2768 }
2769 // LCOV_EXCL_STOP
2770
2771 void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
2772   LOG_ENTER_P(handler_);
2773   if (!handler_->eventlistener_) return;
2774   auto listener = std::bind(&esplusplayer::EsEventListener::OnFirstDecodingDone,
2775                             handler_->eventlistener_, std::placeholders::_1);
2776   auto msg = es_msg::FirstDecodingDone::Make(listener,
2777                                              handler_->eventlistener_userdata_);
2778   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2779   handler_->msg_queue_.push(std::move(msg));
2780   msg_mutex.unlock();
2781   handler_->msg_task_cv_.notify_one();
2782   LOG_LEAVE_P(handler_);
2783 }
2784
2785 void EsPlayer::TrackRendererEventListener::OnVideoDecoderUnderrun() {
2786   LOG_ENTER_P(handler_);
2787   if (!handler_->eventlistener_) return;
2788
2789   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2790       handler_->state_manager_.GetState() != EsState::kPaused) {
2791     return;
2792   }
2793
2794   auto listener =
2795       std::bind(&esplusplayer::EsEventListener::OnVideoDecoderUnderrun,
2796                 handler_->eventlistener_, std::placeholders::_1);
2797   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2798   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2799   handler_->msg_queue_.push(std::move(msg));
2800   msg_mutex.unlock();
2801   handler_->msg_task_cv_.notify_one();
2802   LOG_LEAVE_P(handler_);
2803 }
2804
2805 void EsPlayer::TrackRendererEventListener::OnVideoLatencyStatus(
2806     const LatencyStatus& latency_status) {
2807   LOG_ENTER_P(handler_);
2808   if (!handler_->eventlistener_) return;
2809
2810   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2811       handler_->state_manager_.GetState() != EsState::kPaused) {
2812     return;
2813   }
2814
2815   auto listener = std::bind(
2816       &esplusplayer::EsEventListener::OnVideoLatencyStatus,
2817       handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2818
2819   auto msg = es_msg::PacketLatencyStatus::Make(
2820       latency_status, listener, handler_->eventlistener_userdata_);
2821
2822   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2823   handler_->msg_queue_.push(std::move(msg));
2824   msg_mutex.unlock();
2825   handler_->msg_task_cv_.notify_one();
2826   LOG_LEAVE_P(handler_);
2827 }
2828
2829 void EsPlayer::TrackRendererEventListener::OnAudioLatencyStatus(
2830     const LatencyStatus& latency_status) {
2831   LOG_ENTER_P(handler_);
2832   if (!handler_->eventlistener_) return;
2833
2834   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2835       handler_->state_manager_.GetState() != EsState::kPaused) {
2836     return;
2837   }
2838
2839   auto listener = std::bind(
2840       &esplusplayer::EsEventListener::OnAudioLatencyStatus,
2841       handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
2842
2843   auto msg = es_msg::PacketLatencyStatus::Make(
2844       latency_status, listener, handler_->eventlistener_userdata_);
2845
2846   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2847   handler_->msg_queue_.push(std::move(msg));
2848   msg_mutex.unlock();
2849   handler_->msg_task_cv_.notify_one();
2850   LOG_LEAVE_P(handler_);
2851 }
2852
2853 void EsPlayer::TrackRendererEventListener::OnVideoHighLatency() {
2854   LOG_ENTER_P(handler_);
2855   if (!handler_->eventlistener_) return;
2856
2857   auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoHighLatency,
2858                             handler_->eventlistener_, std::placeholders::_1);
2859
2860   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2861
2862   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2863   handler_->msg_queue_.push(std::move(msg));
2864   msg_mutex.unlock();
2865   handler_->msg_task_cv_.notify_one();
2866   LOG_LEAVE_P(handler_);
2867 }
2868
2869 // LCOV_EXCL_START
2870 void EsPlayer::TrackRendererEventListener::OnAudioHighLatency() {
2871   LOG_ENTER_P(handler_);
2872   if (!handler_->eventlistener_) return;
2873
2874   auto listener = std::bind(&esplusplayer::EsEventListener::OnAudioHighLatency,
2875                             handler_->eventlistener_, std::placeholders::_1);
2876
2877   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
2878
2879   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2880   handler_->msg_queue_.push(std::move(msg));
2881   msg_mutex.unlock();
2882   handler_->msg_task_cv_.notify_one();
2883   LOG_LEAVE_P(handler_);
2884 }
2885
2886 void EsPlayer::TrackRendererEventListener::OnVideoFrameDropped(
2887     const uint64_t& count) {
2888   if (!handler_->eventlistener_) return;
2889
2890   handler_->eventlistener_->OnVideoFrameDropped(
2891       count, handler_->eventlistener_userdata_);
2892
2893 #if 0
2894
2895   if (handler_->state_manager_.GetState() != EsState::kPlaying &&
2896       handler_->state_manager_.GetState() != EsState::kPaused) {
2897     return;
2898   }
2899
2900   auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoFrameDropped,
2901                             handler_->eventlistener_, std::placeholders::_1,
2902                             std::placeholders::_2);
2903
2904   auto msg = es_msg::FrameDroppedCount::Make(
2905       count, listener, handler_->eventlistener_userdata_);
2906
2907   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
2908   handler_->msg_queue_.push(std::move(msg));
2909   msg_mutex.unlock();
2910   handler_->msg_task_cv_.notify_one();
2911   LOG_LEAVE_P(handler_);
2912 #endif
2913 }
2914
2915 void EsPlayer::TrackRendererEventListener::OnDecoderInputBufferTime(
2916     const TrackType& type, const DecoderBufferTime& time) {
2917   if (!handler_->eventlistener_) return;
2918
2919   StreamType stream_type = internal::ConvertToStreamType(type);
2920   handler_->eventlistener_->OnDecoderInputBufferTime(stream_type, time);
2921 }
2922
2923 void EsPlayer::TrackRendererEventListener::OnDecoderOutputBufferTime(
2924     const TrackType& type, const DecoderBufferTime& time) {
2925   if (!handler_->eventlistener_) return;
2926
2927   StreamType stream_type = internal::ConvertToStreamType(type);
2928   handler_->eventlistener_->OnDecoderOutputBufferTime(stream_type, time);
2929 }
2930
2931 // LCOV_EXCL_STOP
2932
2933 bool EsPlayer::SetVideoScanType(const PlayerVideoScanType type) {
2934   LOG_ENTER_P(this);
2935   if (state_manager_.GetState() != EsState::kIdle) {
2936     LOG_ERROR_P(this, "Invalid State , current %d",
2937                 state_manager_.GetStateEnum());
2938     return false;
2939   }
2940   if (type == kPlayerVideoScanTypeProgressive) set_video_progressive_ = 1;
2941   return true;
2942 }
2943 bool EsPlayer::SetTimeUnitType(const PlayerTimeUnitType type) {
2944   LOG_ENTER_P(this);
2945   if (state_manager_.GetState() != EsState::kIdle) {
2946     LOG_ERROR_P(this, "Invalid State , current %d",
2947                 state_manager_.GetStateEnum());
2948     return false;
2949   }
2950   LOG_INFO_P(this, "PlayerTimeUnitType [%s]",
2951              (type == kPlayerTimeUnitTypeMs) ? "Ms" : "Us");
2952   time_unit_type = type;
2953   return true;
2954 }
2955
2956 bool EsPlayer::GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) {
2957   if (!time_in_milliseconds) return false;
2958   if (state_manager_.GetState() <= EsState::kReady) {
2959     *time_in_milliseconds = 0;
2960     return false;
2961   }
2962   return trackrenderer_->GetDecodingTime(type, time_in_milliseconds);
2963 }
2964
2965 bool EsPlayer::SetVideoStreamRotationInfo(const VideoRotation& rotation) {
2966   LOG_ENTER_P(this);
2967   if (state_manager_.GetState() < EsState::kIdle) {
2968     LOG_ERROR_P(this, "Invalid State , current %d",
2969                 state_manager_.GetStateEnum());
2970     return false;
2971   }
2972   video_rotate_ = rotation;
2973   return trackrenderer_->SetVideoStreamRotationInfo(rotation);
2974 }
2975
2976 bool EsPlayer::GetVideoStreamRotationInfo(VideoRotation* rotation) {
2977   LOG_ENTER_P(this);
2978   if (state_manager_.GetState() < EsState::kIdle) {
2979     LOG_ERROR_P(this, "Invalid State , current %d",
2980                 state_manager_.GetStateEnum());
2981     return false;
2982   }
2983   *rotation = video_rotate_;
2984   return true;
2985 }
2986
2987 bool EsPlayer::SetSimpleMixOutBufferLevel(
2988     const PlayerSimpleMixOutBufferLevel level) {
2989   if (state_manager_.GetState() == EsState::kNone) {
2990     LOG_ERROR_P(this, "Invalid State");
2991     return false;
2992   }
2993   int converted_level = 1;
2994   if (level == kPlayerSimpleMixOutBufferLow) {
2995     converted_level = 0;
2996   } else if (level == kPlayerSimpleMixOutBufferMid) {
2997     converted_level = 1;
2998   } else if (level == kPlayerSimpleMixOutBufferHigh) {
2999     converted_level = 2;
3000   }
3001
3002   return trackrenderer_->SetSimpleMixOutBufferLevel(converted_level);
3003 }
3004
3005 #ifndef TIZEN_FEATURE_PUBLIC
3006 kpi::EsCodecLoggerKeys EsPlayer::MakeKpiKeys_() {
3007   kpi::EsCodecLoggerKeys event_info;
3008   event_info.app_id = app_info_.id;
3009   if (submit_data_type_ == SubmitDataType::kCleanData) {
3010     event_info.is_clean = true;
3011   } else {
3012     event_info.is_clean = false;
3013   }
3014
3015   for (const auto& track : track_) {
3016     if (track.type == kTrackTypeVideo) {
3017       event_info.v_codec = track.mimetype;
3018       event_info.v_codec_version = track.version;
3019       event_info.width = track.maxwidth;
3020       event_info.height = track.maxheight;
3021     } else if (track.type == kTrackTypeAudio) {
3022       event_info.a_codec = track.mimetype;
3023     }
3024   }
3025   return event_info;
3026 }
3027 #endif
3028
3029 void EsPlayer::InitValuesFromIni_() {
3030   force_audio_swdecoder_use_ = es_conf::ini_property["force_sw_audio_codec"];
3031   force_video_swdecoder_use_ = es_conf::ini_property["force_sw_video_codec"];
3032 }
3033
3034 #ifdef TIZEN_FEATURE_PUBLIC
3035 bool EsPlayer::EnableVideoHole(bool value) {
3036   if (state_manager_.GetState() < EsState::kIdle) {
3037     LOG_ERROR_P(this, "Invalid State , current %d",
3038                 state_manager_.GetStateEnum());
3039     return false;
3040   }
3041   return trackrenderer_->EnableVideoHole(value);
3042 }
3043
3044 bool EsPlayer::SetSoundStreamInfo(const sound_stream_info_h stream_info) {
3045   if (state_manager_.GetState() != EsState::kIdle) {
3046     LOG_ERROR_P(this, "Invalid State , current %d",
3047                 state_manager_.GetStateEnum());
3048     return false;
3049   }
3050   if (!stream_info) {
3051     LOG_ERROR_P(this, "stream_info is null");
3052     return false;
3053   }
3054   return trackrenderer_->SetSoundStreamInfo(stream_info);
3055 }
3056 #endif
3057
3058 namespace es_conf {
3059
3060 void LoadIniProperty(const Json::Value& root) {
3061   // clang-format off
3062   std::vector<std::string> booleanKeys {
3063       "generate_dot",
3064       "force_sw_audio_codec",
3065       "force_sw_video_codec",
3066       "fallback_to_sw_audio_codec",
3067       "fallback_to_sw_video_codec"
3068   };
3069   // clang-format on
3070   gst_util::GstInit(root);
3071   std::for_each(booleanKeys.begin(), booleanKeys.end(), [&](const auto& key) {
3072     es_conf::ini_property[key] = root.get(key, "").asBool();
3073     LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
3074   });
3075 }
3076
3077 bool LoadIniFile() {
3078   const char* path = esplusplayer_cfg::GetIniPath();
3079   LOG_INFO("path : %s", path);
3080   std::streampos size;
3081   char* buf = nullptr;
3082   std::ifstream file(path, std::ios::binary | std::ios::ate);
3083   if (file.is_open() == false) {
3084     gst_util::GstInit();
3085     LOG_ERROR("Can't open file !!");
3086     return false;
3087   }
3088   BOOST_SCOPE_EXIT(&file) { file.close(); }
3089   BOOST_SCOPE_EXIT_END
3090
3091   size = file.tellg();
3092   if (size <= 0) {
3093     LOG_ERROR("Wrong file size");
3094     return false;
3095   }
3096   size += 1;
3097   buf = static_cast<char*>(calloc(size, sizeof(char)));
3098   if (buf == nullptr) {
3099     LOG_ERROR("Fail to calloc buf");
3100     return false;
3101   }
3102   BOOST_SCOPE_EXIT(&buf) {
3103     if (buf) free(buf);
3104   }
3105   BOOST_SCOPE_EXIT_END
3106
3107   file.seekg(0, std::ios::beg);
3108   file.read(buf, size);
3109
3110   std::string config = buf;
3111   Json::Value root;
3112   Json::Reader reader;
3113   if (!reader.parse(config, root)) {
3114     LOG_ERROR("Fail to parse configuration file %s",
3115               (reader.getFormatedErrorMessages()).c_str());
3116     return false;
3117   }
3118
3119   es_conf::LoadIniProperty(root);
3120   return true;
3121 }
3122
3123 }  // namespace es_conf
3124
3125 }  // namespace esplusplayer