509688b5814dc02d2612a14ce4ae66a6c179ccc9
[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 <inttypes.h>
10 #include <boost/scope_exit.hpp>
11 #include <cassert>
12 #include <chrono>
13 #include <fstream>
14 #include <functional>
15 #include <memory>
16 #include <sstream>
17 #include <thread>
18
19 #include "core/gst_utils.h"
20 #include "core/track_util.h"
21 #include "core/utils/performance_checker.h"
22 #include "core/utils/plusplayer_cfg.h"
23 #include "core/utils/plusplayer_log.h"
24 #include "esplayer/esplayer_drm.h"
25 #include "json/json.h"
26
27 namespace plusplayer {
28
29 namespace es_conf {
30
31 // get values from /etc/multimedia/esplusplayer.ini
32 static std::once_flag loaded;
33 static std::map<std::string, bool> ini_property;
34
35 bool LoadIniFile();
36 void LoadIniProperty(const Json::Value& root);
37
38 }  // namespace es_conf
39
40 namespace util {
41
42 std::uint64_t ConvertMsToNs(std::uint64_t ms) {
43   constexpr std::uint64_t ns_unit = 1000000;
44   if (ms > (G_MAXUINT64 / ns_unit)) return G_MAXUINT64;
45   return ms * ns_unit;
46 }
47 std::uint64_t ConvertNsToMs(std::uint64_t ns) {
48   constexpr std::uint64_t ms_unit = 1000000;
49   return ns / ms_unit;
50 }
51
52 std::int64_t ConvertMsToNs(std::int64_t ms) {
53   constexpr std::int64_t ns_unit = 1000000;
54   if (ms > (G_MAXINT64 / ns_unit)) return G_MAXINT64;
55   return ms * ns_unit;
56 }
57 std::int64_t ConvertNsToMs(std::int64_t ns) {
58   constexpr std::int64_t ms_unit = 1000000;
59   return ns / ms_unit;
60 }
61
62 std::string GetStringFromMatroskaColor(const MatroskaColor& color_info) {
63   std::ostringstream oss;
64   oss << "matrixCoefficients:" << color_info.matrix_coefficients
65       << " bitsPerChannel:" << color_info.bits_per_channel
66       << " chromaSubsamplingHorz:" << color_info.chroma_subsampling_horizontal
67       << " chromaSubsamplingVert:" << color_info.chroma_subsampling_vertical
68       << " cbSubsamplingHorz:" << color_info.cb_subsampling_horizontal
69       << " cbSubsamplingVert:" << color_info.cb_subsampling_vertical
70       << " chromaSitingHorz:" << color_info.chroma_siting_horizontal
71       << " chromaSitingVert:" << color_info.chroma_siting_vertical
72       << " range:" << color_info.range
73       << " transferCharacteristics:" << color_info.transfer_characteristics
74       << " primaries:" << color_info.primaries
75       << " maxCLL:" << color_info.max_cll << " maxFALL:" << color_info.max_fall
76       << " RX:" << color_info.metadata.primary_r_chromaticity_x
77       << " RY:" << color_info.metadata.primary_r_chromaticity_y
78       << " GX:" << color_info.metadata.primary_g_chromaticity_x
79       << " GY:" << color_info.metadata.primary_g_chromaticity_y
80       << " BX:" << color_info.metadata.primary_b_chromaticity_x
81       << " BY:" << color_info.metadata.primary_b_chromaticity_y
82       << " wX:" << color_info.metadata.white_point_chromaticity_x
83       << " wY:" << color_info.metadata.white_point_chromaticity_y
84       << " luminanceMax:" << color_info.metadata.luminance_max
85       << " luminanceMin:" << color_info.metadata.luminance_min
86       << " isHDR10p:" << color_info.is_hdr_10p;
87   return oss.str();
88 }
89
90 }  // namespace util
91
92 namespace internal {
93 // const std::uint64_t kMaxByteOfVideoSrcQueue = 70 * 1024 * 1024;  // 70 MB
94 // const std::uint64_t kMaxByteOfAudioSrcQueue = 10 * 1024 * 1024;  // 10 MB
95 // const std::uint64_t kMaxTimeOfVideoSrcQueue = 10000000000;       // 10 s
96 // const std::uint64_t kMaxTimeOfAudioSrcQueue = 10000000000;       // 10 s
97
98 constexpr uint32_t kNdecodingMode = 0x04;
99
100 enum VolumeLevel { kVolumeMin = 0, kVolumeMax = 100 };
101 constexpr int kMaxFhdWidth = 1920;
102 constexpr int kMaxFhdHeight = 1080;
103
104 inline bool IsPcmMimeType(const std::string& mimetype) {
105   return (mimetype.find("audio/x-raw") != std::string::npos);
106 }
107 inline bool IsAacCodec(const Track& track) {
108   return (track.mimetype.find("audio/mpeg") != std::string::npos &&
109           track.version == 2);
110 }
111 inline bool IsEac3Codec(const std::string& mimetype) {
112   return mimetype.find("audio/x-eac3") != std::string::npos;
113 }
114 inline bool IsAc3Codec(const std::string& mimetype) {
115   return mimetype.find("audio/x-ac3") != std::string::npos;
116 }
117 inline bool IsAvailableCodecSwitch(const Track& track) {
118   if (internal::IsAacCodec(track) || internal::IsAc3Codec(track.mimetype) ||
119       internal::IsEac3Codec(track.mimetype))
120     return true;
121   return false;
122 }
123
124 int ResetEosStatus(const TrackType& type, int eos_status) {
125   if (type == kTrackTypeVideo)
126     eos_status &= ~EosStatus::kVideoEos;
127   else if (type == kTrackTypeAudio)
128     eos_status &= ~EosStatus::kAudioEos;
129   return eos_status;
130 }
131
132 void UpdateCodecTypeTracks(std::vector<Track>& tracks,
133                            const PlayerAudioCodecType& audio_codec_type,
134                            const PlayerVideoCodecType& video_codec_type,
135                            bool force_audio_swdecoder_use) {
136   for (auto& track : tracks) {
137     switch (track.type) {
138       case kTrackTypeAudio: {
139         if (audio_codec_type == kPlayerAudioCodecTypeSW ||
140             force_audio_swdecoder_use)
141           track.use_swdecoder = true;
142         else
143           track.use_swdecoder = false;
144         break;
145       }
146       case kTrackTypeVideo: {
147         if (video_codec_type == kPlayerVideoCodecTypeSW)
148           track.use_swdecoder = true;
149         else
150           track.use_swdecoder = false;
151         break;
152       }
153       default:
154         break;
155     }
156   }
157 }
158 inline bool IsSupportedDrmType(const drm::Type& drm_type) {
159   static const std::map<drm::Type, bool> kSupportedDrmType = {
160       {drm::Type::kPlayready, true},
161   };
162   if (kSupportedDrmType.count(drm_type) == 0) return false;
163   return kSupportedDrmType.at(drm_type);
164 }
165 inline void ResetDrmProperty(drm::Property& drm_property) {
166   drm_property = drm::Property();
167 }
168 inline StreamType ConvertToStreamType(TrackType type) {
169   return (type == kTrackTypeAudio) ? StreamType::kAudio : StreamType::kVideo;
170 }
171 struct AppsrcQueueSizeOption {
172   std::uint64_t current_size = 0;
173   std::uint64_t max_size = 0;
174   std::uint32_t threshold = 0;
175 };
176 inline bool IsUnderRun(AppsrcQueueSizeOption& byte_based,
177                        AppsrcQueueSizeOption& time_based) {
178   bool need_data_by_byte = false, need_data_by_time = false;
179   need_data_by_byte = (byte_based.max_size > 0) &&
180                       (byte_based.current_size * 100 / byte_based.max_size <=
181                        byte_based.threshold);
182   need_data_by_time = (time_based.max_size > 0) &&
183                       (time_based.current_size * 100 / time_based.max_size <=
184                        time_based.threshold);
185   if (need_data_by_byte || need_data_by_time)
186     return true;
187   else
188     return false;
189 }
190 inline bool IsLowLatencyModeDisableAVSync(std::uint32_t mode) {
191   constexpr std::uint32_t kAVSync = 0x0100;
192   return (mode & kAVSync) ? true : false;
193 }
194 inline bool IsLowLatencyModeDisablePreroll(std::uint32_t mode) {
195   constexpr std::uint32_t kPreroll = 0x0200;
196   return (mode & kPreroll) ? true : false;
197 }
198 inline bool IsLowLatencyMode(std::uint32_t mode) {
199   return (mode != static_cast<std::uint32_t>(kLowLatencyModeNone)) ? true
200                                                                    : false;
201 }
202 inline bool IsSupportedTsOffset(std::uint32_t mode) {
203   return IsLowLatencyMode(mode) && !IsLowLatencyModeDisableAVSync(mode) ? true
204                                                                         : false;
205 }
206 inline bool IsSetLowLatencyModeForCatchUp(std::uint32_t low_latency_mode) {
207   std::uint32_t precondition = 0;
208   precondition |= static_cast<std::uint32_t>(kLowLatencyModeAudio);
209   precondition |= static_cast<std::uint32_t>(kLowLatencyModeVideo);
210   precondition |= static_cast<std::uint32_t>(kLowLatencyModeDisableAVSync);
211   precondition |=
212       static_cast<std::uint32_t>(kLowLatencyModeDisableVideoQuality);
213   return (low_latency_mode == precondition) ? true : false;
214 }
215
216 }  // namespace internal
217
218 EsPlayer::EsPlayer() {
219   std::call_once(es_conf::loaded, [this]() { es_conf::LoadIniFile(); });
220 }
221
222 EsPlayer::~EsPlayer() {
223   LOG_ENTER_P(this);
224   try {
225     Close();
226   } catch (...) {
227     LOG_ERROR("Close failed");
228   }
229   LOG_LEAVE_P(this);
230 }
231
232 bool EsPlayer::Open() {
233   LOG_INFO_P(this, "state manager > %p", &state_manager_);
234   Init_();
235   state_manager_.Start();
236   auto op = [this]() noexcept -> bool {
237     const auto start = performance_checker::Start();
238     if (trackrenderer_) {
239       assert(0 && "trackrenderer already exist");
240     }
241     msg_handler_task_ =
242         std::async(std::launch::async, &EsPlayer::MsgTask_, this);
243     trackrenderer_ = TrackRendererAdapter::Create();
244     assert(trackrenderer_);
245
246     trackrenderer_->RegisterListenerForEsplayer(
247         trackrenderer_event_listener_.get());
248     performance_checker::End(start, "Open");
249     return true;
250   };
251   es_event::Open event{op};
252   return state_manager_.ProcessEvent(event);
253 }
254
255 bool EsPlayer::Close() {
256   LOG_ENTER_P(this);
257   std::lock_guard<std::mutex> lk(submit_mutex_);
258   if (state_manager_.GetState() >= EsState::kIdle) {
259     Stop();
260   }
261   auto op = [this]() noexcept {
262     if (is_msg_task_stop_ == false) {
263       is_msg_task_stop_ = true;
264       msg_task_cv_.notify_one();
265       if (msg_handler_task_.valid()) msg_handler_task_.wait();
266     }
267
268     if (trackrenderer_) trackrenderer_.reset();
269     ResetContextForClose_();
270     LOG_LEAVE_P(this);
271     return true;
272   };
273   es_event::Close event{op};
274   state_manager_.ProcessEvent(event);
275   state_manager_.Stop();
276   return true;
277 }
278
279 bool EsPlayer::Deactivate(const StreamType type) {
280   LOG_ENTER_P(this);
281   if (state_manager_.GetState() < EsState::kReady) {
282     LOG_ERROR_P(this, "Invalid State , current %d",
283                 state_manager_.GetStateEnum());
284     return false;
285   }
286   if (!trackrenderer_->Deactivate(static_cast<TrackType>(type))) {
287     return false;
288   }
289   {
290     std::lock_guard<std::mutex> lock(eos_mutex_);
291     switch (type) {
292       case StreamType::kAudio:
293         eos_status_ |= EosStatus::kAudioEos;
294         break;
295       case StreamType::kVideo:
296         eos_status_ |= EosStatus::kVideoEos;
297         break;
298       default:
299         break;
300     }
301   }
302   for (auto& track : track_) {
303     if (track.type == static_cast<TrackType>(type)) {
304       track.active = false;
305     }
306   }
307   return true;
308 }
309
310 bool EsPlayer::Activate(const StreamType type) {
311   LOG_ENTER_P(this);
312   if (state_manager_.GetState() < EsState::kReady) {
313     LOG_ERROR_P(this, "Invalid State , current %d",
314                 state_manager_.GetStateEnum());
315     return false;
316   }
317   if (!track_.empty()) {
318     auto has_track = [type](const Track& item) -> bool {
319       return item.type == static_cast<TrackType>(type);
320     };
321     auto target = std::find_if(track_.begin(), track_.end(), has_track);
322     if (target == track_.end()) {
323       LOG_ERROR_P(this, "there is no track to activate");
324       return false;
325     }
326     if (target->active != false) {
327       LOG_ERROR_P(this, "The track should be deactivated in advance.");
328       return false;
329     }
330     target->active = true;
331     internal::UpdateCodecTypeTracks(track_, audio_codec_type_,
332                                     video_codec_type_,
333                                     force_audio_swdecoder_use_);
334     SetTrackRendererAttributes_();
335     if (!trackrenderer_->Activate(target->type, *target)) {
336       target->active = false;
337       return false;
338     }
339     std::lock_guard<std::mutex> lock2(eos_mutex_);
340     eos_status_ =
341         internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
342     return true;
343   }
344   return false;
345 }
346
347 bool EsPlayer::Start() {
348   LOG_ENTER_P(this);
349   if (is_stopped_) {
350     LOG_ERROR_P(this, "Stop already, no need to Start,leave...");
351     return false;
352   }
353   auto op = [this]() noexcept {
354     if (!trackrenderer_->Start()) {
355       return false;
356     }
357     return true;
358   };
359   es_event::Start event{op};
360   return state_manager_.ProcessEvent(event);
361 }
362
363 bool EsPlayer::Stop() {
364   LOG_ENTER_P(this);
365   is_stopped_ = true;
366   auto stop = [this]() noexcept -> bool {
367     const auto start = performance_checker::Start();
368     if (trackrenderer_) trackrenderer_->Stop();
369     ResetContextForStop_();
370     performance_checker::End(start, "Stop");
371     return true;
372   };
373   for (const auto& track : track_) {
374     es_packet_logger_.PrintStoredPacketInfo(
375         internal::ConvertToStreamType(track.type), true);
376   }
377   es_event::Stop event{stop};
378   bool res = state_manager_.ProcessEventStop(event);
379
380   if (preparetask_.valid()) {
381     LOG_INFO_P(this, "Stopped , Wait Prepare() finish...");
382     preparetask_.wait();
383     LOG_INFO_P(this, "Wait , Wait Prepare() Done...");
384   }
385
386   return res;
387 }
388
389 void EsPlayer::SetTrackRendererAttributes_() {
390   if (trackrenderer_ == nullptr) return;
391   trackrenderer_->SetAttribute(
392       TrackRendererAdapter::Attribute::kVideoQueueMaxByte,
393       src_queue_size_.kMaxByteOfVideoSrcQueue);
394   trackrenderer_->SetAttribute(
395       TrackRendererAdapter::Attribute::kAudioQueueMaxByte,
396       src_queue_size_.kMaxByteOfAudioSrcQueue);
397   trackrenderer_->SetAttribute(
398       TrackRendererAdapter::Attribute::kVideoMinByteThreshold,
399       src_queue_size_.kMinByteThresholdOfVideoSrcQueue);
400   trackrenderer_->SetAttribute(
401       TrackRendererAdapter::Attribute::kAudioMinByteThreshold,
402       src_queue_size_.kMinByteThresholdOfAudioSrcQueue);
403   trackrenderer_->SetAttribute(
404       TrackRendererAdapter::Attribute::kVideoQueueMaxBuffer,
405       src_queue_size_.kMaxBufferOfVideoSrcQueue);
406   trackrenderer_->SetAttribute(
407       TrackRendererAdapter::Attribute::kAudioQueueMaxBuffer,
408       src_queue_size_.kMaxBufferOfAudioSrcQueue);
409   trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kLowLatencyMode,
410                                low_latency_mode_);
411   trackrenderer_->SetAttribute(
412       TrackRendererAdapter::Attribute::kUnlimitedMaxBufferMode,
413       unlimited_max_buffer_mode_);
414   trackrenderer_->SetAttribute(
415       TrackRendererAdapter::Attribute::kAccurateSeekMode, accurate_seek_mode_);
416   trackrenderer_->SetAttribute(
417       TrackRendererAdapter::Attribute::kVideoPreDisplayMode,
418       video_pre_display_mode_);
419   if (resume_time_.is_set) {
420     trackrenderer_->SetAttribute(
421         TrackRendererAdapter::Attribute::kStartRenderingTime,
422         resume_time_.time);
423     resume_time_.is_set = false;
424   }
425 }
426
427 bool EsPlayer::Prepare_() {
428   LOG_ENTER_P(this);
429   if (is_stopped_) {
430     LOG_ERROR_P(this, "Stop already, no need to prepare,leave...");
431     return false;
432   }
433   auto op = [this]() noexcept -> bool {
434     const auto start = performance_checker::Start();
435
436     internal::UpdateCodecTypeTracks(track_, audio_codec_type_,
437                                     video_codec_type_,
438                                     force_audio_swdecoder_use_);
439     std::vector<Track> active_track;
440     if (!track_util::GetActiveTrackList(track_, active_track)) {
441       return false;
442     }
443     trackrenderer_->SetIniProperty(es_conf::ini_property);
444     for (const auto& track : active_track) {
445       switch (track.type) {
446         case kTrackTypeAudio: {
447           std::lock_guard<std::mutex> lock2(eos_mutex_);
448           eos_status_ = internal::ResetEosStatus(kTrackTypeAudio, eos_status_);
449           need_data_[track.type].mask |= kNeedDataMaskByPrepare;
450           break;
451         }
452         case kTrackTypeVideo: {
453           std::lock_guard<std::mutex> lock2(eos_mutex_);
454           eos_status_ = internal::ResetEosStatus(kTrackTypeVideo, eos_status_);
455           need_data_[track.type].mask |= kNeedDataMaskByPrepare;
456           break;
457         }
458         default:
459           break;
460       }
461     }
462     trackrenderer_->SetTrack(active_track);
463     try {
464       SetTrackRendererAttributes_();
465     } catch (...) {
466       LOG_ERROR_P(this, "SetTrackRendererAttributes_ failed");
467       return false;
468     }
469     if (!trackrenderer_->Prepare()) {
470       return false;
471     }
472     performance_checker::End(start, "Prepare");
473     return true;
474   };
475   es_event::Prepare event{op};
476   if (!state_manager_.ProcessEvent(event)) {
477     return false;
478   }
479   LOG_LEAVE_P(this);
480   return true;
481 }
482
483 void EsPlayer::PrepareTask_() {
484   bool ret = Prepare_();
485
486   state_manager_.SetPreparingState(false);
487   if (eventlistener_) {
488     LOG_INFO_P(this, "Prepare completely, call OnPrepareDone(%d)", ret);
489     eventlistener_->OnPrepareDone(ret, eventlistener_userdata_);
490   }
491
492   LOG_LEAVE_P(this);
493 }
494
495 bool EsPlayer::PrepareAsync() {
496   LOG_ENTER_P(this);
497   state_manager_.SetPreparingState(true);
498   preparetask_ = std::async(std::launch::async, &EsPlayer::PrepareTask_, this);
499   if (!preparetask_.valid()) {
500     state_manager_.SetPreparingState(false);
501     return false;
502   }
503   return true;
504 }
505
506 bool EsPlayer::Pause() {
507   LOG_ENTER_P(this);
508   if (is_stopped_) {
509     LOG_ERROR_P(this, "Stop already, no need to pause,leave...");
510     return false;
511   }
512   if (state_manager_.GetState() < EsState::kReady) {
513     LOG_ERROR_P(this, "Invalid State , current %d",
514                 state_manager_.GetStateEnum());
515     return false;
516   }
517   auto op = [this]() noexcept -> bool {
518     if (!trackrenderer_) return false;
519     if (!trackrenderer_->Pause()) {
520       return false;
521     }
522     return true;
523   };
524   for (const auto& track : track_) {
525     es_packet_logger_.PrintStoredPacketInfo(
526         internal::ConvertToStreamType(track.type), true);
527   }
528   es_event::Pause event{op};
529   return state_manager_.ProcessEvent(event);
530 }
531
532 bool EsPlayer::Resume() {
533   LOG_ENTER_P(this);
534   if (is_stopped_) {
535     LOG_ERROR_P(this, "Stop already, no need to Resume,leave...");
536     return false;
537   }
538   if (state_manager_.GetState() <= EsState::kReady) {
539     LOG_ERROR_P(this, "Invalid State , current %d",
540                 state_manager_.GetStateEnum());
541     return false;
542   }
543   if (is_resource_conflicted_) {
544     LOG_ERROR_P(this, "Resume fail resource conflicted");
545     return false;
546   }
547   auto op = [this]() noexcept -> bool {
548     if (!trackrenderer_) return false;
549     if (!trackrenderer_->Resume()) {
550       return false;
551     }
552     return true;
553   };
554   for (const auto& track : track_) {
555     es_packet_logger_.PrintStoredPacketInfo(
556         internal::ConvertToStreamType(track.type), true);
557   }
558   es_event::Resume event{op};
559   return state_manager_.ProcessEvent(event);
560 }
561
562 bool EsPlayer::Seek(const uint64_t time_millisecond) {
563   if (state_manager_.GetState() < EsState::kIdle) {
564     LOG_ERROR_P(this, "Invalid State , current %d",
565                 state_manager_.GetStateEnum());
566     return false;
567   }
568   if (state_manager_.GetState() == EsState::kIdle) {
569     if (state_manager_.GetPreparingState()) {
570       LOG_ERROR_P(this, "Invalid State , during preparing");
571       return false;
572     }
573     LOG_ERROR("[%p] > resume time [%" PRIu64 " ms]", this, time_millisecond);
574     resume_time_.is_set = true;
575     resume_time_.time = time_millisecond;
576     return true;
577   }
578   is_seek_done_need_drop = true;
579   LOG_DEBUG("[%p] > [ENTER] seek time [%" PRIu64 " ms]", this, time_millisecond);
580   for (const auto& track : track_) {
581     std::lock_guard<std::mutex> lock2(eos_mutex_);
582     eos_status_ = internal::ResetEosStatus(track.type, eos_status_);
583     es_packet_logger_.PrintStoredPacketInfo(
584         internal::ConvertToStreamType(track.type), true);
585   }
586   auto op = [this, time_millisecond]() -> bool {
587     if (!trackrenderer_->Seek(time_millisecond, current_playback_rate_,
588                               current_audio_mute_)) {
589       return false;
590     }
591     return true;
592   };
593   es_event::Seek event{op};
594
595   bool ret = state_manager_.ProcessEvent(event);
596   is_seek_done_need_drop = false;
597
598   if (eventlistener_) {
599     if (internal::IsLowLatencyModeDisableAVSync(low_latency_mode_) ||
600         internal::IsLowLatencyModeDisablePreroll(low_latency_mode_)) {
601       auto listener = std::bind(&plusplayer::EsEventListener::OnSeekDone,
602                                 eventlistener_, std::placeholders::_1);
603       auto msg = es_msg::Simple::Make(listener, eventlistener_userdata_);
604       std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
605       msg_queue_.push(std::move(msg));
606       msg_mutex.unlock();
607       msg_task_cv_.notify_one();
608     }
609   }
610
611   LOG_DEBUG("%p, [LEAVE] seek end ", this);
612
613   return ret;
614 }
615
616 bool EsPlayer::SetPlaybackRate(const double rate, const bool audio_mute) {
617   LOG_ENTER_P(this);
618
619   if (rate <= 0 || rate > 2.0) {
620     LOG_ERROR_P(this, "Not a valid PlaybackRate");
621     return false;
622   }
623
624   if (state_manager_.GetState() < EsState::kReady) {
625     LOG_ERROR_P(this, "Invalid State , current %d",
626                 state_manager_.GetStateEnum());
627     return false;
628   }
629
630   auto op = [this, rate, audio_mute]() -> bool {
631     if (!trackrenderer_->SetPlaybackRate(rate, audio_mute)) {
632       return false;
633     }
634     current_playback_rate_ = rate;
635     current_audio_mute_ = audio_mute;
636     return true;
637   };
638   es_event::PlaybackRate event{op};
639   bool ret = state_manager_.ProcessEvent(event);
640
641   LOG_LEAVE_P(this);
642   return ret;
643 }
644
645 bool EsPlayer::SetDisplay(const DisplayType& type, void* obj) {
646   if (state_manager_.GetState() != EsState::kIdle) {
647     LOG_ERROR_P(this, "Invalid State , current %d",
648                 state_manager_.GetStateEnum());
649     return false;
650   }
651   return trackrenderer_->SetDisplay(type, obj);
652 }
653
654 bool EsPlayer::SetDisplay(const DisplayType& type, void* ecore_wl2_window,
655                           const int x, const int y, const int w, const int h) {
656   if (state_manager_.GetState() != EsState::kIdle) {
657     LOG_ERROR_P(this, "Invalid State , current %d",
658                 state_manager_.GetStateEnum());
659     return false;
660   }
661   return trackrenderer_->SetDisplay(type, ecore_wl2_window, x, y, w, h);
662 }
663
664 bool EsPlayer::SetDisplay(const DisplayType& type, unsigned int surface_id,
665                           const int x, const int y, const int w, const int h) {
666   if (state_manager_.GetState() != EsState::kIdle) {
667     LOG_ERROR_P(this, "Invalid State , current %d",
668                 state_manager_.GetStateEnum());
669     return false;
670   }
671   return trackrenderer_->SetDisplay(type, surface_id, x, y, w, h);
672 }
673
674 bool EsPlayer::SetDisplayMode(const DisplayMode& mode) {
675   if (state_manager_.GetState() < EsState::kIdle) {
676     LOG_ERROR_P(this, "Invalid State , current %d",
677                 state_manager_.GetStateEnum());
678     return false;
679   }
680   trackrenderer_->SetDisplayMode(mode);
681   return true;
682 }
683
684 bool EsPlayer::SetDisplayRoi(const Geometry& roi) {
685   if (state_manager_.GetState() < EsState::kIdle) {
686     LOG_ERROR_P(this, "Invalid State , current %d",
687                 state_manager_.GetStateEnum());
688     return false;
689   }
690   return trackrenderer_->SetDisplayRoi(roi);
691 }
692
693 bool EsPlayer::SetVideoRoi(const CropArea& area) {
694   if (state_manager_.GetState() < EsState::kIdle) {
695     LOG_ERROR_P(this, "Invalid State , current %d",
696                 state_manager_.GetStateEnum());
697     return false;
698   }
699   return trackrenderer_->SetVideoRoi(area);
700 }
701
702 bool EsPlayer::SetDisplayRotate(const DisplayRotation& rotate) {
703   if (state_manager_.GetState() < EsState::kIdle) {
704     LOG_ERROR_P(this, "Invalid State , current %d",
705                 state_manager_.GetStateEnum());
706     return false;
707   }
708   return trackrenderer_->SetDisplayRotate(rotate);
709 }
710
711 bool EsPlayer::GetDisplayRotate(DisplayRotation* rotate) {
712   if (state_manager_.GetState() < EsState::kIdle) {
713     LOG_ERROR_P(this, "Invalid State , current %d",
714                 state_manager_.GetStateEnum());
715     return false;
716   }
717   if (trackrenderer_->GetDisplayRotate(rotate)) {
718     return true;
719   }
720   return false;
721 }
722
723 bool EsPlayer::SetDisplayVisible(bool is_visible) {
724   if (state_manager_.GetState() < EsState::kIdle) {
725     LOG_ERROR_P(this, "Invalid State , current %d",
726                 state_manager_.GetStateEnum());
727     return false;
728   }
729   return trackrenderer_->SetDisplayVisible(is_visible);
730 }
731
732 bool EsPlayer::SetTrustZoneUse(bool is_using_tz) {
733   if (state_manager_.GetState() != EsState::kIdle) {
734     LOG_ERROR_P(this, "Invalid State , current %d",
735                 state_manager_.GetStateEnum());
736     return false;
737   }
738   if (drm_property_.type != drm::Type::kNone) {
739     LOG_ERROR_P(this, "drm type is already set for sending encrypted packets");
740     return false;
741   }
742   LOG_INFO_P(this, "set trust zone use [%d]", is_using_tz);
743   drm_property_.external_decryption = is_using_tz;
744
745   drm::Property drm_property = drm_property_;
746   drm_property.type = drm::Type::kPlayready;
747   trackrenderer_->SetDrm(drm_property);
748   return true;
749 }
750
751 bool EsPlayer::SetSubmitDataType(SubmitDataType type) {
752   if (state_manager_.GetState() != EsState::kIdle) {
753     LOG_ERROR_P(this, "Invalid State , current %d",
754                 state_manager_.GetStateEnum());
755     return false;
756   }
757   LOG_INFO_P(this, "set submit data type [%d]", static_cast<int>(type));
758
759   if (type == SubmitDataType::kCleanData) return true;
760   submit_data_type_ = type;
761   if (type == SubmitDataType::kEncryptedData) {
762         drm_property_.type = drm::Type::kPlayready;
763         // TODO: following SubmitDataType, need to set external_decryption
764         drm_property_.external_decryption = true;
765         drm::Property drm_property = drm_property_;
766         trackrenderer_->SetDrm(drm_property);
767   }
768   return true;
769 }
770
771 bool EsPlayer::SetTrack_(const Track& track) {
772   LOG_ENTER_P(this);
773   track_.push_back(std::move(track));
774   return true;
775 }
776
777 bool EsPlayer::ChangeStream_(const Track& track) {
778   TrackType type = track.type;
779   if (track_.empty()) return false;
780   auto has_track = [type](const Track& item) -> bool {
781     return item.type == type;
782   };
783   std::lock_guard<std::mutex> lk(submit_mutex_);
784   auto target = std::find_if(track_.begin(), track_.end(), has_track);
785   if (target == track_.end()) {
786     LOG_ERROR_P(this, "Add a new stream.");
787     SetTrack_(track);
788     return true;
789   }
790   if (target->active != false) {
791     LOG_ERROR_P(this, "The track should be deactivated in advance.");
792     return false;
793   }
794   track_.erase(target);
795   LOG_ERROR_P(this, "previously added %s stream is deleted",
796               (type == kTrackTypeAudio) ? "audio" : "video");
797   return SetTrack_(track);
798 }
799
800 bool EsPlayer::SetStream_(const Track& track) {
801   TrackType type = track.type;
802   if (!track_.empty()) {
803     auto has_track = [type](const Track& item) -> bool {
804       return item.type == type;
805     };
806     auto target = std::find_if(track_.begin(), track_.end(), has_track);
807     if (target != track_.end()) {
808       LOG_ERROR_P(this, "Stream is already exist");
809       return false;
810     }
811   }
812   auto op = [this, track]() noexcept {
813     if (!SetTrack_(track)) {
814       return false;
815     }
816     return true;
817   };
818   es_event::SetStream event{op};
819   return state_manager_.ProcessEvent(event);
820 }
821
822 bool EsPlayer::SetStream(const AudioStreamPtr& stream) {
823   LOG_ENTER_P(this);
824   bool ret = false;
825   BOOST_SCOPE_EXIT(&ret, &stream, &force_audio_swdecoder_use_) {
826     if (ret) force_audio_swdecoder_use_ = stream->GetForceSwDecoderUse();
827   }
828   BOOST_SCOPE_EXIT_END
829   if (state_manager_.GetState() < EsState::kIdle) {
830     LOG_ERROR_P(this, "Invalid State , current %d",
831                 state_manager_.GetStateEnum());
832     return ret;
833   }
834   Track track = stream->GetTrack_();
835   if (state_manager_.GetState() >= EsState::kReady) {
836     track.active = false;
837     ret = ChangeStream_(track);
838     return ret;
839   }
840   ret = SetStream_(track);
841   return ret;
842 }
843
844 bool EsPlayer::SetStream(const VideoStreamPtr& stream) {
845   LOG_ENTER_P(this);
846   if (state_manager_.GetState() < EsState::kIdle) {
847     LOG_ERROR_P(this, "Invalid State , current %d",
848                 state_manager_.GetStateEnum());
849     return false;
850   }
851   Track track = stream->GetTrack_();
852   if (state_manager_.GetState() >= EsState::kReady) {
853     track.active = false;
854     return ChangeStream_(track);
855   }
856   return SetStream_(track);
857 }
858
859
860 void EsPlayer::ResetContextForClose_() {
861   internal::ResetDrmProperty(drm_property_);
862   track_.clear();
863   submit_data_type_ = SubmitDataType::kCleanData;
864   low_latency_mode_ = 0;
865   resume_time_.is_set = false;
866   unlimited_max_buffer_mode_ = 0;
867   audio_codec_type_ = kPlayerAudioCodecTypeHW;
868   video_codec_type_ = kPlayerVideoCodecTypeHW;
869   is_resource_conflicted_ = false;
870   src_queue_size_ = SrcQueueSize();
871   is_msg_task_stop_ = false;
872 }
873
874 void EsPlayer::ResetContextForStop_() {
875   for (int i = 0; i < kTrackTypeMax; ++i) {
876     need_data_[i].mask = kNeedDataMaskNone;
877     need_data_[i].seek_offset = 0;
878   }
879   {
880     std::lock_guard<std::mutex> lock(eos_mutex_);
881     eos_status_ = EosStatus::kAllEos;
882   }
883   current_playback_rate_ = 1.0;
884   current_audio_mute_ = false;
885 }
886
887 void EsPlayer::GetSrcQueueCurrentSize_(const TrackType& type,
888                                        uint64_t* byte_size,
889                                        uint64_t* time_size) {
890   boost::any byte_size_, time_size_;
891   if (type == TrackType::kTrackTypeVideo) {
892     trackrenderer_->GetAttribute(
893         TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelByte,
894         &byte_size_);
895   } else if (type == TrackType::kTrackTypeAudio) {
896     trackrenderer_->GetAttribute(
897         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
898         &byte_size_);
899   } else
900     return;
901   *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
902   *time_size = 0;
903 }
904
905 GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
906                                    MakeBufferStatus* status) {
907   std::shared_ptr<char> buffer = packet->GetBuffer();
908   uint32_t size = packet->GetSize();
909   if (packet->IsEosPacket()) {
910     *status = MakeBufferStatus::kEos;
911     return nullptr;
912   }
913   GstBuffer* gstbuffer = gst_buffer_new_and_alloc(size);
914   if (!gstbuffer) {
915     *status = MakeBufferStatus::kOutOfMemory;
916     return nullptr;
917   }
918   if (buffer != nullptr) {
919     GstMapInfo map;
920     gst_buffer_map(gstbuffer, &map, GST_MAP_WRITE);
921     memcpy(map.data, buffer.get(), size);
922     gst_buffer_unmap(gstbuffer, &map);
923   }
924
925   uint64_t pts = packet->GetPts();
926   uint64_t duration = packet->GetDuration();
927   /* if pts or duration are -1(=GST_CLOCK_TIME_NONE), some of the elements don't
928    * adjust the buffer. */
929   GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
930                                   ? GST_CLOCK_TIME_NONE
931                                   : (GstClockTime)util::ConvertMsToNs(pts);
932   GST_BUFFER_DURATION(gstbuffer) =
933       (duration == GST_CLOCK_TIME_NONE)
934           ? GST_CLOCK_TIME_NONE
935           : (GstClockTime)util::ConvertMsToNs(duration);
936   uint32_t hdr10p_size = packet->GetHdr10pSize();
937   std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
938
939   if (hdr10p_size > 0 && hdr10p_metadata != nullptr) {
940     guint32* blockadditional_size = (guint32*)g_malloc(sizeof(uint32_t));
941     *blockadditional_size = hdr10p_size;
942     gst_mini_object_set_qdata(
943         GST_MINI_OBJECT(gstbuffer),
944         g_quark_from_static_string("matroska_blockadditional_size"),
945         blockadditional_size, g_free);
946
947     /* blockadditional_data : the data sent to omx, size (4 bytes) + metadata */
948     guint8* blockadditional_data =
949         (guint8*)g_malloc(((*blockadditional_size) + 4) * sizeof(guint8));
950     memcpy(blockadditional_data, blockadditional_size, sizeof(uint32_t));
951     memcpy(blockadditional_data + 4, hdr10p_metadata.get(),
952            (*blockadditional_size));
953     gst_mini_object_set_qdata(
954         GST_MINI_OBJECT(gstbuffer),
955         g_quark_from_static_string("matroska_blockadditional_info"),
956         blockadditional_data, g_free);
957   }
958   *status = MakeBufferStatus::kSuccess;
959   return gstbuffer;
960 }
961
962 PacketSubmitStatus EsPlayer::SubmitEosPacket_(const TrackType& type) {
963   PacketSubmitStatus submitstate = PacketSubmitStatus::kSuccess;
964   {
965     std::lock_guard<std::mutex> lock(eos_mutex_);
966     switch (type) {
967       case kTrackTypeAudio:
968         eos_status_ |= EosStatus::kAudioEos;
969         break;
970       case kTrackTypeVideo:
971         eos_status_ |= EosStatus::kVideoEos;
972         break;
973       default:
974         break;
975     }
976     if (eos_status_ != EosStatus::kAllEos) {
977       return submitstate;
978     }
979   }
980   for (int tracktype = kTrackTypeAudio; tracktype < kTrackTypeMax;
981        ++tracktype) {
982     auto inbuffer =
983         DecoderInputBuffer::Create(static_cast<TrackType>(tracktype));
984     if (!trackrenderer_->SubmitPacket2(inbuffer, nullptr)) {
985       std::lock_guard<std::mutex> lock(eos_mutex_);
986       eos_status_ = EosStatus::kAllEos;
987       submitstate = PacketSubmitStatus::kNotPrepared;
988       return submitstate;
989     }
990   }
991   return submitstate;
992 }
993
994 void EsPlayer::UnsetTzQdata_(const DecoderInputBufferPtr& buffer) {
995   const GstBuffer* gstbuf = buffer->Get();
996   if (!gstbuf) return;
997   GstStructure* tzqdata = GST_STRUCTURE(gst_mini_object_steal_qdata(
998       GST_MINI_OBJECT(gstbuf), g_quark_from_static_string("GstTzHandleData")));
999   if (tzqdata) gst_structure_free(tzqdata);
1000 }
1001
1002 PacketSubmitStatus EsPlayer::SubmitDecoderInputBuffer_(
1003     const DecoderInputBufferPtr& buffer) {
1004   PacketSubmitStatus status = PacketSubmitStatus::kSuccess;
1005   TrackRendererAdapter::SubmitStatus submitstate =
1006       TrackRendererAdapter::SubmitStatus::kSuccess;
1007   trackrenderer_->SubmitPacket2(buffer, &submitstate);
1008
1009   switch (submitstate) {
1010     case TrackRendererAdapter::SubmitStatus::kSuccess:
1011     case TrackRendererAdapter::SubmitStatus::kDrop:
1012       status = PacketSubmitStatus::kSuccess;
1013       break;
1014     case TrackRendererAdapter::SubmitStatus::kFull:
1015       UnsetTzQdata_(buffer);
1016       trackrenderer_event_listener_->OnBufferStatus(buffer->GetType(),
1017                                                     BufferStatus::kOverrun);
1018       status = PacketSubmitStatus::kFull;
1019       break;
1020     default:
1021       UnsetTzQdata_(buffer);
1022       status = PacketSubmitStatus::kNotPrepared;
1023       break;
1024   }
1025   return status;
1026 }
1027
1028 void EsPlayer::MakeGstBufferForTzHandle_(GstBuffer* gstbuffer,
1029                                          const TrackType& type,
1030                                          const uint32_t& tz_handle,
1031                                          const uint32_t& packet_size) {
1032   GstStructure* gst_tz_handle_data_structure =
1033       gst_structure_new("GstTzHandleData", "packet_handle", G_TYPE_UINT,
1034                         static_cast<guint32>(tz_handle), "packet_size",
1035                         G_TYPE_UINT, static_cast<guint32>(packet_size),
1036                         "secure", G_TYPE_BOOLEAN, true, nullptr);
1037   gst_mini_object_set_qdata(
1038       GST_MINI_OBJECT(gstbuffer), g_quark_from_string("GstTzHandleData"),
1039       gst_tz_handle_data_structure, (GDestroyNotify)gst_structure_free);
1040
1041   if (type == kTrackTypeAudio) {
1042     Track audio_track;
1043     bool has_active_audio_track =
1044         track_util::GetActiveTrack(track_, kTrackTypeAudio, &audio_track);
1045     if (has_active_audio_track) {
1046       GstStructure* audio_info_structure =
1047           gst_structure_new("AudioInfo", "mime_type", G_TYPE_STRING,
1048                             audio_track.mimetype.c_str(), nullptr);
1049       gst_mini_object_set_qdata(
1050           GST_MINI_OBJECT(gstbuffer), g_quark_from_string("AudioInfo"),
1051           audio_info_structure, (GDestroyNotify)gst_structure_free);
1052     }
1053   }
1054 }
1055
1056 void EsPlayer::MakeGstBufferForEncryptedPacket_(
1057     GstBuffer* gstbuffer, const EsPacketPtr& packet,
1058     const drm::EsPlayerEncryptedInfo& drm_info) {
1059   if (drm_info.handle == 0) return;
1060   auto serialized_drm_info_ptr = esplayer_drm::Serialize(packet, drm_info);
1061   GstStructure* gst_drm_info_structure =
1062       gst_structure_new("drm_info", "drm_specific_info", G_TYPE_BYTES,
1063                         serialized_drm_info_ptr.get(), nullptr);
1064   if (gst_drm_info_structure) {
1065     gst_mini_object_set_qdata(
1066         GST_MINI_OBJECT(gstbuffer), g_quark_from_static_string("drm_info"),
1067         gst_drm_info_structure, (GDestroyNotify)gst_structure_free);
1068   }
1069 }
1070
1071 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
1072                                                  SubmitPacketOperator op) {
1073   if (state_manager_.GetState() < EsState::kIdle) {
1074     return PacketSubmitStatus::kNotPrepared;
1075   }
1076   if (!packet) return PacketSubmitStatus::kInvalidPacket;
1077
1078   TrackType type = static_cast<TrackType>(packet->GetType());
1079   Track activated_track;
1080   if (!track_util::GetActiveTrack(track_, type, &activated_track))
1081     return PacketSubmitStatus::kInvalidPacket;
1082
1083   if (state_manager_.GetState() == EsState::kPaused ||
1084       state_manager_.GetState() == EsState::kReady) {
1085     internal::AppsrcQueueSizeOption byte_based, time_based;
1086     switch (type) {
1087       case kTrackTypeAudio:
1088         byte_based.max_size = src_queue_size_.kMaxByteOfAudioSrcQueue;
1089         time_based.max_size = src_queue_size_.kMaxTimeOfAudioSrcQueue;
1090         byte_based.threshold = src_queue_size_.kMinByteThresholdOfAudioSrcQueue;
1091         time_based.threshold = src_queue_size_.kMinTimeThresholdOfAudioSrcQueue;
1092         break;
1093       case kTrackTypeVideo:
1094         byte_based.max_size = src_queue_size_.kMaxByteOfVideoSrcQueue;
1095         time_based.max_size = src_queue_size_.kMaxTimeOfVideoSrcQueue;
1096         byte_based.threshold = src_queue_size_.kMinByteThresholdOfVideoSrcQueue;
1097         time_based.threshold = src_queue_size_.kMinTimeThresholdOfVideoSrcQueue;
1098         break;
1099       default:
1100         break;
1101     }
1102     GetSrcQueueCurrentSize_(type, &(byte_based.current_size),
1103                             &(time_based.current_size));
1104     if (internal::IsUnderRun(byte_based, time_based))
1105       trackrenderer_event_listener_->OnBufferStatus(type,
1106                                                     BufferStatus::kUnderrun);
1107   }
1108
1109   es_packet_logger_.StorePacketInfo(packet);
1110   es_packet_logger_.PrintStoredPacketInfo(packet->GetType());
1111
1112   MakeBufferStatus make_buffer_status;
1113   GstBuffer* gstbuffer = GetGstBuffer_(packet, &make_buffer_status);
1114   if (!gstbuffer) {
1115     if (make_buffer_status == MakeBufferStatus::kEos)
1116       return SubmitEosPacket_(type);
1117     else if (make_buffer_status == MakeBufferStatus::kOutOfMemory)
1118       return PacketSubmitStatus::kOutOfMemory;
1119   }
1120   if (op != nullptr) {
1121     PacketSubmitStatus op_status = op(gstbuffer);
1122     if (op_status != PacketSubmitStatus::kSuccess) {
1123       return op_status;
1124     }
1125   }
1126
1127   auto inbuffer = DecoderInputBuffer::Create(type, 0, gstbuffer);
1128   gst_buffer_unref(gstbuffer);
1129
1130   if (packet->HasMatroskaColorInfo()) {
1131     std::string color_info_str =
1132         util::GetStringFromMatroskaColor(packet->GetMatroskaColorInfo());
1133     LOG_DEBUG_P(this, "Detected MatroskaColor : %s", color_info_str.c_str());
1134     if (trackrenderer_->SetMatroskaColorInfo(color_info_str) == false)
1135       return PacketSubmitStatus::kNotPrepared;
1136   }
1137
1138   return SubmitDecoderInputBuffer_(inbuffer);
1139 }
1140
1141 PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
1142   std::lock_guard<std::mutex> lk(submit_mutex_);
1143   return SubmitPacketCommon_(packet, nullptr);
1144 }
1145
1146 PacketSubmitStatus EsPlayer::SubmitTrustZonePacket(const EsPacketPtr& packet,
1147                                                    uint32_t tz_handle) {
1148   std::lock_guard<std::mutex> lk(submit_mutex_);
1149   if (submit_data_type_ != SubmitDataType::kTrustZoneData)
1150     return PacketSubmitStatus::kInvalidPacket;
1151   auto submitpacket_op = [this, &tz_handle,
1152                           &packet](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1153     if (tz_handle > 0) {
1154       TrackType type = static_cast<TrackType>(packet->GetType());
1155       uint32_t packet_size = packet->GetSize();
1156       MakeGstBufferForTzHandle_(gstbuffer, type, tz_handle, packet_size);
1157     }
1158     return PacketSubmitStatus::kSuccess;
1159   };
1160   return SubmitPacketCommon_(packet, submitpacket_op);
1161 }
1162
1163 PacketSubmitStatus EsPlayer::SubmitEncryptedPacket(
1164     const EsPacketPtr& packet, const drm::EsPlayerEncryptedInfo& drm_info) {
1165   std::lock_guard<std::mutex> lk(submit_mutex_);
1166   if (submit_data_type_ != SubmitDataType::kEncryptedData)
1167     return PacketSubmitStatus::kInvalidPacket;
1168   auto submitpacket_op =
1169       [this, &packet, &drm_info](GstBuffer* gstbuffer) -> PacketSubmitStatus {
1170     MakeGstBufferForEncryptedPacket_(gstbuffer, packet, drm_info);
1171     return PacketSubmitStatus::kSuccess;
1172   };
1173   return SubmitPacketCommon_(packet, submitpacket_op);
1174 }
1175
1176 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
1177
1178 bool EsPlayer::GetPlayingTime(uint64_t* time_in_milliseconds) {
1179   if (!time_in_milliseconds) return false;
1180   if (state_manager_.GetState() <= EsState::kReady) {
1181     *time_in_milliseconds = 0;
1182     return false;
1183   }
1184   return trackrenderer_->GetPlayingTime(time_in_milliseconds);
1185 }
1186
1187 bool EsPlayer::SetAudioMute(bool is_mute) {
1188   if (state_manager_.GetState() < EsState::kIdle) {
1189     LOG_ERROR_P(this, "Invalid State , current %d",
1190                 state_manager_.GetStateEnum());
1191     return false;
1192   }
1193   return trackrenderer_->SetAudioMute(is_mute);
1194 }
1195
1196 bool EsPlayer::SetVideoFrameBufferType(DecodedVideoFrameBufferType type) {
1197   if (state_manager_.GetState() != EsState::kIdle) {
1198     LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
1199     return false;
1200   }
1201   trackrenderer_->SetVideoFrameBufferType(type);
1202   return true;
1203 }
1204
1205 void EsPlayer::RegisterListener(EsEventListener* listener,
1206                                 EsEventListener::UserData userdata) {
1207   // assert(listener); // allow unregister by setting nullptr
1208   assert(!eventlistener_);
1209   eventlistener_ = listener;
1210   eventlistener_userdata_ = userdata;
1211 }
1212
1213 bool EsPlayer::GetAdaptiveInfo(void* padaptive_info,
1214                                const PlayerAdaptiveInfo& adaptive_type) {
1215   if (!padaptive_info || adaptive_type <= PlayerAdaptiveInfo::kMinType ||
1216       adaptive_type >= PlayerAdaptiveInfo::kMaxType)
1217     return false;
1218   switch (adaptive_type) {
1219     case PlayerAdaptiveInfo::kVideoDroppedFrames:
1220       if (state_manager_.GetState() < EsState::kReady) {
1221         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1222         return false;
1223       }
1224       return trackrenderer_->GetDroppedFrames(padaptive_info);
1225     case PlayerAdaptiveInfo::kDroppedVideoFramesForCatchup:
1226       if (state_manager_.GetState() < EsState::kReady) {
1227         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1228         return false;
1229       }
1230       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeVideo,
1231                                                         padaptive_info);
1232     case PlayerAdaptiveInfo::kDroppedAudioFramesForCatchup:
1233       if (state_manager_.GetState() < EsState::kReady) {
1234         LOG_ERROR_P(this, "Wrong state, we aren't started yet");
1235         return false;
1236       }
1237       return trackrenderer_->GetDroppedFramesForCatchup(kTrackTypeAudio,
1238                                                         padaptive_info);
1239     default:
1240       break;
1241   }
1242   return false;
1243 }
1244
1245 bool EsPlayer::SetVolume(const int& volume) {
1246   if (volume < internal::kVolumeMin || volume > internal::kVolumeMax) {
1247     LOG_ERROR_P(this, "Invalid volume level %d", volume);
1248     return false;
1249   }
1250   if (state_manager_.GetState() < EsState::kIdle) {
1251     LOG_ERROR_P(this, "Invalid State , current %d",
1252                 state_manager_.GetStateEnum());
1253     return false;
1254   }
1255   return trackrenderer_->SetVolume(volume);
1256 }
1257
1258 bool EsPlayer::GetVolume(int* volume) {
1259   if (state_manager_.GetState() < EsState::kIdle) {
1260     LOG_ERROR_P(this, "Invalid State , current %d",
1261                 state_manager_.GetStateEnum());
1262     return false;
1263   }
1264   return trackrenderer_->GetVolume(volume);
1265 }
1266
1267 bool EsPlayer::Flush(const StreamType& type) {
1268   if (state_manager_.GetState() <= EsState::kIdle) {
1269     LOG_ERROR_P(this, "Invalid State , current %d",
1270                 state_manager_.GetStateEnum());
1271     return false;
1272   }
1273   std::lock_guard<std::mutex> lock2(eos_mutex_);
1274   eos_status_ =
1275       internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
1276   es_packet_logger_.ResetLog(type);
1277   return trackrenderer_->Flush(type);
1278 }
1279
1280 void EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
1281   if (state_manager_.GetState() != EsState::kIdle) {
1282     LOG_ERROR_P(this, "Invalid State , current %d",
1283                 state_manager_.GetStateEnum());
1284     return;
1285   }
1286   switch (option) {
1287     case BufferOption::kBufferAudioMaxByteSize:
1288       src_queue_size_.kMaxByteOfAudioSrcQueue = size;
1289       break;
1290     case BufferOption::kBufferVideoMaxByteSize:
1291       src_queue_size_.kMaxByteOfVideoSrcQueue = size;
1292       break;
1293     case BufferOption::kBufferAudioMinByteThreshold:
1294       src_queue_size_.kMinByteThresholdOfAudioSrcQueue =
1295           static_cast<uint32_t>(size);
1296       break;
1297     case BufferOption::kBufferVideoMinByteThreshold:
1298       src_queue_size_.kMinByteThresholdOfVideoSrcQueue =
1299           static_cast<uint32_t>(size);
1300       break;
1301     case BufferOption::kBufferAudioMaxTimeSize:
1302       src_queue_size_.kMaxTimeOfAudioSrcQueue = size;
1303       break;
1304     case BufferOption::kBufferVideoMaxTimeSize:
1305       src_queue_size_.kMaxTimeOfVideoSrcQueue = size;
1306       break;
1307     case BufferOption::kBufferAudioMinTimeThreshold:
1308       src_queue_size_.kMinTimeThresholdOfAudioSrcQueue =
1309           static_cast<uint32_t>(size);
1310       break;
1311     case BufferOption::kBufferVideoMinTimeThreshold:
1312       src_queue_size_.kMinTimeThresholdOfVideoSrcQueue =
1313           static_cast<uint32_t>(size);
1314       break;
1315     default:
1316       LOG_ERROR_P(this, "Invalid option!!!");
1317       break;
1318   }
1319 }
1320
1321 bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
1322   if (state_manager_.GetState() != EsState::kIdle) {
1323     LOG_ERROR_P(this, "Invalid State , current %d",
1324                 state_manager_.GetStateEnum());
1325     return false;
1326   }
1327   low_latency_mode_ |= static_cast<std::uint32_t>(mode);
1328   return true;
1329 }
1330
1331 bool EsPlayer::SetUnlimitedMaxBufferMode() {
1332   if (state_manager_.GetState() != EsState::kIdle) {
1333     LOG_ERROR_P(this, "Invalid State , current %d",
1334                 state_manager_.GetStateEnum());
1335     return false;
1336   }
1337   constexpr std::uint32_t unlimited_max_buffer_mode_on = 1;
1338   unlimited_max_buffer_mode_ = unlimited_max_buffer_mode_on;
1339   return true;
1340 }
1341
1342 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
1343   Track activated_track;
1344   bool is_existed =
1345       track_util::GetActiveTrack(track_, kTrackTypeAudio, &activated_track);
1346   EsState state = state_manager_.GetState();
1347   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
1348     LOG_ERROR_P(this,
1349                 "Invalid State [state:%d] or audio stream already exists[%d],",
1350                 state_manager_.GetStateEnum(), is_existed);
1351     return false;
1352   }
1353   if (force_audio_swdecoder_use_ && type == kPlayerAudioCodecTypeHW) {
1354     LOG_ERROR_P(this, "Not support hw decoder");
1355     return false;
1356   }
1357   LOG_INFO_P(this, "PlayerAudioCodecType [%s]",
1358              (type == kPlayerAudioCodecTypeHW) ? "hardware" : "software");
1359   audio_codec_type_ = type;
1360   return true;
1361 }
1362
1363 bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
1364   Track activated_track;
1365   bool is_existed =
1366       track_util::GetActiveTrack(track_, kTrackTypeVideo, &activated_track);
1367   EsState state = state_manager_.GetState();
1368   if ((state < EsState::kIdle) || (state > EsState::kIdle && is_existed)) {
1369     LOG_ERROR_P(this,
1370                 "Invalid State [state:%d] or video stream already exists[%d],",
1371                 state_manager_.GetStateEnum(), is_existed);
1372     return false;
1373   }
1374   if (type == kPlayerVideoCodecTypeSW &&
1375       vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
1376     LOG_ERROR_P(this,
1377                 "sw video decoder is not supported when video frame buffer "
1378                 "type is scale");
1379     return false;
1380   }
1381   LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
1382              (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
1383   video_codec_type_ = type;
1384   return true;
1385 }
1386
1387
1388 bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
1389   if (state_manager_.GetState() < EsState::kReady) {
1390     LOG_ERROR_P(this, "Invalid State , current %d",
1391                 state_manager_.GetStateEnum());
1392     return false;
1393   }
1394   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1395     LOG_ERROR_P(this,
1396                 "low latency mode have to be set except disable_sync mode");
1397     return false;
1398   }
1399   /* FIME: time unit api will be added to support both ms and us */
1400   if ((offset * 1000000 > G_MAXINT64) || (offset * 1000000 < G_MININT64)) {
1401     LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
1402               "] * 1000000 < G_MAXINT64",
1403         this, offset);
1404     return false;
1405   }
1406   if (type == StreamType::kMax) return false;
1407   if (type == StreamType::kAudio)
1408     trackrenderer_->SetAttribute(
1409         TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
1410         util::ConvertMsToNs(offset));
1411   else if (type == StreamType::kVideo)
1412     trackrenderer_->SetAttribute(
1413         TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
1414         util::ConvertMsToNs(offset));
1415   return true;
1416 }
1417
1418 bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
1419   if (state_manager_.GetState() < EsState::kReady) {
1420     LOG_ERROR_P(this, "Invalid State , current %d",
1421                 state_manager_.GetStateEnum());
1422     return false;
1423   }
1424   if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
1425     LOG_ERROR_P(this, "low latency mode have to be set");
1426     return false;
1427   }
1428   if (type == StreamType::kMax) return false;
1429   boost::any off_set;
1430   if (type == StreamType::kAudio)
1431     trackrenderer_->GetAttribute(
1432         TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
1433   else if (type == StreamType::kVideo)
1434     trackrenderer_->GetAttribute(
1435         TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
1436
1437   *offset = util::ConvertNsToMs(boost::any_cast<int64_t>(off_set));
1438
1439   return true;
1440 }
1441
1442 void EsPlayer::Init_() {
1443   track_.clear();
1444   is_stopped_ = false;
1445   LOG_LEAVE_P(this);
1446 }
1447
1448 void EsPlayer::MsgTask_() {
1449   while (!is_msg_task_stop_) {
1450     std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
1451     if (msg_queue_.empty()) {
1452       msg_task_cv_.wait(msg_mutex);
1453     } else {
1454       msg_mutex.unlock();
1455       msg_queue_.front()->Execute();
1456       msg_mutex.lock();
1457       msg_queue_.pop();
1458     }
1459   }
1460   while (!msg_queue_.empty()) {
1461     std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
1462     msg_queue_.pop();
1463   }
1464   LOG_INFO_P(this, "Stop MsgTask");
1465 }
1466
1467 void EsPlayer::TrackRendererEventListener::OnEos() {
1468   LOG_ENTER_P(handler_);
1469   if (!handler_->eventlistener_) return;
1470   auto listener = std::bind(&plusplayer::EsEventListener::OnEos,
1471                             handler_->eventlistener_, std::placeholders::_1);
1472   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
1473   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1474   handler_->msg_queue_.push(std::move(msg));
1475   msg_mutex.unlock();
1476   handler_->msg_task_cv_.notify_one();
1477   LOG_LEAVE_P(handler_);
1478 }
1479
1480 void EsPlayer::TrackRendererEventListener::OnSeekDone() {
1481   LOG_ENTER_P(handler_);
1482   if (!handler_->eventlistener_) return;
1483   if (handler_->is_seek_done_need_drop == true) return;
1484   auto listener = std::bind(&plusplayer::EsEventListener::OnSeekDone,
1485                             handler_->eventlistener_, std::placeholders::_1);
1486   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
1487   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1488   handler_->msg_queue_.push(std::move(msg));
1489   msg_mutex.unlock();
1490   handler_->msg_task_cv_.notify_one();
1491   LOG_LEAVE_P(handler_);
1492 }
1493
1494 void EsPlayer::TrackRendererEventListener::OnResourceConflicted() {
1495   LOG_ENTER_P(handler_);
1496   if (handler_->is_stopped_) {
1497     LOG_INFO_P(handler_, "LEAVE ~ Stop is called already");
1498     return;
1499   }
1500   LOG_INFO_P(handler_, "Handling resource conflict...");
1501   handler_->is_resource_conflicted_ = true;
1502   handler_->trackrenderer_->Stop();
1503   if (!handler_->eventlistener_ || handler_->is_stopped_) return;
1504   auto listener = std::bind(&plusplayer::EsEventListener::OnResourceConflicted,
1505                             handler_->eventlistener_, std::placeholders::_1);
1506   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
1507   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1508   handler_->msg_queue_.push(std::move(msg));
1509   msg_mutex.unlock();
1510   if (handler_->is_stopped_) {
1511     LOG_LEAVE_P(handler_);
1512     return;
1513   }
1514   handler_->msg_task_cv_.notify_one();
1515   LOG_LEAVE_P(handler_);
1516 }
1517
1518 void EsPlayer::TrackRendererEventListener::OnError(
1519     const ErrorType& error_code) {
1520   if (!handler_->eventlistener_) return;
1521   if (error_code == ErrorType::kResourceLimit) return;
1522   auto listener =
1523       std::bind(&plusplayer::EsEventListener::OnError, handler_->eventlistener_,
1524                 std::placeholders::_1, std::placeholders::_2);
1525   auto msg = es_msg::Error::Make(error_code, listener,
1526                                  handler_->eventlistener_userdata_);
1527
1528   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1529   handler_->msg_queue_.push(std::move(msg));
1530   msg_mutex.unlock();
1531   handler_->msg_task_cv_.notify_one();
1532 }
1533
1534 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
1535     const TrackType& type) {
1536   LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
1537              (type == kTrackTypeAudio) ? "audio" : "video");
1538
1539   handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
1540
1541   auto listener = std::bind(&plusplayer::EsEventListener::OnReadyToPrepare,
1542                             handler_->eventlistener_, std::placeholders::_1,
1543                             std::placeholders::_2);
1544   StreamType stream_type = internal::ConvertToStreamType(type);
1545   auto msg = es_msg::ReadyToPrepare::Make(stream_type, listener,
1546                                           handler_->eventlistener_userdata_);
1547   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1548   handler_->msg_queue_.push(std::move(msg));
1549   msg_mutex.unlock();
1550   handler_->msg_task_cv_.notify_one();
1551 }
1552
1553 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
1554   uint64_t offset = handler_->need_data_[type].seek_offset;
1555
1556   LOG_INFO("[%p] > OnReadyToSeek [%s] offset [%" PRIu64 "]ms", handler_,
1557              (type == kTrackTypeAudio) ? "audio" : "video", offset);
1558
1559   handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
1560   handler_->need_data_[type].seek_offset = 0;
1561
1562   auto listener = std::bind(&plusplayer::EsEventListener::OnReadyToSeek,
1563                             handler_->eventlistener_, std::placeholders::_1,
1564                             std::placeholders::_2, std::placeholders::_3);
1565   StreamType stream_type = internal::ConvertToStreamType(type);
1566   handler_->es_packet_logger_.ResetLog(stream_type);
1567   auto msg = es_msg::ReadyToSeek::Make(stream_type, offset, listener,
1568                                        handler_->eventlistener_userdata_);
1569   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1570   handler_->msg_queue_.push(std::move(msg));
1571   msg_mutex.unlock();
1572   handler_->msg_task_cv_.notify_one();
1573 }
1574
1575 void EsPlayer::TrackRendererEventListener::BufferStatus_(
1576     const TrackType& type, const BufferStatus& status) {
1577   uint64_t byte_size, time_size;
1578   // LOG_INFO_P(handler_, "OnBufferStatus [%s] [%s]",
1579   //        (type == kTrackTypeAudio) ? "audio" : "video",
1580   //        (status == BufferStatus::kUnderrun) ? "underrun" : "overrun");
1581   handler_->GetSrcQueueCurrentSize_(type, &byte_size, &time_size);
1582   auto listener = std::bind(&plusplayer::EsEventListener::OnBufferStatus,
1583                             handler_->eventlistener_, std::placeholders::_1,
1584                             std::placeholders::_2, std::placeholders::_3,
1585                             std::placeholders::_4, std::placeholders::_5);
1586   StreamType stream_type = internal::ConvertToStreamType(type);
1587   auto msg =
1588       es_msg::Bufferstatus::Make(stream_type, status, byte_size, time_size,
1589                                  listener, handler_->eventlistener_userdata_);
1590   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1591   handler_->msg_queue_.push(std::move(msg));
1592   msg_mutex.unlock();
1593   handler_->msg_task_cv_.notify_one();
1594 }
1595
1596 void EsPlayer::TrackRendererEventListener::OnBufferStatus(
1597     const TrackType& type, const BufferStatus& status) {
1598   if (!handler_->eventlistener_) return;
1599   if (internal::IsLowLatencyModeDisableAVSync(handler_->low_latency_mode_))
1600     return;
1601
1602   if (handler_->need_data_[type].mask == kNeedDataMaskByPrepare &&
1603       status == BufferStatus::kUnderrun) {
1604     ReadyToPrepare_(type);
1605   } else if (handler_->need_data_[type].mask == kNeedDataMaskBySeek &&
1606              status == BufferStatus::kUnderrun) {
1607     ReadyToSeek_(type);
1608   } else {
1609     BufferStatus_(type, status);
1610   }
1611 }
1612
1613 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
1614     const DecodedVideoPacket& packet) {
1615   if (!handler_->eventlistener_) return;
1616
1617   handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
1618 }
1619
1620 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
1621                                                       const uint64_t offset) {
1622   if (!handler_->eventlistener_) return;
1623
1624   if (handler_->need_data_[type].mask != kNeedDataMaskByPrepare) {
1625     handler_->need_data_[type].mask |= kNeedDataMaskBySeek;
1626     handler_->need_data_[type].seek_offset = offset;
1627   }
1628 }
1629
1630 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
1631                                                                const int size) {
1632   if (size <= 0) return;
1633   if (!handler_->eventlistener_) return;
1634   auto listener = std::bind(&plusplayer::EsEventListener::OnClosedCaptionData,
1635                             handler_->eventlistener_, std::placeholders::_1,
1636                             std::placeholders::_2, std::placeholders::_3);
1637   auto msg = es_msg::ClosedCaption::Make(data, size, listener,
1638                                          handler_->eventlistener_userdata_);
1639   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1640   handler_->msg_queue_.push(std::move(msg));
1641   msg_mutex.unlock();
1642   handler_->msg_task_cv_.notify_one();
1643 }
1644
1645 void EsPlayer::TrackRendererEventListener::OnFlushDone() {
1646   LOG_ENTER_P(handler_);
1647   if (!handler_->eventlistener_) return;
1648
1649   auto listener = std::bind(&plusplayer::EsEventListener::OnFlushDone,
1650                             handler_->eventlistener_, std::placeholders::_1);
1651   auto msg =
1652       es_msg::FlushDone::Make(listener, handler_->eventlistener_userdata_);
1653   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1654   handler_->msg_queue_.push(std::move(msg));
1655   msg_mutex.unlock();
1656   handler_->msg_task_cv_.notify_one();
1657   LOG_LEAVE_P(handler_);
1658 }
1659
1660 void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
1661                                                    const EventMsg& msg_data) {
1662   if (!handler_->eventlistener_) return;
1663
1664   auto listener = std::bind(&plusplayer::EsEventListener::OnEvent,
1665                             handler_->eventlistener_, std::placeholders::_1,
1666                             std::placeholders::_2, std::placeholders::_3);
1667   auto msg = es_msg::OnEvent::Make(event, msg_data, listener,
1668                                    handler_->eventlistener_userdata_);
1669   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1670   handler_->msg_queue_.push(std::move(msg));
1671   msg_mutex.unlock();
1672   handler_->msg_task_cv_.notify_one();
1673   LOG_LEAVE_P(handler_);
1674 }
1675
1676 void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
1677   LOG_ENTER_P(handler_);
1678   if (!handler_->eventlistener_) return;
1679   auto listener = std::bind(&plusplayer::EsEventListener::OnFirstDecodingDone,
1680                             handler_->eventlistener_, std::placeholders::_1);
1681   auto msg = es_msg::FirstDecodingDone::Make(listener,
1682                                              handler_->eventlistener_userdata_);
1683   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
1684   handler_->msg_queue_.push(std::move(msg));
1685   msg_mutex.unlock();
1686   handler_->msg_task_cv_.notify_one();
1687   LOG_LEAVE_P(handler_);
1688 }
1689
1690 bool EsPlayer::EnableVideoHole(bool value) {
1691   if (state_manager_.GetState() < EsState::kIdle) {
1692     LOG_ERROR_P(this, "Invalid State , current %d",
1693                 state_manager_.GetStateEnum());
1694     return false;
1695   }
1696   return trackrenderer_->EnableVideoHole(value);
1697 }
1698
1699 namespace es_conf {
1700
1701 void LoadIniProperty(const Json::Value& root) {
1702   gst_util::GstInit(root);
1703   std::string key = "generate_dot";
1704   es_conf::ini_property[key] = root.get(key, "").asBool();
1705   LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
1706
1707   key = "use_default_video_codec_sw";
1708   es_conf::ini_property[key] = root.get(key, "").asBool();
1709   LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
1710 }
1711
1712 bool LoadIniFile() {
1713   const char* path = plusplayer_cfg::GetIniPath();
1714   LOG_INFO("path : %s", path);
1715   std::streampos size;
1716   char* buf = nullptr;
1717   std::ifstream file(path, std::ios::binary | std::ios::ate);
1718   if (file.is_open() == false) {
1719     gst_util::GstInit();
1720     LOG_ERROR("Can't open file !!");
1721     return false;
1722   }
1723   BOOST_SCOPE_EXIT(&file) { file.close(); }
1724   BOOST_SCOPE_EXIT_END
1725
1726   size = file.tellg();
1727   if (size <= 0) {
1728     LOG_ERROR("Wrong file size");
1729     return false;
1730   }
1731   size += 1;
1732   buf = static_cast<char*>(calloc(size, sizeof(char)));
1733   if (buf == nullptr) {
1734     LOG_ERROR("Fail to calloc buf");
1735     return false;
1736   }
1737   BOOST_SCOPE_EXIT(&buf) {
1738     if (buf) free(buf);
1739   }
1740   BOOST_SCOPE_EXIT_END
1741
1742   file.seekg(0, std::ios::beg);
1743   file.read(buf, size);
1744
1745   std::string config = buf;
1746   Json::Value root;
1747   Json::Reader reader;
1748   if (!reader.parse(config, root)) {
1749     LOG_ERROR("Fail to parse configuration file %s",
1750               (reader.getFormatedErrorMessages()).c_str());
1751     return false;
1752   }
1753
1754   es_conf::LoadIniProperty(root);
1755   return true;
1756 }
1757
1758 }  // namespace es_conf
1759
1760 }  // namespace plusplayer