Support video capture during playback
[platform/core/multimedia/esplusplayer.git] / src / esplusplayer / src / esplusplayer_capi.cpp
1 #include "esplusplayer_capi/esplusplayer_capi.h"
2
3 #include "plusplayer/esplusplayer.h"
4
5 using plusplayer::EsPlusPlayer;
6 using plusplayer::Geometry;
7
8 #include <inttypes.h>
9 #include <tbm_surface.h>
10
11 #include <functional>
12 #include <iostream>
13 #include <mutex>
14 #include <unordered_map>
15
16 #include "core/utils/plusplayer_log.h"
17 #include "esplayer/decoded_pkt_list.h"
18 #include "esplusplayer_capi/esplusplayer_internal.h"
19 #include "plusplayer/drm.h"
20 #include "plusplayer/elementary_stream.h"
21 #include "plusplayer/espacket.h"
22 #include "plusplayer/esplusplayer.h"
23 #include "plusplayer/track.h"
24 #include "plusplayer/types/buffer.h"
25 #include "plusplayer/types/display.h"
26 #include "plusplayer/types/error.h"
27 #include "plusplayer/types/stream.h"
28
29 using plusplayer::AudioMimeType;
30 using plusplayer::AudioStream;
31 using plusplayer::AudioStreamPtr;
32 using plusplayer::BufferStatus;
33 using plusplayer::CropArea;
34 using plusplayer::DecodedPacketManagerInterface;
35 using plusplayer::DisplayMode;
36 using plusplayer::DisplayRotation;
37 using plusplayer::DisplayType;
38 using plusplayer::ErrorType;
39 using plusplayer::EsPacket;
40 using plusplayer::EsPacketPtr;
41 using plusplayer::EsState;
42 using plusplayer::MatroskaColor;
43 using plusplayer::PlayerAdaptiveInfo;
44 using plusplayer::PlayerLowLatencyMode;
45 using plusplayer::StreamType;
46 using plusplayer::SubmitDataType;
47 using plusplayer::Track;
48 using plusplayer::TrackType;
49 using plusplayer::VideoMimeType;
50 using plusplayer::VideoStream;
51 using plusplayer::VideoStreamPtr;
52 using plusplayer::drm::EsPlayerEncryptedInfo;
53 using plusplayer::drm::Type;
54 using plusplayer::PlayerAudioCodecType;
55 using plusplayer::PlayerVideoCodecType;
56
57 namespace util {
58 const std::unordered_map<esplusplayer_error_type, std::string> kErrorStringMap =
59     {{ESPLUSPLAYER_ERROR_TYPE_NONE, "ESPLUSPLAYER_ERROR_TYPE_NONE"},
60      {ESPLUSPLAYER_ERROR_TYPE_OUT_OF_MEMORY,
61       "ESPLUSPLAYER_ERROR_TYPE_OUT_OF_MEMORY"},
62      {ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER,
63       "ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER"},
64      {ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION,
65       "ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION"},
66      {ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE,
67       "ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE"},
68      {ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_AUDIO_CODEC,
69       "ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_AUDIO_CODEC"},
70      {ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_VIDEO_CODEC,
71       "ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_VIDEO_CODEC"},
72      {ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE,
73       "ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE"},
74      {ESPLUSPLAYER_ERROR_TYPE_CONNECTION_FAILED,
75       "ESPLUSPLAYER_ERROR_TYPE_CONNECTION_FAILED"},
76      {ESPLUSPLAYER_ERROR_TYPE_DRM_EXPIRED,
77       "ESPLUSPLAYER_ERROR_TYPE_DRM_EXPIRED"},
78      {ESPLUSPLAYER_ERROR_TYPE_DRM_NO_LICENSE,
79       "ESPLUSPLAYER_ERROR_TYPE_DRM_NO_LICENSE"},
80      {ESPLUSPLAYER_ERROR_TYPE_DRM_FUTURE_USE,
81       "ESPLUSPLAYER_ERROR_TYPE_DRM_FUTURE_USE"},
82      {ESPLUSPLAYER_ERROR_TYPE_NOT_PERMITTED,
83       "ESPLUSPLAYER_ERROR_TYPE_NOT_PERMITTED"},
84      {ESPLUSPLAYER_ERROR_TYPE_DRM_DECRYPTION_FAILED,
85       "ESPLUSPLAYER_ERROR_TYPE_DRM_DECRYPTION_FAILED"},
86      {ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FORMAT,
87       "ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FORMAT"},
88      {ESPLUSPLAYER_ERROR_TYPE_UNKNOWN, "ESPLUSPLAYER_ERROR_TYPE_UNKNOWN"}};
89
90 const std::string kUnhandledErrorString = "Unhandled Error Type";
91 static const std::string& ConvertErrorTypeToString(
92     esplusplayer_error_type type) {
93   return kErrorStringMap.count(type) > 0 ? kErrorStringMap.at(type)
94                                          : kUnhandledErrorString;
95 }
96 }  // namespace util
97
98 struct EsPlusPlayerPriv;
99
100 class listener_bridge : public plusplayer::EsEventListener {
101  public:
102   listener_bridge() { LOG_ENTER }
103   ~listener_bridge() { LOG_ENTER }
104
105   void ResetPacketList() {
106     if (decoded_pkt_mgr_) decoded_pkt_mgr_->Clear();
107   }
108
109   void ResetMultiSeekControl() {
110     std::unique_lock<std::mutex> lock(multi_seek_control.lock);
111     multi_seek_control.is_offset_valid = false;
112     multi_seek_control.offset = 0;
113   }
114
115   void Reset() {
116     LOG_ENTER
117     ResetPacketList();
118     ResetMultiSeekControl();
119     LOG_LEAVE
120   }
121
122   esplusplayer_error_type ConvertErrorCode(const ErrorType& error_code) {
123     esplusplayer_error_type type = ESPLUSPLAYER_ERROR_TYPE_NONE;
124     switch (error_code) {
125       case ErrorType::kOutOfMemory:
126         type = ESPLUSPLAYER_ERROR_TYPE_OUT_OF_MEMORY;
127         break;
128       case ErrorType::kInvalidParameter:
129         type = ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
130         break;
131       case ErrorType::kInvalidOperation:
132         type = ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
133         break;
134       case ErrorType::kInvalidState:
135         type = ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE;
136         break;
137       case ErrorType::kNotSupportedAudioCodec:
138         type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_AUDIO_CODEC;
139         break;
140       case ErrorType::kNotSupportedVideoCodec:
141         type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_VIDEO_CODEC;
142         break;
143       case ErrorType::kNotSupportedFile:
144         type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE;
145         break;
146       case ErrorType::kConnectionFailed:
147         type = ESPLUSPLAYER_ERROR_TYPE_CONNECTION_FAILED;
148         break;
149       case ErrorType::kDrmExpired:
150         type = ESPLUSPLAYER_ERROR_TYPE_DRM_EXPIRED;
151         break;
152       case ErrorType::kDrmNoLicense:
153         type = ESPLUSPLAYER_ERROR_TYPE_DRM_NO_LICENSE;
154         break;
155       case ErrorType::kDrmFutureUse:
156         type = ESPLUSPLAYER_ERROR_TYPE_DRM_FUTURE_USE;
157         break;
158       case ErrorType::kDrmNotPermitted:
159         type = ESPLUSPLAYER_ERROR_TYPE_NOT_PERMITTED;
160         break;
161       case ErrorType::kDrmInfo:
162         type = ESPLUSPLAYER_ERROR_TYPE_DRM_DECRYPTION_FAILED;
163         break;
164       case ErrorType::kNotSupportedFormat:
165         type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FORMAT;
166         break;
167       default:
168         LOG_ERROR("not defined error %x", static_cast<int>(error_code));
169         type = ESPLUSPLAYER_ERROR_TYPE_UNKNOWN;
170         break;
171     }
172     return type;
173   }
174
175   virtual void OnError(const ErrorType& error_code, UserData userdata) {
176     LOG_ENTER
177     LOG_INFO("error code : %x", static_cast<int>(error_code));
178     if (this->error_cb_)
179       this->error_cb_(ConvertErrorCode(error_code), error_cb_userdata_);
180   }
181
182   virtual void OnBufferStatus(const StreamType& type,
183                               const BufferStatus& status,
184                               const uint64_t byte_size,
185                               const uint64_t time_size, UserData userdata) {
186     // LOG_ENTER
187     // LOG_INFO("stream type : %d, buffer status : %d", static_cast<int>(type),
188     //          static_cast<int>(status));
189
190     if (this->buffer_status_cb_)
191       this->buffer_status_cb_(static_cast<esplusplayer_stream_type>(type),
192                               static_cast<esplusplayer_buffer_status>(status),
193                               buffer_status_cb_userdata_);
194     if (this->buffer_byte_status_cb_)
195       this->buffer_byte_status_cb_(
196           static_cast<esplusplayer_stream_type>(type),
197           static_cast<esplusplayer_buffer_status>(status), byte_size,
198           buffer_byte_status_cb_userdata_);
199     if (this->buffer_time_status_cb_)
200       this->buffer_time_status_cb_(
201           static_cast<esplusplayer_stream_type>(type),
202           static_cast<esplusplayer_buffer_status>(status), time_size,
203           buffer_time_status_cb_userdata_);
204   }
205
206   virtual void OnResourceConflicted(UserData userdata) {
207     LOG_ENTER
208     this->Reset();
209     if (this->resource_conflicted_cb_)
210       this->resource_conflicted_cb_(resource_conflicted_cb_userdata_);
211   }
212
213   virtual void OnEos(UserData userdata) {
214     LOG_ENTER
215     if (this->eos_cb_) this->eos_cb_(eos_cb_userdata_);
216   }
217
218   virtual void OnPrepareDone(bool result, UserData userdata) {
219     LOG_ENTER
220     LOG_INFO("prepare done. result : %s", result ? "true" : "false");
221     if (this->prepare_async_done_cb_)
222       this->prepare_async_done_cb_(result, prepare_async_done_cb_userdata_);
223   }
224
225   virtual void OnReadyToPrepare(const StreamType& type, UserData userdata) {
226     LOG_ENTER
227     LOG_INFO("stream type : %d", static_cast<int>(type));
228     if (this->ready_to_prepare_cb_)
229       this->ready_to_prepare_cb_(static_cast<esplusplayer_stream_type>(type),
230                                  ready_to_prepare_cb_userdata_);
231   }
232
233   virtual void OnSeekDone(UserData userdata) {
234     LOG_ENTER
235     if (this->seek_done_cb_) this->seek_done_cb_(seek_done_cb_userdata_);
236   }
237
238   virtual void OnReadyToSeek(const StreamType& type, const uint64_t offset,
239                              UserData userdata) {
240     LOG_ENTER
241     LOG_INFO("offset : %" PRIu64, offset);
242     std::unique_lock<std::mutex> lock(this->multi_seek_control.lock);
243     if (this->multi_seek_control.is_offset_valid == false ||
244         this->multi_seek_control.offset != offset) {
245       LOG_ERROR("Invalid offset:%" PRIu64, this->multi_seek_control.offset);
246       return;
247     }
248     if (this->ready_to_seek_cb_)
249       this->ready_to_seek_cb_(static_cast<esplusplayer_stream_type>(type),
250                               offset, ready_to_seek_cb_userdata_);
251   }
252
253   void SetDecodedPacketManager(
254       std::shared_ptr<DecodedPacketManagerInterface>& mgr) {
255     decoded_pkt_mgr_ = mgr;
256   }
257
258   virtual void OnMediaPacketGetTbmBufPtr(void** ptr, bool is_scale_change) {
259     // get one free point in current tbm list, send to trackrender, if can't
260     // find, set null
261     void* ptr1 = nullptr;
262     if (decoded_pkt_mgr_)
263       decoded_pkt_mgr_->GetFreeTbmSurface(&ptr1, is_scale_change);
264     *ptr = ptr1;
265   }
266
267   virtual void OnMediaPacketVideoDecoded(
268       const plusplayer::DecodedVideoPacket& packet) {
269     if (this->media_packet_video_decoded_cb_ == nullptr) return;
270     if (!decoded_pkt_mgr_) return;
271
272     auto* _pkt = new esplusplayer_decoded_video_packet();
273     _pkt->pts = packet.pts;
274     _pkt->duration = packet.duration;
275     _pkt->surface_data = static_cast<void*>(packet.surface_data);
276     _pkt->private_data = packet.buffer_addr;
277
278     if (decoded_pkt_mgr_->TryToAdd(_pkt)) {
279       this->media_packet_video_decoded_cb_(
280           _pkt, media_packet_video_decoded_cb_userdata_);
281     } else {
282       LOG_ERROR("Too many buffers are not released. packet(%p) will be drop.",
283                 _pkt);
284     }
285   }
286
287   virtual void OnClosedCaptionData(std::unique_ptr<char[]> data, const int size,
288                                    UserData userdata) {
289     LOG_ENTER
290     if (this->closed_caption_cb_) {
291       this->closed_caption_cb_(data.get(), size, closed_caption_cb_userdata_);
292     }
293   }
294
295   virtual void OnFlushDone(UserData userdata) {
296     LOG_ENTER
297     if (this->flush_done_cb_) this->flush_done_cb_(flush_done_cb_userdata_);
298   }
299
300   virtual void OnEvent(const plusplayer::EventType& event,
301                        const plusplayer::EventMsg& msg_data,
302                        UserData userdata) {
303     LOG_ENTER
304     esplusplayer_event_msg event_msg;
305     event_msg.data = const_cast<char*>(msg_data.data.c_str());
306     event_msg.len = msg_data.len;
307     if (this->event_cb_)
308       this->event_cb_(static_cast<esplusplayer_event_type>(event), event_msg,
309                       event_cb_userdata_);
310   }
311
312   virtual void OnFirstDecodingDone(UserData userdata) {
313     LOG_ENTER
314     if (this->first_video_decoding_done_cb_) {
315       this->first_video_decoding_done_cb_(
316           first_video_decoding_done_cb_userdata_);
317     }
318   }
319
320  private:
321   static void DecodedPacketDeleter(esplusplayer_decoded_video_packet* packet) {
322     if (packet->surface_data != nullptr) {
323       tbm_surface_destroy(static_cast<tbm_surface_h>(packet->surface_data));
324       packet->surface_data = NULL;
325     }
326     delete packet;
327   }
328
329  private:
330   esplusplayer_error_cb error_cb_ = nullptr;
331   void* error_cb_userdata_ = nullptr;
332   esplusplayer_buffer_status_cb buffer_status_cb_ = nullptr;
333   void* buffer_status_cb_userdata_ = nullptr;
334   esplusplayer_buffer_byte_status_cb buffer_byte_status_cb_ = nullptr;
335   void* buffer_byte_status_cb_userdata_ = nullptr;
336   esplusplayer_buffer_time_status_cb buffer_time_status_cb_ = nullptr;
337   void* buffer_time_status_cb_userdata_ = nullptr;
338   esplusplayer_resource_conflicted_cb resource_conflicted_cb_ = nullptr;
339   void* resource_conflicted_cb_userdata_ = nullptr;
340   esplusplayer_eos_cb eos_cb_ = nullptr;
341   void* eos_cb_userdata_ = nullptr;
342   esplusplayer_ready_to_prepare_cb ready_to_prepare_cb_ = nullptr;
343   void* ready_to_prepare_cb_userdata_ = nullptr;
344   esplusplayer_prepare_async_done_cb prepare_async_done_cb_ = nullptr;
345   void* prepare_async_done_cb_userdata_ = nullptr;
346   esplusplayer_seek_done_cb seek_done_cb_ = nullptr;
347   void* seek_done_cb_userdata_ = nullptr;
348   esplusplayer_ready_to_seek_cb ready_to_seek_cb_ = nullptr;
349   void* ready_to_seek_cb_userdata_ = nullptr;
350   esplusplayer_media_packet_video_decoded_cb media_packet_video_decoded_cb_ =
351       nullptr;
352   void* media_packet_video_decoded_cb_userdata_ = nullptr;
353   esplusplayer_closed_caption_cb closed_caption_cb_ = nullptr;
354   void* closed_caption_cb_userdata_ = nullptr;
355   esplusplayer_flush_done_cb flush_done_cb_ = nullptr;
356   void* flush_done_cb_userdata_ = nullptr;
357   esplusplayer_event_cb event_cb_ = nullptr;
358   void* event_cb_userdata_ = nullptr;
359   esplusplayer_first_video_decoding_done_cb first_video_decoding_done_cb_ =
360       nullptr;
361   void* first_video_decoding_done_cb_userdata_ = nullptr;
362
363   std::shared_ptr<DecodedPacketManagerInterface> decoded_pkt_mgr_;
364
365   struct MultiSeekControl {
366     std::mutex lock;
367     bool is_offset_valid = false;
368     uint64_t offset = 0;
369   };
370   friend void update_ready_to_seek_callback(
371       esplusplayer_handle pp, esplusplayer_ready_to_seek_cb ready_to_seek_cb,
372       void* userdata);
373   friend void update_ready_to_seek_offset(esplusplayer_handle pp,
374                                           const uint64_t offset);
375   MultiSeekControl multi_seek_control;
376
377   friend int esplusplayer_set_error_cb(esplusplayer_handle pp,
378                                        esplusplayer_error_cb error_cb,
379                                        void* userdata);
380   friend int esplusplayer_set_buffer_status_cb(
381       esplusplayer_handle pp, esplusplayer_buffer_status_cb buffer_status_cb,
382       void* userdata);
383   friend int esplusplayer_set_buffer_byte_status_cb(
384       esplusplayer_handle pp,
385       esplusplayer_buffer_byte_status_cb buffer_status_cb, void* userdata);
386   friend int esplusplayer_set_buffer_time_status_cb(
387       esplusplayer_handle pp,
388       esplusplayer_buffer_time_status_cb buffer_status_cb, void* userdata);
389   friend int esplusplayer_set_resource_conflicted_cb(
390       esplusplayer_handle pp,
391       esplusplayer_resource_conflicted_cb resource_conflicted_cb,
392       void* userdata);
393   friend int esplusplayer_set_eos_cb(esplusplayer_handle pp,
394                                      esplusplayer_eos_cb eos_cb,
395                                      void* userdata);
396   friend int esplusplayer_set_ready_to_prepare_cb(
397       esplusplayer_handle pp,
398       esplusplayer_ready_to_prepare_cb ready_to_prepare_cb, void* userdata);
399   friend int esplusplayer_set_prepare_async_done_cb(
400       esplusplayer_handle pp,
401       esplusplayer_prepare_async_done_cb prepare_async_done_cb, void* userdata);
402   friend int esplusplayer_set_seek_done_cb(
403       esplusplayer_handle pp, esplusplayer_seek_done_cb seek_done_cb,
404       void* userdata);
405   friend int esplusplayer_set_ready_to_seek_cb(
406       esplusplayer_handle pp, esplusplayer_ready_to_seek_cb ready_to_seek_cb,
407       void* userdata);
408   friend int esplusplayer_set_media_packet_video_decoded_cb(
409       esplusplayer_handle pp,
410       esplusplayer_media_packet_video_decoded_cb media_packet_video_decoded_cb,
411       void* userdata);
412   friend int esplusplayer_set_closed_caption_cb(
413       esplusplayer_handle handle,
414       esplusplayer_closed_caption_cb closed_caption_cb, void* userdata);
415   friend int esplusplayer_set_flush_done_cb(
416       esplusplayer_handle pp, esplusplayer_flush_done_cb flush_done_cb,
417       void* userdata);
418   friend int esplusplayer_set_event_cb(esplusplayer_handle pp,
419                                        esplusplayer_event_cb event_cb,
420                                        void* userdata);
421   friend int esplusplayer_set_first_video_decoding_done_cb(
422       esplusplayer_handle handle,
423       esplusplayer_first_video_decoding_done_cb first_video_decoding_done_cb,
424       void* userdata);
425 };
426
427 struct EsPlusPlayerPriv {
428   std::unique_ptr<EsPlusPlayer> player;
429   std::unique_ptr<listener_bridge> listener{new listener_bridge()};
430   std::shared_ptr<DecodedPacketManagerInterface> decoded_pkt_mgr;
431
432   friend EsPlusPlayerPriv* EsPrivCreate();
433   friend void EsPrivDestroy(EsPlusPlayerPriv*& instance);
434
435  private:
436   EsPlusPlayerPriv() {}
437   ~EsPlusPlayerPriv() {}
438 };
439
440 EsPlusPlayerPriv* EsPrivCreate() {
441   EsPlusPlayerPriv* instance = new EsPlusPlayerPriv();
442   instance->player = EsPlusPlayer::Create();
443   instance->player->RegisterListener(instance->listener.get(),
444                                      instance->player.get());
445   return instance;
446 }
447
448 void EsPrivDestroy(EsPlusPlayerPriv*& instance) {
449   if (instance) delete instance;
450   instance = nullptr;
451 }
452
453 inline bool is_null_(void* object) { return object == nullptr; }
454
455 inline EsPlusPlayer* cast_(esplusplayer_handle pp) {
456   auto priv = static_cast<EsPlusPlayerPriv*>(pp);
457   return priv ? priv->player.get() : nullptr;
458 }
459
460 inline listener_bridge* listener_cast_(esplusplayer_handle pp) {
461   auto priv = static_cast<EsPlusPlayerPriv*>(pp);
462   return priv->listener.get();
463 }
464
465 void update_ready_to_seek_callback(
466     esplusplayer_handle handle, esplusplayer_ready_to_seek_cb ready_to_seek_cb,
467     void* userdata) {
468   LOG_ENTER
469   listener_bridge* listener = nullptr;
470   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
471     LOG_ERROR("ESPlayer or Listener object is nil.");
472     return;
473   }
474   std::unique_lock<std::mutex> lock(listener->multi_seek_control.lock);
475   listener->ready_to_seek_cb_ = ready_to_seek_cb;
476   listener->ready_to_seek_cb_userdata_ = userdata;
477   listener->multi_seek_control.is_offset_valid = false;
478 }
479 void update_ready_to_seek_offset(esplusplayer_handle handle,
480                                  const uint64_t offset) {
481   LOG_ENTER
482   listener_bridge* listener = nullptr;
483   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
484     LOG_ERROR("ESPlayer or Listener object is nil.");
485     return;
486   }
487   std::unique_lock<std::mutex> lock(listener->multi_seek_control.lock);
488   listener->multi_seek_control.offset = offset;
489   listener->multi_seek_control.is_offset_valid = true;
490 }
491
492 inline void convert_matroska_color_info_(
493     const esplusplayer_matroska_color* from, MatroskaColor* to) {
494   to->matrix_coefficients = from->matrix_coefficients;
495   to->bits_per_channel = from->bits_per_channel;
496   to->chroma_subsampling_horizontal = from->chroma_subsampling_horizontal;
497   to->chroma_subsampling_vertical = from->chroma_subsampling_vertical;
498   to->cb_subsampling_horizontal = from->cb_subsampling_horizontal;
499   to->cb_subsampling_vertical = from->cb_subsampling_vertical;
500   to->chroma_siting_horizontal = from->chroma_siting_horizontal;
501   to->chroma_siting_vertical = from->chroma_siting_vertical;
502   to->range = from->range;
503   to->transfer_characteristics = from->transfer_characteristics;
504   to->primaries = from->primaries;
505   to->max_cll = from->max_cll;
506   to->max_fall = from->max_fall;
507   to->is_hdr_10p = from->isHDR10p;
508   to->metadata.primary_r_chromaticity_x =
509       from->metadata.primary_r_chromaticity_x;
510   to->metadata.primary_r_chromaticity_y =
511       from->metadata.primary_r_chromaticity_y;
512   to->metadata.primary_g_chromaticity_x =
513       from->metadata.primary_g_chromaticity_x;
514   to->metadata.primary_g_chromaticity_y =
515       from->metadata.primary_g_chromaticity_y;
516   to->metadata.primary_b_chromaticity_x =
517       from->metadata.primary_b_chromaticity_x;
518   to->metadata.primary_b_chromaticity_y =
519       from->metadata.primary_b_chromaticity_y;
520   to->metadata.white_point_chromaticity_x =
521       from->metadata.white_point_chromaticity_x;
522   to->metadata.white_point_chromaticity_y =
523       from->metadata.white_point_chromaticity_y;
524   to->metadata.luminance_max = from->metadata.luminance_max;
525   to->metadata.luminance_min = from->metadata.luminance_min;
526 }
527
528 inline EsPacketPtr convert_espacket_(esplusplayer_es_packet* from) {
529   std::shared_ptr<char> buffer = nullptr;
530   std::shared_ptr<char> hdr10p_metadata = nullptr;
531   if (from->buffer_size != 0 && from->buffer) {
532     buffer = std::shared_ptr<char>(new char[from->buffer_size],
533                                    std::default_delete<char[]>());
534     memcpy(buffer.get(), from->buffer, from->buffer_size);
535   }
536   if (from->hdr10p_metadata_size != 0 && from->hdr10p_metadata) {
537     hdr10p_metadata = std::shared_ptr<char>(
538         new char[from->hdr10p_metadata_size], std::default_delete<char[]>());
539     memcpy(hdr10p_metadata.get(), from->hdr10p_metadata,
540            from->hdr10p_metadata_size);
541   }
542   auto espacket = EsPacket::Create(static_cast<StreamType>(from->type), buffer,
543                                    from->buffer_size, from->pts, from->duration,
544                                    from->hdr10p_metadata_size, hdr10p_metadata);
545
546   if (from->matroska_color_info != nullptr) {
547     MatroskaColor color_info;
548     convert_matroska_color_info_(from->matroska_color_info, &color_info);
549     bool ret = espacket->SetMatroskaColorInfo(color_info);
550     if (ret == false) return nullptr;
551   }
552   return std::move(espacket);
553 }
554
555 using EncryptedInfoPtr =
556     std::unique_ptr<EsPlayerEncryptedInfo,
557                     std::function<void(EsPlayerEncryptedInfo*)>>;
558 inline EncryptedInfoPtr convert_es_drm_info_(esplusplayer_drm_info* from) {
559   auto custom_deleter = [](EsPlayerEncryptedInfo* drm_info) {
560     if (drm_info == nullptr) return;
561     if (drm_info->sub_data != nullptr) {
562       delete reinterpret_cast<plusplayer::drm::DrmbEsFragmentedMp4Data*>(
563           drm_info->sub_data);
564       drm_info->sub_data = nullptr;
565     }
566     delete drm_info;
567   };
568
569   if (from == nullptr) return EncryptedInfoPtr(nullptr, custom_deleter);
570
571   EncryptedInfoPtr drm_info =
572       EncryptedInfoPtr(new EsPlayerEncryptedInfo(), custom_deleter);
573
574   drm_info->handle = from->handle;
575   drm_info->algorithm =
576       static_cast<plusplayer::drm::DrmbEsCipherAlgorithm>(from->algorithm);
577   drm_info->format =
578       static_cast<plusplayer::drm::DrmbEsMediaFormat>(from->format);
579   drm_info->phase =
580       static_cast<plusplayer::drm::DrmbEsCipherPhase>(from->phase);
581
582   // kid
583   if (from->kid && from->kid_length > 0) {
584     drm_info->kid = std::move(
585         std::vector<unsigned char>(from->kid, from->kid + from->kid_length));
586   }
587
588   // initialization_vector
589   if (from->iv && from->iv_length > 0) {
590     drm_info->initialization_vector = std::move(
591         std::vector<unsigned char>(from->iv, from->iv + from->iv_length));
592   }
593
594   // sub_data
595   auto* from_sub_data =
596       reinterpret_cast<esplusplayer_drmb_es_fmp4_data*>(from->sub_data);
597   if (from_sub_data && from_sub_data->subsample_count > 0) {
598     drm_info->sub_data = new plusplayer::drm::DrmbEsFragmentedMp4Data;
599     auto* sub_data =
600         reinterpret_cast<plusplayer::drm::DrmbEsFragmentedMp4Data*>(
601             drm_info->sub_data);
602     for (uint32_t i = 0; i < from_sub_data->subsample_count; i++) {
603       auto& subsample_info = from_sub_data->subsample_infos[i];
604       sub_data->sub_sample_info_vector.emplace_back(
605           subsample_info.bytes_of_clear_data,
606           subsample_info.bytes_of_encrypted_data);
607     }
608   }
609
610   // split_offsets
611   if (from->split_offsets) {
612     const std::size_t kSplitOffsetMaxSize = 15 * sizeof(int);
613     std::memcpy(drm_info->split_offsets.data(), from->split_offsets,
614                 kSplitOffsetMaxSize);
615   }
616
617   drm_info->use_out_buffer = from->use_out_buffer;
618   drm_info->use_pattern = from->use_pattern;
619   drm_info->crypt_byte_block = from->crypt_byte_block;
620   drm_info->skip_byte_block = from->skip_byte_block;
621
622   return std::move(drm_info);
623 }
624
625 inline AudioStreamPtr convert_stream_ptr_(
626     esplusplayer_audio_stream_info* from) {
627   LOG_INFO("mime type : %d", static_cast<int>(from->mime_type));
628   LOG_INFO("from->bitrate : %d", from->bitrate);
629   LOG_INFO("from->channels : %d", from->channels);
630   LOG_INFO("from->sample_rate : %d", from->sample_rate);
631   LOG_INFO("from->codec_data_length : %d", from->codec_data_length);
632
633   auto stream = AudioStream::Create();
634   std::shared_ptr<char> codec_data = nullptr;
635
636   if (from->codec_data_length != 0) {
637     codec_data = std::shared_ptr<char>(new char[from->codec_data_length],
638                                        std::default_delete<char[]>());
639     memcpy(codec_data.get(), from->codec_data, from->codec_data_length);
640   }
641
642   stream->SetCodecData(codec_data, from->codec_data_length);
643   stream->SetMimeType(static_cast<plusplayer::AudioMimeType>(from->mime_type));
644   stream->SetBitrate(from->bitrate);
645   stream->SetChannels(from->channels);
646   stream->SetSamplerate(from->sample_rate);
647
648   return std::move(stream);
649 }
650
651 inline int convert_return_type_(bool ret) {
652   return ret ? ESPLUSPLAYER_ERROR_TYPE_NONE
653              : ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
654 }
655
656 inline esplusplayer_get_decoded_video_frame_status_type
657 convert_get_decoded_video_frame_status_(
658     const plusplayer::GetDecodedVideoFrameStatus status) {
659   switch (status) {
660     case plusplayer::GetDecodedVideoFrameStatus::kSuccess: {
661       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_SUCCESS;
662     }
663     case plusplayer::GetDecodedVideoFrameStatus::kNoRemainingBuffer: {
664       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_NO_REMAINING_BUFFER;
665     }
666     case plusplayer::GetDecodedVideoFrameStatus::kNoFilledBuffer: {
667       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_NO_FILLED_BUFFER;
668     }
669     case plusplayer::GetDecodedVideoFrameStatus::kUnknown: {
670       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN;
671     }
672     default: { return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN; }
673   }
674   return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN;
675 }
676
677 inline VideoStreamPtr convert_stream_ptr_(
678     esplusplayer_video_stream_info* from) {
679   LOG_INFO("mime type : %u", static_cast<int>(from->mime_type));
680   LOG_INFO("from->width : %u", from->width);
681   LOG_INFO("from->height : %u", from->height);
682   LOG_INFO("from->max_width : %u", from->max_width);
683   LOG_INFO("from->max_height : %u", from->max_height);
684   LOG_INFO("from->framerate_num : %u", from->framerate_num);
685   LOG_INFO("from->framerate_den : %u", from->framerate_den);
686   LOG_INFO("from->codec_data_length : %u", from->codec_data_length);
687
688   auto stream = VideoStream::Create();
689   std::shared_ptr<char> codec_data = nullptr;
690
691   if (from->codec_data_length != 0) {
692     codec_data = std::shared_ptr<char>(new char[from->codec_data_length],
693                                        std::default_delete<char[]>());
694     memcpy(codec_data.get(), from->codec_data, from->codec_data_length);
695   }
696
697   stream->SetCodecData(codec_data, from->codec_data_length);
698   stream->SetMimeType(static_cast<plusplayer::VideoMimeType>(from->mime_type));
699   stream->SetWidth(from->width);
700   stream->SetHeight(from->height);
701   stream->SetMaxWidth(from->max_width);
702   stream->SetMaxHeight(from->max_height);
703   stream->SetFramerate(from->framerate_num, from->framerate_den);
704
705   return std::move(stream);
706 }
707
708 esplusplayer_handle esplusplayer_create() {
709   esplusplayer_handle player = static_cast<esplusplayer_handle>(EsPrivCreate());
710   LOG_INFO("capi handle > [%p], cpp handle > [%p]", player, cast_(player));
711   return player;
712 }
713
714 int esplusplayer_open(esplusplayer_handle handle) {
715   LOG_ENTER_P(cast_(handle))
716   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
717   return convert_return_type_(cast_(handle)->Open());
718 }
719
720 int esplusplayer_close(esplusplayer_handle handle) {
721   LOG_ENTER_P(cast_(handle))
722   listener_bridge* listener = nullptr;
723   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
724     LOG_ERROR("ESPlayer or Listener object is nil.");
725     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
726   }
727
728   bool ret = cast_(handle)->Close();
729   listener->Reset();
730   return convert_return_type_(ret);
731 }
732
733 int esplusplayer_destroy(esplusplayer_handle handle) {
734   LOG_ENTER_P(cast_(handle))
735   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
736
737   if (ESPLUSPLAYER_STATE_NONE != esplusplayer_get_state(handle))
738     return ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE;
739
740   auto priv = static_cast<EsPlusPlayerPriv*>(handle);
741   EsPrivDestroy(priv);
742
743   return ESPLUSPLAYER_ERROR_TYPE_NONE;
744 }
745
746 int esplusplayer_deactivate(esplusplayer_handle handle,
747                             esplusplayer_stream_type type) {
748   LOG_ENTER_P(cast_(handle))
749   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
750
751   return convert_return_type_(
752       cast_(handle)->Deactivate(static_cast<StreamType>(type)));
753 }
754
755 int esplusplayer_activate(esplusplayer_handle handle,
756                           esplusplayer_stream_type type) {
757   LOG_ENTER_P(cast_(handle))
758   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
759
760   return convert_return_type_(
761       cast_(handle)->Activate(static_cast<StreamType>(type)));
762 }
763
764 int esplusplayer_prepare_async(esplusplayer_handle handle) {
765   LOG_ENTER_P(cast_(handle))
766   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
767
768   return convert_return_type_(cast_(handle)->PrepareAsync());
769 }
770
771 int esplusplayer_start(esplusplayer_handle handle) {
772   LOG_ENTER_P(cast_(handle))
773   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
774
775   return convert_return_type_(cast_(handle)->Start());
776 }
777
778 int esplusplayer_stop(esplusplayer_handle handle) {
779   LOG_ENTER_P(cast_(handle))
780   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
781
782   return convert_return_type_(cast_(handle)->Stop());
783 }
784
785 int esplusplayer_pause(esplusplayer_handle handle) {
786   LOG_ENTER_P(cast_(handle))
787   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
788
789   return convert_return_type_(cast_(handle)->Pause());
790 }
791
792 int esplusplayer_resume(esplusplayer_handle handle) {
793   LOG_ENTER_P(cast_(handle))
794   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
795
796   return convert_return_type_(cast_(handle)->Resume());
797 }
798
799 int esplusplayer_set_playback_rate(esplusplayer_handle handle,
800                                    const double playback_rate,
801                                    const bool audio_mute) {
802   LOG_ENTER_P(cast_(handle))
803   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
804   LOG_INFO_P(cast_(handle), "playback rate : %lf, audio mute : %d",
805              playback_rate, audio_mute);
806   return convert_return_type_(
807       cast_(handle)->SetPlaybackRate(playback_rate, audio_mute));
808 }
809
810 int esplusplayer_seek(esplusplayer_handle handle, uint64_t time_ms) {
811   LOG_ENTER_P(cast_(handle))
812   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
813   LOG_INFO("[%p] > time : %" PRIu64, cast_(handle), time_ms);
814   update_ready_to_seek_offset(handle, time_ms);
815
816   return convert_return_type_(cast_(handle)->Seek(time_ms));
817 }
818
819 int esplusplayer_set_display(esplusplayer_handle handle,
820                              esplusplayer_display_type type, void* window) {
821   LOG_ENTER_P(cast_(handle))
822   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
823   if (type < ESPLUSPLAYER_DISPLAY_TYPE_NONE ||
824     type >= ESPLUSPLAYER_DISPLAY_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
825   LOG_INFO_P(cast_(handle), "display type : %d, object : %p",
826              static_cast<int>(type), window);
827
828   return convert_return_type_(
829       cast_(handle)->SetDisplay(static_cast<DisplayType>(type), window));
830 }
831
832 int esplusplayer_set_ecore_display(esplusplayer_handle handle,
833                                    esplusplayer_display_type type, void* window,
834                                    int x, int y, int width, int height) {
835   LOG_ENTER_P(cast_(handle))
836   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
837   if (type < ESPLUSPLAYER_DISPLAY_TYPE_NONE ||
838     type >= ESPLUSPLAYER_DISPLAY_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
839   LOG_INFO_P(cast_(handle), "display type : %d, object : %p",
840              static_cast<int>(type), window);
841
842   return convert_return_type_(cast_(handle)->SetDisplay(
843       static_cast<DisplayType>(type), window, x, y, width, height));
844 }
845
846 int esplusplayer_set_surface_display(esplusplayer_handle handle,
847                                      esplusplayer_display_type type,
848                                      unsigned int surface_id, int x, int y,
849                                      int width, int height) {
850   LOG_ENTER_P(cast_(handle))
851   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
852   if (type < ESPLUSPLAYER_DISPLAY_TYPE_NONE ||
853     type >= ESPLUSPLAYER_DISPLAY_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
854   if (width <= 0 || height <= 0) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
855   LOG_INFO_P(cast_(handle), "display type : %d, object : %u",
856              static_cast<int>(type), surface_id);
857
858   return convert_return_type_(cast_(handle)->SetDisplay(
859       static_cast<DisplayType>(type), surface_id, x, y, width, height));
860 }
861
862 int esplusplayer_set_display_mode(esplusplayer_handle handle,
863                                   esplusplayer_display_mode mode) {
864   LOG_ENTER_P(cast_(handle))
865   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
866   if (mode < ESPLUSPLAYER_DISPLAY_MODE_LETTER_BOX ||
867     mode >= ESPLUSPLAYER_DISPLAY_MODE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
868   LOG_INFO_P(cast_(handle), "display mode : %d", static_cast<int>(mode));
869
870   return convert_return_type_(
871       cast_(handle)->SetDisplayMode(static_cast<DisplayMode>(mode)));
872 }
873
874 int esplusplayer_set_display_roi(esplusplayer_handle handle, int x, int y,
875                                  int width, int height) {
876   LOG_ENTER_P(cast_(handle))
877   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
878   if (width <= 0 || height <= 0) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
879   LOG_INFO_P(cast_(handle), "x : %d, y: %d, width : %d, height : %d", x, y,
880              width, height);
881
882   Geometry roi;
883   roi.x = x;
884   roi.y = y;
885   roi.w = width;
886   roi.h = height;
887
888   return convert_return_type_(cast_(handle)->SetDisplayRoi(roi));
889 }
890
891 int esplusplayer_set_video_roi(esplusplayer_handle handle, double scale_x,
892                                double scale_y, double scale_w, double scale_h) {
893   LOG_ENTER_P(cast_(handle))
894   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
895   LOG_INFO_P(cast_(handle),
896              "scale-x : %lf, scale-y: %lf, scale-w : %lf, scale-h : %lf",
897              scale_x, scale_y, scale_w, scale_h);
898
899   CropArea roi_area;
900   roi_area.scale_x = scale_x;
901   roi_area.scale_y = scale_y;
902   roi_area.scale_w = scale_w;
903   roi_area.scale_h = scale_h;
904
905   return convert_return_type_(cast_(handle)->SetVideoRoi(roi_area));
906 }
907
908 int esplusplayer_set_display_rotation(
909     esplusplayer_handle handle, esplusplayer_display_rotation_type rotation) {
910   LOG_ENTER_P(cast_(handle))
911   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
912   LOG_INFO_P(cast_(handle), "display rotate angle : %d",
913              static_cast<int>(rotation));
914   return convert_return_type_(
915       cast_(handle)->SetDisplayRotate(static_cast<DisplayRotation>(rotation)));
916 }
917
918 int esplusplayer_get_display_rotation(
919     esplusplayer_handle handle, esplusplayer_display_rotation_type* rotation) {
920   LOG_ENTER_P(cast_(handle))
921   if (is_null_(handle) || is_null_(rotation))
922     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
923   return convert_return_type_(cast_(handle)->GetDisplayRotate(
924       reinterpret_cast<DisplayRotation*>(rotation)));
925 }
926
927 int esplusplayer_set_display_visible(esplusplayer_handle handle, bool visible) {
928   LOG_ENTER_P(cast_(handle))
929   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
930   LOG_INFO_P(cast_(handle), "visible : %s", visible ? "true" : "false");
931   return convert_return_type_(cast_(handle)->SetDisplayVisible(visible));
932 }
933
934 int esplusplayer_set_submit_data_type(esplusplayer_handle handle,
935                                       esplusplayer_submit_data_type type) {
936   LOG_ENTER_P(cast_(handle))
937   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
938   if (type < ESPLUSPLAYER_SUBMIT_DATA_TYPE_CLEAN_DATA ||
939     type >= ESPLUSPLAYER_SUBMIT_DATA_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
940   LOG_INFO_P(cast_(handle), "type : %d", type);
941   return convert_return_type_(
942       cast_(handle)->SetSubmitDataType(static_cast<SubmitDataType>(type)));
943 }
944
945 int esplusplayer_set_audio_mute(esplusplayer_handle handle, bool mute) {
946   LOG_ENTER_P(cast_(handle))
947   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
948   LOG_INFO_P(cast_(handle), "mute : %s", mute ? "true" : "false");
949   return convert_return_type_(cast_(handle)->SetAudioMute(mute));
950 }
951
952 esplusplayer_state esplusplayer_get_state(esplusplayer_handle handle) {
953   // LOG_ENTER_P(cast_(handle))
954   if (is_null_(handle)) return esplusplayer_state::ESPLUSPLAYER_STATE_NONE;
955   auto current_state =
956       static_cast<esplusplayer_state>(cast_(handle)->GetState());
957   // LOG_INFO_P(cast_(handle), "state : %d", static_cast<int>(current_state));
958
959   return current_state;
960 }
961
962 esplusplayer_submit_status esplusplayer_submit_packet(
963     esplusplayer_handle handle, esplusplayer_es_packet* packet) {
964   if (is_null_(handle)) return ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED;
965   auto packetptr = convert_espacket_(packet);
966   if (packetptr == nullptr) {
967     LOG_ERROR("packet converting failed");
968     return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
969   }
970   auto status = cast_(handle)->SubmitPacket(packetptr);
971   if (status != plusplayer::PacketSubmitStatus::kSuccess) {
972     LOG_ERROR("SubmitPacket status isn't SUCCESS [%d]",
973               static_cast<int>(status));
974   }
975   return static_cast<esplusplayer_submit_status>(status);
976 }
977
978 esplusplayer_submit_status esplusplayer_submit_encrypted_packet(
979     esplusplayer_handle handle, esplusplayer_es_packet* packet,
980     esplusplayer_drm_info* drm_info) {
981   if (is_null_(handle)) return ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED;
982   auto packetptr = convert_espacket_(packet);
983   if (packetptr == nullptr) {
984     LOG_ERROR("packet converting failed");
985     return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
986   }
987   auto status = plusplayer::PacketSubmitStatus::kSuccess;
988   if (drm_info == nullptr) {
989     status = cast_(handle)->SubmitPacket(packetptr);
990   } else {
991     auto encrypted_info = convert_es_drm_info_(drm_info);
992     status = cast_(handle)->SubmitEncryptedPacket(packetptr, *encrypted_info);
993   }
994   if (status != plusplayer::PacketSubmitStatus::kSuccess) {
995     LOG_ERROR("SubmitPacket status isn't SUCCESS [%d]",
996               static_cast<int>(status));
997   }
998   return static_cast<esplusplayer_submit_status>(status);
999 }
1000
1001 esplusplayer_submit_status esplusplayer_submit_eos_packet(
1002     esplusplayer_handle handle, esplusplayer_stream_type type) {
1003   LOG_ENTER_P(cast_(handle))
1004   if (is_null_(handle)) return ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED;
1005
1006   auto status = cast_(handle)->SubmitPacket(
1007       std::move(EsPacket::CreateEos(static_cast<StreamType>(type))));
1008   return static_cast<esplusplayer_submit_status>(status);
1009 }
1010
1011 int esplusplayer_set_audio_stream_info(esplusplayer_handle handle,
1012                                        esplusplayer_audio_stream_info* info) {
1013   LOG_ENTER_P(cast_(handle))
1014   if (is_null_(handle) || is_null_(info))
1015     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1016
1017   auto stream = convert_stream_ptr_(info);
1018   return convert_return_type_(cast_(handle)->SetStream(std::move(stream)));
1019 }
1020
1021 int esplusplayer_set_video_stream_info(esplusplayer_handle handle,
1022                                        esplusplayer_video_stream_info* info) {
1023   LOG_ENTER_P(cast_(handle))
1024   if (is_null_(handle) || is_null_(info))
1025     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1026
1027   auto stream = convert_stream_ptr_(info);
1028   return convert_return_type_(cast_(handle)->SetStream(std::move(stream)));
1029 }
1030
1031 int esplusplayer_get_playing_time(esplusplayer_handle handle, uint64_t* ms) {
1032   // LOG_ENTER_P(cast_(handle))
1033   if (is_null_(handle) || is_null_(ms))
1034     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1035
1036   auto ret = cast_(handle)->GetPlayingTime(ms);
1037   // LOG_INFO("[%p] > playing time : %" PRIu64, cast_(handle), *ms);
1038   return convert_return_type_(ret);
1039 }
1040
1041 namespace {
1042 std::shared_ptr<DecodedPacketManagerInterface> CreateDecodedPacketManager(
1043     esplusplayer_handle handle,
1044     esplusplayer_decoded_video_frame_buffer_type type) {
1045   std::shared_ptr<DecodedPacketManagerInterface> mgr = nullptr;
1046   if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_COPY)
1047     mgr = std::make_shared<plusplayer::DecodedCopiedPacketList>();
1048   else if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_REFERENCE)
1049     mgr = std::make_shared<plusplayer::DecodedReferencePacketList>();
1050   else if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_SCALE)
1051     mgr = std::make_shared<plusplayer::DecodedScaledPacketList>();
1052   else if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_MANUAL_COPY)
1053     mgr = std::make_shared<plusplayer::ManualDecodedCopiedPacketList>(
1054         [handle](esplusplayer_decoded_video_packet* pkt) {
1055           plusplayer::DecodedVideoPacket _pkt;
1056           _pkt.pts = pkt->pts;
1057           _pkt.duration = pkt->duration;
1058           _pkt.surface_data = static_cast<tbm_surface_h>(pkt->surface_data);
1059           _pkt.buffer_addr = pkt->private_data;
1060           return cast_(handle)->ReturnDecodedPacket(_pkt);
1061         });
1062   return mgr;
1063 }
1064 }  // namespace
1065
1066 int esplusplayer_set_video_frame_buffer_type(
1067     esplusplayer_handle handle,
1068     esplusplayer_decoded_video_frame_buffer_type type) {
1069   LOG_ENTER_P(cast_(handle))
1070   if (is_null_(handle) || is_null_(listener_cast_(handle)))
1071     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1072
1073   auto priv = static_cast<EsPlusPlayerPriv*>(handle);
1074   priv->decoded_pkt_mgr = ::CreateDecodedPacketManager(handle, type);
1075   priv->listener->SetDecodedPacketManager(priv->decoded_pkt_mgr);
1076
1077   auto ret = cast_(handle)->SetVideoFrameBufferType(
1078       static_cast<plusplayer::DecodedVideoFrameBufferType>(type));
1079   return convert_return_type_(ret);
1080 }
1081
1082 int esplusplayer_get_adaptive_info(
1083     esplusplayer_handle handle, void* padaptive_info,
1084     esplusplayer_adaptive_info_type adaptive_type) {
1085   // LOG_ENTER_P(cast_(handle))
1086   if (is_null_(handle) || is_null_(padaptive_info))
1087     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1088
1089   auto ret = cast_(handle)->GetAdaptiveInfo(
1090       padaptive_info, static_cast<PlayerAdaptiveInfo>(adaptive_type));
1091   return convert_return_type_(ret);
1092 }
1093
1094 int esplusplayer_set_volume(esplusplayer_handle handle, const int volume) {
1095   LOG_ENTER_P(cast_(handle))
1096   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1097
1098   auto ret = cast_(handle)->SetVolume(volume);
1099   return convert_return_type_(ret);
1100 }
1101
1102 int esplusplayer_get_volume(esplusplayer_handle handle, int* volume) {
1103   LOG_ENTER_P(cast_(handle))
1104   if (is_null_(handle) || is_null_(volume))
1105     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1106
1107   auto ret = cast_(handle)->GetVolume(volume);
1108   return convert_return_type_(ret);
1109 }
1110
1111 int esplusplayer_flush(esplusplayer_handle handle,
1112                        esplusplayer_stream_type type) {
1113   LOG_ENTER_P(cast_(handle))
1114   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1115   auto ret = cast_(handle)->Flush(static_cast<StreamType>(type));
1116   return convert_return_type_(ret);
1117 }
1118
1119 const char* esplusplayer_get_error_string(esplusplayer_error_type type) {
1120   LOG_ENTER
1121   return util::ConvertErrorTypeToString(type).c_str();
1122 }
1123
1124 int esplusplayer_set_error_cb(esplusplayer_handle handle,
1125                               esplusplayer_error_cb error_cb, void* userdata) {
1126   LOG_ENTER_P(cast_(handle))
1127   listener_bridge* listener = nullptr;
1128   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1129     LOG_ERROR("ESPlayer or Listener object is nil.");
1130     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1131   }
1132
1133   listener->error_cb_ = error_cb;
1134   listener->error_cb_userdata_ = userdata;
1135   return convert_return_type_(true);
1136 }
1137
1138 int esplusplayer_set_buffer_status_cb(
1139     esplusplayer_handle handle, esplusplayer_buffer_status_cb buffer_status_cb,
1140     void* userdata) {
1141   LOG_ENTER_P(cast_(handle))
1142   listener_bridge* listener = nullptr;
1143   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1144     LOG_ERROR("ESPlayer or Listener object is nil.");
1145     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1146   }
1147
1148   listener->buffer_status_cb_ = buffer_status_cb;
1149   listener->buffer_status_cb_userdata_ = userdata;
1150   return convert_return_type_(true);
1151 }
1152
1153 int esplusplayer_set_buffer_byte_status_cb(
1154     esplusplayer_handle handle,
1155     esplusplayer_buffer_byte_status_cb buffer_status_cb, void* userdata) {
1156   LOG_ENTER_P(cast_(handle))
1157   listener_bridge* listener = nullptr;
1158   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1159     LOG_ERROR("ESPlayer or Listener object is nil.");
1160     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1161   }
1162
1163   listener->buffer_byte_status_cb_ = buffer_status_cb;
1164   listener->buffer_byte_status_cb_userdata_ = userdata;
1165   return convert_return_type_(true);
1166 }
1167
1168 int esplusplayer_set_buffer_time_status_cb(
1169     esplusplayer_handle handle,
1170     esplusplayer_buffer_time_status_cb buffer_status_cb, void* userdata) {
1171   LOG_ENTER_P(cast_(handle))
1172   listener_bridge* listener = nullptr;
1173   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1174     LOG_ERROR("ESPlayer or Listener object is nil.");
1175     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1176   }
1177
1178   listener->buffer_time_status_cb_ = buffer_status_cb;
1179   listener->buffer_time_status_cb_userdata_ = userdata;
1180   return convert_return_type_(true);
1181 }
1182
1183 int esplusplayer_set_buffer_size(esplusplayer_handle handle,
1184                                  esplusplayer_buffer_option option,
1185                                  uint64_t size) {
1186   LOG_ENTER_P(cast_(handle))
1187   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1188   LOG_INFO("[%p] > option: %d, size: %" PRId64, cast_(handle),
1189              static_cast<int>(option), size);
1190   cast_(handle)->SetBufferSize(static_cast<plusplayer::BufferOption>(option),
1191                                size);
1192   return convert_return_type_(true);
1193 }
1194
1195 int esplusplayer_enable_video_hole(esplusplayer_handle handle, const bool value) {
1196   LOG_ENTER_P(cast_(handle))
1197   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1198
1199   auto ret = cast_(handle)->EnableVideoHole(value);
1200   return convert_return_type_(ret);
1201 }
1202
1203 int esplusplayer_set_resource_conflicted_cb(
1204     esplusplayer_handle handle,
1205     esplusplayer_resource_conflicted_cb resource_conflicted_cb,
1206     void* userdata) {
1207   LOG_ENTER_P(cast_(handle))
1208   listener_bridge* listener = nullptr;
1209   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1210     LOG_ERROR("ESPlayer or Listener object is nil.");
1211     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1212   }
1213
1214   listener->resource_conflicted_cb_ = resource_conflicted_cb;
1215   listener->resource_conflicted_cb_userdata_ = userdata;
1216   return convert_return_type_(true);
1217 }
1218
1219 int esplusplayer_set_eos_cb(esplusplayer_handle handle,
1220                             esplusplayer_eos_cb eos_cb, void* userdata) {
1221   LOG_ENTER_P(cast_(handle))
1222   listener_bridge* listener = nullptr;
1223   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1224     LOG_ERROR("ESPlayer or Listener object is nil.");
1225     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1226   }
1227
1228   listener->eos_cb_ = eos_cb;
1229   listener->eos_cb_userdata_ = userdata;
1230   return convert_return_type_(true);
1231 }
1232
1233 int esplusplayer_set_ready_to_prepare_cb(
1234     esplusplayer_handle handle,
1235     esplusplayer_ready_to_prepare_cb ready_to_prepare_cb, void* userdata) {
1236   LOG_ENTER_P(cast_(handle))
1237   listener_bridge* listener = nullptr;
1238   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1239     LOG_ERROR("ESPlayer or Listener object is nil.");
1240     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1241   }
1242
1243   listener->ready_to_prepare_cb_ = ready_to_prepare_cb;
1244   listener->ready_to_prepare_cb_userdata_ = userdata;
1245   return convert_return_type_(true);
1246 }
1247
1248 int esplusplayer_set_prepare_async_done_cb(
1249     esplusplayer_handle handle,
1250     esplusplayer_prepare_async_done_cb prepare_async_done_cb, void* userdata) {
1251   LOG_ENTER_P(cast_(handle))
1252   listener_bridge* listener = nullptr;
1253   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1254     LOG_ERROR("ESPlayer or Listener object is nil.");
1255     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1256   }
1257
1258   listener->prepare_async_done_cb_ = prepare_async_done_cb;
1259   listener->prepare_async_done_cb_userdata_ = userdata;
1260   return convert_return_type_(true);
1261 }
1262
1263 int esplusplayer_set_seek_done_cb(esplusplayer_handle handle,
1264                                   esplusplayer_seek_done_cb seek_done_cb,
1265                                   void* userdata) {
1266   LOG_ENTER_P(cast_(handle))
1267   listener_bridge* listener = nullptr;
1268   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1269     LOG_ERROR("ESPlayer or Listener object is nil.");
1270     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1271   }
1272
1273   listener->seek_done_cb_ = seek_done_cb;
1274   listener->seek_done_cb_userdata_ = userdata;
1275   return convert_return_type_(true);
1276 }
1277
1278 int esplusplayer_set_ready_to_seek_cb(
1279     esplusplayer_handle handle, esplusplayer_ready_to_seek_cb ready_to_seek_cb,
1280     void* userdata) {
1281   LOG_ENTER_P(cast_(handle))
1282   listener_bridge* listener = nullptr;
1283   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1284     LOG_ERROR("ESPlayer or Listener object is nil.");
1285     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1286   }
1287   update_ready_to_seek_callback(handle, ready_to_seek_cb, userdata);
1288   return convert_return_type_(true);
1289 }
1290
1291 int esplusplayer_set_media_packet_video_decoded_cb(
1292     esplusplayer_handle handle,
1293     esplusplayer_media_packet_video_decoded_cb media_packet_video_decoded_cb,
1294     void* userdata) {
1295   LOG_ENTER_P(cast_(handle))
1296   listener_bridge* listener = nullptr;
1297   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1298     LOG_ERROR("ESPlayer or Listener object is nil.");
1299     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1300   }
1301
1302   listener->media_packet_video_decoded_cb_ = media_packet_video_decoded_cb;
1303   listener->media_packet_video_decoded_cb_userdata_ = userdata;
1304
1305   return convert_return_type_(true);
1306 }
1307
1308 int esplusplayer_set_closed_caption_cb(
1309     esplusplayer_handle handle,
1310     esplusplayer_closed_caption_cb closed_caption_cb, void* userdata) {
1311   LOG_ENTER_P(cast_(handle))
1312   listener_bridge* listener = nullptr;
1313   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1314     LOG_ERROR("ESPlayer or Listener object is nil.");
1315     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1316   }
1317
1318   listener->closed_caption_cb_ = closed_caption_cb;
1319   listener->closed_caption_cb_userdata_ = userdata;
1320   return convert_return_type_(true);
1321 }
1322
1323 int esplusplayer_set_flush_done_cb(esplusplayer_handle handle,
1324                                    esplusplayer_flush_done_cb flush_done_cb,
1325                                    void* userdata) {
1326   LOG_ENTER_P(cast_(handle))
1327   listener_bridge* listener = nullptr;
1328   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1329     LOG_ERROR("ESPlayer or Listener object is nil.");
1330     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1331   }
1332
1333   listener->flush_done_cb_ = flush_done_cb;
1334   listener->flush_done_cb_userdata_ = userdata;
1335   return convert_return_type_(true);
1336 }
1337
1338 int esplusplayer_set_event_cb(esplusplayer_handle handle,
1339                               esplusplayer_event_cb event_cb, void* userdata) {
1340   LOG_ENTER_P(cast_(handle))
1341   listener_bridge* listener = nullptr;
1342   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1343     LOG_ERROR("ESPlayer or Listener object is nil.");
1344     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1345   }
1346   listener->event_cb_ = event_cb;
1347   listener->event_cb_userdata_ = userdata;
1348
1349   return convert_return_type_(true);
1350 }
1351
1352 int esplusplayer_set_first_video_decoding_done_cb(
1353     esplusplayer_handle handle,
1354     esplusplayer_first_video_decoding_done_cb first_video_decoding_done_cb,
1355     void* userdata) {
1356   LOG_ENTER_P(cast_(handle))
1357   listener_bridge* listener = nullptr;
1358   if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
1359     LOG_ERROR("ESPlayer or Listener object is nil.");
1360     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1361   }
1362   listener->first_video_decoding_done_cb_ = first_video_decoding_done_cb;
1363   listener->first_video_decoding_done_cb_userdata_ = userdata;
1364   return convert_return_type_(true);
1365 }
1366
1367 int esplusplayer_get_decoded_video_packet(
1368     esplusplayer_handle handle, esplusplayer_decoded_video_packet* packet,
1369     esplusplayer_get_decoded_video_frame_status_type* state) {
1370   if (is_null_(handle) || is_null_(packet)) {
1371     LOG_ERROR("handle[%p] or packet[%p] is nil.", handle, packet);
1372     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1373   }
1374   plusplayer::DecodedVideoPacket _packet;
1375   bool ret = false;
1376   auto _state = cast_(handle)->GetDecodedPacket(_packet);
1377   if (_state != plusplayer::GetDecodedVideoFrameStatus::kUnknown) {
1378     ret = true;
1379   }
1380   if (_state == plusplayer::GetDecodedVideoFrameStatus::kSuccess) {
1381     packet->pts = _packet.pts;
1382     packet->duration = _packet.duration;
1383     packet->surface_data = static_cast<void*>(_packet.surface_data);
1384     packet->private_data = _packet.buffer_addr;
1385   }
1386   if (state) {
1387     *state = convert_get_decoded_video_frame_status_(_state);
1388   }
1389   return convert_return_type_(ret);
1390 }
1391
1392 int esplusplayer_decoded_buffer_destroy(
1393     esplusplayer_handle handle, esplusplayer_decoded_video_packet* packet) {
1394   if (is_null_(handle)) {
1395     LOG_ERROR("ESPlayer object is nil.");
1396     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1397   }
1398   auto priv = static_cast<EsPlusPlayerPriv*>(handle);
1399   auto& mgr = priv->decoded_pkt_mgr;
1400   if (mgr == nullptr) {
1401     LOG_ERROR("DecodedPacketManager object is nil.");
1402     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1403   }
1404   mgr->Remove(packet);
1405   return convert_return_type_(true);
1406 }
1407
1408 int esplusplayer_set_low_latency_mode(esplusplayer_handle handle,
1409                                       esplusplayer_low_latency_mode mode) {
1410   LOG_ENTER_P(cast_(handle))
1411   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1412   if (mode != ESPLUSPLAYER_LOW_LATENCY_MODE_NONE &&
1413       mode != ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL) {
1414     LOG_WARN("Not supported latency mode 0x%x", static_cast<std::uint32_t>(mode));
1415     return ESPLUSPLAYER_ERROR_TYPE_NONE;
1416   }
1417   auto ret =
1418       cast_(handle)->SetLowLatencyMode(static_cast<PlayerLowLatencyMode>(mode));
1419   return convert_return_type_(ret);
1420 }
1421
1422 int esplusplayer_set_unlimited_max_buffer_mode(esplusplayer_handle handle) {
1423   LOG_ENTER_P(cast_(handle))
1424   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1425   auto ret = cast_(handle)->SetUnlimitedMaxBufferMode();
1426   return convert_return_type_(ret);
1427 }
1428
1429 int esplusplayer_set_audio_codec_type(esplusplayer_handle handle,
1430                                       esplusplayer_audio_codec_type type) {
1431   LOG_ENTER_P(cast_(handle))
1432   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1433   if (type < ESPLUSPLAYER_AUDIO_CODEC_TYPE_HW ||
1434     type >= ESPLUSPLAYER_AUDIO_CODEC_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
1435   auto ret =
1436       cast_(handle)->SetAudioCodecType(static_cast<PlayerAudioCodecType>(type));
1437   return convert_return_type_(ret);
1438 }
1439
1440 int esplusplayer_set_video_codec_type(esplusplayer_handle handle,
1441                                       esplusplayer_video_codec_type type) {
1442   LOG_ENTER_P(cast_(handle))
1443   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1444   if (type < ESPLUSPLAYER_VIDEO_CODEC_TYPE_HW ||
1445     type >= ESPLUSPLAYER_VIDEO_CODEC_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
1446   auto ret =
1447       cast_(handle)->SetVideoCodecType(static_cast<PlayerVideoCodecType>(type));
1448   return convert_return_type_(ret);
1449 }
1450
1451 int esplusplayer_set_render_time_offset(esplusplayer_handle handle,
1452                                         esplusplayer_stream_type type,
1453                                         int64_t offset) {
1454   LOG_ENTER_P(cast_(handle))
1455   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1456   auto ret =
1457       cast_(handle)->SetRenderTimeOffset(static_cast<StreamType>(type), offset);
1458   return convert_return_type_(ret);
1459 }
1460
1461 int esplusplayer_get_render_time_offset(esplusplayer_handle handle,
1462                                         esplusplayer_stream_type type,
1463                                         int64_t* offset) {
1464   LOG_ENTER_P(cast_(handle))
1465   if (is_null_(handle) || is_null_(offset))
1466     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
1467   auto ret =
1468       cast_(handle)->GetRenderTimeOffset(static_cast<StreamType>(type), offset);
1469   return convert_return_type_(ret);
1470 }