Add initial unified code 20/299920/1
authorGilbok Lee <gilbok.lee@samsung.com>
Wed, 4 Oct 2023 08:42:56 +0000 (17:42 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Thu, 12 Oct 2023 06:58:14 +0000 (15:58 +0900)
Change-Id: Id5247507ede57da40d78b096dbbd1bb0daa1a236

199 files changed:
.clang-format [new file with mode: 0644]
AUTHORS [changed mode: 0755->0644]
CMakeLists.txt
LICENSE.APLv2 [changed mode: 0755->0644]
config/esplusplayer.ini
esplusplayer.pc.in [changed mode: 0755->0644]
include/esplusplayer/appinfo.h [new file with mode: 0644]
include/esplusplayer/attribute.h [new file with mode: 0644]
include/esplusplayer/audioeasinginfo.h [new file with mode: 0644]
include/esplusplayer/decodedvideopacketex.h [new file with mode: 0644]
include/esplusplayer/drm.h [new file with mode: 0644]
include/esplusplayer/elementary_stream.h [moved from include/plusplayer/elementary_stream.h with 86% similarity]
include/esplusplayer/es_eventlistener.h [moved from include/plusplayer/es_eventlistener.h with 51% similarity]
include/esplusplayer/espacket.h [moved from include/plusplayer/espacket.h with 79% similarity]
include/esplusplayer/esplusplayer.h [moved from include/plusplayer/esplusplayer.h with 52% similarity]
include/esplusplayer/external_drm.h [moved from include/plusplayer/external_drm.h with 59% similarity]
include/esplusplayer/track.h [moved from include/plusplayer/track.h with 76% similarity]
include/esplusplayer/types/buffer.h [new file with mode: 0644]
include/esplusplayer/types/display.h [new file with mode: 0644]
include/esplusplayer/types/error.h [moved from include/plusplayer/types/error.h with 74% similarity, mode: 0644]
include/esplusplayer/types/event.h [new file with mode: 0644]
include/esplusplayer/types/latency.h [new file with mode: 0644]
include/esplusplayer/types/picturequality.h [new file with mode: 0644]
include/esplusplayer/types/resource.h [new file with mode: 0644]
include/esplusplayer/types/source.h [new file with mode: 0644]
include/esplusplayer/types/stream.h [new file with mode: 0644]
include/esplusplayer/types/streaming_message.h [new file with mode: 0644]
include/esplusplayer/types/submitdata.h [new file with mode: 0644]
include/esplusplayer_capi/buffer.h
include/esplusplayer_capi/display.h
include/esplusplayer_capi/drm.h
include/esplusplayer_capi/error.h
include/esplusplayer_capi/espacket.h
include/esplusplayer_capi/esplusplayer_capi.h
include/esplusplayer_capi/esplusplayer_internal.h
include/esplusplayer_capi/event.h
include/esplusplayer_capi/latency.h [new file with mode: 0644]
include/esplusplayer_capi/matroska_color.h
include/esplusplayer_capi/state.h
include/esplusplayer_capi/stream.h
include/esplusplayer_capi/submitdatatype.h
include/esplusplayer_capi/submitstatus.h
include/mixer/decodedvideoinfo.h [new file with mode: 0644]
include/mixer/mixer.h [new file with mode: 0644]
include/mixer/mixer_eventlistener.h [new file with mode: 0644]
include/mixer/mixerticket.h [new file with mode: 0644]
include/mixer/mixerticket_eventlistener.h [new file with mode: 0644]
include/mixer_capi/display.h [new file with mode: 0644]
include/mixer_capi/error.h [new file with mode: 0644]
include/mixer_capi/mixer_capi.h [new file with mode: 0644]
include/plusplayer/attribute.h [deleted file]
include/plusplayer/drm.h [deleted file]
include/plusplayer/types/buffer.h [deleted file]
include/plusplayer/types/display.h [deleted file]
include/plusplayer/types/event.h [deleted file]
include/plusplayer/types/source.h [deleted file]
include/plusplayer/types/stream.h [deleted file]
include/plusplayer/types/streaming_message.h [deleted file]
include/plusplayer/types/submitdata.h [deleted file]
packaging/esplusplayer.manifest [changed mode: 0755->0644]
packaging/esplusplayer.spec
src/CMakeLists.txt
src/cpplint.py [new file with mode: 0644]
src/esplusplayer/CMakeLists.txt
src/esplusplayer/include_internal/esplayer/decoded_pkt_list.h
src/esplusplayer/include_internal/esplayer/espacket_logger.h
src/esplusplayer/include_internal/esplayer/esplayer.h
src/esplusplayer/include_internal/esplayer/esplayer_drm.h
src/esplusplayer/include_internal/esplayer/message.hpp
src/esplusplayer/include_internal/esplayer/state_manager.hpp
src/esplusplayer/src/elementary_stream.cpp
src/esplusplayer/src/espacket.cpp
src/esplusplayer/src/espacket_logger.cpp
src/esplusplayer/src/esplayer.cpp
src/esplusplayer/src/esplayer_drm.cpp
src/esplusplayer/src/esplusplayer.cpp
src/esplusplayer/src/esplusplayer_capi.cpp
src/mixer/CMakeLists.txt [new file with mode: 0644]
src/mixer/include_internal/mixer/abs_videoframe.h [new file with mode: 0644]
src/mixer/include_internal/mixer/defaultmixer.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/accessiblebuffer.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/bufferobject.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/memoryallocator.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/phyaddraccessor.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/renderableobj_factory.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/renderableobject.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/videoplanecollection.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/videoplanecolorfiller.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/videoplanecopier.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/videoplanemanipulable.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/videoplanemanipulator.h [new file with mode: 0644]
src/mixer/include_internal/mixer/interfaces/videoplanescaler.h [new file with mode: 0644]
src/mixer/include_internal/mixer/mixedframe.h [new file with mode: 0644]
src/mixer/include_internal/mixer/renderer.h [new file with mode: 0644]
src/mixer/include_internal/mixer/rendererwithdoublebuf.h [new file with mode: 0644]
src/mixer/include_internal/mixer/sys/tbminterface.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenaccessiblebufferobj.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenbufferkeyvideoframe.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenbuffermgr.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenbufferobj.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenbufferphyaddraccessor.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizendefaultphyaddraccessor.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenhwbufferobj.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenhwvideoframe.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizenrenderableobj_factory.h [new file with mode: 0644]
src/mixer/include_internal/mixer/tizen/tizensurfacevideoframe.h [new file with mode: 0644]
src/mixer/include_internal/mixer/types/buffertype.h [new file with mode: 0644]
src/mixer/include_internal/mixer/types/planecomponent.h [new file with mode: 0644]
src/mixer/include_internal/mixer/types/videoplanemanipinfo.h [new file with mode: 0644]
src/mixer/include_internal/mixer/types/videoplanemoveinfo.h [new file with mode: 0644]
src/mixer/include_internal/mixer/videoplane.h [new file with mode: 0644]
src/mixer/src/abs_videoframe.cpp [new file with mode: 0644]
src/mixer/src/defaultmixer.cpp [new file with mode: 0644]
src/mixer/src/mixedframe.cpp [new file with mode: 0644]
src/mixer/src/mixer.cpp [new file with mode: 0644]
src/mixer/src/mixer_capi.cpp [new file with mode: 0644]
src/mixer/src/renderer.cpp [new file with mode: 0644]
src/mixer/src/sys/tbminterface.cpp [new file with mode: 0644]
src/mixer/src/tizen/tizenaccessiblebufferobj.cpp [new file with mode: 0644]
src/mixer/src/tizen/tizenbufferkeyvideoframe.cpp [new file with mode: 0644]
src/mixer/src/tizen/tizendefaultphyaddraccessor.cpp [new file with mode: 0644]
src/mixer/src/tizen/tizenhwbufferobj.cpp [new file with mode: 0644]
src/mixer/src/tizen/tizenhwvideoframe.cpp [new file with mode: 0644]
src/mixer/src/tizen/tizenrenderableobj_factory.cpp [new file with mode: 0644]
src/mixer/src/tizen/tizensurfacevideoframe.cpp [new file with mode: 0644]
src/mixer/src/videoplane.cpp [new file with mode: 0644]
src/plusplayer-core/Build/appendix.mk [new file with mode: 0644]
src/plusplayer-core/Build/basedef.mk [new file with mode: 0644]
src/plusplayer-core/Build/build_c.mk [new file with mode: 0644]
src/plusplayer-core/Build/build_edc.mk [new file with mode: 0644]
src/plusplayer-core/Build/build_po.mk [new file with mode: 0644]
src/plusplayer-core/Build/flags.mk [new file with mode: 0644]
src/plusplayer-core/Build/funcs.mk [new file with mode: 0644]
src/plusplayer-core/Build/makefile [new file with mode: 0644]
src/plusplayer-core/Build/makefile.mk [new file with mode: 0644]
src/plusplayer-core/Build/platform.mk [new file with mode: 0644]
src/plusplayer-core/Build/tooldef.mk [new file with mode: 0644]
src/plusplayer-core/CMakeLists.txt
src/plusplayer-core/build_def.prop [new file with mode: 0644]
src/plusplayer-core/include_internal/core/decodedvideorawmodepacket.h [new file with mode: 0644]
src/plusplayer-core/include_internal/core/decoderinputbuffer.h
src/plusplayer-core/include_internal/core/decoderinputbuffer_listener.h
src/plusplayer-core/include_internal/core/error.h
src/plusplayer-core/include_internal/core/gst_utils.h
src/plusplayer-core/include_internal/core/gstobject_guard.h
src/plusplayer-core/include_internal/core/gstsignal_holder.h
src/plusplayer-core/include_internal/core/kpi.h [new file with mode: 0644]
src/plusplayer-core/include_internal/core/serializer.h
src/plusplayer-core/include_internal/core/subtitle_attr_parser.h
src/plusplayer-core/include_internal/core/track_util.h
src/plusplayer-core/include_internal/core/trackrendereradapter.h
src/plusplayer-core/include_internal/core/trackrendereradapter_utils.h
src/plusplayer-core/include_internal/core/utils/base64.h [new file with mode: 0644]
src/plusplayer-core/include_internal/core/utils/caf_logger.h [new file with mode: 0644]
src/plusplayer-core/include_internal/core/utils/performance_checker.h [changed mode: 0755->0644]
src/plusplayer-core/include_internal/core/utils/plusplayer_cfg.h [changed mode: 0755->0644]
src/plusplayer-core/include_internal/core/utils/plusplayer_log.h
src/plusplayer-core/include_internal/core/utils/scope_exit.h [changed mode: 0755->0644]
src/plusplayer-core/include_internal/core/videoframetypestrategy.h [new file with mode: 0644]
src/plusplayer-core/project_def.prop [new file with mode: 0644]
src/plusplayer-core/src/caf_logger.cpp [new file with mode: 0644]
src/plusplayer-core/src/decodedvideopacketex.cpp [new file with mode: 0644]
src/plusplayer-core/src/decoderinputbuffer.cpp
src/plusplayer-core/src/error.cpp
src/plusplayer-core/src/gst_utils.cpp
src/plusplayer-core/src/gstobject_guard.cpp
src/plusplayer-core/src/gstsignal_holder.cpp [deleted file]
src/plusplayer-core/src/kpi.cpp [new file with mode: 0644]
src/plusplayer-core/src/plusplayer_cfg.cpp
src/plusplayer-core/src/serializer.cpp
src/plusplayer-core/src/subtitle_attr_parser.cpp [deleted file]
src/plusplayer-core/src/track_util.cpp
src/plusplayer-core/src/trackrendereradapter.cpp
src/plusplayer-core/src/trackrendereradapter_utils.cpp
src/plusplayer-core/src/videoframetypestrategy.cpp [new file with mode: 0644]
test/CMakeLists.txt
test/esplusplayer_test.cpp [moved from test/esplusplayer_test.c with 97% similarity]
tomato/tc/TCList.dat [new file with mode: 0644]
tomato/tc/testfarm_script.xml [new file with mode: 0644]
tomato/tc/unit_test/ut_esplusplayer_all.xml [new file with mode: 0644]
ut/include/appwindow.h [changed mode: 0755->0644]
ut/include/esplusplayer/eseventlistener.hpp
ut/include/esplusplayer/esreader.hpp
ut/include/esplusplayer/tclist.h
ut/include/plusplayer/utility.h
ut/include/streamreader.hpp
ut/src/esplusplayer/ut_basic.cpp
ut/src/esplusplayer/ut_display.cpp [changed mode: 0755->0644]
ut/src/esplusplayer/ut_setstream.cpp [changed mode: 0755->0644]
ut/src/plusplayer/utility.cpp
ut/src/ut_espacket.cpp [changed mode: 0755->0644]
ut/src/ut_esplayer.cpp [changed mode: 0755->0644]
ut/src/ut_esplayer2.cpp [changed mode: 0755->0644]
ut/src/ut_esplayer_trackrenderer.cpp [changed mode: 0755->0644]
ut/src/ut_main.cpp [changed mode: 0755->0644]
ut/src/ut_miscellaneous.cpp [changed mode: 0755->0644]
ut/src/ut_streamreader.cpp [changed mode: 0755->0644]
ut/src/ut_trackrendereradapter.cpp [changed mode: 0755->0644]
ut/src/utils/utility.cpp [new file with mode: 0644]

diff --git a/.clang-format b/.clang-format
new file mode 100644 (file)
index 0000000..24d97f2
--- /dev/null
@@ -0,0 +1,3 @@
+BasedOnStyle: Google
+DerivePointerAlignment: false
+PointerAlignment: Left
diff --git a/AUTHORS b/AUTHORS
old mode 100755 (executable)
new mode 100644 (file)
index fc8e056..4108c55 100644 (file)
@@ -4,8 +4,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 PROJECT(esplusplayer)
 SET(description "new multimedia player, object-oriented model")
 SET(PC_NAME "esplusplayer")
-SET(PC_LDFLAGS "-lesplusplayer")
-SET(PC_CFLAGS "-I/usr/include/esplusplayer_capi")
+SET(PC_LDFLAGS "-lesplusplayer -lmixer")
+SET(PC_CFLAGS "-I/usr/include/esplusplayer_capi -I/usr/include/mixer")
 
 SET(INC_DIR ${PROJECT_SOURCE_DIR}/include/)
 INCLUDE_DIRECTORIES(${INC_DIR})
@@ -26,7 +26,9 @@ IF(ESPLUSPLAYER_BUILD_UT)
 ADD_SUBDIRECTORY(ut)
 ENDIF(ESPLUSPLAYER_BUILD_UT)
 
+IF(${TIZEN_PUBLIC} STREQUAL "ON")
 ADD_SUBDIRECTORY(test)
+ENDIF(${TIZEN_PUBLIC} STREQUAL "ON")
 
 IF(UNIX)
 ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution)
@@ -60,4 +62,4 @@ ENDIF(UNIX)
 MESSAGE( STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR} )
 MESSAGE( STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR} )
 MESSAGE( STATUS "LIB_INSTALL_DIR: " ${LIB_INSTALL_DIR} )
-MESSAGE( STATUS "INC_DIR: " ${INC_DIR} )
\ No newline at end of file
+MESSAGE( STATUS "INC_DIR: " ${INC_DIR} )
old mode 100755 (executable)
new mode 100644 (file)
index a78a6d7..588a9ff 100644 (file)
@@ -1,9 +1,14 @@
 {
+  "version" : "0.0.4948390.firmware",
   "gstparam1" : "--gst-debug=*:2",
   "gstparam2" : "--gst-disable-segtrap",
   "gstparam3" : "--gst-plugin-load",
   "gstparam4" : "--gst-disable-registry-fork",
   "gstparam5" : "--gst-disable-registry-update",
+  "tz_video_es_dump" : false,
+  "tz_video_dump_insert_vp9_header" : false,
+  "tz_audio_es_dump" : false,
   "generate_dot" : false,
-  "use_default_video_codec_sw" : false
+  "force_sw_audio_codec" : false,
+  "force_sw_video_codec" : false
 }
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/include/esplusplayer/appinfo.h b/include/esplusplayer/appinfo.h
new file mode 100644 (file)
index 0000000..f57013e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_APPINFO_H__
+#define __ESPLUSPLAYER_APPINFO_H__
+
+#include <string>
+
+namespace esplusplayer {
+
+/**
+* @brief Player app information.
+*/
+struct PlayerAppInfo {
+  std::string id;      /**< App id */
+  std::string version; /**< App version */
+  std::string type;    /**< App type. ex)"MSE", "HTML5", etc.. */
+};
+
+/**
+* @brief Player app information.
+*/
+struct PlayerAppInfoEx {
+  std::string id;      /**< App id */
+  std::string version; /**< App version */
+  std::string type;    /**< App type. ex)"MSE", "HTML5", etc.. */
+  std::string runtitle; /**< App runtitle */
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_PLAYER_APPINFO_H__
\ No newline at end of file
diff --git a/include/esplusplayer/attribute.h b/include/esplusplayer/attribute.h
new file mode 100644 (file)
index 0000000..510c258
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_ATTRIBUTE_H__
+#define __ESPLUSPLAYER_ATTRIBUTE_H__
+
+namespace esplusplayer {
+
+enum class Attribute {
+  kVideoQueueMaxByte,           // std::uint64_t
+  kAudioQueueMaxByte,           // std::uint64_t
+  kVideoQueueCurrentLevelByte,  // std::uint64_t
+  kAudioQueueCurrentLevelByte,  // std::uint64_t
+  kVideoMinByteThreshold,       // std::uint32_t
+  kAudioMinByteThreshold,       // std::uint32_t
+  kVideoQueueMaxTime,           // std::uint64_t
+  kAudioQueueMaxTime,           // std::uint64_t
+  kVideoQueueCurrentLevelTime,  // std::uint64_t
+  kAudioQueueCurrentLevelTime,  // std::uint64_t
+  kVideoMinTimeThreshold,       // std::uint32_t
+  kAudioMinTimeThreshold,       // std::uint32_t
+  kMax,
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_ATTRIBUTE_H__
\ No newline at end of file
diff --git a/include/esplusplayer/audioeasinginfo.h b/include/esplusplayer/audioeasinginfo.h
new file mode 100644 (file)
index 0000000..582dc88
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_AUDIOEASINGINFO_H__
+#define __ESPLUSPLAYER_AUDIOEASINGINFO_H__
+
+namespace esplusplayer {
+
+enum class AudioEasingType {
+  kAudioEasingLinear = 0,
+  kAudioEasingIncubic,
+  kAudioEasingOutcubic,
+  kAudioEasingNone
+};
+
+/**
+ * @brief  audio easing information struct
+ */
+struct AudioEasingInfo {
+  uint32_t target_volume; /**< Audio easing target volume (0 ~ 100)*/
+  uint32_t duration;      /**< Audio easing duration, in millisecond */
+  AudioEasingType type;   /**< Audio easing type */
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_AUDIOEASINGINFO_H__
\ No newline at end of file
diff --git a/include/esplusplayer/decodedvideopacketex.h b/include/esplusplayer/decodedvideopacketex.h
new file mode 100644 (file)
index 0000000..ad1aa85
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_DECODED_VIDEO_PACKET_EX_H__
+#define __ESPLUSPLAYER_DECODED_VIDEO_PACKET_EX_H__
+
+#include <boost/core/noncopyable.hpp>
+#include <memory>
+#include <utility>
+
+#include "tbm_surface.h"
+#include "tbm_type.h"
+
+namespace esplusplayer {
+
+class DecodedVideoPacketEx : private boost::noncopyable {
+ public:
+  using Ptr = std::unique_ptr<DecodedVideoPacketEx>;
+
+  static Ptr Create(const uint64_t pts = 0, const uint64_t duration = 0,
+                    tbm_surface_h surface_data = nullptr,
+                    const void* scaler_index = nullptr);
+
+  DecodedVideoPacketEx() = delete;
+
+  virtual ~DecodedVideoPacketEx();
+
+  uint64_t GetPts() const { return pts_; }
+  uint64_t GetDuration() const { return duration_; }
+  const tbm_surface_h GetTbmSurface() const { return surface_data_; }
+  const void* GetScalerIndex() const { return scaler_index_; }
+
+ protected:
+  explicit DecodedVideoPacketEx(const uint64_t pts, const uint64_t duration,
+                                tbm_surface_h surface_data,
+                                const void* scaler_index)
+      : pts_(pts),
+        duration_(duration),
+        surface_data_(surface_data),
+        scaler_index_(scaler_index) {}
+
+ private:
+  const uint64_t pts_ = 0;
+  const uint64_t duration_ = 0;
+  tbm_surface_h surface_data_ = nullptr;  // tbm_surface
+  const void* scaler_index_ = nullptr;
+};
+
+using DecodedVideoPacketExPtr = DecodedVideoPacketEx::Ptr;
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_DECODED_VIDEO_PACKET_EX_H__
diff --git a/include/esplusplayer/drm.h b/include/esplusplayer/drm.h
new file mode 100644 (file)
index 0000000..2159e2c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_DRM_H__
+#define __ESPLUSPLAYER_DRM_H__
+
+namespace esplusplayer {
+
+namespace drm {
+
+using LicenseAcquiredCb = void*;
+using UserData = void*;
+
+#ifdef DRM_MAPI_AARCH_64
+using DrmHandle = unsigned long;
+#else
+using DrmHandle = int;
+#endif
+
+enum class Type {
+  kNone = 0,
+  kPlayready,
+  kMarlin,
+  kVerimatrix,
+  kWidevineClassic,
+  kSecuremedia,
+  kSdrm,
+  kWidevineCdm = 8,
+  kMax
+};
+
+// post from hlsdemux for getright
+
+struct Property {
+  Type type = Type::kNone;           // Drm type
+  DrmHandle handle = 0;              // Drm handle
+  bool external_decryption = false;  // External Decryption Mode
+  LicenseAcquiredCb license_acquired_cb =
+      nullptr;  // The cb will be invoked when license was acquired.
+  UserData license_acquired_userdata =
+      nullptr;  // The userdata will be sent by license_acquired_cb
+};
+
+}  // namespace drm
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_DRM_H__
similarity index 86%
rename from include/plusplayer/elementary_stream.h
rename to include/esplusplayer/elementary_stream.h
index 88b9101..8413478 100644 (file)
@@ -1,39 +1,29 @@
-/**
- * @file           elementary_stream.h
- * @brief          the contents information for elementary stream
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        0.0.1
- * @SDK_Support    N
- * @remark         You must add contents information of elementary streams for
- * plusplayer::EsPlusPlayer
- * @see            plusplayer::EsPlusPlayer class
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
+
 #ifndef PLUSPLAYER_ELEMENTARY_STREAM_H_
 #define PLUSPLAYER_ELEMENTARY_STREAM_H_
 
 #include <boost/core/noncopyable.hpp>
 #include <memory>
 
-#include "plusplayer/track.h"
-#include "plusplayer/types/stream.h"
+#include "esplusplayer/track.h"
+#include "esplusplayer/types/stream.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 /**
  * @brief   Enumerations for audio mime type
@@ -59,7 +49,10 @@ enum class AudioMimeType {
   kPCM_S32BE,
   kPCM_U32LE,
   kPCM_U32BE,
-  kG711_MULAW
+  kG711_MULAW,
+  kAC4,
+  kMpegH,
+  kFlac
 };
 /**
  * @brief   Enumerations for video mime type
@@ -176,7 +169,7 @@ class AudioStream : private boost::noncopyable {
    * @brief     Get whether to use the sw decoder forcibly
    * @return    @c True if the sw decoder is use, otherwise @c False.
    */
-  bool GetForceSwDecoderUse()  { return force_swdecoder_use_; }
+  bool GetForceSwDecoderUse() { return force_swdecoder_use_; }
 
  private:
   void SetMimeType_(AudioMimeType mimetype);
@@ -336,6 +329,6 @@ class VideoStream : private boost::noncopyable {
 
 using VideoStreamPtr = VideoStream::Ptr;
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
 #endif  // PLUSPLAYER_ELEMENTARY_STREAM_H_
similarity index 51%
rename from include/plusplayer/es_eventlistener.h
rename to include/esplusplayer/es_eventlistener.h
index a77f5c9..8ab9720 100644 (file)
@@ -1,37 +1,30 @@
-/**
- * @file           es_eventlistener.h
- * @brief          the event listener for plusplayer::EsPlusPlayer
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        0.0.1
- * @SDK_Support    N
- * @see            plusplayer::EsPlusPlayer class
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
-#ifndef __PLUSPLAYER_ES_EVENTLISTENER__H__
-#define __PLUSPLAYER_ES_EVENTLISTENER__H__
 
-#include "plusplayer/drm.h"
-#include "plusplayer/types/buffer.h"
-#include "plusplayer/types/error.h"
-#include "plusplayer/types/event.h"
-#include "plusplayer/types/stream.h"
+#ifndef __ESPLUSPLAYER_ES_EVENTLISTENER__H__
+#define __ESPLUSPLAYER_ES_EVENTLISTENER__H__
 
-namespace plusplayer {
+#include "esplusplayer/drm.h"
+#include "esplusplayer/types/buffer.h"
+#include "esplusplayer/types/error.h"
+#include "esplusplayer/types/event.h"
+#include "esplusplayer/types/latency.h"
+#include "esplusplayer/types/stream.h"
+
+namespace esplusplayer {
 
 /**
  * @brief   the interface of es player EventListener class
@@ -44,6 +37,7 @@ class EsEventListener {
   EsEventListener() noexcept {}
   using UserData = void*;
   virtual ~EsEventListener() {}
+// LCOV_EXCL_START
   /**
    * @brief     It will be invoked when error has happened
    * @param     [in] error_code : #ErrorType
@@ -53,6 +47,16 @@ class EsEventListener {
    */
   virtual void OnError(const ErrorType& error_code, UserData userdata) {}
   /**
+ * @brief     It will be invoked when error has happened
+ * @param     [in] error_code : #ErrorType
+ * @param     [in] error_msg : detailed error message including info related to
+ *                 codec,demuxer,network status, etc.
+ * @see       #ErrorType
+ * @see       OnError() if only simple error code is required
+ */
+  virtual void OnErrorMsg(const ErrorType& error_code, const char* error_msg,
+                          UserData userdata) {}
+  /**
    * @brief     It will be invoked when buffer overrun or underrun is detected
    * @param     [in] type : the type of target stream
    * @param     [in] status : current buffer status
@@ -121,6 +125,16 @@ class EsEventListener {
                              UserData userdata) {}
 
   /**
+   * @brief     Set a callback function to be invoked when trackrender side need
+   * to get an useful tbm surface.
+   * @param     [in] ptr : pointer which set to get tbm address.
+   * @param     [in] is_scale_change : parameter which indicate whether the
+   * scale resolution changed.
+   * @remark    SetVideoFrameBufferType()
+   */
+  virtual void OnMediaPacketGetTbmBufPtr(void** ptr, bool is_scale_change) {}
+
+  /**
    * @brief     Set a callback function to be invoked when player decoded video
    *            frame. A video frame can be retrieved
    * @param     [in] packet : decoded video packet
@@ -151,8 +165,76 @@ class EsEventListener {
                        UserData userdata) {}
 
   virtual void OnFirstDecodingDone(UserData userdata) {}
+
+  /**
+   * @brief     It will be invoked when buffer underrun is detected from a video
+   *            decoder.
+   * @param     [in] userdata : the user data passed from the event listener
+   *            registration function
+   */
+  virtual void OnVideoDecoderUnderrun(UserData userdata) {}
+
+  /**
+   * @brief     It will be invoked when the latency status of the video stream
+   * changes.
+   * @param     [in] latency_status : the latency status
+   *            [in] userdata : the user data passed from the event listener
+   *            registration function
+   */
+  virtual void OnVideoLatencyStatus(const LatencyStatus& latency_status,
+                                    UserData userdata) {}
+
+  /**
+  * @brief     It will be invoked when the latency status of the audio stream
+  * changes.
+  * @param     [in] latency_status : the latency status
+  *            [in] userdata : the user data passed from the event listener
+  *            registration function
+  */
+  virtual void OnAudioLatencyStatus(const LatencyStatus& latency_status,
+                                    UserData userdata) {}
+  /**
+   * @brief     It will be invoked when video high latency occurs.
+   * @param     [in] userdata : the user data passed from the event listener
+   *            registration function
+   */
+  virtual void OnVideoHighLatency(UserData userdata) {}
+
+  /**
+   * @brief     It will be invoked when audio high latency occurs.
+   * @param     [in] userdata : the user data passed from the event listener
+   *            registration function
+   */
+  virtual void OnAudioHighLatency(UserData userdata) {}
+
+  /**
+   * @brief     It will be invoked when the frame dropped in SoC
+   * changes.
+   * @param     [in] count : the frame dropped count
+   *            [in] userdata : the user data passed from the event listener
+   *            registration function
+   */
+  virtual void OnVideoFrameDropped(const uint64_t& count,
+                                    UserData userdata) {}
+
+    /**
+   * @brief     Set a callback function to be invoked when input buffer is received in decoder
+   * @param     [in] type : the stream type
+   * @param     [in] time : buffer time info(pts and system time)
+   * @param     [in] userdata : the user data passed from the event listener
+   */
+  virtual void OnDecoderInputBufferTime(const StreamType& type, const DecoderBufferTime& time) {}
+
+    /**
+   * @brief     Set a callback function to be invoked when get one output buffer from decoder
+   * @param     [in] type : the stream type
+   * @param     [in] time : buffer time info(pts and system time)
+   * @param     [in] userdata : the user data passed from the event listener
+   */
+  virtual void OnDecoderOutputBufferTime(const StreamType& type, const DecoderBufferTime& time) {}
 };
+// LCOV_EXCL_STOP
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_ES_EVENTLISTENER__H__
\ No newline at end of file
+#endif  // __ESPLUSPLAYER_ES_EVENTLISTENER__H__
\ No newline at end of file
similarity index 79%
rename from include/plusplayer/espacket.h
rename to include/esplusplayer/espacket.h
index afea7e2..9d51c9f 100644 (file)
@@ -1,36 +1,28 @@
-/**
- * @file           espacket.h
- * @brief          the packet for elementary stream
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        0.0.1
- * @SDK_Support    N
- * @see            plusplayer::EsPlusPlayer class
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
-#ifndef __PLUSPLAYER_ESPACKET_H__
-#define __PLUSPLAYER_ESPACKET_H__
+
+#ifndef __ESPLUSPLAYER_ESPACKET_H__
+#define __ESPLUSPLAYER_ESPACKET_H__
 
 #include <boost/core/noncopyable.hpp>
 #include <memory>
 
-#include "plusplayer/types/stream.h"
+#include "esplusplayer/types/stream.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 /**
  * @brief   Structure of matroska meta data
@@ -70,7 +62,7 @@ struct MatroskaColor {
 
 /**
  * @brief   the interface of the packet class for elementary stream
- * @see     plusplayer::EsPlusPlayer class
+ * @see     esplusplayer::EsPlusPlayer class
  */
 class EsPacket : private boost::noncopyable {
  public:
@@ -183,6 +175,6 @@ class EsPacket : private boost::noncopyable {
 
 using EsPacketPtr = EsPacket::Ptr;
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_ESPACKET_H__
\ No newline at end of file
+#endif  // __ESPLUSPLAYER_ESPACKET_H__
\ No newline at end of file
similarity index 52%
rename from include/plusplayer/esplusplayer.h
rename to include/esplusplayer/esplusplayer.h
index 9f283f1..f51fc27 100644 (file)
@@ -1,28 +1,21 @@
-/**
- * @file           esplusplayer.h
- * @brief          the playback for elementary stream
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        0.0.1
- * @SDK_Support    N
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
-#ifndef __PLUSPLAYER_ESPLUSPLAYER__H__
-#define __PLUSPLAYER_ESPLUSPLAYER__H__
+
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER__H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER__H__
 
 #include <boost/core/noncopyable.hpp>
 #include <list>
 #include <utility>
 #include <vector>
 
-#include "plusplayer/drm.h"
-#include "plusplayer/elementary_stream.h"
-#include "plusplayer/es_eventlistener.h"
-#include "plusplayer/espacket.h"
-#include "plusplayer/external_drm.h"
-#include "plusplayer/types/buffer.h"
-#include "plusplayer/types/display.h"
-#include "plusplayer/types/error.h"
-#include "plusplayer/types/submitdata.h"
+#ifdef USE_MIXER
+#include "mixer/mixer.h"
+#endif
+
+#include "esplusplayer/appinfo.h"
+#include "esplusplayer/audioeasinginfo.h"
+#include "esplusplayer/drm.h"
+#include "esplusplayer/elementary_stream.h"
+#include "esplusplayer/es_eventlistener.h"
+#include "esplusplayer/espacket.h"
+#include "esplusplayer/external_drm.h"
+#include "esplusplayer/types/buffer.h"
+#include "esplusplayer/types/display.h"
+#include "esplusplayer/types/error.h"
+#include "esplusplayer/types/latency.h"
+#include "esplusplayer/types/picturequality.h"
+#include "esplusplayer/types/resource.h"
+#include "esplusplayer/types/submitdata.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 /**
  * @brief  Enumerations for es player state.
@@ -85,7 +87,8 @@ enum PlayerLowLatencyMode {
   kLowLatencyModeAudio = 0x0001,
   /**
    * @description   to support video fast decoding/rendering
-   *                only this value is set, it does not support seamless resolution change.
+   *                Video stream should be composed only of P and I frames.
+   *                The mode support seamless resolution change since tizen 6.5
    */
   kLowLatencyModeVideo = 0x0010,
   /**
@@ -100,16 +103,12 @@ enum PlayerLowLatencyMode {
    */
   kLowLatencyModeVideoDistortionConcealment = kLowLatencyModeVideo | 0x0020,
   /**
-   * @description   to support video fast decoding/rendering and video
-   *                with seamless resolution change.
-   */
-  kLowLatencyModeVideoWithSeamlessResolutionChange = 0x0040,
-  /**
    * @description   to disable clock sync and a/v sync when rendering. it
    *                includes #kLowLatencyModeDisablePreroll.
    */
   kLowLatencyModeDisableAVSync = 0x0100,
   /**
+   * @deprecated    Deprecated since tizen 6.5
    * @description   to disable preroll which means player doesn't wait for
    *                first buffer when state is changed to
    *                #EsState::kReady from #EsState::kIdle.
@@ -119,13 +118,36 @@ enum PlayerLowLatencyMode {
    */
   kLowLatencyModeDisablePreroll = 0x0200,
   /**
+   * @deprecated    Deprecated since tizen 6.5
    * @description   to set lower video quality
    */
   kLowLatencyModeDisableVideoQuality = 0x1000,
   /**
-   * @description   to set game mode
+   * @description   to set game mode for latency
+   *                Video stream should be composed only of P and I frames.
+   *                It must use this value with kLowLatencyModeVideo.
+   *                It must not be used together with
+   *                kLowLatencyModeDisableVideoQuality.
+   *                If use this value, It can expect better latency performance
+   *                than kLowLatencyModeDisableVideoQuality, it can use enhanced
+   *                game_mode.
+   */
+  kLowLatencyModeEnableGameMode =
+      kLowLatencyModeAudio | kLowLatencyModeVideo | 0x2000,
+  /**
+   * @description   to set game mode for latency
+   *                Video stream should be composed only of P and I frames.
+   *                Video stream must use fixed resolution.
+   *                It must not be used together with
+   *                #ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_VIDEO_QUALITY.
+   *                If use this value, It can expect better latency
+   *                performance than
+   *                #ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_VIDEO_QUALITY and
+   *                #ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE
+   *                The mode use lower video quality.
    */
-  kLowLatencyModeEnableGameMode = 0x2000
+  kLowLatencyModeGameModeWithFixedResolution =
+      kLowLatencyModeEnableGameMode | 0x4000
 };
 
 /**
@@ -156,12 +178,61 @@ enum PlayerVideoCodecType {
   kPlayerVideoCodecTypeSW,
   /**
    * @description   hardware codec using n-decoding mode can only be selected.
-                    It must set display type to mixer type by display setting api.
+                    It must set display type to mixer type by display setting
+                    api.
    */
   kPlayerVideoCodecTypeHWNdecoding,
 };
 
 /**
+ * @brief   Enumerations for player video scan type
+ */
+enum PlayerVideoScanType {
+  /**
+   * @description progressive, mfd or dvde will be allocated for H.264 2K in
+   * normal mode.
+   */
+  kPlayerVideoScanTypeProgressive,
+  /**
+   * @description interlaced, only mfd has been allocated for H.264 2K in normal
+   * mode.
+   */
+  kPlayerVideoScanTypeInterlaced,
+};
+
+/**
+ * @brief   Enumerations for the time unit
+ */
+enum PlayerTimeUnitType {
+  /**
+   * @description the timeunit will be ms. It is default value.
+   */
+  kPlayerTimeUnitTypeMs,
+  /**
+   * @description the timeunit will be us.
+   */
+  kPlayerTimeUnitTypeUs,
+};
+
+/**
+ * @brief   Enumerations for buffer level of simple mix out
+ */
+enum PlayerSimpleMixOutBufferLevel {
+  /**
+   * @description buffer level is low
+   */
+  kPlayerSimpleMixOutBufferLow,
+  /**
+   * @description buffer level is middle, default type
+   */
+  kPlayerSimpleMixOutBufferMid,
+  /**
+   * @description buffer level is high
+   */
+  kPlayerSimpleMixOutBufferHigh,
+};
+
+/**
  * @brief  the interface of the playback class for elementary stream
  */
 class EsPlusPlayer : private boost::noncopyable {
@@ -186,6 +257,7 @@ class EsPlusPlayer : private boost::noncopyable {
    * @return    @c True on success, otherwise @c False
    * @see       Close()
    */
+  // LCOV_EXCL_START
   virtual bool Open() { return false; }
   /**
    * @brief     Release all the player resources
@@ -198,19 +270,23 @@ class EsPlusPlayer : private boost::noncopyable {
   virtual bool Close() { return false; }
 
   /**
-   * @brief     Flush the specific buffered stream data and release TV resource
-   *            to change stream.
-   * @remark    To activate, the stream must be set again.
+   * @brief     Not play the specific stream anymore.
+   * @remark    The submitted es packets will be dropped after deactivated.
+   *            It recommands to stop feeding the specific stream's packets.
    * @pre       The player must be set to at least #EsState::kReady
-   * @post       The player state is same as before calling Deactivate().
+   * @post      The player state is same as before calling Deactivate().
    * @return    @c True on success, otherwise @c False.
    * @see       EsPlusPlayer::Deactivate().
    */
   virtual bool Deactivate(const StreamType type) { return false; }
 
   /**
-   * @brief     Reprepare for the specific stream playback.
-   * @remark    There must be active stream to prepare playback.
+   * @brief     Restart to play the specific stream.
+   * @remark    If user wants to change the specific stream info,
+   *            new stream info has to be set before activate.
+   *            User has to submit the specific stream from the
+   *            current playing time for activating.
+   *            The video stream has to be submitted from Iframe.
    * @pre       The player must be set to at least #EsState::kReady
    *            The StreamType must be deactivated in advance.
    *            Stream should be set in advance.
@@ -231,6 +307,40 @@ class EsPlusPlayer : private boost::noncopyable {
   virtual bool Activate(const StreamType type) { return false; }
 
   /**
+   * @brief     Not play the audio stream anymore.
+   * @remark    User has to keep feeding audio packets like when playing audio.
+   * @pre       The player must be set to at least #EsState::kIdle
+   * @post      The player state is same as before calling DeactivateAudio().
+   * @return    @c True on success, otherwise @c False.
+   * @see       EsPlusPlayer::DeactivateAudio()
+   */
+  virtual bool DeactivateAudio() { return false; }
+
+  /**
+   * @brief     Restart to play the audio stream.
+   * @remark    User can't change the audio stream info before activate.
+   * @pre       The player must be set to at least #EsState::kReady
+   *            The audio stream must be deactivated in advance.
+   *            Audio stream should be set in advance.
+   * @return    @c True on success, otherwise @c False
+   * @code
+      VideoStreamPtr audio_stream = AudioStream::Create();
+      audio_stream->SetMimeType(AudioMimeType::kAAC);
+      audio_stream->SetSamplerate(44100);
+      audio_stream->SetChannels(2);
+      SetStream(audio_stream);
+      DeactivateAudio();
+      PrepareAsync();
+      Start();
+      ActivateAudio();
+      DeactivateAudio();
+      ActivateAudio();
+   * @endcode
+   * @see       EsPlusPlayer::ActivateAudio()
+   */
+  virtual bool ActivateAudio() { return false; }
+
+  /**
    * @brief     Prepare the player for playback, asynchronously.
    * @remarks   EsEventListener::OnPrepareDone() will be called when prepare is
    * finished
@@ -291,6 +401,24 @@ class EsPlusPlayer : private boost::noncopyable {
    */
   virtual bool Resume() { return false; }
   /**
+   * @brief     SetAppInfo
+   * @remarks   Set app_id to resource manager. Resource manager check the
+   * priority to control resource.
+   * @param     [in] app_info : application id, version, type
+   * @pre       The player state must be set to #EsState::kIdle
+   * @return    None
+   */
+  virtual void SetAppInfo(const PlayerAppInfo& app_info) { return; }
+  /**
+   * @brief     SetAppInfoEx
+   * @remarks   Set app_id to resource manager. Resource manager check the
+   * priority to control resource.
+   * @param     [in] app_info : application id, version, type, runtitle
+   * @pre       The player state must be set to #EsState::kIdle
+   * @return    None
+   */
+  virtual void SetAppInfoEx(const PlayerAppInfoEx& app_info) { return; }
+  /**
    * @brief     SetPlaybackRate.
    * @remarks   Set playback rate from 0.0 to 2.0.
    * @param     [in] rate : The playback rate from 0.0 to 2.0. EsPlayer isn't
@@ -309,8 +437,8 @@ class EsPlusPlayer : private boost::noncopyable {
    * @brief     Seek for playback, asynchronously.
    * @remarks   EsEventListener::OnSeekDone() will be called if seek operation
    * is finished \n Seek result can be succeeded or not at this moment. \n
-   * @param     [in] time_millisecond : the absolute position(playingtime) of
-   * the stream in milliseconds
+   * @param     [in] time : the absolute position(playingtime) of
+   * the stream default in milliseconds, according to SetTimeUnitType.
    * @pre       The player state must be one of #EsState::kReady,
    * #EsState::kPlaying or #EsState::kPaused
    * @return    @c True if seek operation is started without any problem
@@ -318,7 +446,7 @@ class EsPlusPlayer : private boost::noncopyable {
    * @see       EsEventListener::OnSeekDone() \n
    *            EsPlusPlayer::SubmitPacket()
    */
-  virtual bool Seek(const uint64_t time_millisecond) { return false; }
+  virtual bool Seek(const uint64_t time) { return false; }
   /**
    * @brief     Set the video display
    * @remarks   We are not supporting changing display.
@@ -334,6 +462,27 @@ class EsPlusPlayer : private boost::noncopyable {
    *            EsPlusPlayer::SetDisplayVisible()
    */
   virtual bool SetDisplay(const DisplayType& type, void* obj) { return false; }
+#ifdef USE_MIXER
+  /**
+   * @brief     Set the video display
+   * @remarks   We are not supporting changing display.
+   * @remarks   This API have to be called before calling the
+   * PlusPlayer::Prepare()
+   *            or PlusPlayer::PrepareAsync() to reflect the display type.
+   * @param     [in] type : display type
+   * @param     [in] handle : The handle of mixer ticket
+   * @pre       The player state must be set to #EsState::kIdle
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @see       DisplayType
+   *            PlusPlayer::SetDisplayRoi()
+   *            PlusPlayer::SetDisplayVisible()
+   * @exception  None
+   */
+  virtual bool SetDisplay(const DisplayType& type, MixerTicket* handle) {
+    return false;
+  }
+#endif
   /**
    * @brief     Set the video display
    * @remarks   We are not supporting changing display.
@@ -362,6 +511,29 @@ class EsPlusPlayer : private boost::noncopyable {
    * @remarks   This API have to be called before calling the
    * EsPlusPlayer::PrepareAsync() to reflect the display type.
    * @param     [in] type : display type
+   * @param     [in] ecore_wl2_subsurface : The ecore wayland subsurface handle
+   * @param     [in] x : x param of display window
+   * @param     [in] y : y param of display window
+   * @param     [in] w : width of display window
+   * @param     [in] h : height of display window
+   * @pre       The player state must be set to #EsState::kIdle
+   * @return    @c True on success, otherwise @c False
+   * @see       DisplayType \n
+   *            EsPlusPlayer::SetDisplayMode() \n
+   *            EsPlusPlayer::SetDisplayRoi() \n
+   *            EsPlusPlayer::SetDisplayVisible()
+   */
+  virtual bool SetDisplaySubsurface(const DisplayType& type,
+                                    void* ecore_wl2_subsurface, const int x,
+                                    const int y, const int w, const int h) {
+    return false;
+  }
+  /**
+   * @brief     Set the video display
+   * @remarks   We are not supporting changing display.
+   * @remarks   This API have to be called before calling the
+   * EsPlusPlayer::PrepareAsync() to reflect the display type.
+   * @param     [in] type : display type
    * @param     [in] surface_id : resource id of window.
    * @param     [in] x : x param of display window
    * @param     [in] y : y param of display window
@@ -378,6 +550,18 @@ class EsPlusPlayer : private boost::noncopyable {
                           const int x, const int y, const int w, const int h) {
     return false;
   }
+
+  /**
+   * @brief     Set the video stretch mode on 21:9 TV
+   * @param     [in] mode : stretch mode
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @return    @c True on success, otherwise @c False
+   * @see       EsPlusPlayer::SetVideoRoi()
+   * @post      None
+   * @exception  None
+   * @version   4.8
+   */
+  virtual bool SetStretchMode(const int& mode) { return false; }
   /**
    * @brief     Set the video display mode
    * @param     [in] mode : display mode
@@ -414,6 +598,16 @@ class EsPlusPlayer : private boost::noncopyable {
   virtual bool SetVideoRoi(const CropArea& area) { return false; }
 
   /**
+   * @brief     Resize the render rectangle(the max region that video can be
+   * displayed).
+   * @param     [in] rect : render rectangle.
+   * @pre       Should be called after SetDisplay()
+   * @return    @c True on success, otherwise @c False
+   * @remark    The minimum value of width and height are 1.
+   */
+  virtual bool ResizeRenderRect(const RenderRect& rect) { return false; }
+
+  /**
    * @brief     Set the rotate angle of display
    * @remarks   The default value is 0.
    * @param     [in] rotate : Rotate angle.
@@ -580,14 +774,14 @@ class EsPlusPlayer : private boost::noncopyable {
   virtual EsState GetState() { return EsState::kNone; }
   /**
    * @brief     Get the current playing time of the associated media.
-   * @param     [out] time_in_milliseconds : current playing time in
-   * milliseconds
+   * @param     [out] time : current playing time default in milliseconds,
+   *                can be set by @SetTimeUnitType
    * @pre       The player must be one of #EsState::kPlaying or
    * #EsState::kPaused
    * @return    @c True on success, otherwise @c False
-   *            ("time_in_milliseconds" will be 0)
+   *            ("time" will be 0)
    */
-  virtual bool GetPlayingTime(uint64_t* time_in_milliseconds) { return false; }
+  virtual bool GetPlayingTime(uint64_t* time) { return false; }
   /**
    * @brief     Get the adaptive info from the plugins
    * @param     [in] adaptive_type : App wanted get info type
@@ -620,6 +814,39 @@ class EsPlusPlayer : private boost::noncopyable {
   }
 
   /**
+   * @brief     Set the request frame rate of decoded video
+   * @remarks   Only works when decoded video frame buffer type is scale
+   * @param     [in] request_framerate : the request frame rate of returned
+   * decoded video frame The value of track_framerate and request_framerate
+   * should be one of the following sets: track_framerate indicate the frame
+   * rate of input video stream 1.A/(A-B) = X ,X means drop 1 frame every X
+   * frame 2.Special cases,such as 24000/1000 -> 15000/1000 when
+   * request_framerate.num = 0, return none decoded video frame. when
+   * request_framerate.num/request_framerate.den =
+   * track_framerate.num/track_framerate.den, return all decoded video frame.
+   * when request_framerate.num/request_framerate.den <
+   * track_framerate.num/track_framerate.den, drop some decoded video frame.
+   * @pre       The player state must be not #EsState::kNone
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetDecodedVideoFrameRate(const Rational& request_framerate) {
+    return false;
+  }
+
+  /**
+   * @brief     Set the target scale resolution when decoded video frame buffer
+   * type is scale
+   * @param     [in] target_width : target width of scale.
+   * @param     [in] target_height : target height of scale.
+   * @pre       The player state must be set to #EsState::kIdle
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetVideoFrameBufferScaleResolution(
+      const uint32_t& target_width, const uint32_t& target_height) {
+    return false;
+  }
+
+  /**
    * @brief     Register eventlistener to player
    * @param     [in] listener : listener object
    * @param     [in] userdata : listener object's userdata to be returned via
@@ -658,8 +885,8 @@ class EsPlusPlayer : private boost::noncopyable {
    * @pre       The player state must be set to #EsState::kIdle
    * @return       @c True on success, otherwise @c False
    */
-  virtual void SetBufferSize(const BufferOption& option, uint64_t size) {
-    return;
+  virtual bool SetBufferSize(const BufferOption& option, uint64_t size) {
+    return false;
   }
   /**
    * @brief     Provided api for setting low latency mode
@@ -674,6 +901,23 @@ class EsPlusPlayer : private boost::noncopyable {
   }
 
   /**
+   * @brief     Provided api for enabling video frame peek mode
+   * @pre       The player state must be set to #EsState::kIdle.
+   * @return    @c True on success, otherwise @c False
+   * @see       RenderVideoFrame().
+   */
+  virtual bool SetVideoFramePeekMode() { return false; }
+
+  /**
+   * @brief     Provided api for rendering a video frame which is holded by
+   * video frame peek mode.
+   * @pre       In order to use this api, The player state must be one of
+   * #EsState::kReady or #EsState::kPaused after EsEventListener::OnSeekDone()
+   * or EsEventListener::OnPrepareDone() is called \n
+   * @see       SetVideoFramePeekMode().
+   */
+  virtual bool RenderVideoFrame() { return false; }
+  /**
    * @brief     Provided api for setting unlimited max buffer mode
    * @remarks   The player does not limit es packet transmission although in
    *            buffer overrun status.
@@ -682,6 +926,17 @@ class EsPlusPlayer : private boost::noncopyable {
    */
   virtual bool SetUnlimitedMaxBufferMode() { return false; }
   /**
+   * @brief     Provided api to deliver fmm signal and getting fmm auto status
+   * @remarks   The player just delivers fmm signal to system. It doesn't
+   * gaurantee activating fmm mode. System refers to fmm signal when it decides
+   * to activate fmm mode or not.
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @return    @c ErrorType::kNone = fmm auto mode on @c
+   * ErrorType::kInvalidOperation = fmm audo mode off @c
+   * ErrorType::kInvalidState = internal operation failed
+   */
+  virtual ErrorType SetFmmMode() { return ErrorType::kNone; }
+  /**
    * @brief     Provided api for setting audio codec type
    * @pre       The player state must be set to #EsState::kIdle.
    * @return    @c True on success, otherwise @c False
@@ -698,13 +953,61 @@ class EsPlusPlayer : private boost::noncopyable {
     return false;
   }
   /**
+   * @brief     Provided api for setting alternative video resource(sub decoder
+   *            and sub scaler)
+   * @param     [in] is_set : set alternative video resource
+   *            (@c 0 [defualt] = set all video resources(decoder/scaler) to
+   *                              main resources,
+   *             @c 1 = set all video resources(decoder/scaler) to sub
+   *                    resources,
+   *             @c 2 = set only decoder to sub resource,
+   *             @c 3 = set only scaler to sub resource)
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetAlternativeVideoResource(unsigned int rsc_type) {
+    return false;
+  }
+  /**
+   * @brief     Provided api for setting alternative audio resource(sub decoder
+   *            and audio out)
+   * @param     [in] is_set : set alternative audio resource
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetAlternativeAudioResource(
+      const PlayerAudioResourceType rsc_type) {
+    return false;
+  }
+  /**
+   * @brief     Provided api for switching audio stream between the different
+   *            audio codec types on the fly
+   * @param     [in] stream : audio stream object
+   * @remark    Audio stream can be switched between only #AudioMimeType::kAAC,
+   *            #AudioMimeType::kEac3 and #AudioMimeType::kAC3.
+   *            if other codec type is set, this api will return false.
+   * @pre       The player state must be one of #EsState::kReady,
+   *            #EsState::kPlaying, #EsState::kPaused.
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SwitchAudioStreamOnTheFly(const AudioStreamPtr& stream) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for setting aifilter to video pipeline
+   * @pre       The player state must be set to #EsState::kIdle.
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetAiFilter(void* aifilter) { return false; }
+  /**
    * @brief     Provided api for setting render time offset
    * @param     [in] type : stream type
    * @param     [in] offset : offset (milisecond).
    * @pre       The player state must be set to #EsState::kReady,
    *            #EsState::kPaused or #EsState::kPlaying.
    *            It have to be set to low latency mode.
-   * @see       EsPlusPlayer::SetLowLatencyMode()
+   * @remark    esplusplayer_set_low_latency_mode().
    * @return    @c True on success, otherwise @c False
    */
   virtual bool SetRenderTimeOffset(const StreamType type, int64_t offset) {
@@ -713,16 +1016,216 @@ class EsPlusPlayer : private boost::noncopyable {
   /**
    * @brief     Provided api for getting render time offset
    * @param     [in] type : stream type
-   * @param     [out] offset : offset ptr (milisecond).
+   * @param     [in] offset : offset ptr (milisecond).
    * @pre       The player state must be set to #EsState::kReady,
    *            #EsState::kPaused or #EsState::kPlaying.
    *            It have to be set to low latency mode.
-   * @see       EsPlusPlayer::SetLowLatencyMode()
+   * @remark    esplusplayer_set_low_latency_mode().
    * @return    @c True on success, otherwise @c False
    */
   virtual bool GetRenderTimeOffset(const StreamType type, int64_t* offset) {
     return false;
   }
+
+  /**
+   * @brief     Provided api for setting catch up speed level
+   * @pre       The player state must be set to #EsState::kIdle,
+   *            #EsState::kReady, #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetCatchUpSpeed(const CatchUpSpeed& level) { return false; }
+  /**
+   * @brief     Provided api for getting current video latency status
+   * @pre       The player state must be one of #EsState::kReady,
+   *            #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool GetVideoLatencyStatus(LatencyStatus* status) { return false; }
+  /**
+   * @brief     Provided api for getting current audio latency status
+   * @pre       The player state must be one of #EsState::kReady,
+   *            #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool GetAudioLatencyStatus(LatencyStatus* status) { return false; }
+  /**
+   * @brief     Provided api for setting video mid latency threshold for low
+   * latency playback
+   * @pre       The player state must be set to #EsState::kIdle,
+   *            #EsState::kReady, #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetVideoMidLatencyThreshold(const unsigned int threshold) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for setting audio mid latency threshold for low
+   * latency playback
+   * @pre       The player state must be set to #EsState::kIdle,
+   *            #EsState::kReady, #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetAudioMidLatencyThreshold(const unsigned int threshold) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for setting video high latency threshold for low
+   * latency playback
+   * @pre       The player state must be set to #EsState::kIdle,
+   *            #EsState::kReady, #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetVideoHighLatencyThreshold(const unsigned int threshold) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for setting audio high latency threshold for low
+   * latency playback
+   * @pre       The player state must be set to #EsState::kIdle,
+   *            #EsState::kReady, #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetAudioHighLatencyThreshold(const unsigned int threshold) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for getting the maximum number of frames
+   * @remark    It has to be set game mode, and multi channel pcm
+   * @pre       The player state must be one of #EsState::kReady,
+   *            #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for getting the number of currently queued frames
+   * @remark    It has to be set game mode, and multi channel pcm
+   * @pre       The player state must be one of #EsState::kReady,
+   *            #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for getting the underrun counts in audio out
+   * @remark    It has to be set game mode, and multi channel pcm
+   * @pre       The player state must be one of #EsState::kReady,
+   *            #EsState::kPlaying or #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for initializing audio easing information
+   * @param     [in] init_volume : initial volume
+   * @param     [in] init_elapsed_time : initail elapsed time (milisecond).
+   * @param     [in] easing_info : target_volume, duration(milisecond), easing
+   * type
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool InitAudioEasingInfo(const uint32_t init_volume,
+                                   const uint32_t init_elapsed_time,
+                                   const AudioEasingInfo& easing_info) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for updating audio easing information
+   * @param     [in] easing_info : target_volume, duration(milisecond), easing
+   * type
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @remarks   This API have to be called after calling the
+   * EsPlusPlayer::InitAudioEasingInfo()
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for getting audio easing information
+   * @param     [out] current_volume : current volume
+   * @param     [out] elapsed_time : elapsed time (milisecond).
+   * @param     [out] easing_info : target_volume, duration(milisecond), easing
+   * type
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @remarks   This API have to be called after calling the
+   * EsPlusPlayer::InitAudioEasingInfo()
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool GetAudioEasingInfo(uint32_t* current_volume,
+                                  uint32_t* elapsed_time,
+                                  AudioEasingInfo* easing_info) {
+    return false;
+  }
+
+  /**
+   * @brief     Provided api for starting audio easing
+   * @pre       The player state should be at least #EsState::kReady
+   * @remarks   This API have to be called after calling the
+   * EsPlusPlayer::InitAudioEasingInfo()
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool StartAudioEasing() { return false; }
+
+  /**
+   * @brief     Provided api for stopping audio easing
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @remarks   This API have to be called after calling the
+   * EsPlusPlayer::InitAudioEasingInfo()
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool StopAudioEasing() { return false; }
+
+  /**
+   * @brief     Get virtual resource id
+   * @param     [in] type : The resource type of virtual id.
+   * @param     [out] virtual_id : Stored virtual resource id value.
+   * @pre       The player state should be #EsState::kReady, #EsState::kPlaying
+   * or #EsState::kPaused
+   * @post      None
+   * @return    @c True on success, otherwise @c False ("virtual_id" will be -1)
+   * @exception  None
+   */
+  virtual bool GetVirtualRscId(const RscType type, int* virtual_id) {
+    return false;
+  }
+
+  /**
+   * @brief     Set advanced picture quality type.
+   * @param     [in] type : The picture quality type.
+   * @pre       The player state must be set to #EsState::kIdle.
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool SetAdvancedPictureQualityType(const AdvPictureQualityType type) {
+    return false;
+  }
+
+  /**
+   * @brief     Set resource allocate policy.
+   * @param     [in] policy : The resource allocate policy.
+   * @pre       The player state must be set to #EsState::kIdle.
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool SetResourceAllocatePolicy(const RscAllocPolicy policy) {
+    return false;
+  }
+
   /**
    * @brief     Get the decoded video packet.
    * @param     [out] packet
@@ -732,6 +1235,7 @@ class EsPlusPlayer : private boost::noncopyable {
       DecodedVideoPacket& packet) {
     return GetDecodedVideoFrameStatus::kUnknown;
   }
+
   /**
    * @brief     Return the decoded video packet.
    * @param     [in] packet
@@ -740,16 +1244,102 @@ class EsPlusPlayer : private boost::noncopyable {
   virtual bool ReturnDecodedPacket(const DecodedVideoPacket& packet) {
     return false;
   }
+
+  /**
+   * @brief     Set audio preloading mode
+   * @pre       The player state must be set to #EsState::kIdle
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool SetAudioPreloading() { return false; }
+
+  /**
+   * @brief     Set resource allocate policy.
+   * @param     [in] policy : The resource allocate policy.
+   * @pre       The player state must be set to #EsState::kIdle.
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool SetVideoScanType(const PlayerVideoScanType type) {
+    return false;
+  }
+
+  /**
+   * @brief       Get the decoding time of the stream type.
+   * @param       [in] type : stream type
+   * @param       [out] time_in_milliseconds : decoding time in
+   * milliseconds
+   * @pre         The player must be one of #EsState::kPlaying or
+   * #EsState::kPaused
+   * @return    @c True on success, otherwise @c False
+   *              ("time_in_milliseconds" will be 0)
+   */
+  virtual bool GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) {
+    return false;
+  }
+
+  /**
+   * @brief     Set the time unit type, ms or us.
+   * @param     [in] type : The type of time unit, defalut is ms.
+   * @pre       The player state must be set to #EsState::kIdle.
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool SetTimeUnitType(const PlayerTimeUnitType type) { return false; }
+
+  /**
+   * @brief     Set the rotate angle of video stream
+   * @param     [in] rotation : Rotate type.
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool SetVideoStreamRotationInfo(const VideoRotation& rotation) {
+    return false;
+  }
+
+  /**
+   * @brief     Get the rotate angle of video stream
+   * @param     [out] rotation : Rotate type.
+   * @pre       The player state can be all of #EsState except #EsState::kNone
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool GetVideoStreamRotationInfo(VideoRotation* rotation) {
+    return false;
+  }
+
+  /**
+   * @brief     Set buffer level of simple mix out
+   * @param     [in] level : buffer level of simple mix out
+   * @pre       The player state must be set to #EsState::kIdle.
+   * @post      None
+   * @return    @c True on success, otherwise @c False
+   * @exception  None
+   */
+  virtual bool SetSimpleMixOutBufferLevel(
+      const PlayerSimpleMixOutBufferLevel level) {
+    return false;
+  }
+
+#ifdef TIZEN_FEATURE_PUBLIC
   /**
    * @brief     Provided api for enabling video hole
    * @return    @c True on success, otherwise @c False
    */
   virtual bool EnableVideoHole(bool value) { return false; }
+#endif
+  // LCOV_EXCL_STOP
 
  protected:
   EsPlusPlayer() noexcept {};
 };  // class EsPlusPlayer
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER__H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER__H__
similarity index 59%
rename from include/plusplayer/external_drm.h
rename to include/esplusplayer/external_drm.h
index 226c038..d14f05c 100644 (file)
@@ -1,34 +1,27 @@
-/**
- * @file           external_drm.h
- * @brief          the extrnal drm information for elementary stream
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        0.0.1
- * @SDK_Support    N
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
-#ifndef __PLUSPLAYER_EXTERNAL_DRM_H__
-#define __PLUSPLAYER_EXTERNAL_DRM_H__
+
+#ifndef __ESPLUSPLAYER_EXTERNAL_DRM_H__
+#define __ESPLUSPLAYER_EXTERNAL_DRM_H__
 
 #include <array>
 #include <string>
 #include <vector>
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace drm {
 
@@ -85,7 +78,11 @@ struct DrmbEsFragmentedMp4Data {
  * @brief  Structure of encrypted information for es playback
  */
 struct EsPlayerEncryptedInfo {
-  int32_t handle = 0;
+#ifdef DRM_MAPI_AARCH_64
+  unsigned long handle = 0;
+#else
+  int handle = 0;
+#endif
 
   DrmbEsCipherAlgorithm algorithm = DrmbEsCipherAlgorithm::kUnknown;
   DrmbEsMediaFormat format = DrmbEsMediaFormat::kNone;
@@ -106,6 +103,6 @@ struct EsPlayerEncryptedInfo {
 
 }  // namespace drm
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_EXTERNAL_DRM_H__
+#endif  // __ESPLUSPLAYER_EXTERNAL_DRM_H__
similarity index 76%
rename from include/plusplayer/track.h
rename to include/esplusplayer/track.h
index 005b074..51d1b1d 100644 (file)
@@ -1,28 +1,21 @@
-/**
-* @file
-* @interfacetype  module
-* @privlevel      None-privilege
-* @privilege      None
-* @product        TV, AV, B2B
-* @version        1.0
-* @SDK_Support    N
-*
-* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-* PROPRIETARY/CONFIDENTIAL
-* This software is the confidential and proprietary
-* information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
-* not disclose such Confidential Information and shall use it only in
-* accordance with the terms of the license agreement you entered into with
-* SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
-* suitability of the software, either express or implied, including but not
-* limited to the implied warranties of merchantability, fitness for a
-* particular purpose, or non-infringement. SAMSUNG shall not be liable for any
-* damages suffered by licensee as a result of using, modifying or distributing
-* this software or its derivatives.
-*/
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_TRACK_H__
-#define __PLUSPLAYER_TRACK_H__
+#ifndef __ESPLUSPLAYER_TRACK_H__
+#define __ESPLUSPLAYER_TRACK_H__
 
 #include <boost/any.hpp>
 #include <boost/core/noncopyable.hpp>
@@ -32,7 +25,7 @@
 #include <memory>
 #include <string>
 
-namespace plusplayer {
+namespace esplusplayer {
 
 const int kInvalidTrackIndex = -1;
 
@@ -73,25 +66,19 @@ struct Track {
   bool use_swdecoder = false;
   std::string language_code;
   std::string subtitle_format;
-  std::string stream_format;
-  std::string alignment;
-  std::string original_media_type;
-  std::string protection_system;
   Track() {};
   Track(int _index, int _id, std::string _mimetype, std::string _streamtype, std::string _container_type,
     TrackType _type, std::shared_ptr<char> _codec_data, unsigned int _codec_tag,  int _codec_data_len,
     int _width, int _height, int _maxwidth, int _maxheight, int _framerate_num, int _framerate_den,
     int _sample_rate, int _sample_format, int _channels, int _version, int _layer, int _bits_per_sample,
     int _block_align, int _bitrate, int _endianness, bool _is_signed, bool _active, bool _use_swdecoder,
-    std::string _language_code, std::string _subtitle_format, std::string _stream_format, std::string _alignment,
-       std::string _original_media_type, std::string _protection_system)
+    std::string _language_code, std::string _subtitle_format)
      : index(_index), id(_id), mimetype(_mimetype), streamtype(_streamtype), container_type(_container_type),
     type(_type), codec_data(_codec_data), codec_tag(_codec_tag),  codec_data_len(_codec_data_len),
     width(_width), height(_height), maxwidth(_maxwidth), maxheight(_maxheight), framerate_num(_framerate_num), framerate_den(_framerate_den),
     sample_rate(_sample_rate), sample_format(_sample_format), channels(_channels), version(_version), layer(_layer), bits_per_sample(_bits_per_sample),
     block_align(_block_align), bitrate(_bitrate), endianness(_endianness), is_signed(_is_signed), active(_active), use_swdecoder(_use_swdecoder),
-    language_code(_language_code), subtitle_format(_subtitle_format), stream_format(_stream_format), alignment(_alignment),
-       original_media_type(_original_media_type), protection_system(_protection_system) {};
+    language_code(_language_code), subtitle_format(_subtitle_format) {};
 };
 
 enum SubtitleAttrType {
@@ -162,6 +149,6 @@ struct Rational {
   int num = 0;     // the numerator value
   int den = 0;     // the denominator value
 };
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_TRACK_H__
\ No newline at end of file
+#endif  // __ESPLUSPLAYER_TRACK_H__
\ No newline at end of file
diff --git a/include/esplusplayer/types/buffer.h b/include/esplusplayer/types/buffer.h
new file mode 100644 (file)
index 0000000..62226d1
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __ESPLUSPLAYER_TYPES_BUFFER_H__
+#define __ESPLUSPLAYER_TYPES_BUFFER_H__
+
+#include <cstdint>
+
+#include "tbm_type.h"
+
+namespace esplusplayer {
+
+/**
+ * @brief  Enumerations for the buffer status
+ */
+enum class BufferStatus { kUnderrun, kOverrun };
+
+enum class DecodedVideoFrameBufferType {
+  kNone,
+  kCopy,
+  kReference,
+  kScale,
+  kManualCopy,
+};
+
+enum class BufferOption {
+  kBufferAudioMaxTimeSize,
+  kBufferVideoMaxTimeSize,
+  kBufferAudioMinTimeThreshold,
+  kBufferVideoMinTimeThreshold,
+  kBufferAudioMaxByteSize,
+  kBufferVideoMaxByteSize,
+  kBufferAudioMinByteThreshold,
+  kBufferVideoMinByteThreshold,
+  kBufferOptionMax
+};
+
+struct DecodedVideoPacket {
+  uint64_t pts = 0;
+  uint64_t duration = 0;
+  tbm_surface_h surface_data = nullptr;  // tbm_surface
+  void* scaler_index = nullptr;
+#ifdef TIZEN_FEATURE_PUBLIC
+  void* buffer_addr = nullptr;
+#endif
+};
+
+struct DecoderBufferTime{
+  uint64_t pts = 0;
+  uint64_t system_time = 0;
+} ;
+
+/**
+ * @brief Enumerations for the state of getting decoded packet
+ */
+enum class GetDecodedVideoFrameStatus {
+  kSuccess,
+  kNoRemainingBuffer,
+  kNoFilledBuffer,
+  kUnknown,
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_BUFFER_H__
diff --git a/include/esplusplayer/types/display.h b/include/esplusplayer/types/display.h
new file mode 100644 (file)
index 0000000..f5ee611
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __ESPLUSPLAYER_TYPES_DISPLAY_H__
+#define __ESPLUSPLAYER_TYPES_DISPLAY_H__
+
+namespace esplusplayer {
+
+enum class DisplayType { kNone, kOverlay, kEvas, kMixer };
+
+enum class DisplayMode {
+  kLetterBox,
+  kOriginSize,
+  kFullScreen,
+  kCroppedFull,
+  kOriginOrLetter,
+  kDstRoi,
+  kAutoAspectRatio,
+  kMax
+};
+
+enum class DisplayRotation { kNone, kRotate90, kRotate180, kRotate270 };
+
+struct Geometry {
+  int x = 0, y = 0;
+  int w = 1920, h = 1080;
+};
+
+struct CropArea {
+  double scale_x = 0.0;
+  double scale_y = 0.0;
+  double scale_w = 1.0;
+  double scale_h = 1.0;
+};
+
+struct RenderRect {
+  int x = 0, y = 0;
+  int w = 1920, h = 1080;
+};
+
+enum class VisibleStatus { kHide, kVisible };
+
+struct DisplayInfo {
+  Geometry geometry;
+  CropArea croparea;
+  VisibleStatus visible_status = VisibleStatus::kVisible;
+};
+
+enum class StillMode { kNone, kOff, kOn };
+
+struct DisplayObject {
+  DisplayType type_;
+  int surface_id_;
+  DisplayMode mode_;
+  Geometry geometry_;
+  void* obj_;
+  bool is_obj_ = false;
+};
+
+enum class VideoRotation {
+  kVideoRotateNone,
+  kVideoRotate90,
+  kVideoRotate180,
+  kVideoRotate270,
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_DISPLAY_H__
old mode 100755 (executable)
new mode 100644 (file)
similarity index 74%
rename from include/plusplayer/types/error.h
rename to include/esplusplayer/types/error.h
index 9865ad7..a41be28
@@ -1,32 +1,25 @@
-/**
-* @file
-* @interfacetype  module
-* @privlevel      None-privilege
-* @privilege      None
-* @product        TV, AV, B2B
-* @version        1.0
-* @SDK_Support    N
+/*
+* Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
 *
-* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-* PROPRIETARY/CONFIDENTIAL
-* This software is the confidential and proprietary
-* information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
-* not disclose such Confidential Information and shall use it only in
-* accordance with the terms of the license agreement you entered into with
-* SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
-* suitability of the software, either express or implied, including but not
-* limited to the implied warranties of merchantability, fitness for a
-* particular purpose, or non-infringement. SAMSUNG shall not be liable for any
-* damages suffered by licensee as a result of using, modifying or distributing
-* this software or its derivatives.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
 */
 
-#ifndef __PLUSPLAYER_TYPES_ERROR_H__
-#define __PLUSPLAYER_TYPES_ERROR_H__
+#ifndef __ESPLUSPLAYER_TYPES_ERROR_H__
+#define __ESPLUSPLAYER_TYPES_ERROR_H__
 
 #include "tizen.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 #define PLUSPLAYER_ERROR_CLASS          TIZEN_ERROR_PLAYER | 0x20
 
@@ -61,6 +54,7 @@ enum class ErrorType {
   kNotSupportedVideoCodec = PLUSPLAYER_ERROR_CLASS | 0x0f, /**< Not supported video codec but audio can be played (Since 4.0) */
   kNotSupportedSubtitle = PLUSPLAYER_ERROR_CLASS | 0x10, /**< Not supported subtitle format (Since 4.0) */
 
+  // TODO(euna7.ko) Can be removed. refer to http://168.219.243.246:8090/pages/viewpage.action?pageId=27269511
   kDrmInfo = PLUSPLAYER_CUSTOM_ERROR_CLASS | 0x05,              /**< playready drm error info */
   kNotSupportedFormat = PLUSPLAYER_CUSTOM_ERROR_CLASS | 0x08,
   kStreamingPlayer = PLUSPLAYER_CUSTOM_ERROR_CLASS | 0x09,
@@ -72,6 +66,6 @@ enum class ErrorType {
   kUnknown
 };
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_TYPES_ERROR_H__
+#endif  // __ESPLUSPLAYER_TYPES_ERROR_H__
diff --git a/include/esplusplayer/types/event.h b/include/esplusplayer/types/event.h
new file mode 100644 (file)
index 0000000..4bc022a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_TYPES_EVENT_H__
+#define __ESPLUSPLAYER_TYPES_EVENT_H__
+
+namespace esplusplayer {
+/**
+ * @brief
+ */
+typedef struct {
+  /**
+   * @description
+   */
+  std::string data;
+  /**
+   * @description
+   */
+  uint64_t len;
+} EventMsg;
+
+/**
+ * @brief
+ */
+enum class EventType {
+  kNone,
+  kResolutionChanged,
+  kRequestedFirstRenderFrame,
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_EVENT_H__
diff --git a/include/esplusplayer/types/latency.h b/include/esplusplayer/types/latency.h
new file mode 100644 (file)
index 0000000..dcb918b
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_TYPES_LATENCY_H__
+#define __ESPLUSPLAYER_TYPES_LATENCY_H__
+
+namespace esplusplayer {
+
+enum class CatchUpSpeed {
+  kNone,
+  kSlow,
+  kNormal,
+  kFast
+};
+
+enum class LatencyStatus {
+  kLow,
+  kMid,
+  kHigh
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_LATENCY_H__
\ No newline at end of file
diff --git a/include/esplusplayer/types/picturequality.h b/include/esplusplayer/types/picturequality.h
new file mode 100644 (file)
index 0000000..f11babf
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_PICTUREQUALITY_H__
+#define __ESPLUSPLAYER_PICTUREQUALITY_H__
+
+namespace esplusplayer {
+
+/**
+* @brief Advanced Picture Quality Type.
+*/
+enum class AdvPictureQualityType {
+  kVideoCall,
+  kUsbCamera,
+  kAirplayMirroring
+};
+
+}  // namespace esplusplayer
+#endif  // __ESPLUSPLAYER_PICTUREQUALITY_H__
\ No newline at end of file
diff --git a/include/esplusplayer/types/resource.h b/include/esplusplayer/types/resource.h
new file mode 100644 (file)
index 0000000..4ff5c8d
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_TYPES_RESOURCE_H__
+#define __ESPLUSPLAYER_TYPES_RESOURCE_H__
+
+namespace esplusplayer {
+
+/**
+ * @brief  Enumerations for the resource type
+ */
+enum class RscType { kVideoRenderer };
+
+/**
+ * @brief   Enumerations for resource allocate policy
+ */
+enum class RscAllocPolicy {
+  /**
+   * @description   exclusive policy, default policy
+   */
+  kRscAllocExclusive,
+  /**
+   * @description   conditional policy
+   */
+  kRscAllocConditional,
+  /**
+   * @description   exclusive no explicit policy
+   */
+  kRscAllocExclusiveNoExplicit,
+};
+
+/**
+ * @brief   Enumerations for audio resource type
+ */
+enum PlayerAudioResourceType {
+  /**
+   * @description   all audio resources(decoder/audio out) to main resources
+   */
+  kPlayerAudioResourceTypeMain,
+  /**
+   * @description   only audio decoder to sub resource
+   */
+  kPlayerAudioResourceTypeSubDecoder,
+  /**
+   * @description   only audio out to simple mix out resource
+   */
+  kPlayerAudioResourceTypeSimpleMixOut,
+};
+
+}  // namespace plusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_RESOURCE_H__
\ No newline at end of file
diff --git a/include/esplusplayer/types/source.h b/include/esplusplayer/types/source.h
new file mode 100644 (file)
index 0000000..eb17702
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_TRACKSOURCE_TYPES_H__
+#define __ESPLUSPLAYER_SRC_TRACKSOURCE_TYPES_H__
+
+namespace esplusplayer {
+
+enum class SourceType {
+  kNone,
+  kBase,
+  kHttp,
+  kHls,
+  kDash,
+  kSmooth,
+  kFile,
+  kExternalSubtitle,
+  kNotFound,
+  kMax
+};
+
+enum class ContentFormat {
+  kNone,
+  kMP4Mov,
+  kMpegts,
+  k3GpMov,
+  kAudioMpeg,
+  kAudioMpegAac,
+  kMkv,
+  kAvi,
+  kVideoAsf,
+  kAppXid3,
+  kUnknown
+};
+
+enum class TrickPlayMode {
+  kNone,
+  kDefault,
+  kBySeek
+};
+
+enum class PlayingTimeSupport {
+  kNone,
+  kNeeded
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_TRACKSOURCE_TYPES_H__
diff --git a/include/esplusplayer/types/stream.h b/include/esplusplayer/types/stream.h
new file mode 100644 (file)
index 0000000..af0751d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_TYPES_STREAM_H__
+#define __ESPLUSPLAYER_TYPES_STREAM_H__
+
+namespace esplusplayer {
+
+/**
+ * @brief  Enumerations for the stream type
+ */
+enum class StreamType { kAudio = 0, kVideo, kMax };
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_STREAM_H__
\ No newline at end of file
diff --git a/include/esplusplayer/types/streaming_message.h b/include/esplusplayer/types/streaming_message.h
new file mode 100644 (file)
index 0000000..6017239
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_TYPES_STREAMING_MESSAGE_H__
+#define __ESPLUSPLAYER_TYPES_STREAMING_MESSAGE_H__
+
+namespace esplusplayer {
+
+enum class StreamingMessageType {
+  kNone = 0,
+  // kResolutionChanged,
+  // kAdEnd,
+  // kAdStart,
+  // kRenderDone,
+  kBitrateChange,
+  // kFragmentInfo,
+  kSparseTrackDetect,
+  // kStreamingEvent,
+  // kDrmChallengeData,
+  kDrmInitData,
+  // kHttpErrorCode,
+  // kDrmRenewSessionData,
+  kStreamEventType,
+  kStreamEventData,
+  kStreamSyncFlush,
+  kStreamMrsUrlChanged,
+  kDrmKeyRotation,
+  kFragmentDownloadInfo,
+  kDvrLiveLag,
+  kSparseTrackData,
+  kConnectionRetry,
+  kConfigLowLatency,
+  kCurlErrorDebugInfo,
+  kParDarChange
+};
+
+struct MessageParam {
+  std::string data;
+  int size = 0;
+  int code = 0;  // Error or warning code
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_STREAMING_MESSAGE_H__
\ No newline at end of file
diff --git a/include/esplusplayer/types/submitdata.h b/include/esplusplayer/types/submitdata.h
new file mode 100644 (file)
index 0000000..5906c94
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_TYPES_SUBMITDATA_H__
+#define __ESPLUSPLAYER_TYPES_SUBMITDATA_H__
+
+namespace esplusplayer {
+
+/**
+ * @brief Enumerations for the type of espacket submitted
+ */
+enum class SubmitDataType {
+  kCleanData,      // For clean data
+  kEncryptedData,  // For encrypted data
+  kTrustZoneData   // For trustzone data
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_TYPES_SUBMITDATA_H__
\ No newline at end of file
index 4258e3c..4da89a8 100644 (file)
@@ -1,45 +1,36 @@
-/**
- * @file
- * @brief          The buffer for playback.
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style buffer related enum.
- * @see            N/A
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_BUFFER_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_BUFFER_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_BUFFER_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_BUFFER_H__
 
 #ifdef __cplusplus
+#include <cstdint>
 extern "C" {
-#endif
-
+#else
 #include <stdint.h>
+#endif
 
 /**
  * @brief  Enumerations for the buffer status
  */
-typedef enum {
+enum esplusplayer_buffer_status {
   ESPLUSPLAYER_BUFFER_STATUS_UNDERRUN,
   ESPLUSPLAYER_BUFFER_STATUS_OVERRUN
-} esplusplayer_buffer_status;
+};
 
 /**
  * @brief  Enumerations for video decoded buffer type
@@ -47,13 +38,13 @@ typedef enum {
  * decoded video frame will be croped and scaled, then sent to
  * user by media_packet_video_decoded_cb, only support hw decoder now
 */
-typedef enum {
+enum esplusplayer_decoded_video_frame_buffer_type {
   ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_NONE,
   ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_COPY,
   ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_REFERENCE,
   ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_SCALE,
   ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_MANUAL_COPY
-} esplusplayer_decoded_video_frame_buffer_type;
+};
 
 /**
  * @brief  Enumerations for buffer size option
@@ -64,7 +55,7 @@ typedef enum {
  * MIN_BYTE_THRESHOLD : Emit under-run when queued bytes drops below this
  * percent of  max-byte-size(size%)
  */
-typedef enum {
+enum esplusplayer_buffer_option {
   ESPLUSPLAYER_BUFFER_AUDIO_MAX_TIME_SIZE,
   ESPLUSPLAYER_BUFFER_VIDEO_MAX_TIME_SIZE,
   ESPLUSPLAYER_BUFFER_AUDIO_MIN_TIME_THRESHOLD,
@@ -73,7 +64,7 @@ typedef enum {
   ESPLUSPLAYER_BUFFER_VIDEO_MAX_BYTE_SIZE,
   ESPLUSPLAYER_BUFFER_AUDIO_MIN_BYTE_THRESHOLD,
   ESPLUSPLAYER_BUFFER_VIDEO_MIN_BYTE_THRESHOLD
-} esplusplayer_buffer_option;
+};
 
 /**
  * @brief  video decoded buffer struct
@@ -97,8 +88,22 @@ typedef struct {
   void* private_data;
 } esplusplayer_decoded_video_packet;
 
+/**
+ * @brief  decoder input and output buffer time struct
+ */
+typedef struct {
+  /**
+   * @description   buffer pts, in millisecond
+   */
+  uint64_t pts;
+  /**
+   * @description   system time of decoder input or output buffer, in millisecond
+   */
+  uint64_t system_time;
+} esplusplayer_decoder_buffer_time;
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_BUFFER_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_BUFFER_H__
index a509f82..60b32d8 100644 (file)
@@ -1,34 +1,21 @@
-/**
- * @file
- * @brief          Display related enums
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style display releted data structures
- *                 and enums.
- * @see            The display related enum values and data structures will be
- *                 converted by this managed C version types to avoid binary
- *                 compatibility.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_DISPLAY_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_DISPLAY_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_DISPLAY_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_DISPLAY_H__
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,39 +24,37 @@ extern "C" {
 /**
  * @brief  Enumerations for the display mode
  */
-typedef enum {
+enum esplusplayer_display_mode {
   ESPLUSPLAYER_DISPLAY_MODE_LETTER_BOX,
   ESPLUSPLAYER_DISPLAY_MODE_ORIGIN_SIZE,
   ESPLUSPLAYER_DISPLAY_MODE_FULL_SCREEN,
   ESPLUSPLAYER_DISPLAY_MODE_CROPPED_FULL,
   ESPLUSPLAYER_DISPLAY_MODE_ORIGIN_OR_LETTER,
-  ESPLUSPLAYER_DISPLAY_MODE_DST_ROI,
-  ESPLUSPLAYER_DISPLAY_MODE_MAX
-} esplusplayer_display_mode;
+  ESPLUSPLAYER_DISPLAY_MODE_DST_ROI
+};
 
 /**
  * @brief  Enumerations for the display type
  */
-typedef enum {
+enum esplusplayer_display_type {
   ESPLUSPLAYER_DISPLAY_TYPE_NONE,
   ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
   ESPLUSPLAYER_DISPLAY_TYPE_EVAS,
-  ESPLUSPLAYER_DISPLAY_TYPE_MIXER,
-  ESPLUSPLAYER_DISPLAY_TYPE_MAX
-} esplusplayer_display_type;
+  ESPLUSPLAYER_DISPLAY_TYPE_MIXER
+};
 
 /**
  * @brief  Enumerations for the display rotation type
  */
-typedef enum {
+enum esplusplayer_display_rotation_type {
   ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_NONE,
   ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_90,
   ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_180,
   ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_270
-} esplusplayer_display_rotation_type;
+};
 
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_DISPLAY_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_DISPLAY_H__
index a40c213..dd4d979 100644 (file)
@@ -1,33 +1,21 @@
-/**
- * @file
- * @brief          Drm related enums
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style drm releted data structures and
- *                 enums.
- * @see            Drm releated event listeners, enum classes, etc.. are
- *                 converted to this.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_DRM_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_DRM_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_DRM_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_DRM_H__
 
 #ifdef __cplusplus
 extern "C" {
@@ -38,28 +26,28 @@ extern "C" {
 /**
  * @brief  Enumerations for the drm type
  */
-typedef enum {
+enum esplusplayer_drm_type {
   ESPLUSPLAYER_DRM_TYPE_NONE,
   ESPLUSPLAYER_DRM_TYPE_PLAYREADY,
   ESPLUSPLAYER_DRM_TYPE_MARLIN,
   ESPLUSPLAYER_DRM_TYPE_VERIMATRIX,
   ESPLUSPLAYER_DRM_TYPE_WV_MODULAR
-} esplusplayer_drm_type;
+};
 
 /**
  * @brief  Enumerations for the algorithm encrypted
  */
-typedef enum {
+enum esplusplayer_drmb_es_cipher_algorithm {
   ESPLUSPLAYER_DRMB_ES_CIPHER_ALGORITHM_UNKNOWN = -1,
   ESPLUSPLAYER_DRMB_ES_CIPHER_ALGORITHM_RC4 = 0,
   ESPLUSPLAYER_DRMB_ES_CIPHER_ALGORITHM_AES128_CTR = 1,
   ESPLUSPLAYER_DRMB_ES_CIPHER_ALGORITHM_AES128_CBC = 2
-} esplusplayer_drmb_es_cipher_algorithm;
+};
 
 /**
  * @brief  Enumerations for the algorithm encrypted
  */
-typedef enum {
+enum esplusplayer_drmb_es_media_format {
   ESPLUSPLAYER_DRMB_ES_MEDIA_FORMAT_NONE = 0,
   ESPLUSPLAYER_DRMB_ES_MEDIA_FORMAT_FMP4 = 1,
   ESPLUSPLAYER_DRMB_ES_MEDIA_FORMAT_TS = 2,
@@ -68,17 +56,17 @@ typedef enum {
   ESPLUSPLAYER_DRMB_ES_MEDIA_FORMAT_FMP4_VIDEO = 5,
   ESPLUSPLAYER_DRMB_ES_MEDIA_FORMAT_CLEAN_AUDIO = 6,
   ESPLUSPLAYER_DRMB_ES_MEDIA_FORMAT_PES = 7
-} esplusplayer_drmb_es_media_format;
+};
 
 /**
  * @brief  Enumerations for the phase for cipher
  */
-typedef enum {
+enum esplusplayer_drmb_es_cipher_phase {
   ESPLUSPLAYER_DRMB_ES_CIPHER_PHASE_NONE = 0,
   ESPLUSPLAYER_DRMB_ES_CIPHER_PHASE_INIT = 1,
   ESPLUSPLAYER_DRMB_ES_CIPHER_PHASE_UPDATE = 2,
   ESPLUSPLAYER_DRMB_ES_CIPHER_PHASE_FINAL = 3
-} esplusplayer_drmb_es_cipher_phase;
+};
 
 /**
  * @brief  Subsample information structure for encrypted es
@@ -110,12 +98,81 @@ typedef struct {
 
 /**
  * @brief  The information to decrypt es packet
+ * @version 6.0
+ */
+typedef struct {
+  /**
+   * @description   The handle to decrypt es packet.
+   */
+  unsigned long handle;
+  /**
+   * @description   The algorithm encrypted.
+   */
+  esplusplayer_drmb_es_cipher_algorithm algorithm;
+  /**
+   * @description   The es media format.
+   */
+  esplusplayer_drmb_es_media_format format;
+  /**
+   * @description   The phase to decrypt.
+   */
+  esplusplayer_drmb_es_cipher_phase phase;
+  /**
+   * @description   The KID.
+   */
+  unsigned char* kid;
+  /**
+   * @description   The length of KID.
+   */
+  uint32_t kid_length;
+  /**
+   * @description   The vector for initialization.
+   */
+  unsigned char* iv;
+  /**
+   * @description   The length of IV.
+   */
+  uint32_t iv_length;
+  /**
+   * @description   The sub data.
+   * @see           esplusplayer_drmb_es_fmp4_data
+   */
+  void* sub_data;
+  /**
+   * @description   The offset of sample.
+   *                It can be NULL.
+   *                If used, it have to be -1 terminated.
+   *                Max offset is 15.
+   */
+  int* split_offsets;
+  /**
+   * @description   It should be 0 when it must be protected with trustzone.
+   */
+  bool use_out_buffer;
+  /**
+   * @description   If use 'cbcs' pattern scheme, It should be 1. otherwise 0.
+   */
+  bool use_pattern;
+  /**
+   * @description   In case that use_patter is 1,
+   *                count of the encrypted blocks in the protection pattern.
+   */
+  uint32_t crypt_byte_block;
+  /**
+   * @description   In case that use_patter is 1,
+   *                count of the unencrypted blocks in the protection pattern.
+   */
+  uint32_t skip_byte_block;
+} esplusplayer_drm_info_64bit;
+
+/**
+ * @brief  The information to decrypt es packet
  */
 typedef struct {
   /**
    * @description   The handle to decrypt es packet.
    */
-  int32_t handle;
+  int handle;
   /**
    * @description   The algorithm encrypted.
    */
@@ -180,4 +237,4 @@ typedef struct {
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_DRM_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_DRM_H__
index c1f7874..fd180f5 100644 (file)
@@ -1,32 +1,21 @@
-/**
- * @file
- * @brief          Error related enums
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style error releted enum.
- * @see            All error enum values will be converted to this managed error
- *                 types.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_ERROR_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_ERROR_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ERROR_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ERROR_H__
 
 #include "tizen.h"
 
@@ -42,7 +31,7 @@ extern "C" {
 /**
  * @brief  Enumerations for the error type
  */
-typedef enum {
+enum esplusplayer_error_type {
   ESPLUSPLAYER_ERROR_TYPE_NONE = TIZEN_ERROR_NONE, /**< Successful */
   ESPLUSPLAYER_ERROR_TYPE_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
   ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
@@ -60,10 +49,10 @@ typedef enum {
   ESPLUSPLAYER_ERROR_TYPE_DRM_DECRYPTION_FAILED = ESPLUSPLAYER_CUSTOM_ERROR_CLASS | 0x05, /**< drm decryption failed */
   ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FORMAT = ESPLUSPLAYER_CUSTOM_ERROR_CLASS | 0x08,/**< format not supported */
   ESPLUSPLAYER_ERROR_TYPE_UNKNOWN
-} esplusplayer_error_type;
+};
 
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_ERROR_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ERROR_H__
index 417da2d..0f16cbb 100644 (file)
@@ -1,39 +1,31 @@
-/**
- * @file
- * @brief          The packet for elementary stream
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @see            plusplayer::EsPlusPlayer class
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPACKET_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPACKET_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPACKET_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPACKET_H__
 
 #include "esplusplayer_capi/matroska_color.h"
 #include "esplusplayer_capi/stream.h"
 
 #ifdef __cplusplus
+#include <cstdint>
 extern "C" {
-#endif
-
+#else
 #include <stdint.h>
+#endif
 
 /**
  * @brief   Es packet structure
@@ -111,4 +103,4 @@ typedef struct {
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPACKET_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPACKET_H__
index 9c17146..5326ed8 100644 (file)
@@ -1,31 +1,21 @@
-/**
- * @file           esplusplayer_capi.h
- * @brief          EsPlusPlayer api c version
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is esplusplayer api header implemented as C style to
- *                 avoid binary compatibility issues.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
- */
-
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_CAPI_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_CAPI_H__
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_CAPI_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_CAPI_H__
 
 #include "esplusplayer_capi/buffer.h"
 #include "esplusplayer_capi/display.h"
@@ -33,6 +23,7 @@
 #include "esplusplayer_capi/error.h"
 #include "esplusplayer_capi/espacket.h"
 #include "esplusplayer_capi/event.h"
+#include "esplusplayer_capi/latency.h"
 #include "esplusplayer_capi/state.h"
 #include "esplusplayer_capi/stream.h"
 #include "esplusplayer_capi/submitdatatype.h"
@@ -69,24 +60,35 @@ typedef void (*esplusplayer_closed_caption_cb)(const char* data, const int size,
 typedef void (*esplusplayer_flush_done_cb)(void*);
 typedef void (*esplusplayer_event_cb)(const esplusplayer_event_type,
                                       const esplusplayer_event_msg, void*);
+typedef void (*esplusplayer_video_latency_status_cb)(
+    const esplusplayer_latency_status latency_status, void*);
+typedef void (*esplusplayer_audio_latency_status_cb)(
+    const esplusplayer_latency_status latency_status, void*);
+typedef void (*esplusplayer_video_high_latency_cb)(void*);
+typedef void (*esplusplayer_audio_high_latency_cb)(void*);
+typedef void (*esplusplayer_video_frame_dropped_cb)(const uint64_t count,
+                                                    void*);
+typedef void (*esplusplayer_decoder_buffer_time_cb)(
+    const esplusplayer_stream_type, const esplusplayer_decoder_buffer_time,
+    void*);
 
 typedef void* esplusplayer_handle;
 
 /**
  * @brief  Enumerations for the Adaptive info type
  */
-typedef enum {
+enum esplusplayer_adaptive_info_type {
   ESPLUSPLAYER_ADAPT_INFO_TYPE_NONE,
   ESPLUSPLAYER_ADAPT_INFO_TYPE_DROPPED_FRAMES,
   ESPLUSPLAYER_ADAPT_INFO_TYPE_DROPPED_VIDEO_FRAMES_FOR_CATCHUP,
   ESPLUSPLAYER_ADAPT_INFO_TYPE_DROPPED_AUDIO_FRAMES_FOR_CATCHUP,
-} esplusplayer_adaptive_info_type;
+};
 
 /**
  * @brief   Enumerations for low latency mode
- * @remark  Public supports #ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL only.
+ * @version 3.2
  */
-typedef enum {
+enum esplusplayer_low_latency_mode {
   ESPLUSPLAYER_LOW_LATENCY_MODE_NONE = 0x0000,
   /**
    * @description   to support audio fast decoding/rendering
@@ -105,7 +107,7 @@ typedef enum {
    *                For applications using the UDP protocol, packet loss can
    *                occur. when video distortion by video packet loss is
    *                detected, it is a function to conceal distortion by showing
-   *                previous video frame. It is supported only in h.264 codec &
+   *                previous vido frame. It is supported only in h.264 codec &
    *                FHD or lower resolution.
    */
   ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO_DISTORTION_CONCEALMENT =
@@ -121,7 +123,7 @@ typedef enum {
    *                #ESPLUSPLAYER_STATE_READY from #ESPLUSPLAYER_STATE_IDLE.
    *                It changes the state immediately.
    *                It's usually used for sparse stream. (e.g. video packet
-   *                arrives but audio packet doesn't yet.)
+   *                arrives but audio packet does't yet.)
    */
   ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL = 0x0200,
   /**
@@ -159,27 +161,26 @@ typedef enum {
    */
   ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE_WITH_FIXED_RESOLUTION =
       ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE | 0x4000,
-} esplusplayer_low_latency_mode;
+};
 
 /**
  * @brief   Enumerations for esplusplayer audio codec type
  */
-typedef enum {
+enum esplusplayer_audio_codec_type {
   /**
    * @description   hardware codec can only be selected, default type
    */
   ESPLUSPLAYER_AUDIO_CODEC_TYPE_HW,
   /**
-   * @description   software codec can only be selected
+   * @description   sorfware codec can only be selected
    */
-  ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW,
-  ESPLUSPLAYER_AUDIO_CODEC_TYPE_MAX
-} esplusplayer_audio_codec_type;
+  ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW
+};
 
 /**
  * @brief   Enumerations for esplusplayer video codec type
  */
-typedef enum {
+enum esplusplayer_video_codec_type {
   /**
    * @description   hardware codec can only be selected, default type
    */
@@ -194,15 +195,14 @@ typedef enum {
   api.
                    esplusplayer_set_display()
   */
-  ESPLUSPLAYER_VIDEO_CODEC_TYPE_HW_N_DECODING,
-  ESPLUSPLAYER_VIDEO_CODEC_TYPE_MAX
+  ESPLUSPLAYER_VIDEO_CODEC_TYPE_HW_N_DECODING
 
-} esplusplayer_video_codec_type;
+};
 /**
  * @brief   Enumerations for esplusplayer audio easing type
  * @version 3.0
  */
-typedef enum {
+enum esplusplayer_audio_easing_type {
   /**
    * @description audio easing function type is linear
    */
@@ -219,33 +219,142 @@ typedef enum {
    * @description audio easing function type is none
    */
   ESPLUSPLAYER_AUDIO_EASING_NONE
-} esplusplayer_audio_easing_type;
+};
 
 /**
  * @brief   Enumerations for esplusplayer resource type
  * @version 3.0
  */
-typedef enum {
+enum esplusplayer_rsc_type {
   /**
    * @description video renderer type
    */
   ESPLUSPLAYER_RSC_TYPE_VIDEO_RENDERER
-} esplusplayer_rsc_type;
+};
 
 /**
  * @brief   Enumerations for advanced video quality type
- * @version 3.1
+ * @version 4.0
  */
-typedef enum {
+enum esplusplayer_advanced_picture_quality_type {
   /**
    * @description advanced picture quality for video call
+   * @version 3.1
    */
   ESPLUSPLAYER_ADVANCED_PICTURE_QUALITY_VIDEO_CALL,
   /**
    * @description advanced picture quality for usb camera
+   * @version 3.1
+   */
+  ESPLUSPLAYER_ADVANCED_PICTURE_QUALITY_USB_CAMERA,
+  /**
+   * @description advanced picture quality for airplay screen mirroring
+   * @version 4.0
+   */
+  ESPLUSPLAYER_ADVANCED_PICTURE_QUALITY_AIRPLAY_MIRRORING
+};
+
+/**
+ * @brief   Enumerations for audio resource type
+ * @version 3.8
+ */
+enum esplusplayer_audio_resource_type {
+  /**
+   * @description all audio resources(decoder/audio out) to main resources
+   */
+  ESPLUSPLAYER_AUDIO_RESOURCE_MAIN,
+  /**
+   * @description only audio decoder to sub resource
+   */
+  ESPLUSPLAYER_AUDIO_RESOURCE_SUB_DECODER,
+  /**
+   * @description only audio out to simple mix out resource
+   */
+  ESPLUSPLAYER_AUDIO_RESOURCE_SIMPLE_MIX_OUT
+};
+
+/**
+ * @brief   Enumerations for buffer level of simple mix out
+ * @version 3.8
+ */
+enum esplusplayer_simple_mix_out_buffer_level {
+  /**
+   * @description buffer level is low
+   */
+  ESPLUSPLAYER_SIMPLE_MIX_OUT_BUFFER_LOW,
+  /**
+   * @description buffer level is middle, default type
+   */
+  ESPLUSPLAYER_SIMPLE_MIX_OUT_BUFFER_MID,
+  /**
+   * @description buffer level is high
+   */
+  ESPLUSPLAYER_SIMPLE_MIX_OUT_BUFFER_HIGH
+};
+
+/**
+ * @brief  ESPlusplayer easing target volume, duration, type information
+ * @version 3.0
+ */
+typedef struct {
+  /**
+   * @description   audio easing target volume (0 ~ 100)
+   */
+  unsigned int volume;
+  /**
+   * @description   audio easing duration, in millisecond
+   */
+  unsigned int duration;
+  /**
+   * @description   audio easing function type
+   */
+  esplusplayer_audio_easing_type type;
+} esplusplayer_target_audio_easing_info;
+
+/**
+ * @brief  ESPlusplayer app id, version, type information
+ */
+typedef struct {
+  /**
+   * @description   App id for controlling resource.
+   */
+  char* id;
+  /**
+   * @description   When there is playback market issue, KPI logger will
+   *                send the version.
+   */
+  char* version;
+  /**
+   * @description   RunningApps.InformationTicker will use this type to show
+   *                stream information. ex) "MSE", "HTML5", etc..
+   */
+  char* type;
+} esplusplayer_app_info;
+
+/**
+ * @brief  ESPlusplayer app id, version, type, runtitle information
+ * @version 5.0
+ */
+typedef struct {
+  /**
+   * @description   App id for controlling resource.
+   */
+  char* id;
+  /**
+   * @description   When there is playback market issue, KPI logger will
+   *                send the version.
+   */
+  char* version;
+  /**
+   * @description   RunningApps.InformationTicker will use this type to show
+   *                stream information. ex) "MSE", "HTML5", etc..
+   */
+  char* type;
+  /**
+   * @description   App runtitle.
    */
-  ESPLUSPLAYER_ADVANCED_PICTURE_QUALITY_USB_CAMERA
-} esplusplayer_advanced_picture_quality_type;
+  char* runtitle;
+} esplusplayer_app_info_ex;
 
 typedef struct {
   /**
@@ -274,8 +383,9 @@ typedef struct {
 
 /**
  * @brief  resource allocate policy
+ * @version 3.3
  */
-typedef enum {
+enum esplusplayer_rsc_alloc_policy {
   /**
    * @description exclusive policy, RM will return the requested resources,
    * default policy
@@ -285,14 +395,20 @@ typedef enum {
    * @description conditional policy, when trying to allocate resources and
    * available resources are not left, RM will return fail.
    */
-  ESPLUSPLAYER_RSC_ALLOC_EXCLUSIVE_CONDITIONAL
-} esplusplayer_rsc_alloc_policy;
+  ESPLUSPLAYER_RSC_ALLOC_EXCLUSIVE_CONDITIONAL,
+  /**
+   * @description exclusive no explicit policy, RM will return available
+   * resources.
+   * @version 6.0
+   */
+  ESPLUSPLAYER_RSC_ALLOC_EXCLUSIVE_NO_EXPLICIT
+};
 
 /**
  * @brief Enumerations for the status of getting decoded video frame
  * @version 4.0
  */
-typedef enum {
+enum esplusplayer_get_decoded_video_frame_status_type {
   /** @brief successfully decoded video frame acquired. */
   ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_SUCCESS,
   /** @brief  it means app has to return the video before getting decoded
@@ -307,7 +423,50 @@ typedef enum {
    * @brief  internal error
    */
   ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN
-} esplusplayer_get_decoded_video_frame_status_type;
+};
+
+/**
+ * @brief Enumerations for the video scan type
+ * @version 4.0
+ */
+enum esplusplayer_video_scan_type {
+  /**
+   * @description progressive, mfd or dvde will be allocated for H.264 2K in
+   * normal mode.
+   */
+  ESPLUSPLAYER_VIDEO_SCAN_TYPE_PROGRESSIVE,
+  /**
+   * @description interlaced, only mfd has been allocated for H.264 2K in normal
+   * mode.
+   */
+  ESPLUSPLAYER_VIDEO_SCAN_TYPE_INTERLACED,
+};
+
+/**
+ * @brief Enumerations for the time unit type
+ * @version 5.0
+ */
+enum esplusplayer_time_unit_type {
+  /**
+   * @description the timeunit will be ms. It is default value.
+   */
+  ESPLUSPLAYER_TIME_UNIT_MS,
+  /**
+   * @description the timeunit will be us.
+   */
+  ESPLUSPLAYER_TIME_UNIT_US,
+};
+
+/**
+ * @brief  Enumerations for the video stream rotation type
+ * @version 5.2
+ */
+enum esplusplayer_video_stream_rotation_type {
+  ESPLUSPLAYER_VIDEO_ROTATION_NONE,
+  ESPLUSPLAYER_VIDEO_ROTATION_90,
+  ESPLUSPLAYER_VIDEO_ROTATION_180,
+  ESPLUSPLAYER_VIDEO_ROTATION_270
+};
 
 /**
  * @brief     Create a esplusplayer handle.
@@ -327,11 +486,13 @@ esplusplayer_handle esplusplayer_create();
 /**
  * @brief     Open esplusplayer handle.
  * @param     [in] handle : esplusplayer handle
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_handle esplayer = esplusplayer_create();
  *            esplusplayer_open(esplayer);
@@ -350,11 +511,13 @@ int esplusplayer_open(esplusplayer_handle handle);
  * @brief     Release all the player resources and all setting except callback
  *            functions.
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @pre       The player state must be all of #esplusplayer_state except
  *            #ESPLUSPLAYER_STATE_NONE.
  * @post      The player state will be #ESPLUSPLAYER_STATE_NONE.
@@ -366,11 +529,13 @@ int esplusplayer_close(esplusplayer_handle handle);
 /**
  * @brief     Release player handle.
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_create()
  * @endcode
@@ -382,23 +547,26 @@ int esplusplayer_close(esplusplayer_handle handle);
 int esplusplayer_destroy(esplusplayer_handle handle);
 
 /**
- * @brief     Flush the specific buffered stream data and release TV resource
- *            to change stream.
- * @remark    To activate, the stream must be set again.
+ * @brief     Not play the specific stream anymore.
+ * @remark    The submitted es packets will be dropped after deactivated.
+ *            It recommands to stop feeding the specific stream's packets.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : stream type which user want to deactivate.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
             refer to the sample code of esplusplayer_activate()
*            refer to the sample code of esplusplayer_activate()
  * @endcode
  * @pre       The player state must be at least #ESPLUSPLAYER_STATE_READY
  * @post      The player state is same as before calling
- *            esplusplayer_deactivate(). The deactivated stream will stop
- *            rendering and release the decoder, renderer resources.
+ *            esplusplayer_deactivate(). The buffered data of the deactivated
+ * stream will be flushed and the resources for decoding and rendering will be
+ * released.
  * @exception None
  * @see       esplusplayer_activate
  */
@@ -406,26 +574,31 @@ int esplusplayer_deactivate(esplusplayer_handle handle,
                             esplusplayer_stream_type type);
 
 /**
- * @brief     Reprepare for the specific stream playback.
- * @remark    There must be active stream to prepare playback.
+ * @brief     Restart to play the specific stream.
+ * @remark    If user wants to change the specific stream info, new stream info
+ * has to be set before activate. User has to submit the specific stream from
+ * the current playing time for activating. The video stream has to be submitted
+ * from Iframe.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : stream type which user want to activate.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
  *            esplusplayer_deactivate(esplayer, ESPLUSPLAYER_STREAM_TYPE_VIDEO);
- *            esplusplayer_video_stream_info stream;
- *            stream.width = 640;
- *            stream.height = 352;
- *            stream.mime_type = ESPLUSPLAYER_VIDEO_MIME_TYPE_H264;
- *            stream.framerate_num = 30;
- *            stream.framerate_den = 1;
- *            esplusplayer_set_video_stream_info(esplayer, &stream);
+ *            esplusplayer_set_video_stream_info* stream;
+ *            stream->width = 640;
+ *            stream->height = 352;
+ *            stream->mime_type = ESPLUSPLAYER_VIDEO_MIME_TYPE_H264;
+ *            stream->framerate_num = 30;
+ *            stream->framerate_den = 1;
+ *            esplusplayer_set_video_stream_info(esplayer, stream);
  *            esplusplayer_activate(esplayer, ESPLUSPLAYER_STREAM_TYPE_VIDEO);
  *            // ... your codes ...
  *            esplusplayer_close(esplayer);
@@ -441,21 +614,104 @@ int esplusplayer_activate(esplusplayer_handle handle,
                           esplusplayer_stream_type type);
 
 /**
+ * @brief     Not play the audio stream anymore.
+ * @remark    User has to keep feeding audio packets like when playing audio.
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *             refer to the sample code of esplusplayer_activate_audio()
+ * @endcode
+ * @pre       The player state must be at least #ESPLUSPLAYER_STATE_IDLE
+ * @post      The player state is same as before calling
+ *            esplusplayer_deactivate_audio(). The player will keep buffering
+ *            the audio packets and consuming it at the rendering time.
+ *            All audio resources of decoder and renderer will be released.
+ * @exception None
+ * @version   6.0
+ * @see       esplusplayer_activate_audio
+ */
+int esplusplayer_deactivate_audio(esplusplayer_handle handle);
+
+/**
+ * @brief     Restart to play the audio stream.
+ * @remark    User can't change the audio stream info before activate.
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            // play one esplayer in normal
+ *            esplusplayer_handle esplayer1 = esplusplayer_create();
+ *            esplusplayer_open(esplayer1);
+ *            esplusplayer_audio_stream_info audio_stream_1;
+ *            audio_stream_1.codec_data = nullptr;
+ *            audio_stream_1.codec_data_length = 0;
+ *            esplusplayer_set_audio_stream_info(esplayer1, &audio_stream_1);
+ *            // ... your codes ...
+ *            esplusplayer_prepare_async(esplayer1);
+ *            esplusplayer_start(esplayer1);
+ *
+ *            // play one more esplayer started in deactivate
+ *            esplusplayer_handle esplayer2 = esplusplayer_create();
+ *            esplusplayer_open(esplayer2);
+ *            esplusplayer_audio_stream_info audio_stream_2;
+ *            audio_stream_2.codec_data = nullptr;
+ *            audio_stream_2.codec_data_length = 0;
+ *            esplusplayer_set_audio_stream_info(esplayer2, &audio_stream_2);
+ *            // ... your codes ...
+ *            esplusplayer_deactivate_audio(esplayer2);
+ *            esplusplayer_prepare_async(esplayer2);
+ *            esplusplayer_start(esplayer2);
+ *
+ *            // if you want to play esplayer2, deactivate esplayer1 first
+ *            // and then activate esplayer2
+ *            esplusplayer_deactivate_audio(esplayer1);
+ *            esplusplayer_activate_audio(esplayer2);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer1);
+ *            esplusplayer_destroy(esplayer1);
+ *            esplusplayer_close(esplayer2);
+ *            esplusplayer_destroy(esplayer2);
+ * @endcode
+ * @pre       The player state must be at least #ESPLUSPLAYER_STATE_READY
+ * @post      The player state is same as before calling
+ *            esplusplayer_activate_audio(). Rebuild audio pipeline to render
+ *            the audio stream.
+ * @exception None
+ * @version   6.0
+ * @see       esplusplayer_deactivate_audio
+ */
+int esplusplayer_activate_audio(esplusplayer_handle handle);
+
+/**
  * @brief     Prepare the player for playback, asynchronously.
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            static void OnPrepareDone(bool ret, void* userdata) {
  *                //Something you want to do when prepare done, but, we strongly
- *                //recommend DO NOT CALL PLAYER APIs in this callback
+ *                //recommend DO NOT CALL PLAYER APIs in this callbck
  *                printf("OnPrepareDone\n");
  *            }
  *            esplusplayer_handle esplayer = esplusplayer_create();
- *            esplusplayer_set_prepare_async_done_cb(esplayer, OnPrepareDone,nullptr);
+ *            esplusplayer_set_prepare_async_done_cb(esplayer,
+ * OnPrepareDone,nullptr);
  *            esplusplayer_open(esplayer);
  *            esplusplayer_prepare_async(esplayer);
  *            // ... your codes ...
@@ -487,11 +743,13 @@ int esplusplayer_prepare_async(esplusplayer_handle handle);
 /**
  * @brief     Start playback.
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            esplusplayer_start(esplayer);
@@ -511,11 +769,13 @@ int esplusplayer_start(esplusplayer_handle handle);
 /**
  * @brief     Stop playing media content.
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
@@ -540,11 +800,13 @@ int esplusplayer_stop(esplusplayer_handle handle);
 /**
  * @brief     Pause playing media content.
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
@@ -565,11 +827,13 @@ int esplusplayer_pause(esplusplayer_handle handle);
 /**
  * @brief     Resume playing media content.
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
@@ -595,11 +859,13 @@ int esplusplayer_resume(esplusplayer_handle handle);
  * @param     [in] playback_rate :  the playback rate from 0.0 to 2.0.
  * @param     [in] audio_mute :  the audio is mute on/off, true: mute on, false:
  * mute off.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
@@ -621,12 +887,15 @@ int esplusplayer_set_playback_rate(esplusplayer_handle handle,
 /**
  * @brief     Seek for playback, asynchronously.
  * @param     [in] handle : esplusplayer handle.
- * @param     [in] time_ms : seek time in milliseconds
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @param     [in] time : seek time default in milliseconds, can be set by
+ * @esplusplayer_set_timeunit_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
@@ -639,7 +908,7 @@ int esplusplayer_set_playback_rate(esplusplayer_handle handle,
  *            #ESPLUSPLAYER_STATE_PAUSED or #ESPLUSPLAYER_STATE_PLAYING.
  *            In ESPLUSPLAYER_STATE_IDLE, this api can be called exceptionally
  *            between esplusplayer_open() and esplusplayer_prepare_async().
- *            the start time of playback can be set explicitly when starting
+ *            the start time of plyabak can be set explicitly when starting
  *            first playback. In this case, esplusplayer_set_seek_done_cb is not
  *            called.
  * @post      None
@@ -654,18 +923,50 @@ int esplusplayer_set_playback_rate(esplusplayer_handle handle,
  * @see       esplusplayer_ready_to_seek_cb() \n
  *            esplusplayer_prepare_async()
  */
-int esplusplayer_seek(esplusplayer_handle handle, uint64_t time_ms);
+int esplusplayer_seek(esplusplayer_handle handle, uint64_t time);
+
+/**
+ * @brief     Set App id to esplayer to control resource confliction.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] app_info : application id, version, type.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_app_info appinfo;
+ *            appinfo.id = "youtube";
+ *            appinfo.version = "3.0";
+ *            appinfo.type = "MSE";
+ *            esplusplayer_handle esplayer = esplusplayer_create();
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_app_info(esplayer,&appinfo);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception None
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_set_app_info(esplusplayer_handle handle,
+                              const esplusplayer_app_info* app_info);
 
 /**
  * @brief     Set the video display.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : display type.
  * @param     [in] window : the handle to display window.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_display(esplayer,ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,window);
@@ -685,8 +986,6 @@ int esplusplayer_seek(esplusplayer_handle handle, uint64_t time_ms);
  */
 int esplusplayer_set_display(esplusplayer_handle handle,
                              esplusplayer_display_type type, void* window);
-
-#ifdef TIZEN_FEATURE_TV
 /**
  * @brief     Set the video display.
  * @param     [in] handle : esplusplayer handle.
@@ -709,17 +1008,38 @@ int esplusplayer_set_display_ecore_subsurface(esplusplayer_handle handle,
                                               esplusplayer_display_type type,
                                               void* subsurface, int x, int y,
                                               int width, int height);
-#endif
-
+/**
+ * @brief     Set the video display.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] type : display type.
+ * @param     [in] window : the ecore wayland2 window handle.
+ * @param     [in] x : the x coordinate of window.
+ * @param     [in] y : the ycoordinate of window.
+ * @param     [in] width : the width of window.
+ * @param     [in] height : the height of window.
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @pre       The player state must be #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception   None
+ * @version   4.0
+ * @see       esplusplayer_set_display_mode() \n
+ *            esplusplayer_set_display_roi() \n
+ *            esplusplayer_set_display_visible()
+ */
+int esplusplayer_set_ecore_display(esplusplayer_handle handle,
+                                   esplusplayer_display_type type, void* window,
+                                   int x, int y, int width, int height);
 /**
  * @brief     Set the video display mode.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] mode : display mode.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_display_mode(esplayer,ESPLUSPLAYER_DISPLAY_MODE_DST_ROI);
@@ -746,11 +1066,13 @@ int esplusplayer_set_display_mode(esplusplayer_handle handle,
  * @param     [in] y : var startPointY in src video area.
  * @param     [in] width : width of display in src video area.
  * @param     [in] height : height of display in src video area.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_display(esplayer,ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,window);
@@ -775,17 +1097,47 @@ int esplusplayer_set_display_roi(esplusplayer_handle handle, int x, int y,
                                  int width, int height);
 
 /**
+ * @brief     Set the video stretch mode on 21:9 TV.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] mode : stretch mode.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_stretch_mode(esplayer,1);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #esplusplayer_state except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ * @post      None
+ * @exception None
+ * @version   4.8
+ * @remark    If no display is set, no operation is performed.
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_set_video_roi()
+ */
+int esplusplayer_set_stretch_mode(esplusplayer_handle handle, int mode);
+
+/**
  * @brief     Set the Crop Area(Region Of Src ratio) area of display.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] scale_x: x label ratio in src video area.
  * @param     [in] scale_y: y label ratio in src video area.
  * @param     [in] scale_w: width ratio in src video area.
  * @param     [in] scale_h: height ratio in src video area.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_display(esplayer,ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,window);
@@ -797,7 +1149,7 @@ int esplusplayer_set_display_roi(esplusplayer_handle handle, int x, int y,
  *            #ESPLUSPLAYER_STATE_NONE. \n
  * @post      None
  * @exception None
- * @remark    The minimum value of input are 0,maximum value is 1.
+ * @remark    The minimum value of input are 0,maximun value is 1.
  * @see       esplusplayer_open() \n
  *            esplusplayer_set_display() \n
  *            esplusplayer_set_display_visible()
@@ -806,15 +1158,42 @@ int esplusplayer_set_video_roi(esplusplayer_handle handle, double scale_x,
                                double scale_y, double scale_w, double scale_h);
 
 /**
+ * @brief     Resize the render rectangle(the max region that video can be
+ * displayed).
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] x: x coordinate of render rectangle.
+ * @param     [in] y: y coordinate of render rectangle.
+ * @param     [in] width: width  of render rectangle.
+ * @param     [in] height: height  of render rectangle.
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @pre       Should be called after esplusplayer_set_display() \n
+ *            esplusplayer_set_surface_display() \n
+ *            esplusplayer_set_ecore_display() \n
+ *            esplusplayer_set_display_ecore_subsurface
+ * @post      None
+ * @exception   None
+ * @version   3.2
+ * @remark    The minimum value of width and height are 1.
+ * @see       esplusplayer_set_display() \n
+ *            esplusplayer_set_surface_display() \n
+ *            esplusplayer_set_ecore_display() \n
+ *            esplusplayer_set_display_ecore_subsurface
+ */
+int esplusplayer_resize_render_rect(esplusplayer_handle handle, int x, int y,
+                                    int width, int height);
+
+/**
  * @brief     Set the visibility of the video display.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] visible : the visibility of the display.
  *            (@c true = visible, @c false = non-visible)
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_display(esplayer,ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,window);
@@ -835,11 +1214,13 @@ int esplusplayer_set_display_visible(esplusplayer_handle handle, bool visible);
  * @brief     Set the rotate angle of the video display.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] rotation : the rotate angle of the display.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_display(esplayer,ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,window);
@@ -862,15 +1243,18 @@ int esplusplayer_set_display_rotation(
  * @param     [in] handle : esplusplayer handle.
  * @param     [out] rotation : the rotate angle of the display which want to
  * get.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_display_rotation(esplayer,ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_90);
- *            esplusplayer_display_rotation_type rotation_get = ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_NONE;
+ *            esplusplayer_display_rotation_type rotation_get =
+ * ESPLUSPLAYER_DISPLAY_ROTATION_TYPE_NONE;
  *            // ... your codes ...
  *            esplusplayer_get_display_rotation(esplayer,&rotation_get);
  *            // ... your codes ...
@@ -887,15 +1271,49 @@ int esplusplayer_get_display_rotation(
     esplusplayer_handle handle, esplusplayer_display_rotation_type* rotation);
 
 /**
+ * @deprecated Deprecated since API V2.0. Use
+ *             esplusplayer_set_submit_data_type() instead.
+ * @brief     Set whether to send decrypted es packets in the trust zone.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] using_tz : whether to use trust zone memory.
+ *            (@c true = if decrypted packets are sent in trust zone, @c false =
+ *            otherwise @c)
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_tz_use(esplayer, true);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception None
+ * @remark    This API have to be called before calling
+ *            esplusplayer_prepare_async(). \n If using_tz is set to true, use
+ *            esplusplayer_submit_trust_zone_packet() to send decrypted packets.
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_submit_trust_zone_packet()
+ */
+int esplusplayer_set_tz_use(esplusplayer_handle handle, bool using_tz);
+
+/**
  * @brief     Set whether to send decrypted es packets in the trust zone or
  *            encrypted es packets.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : whether to use trust zone memory or encrypted data
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_submit_data_type(esplayer,ESPLUSPLAYER_SUBMIT_DATA_TYPE_CLEAN_DATA);
@@ -909,9 +1327,13 @@ int esplusplayer_get_display_rotation(
  *            esplusplayer_prepare_async(). \n
  *            If type is ESPLUSPLAYER_SUBMIT_DATA_TYPE_CLEAN_DATA use
  *            esplusplayer_submit_packet() to send clean packets. \n
+ *            If type is ESPLUSPLAYER_SUBMIT_DATA_TYPE_TRUSTZONE_DATA, use
+ *            esplusplayer_submit_trust_zone_packet() to send decrypted packets
+ *            in trust zone \n
  *            If type is ESPLUSPLAYER_SUBMIT_DATA_TYPE_ENCRYPTED_DATA, use
  *            esplusplayer_submit_encrypted_packet() to send encrypted packets.
  * @see       esplusplayer_open() \n
+ *            esplusplayer_submit_trust_zone_packet() \n
  *            esplusplayer_submit_encrypted_packet() \n
  *            esplusplayer_submit_data_type
  */
@@ -923,11 +1345,13 @@ int esplusplayer_set_submit_data_type(esplusplayer_handle handle,
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] mute : on mute of the sound.
  *            (@c true = mute, @c false = non-mute)
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success, otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success, otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_audio_mute(esplayer, true);
@@ -971,54 +1395,72 @@ esplusplayer_state esplusplayer_get_state(esplusplayer_handle handle);
  *                // ... your codes ...
  *                printf ("OnPrepareDone\n");
  *            }
- *            static void OnReadyToPrepare(const esplusplayer_stream_type type,void* userdata) {
+ *            static void OnReadyToPrepare(const esplusplayer_stream_type
+ *type,void* userdata) {
  *                if (type == ESPLUSPLAYER_STREAM_TYPE_VIDEO) {
- *                    //Something you want to do when feed es video stream is allowed
+ *                    //Something you want to do when feed es video stream is
+ *allowed
  *                } else {
- *                    //Something you want to do when feed es audio stream is allowed
+ *                    //Something you want to do when feed es audio stream is
+ *allowed
  *                }
  *                //Something you want to do when OnReadyToPrepare
  *                printf ("OnReadyToPrepare\n");
  *            }
- *            static void OnBufferByteStatus(const esplusplayer_stream_type type,
- *                                           const esplusplayer_buffer_status status,
- *                                           uint64_t byte_size, void* userdata) {
+ *            static void OnBufferByteStatus(const esplusplayer_stream_type
+ *type,
+ *                                           const esplusplayer_buffer_status
+ *status,
+ *                                           uint64_t byte_size, void* userdata)
+ *{
  *                if (type == ESPLUSPLAYER_STREAM_TYPE_VIDEO) {
  *                    if (status == ESPLUSPLAYER_BUFFER_STATUS_UNDERRUN) {
- *                        //Something you want to do when es video buffer is enough
+ *                        //Something you want to do when es video buffer is
+ *enough
  *                    } else {
- *                        //Something you want to do when es video buffer is not enough
+ *                        //Something you want to do when es video buffer is not
+ *enough
  *                    }
  *                } else {
  *                    if (status == ESPLUSPLAYER_BUFFER_STATUS_UNDERRUN) {
- *                        //Something you want to do when es audio buffer is enough
+ *                        //Something you want to do when es audio buffer is
+ *enough
  *                    } else {
- *                        //Something you want to do when es audio buffer is not enough
+ *                        //Something you want to do when es audio buffer is not
+ *enough
  *                    }
  *                }
  *                //Something you want to do when OnBufferByteStatus
  *                printf ("OnBufferByteStatus\n");
  *            }
- *            static void OnBufferTimeStatus(const esplusplayer_stream_type type,
- *                                           const esplusplayer_buffer_status status,
- *                                           uint64_t time_size,void* userdata) {
+ *            static void OnBufferTimeStatus(const esplusplayer_stream_type
+ *type,
+ *                                           const esplusplayer_buffer_status
+ *status,
+ *                                           uint64_t time_size,void* userdata)
+ *{
  *                if (type == ESPLUSPLAYER_STREAM_TYPE_VIDEO) {
  *                    if (status == ESPLUSPLAYER_BUFFER_STATUS_UNDERRUN) {
- *                        //Something you want to do when es video buffer is enough
+ *                        //Something you want to do when es video buffer is
+ *enough
  *                    } else {
- *                        //Something you want to do when es video buffer is not enough
+ *                        //Something you want to do when es video buffer is not
+ *enough
  *                    }
  *                } else {
  *                    if (status == ESPLUSPLAYER_BUFFER_STATUS_UNDERRUN) {
- *                        //Something you want to do when es audio buffer is enough
+ *                        //Something you want to do when es audio buffer is
+ *enough
  *                    } else {
- *                        //Something you want to do when es audio buffer is not enough
+ *                        //Something you want to do when es audio buffer is not
+ *enough
  *                    }
  *                }
  *                //Something you want to do when OnBufferTimeStatus
  *                printf ("OnBufferTimeStatus\n");
  *            }
- *            void FeedEsPacket(esplusplayer_handle player,esplusplayer_es_packet pkt) {
+ *            void FeedEsPacket(esplusplayer_handle
+ *player,esplusplayer_es_packet pkt) {
  *               // ... your codes ...
  *              if(feed is allowed && buffer is enough) {
  *                   esplusplayer_submit_packet(player, &pkt);
@@ -1057,7 +1499,39 @@ esplusplayer_state esplusplayer_get_state(esplusplayer_handle handle);
 esplusplayer_submit_status esplusplayer_submit_packet(
     esplusplayer_handle handle, esplusplayer_es_packet* packet);
 
-#ifdef TIZEN_FEATURE_TV
+/**
+ * @brief     Submit es packet to decode audio or video.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] packet : es packet pointer.
+ * @param     [in] tz_handle : es decrypted tz handle.
+ * @return    @c ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS : succeed to submit es
+ *            packet,
+ *            otherwise @c : fail to submit es packet.
+ * @code
+ *            refer to the sample code of esplusplayer_submit_packet();
+ * @endcode
+ * @pre       User can submit es packets after
+ *            esplusplayer_ready_to_prepare_cb() or
+ *            esplusplayer_ready_to_seek_cb() is called.
+ * @post      None
+ * @exception None
+ * @remark    Amount of packets for at least one decoded frame must be submitted
+ *            after calling esplusplayer_prepare_async() or esplusplayer_seek()
+ *            for invoking esplusplayer_prepare_async_done_cb() or
+ *            esplusplayer_seek_done_cb(). \n
+ *            To use this api, Must set
+ * ESPLUSPLAYER_SUBMIT_DATA_TYPE_TRUSTZONE_DATA using
+ * esplusplayer_set_submit_data_type() \n This api must be called from a
+ * different thread than other apis.
+ * @see       esplusplayer_es_packet \n
+ *            esplusplayer_buffer_status_cb() \n
+ *            esplusplayer_ready_to_prepare_cb() \n
+ *            esplusplayer_ready_to_seek_cb()
+ */
+esplusplayer_submit_status esplusplayer_submit_trust_zone_packet(
+    esplusplayer_handle handle, esplusplayer_es_packet* packet,
+    uint32_t tz_handle);
+
 /**
  * @brief     Submit encrypted es packet to decode and decrypt audio or video.
  * @param     [in] handle : esplusplayer handle.
@@ -1086,27 +1560,65 @@ esplusplayer_submit_status esplusplayer_submit_packet(
  * esplusplayer_set_submit_data_type() \n This api must be called from a
  * different thread than other apis.
  * @see       esplusplayer_es_packet \n
- *            esplusplayer_drm_info \n
+ *            esplusplayer_drm_info_64bit \n
  *            esplusplayer_buffer_status_cb() \n
  *            esplusplayer_ready_to_prepare_cb() \n
  *            esplusplayer_ready_to_seek_cb() \n
  *            esplusplayer_submit_packet()
+ *@version 6.0
  */
-esplusplayer_submit_status esplusplayer_submit_encrypted_packet(
+esplusplayer_submit_status esplusplayer_submit_encrypted_packet_64bit(
     esplusplayer_handle handle, esplusplayer_es_packet* packet,
-    esplusplayer_drm_info* drm_info);
-#endif
+    esplusplayer_drm_info_64bit* drm_info);
 
 /**
- * @brief     Generate EOS(End Of Stream) packet explicitly and submit it to the
- *            player.
+ * @brief     Submit encrypted es packet to decode and decrypt audio or video.
  * @param     [in] handle : esplusplayer handle.
- * @param     [in] type : stream type which reaches eos.
- * @return    @c ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS : succeed to submit EOS
- * packet,
- *            otherwise @c : fail to submit EOS packet.
+ * @param     [in] packet : es packet pointer.
+ * @param     [in] drm_info : information to decrypt es packet.
+ *                            esplusplayer doesn't take ownership. user should
+ *                            free it. if you deliver it as (null), this api
+ *                            works as esplusplayer_submit_packet().
+ * @return    @c ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS : succeed to submit es
+ *            packet,
+ *            otherwise @c : fail to submit es packet.
  * @code
- *            esplusplayer_handle esplayer = esplusplayer_create();
+ *            refer to the sample code of esplusplayer_submit_packet();
+ * @endcode
+ * @pre       User can submit es packets after
+ *            esplusplayer_ready_to_prepare_cb() or
+ *            esplusplayer_ready_to_seek_cb() is called.
+ * @post      None
+ * @exception None
+ * @remark    Amount of packets for at least one decoded frame must be submitted
+ *            after calling esplusplayer_prepare_async() or esplusplayer_seek()
+ *            for invoking esplusplayer_prepare_async_done_cb() or
+ *            esplusplayer_seek_done_cb(). \n
+ *            To use this api, Must set
+ * ESPLUSPLAYER_SUBMIT_DATA_TYPE_ENCRYPTED_DATA using
+ * esplusplayer_set_submit_data_type() \n This api must be called from a
+ * different thread than other apis.
+ * @see       esplusplayer_es_packet \n
+ *            esplusplayer_drm_info \n
+ *            esplusplayer_buffer_status_cb() \n
+ *            esplusplayer_ready_to_prepare_cb() \n
+ *            esplusplayer_ready_to_seek_cb() \n
+ *            esplusplayer_submit_packet()
+ */
+esplusplayer_submit_status esplusplayer_submit_encrypted_packet(
+    esplusplayer_handle handle, esplusplayer_es_packet* packet,
+    esplusplayer_drm_info* drm_info);
+
+/**
+ * @brief     Generate EOS(End Of Stream) packet explicitly and submit it to the
+ *            player.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] type : stream type which reaches eos.
+ * @return    @c ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS : succeed to submit EOS
+ * packet,
+ *            otherwise @c : fail to submit EOS packet.
+ * @code
+ *            esplusplayer_handle esplayer = esplusplayer_create();
  *            // ... your codes ...
  *            esplusplayer_submit_eos_packet(esplayer,ESPLUSPLAYER_STREAM_TYPE_VIDEO);
  *            // ... your codes ...
@@ -1122,11 +1634,13 @@ esplusplayer_submit_status esplusplayer_submit_eos_packet(
  * @brief     Set audio stream to have contents information.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] stream : audio stream pointer.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_audio_stream_info audio_stream;
@@ -1152,11 +1666,13 @@ int esplusplayer_set_audio_stream_info(esplusplayer_handle handle,
  * @brief     Set video stream to have contents information.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] stream : video stream pointer.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE except
  *            video stream is deactivated.
  * @post      None
@@ -1172,12 +1688,15 @@ int esplusplayer_set_video_stream_info(esplusplayer_handle handle,
 /**
  * @brief     Get the current playing time of the associated media.
  * @param     [in] handle : esplusplayer handle.
- * @param     [out] ms : current playing time in milliseconds.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @param     [out] cur_time : current playing time default in milliseconds, can
+ * be set by @esplusplayer_set_timeunit_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            esplusplayer_start(esplayer);
@@ -1193,18 +1712,20 @@ int esplusplayer_set_video_stream_info(esplusplayer_handle handle,
  * @exception None
  * @see       esplusplayer_prepare_async()
  */
-int esplusplayer_get_playing_time(esplusplayer_handle handle, uint64_t* ms);
-
+int esplusplayer_get_playing_time(esplusplayer_handle handle,
+                                  uint64_t* cur_time);
 /**
  * @brief     Get dropped frame counts in videosink.
  * @param     [in] handle : esplusplayer handle.
  * @param     [out] padaptive_info : dropped frame counts.
  * @param     [in] adaptive_type : type of adaptive info which APP want to get.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
@@ -1228,11 +1749,13 @@ int esplusplayer_get_adaptive_info(
  * @brief     Set volume to player
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] volume : volume level(0 ~ 100).
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            int vol = 80;
@@ -1251,11 +1774,13 @@ int esplusplayer_set_volume(esplusplayer_handle handle, const int volume);
  * @brief     Get volume from player
  * @param     [in] handle : esplusplayer handle.
  * @param     [out] volume : volume ptr.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            // ... your codes ...
@@ -1275,11 +1800,13 @@ int esplusplayer_get_volume(esplusplayer_handle handle, int* volume);
  * @brief     Set decoded video frame buffer type.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : one of the video decoded buffer type to set .
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_video_frame_buffer_type(esplayer,
@@ -1307,16 +1834,69 @@ int esplusplayer_set_video_frame_buffer_type(
     esplusplayer_decoded_video_frame_buffer_type type);
 
 /**
+ * @brief     Set the request frame rate of decoded video
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] request_framerate : the request frame rate of returned
+ * decoded video frame
+ *                 The value of track_framerate(A) and request_framerate(B)
+ * should be one of the following sets:
+ *                 track_framerate indicate the frame rate of input video stream
+ *                 1.A/(A-B) = X ,X means drop 1 frame every X frame
+ *                 2.Special cases,such as 24000/1000 -> 15000/1000
+ *                 when request_framerate.num = 0, return none decoded video
+ * frame
+ *                 when request_framerate.num/request_framerate.den =
+ *                   track_framerate.num/track_framerate.den, return all decoded
+ *                   video frame
+ *                 when request_framerate.num/request_framerate.den <
+ *                   track_framerate.num/track_framerate.den, drop some decoded
+ *                   video frame
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @pre       The player state must be not #ESPLUSPLAYER_STATE_NONE.
+ * @post      None
+ * @exception   None
+ * @version   3.4
+ * @remark    only works when decoded video frame buffer type is scale
+ *            esplusplayer_set_video_frame_buffer_type()
+ *            esplusplayer_set_media_packet_video_decoded_cb()
+ */
+int esplusplayer_set_decoded_video_frame_rate(
+    esplusplayer_handle handle, esplusplayer_rational request_framerate);
+
+/**
+ * @brief     Set the target scale resolution when decoded video frame buffer
+ * type is scale
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] target_width : scale target width of video frame buffer.
+ * @param     [in] target_width : scale target height of video frame buffer.
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @pre       The player state can be set in all states except
+ * #ESPLUSPLAYER_STATE_NONE.
+ * @post      None
+ * @exception   None
+ * @version   3.1
+ * @remark    esplusplayer_set_video_frame_buffer_type()
+ *            esplusplayer_set_media_packet_video_decoded_cb()
+ *            If user don't call this api to set target_width and target_height,
+ * the default
+ *            target scale resolution is 960x540
+ */
+int esplusplayer_set_video_frame_buffer_scale_resolution(
+    esplusplayer_handle handle, uint32_t target_width, uint32_t target_height);
+
+/**
  * @brief     Flush buffers for a player.
  * @param     [in] handle : esplusplayer handle ptr.
  * @param     [in] type : choose which stream data need to be
  *            flush,audio/video,if need flush all pipeline can call this API
  * twice.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            prepare esplayer done
  *            // ... your codes ...
@@ -1340,7 +1920,8 @@ int esplusplayer_flush(esplusplayer_handle handle,
  * @code
  *            // ... your codes ...
  *            const char* error;
- *            error = esplusplayer_get_error_string(ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE);
+ *            error =
+ * esplusplayer_get_error_string(ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE);
  *            // ... your codes ...
  * @endcode
  * @pre       None
@@ -1354,11 +1935,13 @@ const char* esplusplayer_get_error_string(esplusplayer_error_type type);
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] error_cb : the error callback function to register.
  * @param     [in] userdata : userdata of esplusplayer_error_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            static void OnError(const esplusplayer_error_type err_code, void*
  *                userdata) {
@@ -1388,11 +1971,13 @@ int esplusplayer_set_error_cb(esplusplayer_handle handle,
  * @param     [in] buffer_status_cb : the buffer status callback function to
  * register.
  * @param     [in] userdata : userdata of esplusplayer_buffer_status_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1415,11 +2000,13 @@ int esplusplayer_set_buffer_status_cb(
  * @param     [in] buffer_status_cb : the buffer byte status callback function
  *            to register.
  * @param     [in] userdata : userdata of esplusplayer_buffer_byte_status_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_submit_packet();
  * @endcode
@@ -1440,11 +2027,13 @@ int esplusplayer_set_buffer_byte_status_cb(
  * @param     [in] buffer_status_cb : the buffer time status callback function
  *            to register.
  * @param     [in] userdata : userdata of esplusplayer_buffer_time_status_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ failed
  * @code
               refer to the sample code of esplusplayer_submit_packet();
  * @endcode
@@ -1463,15 +2052,79 @@ int esplusplayer_set_buffer_time_status_cb(
     esplusplayer_buffer_time_status_cb buffer_status_cb, void* userdata);
 
 /**
+ * @brief     Set a callback function to be invoked when video latency status
+ *            is changed.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] video_latency_status_cb : the video latency status callback
+ * function to register.
+ * @param     [in] userdata : userdata of
+ *             esplusplayer_set_video_latency_status_cb()
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            refer to the sample code of esplusplayer_set_error_cb();
+ * @endcode
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_NONE
+ *            or #ESPLUSPLAYER_STATE_IDLE.
+ * @post      esplusplayer_video_latency_status_cb() will be invoked.
+ * @exception None
+ * @version   2.7
+ * @remark    esplusplayer_video_latency_status_cb() will be invoked only
+ *            when mid / high latency threshold is set.
+ */
+int esplusplayer_set_video_latency_status_cb(
+    esplusplayer_handle handle,
+    esplusplayer_video_latency_status_cb video_latency_status_cb,
+    void* userdata);
+
+/**
+ * @brief     Set a callback function to be invoked when audio latency status
+ * is changed.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] audio_latency_status_cb : the audio latency status callback
+ * function to register.
+ * @param     [in] userdata : userdata of
+ *            esplusplayer_set_audio_latency_status_cb()
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            refer to the sample code of esplusplayer_set_error_cb();
+ * @endcode
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_NONE
+ *            or #ESPLUSPLAYER_STATE_IDLE.
+ * @post      esplusplayer_audio_latency_status_cb() will be invoked.
+ * @exception None
+ * @version   2.7
+ * @remark    esplusplayer_audio_latency_status_cb() will be invoked only
+ *            when mid / high latency threshold is set.
+ */
+int esplusplayer_set_audio_latency_status_cb(
+    esplusplayer_handle handle,
+    esplusplayer_audio_latency_status_cb audio_latency_status_cb,
+    void* userdata);
+
+/**
  * @brief     Set buffer size with different option
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] option : the option of buffer size.
  * @param     [in] size : size of selected buffer option.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_buffer_size(esplayer,ESPLUSPLAYER_BUFFER_AUDIO_MAX_BYTE_SIZE,10240)
@@ -1479,10 +2132,16 @@ int esplusplayer_set_buffer_time_status_cb(
  *            esplusplayer_close(esplayer);
  * @endcode
  * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ *            When the stream is deactivated, it can be set in
+ *            #ESPLUSPLAYER_STATE_READY, #ESPLUSPLAYER_STATE_PAUSED and
+ *            #ESPLUSPLAYER_STATE_PLAYING. The changed buffer size will be
+ *            applied when esplusplayer_activate() is called.
  * @post      None
  * @exception None
  * @remark    esplusplayer_buffer_option
- * @see       esplusplayer_open()
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_deactivate() \n
+ *            esplusplayer_activate()
  */
 int esplusplayer_set_buffer_size(esplusplayer_handle handle,
                                  esplusplayer_buffer_option option,
@@ -1494,11 +2153,13 @@ int esplusplayer_set_buffer_size(esplusplayer_handle handle,
  * @param     [in] resource_conflicted_cb : the resource conflicted callback
  *            function to register.
  * @param     [in] userdata : userdata of resource_conflicted_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1521,11 +2182,13 @@ int esplusplayer_set_resource_conflicted_cb(
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] eos_cb : the eos callback function to register.
  * @param     [in] userdata : userdata of esplusplayer_eos_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1547,11 +2210,13 @@ int esplusplayer_set_eos_cb(esplusplayer_handle handle,
  * @param     [in] ready_to_prepare_cb : the ready to prepare callback function
  *            to register.
  * @param     [in] userdata : userdata of ready_to_prepare_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_submit_packet();
  * @endcode
@@ -1571,14 +2236,16 @@ int esplusplayer_set_ready_to_prepare_cb(
  * @brief     Set a callback function to be invoked when player is prepared to
  *            be started.
  * @param     [in] handle : esplusplayer handle.
- * @param     [in] prepare_async_done_cb : the prepare async done callback
+ * @param     [in] prepare_async_done_cb : the repare async done callback
  * function to register.
  * @param     [in] userdata : userdata of prepare_async_done_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of plusplayer_prepare_async();
  * @endcode
@@ -1603,11 +2270,13 @@ int esplusplayer_set_prepare_async_done_cb(
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] seek_done_cb : the seek done callback function to register.
  * @param     [in] userdata : userdata of esplusplayer_seek_done_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1630,11 +2299,13 @@ int esplusplayer_set_seek_done_cb(esplusplayer_handle handle,
  * @param     [in] ready_to_seek_cb : the ready to seek callback function to
  *            register.
  * @param     [in] userdata : userdata of esplusplayer_ready_to_seek_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1643,7 +2314,8 @@ int esplusplayer_set_seek_done_cb(esplusplayer_handle handle,
  * @post      None
  * @exception None
  * @remark    esplusplayer_seek()
- *            if ready_to_seek_cb is set to null, esplusplayer_ready_to_seek_cb()
+ *            if ready_to_seek_cb is set to null,
+ * esplusplayer_ready_to_seek_cb()
  *            will not be invoked anymore.
  */
 int esplusplayer_set_ready_to_seek_cb(
@@ -1658,11 +2330,13 @@ int esplusplayer_set_ready_to_seek_cb(
  * decoded callback function to register.
  * @param     [in] userdata : userdata of
  * esplusplayer_set_media_packet_video_decoded_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1693,18 +2367,20 @@ int esplusplayer_set_media_packet_video_decoded_cb(
  * register.
  * @param     [in] userdata : userdata of esplusplayer_closed_caption_cb
  *            callback function.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
  * @pre       The player state must be set to #ESPLUSPLAYER_STATE_NONE
  *            or #ESPLUSPLAYER_STATE_IDLE.
  * @post      When there is closed caption data, call
- *            esplusplayer_closed_caption_cb to notify that there is closed
+ *            esplusplayer_closed_caption_cb to nofity that there is closed
  *            caption needed to be displayed.
  * @exception None
  * @remark    esplusplayer_closed_caption_cb \n
@@ -1712,7 +2388,8 @@ int esplusplayer_set_media_packet_video_decoded_cb(
  *            [in] size : length of closed caption data \n
  *            [in] userdata : userdata of esplusplayer_closed_caption_cb
  *            callback function.
- *            if closed_caption_cb is set to null, esplusplayer_closed_caption_cb()
+ *            if closed_caption_cb is set to null,
+ * esplusplayer_closed_caption_cb()
  *            will not be invoked anymore.
  */
 int esplusplayer_set_closed_caption_cb(
@@ -1720,16 +2397,18 @@ int esplusplayer_set_closed_caption_cb(
     esplusplayer_closed_caption_cb closed_caption_cb, void* userdata);
 
 /**
- * @brief     Set a callback function to be invoked when the flush operation is
- *            done.
+ * @brief     Set a callback function to be invoked when player is flush
+ *            successed.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] flush_done_cb : the flush done callback function to register.
  * @param     [in] userdata : userdata of esplusplayer_flush_done_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1749,11 +2428,13 @@ int esplusplayer_set_flush_done_cb(esplusplayer_handle handle,
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] event_cb : the callback function to register.
  * @param     [in] userdata : userdata of esplusplayer_event_cb()
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            refer to the sample code of esplusplayer_set_error_cb();
  * @endcode
@@ -1786,38 +2467,102 @@ int esplusplayer_decoded_buffer_destroy(
  *            set to duplicate.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] mode : one of the low latency mode to set.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
- *            esplusplayer_set_low_latency_mode(esplayer, ESPLUSPLAYER_LOW_LATENCY_MODE_NONE);
+ *            esplusplayer_set_low_latency_mode(esplayer,ESPLUSPLAYER_LOW_LATENCY_MODE_NONE);
  *            // ... your codes ...
  *            esplusplayer_close(esplayer);
  * @endcode
  * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
  * @post      None
  * @exception None
- * @remark    Public supports #ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL only.
- *            No operation is performed and #ESPLUSPLAYER_ERROR_TYPE_NONE will be returned,
- *            if @a mode is not #ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL to make compatible with TV API.
+ * @remark    esplusplayer_set_low_latency_mode().
+ *            if set ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC:
+ *            1, esplusplayer_buffer_status_cb/
+ *            esplusplayer_buffer_byte_status_cb/
+ *            esplusplayer_buffer_time_status_cb/
+ *            esplusplayer_ready_to_prepare_cb/
+ *            esplusplayer_ready_to_seek_cb/esplusplayer_seek_done_cb
+ *            callbacks are not invoked
+ *            2, If es packets are sent after esplusplayer_start() is called,
+ *            it will be played immediately.
  * @see       esplusplayer_open()
  */
 int esplusplayer_set_low_latency_mode(esplusplayer_handle handle,
                                       esplusplayer_low_latency_mode mode);
 
 /**
+ * @brief     Provided api for enabling video frame peek mode
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_video_frame_peek_mode(esplayer);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception None
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_render_video_frame().
+ */
+int esplusplayer_set_video_frame_peek_mode(esplusplayer_handle handle);
+
+/**
+ * @brief     Provided api for rendering a video frame which is holded by video
+ *            frame peek mode.
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            esplusplayer_render_video_frame(esplayer);
+ *            // ... your codes ...
+ *            esplusplayer_stop(esplayer);
+ * @endcode
+ * @pre       In order to use this api,
+ *            The player state must be one of #ESPLUSPLAYER_STATE_READY or
+ *            #ESPLUSPLAYER_STATE_PAUSED after esplusplayer_seek_done_cb or
+ *            esplusplayer_prepare_async_done_cb is called \n
+ * @post      None
+ * @exception None
+ * @see       esplusplayer_set_video_frame_peek_mode() \n
+ *            esplusplayer_prepare_async()
+ */
+int esplusplayer_render_video_frame(esplusplayer_handle handle);
+
+/**
  * @brief     Provided api for setting unlimited max buffer mode, the player
  *            does not limit es packet transmission although in buffer overrun
  * status
  * @param     [in] handle : esplusplayer handle.
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_unlimited_max_buffer_mode(esplayer);
@@ -1830,27 +2575,54 @@ int esplusplayer_set_low_latency_mode(esplusplayer_handle handle,
  * @remark    esplusplayer_set_unlimited_max_buffer_mode().
  *            esplusplayer_buffer_status_cb() will be invoked in
  *            overrun/underrun buffer status. but
- *            esplusplayer_submit_packet() /
- *            esplusplayer_submit_encrypted_packet()
+ * esplusplayer_submit_packet()/esplusplayer_submit_trust_zone_packet()
+ *            /esplusplayer_submit_encrypted_packet()
  *            does not return ESPLUSPLAYER_SUBMIT_STATUS_FULL
  * @see       esplusplayer_open() \n
  *            esplusplayer_submit_packet() \n
+ *            esplusplayer_submit_trust_zone_packet() \n
  *            esplusplayer_submit_encrypted_packet()
  */
 int esplusplayer_set_unlimited_max_buffer_mode(esplusplayer_handle handle);
-
+/**
+ * @brief     Provided api to deliver fmm signal and getting fmm auto status.
+ *            The player just delivers fmm signal to system. It doesn't
+ * gaurantee
+ *            activating fmm mode. System refers to fmm signal when it decides
+ * to activate
+ *            fmm mode or not.
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE fmm auto mode on
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION fmm auto mode off
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE Internal operation failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_fmm_mode(esplayer);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_IDLE,
+ *            #ESPLUSPLAYER_STATE_READY, #ESPLUSPLAYER_STATE_PLAYING
+ *            or #ESPLUSPLAYER_STATE_PAUSED
+ * @post      None
+ * @exception None
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_set_fmm_mode(esplusplayer_handle handle);
 /**
  * @brief     Provided api for setting audio codec type for playback.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : codec type(hardware/software).
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ failed
  * @code
  *            esplusplayer_open(esplayer);
- *            esplusplayer_set_audio_codec_type(esplayer,ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW);
+ * esplusplayer_set_audio_codec_type(esplayer,ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW);
  *            // ... your codes ...
  *            esplusplayer_close(esplayer);
  * @endcode
@@ -1872,14 +2644,16 @@ int esplusplayer_set_audio_codec_type(esplusplayer_handle handle,
  * @brief     Provided api for setting video codec type for playback.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : codec type(hardware/software).
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ failed
  * @code
  *            esplusplayer_open(esplayer);
- *            esplusplayer_set_video_codec_type(esplayer,ESPLUSPLAYER_VIDEO_CODEC_TYPE_SW);
+ * esplusplayer_set_video_codec_type(esplayer,ESPLUSPLAYER_VIDEO_CODEC_TYPE_SW);
  *            // ... your codes ...
  *            esplusplayer_close(esplayer);
  * @endcode
@@ -1898,16 +2672,174 @@ int esplusplayer_set_audio_codec_type(esplusplayer_handle handle,
 int esplusplayer_set_video_codec_type(esplusplayer_handle handle,
                                       esplusplayer_video_codec_type type);
 /**
+ * @brief     Provided api for setting alternative video resource(sub decoder
+ *            and sub scaler)
+ * @param     [in] handle : esplusplayer handle ptr.
+ * @param     [in] rsc_type : set alternative video resource
+ *            (@c 0 [defualt] = set all video resources(decoder/scaler) to main
+ *                              resources,
+ *             @c 1 = set all video resources(decoder/scaler) to sub resources,
+ *             @c 2 = set only decoder to sub resource,
+ *             @c 3 = set only scaler to sub resource)
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_alternative_video_resource(esplayer,1);
+ *             // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #State except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ * @post      None
+ * @exception None
+ * @remark    if app has set not default resource allocate policy via
+ *            esplusplayer_set_resource_allocate_policy(), this api will return
+ * false.
+ * @version   3.0
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_set_alternative_video_resource(esplusplayer_handle handle,
+                                                unsigned int rsc_type);
+/**
+ * @brief     Provided api for setting alternative audio resource(sub decoder
+ *            and simple mix audio out)
+ * @param     [in] handle : esplusplayer handle ptr.
+ * @param     [in] rsc_type : set alternative audio resource type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_audio_codec_type(esplayer,
+ * ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW)
+ *            esplusplayer_set_alternative_audio_resource(esplayer,
+ * ESPLUSPLAYER_AUDIO_RESOURCE_SIMPLE_MIX_OUT);
+ *             // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ *
+ *            prepare esplayer done
+ *             // ... your codes ...
+ *            esplusplayer_deactivate(esplayer, ESPLUSPLAYER_STREAM_TYPE_AUDIO)
+ *            esplusplayer_set_audio_codec_type(esplayer,
+ * ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW)
+ *            esplusplayer_set_alternative_audio_resource(esplayer,
+ * ESPLUSPLAYER_AUDIO_RESOURCE_SIMPLE_MIX_OUT);
+ *            esplusplayer_activate(esplayer, ESPLUSPLAYER_STREAM_TYPE_AUDIO)
+ *             // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #State except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ * @post      None
+ * @exception None
+ * @remark    Simple out is no sound effect. Simple mix out sound is mixed with
+ * main sound and output
+ *            through only main speaker. Simple mix out output format is
+ * fixed(eg. 48kh, 2ch).
+ *            If you use simple mix out resource, audio decoder should be S/W
+ * type.
+ * @version   3.8
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_set_audio_codec_type()
+ */
+int esplusplayer_set_alternative_audio_resource(
+    esplusplayer_handle handle, esplusplayer_audio_resource_type rsc_type);
+/**
+ * @brief     Provided api for switching audio stream between the different
+ *            audio codec types on the fly
+ * @param     [in] handle : esplusplayer handle ptr.
+ * @param     [in] stream : audio stream pointer
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            esplusplayer_audio_stream_info audio_stream;
+ *            audio_stream.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_AC3;
+ *            audio_stream.sample_rate = 48000;
+ *            audio_stream.channels = 2;
+ *            esplusplayer_switch_audio_stream_onthefly(esplayer,
+ *                &audio_stream);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_READY,
+ *            #ESPLUSPLAYER_STATE_PAUSED or #ESPLUSPLAYER_STATE_PLAYING
+ * @post      None
+ * @exception   None
+ * @remark    Audio codec can be switched between only
+ *            #ESPLUSPLAYER_AUDIO_MIME_TYPE_AAC,
+ *            #ESPLUSPLAYER_AUDIO_MIME_TYPE_EAC3
+ *            and #ESPLUSPLAYER_AUDIO_MIME_TYPE_AC3.
+ *            if other codec is set, this api will return false.
+ * @version   3.0
+ * @see       esplusplayer_prepare_async()
+ */
+int esplusplayer_switch_audio_stream_onthefly(
+    esplusplayer_handle handle, esplusplayer_audio_stream_info* stream);
+/**
+ * @brief     Provided api for setting aifilter
+ * @param     [in] handle : esplusplayer handle ptr.
+ * @param     [in] aifilter :  aifilter plugin.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            GstElement* aifilter_ =
+ *                gst_element_factory_make("aifilter_autozoom","auto_zoom");
+ *            g_object_set(G_OBJECT(aifilter_), "az_cb_out_fps", 30, NULL);
+ *            g_object_set(G_OBJECT(aifilter_), "az_inference_fps", 2, NULL);
+ *            g_object_set(G_OBJECT(aifilter_), "az_disp_width", 1920, NULL);
+ *            g_object_set(G_OBJECT(aifilter_), "az_disp_height", 1080, NULL);
+ *            g_object_set(G_OBJECT(aifilter_), "az_detection_type", 2, NULL);
+ *            g_object_set(G_OBJECT(aifilter_), "az_scaler_type", 1, NULL);
+ *            g_object_set(G_OBJECT(aifilter_), "az_target_num", 2, NULL);
+ *            esplusplayer_set_aifilter(esplayer,aifilter_);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception None
+ * @version   3.0
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_set_aifilter(esplusplayer_handle handle, void* aifilter);
+
+/**
  * @brief     Provided api for setting render time offset
  * @param     [in] handle : esplusplayer handle ptr.
  * @param     [in] type : stream type
- * @param     [in] offset : offset (in milliseconds).
+ * @param     [in] offset : offset (default in milliseconds, can be set by
+ * @esplusplayer_set_timeunit_type).
  *                          G_MININT64 <= offset * 1000000 <= G_MAXINT64
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @code
  *            esplusplayer_open(esplayer);
  *            esplusplayer_set_low_latency_mode(esplayer,ESPLUSPLAYER_LOW_LATENCY_MODE_NONE);
@@ -1929,8 +2861,8 @@ int esplusplayer_set_video_codec_type(esplusplayer_handle handle,
  * @remark    esplusplayer_set_low_latency_mode().
  * @post      None
  * @exception None
+ * @version   3.0
  * @see       esplusplayer_open()
- *            esplusplayer_get_render_time_offset()
  */
 int esplusplayer_set_render_time_offset(esplusplayer_handle handle,
                                         esplusplayer_stream_type type,
@@ -1939,39 +2871,684 @@ int esplusplayer_set_render_time_offset(esplusplayer_handle handle,
  * @brief     Provided api for getting render time offset
  * @param     [in] handle : esplusplayer handle ptr.
  * @param     [in] type : stream type
- * @param     [in] offset : offset ptr (in milliseconds).
- * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of esplusplayer_error_type
+ * @param     [in] offset : offset ptr (default in milliseconds, can be set by
+ * @esplusplayer_set_timeunit_type).
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
  *            values will be returned.
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
  * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
- * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation failed
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
  * @pre       The player state must be set to #ESPLUSPLAYER_STATE_READY,
  *            #ESPLUSPLAYER_STATE_PAUSED or #ESPLUSPLAYER_STATE_PLAYING.
  *            It have to be set to low latency mode.
  * @remark    esplusplayer_set_low_latency_mode().
  * @post      None
  * @exception None
- * see        esplusplayer_set_render_time_offset()
+ * @version   3.0
+ * see        esplusplayer_set_render_time_offset
  */
 int esplusplayer_get_render_time_offset(esplusplayer_handle handle,
                                         esplusplayer_stream_type type,
                                         int64_t* offset);
 /**
- * @brief     Requests decoded video frame packet to acquire it. it works only
- *            with #ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_MANUAL_COPY
- *            mode
+ * @brief     Provided api for setting catch up speed level in low latency mode
  * @param     [in] handle : esplusplayer handle.
- * @param     [out] packet : the decoded buffer.
- * @param     [out] status : (nullable) the result of video frame requested
- * @pre       The player state must be one of #ESPLUSPLAYER_STATE_READY or
- *            #ESPLUSPLAYER_STATE_PAUSED or #ESPLUSPLAYER_STATE_PLAYING.
+ * @param     [in] level : speed level to catch up
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO);
+ *            esplusplayer_set_catch_up_speed(esplayer,ESPLUSPLAYER_CATCH_UP_SPEED_MID);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_IDLE,
+ *            #ESPLUSPLAYER_STATE_READY, #ESPLUSPLAYER_STATE_PLAYING
+ *            or #ESPLUSPLAYER_STATE_PAUSED
+ *            esplusplayer_set_low_latency_mode() should be called as below
+ *            before this api is called.
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_AUDIO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_VIDEO_QUALITY)
  * @post      None
- * @return    #ESPLUSPLAYER_ERROR_TYPE_NONE on success, otherwise one of
- *            esplusplayer_error_type values will be returned.
  * @exception None
- * @version   4.0
- * @see       esplusplayer_set_video_frame_buffer_type()
- * @see       esplusplayer_decoded_buffer_destroy()
+ * @version   2.7
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_set_catch_up_speed(esplusplayer_handle handle,
+                                    esplusplayer_catch_up_speed level);
+
+/**
+ * @brief     Provided api for getting current video latency status
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] status : current latency status
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            esplusplayer_latency_status current_status =
+ *                ESPLUSPLAYER_LATENCY_LOW;
+ *            esplusplayer_get_video_latency_status(esplayer, &current_status);
+ *            // ... your codes ...
+ *            esplusplayer_stop(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_READY,
+ *            #ESPLUSPLAYER_STATE_PLAYING or #ESPLUSPLAYER_STATE_PAUSED
+ * @post      None
+ * @exception None
+ * @version   2.7
+ * @see       esplusplayer_prepare_async()
+ */
+int esplusplayer_get_video_latency_status(esplusplayer_handle handle,
+                                          esplusplayer_latency_status* status);
+
+/**
+ * @brief     Provided api for getting current audio latency status
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] status : current latency status
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            esplusplayer_latency_status current_status =
+ *                ESPLUSPLAYER_LATENCY_LOW;
+ *            esplusplayer_get_audio_latency_status(esplayer, &current_status);
+ *            // ... your codes ...
+ *            esplusplayer_stop(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_READY,
+ *            #ESPLUSPLAYER_STATE_PLAYING or #ESPLUSPLAYER_STATE_PAUSED
+ * @post      None
+ * @exception None
+ * @version   2.7
+ * @see       esplusplayer_prepare_async()
+ */
+int esplusplayer_get_audio_latency_status(esplusplayer_handle handle,
+                                          esplusplayer_latency_status* status);
+
+/**
+ * @brief     Provided api for setting video mid latency threshold for low
+ * latency
+ * playback
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] threshold: the threshold(number) of the video frames for mid
+ * latency.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO);
+ *            esplusplayer_set_video_mid_latency_threshold(esplayer,2);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_IDLE,
+ *            #ESPLUSPLAYER_STATE_READY, #ESPLUSPLAYER_STATE_PLAYING
+ *            or #ESPLUSPLAYER_STATE_PAUSED
+ *            esplusplayer_set_low_latency_mode() should be called as below
+ *            before this api is called.
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_AUDIO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                  ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE)
+ * @post      None
+ * @exception None
+ * @version   2.7
+ * @see       esplusplayer_open()
+ */
+/// TODO:: set the min/max value of the threshold
+int esplusplayer_set_video_mid_latency_threshold(esplusplayer_handle handle,
+                                                 const unsigned int threshold);
+
+/**
+ * @brief     Provided api for setting audio mid latency threshold for low
+ * latency
+ * playback
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] threshold: the threshold(number) of the audio frames for mid
+ * latency.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,ESPLUSPLAYER_LOW_LATENCY_MODE_AUDIO);
+ *            esplusplayer_set_audio_mid_latency_threshold(esplayer,2);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_IDLE,
+ *            #ESPLUSPLAYER_STATE_READY, #ESPLUSPLAYER_STATE_PLAYING
+ *            or #ESPLUSPLAYER_STATE_PAUSED
+ *            esplusplayer_set_low_latency_mode() should be called as below
+ *            before this api is called.
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_AUDIO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                  ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE)
+ * @post      None
+ * @exception None
+ * @version   2.7
+ * @see       esplusplayer_open()
+ */
+/// TODO:: set the min/max value of the threshold
+int esplusplayer_set_audio_mid_latency_threshold(esplusplayer_handle handle,
+                                                 const unsigned int threshold);
+
+/**
+ * @brief     Provided api for setting video high latency threshold for low
+ * latency
+ * playback
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] threshold: the threshold(number) of the video frames for high
+ * latency.
+ * @param     [in] video_high_latency_cb : high latency callback function to
+ * register
+ * @param     [in] userdata : userdata of esplusplayer_high_latency_cb()
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            static void OnVideoHighLatency(void* userdata) {
+ *                printf ("OnVideoHighLatency\n");
+ *            }
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO);
+ *            esplusplayer_set_video_high_latency_threshold(esplayer, 2,
+ *                OnVideoHighLatency, nullptr);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_IDLE,
+ *            #ESPLUSPLAYER_STATE_READY, #ESPLUSPLAYER_STATE_PLAYING
+ *            or #ESPLUSPLAYER_STATE_PAUSED
+ *            esplusplayer_set_low_latency_mode() should be called as below
+ *            before this api is called.
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_AUDIO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                  ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE)
+ * @post      None
+ * @exception None
+ * @version   2.7
+ * @see       esplusplayer_open()
+ */
+/// TODO:: set the min/max value of the threshold
+int esplusplayer_set_video_high_latency_threshold(
+    esplusplayer_handle handle, const unsigned int threshold,
+    esplusplayer_video_high_latency_cb video_high_latency_cb, void* userdata);
+
+/**
+ * @brief     Provided api for setting audio high latency threshold for low
+ * latency
+ * playback
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] threshold: the threshold(number) of the audio frames for high
+ * latency.
+ * @param     [in] audio_high_latency_cb : high latency callback function to
+ * register
+ * @param     [in] userdata : userdata of esplusplayer_high_latency_cb()
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            static void OnAudioHighLatency(void* userdata) {
+ *                printf ("OnAudioHighLatency\n");
+ *            }
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,ESPLUSPLAYER_LOW_LATENCY_MODE_AUDIO);
+ *            esplusplayer_set_audio_high_latency_threshold(esplayer, 2,
+ *                OnAudioHighLatency, nullptr);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_IDLE,
+ *            #ESPLUSPLAYER_STATE_READY, #ESPLUSPLAYER_STATE_PLAYING
+ *            or #ESPLUSPLAYER_STATE_PAUSED
+ *            esplusplayer_set_low_latency_mode() should be called as below
+ *            before this api is called.
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_AUDIO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC),
+ *            esplusplayer_set_low_latency_mode(handle,
+ *                ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE)
+ * @post      None
+ * @exception None
+ * @version   2.7
+ * @see       esplusplayer_open()
+ */
+/// TODO:: set the min/max value of the threshold
+int esplusplayer_set_audio_high_latency_threshold(
+    esplusplayer_handle handle, const unsigned int threshold,
+    esplusplayer_audio_high_latency_cb audio_high_latency_cb, void* userdata);
+
+/**
+ * @brief     Provided api for getting the maximum number of frames.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] frame_count : maximum frame count.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,
+ * ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE);
+ *            esplusplayer_audio_stream_info audio_stream;
+ *            audio_stream.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_PCM_S16LE;
+ *            audio_stream.sample_rate = 48000;
+ *            audio_stream.channels = 6;
+ *            esplusplayer_set_audio_stream_info(esplayer, &audio_stream);
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            uint64_t frame_count = 0;
+ *            esplusplayer_get_low_latency_pcm_buffer_size(esplayer,
+ * &frame_count)
+ *            // ... your codes ...
+ *            esplusplayer_stop(esplayer);
+ * @endcode
+ * @pre       The player state must be at least #ESPLUSPLAYER_STATE_READY.
+ *            It has to be set to game mode, and multi channel pcm.
+ * @post      None
+ * @exception None
+ * @version   6.0
+ * @see       esplusplayer_get_low_latency_pcm_current_buffer_level() \n
+ *            esplusplayer_get_low_latency_pcm_underrun_count()
+ */
+int esplusplayer_get_low_latency_pcm_buffer_size(esplusplayer_handle handle,
+                                                 uint64_t* frame_count);
+
+/**
+ * @brief     Provided api for getting the number of currently queued frames.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] frame_count : queued frame count.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,
+ * ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE);
+ *            esplusplayer_audio_stream_info audio_stream;
+ *            audio_stream.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_PCM_S16LE;
+ *            audio_stream.sample_rate = 48000;
+ *            audio_stream.channels = 6;
+ *            esplusplayer_set_audio_stream_info(esplayer, &audio_stream);
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            uint64_t frame_count = 0;
+ *            esplusplayer_get_low_latency_pcm_current_buffer_level(esplayer,
+ * &frame_count)
+ *            // ... your codes ...
+ *            esplusplayer_stop(esplayer);
+ * @endcode
+ * @pre       The player state must be at least #ESPLUSPLAYER_STATE_READY.
+ *            It has to be set to game mode, and multi channel pcm.
+ * @post      None
+ * @exception None
+ * @version   6.0
+ * @see       esplusplayer_get_low_latency_pcm_buffer_size() \n
+ *            esplusplayer_get_low_latency_pcm_underrun_count()
+ */
+int esplusplayer_get_low_latency_pcm_current_buffer_level(
+    esplusplayer_handle handle, uint64_t* frame_count);
+
+/**
+ * @brief     Provided api for getting the underrun counts in audio out.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] underrun_count : underrun counts in audio out.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_low_latency_mode(esplayer,
+ * ESPLUSPLAYER_LOW_LATENCY_MODE_ENABLE_GAME_MODE);
+ *            esplusplayer_audio_stream_info audio_stream;
+ *            audio_stream.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_PCM_S16LE;
+ *            audio_stream.sample_rate = 48000;
+ *            audio_stream.channels = 6;
+ *            esplusplayer_set_audio_stream_info(esplayer, &audio_stream);
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            uint64_t underrun_count = 0;
+ *            esplusplayer_get_low_latency_pcm_underrun_count(esplayer,
+ * &underrun_count)
+ *            // ... your codes ...
+ *            esplusplayer_stop(esplayer);
+ * @endcode
+ * @pre       The player state must be at least #ESPLUSPLAYER_STATE_READY.
+ *            It has to be set to game mode, and multi channel pcm.
+ * @post      None
+ * @exception None
+ * @version   6.0
+ * @see       esplusplayer_get_low_latency_pcm_buffer_size() \n
+ *            esplusplayer_get_low_latency_pcm_current_buffer_level()
+ */
+int esplusplayer_get_low_latency_pcm_underrun_count(esplusplayer_handle handle,
+                                                    uint64_t* underrun_count);
+
+/**
+ * @brief     Initialize easing info to esplayer.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] init_volume : initial easing volume (0 ~ 100).
+ * @param     [in] elapsed_time : initial elapsed time (millisecond).
+ * @param     [in] easing_info : target volume, duration, type.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            uint32_t volume = 50, elapsed_time = 10000;
+ *            esplusplayer_target_audio_easing_info easing_info;
+ *            easing_info.volume = 30;
+ *            easing_info.duration = 100;
+ *            easing_info.type = ESPLUSPLAYER_AUDIO_EASING_INCUBIC;
+ *            esplusplayer_init_audio_easing_info(esplayer,volume,elapsed_time,&easing_info);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #esplusplayer_state except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ * @post      None
+ * @exception None
+ * @version   3.0
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_init_audio_easing_info(
+    esplusplayer_handle handle, uint32_t init_volume, uint32_t elapsed_time,
+    const esplusplayer_target_audio_easing_info* easing_info);
+
+/**
+ * @brief     Update easing info to esplayer to update target info.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] easing_info : target volume, duration, type.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            // ... your codes ...
+ *            esplusplayer_target_audio_easing_info easing_info;
+ *            easing_info.volume = 30;
+ *            easing_info.duration = 100;
+ *            easing_info.type = ESPLUSPLAYER_AUDIO_EASING_INCUBIC;
+ *            esplusplayer_update_audio_easing_info(esplayer,&easing_info);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #esplusplayer_state except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ *            This api should be called after
+ *            esplusplayer_init_audio_easing_info() is called
+ * @post      None
+ * @exception None
+ * @version   3.0
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_update_audio_easing_info(
+    esplusplayer_handle handle,
+    const esplusplayer_target_audio_easing_info* easing_info);
+
+/**
+ * @brief     Get easing info currently in easing operation from esplayer
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] current_volume : current volume (0 ~ 100).
+ * @param     [out] elapsed_time : elapsed time (millisecond).
+ * @param     [out] easing_info : target volume, duration, type.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            // ... your codes ...
+ *            uint32_t cur_volume = 50, elapsed_time = 0;
+ *            esplusplayer_target_audio_easing_info easing_info;
+ *
+ esplusplayer_get_audio_easing_info(esplayer,&cur_volume,&elapsed_time,&easing_info);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #esplusplayer_state except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ *            This api should be called after
+ *            esplusplayer_init_audio_easing_info() is called
+ * @post      None
+ * @exception None
+ * @version   3.0
+ * @see       esplusplayer_open()
+
+ */
+int esplusplayer_get_audio_easing_info(
+    esplusplayer_handle handle, uint32_t* current_volume,
+    uint32_t* elapsed_time, esplusplayer_target_audio_easing_info* easing_info);
+
+/**
+ * @brief     Start audio easing using a registered audio easing info
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            prepare esplayer done
+ *            uint32_t volume = 50, elapsed_time = 10000;
+ *            esplusplayer_target_audio_easing_info easing_info;
+ *            easing_info.volume = 30;
+ *            easing_info.duration = 100;
+ *            easing_info.type = ESPLUSPLAYER_AUDIO_EASING_INCUBIC;
+ *            esplusplayer_init_audio_easing_info(esplayer,volume,elapsed_time,&easing_info);
+ *            esplusplayer_start_audio_easing(esplayer);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state should be at least #ESPLUSPLAYER_STATE_READY.
+ *            This api should be called after
+ *            esplusplayer_init_audio_easing_info() is called
+ * @post      None
+ * @exception None
+ * @version   3.0
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_init_audio_easing_info() \n
+ *            esplusplayer_update_audio_easing_info() \n
+ *            esplusplayer_stop_audio_easing() \n
+ *            esplusplayer_prepare_async()
+ */
+int esplusplayer_start_audio_easing(esplusplayer_handle handle);
+
+/**
+ * @brief     Stop audio easing
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            // ... your codes ...
+ *            esplusplayer_stop_audio_easing(esplayer);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #esplusplayer_state except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ *            This api should be called after
+ *            esplusplayer_init_audio_easing_info() is called
+ * @post      None
+ * @exception   None
+ * @version   3.0
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_start_audio_easing()
+ */
+int esplusplayer_stop_audio_easing(esplusplayer_handle handle);
+
+/**
+ * @brief     Get virtual resource id
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] type : The resource type of virtual id.
+ * @param     [out] virtual_id : Stored virtual resource id value.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ failed
+ * @code
+ *            prepare esplayer done
+ *            // ... your codes ...
+ *            int virtual_id;
+ *
+ esplusplayer_get_virtual_rsc_id(esplayer,ESPLUSPLAYER_RSC_TYPE_VIDEO_RENDERER,&virtual_id);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ *            esplusplayer_destroy(esplayer);
+ * @endcode
+ * @pre       The player state should be #State::kReady, #State::kPlaying or
+ *            #State::kPaused
+ * @post      None
+ * @return    @c True on success, otherwise @c False ("virtual_id" will be -1)
+ * @exception None
+ * @version   3.0
+ * @remark    This function returns virtual resource id which player is
+ *            allocated from resource manager. For example, virtual scaler id is
+ *            required for an application to use capture API directly.
+ * @see       esplusplayer_prepare_async()
+
+ */
+int esplusplayer_get_virtual_rsc_id(esplusplayer_handle handle,
+                                    const esplusplayer_rsc_type type,
+                                    int* virtual_id);
+
+/**
+ * @brief     Set advanced picture quality type.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] type : The picture quality type.
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @exception  None
+ * @version   3.1
+ */
+int esplusplayer_set_advanced_picture_quality_type(
+    esplusplayer_handle handle,
+    esplusplayer_advanced_picture_quality_type type);
+
+/**
+ * @brief     Set resource allocate policy.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] policy : The resource allocate policy.
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @exception  None
+ * @version   3.3
+ * @remark    If app has set not default alternaltive resource via
+ *            esplusplayer_set_alternative_video_resource(), alternative
+ *            resource setting will be ignored.
+ */
+int esplusplayer_set_resource_allocate_policy(
+    esplusplayer_handle handle, esplusplayer_rsc_alloc_policy policy);
+
+/**
+ * @brief     Requests decoded video frame packet to acquire it. it works only
+ *            with #ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_MANUAL_COPY
+ *            mode
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] packet : the decoded buffer.
+ * @param     [out] status : (nullable) the result of video frame requested
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_READY or
+ *            #ESPLUSPLAYER_STATE_PAUSED or #ESPLUSPLAYER_STATE_PLAYING.
+ * @post      None
+ * @return    #ESPLUSPLAYER_ERROR_TYPE_NONE on success, otherwise one of
+ *            esplusplayer_error_type values will be returned.
+ * @exception None
+ * @version   4.0
+ * @see       esplusplayer_set_video_frame_buffer_type()
+ * @see       esplusplayer_decoded_buffer_destroy()
  * @see       esplusplayer_decoded_video_frame_buffer_type
  * @code
  * ...
@@ -2016,6 +3593,343 @@ int esplusplayer_get_decoded_video_packet(
     esplusplayer_get_decoded_video_frame_status_type* status);
 
 /**
+ * @brief     Set preloading of the audio pipeline.
+ * @param     [in] handle : esplusplayer handle.
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @remark    If the other player is used by pre-loading mode, this player can
+ *            be prepared before the other player is released.
+ *            If app call esplusplayer_start before the original player is
+ *            released, the sound of original player can be affected.
+ * @exception None
+ * @version   4.0
+ * @code
+ * ...
+ * esplusplayer_handle esplayer1 = esplusplayer_create();
+ * esplusplayer_open(esplayer1);
+ * esplusplayer_set_audio_preloading(esplayer1);
+ * esplusplayer_audio_stream_info audio_stream_1;
+ * if (audio_stream_1's mime type is PCM or G711_MULAW)
+ *   audio_stream_1.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_G711_MULAW;
+ * else
+ *   audio_stream_1.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_AAC;
+ * esplusplayer_set_audio_stream_info(esplayer1, &audio_stream_1);
+ * esplusplayer_prepare_async(esplayer1);
+ * esplusplayer_start(esplayer1);
+ * // ... while playing esplayer1 ...
+ * // the other player can be prepared if original player is preloading mode.
+ * esplusplayer_handle esplayer2 = esplusplayer_create();
+ * esplusplayer_open(esplayer2);
+ * esplusplayer_set_audio_preloading(esplayer2);
+ * esplusplayer_audio_stream_info audio_stream_2;
+ * if (audio_stream_1's mime type is PCM or G711_MULAW) {
+ *   // audio_stream_2 can use the mime type except for PCM or G711_MULAW type.
+ *   audio_stream_2.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_AAC;
+ *   esplusplayer_set_audio_stream_info(esplayer2, &audio_stream_2);
+ * } else {
+ *   if (audio_stream_2's mime type is PCM or G711_MULAW) {
+ *     audio_stream_2.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_G711_MULAW;
+ *     esplusplayer_set_audio_stream_info(esplayer2, &audio_stream_2);
+ *   } else {
+ *     // if all player don't use PCM or G711_MULAW type, one player need to set
+ *     // sw codec type.
+ *     audio_stream_2.mime_type = ESPLUSPLAYER_AUDIO_MIME_TYPE_AAC;
+ *     esplusplayer_set_audio_stream_info(esplayer2, &audio_stream_2);
+ *     esplusplayer_set_audio_codec_type(esplayer2,
+ *                                       ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW);
+ *   }
+ * }
+ * esplusplayer_prepare_async(esplayer2);
+ * // the player can be started after the original player is stopped or the
+ * // original player's audio stream is deactivated.
+ * if (the app want to keep the original player instance)
+ *   esplusplayer_deactivate(esplayer1,ESPLUSPLAYER_STREAM_TYPE_AUDIO);
+ * else
+ *   esplusplayer_stop(esplayer1);
+ * esplusplayer_start(esplayer2);
+ * ...
+ * @endcode
+ */
+int esplusplayer_set_audio_preloading(esplusplayer_handle handle);
+
+/**
+ * @brief     Set a callback function to be invoked when video frames are
+ *            dropped by SoC.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] video_frame_dropped_cb : the callback function to register.
+ * @param     [in] userdata : userdata of
+ * esplusplayer_set_video_frame_dropped_cb()
+ * @pre       The player state must be one of #ESPLUSPLAYER_STATE_READY or
+ *            #ESPLUSPLAYER_STATE_PAUSED or #ESPLUSPLAYER_STATE_PLAYING.
+ * @post      esplusplayer_video_frame_dropped_cb() will be invoked.
+ *            if error_cb is set to null, esplusplayer_error_cb() will not be
+ * @return    #ESPLUSPLAYER_ERROR_TYPE_NONE on success, otherwise one of
+ *            esplusplayer_error_type values will be returned.
+ * @exception None
+ * @version   2.7
+ * @see       esplusplayer_video_frame_dropped_cb()
+ * @code
+ * void video_frame_dropped_cb(const uint64_t count, void* userdata){
+ * // do you job
+ * }
+ * esplusplayer_set_video_frame_dropped_cb(handle,
+ * video_frame_dropped_cb, userdata);
+ * ...
+ * esplusplayer_prepare_async(handle);
+ * ...
+ * @endcode
+ */
+int esplusplayer_set_video_frame_dropped_cb(
+    esplusplayer_handle handle,
+    esplusplayer_video_frame_dropped_cb video_frame_dropped_cb, void* userdata);
+
+/**
+ * @brief     Set video scan type.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] type : The video scan type.
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @exception  None
+ * @version   4.0
+ */
+int esplusplayer_set_video_scan_type(esplusplayer_handle handle,
+                                     esplusplayer_video_scan_type type);
+
+/**
+ * @brief     Get decoding time of the stream
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] type : stream type.
+ * @param     [out] time_in_milliseconds : current decoding time in
+ * milliseconds.
+ * @pre       The player must be one of #ESPLUSPLAYER_STATE_PAUSE or
+ *            #ESPLUSPLAYER_STATE_PLAYING
+ * @post      None
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @exception  None
+ * @version   2.7
+ */
+int esplusplayer_get_decoding_time(esplusplayer_handle handle,
+                                   esplusplayer_stream_type type,
+                                   int32_t* time_in_milliseconds);
+
+/**
+ * @brief     Set the timeunit ms or us. All other espp time related API should
+ * follow this time unit type.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] type : time unit type.
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_IDLE
+ * @post      None
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @exception  None
+ * @version   5.0
+ */
+int esplusplayer_set_timeunit_type(esplusplayer_handle handle,
+                                   esplusplayer_time_unit_type type);
+
+/**
+ * @brief     Set a callback function to be invoked when decoder receive one
+ * input buffer.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] decoder_buffer_time_cb : the decoder input buffer time
+ * callback function to register.
+ * @param     [in] userdata : userdata of
+ * esplusplayer_set_decoder_input_buffer_time_cb()
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            refer to the sample code of esplusplayer_set_error_cb();
+ * @endcode
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_NONE
+ *            or #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception None
+ * @version   5.0
+ */
+int esplusplayer_set_decoder_input_buffer_time_cb(
+    esplusplayer_handle handle,
+    esplusplayer_decoder_buffer_time_cb decoder_buffer_time_cb, void* userdata);
+
+/**
+ * @brief     Set a callback function to be invoked when get one output buffer
+ * from decoder.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] decoder_buffer_time_cb : the decoder output buffer time
+ * callback function to register.
+ * @param     [in] userdata : userdata of
+ * esplusplayer_set_decoder_output_buffer_time_cb()
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            refer to the sample code of esplusplayer_set_error_cb();
+ * @endcode
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_NONE
+ *            or #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception None
+ * @version   5.0
+ */
+int esplusplayer_set_decoder_output_buffer_time_cb(
+    esplusplayer_handle handle,
+    esplusplayer_decoder_buffer_time_cb decoder_buffer_time_cb, void* userdata);
+
+/**
+ * @brief     Set App id to esplayer to control resource confliction.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] app_info : application id, version, type, runtitle.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_app_info appinfo;
+ *            appinfo.id = "youtube";
+ *            appinfo.version = "3.0";
+ *            appinfo.type = "MSE";
+ *            appinfo.runtitle = "YouTube";
+ *            esplusplayer_handle esplayer = esplusplayer_create();
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_app_info_ex(esplayer,&appinfo);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state must be #ESPLUSPLAYER_STATE_IDLE.
+ * @post      None
+ * @exception None
+ * @version   5.0
+ * @see       esplusplayer_open()
+ */
+int esplusplayer_set_app_info_ex(esplusplayer_handle handle,
+                                 const esplusplayer_app_info_ex* app_info);
+
+/**
+ * @brief     Set the rotate angle of the video stream.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] rotation : the rotate angle of the video.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_video_stream_rotation_info(esplayer_,ESPLUSPLAYER_VIDEO_ROTATION_90);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #esplusplayer_state except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ * @post      this API worked only when video sink created.
+ * @exception None
+ * @version   5.2
+ * @see       esplusplayer_open() \n
+ */
+int esplusplayer_set_video_stream_rotation_info(
+    esplusplayer_handle handle,
+    const esplusplayer_video_stream_rotation_type rotation);
+
+/**
+ * @brief     Get the rotate angle of the video stream.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [out] rotation : the rotate angle of the video stream which want
+ * to
+ * get.
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type
+ *            values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_display_rotation_type rotation_get =
+ * ESPLUSPLAYER_VIDEO_ROTATION_NONE;
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_video_stream_rotation_info(esplayer,ESPLUSPLAYER_VIDEO_ROTATION_90);
+ *            // ... your codes ...
+ *            esplusplayer_get_video_stream_rotation_info(esplayer,&rotation_get);
+ *            // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #esplusplayer_state except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ * @post      this API worked only when video sink created.
+ * @exception None
+ * @version   5.2
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_set_video_stream_rotation_info()
+ */
+int esplusplayer_get_video_stream_rotation_info(
+    esplusplayer_handle handle,
+    esplusplayer_video_stream_rotation_type* rotation);
+
+/**
+ * @brief     Provided api for setting buffer level of simple mix out
+ * @param     [in] handle : esplusplayer handle ptr.
+ * @param     [in] level : set buffer level of simple mix out
+ * @return    @c ESPLUSPLAYER_ERROR_TYPE_NONE on success,otherwise @c one of
+ * esplusplayer_error_type values will be returned.
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_NONE Successful
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER Invalid parameter
+ * @retval    #ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION Internal operation
+ * failed
+ * @code
+ *            esplusplayer_open(esplayer);
+ *            esplusplayer_set_audio_codec_type(esplayer,
+ * ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW)
+ *            esplusplayer_set_alternative_audio_resource(esplayer,
+ * ESPLUSPLAYER_AUDIO_RESOURCE_SIMPLE_MIX_OUT);
+ *            esplusplayer_set_simple_mix_out_buffer_level(esplayer,
+ * ESPLUSPLAYER_SIMPLE_MIX_OUT_BUFFER_LOW);
+ *             // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ *
+ *            prepare esplayer done
+ *             // ... your codes ...
+ *            esplusplayer_deactivate(esplayer, ESPLUSPLAYER_STREAM_TYPE_AUDIO)
+ *            esplusplayer_set_audio_codec_type(esplayer,
+ * ESPLUSPLAYER_AUDIO_CODEC_TYPE_SW)
+ *            esplusplayer_set_alternative_audio_resource(esplayer,
+ * ESPLUSPLAYER_AUDIO_RESOURCE_SIMPLE_MIX_OUT);
+ *            esplusplayer_set_simple_mix_out_buffer_level(esplayer,
+ * ESPLUSPLAYER_SIMPLE_MIX_OUT_BUFFER_LOW);
+ *            esplusplayer_activate(esplayer, ESPLUSPLAYER_STREAM_TYPE_AUDIO);
+ *             // ... your codes ...
+ *            esplusplayer_close(esplayer);
+ * @endcode
+ * @pre       The player state can be all of #State except
+ *            #ESPLUSPLAYER_STATE_NONE.
+ * @post      None
+ * @exception None
+ * @remark    This API can set only before esplusplayer_prepare_async() or
+ *            after esplusplayer_deactivate(ESPLUSPLAYER_STREAM_TYPE_AUDIO).
+ * @version   3.8
+ * @see       esplusplayer_open() \n
+ *            esplusplayer_set_audio_codec_type()
+ *            esplusplayer_set_alternative_audio_resource()
+ */
+int esplusplayer_set_simple_mix_out_buffer_level(
+    esplusplayer_handle handle, esplusplayer_simple_mix_out_buffer_level level);
+
+
+#ifdef TIZEN_FEATURE_PUBLIC
+/**
  * @brief     Provided api for enabling video hole.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] value : the value of video hole.
@@ -2041,9 +3955,9 @@ int esplusplayer_get_decoded_video_packet(
  *            esplusplayer_set_media_packet_video_decoded_cb()
  */
 int esplusplayer_enable_video_hole(esplusplayer_handle handle, const bool value);
-
+#endif
 #ifdef __cplusplus
 }
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_CAPI_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_CAPI_H__
index 11b398b..9909853 100644 (file)
@@ -1,32 +1,23 @@
-/**
- * @file           esplusplayer_internal.h
- * @brief          EsPlusPlayer internally used api c version
- * @interfacetype  module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is esplusplayer api header implemented as C style to
- *                 avoid binary compatibility issues.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_INTERNAL_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_INTERNAL_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_INTERNAL_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_INTERNAL_H__
 
+#include "esplusplayer_capi/buffer.h"
 #include "esplusplayer_capi/display.h"
 
 #ifdef __cplusplus
@@ -35,6 +26,7 @@ extern "C" {
 
 #include <stdint.h>
 
+typedef void (*esplusplayer_decoder_underrun_cb)(void* userdata);
 typedef void* esplusplayer_handle;
 typedef void (*esplusplayer_first_video_decoding_done_cb)(void*);
 
@@ -42,27 +34,6 @@ typedef void (*esplusplayer_first_video_decoding_done_cb)(void*);
  * @brief     Set the video display.
  * @param     [in] handle : esplusplayer handle.
  * @param     [in] type : display type.
- * @param     [in] window : the ecore wayland window handle.
- * @param     [in] x : the x coordinate of window.
- * @param     [in] y : the ycoordinate of window.
- * @param     [in] width : the width of window.
- * @param     [in] height : the height of window.
- * @return    @c one of esplusplayer_error_type values will be returned.
- * @pre       The player state can be all of #esplusplayer_state except
- *            #ESPLUSPLAYER_STATE_NONE.
- * @post      None
- * @exception   None
- * @see       esplusplayer_set_display_mode() \n
- *            esplusplayer_set_display_roi() \n
- *            esplusplayer_set_display_visible()
- */
-int esplusplayer_set_ecore_display(esplusplayer_handle handle,
-                                   esplusplayer_display_type type, void* window,
-                                   int x, int y, int width, int height);
-/**
- * @brief     Set the video display.
- * @param     [in] handle : esplusplayer handle.
- * @param     [in] type : display type.
  * @param     [in] surface_id : resource id of window.
  * @param     [in] x : the x coordinate of window.
  * @param     [in] y : the ycoordinate of window.
@@ -87,8 +58,87 @@ int esplusplayer_set_first_video_decoding_done_cb(
     esplusplayer_first_video_decoding_done_cb first_video_decoding_done_cb,
     void* userdata);
 
+/**
+ * @brief     Set a callback function to be invoked when buffer underrun is
+ *            occurred from a video decoder.
+ * @param     [in] handle : esplusplayer handle.
+ * @param     [in] callback : the callback function to register.
+ * @param     [in] userdata : userdata of esplusplayer_decoder_underrun_cb()
+ * @return    @c one of esplusplayer_error_type values will be returned.
+ * @pre       The player state must be set to #ESPLUSPLAYER_STATE_NONE or
+ *            #ESPLUSPLAYER_STATE_IDLE.
+ * @post      esplusplayer_decoder_underrun_cb() will be invoked.
+ * @exception   None
+ * @remark    esplusplayer_decoder_underrun_cb().
+ *            if video_decoder_underrun_cb is set to null,
+ *            esplusplayer_decoder_underrun_cb() will not be invoked anymore.
+ */
+int esplusplayer_set_video_decoder_underrun_cb(
+    esplusplayer_handle handle,
+    esplusplayer_decoder_underrun_cb video_decoder_underrun_cb, void* userdata);
+
+/**
+ * @brief     Get the size of struct esplusplayer_app_info
+ * @param     None
+ * @return    Total size of struct esplusplayer_app_info
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+int get_size_of_esplusplayer_app_info(void);
+
+/**
+ * @brief     Get the size of struct esplusplayer_es_packet
+ * @param     None
+ * @return    Total size of struct esplusplayer_es_packet
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+int get_size_of_esplusplayer_es_packet(void);
+
+/**
+ * @brief     Get the size of struct esplusplayer_es_tz_packet
+ * @param     None
+ * @return    Total size of struct esplusplayer_es_tz_packet
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+int get_size_of_esplusplayer_es_tz_packet(void);
+
+/**
+ * @brief     Get the size of struct esplusplayer_audio_stream_info
+ * @param     None
+ * @return    Total size of struct esplusplayer_audio_stream_info
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+int get_size_of_esplusplayer_audio_stream_info(void);
+
+/**
+ * @brief     Get the size of struct esplusplayer_video_stream_info
+ * @param     None
+ * @return    Total size of struct esplusplayer_video_stream_info
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+int get_size_of_esplusplayer_video_stream_info(void);
+
+/**
+ * @brief     Get the size of struct esplusplayer_drm_info
+ * @param     None
+ * @return    Total size of struct esplusplayer_drm_info
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+int get_size_of_esplusplayer_drm_info(void);
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_INTERNAL_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_ESPLUSPLAYER_INTERNAL_H__
index 8c11b60..5f0a3a1 100644 (file)
@@ -1,37 +1,28 @@
-/**
- * @file
- * @brief          The event for playback.
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style event related enum and structure.
- * @see            N/A
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_EVENT_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_EVENT_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_EVENT_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_EVENT_H__
 
 #ifdef __cplusplus
+#include <cstdint>
 extern "C" {
-#endif
-
+#else
 #include <stdint.h>
+#endif
 
 /**
  * @brief Event message
@@ -51,21 +42,21 @@ typedef struct {
 /**
  * @brief Enumerations for event message types
  */
-typedef enum {
+enum esplusplayer_event_type {
   ESPLUSPLAYER_EVENT_NONE,
   ESPLUSPLAYER_EVENT_RESOLUTION_CHANGED,
   /**
    * @description requested first render video frame to display module.
    * Actual displaying timing on screen could be delay. It depends on H/W
    * rendering system.
-   * This event will happen in case of ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC
+   * Ths event will happen in case of ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC
    * or ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL mode.
    */
   ESPLUSPLAYER_EVENT_REQUESTED_FIRST_RENDER_FRAME,
-} esplusplayer_event_type;
+};
 
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_EVENT_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_EVENT_H__
diff --git a/include/esplusplayer_capi/latency.h b/include/esplusplayer_capi/latency.h
new file mode 100644 (file)
index 0000000..2f0a2db
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_LATENCY_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_LATENCY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * @brief   Enumerations for esplusplayer catch up speed
+ */
+enum esplusplayer_catch_up_speed {
+  ESPLUSPLAYER_CATCH_UP_SPEED_NONE, /**< do not use catch up mode */
+  ESPLUSPLAYER_CATCH_UP_SPEED_SLOW, /**< catch up speed is slow */
+  ESPLUSPLAYER_CATCH_UP_SPEED_MID,  /**< catch up speed is normal */
+  ESPLUSPLAYER_CATCH_UP_SPEED_FAST  /**< catch up speed is fast */
+};
+
+/**
+ * @brief   Enumerations for esplusplayer latency status
+ */
+enum esplusplayer_latency_status {
+  ESPLUSPLAYER_LATENCY_LOW, /**< latency status is low */
+  ESPLUSPLAYER_LATENCY_MID, /**< latency status is middle */
+  ESPLUSPLAYER_LATENCY_HIGH /**< latency status is high */
+};
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_LATENCY_H__
index 42d1187..f2b1aa3 100644 (file)
@@ -1,36 +1,28 @@
-/**
- * @file
- * @brief          The matroska color info
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @see            plusplayer::EsPlusPlayer class
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_MATROSKA_COLOR_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_MATROSKA_COLOR_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_MATROSKA_COLOR_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_MATROSKA_COLOR_H__
 
 #ifdef __cplusplus
+#include <cstdint>
 extern "C" {
-#endif
-
+#else
 #include <stdint.h>
+#endif
 
 /**
  * @brief   Structure of matroska matering metadata
@@ -167,4 +159,4 @@ typedef struct {
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_MATROSKA_COLOR_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_MATROSKA_COLOR_H__
index 2c2d1c5..c7c2c67 100644 (file)
@@ -1,31 +1,21 @@
-/**
- * @file
- * @brief          State enum.
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style state related enum.
- * @see            State enum convertion.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_STATE_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_STATE_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_STATE_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_STATE_H__
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,7 +24,7 @@ extern "C" {
 /**
  * @brief  Enumerations for es player state.
  */
-typedef enum {
+enum esplusplayer_state {
   ESPLUSPLAYER_STATE_NONE,  /**<Player is created, but not opened*/
   ESPLUSPLAYER_STATE_IDLE,  /**<Player is opened, but not prepared or player is
                                stopped*/
@@ -42,10 +32,10 @@ typedef enum {
   ESPLUSPLAYER_STATE_PLAYING, /**<Player is playing media*/
   ESPLUSPLAYER_STATE_PAUSED,    /**<Player is playing media*/
   ESPLUSPLAYER_STATE_MAX
-} esplusplayer_state;
+};
 
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_STATE_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_STATE_H__
index 902632b..b6b499f 100644 (file)
@@ -1,33 +1,21 @@
-/**
- * @file
- * @brief          Stream info related data structures and enums
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style track releted data structures and
- *                 enums.
- * @see            All track releated types shared_ptr, boost::any, enum
- *                 classes, std::string, etc.. are converted to this.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_TRACK_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_TRACK_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_TRACK_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_TRACK_H__
 
 #ifdef __cplusplus
 extern "C" {
@@ -36,16 +24,17 @@ extern "C" {
 /**
  * @brief  Enumerations for the stream type
  */
-typedef enum {
+enum esplusplayer_stream_type {
   ESPLUSPLAYER_STREAM_TYPE_AUDIO,
   ESPLUSPLAYER_STREAM_TYPE_VIDEO,
   ESPLUSPLAYER_STREAM_TYPE_MAX
-} esplusplayer_stream_type;
+};
 
 /**
  * @brief   Enumerations for audio mime type
+ * @version 6.0
  */
-typedef enum {
+enum esplusplayer_audio_mime_type {
   ESPLUSPLAYER_AUDIO_MIME_TYPE_UNKNOWN,
   ESPLUSPLAYER_AUDIO_MIME_TYPE_AAC,
   ESPLUSPLAYER_AUDIO_MIME_TYPE_MP2,
@@ -66,13 +55,18 @@ typedef enum {
   ESPLUSPLAYER_AUDIO_MIME_TYPE_PCM_S32BE,
   ESPLUSPLAYER_AUDIO_MIME_TYPE_PCM_U32LE,
   ESPLUSPLAYER_AUDIO_MIME_TYPE_PCM_U32BE,
-  ESPLUSPLAYER_AUDIO_MIME_TYPE_G711_MULAW
-} esplusplayer_audio_mime_type;
+  ESPLUSPLAYER_AUDIO_MIME_TYPE_G711_MULAW,
+  ESPLUSPLAYER_AUDIO_MIME_TYPE_AC4,
+  ESPLUSPLAYER_AUDIO_MIME_TYPE_MPEGH,
+  ESPLUSPLAYER_AUDIO_MIME_TYPE_FLAC
+};
 
 /**
  * @brief   Enumerations for video mime type
+ * @description ESPLUSPLAYER_VIDEO_MIME_TYPE_WMV3 only can be supported before
+ * TIZEN8.0
  */
-typedef enum {
+enum esplusplayer_video_mime_type {
   ESPLUSPLAYER_VIDEO_MIME_TYPE_UNKNOWN,
   ESPLUSPLAYER_VIDEO_MIME_TYPE_H263,
   ESPLUSPLAYER_VIDEO_MIME_TYPE_H264,
@@ -85,7 +79,7 @@ typedef enum {
   ESPLUSPLAYER_VIDEO_MIME_TYPE_WMV3,
   ESPLUSPLAYER_VIDEO_MIME_TYPE_AV1,
   ESPLUSPLAYER_VIDEO_MIME_TYPE_MJPEG
-} esplusplayer_video_mime_type;
+};
 
 /**
  * @brief   Audio stream information structure
@@ -163,4 +157,4 @@ typedef struct {
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_TRACK_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_TRACK_H__
index acb80ca..73642e2 100644 (file)
@@ -1,31 +1,21 @@
-/**
- * @file
- * @brief          For submit data type enum.
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style submitstatus related enum.
- * @see            SubmitDataType enum conversion.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITDATATYPE_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITDATATYPE_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITDATATYPE_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITDATATYPE_H__
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,15 +24,14 @@ extern "C" {
 /**
  * @brief  Enumerations for the type of buffers submitted
  */
-typedef enum {
+enum esplusplayer_submit_data_type {
   ESPLUSPLAYER_SUBMIT_DATA_TYPE_CLEAN_DATA,
   ESPLUSPLAYER_SUBMIT_DATA_TYPE_ENCRYPTED_DATA,
-//  ESPLUSPLAYER_SUBMIT_DATA_TYPE_TRUSTZONE_DATA,
-  ESPLUSPLAYER_SUBMIT_DATA_TYPE_MAX,
-} esplusplayer_submit_data_type;
+  ESPLUSPLAYER_SUBMIT_DATA_TYPE_TRUSTZONE_DATA,
+};
 
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITDATATYPE_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITDATATYPE_H__
index cc28c4c..d7f8f84 100644 (file)
@@ -1,31 +1,21 @@
-/**
- * @file
- * @brief          For submitstatus enum.
- * @interfacetype  Platform
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        2.0
- * @SDK_Support    N
- * @remark         This is a group of C style submitstatus related enum.
- * @see            Submitstatus enum convertion.
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#ifndef __PLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITSTATUS_H__
-#define __PLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITSTATUS_H__
+#ifndef __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITSTATUS_H__
+#define __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITSTATUS_H__
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,16 +24,16 @@ extern "C" {
 /**
  * @brief  Enumerations for the buffer status
  */
-typedef enum {
+enum esplusplayer_submit_status {
   ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED,
   ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET,
   ESPLUSPLAYER_SUBMIT_STATUS_OUT_OF_MEMORY,
   ESPLUSPLAYER_SUBMIT_STATUS_FULL,
   ESPLUSPLAYER_SUBMIT_STATUS_SUCCESS
-} esplusplayer_submit_status;
+};
 
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // __PLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITSTATUS_H__
+#endif  // __ESPLUSPLAYER_ESPLUSPLAYER_CAPI_SUBMITSTATUS_H__
diff --git a/include/mixer/decodedvideoinfo.h b/include/mixer/decodedvideoinfo.h
new file mode 100644 (file)
index 0000000..de8cf89
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_DECODED_VIDEO_INFO_H__
+#define __ESPLUSPLAYER_MIXER_DECODED_VIDEO_INFO_H__
+
+#include <tbm_type_common.h>
+
+#include <cstdint>
+
+namespace esplusplayer {
+
+struct DecodedRawPlaneInfo {
+  std::uint32_t phyaddr;
+  std::uint32_t viraddr;
+  std::uint32_t linesize;
+};
+
+struct DecodedRawInfo {
+  std::uint32_t width;
+  std::uint32_t height;
+  DecodedRawPlaneInfo y_info;
+  DecodedRawPlaneInfo uv_info;
+};
+
+struct DecodedVideoKeyTypeInfo {
+  std::uint32_t width;
+  std::uint32_t height;
+  tbm_key key;
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_DECODED_VIDEO_INFO_H__
diff --git a/include/mixer/mixer.h b/include/mixer/mixer.h
new file mode 100644 (file)
index 0000000..d63ebc0
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_MIXER__H__
+#define __ESPLUSPLAYER_MIXER_MIXER__H__
+
+#include <boost/core/noncopyable.hpp>
+#include <memory>
+
+#include "mixer/mixer_eventlistener.h"
+#include "mixer/mixerticket.h"
+#include "esplusplayer/types/display.h"
+// LCOV_EXCL_START
+namespace esplusplayer {
+/**
+ * @brief Enumerations for Resource allocation policy
+ */
+enum class RscAllocMode {
+  kDefault,  /**< Main -> Sub -> S/W */
+  kNdecoder, /**< Only N decoder */
+  kDisable   /**< Mixer is NOT involved in resource allocation */
+};
+/**
+ * @brief Class Mixer
+ */
+/**
+ * @brief   Provides methods to control mixer pipeline and modify
+ *          mixed frame.
+ * @remark  It internally manages MixerTicket objects which are
+ *          combined with player objects.
+ * @see     Mixerticket
+ */
+class Mixer : private boost::noncopyable {
+ public:
+  using Ptr = std::unique_ptr<Mixer>;
+  /**
+   * @brief      Create a mixer object
+   * @remarks    You must use this to get mixer object
+   * @pre        None
+   * @post       None
+   * @exception  None
+   * @return     mixer object (unique_ptr<Mixer>)
+   */
+  static Ptr Create();
+  /**
+   * @brief Struct for Resolution info of mixed frame.
+   * @brief Default info is 1920x1080, 30fps
+   */
+  struct ResolutionInfo {
+    int width = 1920;       /**< Width of mixed frame */
+    int height = 1080;      /**< Height of mixed frame */
+    int framerate_num = 30; /**< Framerate numerator of mixed frame */
+    int framerate_den = 1;  /**< Framerate denominator of mixed frame */
+  };
+
+ public:
+  /**
+   * @brief     Destructor of Mixer
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   * @see       Mixer::Create()
+   */
+  virtual ~Mixer(){};
+  /**
+   * @brief     Starts Mixer
+   * @pre       None
+   * @post      Black frame or mixed frame will be displayed on the screen
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       Mixer::Stop()
+   */
+// LCOV_EXCL_START
+  virtual bool Start() { return false; }
+  /**
+   * @brief     Stops Mixer
+   * @pre       Mixer::Start() was called
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       Mixer::Start()
+   */
+  virtual bool Stop() { return false; }
+  /**
+   * @brief     Gets maximal number of players which can be connected to Mixer
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    Non-zero value on success, otherwise zero
+   */
+  virtual int GetMaximumAllowedNumberOfPlayer() { return 0; }
+  /**
+   * @brief     Sets the video display
+   * @remarks   We are not supporting changing display.
+   * @remarks   This API have to be called before calling the
+   *            Mixer::Start() to reflect the display type.
+   * @param     [in] type : display type
+   * @param     [in] obj : The handle to display window
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       DisplayType
+   *            Mixer::SetDisplayRoi()
+   */
+  virtual bool SetDisplay(const DisplayType type, void* obj) { return false; }
+  /**
+   * @brief     Sets the video display
+   * @remarks   We are not supporting changing display.
+   * @remarks   This API have to be called before calling the
+   *            Mixer::Start() to reflect the display type.
+   * @param     [in] type : display type
+   * @param     [in] serface_id : resource id of window
+   * @param     [in] x : x param of display window
+   * @param     [in] y : y param of display window
+   * @param     [in] w : width of display window
+   * @param     [in] h : height of display window
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       DisplayType
+   *            Mixer::SetDisplayRoi()
+   */
+  virtual bool SetDisplay(const DisplayType type, const uint32_t surface_id, const int x, const int y, const int w, const int h) { return false; }
+  /**
+   * @brief     Set the video display mode
+   * @param     [in] mode : display mode
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       DisplayMode
+   * @see       Mixer::SetDisplay()
+   * @see       Mixer::SetDisplayRoi()
+   */
+  virtual bool SetDisplayMode(const DisplayMode& mode) { return false; }
+  /**
+   * @brief     Sets the ROI(Region Of Interest) area of display
+   * @remarks   The minimum value of width and height are 1.
+   * @param     [in] geometry : Roi Geometry
+   * @pre       Before set display ROI, #DisplayMode::kDstRoi must be set
+   *            with Mixer::SetDisplayMode().
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       DisplayMode  \n
+   *            Mixer::SetDisplay() \n
+   *            Mixer::SetDisplayMode()
+   */
+  virtual bool SetDisplayRoi(const Geometry& geometry) { return false; }
+   /**
+   * @brief     Set Resource allocation policy.
+   * @param     [in] mode : Resource allocation policy
+   * @pre       This api should be called before setting player's display type to
+   *            mixer type.
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetRscAllocMode(const RscAllocMode& mode) { return false; }
+  /**
+   * @brief     Disable audio focus setting.
+   *            The mixer has no authority to set audio focus and player can
+   *            control audio pipeline's activation/deactivation.
+   * @pre       This api should be called before setting player's display type to
+   *            mixer type.
+   * @post      SetAudioFocus() will return false.
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool DisableAudioFocusSetting() { return false; }
+  /**
+   * @brief     Set the alternative video scaler.
+   *            The mixer change to use the sub video scaler instead of main video
+   *            scaler(default).
+   * @pre       This api should be called before setting player's display type to
+   *            mixer type.
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetAlternativeVideoScaler() { return false; }
+  /**
+   * @brief     Sets audio focus on the specific player object
+   * @param     [in] player_instance : The handle to player instance
+   * @pre       None
+   * @post      The player which gets audio focus will activate its audio
+   *            pipeline.
+   *            By default, players deactivate audio until setting audio focus.
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetAudioFocus(const void* player_instance) { return false; }
+  /**
+   * @brief     Applies geometry changes on mixed frame
+   * @pre       SetDisplayRoi() was called for players which are connected to
+   *            Mixer.
+   * @post      All the geometry changes will be applied to mixed frame.
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool Commit() { return false; }
+  /**
+   * @brief     Sets resolution of mixed frame
+   * @remarks   By default, the resolution of mixed frame is 1920x1080.
+   * @param     [in] info : The resolution info of mixed frame
+   * @pre       Mixer has no connected players yet.
+   * @post      The resolution of mixed frame will be changed.
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool SetResolution(const ResolutionInfo& info) { return false; }
+  /**
+   * @brief     Register eventlistener to Mixer
+   * @param     [in] listener : listener object
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       MixerEventListener
+   */
+  virtual bool RegisterListener(MixerEventListener* listener) { return false; }
+  /**
+   * @brief     Creates MixerTicket object for the specific player
+   * @param     [in] player_instance : The handle to player instance
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    A valid @c MixerTicket object on success, otherwise @c nullptr
+   */
+  virtual MixerTicket* CreateTicket(const void* player_instance) {
+    return nullptr;
+  }
+// LCOV_EXCL_STOP
+
+ protected:
+  /**
+   * @brief     Constructor of Mixer
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   * @see       Mixer::Create()
+   */
+  Mixer() noexcept {};
+};
+
+}  // namespace esplusplayer
+// LCOV_EXCL_STOP
+
+#endif  // __ESPLUSPLAYER_MIXER_MIXER__H__
diff --git a/include/mixer/mixer_eventlistener.h b/include/mixer/mixer_eventlistener.h
new file mode 100644 (file)
index 0000000..34363ff
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_MIXER_MIXER_EVENTLISTENER__H__
+#define __ESPLUSPLAYER_SRC_MIXER_MIXER_EVENTLISTENER__H__
+
+namespace esplusplayer {
+/**
+ * @brief Class MixerEventListener
+ */
+/**
+ * @brief   Notifies event that an application needs to handle.
+ * @remark  An application should implement concrete class.
+ * @see     Mixer::RegisterListener
+ */
+class MixerEventListener {
+ public:
+  /**
+   * @brief     Constuctor of MixerEventListener
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+  MixerEventListener(){};
+  /**
+   * @brief     Destructor of MixerEventListener
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+  virtual ~MixerEventListener(){};
+  /**
+   * @brief     It will be invoked when an error is occured in Mixer object
+   * @remark    OnError means that Mixer can't continue its operation.
+   *            An application may need to terminate Mixer usage.
+   * @pre       MixerEventListener object is registered
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+// LCOV_EXCL_START
+  virtual void OnError() {}
+  /**
+   * @brief     It will be invoked when Mixer's own pipeline is notified
+   *            resource confliction
+   * @remark    OnResourceConflicted means that Mixer can't play anymore.
+   *            An application must terminate Mixer usage.
+   * @pre       MixerEventListener object is registered
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+  virtual void OnResourceConflicted() {}
+// LCOV_EXCL_STOP
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_MIXER_MIXER_EVENTLISTENER__H__
diff --git a/include/mixer/mixerticket.h b/include/mixer/mixerticket.h
new file mode 100644 (file)
index 0000000..dbe0793
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_MIXER_MIXERTICKET__H__
+#define __ESPLUSPLAYER_SRC_MIXER_MIXERTICKET__H__
+
+#include <memory>
+
+#include "mixer/decodedvideoinfo.h"
+#include "mixer/mixerticket_eventlistener.h"
+
+namespace esplusplayer {
+/**
+ * @brief Enumerations for Resource category
+ * @brief Each player informs mixer with this category so that
+ *        Mixer can understand which player uses which resources.
+ */
+enum class ResourceCategory {
+  kVideoDecoder, /**< Video decoder category */
+  kAudioDecoder, /**< Audio decoder category */
+  kScaler        /**< Scaler category */
+};
+/**
+ * @brief Enumerations for Resource type
+ * @brief Each player informs mixer with this type so that
+ *        Mixer can understand which player uses main or sub type.
+ */
+enum class ResourceType {
+  kHwMain, /**< H/W Main resource type */
+  kHwSub,  /**< H/W Sub resource type */
+  kSw,     /**< S/W resource type. Only valid for decoder category */
+  kNdecoder,  /**< N decoder resource type */
+  kMax     /**< Size of this enumeration (not used) */
+};
+/**
+ * @brief Class MixerTicket
+ */
+/**
+ * @brief   Provides methods for player to send their raw video
+ *          frame to Mixer.
+ * @remark  It also helps player to request H/W resources without
+ *          causing confliction.
+ * @see     Mixer
+ */
+class MixerTicket {
+ public:
+  /**
+   * @brief     Constuctor of MixerTicket
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+  MixerTicket(){};
+  /**
+   * @brief     Destructor of MixerTicket
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+// LCOV_EXCL_START
+  virtual ~MixerTicket(){};
+  /**
+   * @brief     Gets currently available resource type for the player
+   * @param     [in] category : The resource category that player wants to use
+   * @param     [out] type : The resource type that player can allocate
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool GetAvailableResourceType(const ResourceCategory& category,
+                                        ResourceType* type) {
+    return false;
+  }
+  /**
+   * @brief     Informs mixer about resource allocation status
+   * @param     [in] category : The resource category that player is using
+   * @param     [in] type : The resource type that player is using
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool Alloc(const ResourceCategory& category,
+                     const ResourceType& type) {
+    return false;
+  }
+  /**
+   * @brief     Renders decoded video frame into mixed frame in Mixer object
+   * @param     [in] info : The decoded physical address by H/W deocder
+   *            and the resolution of video frame.
+   * @pre       MixerTicket::Prepare() must be performed without error
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool Render(const DecodedRawInfo& info) { return false; }
+  /**
+   * @brief     Renders decoded video frame into mixed frame in Mixer object
+   * @param     [in] info : The information for tbm_key exported and the
+   *            resolution of video frame.
+   * @pre       MixerTicket::Prepare() must be performed without error
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool Render(const DecodedVideoKeyTypeInfo& info) { return false; }
+  /**
+   * @brief     Registers eventlistener to MixerTicket
+   * @param     [in] listener : listener object
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   * @see       MixerTicketEventListener
+   */
+  virtual bool RegisterListener(MixerTicketEventListener* listener) {
+    return false;
+  }
+  /**
+   * @brief     Prepares MixerTicket objects to be ready for use
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool Prepare() { return false; }
+  /**
+   * @brief     Get the status whether the mixer can handle player's audio focus.
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True : The mixer can handle player's audio focus,
+   *            @c False : The mixer can't handle player's audio focus and
+   *                       the attached players will determin whether to activate
+   *                       audio track directly.
+   */
+  virtual bool IsAudioFocusHandler() { return false; }
+  /**
+   * @brief     Get the status whether Mixer can handle player's resource
+   *            allocation.
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    @c True : The mixer will allocate appropriate video decoder
+   *                      resources to the attached players,
+   *            @c False : The attached player sets the video decoder resource to
+   *                       be allocated directly instead of the mixer.
+   */
+  virtual bool IsRscAllocHandler() { return false; }
+// LCOV_EXCL_STOP
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_MIXER_MIXERTICKET__H__
\ No newline at end of file
diff --git a/include/mixer/mixerticket_eventlistener.h b/include/mixer/mixerticket_eventlistener.h
new file mode 100644 (file)
index 0000000..25b7e80
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_MIXER_MIXERTICKET_EVENTLISTENER__H__
+#define __ESPLUSPLAYER_SRC_MIXER_MIXERTICKET_EVENTLISTENER__H__
+
+#include "esplusplayer/types/display.h"
+
+namespace esplusplayer {
+/**
+ * @brief Class MixerTicketEventListener
+ */
+/**
+ * @brief   Notifies event that player needs to handle.
+ * @remark  Player should implement concrete class.
+ * @see     MixerTicket::RegisterListener
+ */
+class MixerTicketEventListener {
+ public:
+  /**
+   * @brief     Constuctor of MixerTicketEventListener
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+  MixerTicketEventListener(){};
+  /**
+   * @brief     Destructor of MixerTicketEventListener
+   * @pre       None
+   * @post      None
+   * @exception None
+   * @return    None
+   */
+  virtual ~MixerTicketEventListener(){};
+  /**
+   * @brief     It will be invoked when audio focus is being changed
+   * @param     [in] active : @c True if the player gets focused, otherwise @c
+   *            False.
+   * @pre       MixerTicketEventListener object is registered
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+// LCOV_EXCL_START
+  virtual bool OnAudioFocusChanged(bool active) { return false; }
+  /**
+   * @brief     It will be invoked when the mixed frame's geometry is being
+   *            changed
+   * @param     [in] cur_info : current display info that Mixer stores for this
+   *            player
+   * @param     [out] new_info : update display info that player needs to
+   *            provide for Mixer
+   * @pre       MixerTicketEventListener object is registered
+   * @post      None
+   * @exception None
+   * @return    @c True on success, otherwise @c False
+   */
+  virtual bool OnUpdateDisplayInfo(const DisplayInfo& cur_info,
+                                   DisplayInfo* new_info) {
+    return false;
+  }
+// LCOV_EXCL_STOP
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_MIXER_MIXERTICKET_EVENTLISTENER__H__
diff --git a/include/mixer_capi/display.h b/include/mixer_capi/display.h
new file mode 100644 (file)
index 0000000..17b576b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_CAPI_DISPLAY_H__
+#define __ESPLUSPLAYER_MIXER_CAPI_DISPLAY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief  Enumerations for the display mode
+ */
+enum mixer_display_mode {
+  MIXER_DISPLAY_MODE_LETTER_BOX,
+  MIXER_DISPLAY_MODE_ORIGIN_SIZE,
+  MIXER_DISPLAY_MODE_FULL_SCREEN,
+  MIXER_DISPLAY_MODE_CROPPED_FULL,
+  MIXER_DISPLAY_MODE_ORIGIN_OR_LETTER,
+  MIXER_DISPLAY_MODE_DST_ROI
+};
+
+/**
+ * @brief  Enumerations for the display type
+ */
+enum mixer_display_type {
+  MIXER_DISPLAY_TYPE_NONE,
+  MIXER_DISPLAY_TYPE_OVERLAY,
+};
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // __ESPLUSPLAYER_MIXER_CAPI_DISPLAY_H__
\ No newline at end of file
diff --git a/include/mixer_capi/error.h b/include/mixer_capi/error.h
new file mode 100644 (file)
index 0000000..57e9d22
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_CAPI_ERROR_H__
+#define __ESPLUSPLAYER_MIXER_CAPI_ERROR_H__
+
+#include "tizen.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIXER_ERROR_CLASS TIZEN_ERROR_PLAYER | 0x20
+
+/**
+ * @brief  Enumerations for the error type
+ */
+enum mixer_error_type {
+  MIXER_ERROR_TYPE_NONE = TIZEN_ERROR_NONE, /**< Successful */
+  MIXER_ERROR_TYPE_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+  MIXER_ERROR_TYPE_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid operation */
+};
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // __ESPLUSPLAYER_MIXER_CAPI_ERROR_H__
\ No newline at end of file
diff --git a/include/mixer_capi/mixer_capi.h b/include/mixer_capi/mixer_capi.h
new file mode 100644 (file)
index 0000000..9141fe6
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_CAPI_MIXER_CAPI_H__
+#define __ESPLUSPLAYER_MIXER_CAPI_MIXER_CAPI_H__
+
+#include "mixer_capi/error.h"
+#include "mixer_capi/display.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef void (*mixer_resource_conflicted_cb)(void*);
+
+typedef void* mixer_handle;
+typedef void* mixer_ticket_h;
+
+/**
+ * @brief  Enumerations for the resource allocation mode
+ */
+enum mixer_rsc_alloc_mode {
+  MIXER_RSC_ALLOC_MODE_DEFAULT,  /**< Main -> Sub -> S/W */
+  MIXER_RSC_ALLOC_MODE_NDECODER, /**< Only N decoder */
+  MIXER_RSC_ALLOC_MODE_DISABLE /**< Mixer is NOT involved in resource allocation */
+};
+
+/**
+ * @brief     Create a mixer handle
+ * @param     None
+ * @return    return mixer handle pointer
+ * @code
+      // basic api call sequence
+      mixer_handle mixer = mixer_create();
+      mixer_set_display(mixer, MIXER_DISPLAY_TYPE_OVERLAY, window);
+
+      esplusplayer_handle player1 = esplusplayer_create();
+      esplusplayer_open(player1);
+
+      esplusplayer_set_display(player1, ESPLUSPLAYER_DISPLAY_TYPE_MIXER, mixer);
+      eplusplayer_set_display_roi(player1, x, y, w, h);
+
+      mixer_set_audio_focus(mixer, player1);
+
+      esplusplayer_set_video_stream_info(player1, video_info);
+      esplusplayer_set_audio_stream_info(player1, audio_info);
+      esplusplayer_prepare_async(player1);
+
+      mixer_start(mixer);
+      esplusplayer_start(player1);
+
+      mixer_stop(mixer);
+      esplusplayer_close(player1);
+      mixer_destroy(mixer);
+      esplusplayer_destroy(player1);
+ * @endcode
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+mixer_handle mixer_create();
+
+/**
+ * @brief     Release mixer handle
+ * @param     [in] handle : mixer handle
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       None
+ * @post      mixer handle will be removed
+ * @exception   None
+ * @see       mixer_create()
+ */
+int mixer_destroy(mixer_handle handle);
+
+/**
+ * @brief     Starts Mixer.
+ * @param     [in] handle : mixer handle
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       None
+ * @post      Black frame or mixed frame will be displayed on the screen
+ * @exception   None
+ * @see       mixer_stop()
+ */
+int mixer_start(mixer_handle handle);
+
+/**
+ * @brief     Stops Mixer
+ * @param     [in] handle : Mixer handle
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       mixer_start() should be called
+ * @post      None
+ * @exception   None
+ * @see       mixer_start()
+ */
+int mixer_stop(mixer_handle handle);
+
+/**
+ * @brief     Gets maximal number of players which can be connected to Mixer
+ * @param     [in] handle : Mixer handle
+ * @return    Non-zero value on success, otherwise zero
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+int mixer_get_max_allowed_number_of_player(mixer_handle handle);
+
+/**
+ * @brief     Sets the video display
+ * @param     [in] handle : Mixer handle
+ * @param     [in] type : display type
+ * @param     [in] window : The handle to display window
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       This API have to be called before calling the
+ *            mixer_start() to reflect the display type
+ * @post      None
+ * @exception   None
+ * @remarks    We are not supporting changing display
+ * @see       mixer_display_type \n
+ *            mixer_set_display_roi()
+ */
+int mixer_set_display(mixer_handle handle, mixer_display_type type,
+                      void* window);
+
+/**
+ * @brief     Set the video display mode
+ * @param     [in] handle : Mixer handle
+ * @param     [in] mode : display mode
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       None
+ * @post      None
+ * @exception   None
+ * @see       mixer_display_mode
+ * @see       mixer_set_display() \n
+ *            mixer_set_display_roi()
+ */
+int mixer_set_display_mode(mixer_handle handle, mixer_display_mode mode);
+
+/**
+ * @brief     Sets the ROI(Region Of Interest) area of display
+ * @param     [in] handle : Mixer handle
+ * @param     [in] geometry : Roi Geometry
+ * @return    @c one of mixer_error_type values will be returned
+ * @code
+      // The ROI of mixer means display area in tv screen.
+      // The ROI of each player means display area in mixer's ROI.
+
+      mixer_set_display_mode(mixer, MIXER_DISPLAY_MODE_DST_ROI);
+      mixer_set_display_roi(mixer, 0, 0, 1920, 1080);
+
+      esplusplayer_set_display_roi(player1, 20, 20, 700, 400);
+      esplusplayer_set_display_roi(player2, 20, 20, 700, 400);
+
+      mixer_commit(mixer);
+ * @endcode
+ * @pre       Before set display ROI, #MIXER_DISPLAY_MODE_DST_ROI must be set
+ *            with mixer_set_display_mode()
+ * @post      None
+ * @exception   None
+ * @remarks    The minimum value of width and height are 1.
+ * @see       mixer_display_mode \n
+ *            mixer_set_display() \n
+ *            mixer_set_display_mode()
+ */
+int mixer_set_display_roi(mixer_handle handle, const int x, const int y,
+                          const int width, const int height);
+
+ /**
+  * @brief     Applies geometry changes on mixed frame
+  * @param     [in] handle : Mixer handle
+  * @return    @c one of mixer_error_type values will be returned
+  * @pre       set display roi api was called for players which are connected to
+  *            Mixer.
+  * @post      All the geometry changes will be applied to mixed frame.
+  * @exception   None
+  * @see       mixer_set_display_roi()
+  */
+ int mixer_commit(mixer_handle handle);
+
+ /**
+  * @brief     Set Resource allocation policy
+  * @param     [in] handle : Mixer handle
+  * @param     [in] mode : Resource allocation policy
+  * @return    @c one of mixer_error_type values will be returned
+  * @pre       This api should be called before setting player's display type to
+  *            mixer type.
+  * @post      None
+  * @exception None
+  */
+ int mixer_set_rsc_alloc_mode(mixer_handle handle,
+                              const mixer_rsc_alloc_mode mode);
+
+/**
+ * @brief     Disable audio focus setting.
+ *            The mixer has no authority to set audio focus and player can
+ *            control audio pipeline's activation/deactivation.
+ * @param     [in] handle : Mixer handle
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       This api should be called before setting player's display type to
+ *            mixer type.
+ * @post      mixer_set_audio_focus() will return error.
+ * @exception   None
+ */
+int mixer_disable_audio_focus_setting(mixer_handle handle);
+
+/**
+ * @brief     Set the alternative video scaler.
+ *            The mixer change to use the sub video scaler instead of main video
+ *            scaler(default).
+ * @param     [in] handle : Mixer handle
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       This api should be called before mixer_start().
+ * @post      None
+ * @exception   None
+ */
+int mixer_set_alternative_video_scaler(mixer_handle handle);
+
+/**
+ * @brief     Sets audio focus on the specific player object
+ * @param     [in] handle : Mixer handle
+ * @param     [in] player_instance : The handle to player instance
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       None
+ * @post      The player which gets audio focus will activate its audio
+ *            pipeline. By default, players deactivate audio until setting
+ *            audio focus.
+ * @exception   None
+ */
+int mixer_set_audio_focus(mixer_handle handle, const void* player_instance);
+
+/**
+ * @brief     Sets resolution of mixed frame
+ * @param     [in] handle : Mixer handle
+ * @param     [in] info : The resolution info of mixed frame
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       Mixer has no connected players yet.
+ * @post      The resolution of mixed frame will be changed.
+ * @exception   None
+ * @remarks    By default, the resolution of mixed frame is 1920x1080.
+ */
+int mixer_set_resolution(mixer_handle handle, const int width, const int height,
+                         const int framerate_num, const int framerate_den);
+
+/**
+ * @brief     Creates MixerTicket object for the specific player
+ * @param     [in] handle : Mixer handle
+ * @param     [in] player_instance : The handle to player instance
+ * @return    A valid @c MixerTicket object on success, otherwise @c nullptr
+ * @pre       None
+ * @post      None
+ * @exception   None
+ */
+mixer_ticket_h mixer_create_ticket(mixer_handle handle,
+                                   const void* player_instance);
+
+// callback function
+
+/**
+ * @brief     It will be invoked when Mixer's own pipeline is notified
+ *            resource confliction
+ * @param     [in] handle : Mixer handle
+ * @param     [in] callback : the callback function to register
+ * @param     [in] userdata : userdata of resource_conflicted_cb()
+ * @return    @c one of mixer_error_type values will be returned
+ * @pre       None
+ * @post      resource_conflicted_cb will be invoked when resources are
+ *            conflicted
+ * @exception   None
+ * @remark    resource_conflicted_cb means that Mixer can't play anymore.
+ *            An application must terminate Mixer usage.
+ */
+int mixer_set_resource_conflicted_cb(
+    mixer_handle handle, mixer_resource_conflicted_cb resource_conflicted_cb,
+    void* userdata);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __ESPLUSPLAYER_MIXER_CAPI_MIXER_CAPI_H__
+
diff --git a/include/plusplayer/attribute.h b/include/plusplayer/attribute.h
deleted file mode 100644 (file)
index a804d9d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * @file           attribute.h
- * @interfacetype  module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        1.0
- * @SDK_Support    N
- *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
- */
-#ifndef __PLUSPLAYER_ATTRIBUTE_H__
-#define __PLUSPLAYER_ATTRIBUTE_H__
-
-namespace plusplayer {
-
-/**
- * @brief Enumeration for plusplayer attribute
- *        If there is new attribute, please write details in below documents.
- */
-enum class Attribute {
-  kVideoQueueMaxByte,           // std::uint64_t
-  kAudioQueueMaxByte,           // std::uint64_t
-  kVideoQueueCurrentLevelByte,  // std::uint64_t
-  kAudioQueueCurrentLevelByte,  // std::uint64_t
-  kVideoMinByteThreshold,       // std::uint32_t
-  kAudioMinByteThreshold,       // std::uint32_t
-  kVideoQueueMaxBuffer,         // std::uint64_t
-  kAudioQueueMaxBuffer,         // std::uint64_t
-#if 0
-  kVideoQueueMaxTime,           // std::uint64_t
-  kAudioQueueMaxTime,           // std::uint64_t
-  kVideoQueueCurrentLevelTime,  // std::uint64_t
-  kAudioQueueCurrentLevelTime,  // std::uint64_t
-  kVideoMinTimeThreshold,       // std::uint32_t
-  kAudioMinTimeThreshold,       // std::uint32_t
-#endif
-  kMax,
-};
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_ATTRIBUTE_H__
\ No newline at end of file
diff --git a/include/plusplayer/drm.h b/include/plusplayer/drm.h
deleted file mode 100644 (file)
index ba7b7e0..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
-* @file
-* @interfacetype  module
-* @privlevel      None-privilege
-* @privilege      None
-* @product        TV, AV, B2B
-* @version        1.0
-* @SDK_Support    N
-*
-* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-* PROPRIETARY/CONFIDENTIAL
-* This software is the confidential and proprietary
-* information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
-* not disclose such Confidential Information and shall use it only in
-* accordance with the terms of the license agreement you entered into with
-* SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
-* suitability of the software, either express or implied, including but not
-* limited to the implied warranties of merchantability, fitness for a
-* particular purpose, or non-infringement. SAMSUNG shall not be liable for any
-* damages suffered by licensee as a result of using, modifying or distributing
-* this software or its derivatives.
-*/
-
-#ifndef __PLUSPLAYER_DRM_H__
-#define __PLUSPLAYER_DRM_H__
-
-namespace plusplayer {
-
-namespace drm {
-
-using LicenseAcquiredCb = void*;
-using UserData = void*;
-using DrmHandle = int;
-
-enum class Type {
-  kNone = 0,
-  kPlayready,
-  kMarlin,
-  kVerimatrix,
-  kWidevineClassic,
-  kSecuremedia,
-  kSdrm,
-  kWidevineCdm = 8,
-  kClearkey,
-  kMax
-};
-
-// post from hlsdemux for getright
-
-struct Property {
-  Type type = Type::kNone; // Drm type
-  DrmHandle handle = 0; // Drm handle
-  bool external_decryption = false; // External Decryption Mode
-  LicenseAcquiredCb license_acquired_cb = nullptr; // The cb will be invoked when license was acquired.
-  UserData license_acquired_userdata = nullptr; // The userdata will be sent by license_acquired_cb
-};
-
-}  // namespace drm
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_DRM_H__
diff --git a/include/plusplayer/types/buffer.h b/include/plusplayer/types/buffer.h
deleted file mode 100644 (file)
index 76ca1e8..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * @file
- * @brief          the buffer for playback
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        0.0.1
- * @SDK_Support    N
- *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
- */
-#ifndef __PLUSPLAYER_TYPES_BUFFER_H__
-#define __PLUSPLAYER_TYPES_BUFFER_H__
-
-#include <cstdint>
-
-#include "tbm_type.h"
-
-namespace plusplayer {
-
-/**
- * @brief  Enumerations for the buffer status
- */
-enum class BufferStatus { kUnderrun, kOverrun };
-
-enum class DecodedVideoFrameBufferType { kNone, kCopy, kReference, kScale };
-
-enum class BufferOption {
-  kBufferAudioMaxTimeSize,
-  kBufferVideoMaxTimeSize,
-  kBufferAudioMinTimeThreshold,
-  kBufferVideoMinTimeThreshold,
-  kBufferAudioMaxByteSize,
-  kBufferVideoMaxByteSize,
-  kBufferAudioMinByteThreshold,
-  kBufferVideoMinByteThreshold,
-  kBufferOptionMax
-};
-
-struct DecodedVideoPacket {
-  uint64_t pts = 0;
-  uint64_t duration = 0;
-  tbm_surface_h surface_data = nullptr;  // tbm_surface
-  void* buffer_addr = nullptr;
-};
-
-struct DecoderBufferTime {
-  uint64_t pts = 0;
-  uint64_t system_time = 0;
-};
-
-/**
- * @brief Enumerations for the state of getting decoded packet
- */
-enum class GetDecodedVideoFrameStatus {
-  kSuccess,
-  kNoRemainingBuffer,
-  kNoFilledBuffer,
-  kUnknown,
-};
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_TYPES_BUFFER_H__
diff --git a/include/plusplayer/types/display.h b/include/plusplayer/types/display.h
deleted file mode 100644 (file)
index c05c738..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @file
- * @interfacetype  module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        1.0
- * @SDK_Support    N
- *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
- */
-
-#ifndef __PLUSPLAYER_TYPES_DISPLAY_H__
-#define __PLUSPLAYER_TYPES_DISPLAY_H__
-
-namespace plusplayer {
-
-enum class DisplayType { kNone, kOverlay, kEvas, kMixer };
-
-enum class DisplayMode {
-  kLetterBox,
-  kOriginSize,
-  kFullScreen,
-  kCroppedFull,
-  kOriginOrLetter,
-  kDstRoi,
-  kAutoAspectRatio,
-  kMax
-};
-
-enum class DisplayRotation { kNone, kRotate90, kRotate180, kRotate270 };
-
-struct Geometry {
-  int x = 0, y = 0;
-  int w = 1920, h = 1080;
-};
-
-struct CropArea {
-  double scale_x = 0.0;
-  double scale_y = 0.0;
-  double scale_w = 1.0;
-  double scale_h = 1.0;
-};
-
-struct RenderRect {
-  int x = 0, y = 0;
-  int w = 1920, h = 1080;
-};
-
-enum class VisibleStatus { kHide, kVisible };
-
-struct DisplayInfo {
-  Geometry geometry;
-  CropArea croparea;
-  VisibleStatus visible_status = VisibleStatus::kVisible;
-};
-
-enum class StillMode { kNone, kOff, kOn };
-
-struct DisplayObject {
-  DisplayType type_;
-  int surface_id_;
-  DisplayMode mode_;
-  Geometry geometry_;
-  void* obj_;
-  bool is_obj_ = false;
-};
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_TYPES_DISPLAY_H__
diff --git a/include/plusplayer/types/event.h b/include/plusplayer/types/event.h
deleted file mode 100755 (executable)
index 1906d03..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * @file
- * @brief          The event for playback.
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        1.0
- * @SDK_Support    N
- * @remark         This is a group of C style event related enum and structure.
- * @see            N/A
- *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
- */
-
-#ifndef __PLUSPLAYER_TYPES_EVENT_H__
-#define __PLUSPLAYER_TYPES_EVENT_H__
-
-namespace plusplayer {
-/**
- * @brief
- */
-typedef struct {
-  /**
-   * @description
-   */
-  std::string data;
-  /**
-   * @description
-   */
-  uint64_t len;
-} EventMsg;
-
-/**
- * @brief
- */
-enum class EventType {
-  kNone,
-  kResolutionChanged,
-  kRequestedFirstRenderFrame,
-};
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_TYPES_EVENT_H__
diff --git a/include/plusplayer/types/source.h b/include/plusplayer/types/source.h
deleted file mode 100755 (executable)
index 433442a..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
-* @file           source.h
-* @brief          Types related to TrackSource
-* @interfacetype  module
-* @privlevel      None-privilege
-* @privilege      None
-* @product        TV, AV, B2B
-* @version        1.0
-* @SDK_Support    N
-*
-* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-* PROPRIETARY/CONFIDENTIAL
-* This software is the confidential and proprietary
-* information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
-* not disclose such Confidential Information and shall use it only in
-* accordance with the terms of the license agreement you entered into with
-* SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
-* suitability of the software, either express or implied, including but not
-* limited to the implied warranties of merchantability, fitness for a
-* particular purpose, or non-infringement. SAMSUNG shall not be liable for any
-* damages suffered by licensee as a result of using, modifying or distributing
-* this software or its derivatives.
-*/
-
-#ifndef __PLUSPLAYER_SRC_TRACKSOURCE_TYPES_H__
-#define __PLUSPLAYER_SRC_TRACKSOURCE_TYPES_H__
-
-namespace plusplayer {
-
-enum class SourceType {
-  kNone,
-  kBase,
-  kHttp,
-  kHls,
-  kDash,
-  kSmooth,
-  kFile,
-  kExternalSubtitle,
-  kNotFound,
-  kMax
-};
-
-enum class ContentFormat {
-  kNone,
-  kMP4Mov,
-  kMpegts,
-  k3GpMov,
-  kAudioMpeg,
-  kAudioMpegAac,
-  kMkv,
-  kAvi,
-  kVideoAsf,
-  kAppXid3,
-  kUnknown
-};
-
-enum class TrickPlayMode {
-  kNone,
-  kDefault,
-  kBySeek
-};
-
-enum class PlayingTimeSupport {
-  kNone,
-  kNeeded
-};
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_SRC_TRACKSOURCE_TYPES_H__
diff --git a/include/plusplayer/types/stream.h b/include/plusplayer/types/stream.h
deleted file mode 100755 (executable)
index f107592..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * @file
- * @brief          the stream information for playback
- * @interfacetype  Module
- * @privlevel      None-privilege
- * @privilege      None
- * @product        TV, AV, B2B
- * @version        0.0.1
- * @SDK_Support    N
- *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
- * PROPRIETARY/CONFIDENTIAL
- * This software is the confidential and proprietary
- * information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into with
- * SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
- * suitability of the software, either express or implied, including but not
- * limited to the implied warranties of merchantability, fitness for a
- * particular purpose, or non-infringement. SAMSUNG shall not be liable for any
- * damages suffered by licensee as a result of using, modifying or distributing
- * this software or its derivatives.
- */
-#ifndef __PLUSPLAYER_TYPES_STREAM_H__
-#define __PLUSPLAYER_TYPES_STREAM_H__
-
-namespace plusplayer {
-
-/**
- * @brief  Enumerations for the stream type
- */
-enum class StreamType { kAudio = 0, kVideo, kMax };
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_TYPES_STREAM_H__
\ No newline at end of file
diff --git a/include/plusplayer/types/streaming_message.h b/include/plusplayer/types/streaming_message.h
deleted file mode 100755 (executable)
index 6c5de10..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
-* @file           streaming_message.h
-* @interfacetype  module
-* @privlevel      None-privilege
-* @privilege      None
-* @product        TV, AV, B2B
-* @version        1.0
-* @SDK_Support    N
-*
-* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
-* PROPRIETARY/CONFIDENTIAL
-* This software is the confidential and proprietary
-* information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
-* not disclose such Confidential Information and shall use it only in
-* accordance with the terms of the license agreement you entered into with
-* SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
-* suitability of the software, either express or implied, including but not
-* limited to the implied warranties of merchantability, fitness for a
-* particular purpose, or non-infringement. SAMSUNG shall not be liable for any
-* damages suffered by licensee as a result of using, modifying or distributing
-* this software or its derivatives.
-*/
-
-#ifndef __PLUSPLAYER_TYPES_STREAMING_MESSAGE_H__
-#define __PLUSPLAYER_TYPES_STREAMING_MESSAGE_H__
-
-namespace plusplayer {
-
-enum class StreamingMessageType {
-  kNone = 0,
-  // kResolutionChanged,
-  // kAdEnd,
-  // kAdStart,
-  // kRenderDone,
-  kBitrateChange,
-  // kFragmentInfo,
-  kSparseTrackDetect,
-  // kStreamingEvent,
-  // kDrmChallengeData,
-  kDrmInitData,
-  // kHttpErrorCode,
-  // kDrmRenewSessionData,
-  kStreamEventType,
-  kStreamEventData,
-  kStreamSyncFlush,
-  kStreamMrsUrlChanged,
-  kDrmKeyRotation,
-  kFragmentDownloadInfo,
-  kDvrLiveLag,
-  kSparseTrackData,
-  kConnectionRetry,
-  kConfigLowLatency,
-  kCurlErrorDebugInfo,
-  kParDarChange
-};
-
-struct MessageParam {
-  std::string data;
-  int size = 0;
-  int code = 0;  // Error or warning code
-};
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_TYPES_STREAMING_MESSAGE_H__
\ No newline at end of file
diff --git a/include/plusplayer/types/submitdata.h b/include/plusplayer/types/submitdata.h
deleted file mode 100755 (executable)
index 8ade19f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
-* @file           submitdata.h
-* @brief          the data type to submit
-* @interfacetype  Module
-* @privlevel      None-privilege
-* @privilege      None
-* @product        TV, AV, B2B
-* @version        0.0.1
-* @SDK_Support    N
-*
-* Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
-* PROPRIETARY/CONFIDENTIAL
-* This software is the confidential and proprietary
-* information of SAMSUNG ELECTRONICS ("Confidential Information"). You shall
-* not disclose such Confidential Information and shall use it only in
-* accordance with the terms of the license agreement you entered into with
-* SAMSUNG ELECTRONICS. SAMSUNG make no representations or warranties about the
-* suitability of the software, either express or implied, including but not
-* limited to the implied warranties of merchantability, fitness for a
-* particular purpose, or non-infringement. SAMSUNG shall not be liable for any
-* damages suffered by licensee as a result of using, modifying or distributing
-* this software or its derivatives.
-*/
-#ifndef __PLUSPLAYER_TYPES_SUBMITDATA_H__
-#define __PLUSPLAYER_TYPES_SUBMITDATA_H__
-
-namespace plusplayer {
-
-/**
- * @brief Enumerations for the type of espacket submitted
- */
-enum class SubmitDataType {
-  kCleanData,      // For clean data
-  kEncryptedData,  // For encrypted data
-  kTrustZoneData   // For trustzone data
-};
-
-}  // namespace plusplayer
-
-#endif  // __PLUSPLAYER_TYPES_SUBMITDATA_H__
\ No newline at end of file
old mode 100755 (executable)
new mode 100644 (file)
index 1bd76f6..d17e41e 100644 (file)
@@ -1,16 +1,24 @@
-# %bcond_with : disable ESPLUSPLAYER_UT by default, %bcond_without : enable ESPLUSPLAYER_UT
+#%bcond_with : disable ESPLUSPLAYER_UT by default, %bcond_without : enable ESPLUSPLAYER_UT
+%bcond_without TIZEN_PUBLIC
+
+%if ("%{_vd_cfg_product_type}" != "AUDIO")
 %bcond_without ESPLUSPLAYER_UT
+%else
+%bcond_with ESPLUSPLAYER_UT
+%endif
+#echo "Product Type: %{_vd_cfg_product_type}"
+
 Name:       esplusplayer
 Summary:    new multimedia streaming player
-Version:    0.0.16
+Version:    1.2.1
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
 Source1001: esplusplayer.manifest
 BuildRequires:  cmake
+BuildRequires:  curl
 BuildRequires:  pkgconfig(glib-2.0)
-BuildRequires:  pkgconfig(capi-base-common)
 BuildRequires:  pkgconfig(gstreamer-1.0)
 BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
 BuildRequires:  pkgconfig(dlog)
@@ -19,27 +27,39 @@ BuildRequires:  pkgconfig(elementary)
 BuildRequires:  pkgconfig(ecore)
 BuildRequires:  pkgconfig(evas)
 BuildRequires:  pkgconfig(ecore-wl2)
-BuildRequires:  pkgconfig(wayland-client)
-BuildRequires:  pkgconfig(tizen-extension-client)
+%if %{with TIZEN_PUBLIC}
+BuildRequires:  pkgconfig(libtrackrenderer)
+# for test
+BuildRequires:  pkgconfig(capi-mediademuxer)
+BuildRequires:  pkgconfig(appcore-efl)
+%else
+BuildRequires:  pkgconfig(tv-resource-manager)
+BuildRequires:  pkgconfig(drmdecrypt)
+BuildRequires:  pkgconfig(context-aware-api)
+%if ("%{_vd_cfg_product_type}" != "AUDIO")
+BuildRequires:  pkgconfig(graphics-control)
+BuildRequires:  pkgconfig(libavoc)
+%else
+BuildRequires:  pkgconfig(libavoc-av)
+%endif
+BuildRequires:  pkgconfig(capi-trackrenderer-tv)
+BuildRequires:  pkgconfig(logger)
+%endif
+
 BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(jsoncpp)
-BuildRequires:  pkgconfig(capi-system-info)
+BuildRequires:  pkgconfig(icu-i18n)
 BuildRequires:  pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(libtbm)
-BuildRequires:  pkgconfig(libtrackrenderer)
 
+BuildRequires:  pkgconfig(libtbm)
+BuildRequires:  pkgconfig(capi-system-info)
 
+%if (("%{sec_buildconf_product_lite_tizen}" == "n") || %{with TIZEN_PUBLIC})
 # for ut
-#BuildRequires:  pkgconfig(capi-media-player)
-#BuildRequires:  pkgconfig(gtest_gmock)
+BuildRequires:  gtest-devel
 BuildRequires:  pkgconfig(appcore-efl)
-#BuildRequires:  pkgconfig(libresourced)
-BuildRequires:  pkgconfig(gmock)
-BuildRequires:  pkgconfig(libinput)
-BuildRequires:  pkgconfig(gstreamer-app-1.0)
-
-# for test
-BuildRequires: pkgconfig(capi-mediademuxer)
+%endif
 
 %define _packagedir /usr
 %define _bindir %{_packagedir}/bin
@@ -66,27 +86,121 @@ Requires:   %{name} = %{version}-%{release}
 
 %description config
 
+#################################################
+# gcov
+#################################################
+%if 0%{?vd_gcov:1}
+%package gcov
+Summary: gcov enabled package
+Group: gcov package
+
+%description gcov
+This package is gcov package for coverage measurement.
+%endif
+
+%if %{with TIZEN_PUBLIC}
 %package tool
 Summary:  Esplusplayer API testsuite with mediademuxer
 Requires: %{name} = %{version}-%{release}
 
 %description tool
 Esplusplayer API testsuite with mediademuxer
+%endif
 
 %prep
 %setup -q
 cp %{SOURCE1001} .
 
+%if ("%{sec_buildconf_product_lite_tizen}" == "n")
+%if ("%{_vd_cfg_product_type}" != "AUDIO")
+%{?!TOMATO: %define TOMATO n}
+
+%define _tomatoname esplusplayer
+%define _tomatodir  /opt/usr/apps/tomato/testcase/%{name}
+%define _tomatobin /opt/usr/apps/tomato/testcase/%{name}/bin
+
+%package ut-component-tomato
+Summary: Test package with TOMATO
+BuildRequires:  gtest-devel
+%if %{without TIZEN_PUBLIC}
+BuildRequires:  pkgconfig(video-capture)
+BuildRequires:  pkgconfig(audio-control)
+BuildRequires:  pkgconfig(video-sink)
+%endif
+BuildRequires:  libjpeg-turbo-devel
+
+#BuildRequires:  pkgconfig(capi-system-info)
+Requires: %{name} = %{version}-%{release}
+
+%description ut-component-tomato
+This package is for test
+
+%files ut-component-tomato
+%defattr(-,root,root,-)
+%{_bindir}/esplusplayer_ut
+%{_tomatodir}/*
+
+%endif
+%endif
 
 %build
 export CFLAGS+=" -Wno-deprecated-declarations"
 export CXXFLAGS+=" -Wno-deprecated-declarations"
 
+%if %{with TIZEN_PUBLIC}
+export CFLAGS+=" -DTIZEN_FEATURE_PUBLIC"
+export CXXFLAGS+=" -DTIZEN_FEATURE_PUBLIC"
+%define TIZEN_PUBLIC ON
+%define USE_MIXER no
+%else
+%if ("%{_vd_cfg_product_type}" == "AUDIO")
+export CFLAGS+=" -DIS_AUDIO_PRODUCT"
+export CXXFLAGS+=" -DIS_AUDIO_PRODUCT"
+%define PRODUCT_TYPE_AUDIO yes
+%define USE_MIXER no
+%else
+export CFLAGS+=" -DUSE_MIXER"
+export CXXFLAGS+=" -DUSE_MIXER"
+%define PRODUCT_TYPE_AUDIO no
+%define USE_MIXER yes
+%endif
+%define TIZEN_PUBLIC OFF
+%endif
+
+#TODO: check AV type is used or not
+%if ("%{_vd_cfg_product_type}" == "AV")
+export CFLAGS+=" -DIS_AV_PRODUCT"
+export CXXFLAGS+=" -DIS_AV_PRODUCT"
+%endif
+
+#TODO: AUDIO type is used to enable fmm mode API impl.
+%if ("%{_vd_cfg_product_type}" == "AUDIO")
+export CFLAGS+=" -DSOUNDBAR_PRODUCT"
+export CXXFLAGS+=" -DSOUNDBAR_PRODUCT"
+%define _support_soundbar -DSUPPORT_SOUNDBAR=ON
+%endif
+
+%if 0%{?vd_gcov:1}
+export CFLAGS+=" -fprofile-arcs -ftest-coverage"
+export CXXFLAGS+=" -fprofile-arcs -ftest-coverage"
+export FFLAGS+=" -fprofile-arcs -ftest-coverage"
+export LDFLAGS+=" -lgcov"
+#export CFLAGS+=" -DIS_TOMATO"
+#export CXXFLAGS+=" -DIS_TOMATO"
+%endif
+
 export CXXFLAGS+=" -Wno-pessimizing-move"
+
+%if %{without TIZEN_PUBLIC}
+%ifarch aarch64
+export CXXFLAGS+=" -DDRM_MAPI_AARCH_64"
+%endif
+%endif
+
 %if %{with ESPLUSPLAYER_UT}
-%cmake . -DESPLUSPLAYER_BUILD_UT=ON
+%cmake . -DESPLUSPLAYER_BUILD_UT=ON -DPRODUCT_TYPE_AUDIO=%PRODUCT_TYPE_AUDIO -DUSE_MIXER=%USE_MIXER -DTIZEN_PUBLIC=%TIZEN_PUBLIC
 %else
-%cmake .
+%cmake . -DPRODUCT_TYPE_AUDIO=%PRODUCT_TYPE_AUDIO -DUSE_MIXER=%USE_MIXER -DTIZEN_PUBLIC=%TIZEN_PUBLIC
 %endif
 
 make %{?jobs:-j%jobs}
@@ -94,27 +208,69 @@ make %{?jobs:-j%jobs}
 %install
 rm -rf %{buildroot}
 
+%if ("%{sec_buildconf_product_lite_tizen}" == "n")
+mkdir -p %{buildroot}%{_tomatodir}
+mkdir -p %{buildroot}%{_tomatodir}/log
+mkdir -p %{buildroot}%{_tomatodir}/result
+mkdir -p %{buildroot}%{_tomatodir}/tc
+cp -rf tomato/tc/* %{buildroot}%{_tomatodir}/tc
+%endif
+
 %make_install
 mkdir -p %{buildroot}%TZ_SYS_RO_ETC/multimedia
+#mkdir -p %{buildroot}%TZ_SYS_RW_APP/multimedia
+#mkdir -p %{buildroot}/opt
+#mkdir -p %{buildroot}/opt/usr
+#mkdir -p %{buildroot}/opt/usr/home
+#mkdir -p %{buildroot}/opt/usr/home/owner
+#mkdir -p %{buildroot}/opt/usr/home/owner/models
 cp -rf config/esplusplayer.ini %{buildroot}%TZ_SYS_RO_ETC/multimedia/esplusplayer.ini
 
+%if 0%{?vd_gcov:1}
+mkdir -p %{buildroot}%{_datadir}/gcov/obj
+find . \( -name '*.gcno' -o -name '*.cpp' -o -name '*.c' -o -name '*.hpp' -o -name '*.h' \) ! -path "./ut/*" ! -path "./test/*" ! -path "*/CompilerIdCXX/*" -exec cp --parents -r '{}' %{buildroot}%{_datadir}/gcov/obj ';'
+%endif
+
 %files
 %defattr(-,root,root,-)
 %manifest esplusplayer.manifest
 %license LICENSE.APLv2
 %{_libdir}/libespplayer-core.so
 %{_libdir}/libesplusplayer.so
+%if ("%{USE_MIXER}" == "yes")
+%{_libdir}/libmixer.so
+%endif
+
 %TZ_SYS_RO_ETC/multimedia/esplusplayer.ini
 
 %files devel
 %defattr(-,root,root,-)
+%{_includedir}/esplusplayer/*.h
+%{_includedir}/esplusplayer/types/*.h
 %{_includedir}/esplusplayer_capi/*.h
+%{_includedir}/mixer/*.h
+%{_includedir}/mixer_capi/*.h
 %{_pkgconfigdir}/esplusplayer.pc
 
+%files config
+%defattr(-,root,root,-)
+%manifest esplusplayer.manifest
+%license LICENSE.APLv2
+%TZ_SYS_RO_ETC/multimedia/esplusplayer.ini
+%attr(0775, owner,users) %TZ_SYS_RO_ETC/multimedia
+
+%if 0%{?vd_gcov:1}
+%files gcov
+%{_datadir}/gcov/*
+%endif
+
+%if %{with TIZEN_PUBLIC}
 %files tool
 %defattr(-,root,root,-)
 %{_bindir}/esplusplayer_test
 %if %{with ESPLUSPLAYER_UT}
 %{_bindir}/esplusplayer_ut
+%endif
 %defattr(-,root,root,-)
 %endif
+
index 9f8e3f8..dbd90f4 100644 (file)
@@ -1,2 +1,5 @@
 ADD_SUBDIRECTORY(plusplayer-core)
-ADD_SUBDIRECTORY(esplusplayer)
\ No newline at end of file
+ADD_SUBDIRECTORY(esplusplayer)
+IF(${USE_MIXER} STREQUAL "yes")
+ADD_SUBDIRECTORY(mixer)
+ENDIF(${USE_MIXER} STREQUAL "yes")
diff --git a/src/cpplint.py b/src/cpplint.py
new file mode 100644 (file)
index 0000000..52cb7d0
--- /dev/null
@@ -0,0 +1,6123 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Does google-lint on c++ files.
+
+The goal of this script is to identify places in the code that *may*
+be in non-compliance with google style.  It does not attempt to fix
+up these problems -- the point is to educate.  It does also not
+attempt to find all problems, or to ensure that everything it does
+find is legitimately a problem.
+
+In particular, we can get very confused by /* and // inside strings!
+We do a small hack, which is to ignore //'s with "'s after them on the
+same line, but it is far from perfect (in either direction).
+"""
+
+import codecs
+import copy
+import getopt
+import math  # for log
+import os
+import re
+import sre_compile
+import string
+import sys
+import unicodedata
+
+
+_USAGE = """
+Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
+                   [--counting=total|toplevel|detailed] [--root=subdir]
+                   [--linelength=digits] [--headers=x,y,...]
+        <file> [file] ...
+
+  The style guidelines this tries to follow are those in
+    https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
+
+  Every problem is given a confidence score from 1-5, with 5 meaning we are
+  certain of the problem, and 1 meaning it could be a legitimate construct.
+  This will miss some errors, and is not a substitute for a code review.
+
+  To suppress false-positive errors of a certain category, add a
+  'NOLINT(category)' comment to the line.  NOLINT or NOLINT(*)
+  suppresses errors of all categories on that line.
+
+  The files passed in will be linted; at least one file must be provided.
+  Default linted extensions are .cc, .cpp, .cu, .cuh and .h.  Change the
+  extensions with the --extensions flag.
+
+  Flags:
+
+    output=vs7
+      By default, the output is formatted to ease emacs parsing.  Visual Studio
+      compatible output (vs7) may also be used.  Other formats are unsupported.
+
+    verbose=#
+      Specify a number 0-5 to restrict errors to certain verbosity levels.
+
+    filter=-x,+y,...
+      Specify a comma-separated list of category-filters to apply: only
+      error messages whose category names pass the filters will be printed.
+      (Category names are printed with the message and look like
+      "[whitespace/indent]".)  Filters are evaluated left to right.
+      "-FOO" and "FOO" means "do not print categories that start with FOO".
+      "+FOO" means "do print categories that start with FOO".
+
+      Examples: --filter=-whitespace,+whitespace/braces
+                --filter=whitespace,runtime/printf,+runtime/printf_format
+                --filter=-,+build/include_what_you_use
+
+      To see a list of all the categories used in cpplint, pass no arg:
+         --filter=
+
+    counting=total|toplevel|detailed
+      The total number of errors found is always printed. If
+      'toplevel' is provided, then the count of errors in each of
+      the top-level categories like 'build' and 'whitespace' will
+      also be printed. If 'detailed' is provided, then a count
+      is provided for each category like 'build/class'.
+
+    root=subdir
+      The root directory used for deriving header guard CPP variable.
+      By default, the header guard CPP variable is calculated as the relative
+      path to the directory that contains .git, .hg, or .svn.  When this flag
+      is specified, the relative path is calculated from the specified
+      directory. If the specified directory does not exist, this flag is
+      ignored.
+
+      Examples:
+        Assuming that src/.git exists, the header guard CPP variables for
+        src/chrome/browser/ui/browser.h are:
+
+        No flag => CHROME_BROWSER_UI_BROWSER_H_
+        --root=chrome => BROWSER_UI_BROWSER_H_
+        --root=chrome/browser => UI_BROWSER_H_
+
+    linelength=digits
+      This is the allowed line length for the project. The default value is
+      80 characters.
+
+      Examples:
+        --linelength=120
+
+    extensions=extension,extension,...
+      The allowed file extensions that cpplint will check
+
+      Examples:
+        --extensions=hpp,cpp
+
+    headers=x,y,...
+      The header extensions that cpplint will treat as .h in checks. Values are
+      automatically added to --extensions list.
+
+      Examples:
+        --headers=hpp,hxx
+        --headers=hpp
+
+    cpplint.py supports per-directory configurations specified in CPPLINT.cfg
+    files. CPPLINT.cfg file can contain a number of key=value pairs.
+    Currently the following options are supported:
+
+      set noparent
+      filter=+filter1,-filter2,...
+      exclude_files=regex
+      linelength=80
+      root=subdir
+      headers=x,y,...
+
+    "set noparent" option prevents cpplint from traversing directory tree
+    upwards looking for more .cfg files in parent directories. This option
+    is usually placed in the top-level project directory.
+
+    The "filter" option is similar in function to --filter flag. It specifies
+    message filters in addition to the |_DEFAULT_FILTERS| and those specified
+    through --filter command-line flag.
+
+    "exclude_files" allows to specify a regular expression to be matched against
+    a file name. If the expression matches, the file is skipped and not run
+    through liner.
+
+    "linelength" allows to specify the allowed line length for the project.
+
+    The "root" option is similar in function to the --root flag (see example
+    above).
+    
+    The "headers" option is similar in function to the --headers flag 
+    (see example above).
+
+    CPPLINT.cfg has an effect on files in the same directory and all
+    sub-directories, unless overridden by a nested configuration file.
+
+      Example file:
+        filter=-build/include_order,+build/include_alpha
+        exclude_files=.*\.cc
+
+    The above example disables build/include_order warning and enables
+    build/include_alpha as well as excludes all .cc from being
+    processed by linter, in the current directory (where the .cfg
+    file is located) and all sub-directories.
+"""
+
+# We categorize each error message we print.  Here are the categories.
+# We want an explicit list so we can list them all in cpplint --filter=.
+# If you add a new error message with a new category, add it to the list
+# here!  cpplint_unittest.py should tell you if you forget to do this.
+_ERROR_CATEGORIES = [
+    'build/class',
+    'build/c++11',
+    'build/c++14',
+    'build/c++tr1',
+    'build/deprecated',
+    'build/endif_comment',
+    'build/explicit_make_pair',
+    'build/forward_decl',
+    'build/header_guard',
+    'build/include',
+    'build/include_alpha',
+    'build/include_order',
+    'build/include_what_you_use',
+    'build/namespaces',
+    'build/printf_format',
+    'build/storage_class',
+    'legal/copyright',
+    'readability/alt_tokens',
+    'readability/braces',
+    'readability/casting',
+    'readability/check',
+    'readability/constructors',
+    'readability/fn_size',
+    'readability/inheritance',
+    'readability/multiline_comment',
+    'readability/multiline_string',
+    'readability/namespace',
+    'readability/nolint',
+    'readability/nul',
+    'readability/strings',
+    'readability/todo',
+    'readability/utf8',
+    'runtime/arrays',
+    'runtime/casting',
+    'runtime/explicit',
+    'runtime/int',
+    'runtime/init',
+    'runtime/invalid_increment',
+    'runtime/member_string_references',
+    'runtime/memset',
+    'runtime/indentation_namespace',
+    'runtime/operator',
+    'runtime/printf',
+    'runtime/printf_format',
+    'runtime/references',
+    'runtime/string',
+    'runtime/threadsafe_fn',
+    'runtime/vlog',
+    'whitespace/blank_line',
+    'whitespace/braces',
+    'whitespace/comma',
+    'whitespace/comments',
+    'whitespace/empty_conditional_body',
+    'whitespace/empty_if_body',
+    'whitespace/empty_loop_body',
+    'whitespace/end_of_line',
+    'whitespace/ending_newline',
+    'whitespace/forcolon',
+    'whitespace/indent',
+    'whitespace/line_length',
+    'whitespace/newline',
+    'whitespace/operators',
+    'whitespace/parens',
+    'whitespace/semicolon',
+    'whitespace/tab',
+    'whitespace/todo',
+    ]
+
+# These error categories are no longer enforced by cpplint, but for backwards-
+# compatibility they may still appear in NOLINT comments.
+_LEGACY_ERROR_CATEGORIES = [
+    'readability/streams',
+    'readability/function',
+    ]
+
+# The default state of the category filter. This is overridden by the --filter=
+# flag. By default all errors are on, so only add here categories that should be
+# off by default (i.e., categories that must be enabled by the --filter= flags).
+# All entries here should start with a '-' or '+', as in the --filter= flag.
+_DEFAULT_FILTERS = ['-build/include_alpha']
+
+# The default list of categories suppressed for C (not C++) files.
+_DEFAULT_C_SUPPRESSED_CATEGORIES = [
+    'readability/casting',
+    ]
+
+# The default list of categories suppressed for Linux Kernel files.
+_DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
+    'whitespace/tab',
+    ]
+
+# We used to check for high-bit characters, but after much discussion we
+# decided those were OK, as long as they were in UTF-8 and didn't represent
+# hard-coded international strings, which belong in a separate i18n file.
+
+# C++ headers
+_CPP_HEADERS = frozenset([
+    # Legacy
+    'algobase.h',
+    'algo.h',
+    'alloc.h',
+    'builtinbuf.h',
+    'bvector.h',
+    'complex.h',
+    'defalloc.h',
+    'deque.h',
+    'editbuf.h',
+    'fstream.h',
+    'function.h',
+    'hash_map',
+    'hash_map.h',
+    'hash_set',
+    'hash_set.h',
+    'hashtable.h',
+    'heap.h',
+    'indstream.h',
+    'iomanip.h',
+    'iostream.h',
+    'istream.h',
+    'iterator.h',
+    'list.h',
+    'map.h',
+    'multimap.h',
+    'multiset.h',
+    'ostream.h',
+    'pair.h',
+    'parsestream.h',
+    'pfstream.h',
+    'procbuf.h',
+    'pthread_alloc',
+    'pthread_alloc.h',
+    'rope',
+    'rope.h',
+    'ropeimpl.h',
+    'set.h',
+    'slist',
+    'slist.h',
+    'stack.h',
+    'stdiostream.h',
+    'stl_alloc.h',
+    'stl_relops.h',
+    'streambuf.h',
+    'stream.h',
+    'strfile.h',
+    'strstream.h',
+    'tempbuf.h',
+    'tree.h',
+    'type_traits.h',
+    'vector.h',
+    # 17.6.1.2 C++ library headers
+    'algorithm',
+    'array',
+    'atomic',
+    'bitset',
+    'chrono',
+    'codecvt',
+    'complex',
+    'condition_variable',
+    'deque',
+    'exception',
+    'forward_list',
+    'fstream',
+    'functional',
+    'future',
+    'initializer_list',
+    'iomanip',
+    'ios',
+    'iosfwd',
+    'iostream',
+    'istream',
+    'iterator',
+    'limits',
+    'list',
+    'locale',
+    'map',
+    'memory',
+    'mutex',
+    'new',
+    'numeric',
+    'ostream',
+    'queue',
+    'random',
+    'ratio',
+    'regex',
+    'scoped_allocator',
+    'set',
+    'sstream',
+    'stack',
+    'stdexcept',
+    'streambuf',
+    'string',
+    'strstream',
+    'system_error',
+    'thread',
+    'tuple',
+    'typeindex',
+    'typeinfo',
+    'type_traits',
+    'unordered_map',
+    'unordered_set',
+    'utility',
+    'valarray',
+    'vector',
+    # 17.6.1.2 C++ headers for C library facilities
+    'cassert',
+    'ccomplex',
+    'cctype',
+    'cerrno',
+    'cfenv',
+    'cfloat',
+    'cinttypes',
+    'ciso646',
+    'climits',
+    'clocale',
+    'cmath',
+    'csetjmp',
+    'csignal',
+    'cstdalign',
+    'cstdarg',
+    'cstdbool',
+    'cstddef',
+    'cstdint',
+    'cstdio',
+    'cstdlib',
+    'cstring',
+    'ctgmath',
+    'ctime',
+    'cuchar',
+    'cwchar',
+    'cwctype',
+    ])
+
+# Type names
+_TYPES = re.compile(
+    r'^(?:'
+    # [dcl.type.simple]
+    r'(char(16_t|32_t)?)|wchar_t|'
+    r'bool|short|int|long|signed|unsigned|float|double|'
+    # [support.types]
+    r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|'
+    # [cstdint.syn]
+    r'(u?int(_fast|_least)?(8|16|32|64)_t)|'
+    r'(u?int(max|ptr)_t)|'
+    r')$')
+
+
+# These headers are excluded from [build/include] and [build/include_order]
+# checks:
+# - Anything not following google file name conventions (containing an
+#   uppercase character, such as Python.h or nsStringAPI.h, for example).
+# - Lua headers.
+_THIRD_PARTY_HEADERS_PATTERN = re.compile(
+    r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
+
+# Pattern for matching FileInfo.BaseName() against test file name
+_TEST_FILE_SUFFIX = r'(_test|_unittest|_regtest)$'
+
+# Pattern that matches only complete whitespace, possibly across multiple lines.
+_EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL)
+
+# Assertion macros.  These are defined in base/logging.h and
+# testing/base/public/gunit.h.
+_CHECK_MACROS = [
+    'DCHECK', 'CHECK',
+    'EXPECT_TRUE', 'ASSERT_TRUE',
+    'EXPECT_FALSE', 'ASSERT_FALSE',
+    ]
+
+# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
+_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
+
+for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
+                        ('>=', 'GE'), ('>', 'GT'),
+                        ('<=', 'LE'), ('<', 'LT')]:
+  _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
+  _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
+  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
+  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
+
+for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
+                            ('>=', 'LT'), ('>', 'LE'),
+                            ('<=', 'GT'), ('<', 'GE')]:
+  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
+  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
+
+# Alternative tokens and their replacements.  For full list, see section 2.5
+# Alternative tokens [lex.digraph] in the C++ standard.
+#
+# Digraphs (such as '%:') are not included here since it's a mess to
+# match those on a word boundary.
+_ALT_TOKEN_REPLACEMENT = {
+    'and': '&&',
+    'bitor': '|',
+    'or': '||',
+    'xor': '^',
+    'compl': '~',
+    'bitand': '&',
+    'and_eq': '&=',
+    'or_eq': '|=',
+    'xor_eq': '^=',
+    'not': '!',
+    'not_eq': '!='
+    }
+
+# Compile regular expression that matches all the above keywords.  The "[ =()]"
+# bit is meant to avoid matching these keywords outside of boolean expressions.
+#
+# False positives include C-style multi-line comments and multi-line strings
+# but those have always been troublesome for cpplint.
+_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
+    r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
+
+
+# These constants define types of headers for use with
+# _IncludeState.CheckNextIncludeOrder().
+_C_SYS_HEADER = 1
+_CPP_SYS_HEADER = 2
+_LIKELY_MY_HEADER = 3
+_POSSIBLE_MY_HEADER = 4
+_OTHER_HEADER = 5
+
+# These constants define the current inline assembly state
+_NO_ASM = 0       # Outside of inline assembly block
+_INSIDE_ASM = 1   # Inside inline assembly block
+_END_ASM = 2      # Last line of inline assembly block
+_BLOCK_ASM = 3    # The whole block is an inline assembly block
+
+# Match start of assembly blocks
+_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
+                        r'(?:\s+(volatile|__volatile__))?'
+                        r'\s*[{(]')
+
+# Match strings that indicate we're working on a C (not C++) file.
+_SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|'
+                            r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))')
+
+# Match string that indicates we're working on a Linux Kernel file.
+_SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)')
+
+_regexp_compile_cache = {}
+
+# {str, set(int)}: a map from error categories to sets of linenumbers
+# on which those errors are expected and should be suppressed.
+_error_suppressions = {}
+
+# The root directory used for deriving header guard CPP variable.
+# This is set by --root flag.
+_root = None
+
+# The allowed line length of files.
+# This is set by --linelength flag.
+_line_length = 80
+
+# The allowed extensions for file names
+# This is set by --extensions flag.
+_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh'])
+
+# Treat all headers starting with 'h' equally: .h, .hpp, .hxx etc.
+# This is set by --headers flag.
+_hpp_headers = set(['h'])
+
+# {str, bool}: a map from error categories to booleans which indicate if the
+# category should be suppressed for every line.
+_global_error_suppressions = {}
+
+def ProcessHppHeadersOption(val):
+  global _hpp_headers
+  try:
+    _hpp_headers = set(val.split(','))
+    # Automatically append to extensions list so it does not have to be set 2 times
+    _valid_extensions.update(_hpp_headers)
+  except ValueError:
+    PrintUsage('Header extensions must be comma seperated list.')
+
+def IsHeaderExtension(file_extension):
+  return file_extension in _hpp_headers
+
+def ParseNolintSuppressions(filename, raw_line, linenum, error):
+  """Updates the global list of line error-suppressions.
+
+  Parses any NOLINT comments on the current line, updating the global
+  error_suppressions store.  Reports an error if the NOLINT comment
+  was malformed.
+
+  Args:
+    filename: str, the name of the input file.
+    raw_line: str, the line of input text, with comments.
+    linenum: int, the number of the current line.
+    error: function, an error handler.
+  """
+  matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
+  if matched:
+    if matched.group(1):
+      suppressed_line = linenum + 1
+    else:
+      suppressed_line = linenum
+    category = matched.group(2)
+    if category in (None, '(*)'):  # => "suppress all"
+      _error_suppressions.setdefault(None, set()).add(suppressed_line)
+    else:
+      if category.startswith('(') and category.endswith(')'):
+        category = category[1:-1]
+        if category in _ERROR_CATEGORIES:
+          _error_suppressions.setdefault(category, set()).add(suppressed_line)
+        elif category not in _LEGACY_ERROR_CATEGORIES:
+          error(filename, linenum, 'readability/nolint', 5,
+                'Unknown NOLINT error category: %s' % category)
+
+
+def ProcessGlobalSuppresions(lines):
+  """Updates the list of global error suppressions.
+
+  Parses any lint directives in the file that have global effect.
+
+  Args:
+    lines: An array of strings, each representing a line of the file, with the
+           last element being empty if the file is terminated with a newline.
+  """
+  for line in lines:
+    if _SEARCH_C_FILE.search(line):
+      for category in _DEFAULT_C_SUPPRESSED_CATEGORIES:
+        _global_error_suppressions[category] = True
+    if _SEARCH_KERNEL_FILE.search(line):
+      for category in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES:
+        _global_error_suppressions[category] = True
+
+
+def ResetNolintSuppressions():
+  """Resets the set of NOLINT suppressions to empty."""
+  _error_suppressions.clear()
+  _global_error_suppressions.clear()
+
+
+def IsErrorSuppressedByNolint(category, linenum):
+  """Returns true if the specified error category is suppressed on this line.
+
+  Consults the global error_suppressions map populated by
+  ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions.
+
+  Args:
+    category: str, the category of the error.
+    linenum: int, the current line number.
+  Returns:
+    bool, True iff the error should be suppressed due to a NOLINT comment or
+    global suppression.
+  """
+  return (_global_error_suppressions.get(category, False) or
+          linenum in _error_suppressions.get(category, set()) or
+          linenum in _error_suppressions.get(None, set()))
+
+
+def Match(pattern, s):
+  """Matches the string with the pattern, caching the compiled regexp."""
+  # The regexp compilation caching is inlined in both Match and Search for
+  # performance reasons; factoring it out into a separate function turns out
+  # to be noticeably expensive.
+  if pattern not in _regexp_compile_cache:
+    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+  return _regexp_compile_cache[pattern].match(s)
+
+
+def ReplaceAll(pattern, rep, s):
+  """Replaces instances of pattern in a string with a replacement.
+
+  The compiled regex is kept in a cache shared by Match and Search.
+
+  Args:
+    pattern: regex pattern
+    rep: replacement text
+    s: search string
+
+  Returns:
+    string with replacements made (or original string if no replacements)
+  """
+  if pattern not in _regexp_compile_cache:
+    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+  return _regexp_compile_cache[pattern].sub(rep, s)
+
+
+def Search(pattern, s):
+  """Searches the string for the pattern, caching the compiled regexp."""
+  if pattern not in _regexp_compile_cache:
+    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
+  return _regexp_compile_cache[pattern].search(s)
+
+
+def _IsSourceExtension(s):
+  """File extension (excluding dot) matches a source file extension."""
+  return s in ('c', 'cc', 'cpp', 'cxx')
+
+
+class _IncludeState(object):
+  """Tracks line numbers for includes, and the order in which includes appear.
+
+  include_list contains list of lists of (header, line number) pairs.
+  It's a lists of lists rather than just one flat list to make it
+  easier to update across preprocessor boundaries.
+
+  Call CheckNextIncludeOrder() once for each header in the file, passing
+  in the type constants defined above. Calls in an illegal order will
+  raise an _IncludeError with an appropriate error message.
+
+  """
+  # self._section will move monotonically through this set. If it ever
+  # needs to move backwards, CheckNextIncludeOrder will raise an error.
+  _INITIAL_SECTION = 0
+  _MY_H_SECTION = 1
+  _C_SECTION = 2
+  _CPP_SECTION = 3
+  _OTHER_H_SECTION = 4
+
+  _TYPE_NAMES = {
+      _C_SYS_HEADER: 'C system header',
+      _CPP_SYS_HEADER: 'C++ system header',
+      _LIKELY_MY_HEADER: 'header this file implements',
+      _POSSIBLE_MY_HEADER: 'header this file may implement',
+      _OTHER_HEADER: 'other header',
+      }
+  _SECTION_NAMES = {
+      _INITIAL_SECTION: "... nothing. (This can't be an error.)",
+      _MY_H_SECTION: 'a header this file implements',
+      _C_SECTION: 'C system header',
+      _CPP_SECTION: 'C++ system header',
+      _OTHER_H_SECTION: 'other header',
+      }
+
+  def __init__(self):
+    self.include_list = [[]]
+    self.ResetSection('')
+
+  def FindHeader(self, header):
+    """Check if a header has already been included.
+
+    Args:
+      header: header to check.
+    Returns:
+      Line number of previous occurrence, or -1 if the header has not
+      been seen before.
+    """
+    for section_list in self.include_list:
+      for f in section_list:
+        if f[0] == header:
+          return f[1]
+    return -1
+
+  def ResetSection(self, directive):
+    """Reset section checking for preprocessor directive.
+
+    Args:
+      directive: preprocessor directive (e.g. "if", "else").
+    """
+    # The name of the current section.
+    self._section = self._INITIAL_SECTION
+    # The path of last found header.
+    self._last_header = ''
+
+    # Update list of includes.  Note that we never pop from the
+    # include list.
+    if directive in ('if', 'ifdef', 'ifndef'):
+      self.include_list.append([])
+    elif directive in ('else', 'elif'):
+      self.include_list[-1] = []
+
+  def SetLastHeader(self, header_path):
+    self._last_header = header_path
+
+  def CanonicalizeAlphabeticalOrder(self, header_path):
+    """Returns a path canonicalized for alphabetical comparison.
+
+    - replaces "-" with "_" so they both cmp the same.
+    - removes '-inl' since we don't require them to be after the main header.
+    - lowercase everything, just in case.
+
+    Args:
+      header_path: Path to be canonicalized.
+
+    Returns:
+      Canonicalized path.
+    """
+    return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
+
+  def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
+    """Check if a header is in alphabetical order with the previous header.
+
+    Args:
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      header_path: Canonicalized header to be checked.
+
+    Returns:
+      Returns true if the header is in alphabetical order.
+    """
+    # If previous section is different from current section, _last_header will
+    # be reset to empty string, so it's always less than current header.
+    #
+    # If previous line was a blank line, assume that the headers are
+    # intentionally sorted the way they are.
+    if (self._last_header > header_path and
+        Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
+      return False
+    return True
+
+  def CheckNextIncludeOrder(self, header_type):
+    """Returns a non-empty error message if the next header is out of order.
+
+    This function also updates the internal state to be ready to check
+    the next include.
+
+    Args:
+      header_type: One of the _XXX_HEADER constants defined above.
+
+    Returns:
+      The empty string if the header is in the right order, or an
+      error message describing what's wrong.
+
+    """
+    error_message = ('Found %s after %s' %
+                     (self._TYPE_NAMES[header_type],
+                      self._SECTION_NAMES[self._section]))
+
+    last_section = self._section
+
+    if header_type == _C_SYS_HEADER:
+      if self._section <= self._C_SECTION:
+        self._section = self._C_SECTION
+      else:
+        self._last_header = ''
+        return error_message
+    elif header_type == _CPP_SYS_HEADER:
+      if self._section <= self._CPP_SECTION:
+        self._section = self._CPP_SECTION
+      else:
+        self._last_header = ''
+        return error_message
+    elif header_type == _LIKELY_MY_HEADER:
+      if self._section <= self._MY_H_SECTION:
+        self._section = self._MY_H_SECTION
+      else:
+        self._section = self._OTHER_H_SECTION
+    elif header_type == _POSSIBLE_MY_HEADER:
+      if self._section <= self._MY_H_SECTION:
+        self._section = self._MY_H_SECTION
+      else:
+        # This will always be the fallback because we're not sure
+        # enough that the header is associated with this file.
+        self._section = self._OTHER_H_SECTION
+    else:
+      assert header_type == _OTHER_HEADER
+      self._section = self._OTHER_H_SECTION
+
+    if last_section != self._section:
+      self._last_header = ''
+
+    return ''
+
+
+class _CppLintState(object):
+  """Maintains module-wide state.."""
+
+  def __init__(self):
+    self.verbose_level = 1  # global setting.
+    self.error_count = 0    # global count of reported errors
+    # filters to apply when emitting error messages
+    self.filters = _DEFAULT_FILTERS[:]
+    # backup of filter list. Used to restore the state after each file.
+    self._filters_backup = self.filters[:]
+    self.counting = 'total'  # In what way are we counting errors?
+    self.errors_by_category = {}  # string to int dict storing error counts
+
+    # output format:
+    # "emacs" - format that emacs can parse (default)
+    # "vs7" - format that Microsoft Visual Studio 7 can parse
+    self.output_format = 'emacs'
+
+  def SetOutputFormat(self, output_format):
+    """Sets the output format for errors."""
+    self.output_format = output_format
+
+  def SetVerboseLevel(self, level):
+    """Sets the module's verbosity, and returns the previous setting."""
+    last_verbose_level = self.verbose_level
+    self.verbose_level = level
+    return last_verbose_level
+
+  def SetCountingStyle(self, counting_style):
+    """Sets the module's counting options."""
+    self.counting = counting_style
+
+  def SetFilters(self, filters):
+    """Sets the error-message filters.
+
+    These filters are applied when deciding whether to emit a given
+    error message.
+
+    Args:
+      filters: A string of comma-separated filters (eg "+whitespace/indent").
+               Each filter should start with + or -; else we die.
+
+    Raises:
+      ValueError: The comma-separated filters did not all start with '+' or '-'.
+                  E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
+    """
+    # Default filters always have less priority than the flag ones.
+    self.filters = _DEFAULT_FILTERS[:]
+    self.AddFilters(filters)
+
+  def AddFilters(self, filters):
+    """ Adds more filters to the existing list of error-message filters. """
+    for filt in filters.split(','):
+      clean_filt = filt.strip()
+      if clean_filt:
+        self.filters.append(clean_filt)
+    for filt in self.filters:
+      if not (filt.startswith('+') or filt.startswith('-')):
+        raise ValueError('Every filter in --filters must start with + or -'
+                         ' (%s does not)' % filt)
+
+  def BackupFilters(self):
+    """ Saves the current filter list to backup storage."""
+    self._filters_backup = self.filters[:]
+
+  def RestoreFilters(self):
+    """ Restores filters previously backed up."""
+    self.filters = self._filters_backup[:]
+
+  def ResetErrorCounts(self):
+    """Sets the module's error statistic back to zero."""
+    self.error_count = 0
+    self.errors_by_category = {}
+
+  def IncrementErrorCount(self, category):
+    """Bumps the module's error statistic."""
+    self.error_count += 1
+    if self.counting in ('toplevel', 'detailed'):
+      if self.counting != 'detailed':
+        category = category.split('/')[0]
+      if category not in self.errors_by_category:
+        self.errors_by_category[category] = 0
+      self.errors_by_category[category] += 1
+
+  def PrintErrorCounts(self):
+    """Print a summary of errors by category, and the total."""
+    for category, count in self.errors_by_category.iteritems():
+      sys.stderr.write('Category \'%s\' errors found: %d\n' %
+                       (category, count))
+    sys.stdout.write('Total errors found: %d\n' % self.error_count)
+
+_cpplint_state = _CppLintState()
+
+
+def _OutputFormat():
+  """Gets the module's output format."""
+  return _cpplint_state.output_format
+
+
+def _SetOutputFormat(output_format):
+  """Sets the module's output format."""
+  _cpplint_state.SetOutputFormat(output_format)
+
+
+def _VerboseLevel():
+  """Returns the module's verbosity setting."""
+  return _cpplint_state.verbose_level
+
+
+def _SetVerboseLevel(level):
+  """Sets the module's verbosity, and returns the previous setting."""
+  return _cpplint_state.SetVerboseLevel(level)
+
+
+def _SetCountingStyle(level):
+  """Sets the module's counting options."""
+  _cpplint_state.SetCountingStyle(level)
+
+
+def _Filters():
+  """Returns the module's list of output filters, as a list."""
+  return _cpplint_state.filters
+
+
+def _SetFilters(filters):
+  """Sets the module's error-message filters.
+
+  These filters are applied when deciding whether to emit a given
+  error message.
+
+  Args:
+    filters: A string of comma-separated filters (eg "whitespace/indent").
+             Each filter should start with + or -; else we die.
+  """
+  _cpplint_state.SetFilters(filters)
+
+def _AddFilters(filters):
+  """Adds more filter overrides.
+
+  Unlike _SetFilters, this function does not reset the current list of filters
+  available.
+
+  Args:
+    filters: A string of comma-separated filters (eg "whitespace/indent").
+             Each filter should start with + or -; else we die.
+  """
+  _cpplint_state.AddFilters(filters)
+
+def _BackupFilters():
+  """ Saves the current filter list to backup storage."""
+  _cpplint_state.BackupFilters()
+
+def _RestoreFilters():
+  """ Restores filters previously backed up."""
+  _cpplint_state.RestoreFilters()
+
+class _FunctionState(object):
+  """Tracks current function name and the number of lines in its body."""
+
+  _NORMAL_TRIGGER = 250  # for --v=0, 500 for --v=1, etc.
+  _TEST_TRIGGER = 400    # about 50% more than _NORMAL_TRIGGER.
+
+  def __init__(self):
+    self.in_a_function = False
+    self.lines_in_function = 0
+    self.current_function = ''
+
+  def Begin(self, function_name):
+    """Start analyzing function body.
+
+    Args:
+      function_name: The name of the function being tracked.
+    """
+    self.in_a_function = True
+    self.lines_in_function = 0
+    self.current_function = function_name
+
+  def Count(self):
+    """Count line in current function body."""
+    if self.in_a_function:
+      self.lines_in_function += 1
+
+  def Check(self, error, filename, linenum):
+    """Report if too many lines in function body.
+
+    Args:
+      error: The function to call with any errors found.
+      filename: The name of the current file.
+      linenum: The number of the line to check.
+    """
+    if not self.in_a_function:
+      return
+
+    if Match(r'T(EST|est)', self.current_function):
+      base_trigger = self._TEST_TRIGGER
+    else:
+      base_trigger = self._NORMAL_TRIGGER
+    trigger = base_trigger * 2**_VerboseLevel()
+
+    if self.lines_in_function > trigger:
+      error_level = int(math.log(self.lines_in_function / base_trigger, 2))
+      # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
+      if error_level > 5:
+        error_level = 5
+      error(filename, linenum, 'readability/fn_size', error_level,
+            'Small and focused functions are preferred:'
+            ' %s has %d non-comment lines'
+            ' (error triggered by exceeding %d lines).'  % (
+                self.current_function, self.lines_in_function, trigger))
+
+  def End(self):
+    """Stop analyzing function body."""
+    self.in_a_function = False
+
+
+class _IncludeError(Exception):
+  """Indicates a problem with the include order in a file."""
+  pass
+
+
+class FileInfo(object):
+  """Provides utility functions for filenames.
+
+  FileInfo provides easy access to the components of a file's path
+  relative to the project root.
+  """
+
+  def __init__(self, filename):
+    self._filename = filename
+
+  def FullName(self):
+    """Make Windows paths like Unix."""
+    return os.path.abspath(self._filename).replace('\\', '/')
+
+  def RepositoryName(self):
+    """FullName after removing the local path to the repository.
+
+    If we have a real absolute path name here we can try to do something smart:
+    detecting the root of the checkout and truncating /path/to/checkout from
+    the name so that we get header guards that don't include things like
+    "C:\Documents and Settings\..." or "/home/username/..." in them and thus
+    people on different computers who have checked the source out to different
+    locations won't see bogus errors.
+    """
+    fullname = self.FullName()
+
+    if os.path.exists(fullname):
+      project_dir = os.path.dirname(fullname)
+
+      if os.path.exists(os.path.join(project_dir, ".svn")):
+        # If there's a .svn file in the current directory, we recursively look
+        # up the directory tree for the top of the SVN checkout
+        root_dir = project_dir
+        one_up_dir = os.path.dirname(root_dir)
+        while os.path.exists(os.path.join(one_up_dir, ".svn")):
+          root_dir = os.path.dirname(root_dir)
+          one_up_dir = os.path.dirname(one_up_dir)
+
+        prefix = os.path.commonprefix([root_dir, project_dir])
+        return fullname[len(prefix) + 1:]
+
+      # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
+      # searching up from the current path.
+      root_dir = current_dir = os.path.dirname(fullname)
+      while current_dir != os.path.dirname(current_dir):
+        if (os.path.exists(os.path.join(current_dir, ".git")) or
+            os.path.exists(os.path.join(current_dir, ".hg")) or
+            os.path.exists(os.path.join(current_dir, ".svn"))):
+          root_dir = current_dir
+        current_dir = os.path.dirname(current_dir)
+
+      if (os.path.exists(os.path.join(root_dir, ".git")) or
+          os.path.exists(os.path.join(root_dir, ".hg")) or
+          os.path.exists(os.path.join(root_dir, ".svn"))):
+        prefix = os.path.commonprefix([root_dir, project_dir])
+        return fullname[len(prefix) + 1:]
+
+    # Don't know what to do; header guard warnings may be wrong...
+    return fullname
+
+  def Split(self):
+    """Splits the file into the directory, basename, and extension.
+
+    For 'chrome/browser/browser.cc', Split() would
+    return ('chrome/browser', 'browser', '.cc')
+
+    Returns:
+      A tuple of (directory, basename, extension).
+    """
+
+    googlename = self.RepositoryName()
+    project, rest = os.path.split(googlename)
+    return (project,) + os.path.splitext(rest)
+
+  def BaseName(self):
+    """File base name - text after the final slash, before the final period."""
+    return self.Split()[1]
+
+  def Extension(self):
+    """File extension - text following the final period."""
+    return self.Split()[2]
+
+  def NoExtension(self):
+    """File has no source file extension."""
+    return '/'.join(self.Split()[0:2])
+
+  def IsSource(self):
+    """File has a source file extension."""
+    return _IsSourceExtension(self.Extension()[1:])
+
+
+def _ShouldPrintError(category, confidence, linenum):
+  """If confidence >= verbose, category passes filter and is not suppressed."""
+
+  # There are three ways we might decide not to print an error message:
+  # a "NOLINT(category)" comment appears in the source,
+  # the verbosity level isn't high enough, or the filters filter it out.
+  if IsErrorSuppressedByNolint(category, linenum):
+    return False
+
+  if confidence < _cpplint_state.verbose_level:
+    return False
+
+  is_filtered = False
+  for one_filter in _Filters():
+    if one_filter.startswith('-'):
+      if category.startswith(one_filter[1:]):
+        is_filtered = True
+    elif one_filter.startswith('+'):
+      if category.startswith(one_filter[1:]):
+        is_filtered = False
+    else:
+      assert False  # should have been checked for in SetFilter.
+  if is_filtered:
+    return False
+
+  return True
+
+
+def Error(filename, linenum, category, confidence, message):
+  """Logs the fact we've found a lint error.
+
+  We log where the error was found, and also our confidence in the error,
+  that is, how certain we are this is a legitimate style regression, and
+  not a misidentification or a use that's sometimes justified.
+
+  False positives can be suppressed by the use of
+  "cpplint(category)"  comments on the offending line.  These are
+  parsed into _error_suppressions.
+
+  Args:
+    filename: The name of the file containing the error.
+    linenum: The number of the line containing the error.
+    category: A string used to describe the "category" this bug
+      falls under: "whitespace", say, or "runtime".  Categories
+      may have a hierarchy separated by slashes: "whitespace/indent".
+    confidence: A number from 1-5 representing a confidence score for
+      the error, with 5 meaning that we are certain of the problem,
+      and 1 meaning that it could be a legitimate construct.
+    message: The error message.
+  """
+  if _ShouldPrintError(category, confidence, linenum):
+    _cpplint_state.IncrementErrorCount(category)
+    if _cpplint_state.output_format == 'vs7':
+      sys.stderr.write('%s(%s): error cpplint: [%s] %s [%d]\n' % (
+          filename, linenum, category, message, confidence))
+    elif _cpplint_state.output_format == 'eclipse':
+      sys.stderr.write('%s:%s: warning: %s  [%s] [%d]\n' % (
+          filename, linenum, message, category, confidence))
+    else:
+      sys.stderr.write('%s:%s:  %s  [%s] [%d]\n' % (
+          filename, linenum, message, category, confidence))
+
+
+# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
+_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
+    r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
+# Match a single C style comment on the same line.
+_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
+# Matches multi-line C style comments.
+# This RE is a little bit more complicated than one might expect, because we
+# have to take care of space removals tools so we can handle comments inside
+# statements better.
+# The current rule is: We only clear spaces from both sides when we're at the
+# end of the line. Otherwise, we try to remove spaces from the right side,
+# if this doesn't work we try on left side but only if there's a non-character
+# on the right.
+_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
+    r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
+    _RE_PATTERN_C_COMMENTS + r'\s+|' +
+    r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
+    _RE_PATTERN_C_COMMENTS + r')')
+
+
+def IsCppString(line):
+  """Does line terminate so, that the next symbol is in string constant.
+
+  This function does not consider single-line nor multi-line comments.
+
+  Args:
+    line: is a partial line of code starting from the 0..n.
+
+  Returns:
+    True, if next character appended to 'line' is inside a
+    string constant.
+  """
+
+  line = line.replace(r'\\', 'XX')  # after this, \\" does not match to \"
+  return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
+
+
+def CleanseRawStrings(raw_lines):
+  """Removes C++11 raw strings from lines.
+
+    Before:
+      static const char kData[] = R"(
+          multi-line string
+          )";
+
+    After:
+      static const char kData[] = ""
+          (replaced by blank line)
+          "";
+
+  Args:
+    raw_lines: list of raw lines.
+
+  Returns:
+    list of lines with C++11 raw strings replaced by empty strings.
+  """
+
+  delimiter = None
+  lines_without_raw_strings = []
+  for line in raw_lines:
+    if delimiter:
+      # Inside a raw string, look for the end
+      end = line.find(delimiter)
+      if end >= 0:
+        # Found the end of the string, match leading space for this
+        # line and resume copying the original lines, and also insert
+        # a "" on the last line.
+        leading_space = Match(r'^(\s*)\S', line)
+        line = leading_space.group(1) + '""' + line[end + len(delimiter):]
+        delimiter = None
+      else:
+        # Haven't found the end yet, append a blank line.
+        line = '""'
+
+    # Look for beginning of a raw string, and replace them with
+    # empty strings.  This is done in a loop to handle multiple raw
+    # strings on the same line.
+    while delimiter is None:
+      # Look for beginning of a raw string.
+      # See 2.14.15 [lex.string] for syntax.
+      #
+      # Once we have matched a raw string, we check the prefix of the
+      # line to make sure that the line is not part of a single line
+      # comment.  It's done this way because we remove raw strings
+      # before removing comments as opposed to removing comments
+      # before removing raw strings.  This is because there are some
+      # cpplint checks that requires the comments to be preserved, but
+      # we don't want to check comments that are inside raw strings.
+      matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
+      if (matched and
+          not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
+                    matched.group(1))):
+        delimiter = ')' + matched.group(2) + '"'
+
+        end = matched.group(3).find(delimiter)
+        if end >= 0:
+          # Raw string ended on same line
+          line = (matched.group(1) + '""' +
+                  matched.group(3)[end + len(delimiter):])
+          delimiter = None
+        else:
+          # Start of a multi-line raw string
+          line = matched.group(1) + '""'
+      else:
+        break
+
+    lines_without_raw_strings.append(line)
+
+  # TODO(unknown): if delimiter is not None here, we might want to
+  # emit a warning for unterminated string.
+  return lines_without_raw_strings
+
+
+def FindNextMultiLineCommentStart(lines, lineix):
+  """Find the beginning marker for a multiline comment."""
+  while lineix < len(lines):
+    if lines[lineix].strip().startswith('/*'):
+      # Only return this marker if the comment goes beyond this line
+      if lines[lineix].strip().find('*/', 2) < 0:
+        return lineix
+    lineix += 1
+  return len(lines)
+
+
+def FindNextMultiLineCommentEnd(lines, lineix):
+  """We are inside a comment, find the end marker."""
+  while lineix < len(lines):
+    if lines[lineix].strip().endswith('*/'):
+      return lineix
+    lineix += 1
+  return len(lines)
+
+
+def RemoveMultiLineCommentsFromRange(lines, begin, end):
+  """Clears a range of lines for multi-line comments."""
+  # Having // dummy comments makes the lines non-empty, so we will not get
+  # unnecessary blank line warnings later in the code.
+  for i in range(begin, end):
+    lines[i] = '/**/'
+
+
+def RemoveMultiLineComments(filename, lines, error):
+  """Removes multiline (c-style) comments from lines."""
+  lineix = 0
+  while lineix < len(lines):
+    lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
+    if lineix_begin >= len(lines):
+      return
+    lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
+    if lineix_end >= len(lines):
+      error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
+            'Could not find end of multi-line comment')
+      return
+    RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
+    lineix = lineix_end + 1
+
+
+def CleanseComments(line):
+  """Removes //-comments and single-line C-style /* */ comments.
+
+  Args:
+    line: A line of C++ source.
+
+  Returns:
+    The line with single-line comments removed.
+  """
+  commentpos = line.find('//')
+  if commentpos != -1 and not IsCppString(line[:commentpos]):
+    line = line[:commentpos].rstrip()
+  # get rid of /* ... */
+  return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
+
+
+class CleansedLines(object):
+  """Holds 4 copies of all lines with different preprocessing applied to them.
+
+  1) elided member contains lines without strings and comments.
+  2) lines member contains lines without comments.
+  3) raw_lines member contains all the lines without processing.
+  4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
+     strings removed.
+  All these members are of <type 'list'>, and of the same length.
+  """
+
+  def __init__(self, lines):
+    self.elided = []
+    self.lines = []
+    self.raw_lines = lines
+    self.num_lines = len(lines)
+    self.lines_without_raw_strings = CleanseRawStrings(lines)
+    for linenum in range(len(self.lines_without_raw_strings)):
+      self.lines.append(CleanseComments(
+          self.lines_without_raw_strings[linenum]))
+      elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
+      self.elided.append(CleanseComments(elided))
+
+  def NumLines(self):
+    """Returns the number of lines represented."""
+    return self.num_lines
+
+  @staticmethod
+  def _CollapseStrings(elided):
+    """Collapses strings and chars on a line to simple "" or '' blocks.
+
+    We nix strings first so we're not fooled by text like '"http://"'
+
+    Args:
+      elided: The line being processed.
+
+    Returns:
+      The line with collapsed strings.
+    """
+    if _RE_PATTERN_INCLUDE.match(elided):
+      return elided
+
+    # Remove escaped characters first to make quote/single quote collapsing
+    # basic.  Things that look like escaped characters shouldn't occur
+    # outside of strings and chars.
+    elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
+
+    # Replace quoted strings and digit separators.  Both single quotes
+    # and double quotes are processed in the same loop, otherwise
+    # nested quotes wouldn't work.
+    collapsed = ''
+    while True:
+      # Find the first quote character
+      match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
+      if not match:
+        collapsed += elided
+        break
+      head, quote, tail = match.groups()
+
+      if quote == '"':
+        # Collapse double quoted strings
+        second_quote = tail.find('"')
+        if second_quote >= 0:
+          collapsed += head + '""'
+          elided = tail[second_quote + 1:]
+        else:
+          # Unmatched double quote, don't bother processing the rest
+          # of the line since this is probably a multiline string.
+          collapsed += elided
+          break
+      else:
+        # Found single quote, check nearby text to eliminate digit separators.
+        #
+        # There is no special handling for floating point here, because
+        # the integer/fractional/exponent parts would all be parsed
+        # correctly as long as there are digits on both sides of the
+        # separator.  So we are fine as long as we don't see something
+        # like "0.'3" (gcc 4.9.0 will not allow this literal).
+        if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
+          match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
+          collapsed += head + match_literal.group(1).replace("'", '')
+          elided = match_literal.group(2)
+        else:
+          second_quote = tail.find('\'')
+          if second_quote >= 0:
+            collapsed += head + "''"
+            elided = tail[second_quote + 1:]
+          else:
+            # Unmatched single quote
+            collapsed += elided
+            break
+
+    return collapsed
+
+
+def FindEndOfExpressionInLine(line, startpos, stack):
+  """Find the position just after the end of current parenthesized expression.
+
+  Args:
+    line: a CleansedLines line.
+    startpos: start searching at this position.
+    stack: nesting stack at startpos.
+
+  Returns:
+    On finding matching end: (index just after matching end, None)
+    On finding an unclosed expression: (-1, None)
+    Otherwise: (-1, new stack at end of this line)
+  """
+  for i in xrange(startpos, len(line)):
+    char = line[i]
+    if char in '([{':
+      # Found start of parenthesized expression, push to expression stack
+      stack.append(char)
+    elif char == '<':
+      # Found potential start of template argument list
+      if i > 0 and line[i - 1] == '<':
+        # Left shift operator
+        if stack and stack[-1] == '<':
+          stack.pop()
+          if not stack:
+            return (-1, None)
+      elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
+        # operator<, don't add to stack
+        continue
+      else:
+        # Tentative start of template argument list
+        stack.append('<')
+    elif char in ')]}':
+      # Found end of parenthesized expression.
+      #
+      # If we are currently expecting a matching '>', the pending '<'
+      # must have been an operator.  Remove them from expression stack.
+      while stack and stack[-1] == '<':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+      if ((stack[-1] == '(' and char == ')') or
+          (stack[-1] == '[' and char == ']') or
+          (stack[-1] == '{' and char == '}')):
+        stack.pop()
+        if not stack:
+          return (i + 1, None)
+      else:
+        # Mismatched parentheses
+        return (-1, None)
+    elif char == '>':
+      # Found potential end of template argument list.
+
+      # Ignore "->" and operator functions
+      if (i > 0 and
+          (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
+        continue
+
+      # Pop the stack if there is a matching '<'.  Otherwise, ignore
+      # this '>' since it must be an operator.
+      if stack:
+        if stack[-1] == '<':
+          stack.pop()
+          if not stack:
+            return (i + 1, None)
+    elif char == ';':
+      # Found something that look like end of statements.  If we are currently
+      # expecting a '>', the matching '<' must have been an operator, since
+      # template argument list should not contain statements.
+      while stack and stack[-1] == '<':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+
+  # Did not find end of expression or unbalanced parentheses on this line
+  return (-1, stack)
+
+
+def CloseExpression(clean_lines, linenum, pos):
+  """If input points to ( or { or [ or <, finds the position that closes it.
+
+  If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
+  linenum/pos that correspond to the closing of the expression.
+
+  TODO(unknown): cpplint spends a fair bit of time matching parentheses.
+  Ideally we would want to index all opening and closing parentheses once
+  and have CloseExpression be just a simple lookup, but due to preprocessor
+  tricks, this is not so easy.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    pos: A position on the line.
+
+  Returns:
+    A tuple (line, linenum, pos) pointer *past* the closing brace, or
+    (line, len(lines), -1) if we never find a close.  Note we ignore
+    strings and comments when matching; and the line we return is the
+    'cleansed' line at linenum.
+  """
+
+  line = clean_lines.elided[linenum]
+  if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
+    return (line, clean_lines.NumLines(), -1)
+
+  # Check first line
+  (end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
+  if end_pos > -1:
+    return (line, linenum, end_pos)
+
+  # Continue scanning forward
+  while stack and linenum < clean_lines.NumLines() - 1:
+    linenum += 1
+    line = clean_lines.elided[linenum]
+    (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
+    if end_pos > -1:
+      return (line, linenum, end_pos)
+
+  # Did not find end of expression before end of file, give up
+  return (line, clean_lines.NumLines(), -1)
+
+
+def FindStartOfExpressionInLine(line, endpos, stack):
+  """Find position at the matching start of current expression.
+
+  This is almost the reverse of FindEndOfExpressionInLine, but note
+  that the input position and returned position differs by 1.
+
+  Args:
+    line: a CleansedLines line.
+    endpos: start searching at this position.
+    stack: nesting stack at endpos.
+
+  Returns:
+    On finding matching start: (index at matching start, None)
+    On finding an unclosed expression: (-1, None)
+    Otherwise: (-1, new stack at beginning of this line)
+  """
+  i = endpos
+  while i >= 0:
+    char = line[i]
+    if char in ')]}':
+      # Found end of expression, push to expression stack
+      stack.append(char)
+    elif char == '>':
+      # Found potential end of template argument list.
+      #
+      # Ignore it if it's a "->" or ">=" or "operator>"
+      if (i > 0 and
+          (line[i - 1] == '-' or
+           Match(r'\s>=\s', line[i - 1:]) or
+           Search(r'\boperator\s*$', line[0:i]))):
+        i -= 1
+      else:
+        stack.append('>')
+    elif char == '<':
+      # Found potential start of template argument list
+      if i > 0 and line[i - 1] == '<':
+        # Left shift operator
+        i -= 1
+      else:
+        # If there is a matching '>', we can pop the expression stack.
+        # Otherwise, ignore this '<' since it must be an operator.
+        if stack and stack[-1] == '>':
+          stack.pop()
+          if not stack:
+            return (i, None)
+    elif char in '([{':
+      # Found start of expression.
+      #
+      # If there are any unmatched '>' on the stack, they must be
+      # operators.  Remove those.
+      while stack and stack[-1] == '>':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+      if ((char == '(' and stack[-1] == ')') or
+          (char == '[' and stack[-1] == ']') or
+          (char == '{' and stack[-1] == '}')):
+        stack.pop()
+        if not stack:
+          return (i, None)
+      else:
+        # Mismatched parentheses
+        return (-1, None)
+    elif char == ';':
+      # Found something that look like end of statements.  If we are currently
+      # expecting a '<', the matching '>' must have been an operator, since
+      # template argument list should not contain statements.
+      while stack and stack[-1] == '>':
+        stack.pop()
+      if not stack:
+        return (-1, None)
+
+    i -= 1
+
+  return (-1, stack)
+
+
+def ReverseCloseExpression(clean_lines, linenum, pos):
+  """If input points to ) or } or ] or >, finds the position that opens it.
+
+  If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
+  linenum/pos that correspond to the opening of the expression.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    pos: A position on the line.
+
+  Returns:
+    A tuple (line, linenum, pos) pointer *at* the opening brace, or
+    (line, 0, -1) if we never find the matching opening brace.  Note
+    we ignore strings and comments when matching; and the line we
+    return is the 'cleansed' line at linenum.
+  """
+  line = clean_lines.elided[linenum]
+  if line[pos] not in ')}]>':
+    return (line, 0, -1)
+
+  # Check last line
+  (start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
+  if start_pos > -1:
+    return (line, linenum, start_pos)
+
+  # Continue scanning backward
+  while stack and linenum > 0:
+    linenum -= 1
+    line = clean_lines.elided[linenum]
+    (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
+    if start_pos > -1:
+      return (line, linenum, start_pos)
+
+  # Did not find start of expression before beginning of file, give up
+  return (line, 0, -1)
+
+
+def CheckForCopyright(filename, lines, error):
+  """Logs an error if no Copyright message appears at the top of the file."""
+
+  # We'll say it should occur by line 10. Don't forget there's a
+  # dummy line at the front.
+  for line in xrange(1, min(len(lines), 11)):
+    if re.search(r'Copyright', lines[line], re.I): break
+  else:                       # means no copyright line was found
+    error(filename, 0, 'legal/copyright', 5,
+          'No copyright message found.  '
+          'You should have a line: "Copyright [year] <Copyright Owner>"')
+
+
+def GetIndentLevel(line):
+  """Return the number of leading spaces in line.
+
+  Args:
+    line: A string to check.
+
+  Returns:
+    An integer count of leading spaces, possibly zero.
+  """
+  indent = Match(r'^( *)\S', line)
+  if indent:
+    return len(indent.group(1))
+  else:
+    return 0
+
+
+def GetHeaderGuardCPPVariable(filename):
+  """Returns the CPP variable that should be used as a header guard.
+
+  Args:
+    filename: The name of a C++ header file.
+
+  Returns:
+    The CPP variable that should be used as a header guard in the
+    named file.
+
+  """
+
+  # Restores original filename in case that cpplint is invoked from Emacs's
+  # flymake.
+  filename = re.sub(r'_flymake\.h$', '.h', filename)
+  filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
+  # Replace 'c++' with 'cpp'.
+  filename = filename.replace('C++', 'cpp').replace('c++', 'cpp')
+
+  fileinfo = FileInfo(filename)
+  file_path_from_root = fileinfo.RepositoryName()
+  if _root:
+    suffix = os.sep
+    # On Windows using directory separator will leave us with
+    # "bogus escape error" unless we properly escape regex.
+    if suffix == '\\':
+      suffix += '\\'
+    file_path_from_root = re.sub('^' + _root + suffix, '', file_path_from_root)
+  return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
+
+
+def CheckForHeaderGuard(filename, clean_lines, error):
+  """Checks that the file contains a header guard.
+
+  Logs an error if no #ifndef header guard is present.  For other
+  headers, checks that the full pathname is used.
+
+  Args:
+    filename: The name of the C++ header file.
+    clean_lines: A CleansedLines instance containing the file.
+    error: The function to call with any errors found.
+  """
+
+  # Don't check for header guards if there are error suppression
+  # comments somewhere in this file.
+  #
+  # Because this is silencing a warning for a nonexistent line, we
+  # only support the very specific NOLINT(build/header_guard) syntax,
+  # and not the general NOLINT or NOLINT(*) syntax.
+  raw_lines = clean_lines.lines_without_raw_strings
+  for i in raw_lines:
+    if Search(r'//\s*NOLINT\(build/header_guard\)', i):
+      return
+
+  cppvar = GetHeaderGuardCPPVariable(filename)
+
+  ifndef = ''
+  ifndef_linenum = 0
+  define = ''
+  endif = ''
+  endif_linenum = 0
+  for linenum, line in enumerate(raw_lines):
+    linesplit = line.split()
+    if len(linesplit) >= 2:
+      # find the first occurrence of #ifndef and #define, save arg
+      if not ifndef and linesplit[0] == '#ifndef':
+        # set ifndef to the header guard presented on the #ifndef line.
+        ifndef = linesplit[1]
+        ifndef_linenum = linenum
+      if not define and linesplit[0] == '#define':
+        define = linesplit[1]
+    # find the last occurrence of #endif, save entire line
+    if line.startswith('#endif'):
+      endif = line
+      endif_linenum = linenum
+
+  if not ifndef or not define or ifndef != define:
+    error(filename, 0, 'build/header_guard', 5,
+          'No #ifndef header guard found, suggested CPP variable is: %s' %
+          cppvar)
+    return
+
+  # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
+  # for backward compatibility.
+  if ifndef != cppvar:
+    error_level = 0
+    if ifndef != cppvar + '_':
+      error_level = 5
+
+    ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
+                            error)
+    error(filename, ifndef_linenum, 'build/header_guard', error_level,
+          '#ifndef header guard has wrong style, please use: %s' % cppvar)
+
+  # Check for "//" comments on endif line.
+  ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
+                          error)
+  match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
+  if match:
+    if match.group(1) == '_':
+      # Issue low severity warning for deprecated double trailing underscore
+      error(filename, endif_linenum, 'build/header_guard', 0,
+            '#endif line should be "#endif  // %s"' % cppvar)
+    return
+
+  # Didn't find the corresponding "//" comment.  If this file does not
+  # contain any "//" comments at all, it could be that the compiler
+  # only wants "/**/" comments, look for those instead.
+  no_single_line_comments = True
+  for i in xrange(1, len(raw_lines) - 1):
+    line = raw_lines[i]
+    if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
+      no_single_line_comments = False
+      break
+
+  if no_single_line_comments:
+    match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
+    if match:
+      if match.group(1) == '_':
+        # Low severity warning for double trailing underscore
+        error(filename, endif_linenum, 'build/header_guard', 0,
+              '#endif line should be "#endif  /* %s */"' % cppvar)
+      return
+
+  # Didn't find anything
+  error(filename, endif_linenum, 'build/header_guard', 5,
+        '#endif line should be "#endif  // %s"' % cppvar)
+
+
+def CheckHeaderFileIncluded(filename, include_state, error):
+  """Logs an error if a .cc file does not include its header."""
+
+  # Do not check test files
+  fileinfo = FileInfo(filename)
+  if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
+    return
+
+  headerfile = filename[0:len(filename) - len(fileinfo.Extension())] + '.h'
+  if not os.path.exists(headerfile):
+    return
+  headername = FileInfo(headerfile).RepositoryName()
+  first_include = 0
+  for section_list in include_state.include_list:
+    for f in section_list:
+      if headername in f[0] or f[0] in headername:
+        return
+      if not first_include:
+        first_include = f[1]
+
+  error(filename, first_include, 'build/include', 5,
+        '%s should include its header file %s' % (fileinfo.RepositoryName(),
+                                                  headername))
+
+
+def CheckForBadCharacters(filename, lines, error):
+  """Logs an error for each line containing bad characters.
+
+  Two kinds of bad characters:
+
+  1. Unicode replacement characters: These indicate that either the file
+  contained invalid UTF-8 (likely) or Unicode replacement characters (which
+  it shouldn't).  Note that it's possible for this to throw off line
+  numbering if the invalid UTF-8 occurred adjacent to a newline.
+
+  2. NUL bytes.  These are problematic for some tools.
+
+  Args:
+    filename: The name of the current file.
+    lines: An array of strings, each representing a line of the file.
+    error: The function to call with any errors found.
+  """
+  for linenum, line in enumerate(lines):
+    if u'\ufffd' in line:
+      error(filename, linenum, 'readability/utf8', 5,
+            'Line contains invalid UTF-8 (or Unicode replacement character).')
+    if '\0' in line:
+      error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
+
+
+def CheckForNewlineAtEOF(filename, lines, error):
+  """Logs an error if there is no newline char at the end of the file.
+
+  Args:
+    filename: The name of the current file.
+    lines: An array of strings, each representing a line of the file.
+    error: The function to call with any errors found.
+  """
+
+  # The array lines() was created by adding two newlines to the
+  # original file (go figure), then splitting on \n.
+  # To verify that the file ends in \n, we just have to make sure the
+  # last-but-two element of lines() exists and is empty.
+  if len(lines) < 3 or lines[-2]:
+    error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
+          'Could not find a newline character at the end of the file.')
+
+
+def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
+  """Logs an error if we see /* ... */ or "..." that extend past one line.
+
+  /* ... */ comments are legit inside macros, for one line.
+  Otherwise, we prefer // comments, so it's ok to warn about the
+  other.  Likewise, it's ok for strings to extend across multiple
+  lines, as long as a line continuation character (backslash)
+  terminates each line. Although not currently prohibited by the C++
+  style guide, it's ugly and unnecessary. We don't do well with either
+  in this lint program, so we warn about both.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Remove all \\ (escaped backslashes) from the line. They are OK, and the
+  # second (escaped) slash may trigger later \" detection erroneously.
+  line = line.replace('\\\\', '')
+
+  if line.count('/*') > line.count('*/'):
+    error(filename, linenum, 'readability/multiline_comment', 5,
+          'Complex multi-line /*...*/-style comment found. '
+          'Lint may give bogus warnings.  '
+          'Consider replacing these with //-style comments, '
+          'with #if 0...#endif, '
+          'or with more clearly structured multi-line comments.')
+
+  if (line.count('"') - line.count('\\"')) % 2:
+    error(filename, linenum, 'readability/multiline_string', 5,
+          'Multi-line string ("...") found.  This lint script doesn\'t '
+          'do well with such strings, and may give bogus warnings.  '
+          'Use C++11 raw strings or concatenation instead.')
+
+
+# (non-threadsafe name, thread-safe alternative, validation pattern)
+#
+# The validation pattern is used to eliminate false positives such as:
+#  _rand();               // false positive due to substring match.
+#  ->rand();              // some member function rand().
+#  ACMRandom rand(seed);  // some variable named rand.
+#  ISAACRandom rand();    // another variable named rand.
+#
+# Basically we require the return value of these functions to be used
+# in some expression context on the same line by matching on some
+# operator before the function name.  This eliminates constructors and
+# member function calls.
+_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
+_THREADING_LIST = (
+    ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
+    ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
+    ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
+    ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
+    ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
+    ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
+    ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
+    ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
+    ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
+    ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
+    ('strtok(', 'strtok_r(',
+     _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
+    ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
+    )
+
+
+def CheckPosixThreading(filename, clean_lines, linenum, error):
+  """Checks for calls to thread-unsafe functions.
+
+  Much code has been originally written without consideration of
+  multi-threading. Also, engineers are relying on their old experience;
+  they have learned posix before threading extensions were added. These
+  tests guide the engineers to use thread-safe functions (when using
+  posix directly).
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
+    # Additional pattern matching check to confirm that this is the
+    # function we are looking for
+    if Search(pattern, line):
+      error(filename, linenum, 'runtime/threadsafe_fn', 2,
+            'Consider using ' + multithread_safe_func +
+            '...) instead of ' + single_thread_func +
+            '...) for improved thread safety.')
+
+
+def CheckVlogArguments(filename, clean_lines, linenum, error):
+  """Checks that VLOG() is only used for defining a logging level.
+
+  For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
+  VLOG(FATAL) are not.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
+    error(filename, linenum, 'runtime/vlog', 5,
+          'VLOG() should be used with numeric verbosity level.  '
+          'Use LOG() if you want symbolic severity levels.')
+
+# Matches invalid increment: *count++, which moves pointer instead of
+# incrementing a value.
+_RE_PATTERN_INVALID_INCREMENT = re.compile(
+    r'^\s*\*\w+(\+\+|--);')
+
+
+def CheckInvalidIncrement(filename, clean_lines, linenum, error):
+  """Checks for invalid increment *count++.
+
+  For example following function:
+  void increment_counter(int* count) {
+    *count++;
+  }
+  is invalid, because it effectively does count++, moving pointer, and should
+  be replaced with ++*count, (*count)++ or *count += 1.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  if _RE_PATTERN_INVALID_INCREMENT.match(line):
+    error(filename, linenum, 'runtime/invalid_increment', 5,
+          'Changing pointer instead of value (or unused value of operator*).')
+
+
+def IsMacroDefinition(clean_lines, linenum):
+  if Search(r'^#define', clean_lines[linenum]):
+    return True
+
+  if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
+    return True
+
+  return False
+
+
+def IsForwardClassDeclaration(clean_lines, linenum):
+  return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
+
+
+class _BlockInfo(object):
+  """Stores information about a generic block of code."""
+
+  def __init__(self, linenum, seen_open_brace):
+    self.starting_linenum = linenum
+    self.seen_open_brace = seen_open_brace
+    self.open_parentheses = 0
+    self.inline_asm = _NO_ASM
+    self.check_namespace_indentation = False
+
+  def CheckBegin(self, filename, clean_lines, linenum, error):
+    """Run checks that applies to text up to the opening brace.
+
+    This is mostly for checking the text after the class identifier
+    and the "{", usually where the base class is specified.  For other
+    blocks, there isn't much to check, so we always pass.
+
+    Args:
+      filename: The name of the current file.
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      error: The function to call with any errors found.
+    """
+    pass
+
+  def CheckEnd(self, filename, clean_lines, linenum, error):
+    """Run checks that applies to text after the closing brace.
+
+    This is mostly used for checking end of namespace comments.
+
+    Args:
+      filename: The name of the current file.
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      error: The function to call with any errors found.
+    """
+    pass
+
+  def IsBlockInfo(self):
+    """Returns true if this block is a _BlockInfo.
+
+    This is convenient for verifying that an object is an instance of
+    a _BlockInfo, but not an instance of any of the derived classes.
+
+    Returns:
+      True for this class, False for derived classes.
+    """
+    return self.__class__ == _BlockInfo
+
+
+class _ExternCInfo(_BlockInfo):
+  """Stores information about an 'extern "C"' block."""
+
+  def __init__(self, linenum):
+    _BlockInfo.__init__(self, linenum, True)
+
+
+class _ClassInfo(_BlockInfo):
+  """Stores information about a class."""
+
+  def __init__(self, name, class_or_struct, clean_lines, linenum):
+    _BlockInfo.__init__(self, linenum, False)
+    self.name = name
+    self.is_derived = False
+    self.check_namespace_indentation = True
+    if class_or_struct == 'struct':
+      self.access = 'public'
+      self.is_struct = True
+    else:
+      self.access = 'private'
+      self.is_struct = False
+
+    # Remember initial indentation level for this class.  Using raw_lines here
+    # instead of elided to account for leading comments.
+    self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
+
+    # Try to find the end of the class.  This will be confused by things like:
+    #   class A {
+    #   } *x = { ...
+    #
+    # But it's still good enough for CheckSectionSpacing.
+    self.last_line = 0
+    depth = 0
+    for i in range(linenum, clean_lines.NumLines()):
+      line = clean_lines.elided[i]
+      depth += line.count('{') - line.count('}')
+      if not depth:
+        self.last_line = i
+        break
+
+  def CheckBegin(self, filename, clean_lines, linenum, error):
+    # Look for a bare ':'
+    if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
+      self.is_derived = True
+
+  def CheckEnd(self, filename, clean_lines, linenum, error):
+    # If there is a DISALLOW macro, it should appear near the end of
+    # the class.
+    seen_last_thing_in_class = False
+    for i in xrange(linenum - 1, self.starting_linenum, -1):
+      match = Search(
+          r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
+          self.name + r'\)',
+          clean_lines.elided[i])
+      if match:
+        if seen_last_thing_in_class:
+          error(filename, i, 'readability/constructors', 3,
+                match.group(1) + ' should be the last thing in the class')
+        break
+
+      if not Match(r'^\s*$', clean_lines.elided[i]):
+        seen_last_thing_in_class = True
+
+    # Check that closing brace is aligned with beginning of the class.
+    # Only do this if the closing brace is indented by only whitespaces.
+    # This means we will not check single-line class definitions.
+    indent = Match(r'^( *)\}', clean_lines.elided[linenum])
+    if indent and len(indent.group(1)) != self.class_indent:
+      if self.is_struct:
+        parent = 'struct ' + self.name
+      else:
+        parent = 'class ' + self.name
+      error(filename, linenum, 'whitespace/indent', 3,
+            'Closing brace should be aligned with beginning of %s' % parent)
+
+
+class _NamespaceInfo(_BlockInfo):
+  """Stores information about a namespace."""
+
+  def __init__(self, name, linenum):
+    _BlockInfo.__init__(self, linenum, False)
+    self.name = name or ''
+    self.check_namespace_indentation = True
+
+  def CheckEnd(self, filename, clean_lines, linenum, error):
+    """Check end of namespace comments."""
+    line = clean_lines.raw_lines[linenum]
+
+    # Check how many lines is enclosed in this namespace.  Don't issue
+    # warning for missing namespace comments if there aren't enough
+    # lines.  However, do apply checks if there is already an end of
+    # namespace comment and it's incorrect.
+    #
+    # TODO(unknown): We always want to check end of namespace comments
+    # if a namespace is large, but sometimes we also want to apply the
+    # check if a short namespace contained nontrivial things (something
+    # other than forward declarations).  There is currently no logic on
+    # deciding what these nontrivial things are, so this check is
+    # triggered by namespace size only, which works most of the time.
+    if (linenum - self.starting_linenum < 10
+        and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
+      return
+
+    # Look for matching comment at end of namespace.
+    #
+    # Note that we accept C style "/* */" comments for terminating
+    # namespaces, so that code that terminate namespaces inside
+    # preprocessor macros can be cpplint clean.
+    #
+    # We also accept stuff like "// end of namespace <name>." with the
+    # period at the end.
+    #
+    # Besides these, we don't accept anything else, otherwise we might
+    # get false negatives when existing comment is a substring of the
+    # expected namespace.
+    if self.name:
+      # Named namespace
+      if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
+                    re.escape(self.name) + r'[\*/\.\\\s]*$'),
+                   line):
+        error(filename, linenum, 'readability/namespace', 5,
+              'Namespace should be terminated with "// namespace %s"' %
+              self.name)
+    else:
+      # Anonymous namespace
+      if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
+        # If "// namespace anonymous" or "// anonymous namespace (more text)",
+        # mention "// anonymous namespace" as an acceptable form
+        if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
+          error(filename, linenum, 'readability/namespace', 5,
+                'Anonymous namespace should be terminated with "// namespace"'
+                ' or "// anonymous namespace"')
+        else:
+          error(filename, linenum, 'readability/namespace', 5,
+                'Anonymous namespace should be terminated with "// namespace"')
+
+
+class _PreprocessorInfo(object):
+  """Stores checkpoints of nesting stacks when #if/#else is seen."""
+
+  def __init__(self, stack_before_if):
+    # The entire nesting stack before #if
+    self.stack_before_if = stack_before_if
+
+    # The entire nesting stack up to #else
+    self.stack_before_else = []
+
+    # Whether we have already seen #else or #elif
+    self.seen_else = False
+
+
+class NestingState(object):
+  """Holds states related to parsing braces."""
+
+  def __init__(self):
+    # Stack for tracking all braces.  An object is pushed whenever we
+    # see a "{", and popped when we see a "}".  Only 3 types of
+    # objects are possible:
+    # - _ClassInfo: a class or struct.
+    # - _NamespaceInfo: a namespace.
+    # - _BlockInfo: some other type of block.
+    self.stack = []
+
+    # Top of the previous stack before each Update().
+    #
+    # Because the nesting_stack is updated at the end of each line, we
+    # had to do some convoluted checks to find out what is the current
+    # scope at the beginning of the line.  This check is simplified by
+    # saving the previous top of nesting stack.
+    #
+    # We could save the full stack, but we only need the top.  Copying
+    # the full nesting stack would slow down cpplint by ~10%.
+    self.previous_stack_top = []
+
+    # Stack of _PreprocessorInfo objects.
+    self.pp_stack = []
+
+  def SeenOpenBrace(self):
+    """Check if we have seen the opening brace for the innermost block.
+
+    Returns:
+      True if we have seen the opening brace, False if the innermost
+      block is still expecting an opening brace.
+    """
+    return (not self.stack) or self.stack[-1].seen_open_brace
+
+  def InNamespaceBody(self):
+    """Check if we are currently one level inside a namespace body.
+
+    Returns:
+      True if top of the stack is a namespace block, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
+
+  def InExternC(self):
+    """Check if we are currently one level inside an 'extern "C"' block.
+
+    Returns:
+      True if top of the stack is an extern block, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _ExternCInfo)
+
+  def InClassDeclaration(self):
+    """Check if we are currently one level inside a class or struct declaration.
+
+    Returns:
+      True if top of the stack is a class/struct, False otherwise.
+    """
+    return self.stack and isinstance(self.stack[-1], _ClassInfo)
+
+  def InAsmBlock(self):
+    """Check if we are currently one level inside an inline ASM block.
+
+    Returns:
+      True if the top of the stack is a block containing inline ASM.
+    """
+    return self.stack and self.stack[-1].inline_asm != _NO_ASM
+
+  def InTemplateArgumentList(self, clean_lines, linenum, pos):
+    """Check if current position is inside template argument list.
+
+    Args:
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      pos: position just after the suspected template argument.
+    Returns:
+      True if (linenum, pos) is inside template arguments.
+    """
+    while linenum < clean_lines.NumLines():
+      # Find the earliest character that might indicate a template argument
+      line = clean_lines.elided[linenum]
+      match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
+      if not match:
+        linenum += 1
+        pos = 0
+        continue
+      token = match.group(1)
+      pos += len(match.group(0))
+
+      # These things do not look like template argument list:
+      #   class Suspect {
+      #   class Suspect x; }
+      if token in ('{', '}', ';'): return False
+
+      # These things look like template argument list:
+      #   template <class Suspect>
+      #   template <class Suspect = default_value>
+      #   template <class Suspect[]>
+      #   template <class Suspect...>
+      if token in ('>', '=', '[', ']', '.'): return True
+
+      # Check if token is an unmatched '<'.
+      # If not, move on to the next character.
+      if token != '<':
+        pos += 1
+        if pos >= len(line):
+          linenum += 1
+          pos = 0
+        continue
+
+      # We can't be sure if we just find a single '<', and need to
+      # find the matching '>'.
+      (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
+      if end_pos < 0:
+        # Not sure if template argument list or syntax error in file
+        return False
+      linenum = end_line
+      pos = end_pos
+    return False
+
+  def UpdatePreprocessor(self, line):
+    """Update preprocessor stack.
+
+    We need to handle preprocessors due to classes like this:
+      #ifdef SWIG
+      struct ResultDetailsPageElementExtensionPoint {
+      #else
+      struct ResultDetailsPageElementExtensionPoint : public Extension {
+      #endif
+
+    We make the following assumptions (good enough for most files):
+    - Preprocessor condition evaluates to true from #if up to first
+      #else/#elif/#endif.
+
+    - Preprocessor condition evaluates to false from #else/#elif up
+      to #endif.  We still perform lint checks on these lines, but
+      these do not affect nesting stack.
+
+    Args:
+      line: current line to check.
+    """
+    if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
+      # Beginning of #if block, save the nesting stack here.  The saved
+      # stack will allow us to restore the parsing state in the #else case.
+      self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
+    elif Match(r'^\s*#\s*(else|elif)\b', line):
+      # Beginning of #else block
+      if self.pp_stack:
+        if not self.pp_stack[-1].seen_else:
+          # This is the first #else or #elif block.  Remember the
+          # whole nesting stack up to this point.  This is what we
+          # keep after the #endif.
+          self.pp_stack[-1].seen_else = True
+          self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
+
+        # Restore the stack to how it was before the #if
+        self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
+      else:
+        # TODO(unknown): unexpected #else, issue warning?
+        pass
+    elif Match(r'^\s*#\s*endif\b', line):
+      # End of #if or #else blocks.
+      if self.pp_stack:
+        # If we saw an #else, we will need to restore the nesting
+        # stack to its former state before the #else, otherwise we
+        # will just continue from where we left off.
+        if self.pp_stack[-1].seen_else:
+          # Here we can just use a shallow copy since we are the last
+          # reference to it.
+          self.stack = self.pp_stack[-1].stack_before_else
+        # Drop the corresponding #if
+        self.pp_stack.pop()
+      else:
+        # TODO(unknown): unexpected #endif, issue warning?
+        pass
+
+  # TODO(unknown): Update() is too long, but we will refactor later.
+  def Update(self, filename, clean_lines, linenum, error):
+    """Update nesting state with current line.
+
+    Args:
+      filename: The name of the current file.
+      clean_lines: A CleansedLines instance containing the file.
+      linenum: The number of the line to check.
+      error: The function to call with any errors found.
+    """
+    line = clean_lines.elided[linenum]
+
+    # Remember top of the previous nesting stack.
+    #
+    # The stack is always pushed/popped and not modified in place, so
+    # we can just do a shallow copy instead of copy.deepcopy.  Using
+    # deepcopy would slow down cpplint by ~28%.
+    if self.stack:
+      self.previous_stack_top = self.stack[-1]
+    else:
+      self.previous_stack_top = None
+
+    # Update pp_stack
+    self.UpdatePreprocessor(line)
+
+    # Count parentheses.  This is to avoid adding struct arguments to
+    # the nesting stack.
+    if self.stack:
+      inner_block = self.stack[-1]
+      depth_change = line.count('(') - line.count(')')
+      inner_block.open_parentheses += depth_change
+
+      # Also check if we are starting or ending an inline assembly block.
+      if inner_block.inline_asm in (_NO_ASM, _END_ASM):
+        if (depth_change != 0 and
+            inner_block.open_parentheses == 1 and
+            _MATCH_ASM.match(line)):
+          # Enter assembly block
+          inner_block.inline_asm = _INSIDE_ASM
+        else:
+          # Not entering assembly block.  If previous line was _END_ASM,
+          # we will now shift to _NO_ASM state.
+          inner_block.inline_asm = _NO_ASM
+      elif (inner_block.inline_asm == _INSIDE_ASM and
+            inner_block.open_parentheses == 0):
+        # Exit assembly block
+        inner_block.inline_asm = _END_ASM
+
+    # Consume namespace declaration at the beginning of the line.  Do
+    # this in a loop so that we catch same line declarations like this:
+    #   namespace proto2 { namespace bridge { class MessageSet; } }
+    while True:
+      # Match start of namespace.  The "\b\s*" below catches namespace
+      # declarations even if it weren't followed by a whitespace, this
+      # is so that we don't confuse our namespace checker.  The
+      # missing spaces will be flagged by CheckSpacing.
+      namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
+      if not namespace_decl_match:
+        break
+
+      new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
+      self.stack.append(new_namespace)
+
+      line = namespace_decl_match.group(2)
+      if line.find('{') != -1:
+        new_namespace.seen_open_brace = True
+        line = line[line.find('{') + 1:]
+
+    # Look for a class declaration in whatever is left of the line
+    # after parsing namespaces.  The regexp accounts for decorated classes
+    # such as in:
+    #   class LOCKABLE API Object {
+    #   };
+    class_decl_match = Match(
+        r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
+        r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))'
+        r'(.*)$', line)
+    if (class_decl_match and
+        (not self.stack or self.stack[-1].open_parentheses == 0)):
+      # We do not want to accept classes that are actually template arguments:
+      #   template <class Ignore1,
+      #             class Ignore2 = Default<Args>,
+      #             template <Args> class Ignore3>
+      #   void Function() {};
+      #
+      # To avoid template argument cases, we scan forward and look for
+      # an unmatched '>'.  If we see one, assume we are inside a
+      # template argument list.
+      end_declaration = len(class_decl_match.group(1))
+      if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
+        self.stack.append(_ClassInfo(
+            class_decl_match.group(3), class_decl_match.group(2),
+            clean_lines, linenum))
+        line = class_decl_match.group(4)
+
+    # If we have not yet seen the opening brace for the innermost block,
+    # run checks here.
+    if not self.SeenOpenBrace():
+      self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
+
+    # Update access control if we are inside a class/struct
+    if self.stack and isinstance(self.stack[-1], _ClassInfo):
+      classinfo = self.stack[-1]
+      access_match = Match(
+          r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
+          r':(?:[^:]|$)',
+          line)
+      if access_match:
+        classinfo.access = access_match.group(2)
+
+        # Check that access keywords are indented +1 space.  Skip this
+        # check if the keywords are not preceded by whitespaces.
+        indent = access_match.group(1)
+        if (len(indent) != classinfo.class_indent + 1 and
+            Match(r'^\s*$', indent)):
+          if classinfo.is_struct:
+            parent = 'struct ' + classinfo.name
+          else:
+            parent = 'class ' + classinfo.name
+          slots = ''
+          if access_match.group(3):
+            slots = access_match.group(3)
+          error(filename, linenum, 'whitespace/indent', 3,
+                '%s%s: should be indented +1 space inside %s' % (
+                    access_match.group(2), slots, parent))
+
+    # Consume braces or semicolons from what's left of the line
+    while True:
+      # Match first brace, semicolon, or closed parenthesis.
+      matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
+      if not matched:
+        break
+
+      token = matched.group(1)
+      if token == '{':
+        # If namespace or class hasn't seen a opening brace yet, mark
+        # namespace/class head as complete.  Push a new block onto the
+        # stack otherwise.
+        if not self.SeenOpenBrace():
+          self.stack[-1].seen_open_brace = True
+        elif Match(r'^extern\s*"[^"]*"\s*\{', line):
+          self.stack.append(_ExternCInfo(linenum))
+        else:
+          self.stack.append(_BlockInfo(linenum, True))
+          if _MATCH_ASM.match(line):
+            self.stack[-1].inline_asm = _BLOCK_ASM
+
+      elif token == ';' or token == ')':
+        # If we haven't seen an opening brace yet, but we already saw
+        # a semicolon, this is probably a forward declaration.  Pop
+        # the stack for these.
+        #
+        # Similarly, if we haven't seen an opening brace yet, but we
+        # already saw a closing parenthesis, then these are probably
+        # function arguments with extra "class" or "struct" keywords.
+        # Also pop these stack for these.
+        if not self.SeenOpenBrace():
+          self.stack.pop()
+      else:  # token == '}'
+        # Perform end of block checks and pop the stack.
+        if self.stack:
+          self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
+          self.stack.pop()
+      line = matched.group(2)
+
+  def InnermostClass(self):
+    """Get class info on the top of the stack.
+
+    Returns:
+      A _ClassInfo object if we are inside a class, or None otherwise.
+    """
+    for i in range(len(self.stack), 0, -1):
+      classinfo = self.stack[i - 1]
+      if isinstance(classinfo, _ClassInfo):
+        return classinfo
+    return None
+
+  def CheckCompletedBlocks(self, filename, error):
+    """Checks that all classes and namespaces have been completely parsed.
+
+    Call this when all lines in a file have been processed.
+    Args:
+      filename: The name of the current file.
+      error: The function to call with any errors found.
+    """
+    # Note: This test can result in false positives if #ifdef constructs
+    # get in the way of brace matching. See the testBuildClass test in
+    # cpplint_unittest.py for an example of this.
+    for obj in self.stack:
+      if isinstance(obj, _ClassInfo):
+        error(filename, obj.starting_linenum, 'build/class', 5,
+              'Failed to find complete declaration of class %s' %
+              obj.name)
+      elif isinstance(obj, _NamespaceInfo):
+        error(filename, obj.starting_linenum, 'build/namespaces', 5,
+              'Failed to find complete declaration of namespace %s' %
+              obj.name)
+
+
+def CheckForNonStandardConstructs(filename, clean_lines, linenum,
+                                  nesting_state, error):
+  r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
+
+  Complain about several constructs which gcc-2 accepts, but which are
+  not standard C++.  Warning about these in lint is one way to ease the
+  transition to new compilers.
+  - put storage class first (e.g. "static const" instead of "const static").
+  - "%lld" instead of %qd" in printf-type functions.
+  - "%1$d" is non-standard in printf-type functions.
+  - "\%" is an undefined character escape sequence.
+  - text after #endif is not allowed.
+  - invalid inner-style forward declaration.
+  - >? and <? operators, and their >?= and <?= cousins.
+
+  Additionally, check for constructor/destructor style violations and reference
+  members, as it is very convenient to do so while checking for
+  gcc-2 compliance.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: A callable to which errors are reported, which takes 4 arguments:
+           filename, line number, error level, and message
+  """
+
+  # Remove comments from the line, but leave in strings for now.
+  line = clean_lines.lines[linenum]
+
+  if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
+    error(filename, linenum, 'runtime/printf_format', 3,
+          '%q in format strings is deprecated.  Use %ll instead.')
+
+  if Search(r'printf\s*\(.*".*%\d+\$', line):
+    error(filename, linenum, 'runtime/printf_format', 2,
+          '%N$ formats are unconventional.  Try rewriting to avoid them.')
+
+  # Remove escaped backslashes before looking for undefined escapes.
+  line = line.replace('\\\\', '')
+
+  if Search(r'("|\').*\\(%|\[|\(|{)', line):
+    error(filename, linenum, 'build/printf_format', 3,
+          '%, [, (, and { are undefined character escapes.  Unescape them.')
+
+  # For the rest, work with both comments and strings removed.
+  line = clean_lines.elided[linenum]
+
+  if Search(r'\b(const|volatile|void|char|short|int|long'
+            r'|float|double|signed|unsigned'
+            r'|schar|u?int8|u?int16|u?int32|u?int64)'
+            r'\s+(register|static|extern|typedef)\b',
+            line):
+    error(filename, linenum, 'build/storage_class', 5,
+          'Storage-class specifier (static, extern, typedef, etc) should be '
+          'at the beginning of the declaration.')
+
+  if Match(r'\s*#\s*endif\s*[^/\s]+', line):
+    error(filename, linenum, 'build/endif_comment', 5,
+          'Uncommented text after #endif is non-standard.  Use a comment.')
+
+  if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
+    error(filename, linenum, 'build/forward_decl', 5,
+          'Inner-style forward declarations are invalid.  Remove this line.')
+
+  if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
+            line):
+    error(filename, linenum, 'build/deprecated', 3,
+          '>? and <? (max and min) operators are non-standard and deprecated.')
+
+  if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
+    # TODO(unknown): Could it be expanded safely to arbitrary references,
+    # without triggering too many false positives? The first
+    # attempt triggered 5 warnings for mostly benign code in the regtest, hence
+    # the restriction.
+    # Here's the original regexp, for the reference:
+    # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
+    # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
+    error(filename, linenum, 'runtime/member_string_references', 2,
+          'const string& members are dangerous. It is much better to use '
+          'alternatives, such as pointers or simple constants.')
+
+  # Everything else in this function operates on class declarations.
+  # Return early if the top of the nesting stack is not a class, or if
+  # the class head is not completed yet.
+  classinfo = nesting_state.InnermostClass()
+  if not classinfo or not classinfo.seen_open_brace:
+    return
+
+  # The class may have been declared with namespace or classname qualifiers.
+  # The constructor and destructor will not have those qualifiers.
+  base_classname = classinfo.name.split('::')[-1]
+
+  # Look for single-argument constructors that aren't marked explicit.
+  # Technically a valid construct, but against style.
+  explicit_constructor_match = Match(
+      r'\s+(?:(?:inline|constexpr)\s+)*(explicit\s+)?'
+      r'(?:(?:inline|constexpr)\s+)*%s\s*'
+      r'\(((?:[^()]|\([^()]*\))*)\)'
+      % re.escape(base_classname),
+      line)
+
+  if explicit_constructor_match:
+    is_marked_explicit = explicit_constructor_match.group(1)
+
+    if not explicit_constructor_match.group(2):
+      constructor_args = []
+    else:
+      constructor_args = explicit_constructor_match.group(2).split(',')
+
+    # collapse arguments so that commas in template parameter lists and function
+    # argument parameter lists don't split arguments in two
+    i = 0
+    while i < len(constructor_args):
+      constructor_arg = constructor_args[i]
+      while (constructor_arg.count('<') > constructor_arg.count('>') or
+             constructor_arg.count('(') > constructor_arg.count(')')):
+        constructor_arg += ',' + constructor_args[i + 1]
+        del constructor_args[i + 1]
+      constructor_args[i] = constructor_arg
+      i += 1
+
+    defaulted_args = [arg for arg in constructor_args if '=' in arg]
+    noarg_constructor = (not constructor_args or  # empty arg list
+                         # 'void' arg specifier
+                         (len(constructor_args) == 1 and
+                          constructor_args[0].strip() == 'void'))
+    onearg_constructor = ((len(constructor_args) == 1 and  # exactly one arg
+                           not noarg_constructor) or
+                          # all but at most one arg defaulted
+                          (len(constructor_args) >= 1 and
+                           not noarg_constructor and
+                           len(defaulted_args) >= len(constructor_args) - 1))
+    initializer_list_constructor = bool(
+        onearg_constructor and
+        Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
+    copy_constructor = bool(
+        onearg_constructor and
+        Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
+              % re.escape(base_classname), constructor_args[0].strip()))
+
+    if (not is_marked_explicit and
+        onearg_constructor and
+        not initializer_list_constructor and
+        not copy_constructor):
+      if defaulted_args:
+        error(filename, linenum, 'runtime/explicit', 5,
+              'Constructors callable with one argument '
+              'should be marked explicit.')
+      else:
+        error(filename, linenum, 'runtime/explicit', 5,
+              'Single-parameter constructors should be marked explicit.')
+    elif is_marked_explicit and not onearg_constructor:
+      if noarg_constructor:
+        error(filename, linenum, 'runtime/explicit', 5,
+              'Zero-parameter constructors should not be marked explicit.')
+
+
+def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
+  """Checks for the correctness of various spacing around function calls.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Since function calls often occur inside if/for/while/switch
+  # expressions - which have their own, more liberal conventions - we
+  # first see if we should be looking inside such an expression for a
+  # function call, to which we can apply more strict standards.
+  fncall = line    # if there's no control flow construct, look at whole line
+  for pattern in (r'\bif\s*\((.*)\)\s*{',
+                  r'\bfor\s*\((.*)\)\s*{',
+                  r'\bwhile\s*\((.*)\)\s*[{;]',
+                  r'\bswitch\s*\((.*)\)\s*{'):
+    match = Search(pattern, line)
+    if match:
+      fncall = match.group(1)    # look inside the parens for function calls
+      break
+
+  # Except in if/for/while/switch, there should never be space
+  # immediately inside parens (eg "f( 3, 4 )").  We make an exception
+  # for nested parens ( (a+b) + c ).  Likewise, there should never be
+  # a space before a ( when it's a function argument.  I assume it's a
+  # function argument when the char before the whitespace is legal in
+  # a function name (alnum + _) and we're not starting a macro. Also ignore
+  # pointers and references to arrays and functions coz they're too tricky:
+  # we use a very simple way to recognize these:
+  # " (something)(maybe-something)" or
+  # " (something)(maybe-something," or
+  # " (something)[something]"
+  # Note that we assume the contents of [] to be short enough that
+  # they'll never need to wrap.
+  if (  # Ignore control structures.
+      not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
+                 fncall) and
+      # Ignore pointers/references to functions.
+      not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
+      # Ignore pointers/references to arrays.
+      not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
+    if Search(r'\w\s*\(\s(?!\s*\\$)', fncall):      # a ( used for a fn call
+      error(filename, linenum, 'whitespace/parens', 4,
+            'Extra space after ( in function call')
+    elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
+      error(filename, linenum, 'whitespace/parens', 2,
+            'Extra space after (')
+    if (Search(r'\w\s+\(', fncall) and
+        not Search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and
+        not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
+        not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
+        not Search(r'\bcase\s+\(', fncall)):
+      # TODO(unknown): Space after an operator function seem to be a common
+      # error, silence those for now by restricting them to highest verbosity.
+      if Search(r'\boperator_*\b', line):
+        error(filename, linenum, 'whitespace/parens', 0,
+              'Extra space before ( in function call')
+      else:
+        error(filename, linenum, 'whitespace/parens', 4,
+              'Extra space before ( in function call')
+    # If the ) is followed only by a newline or a { + newline, assume it's
+    # part of a control statement (if/while/etc), and don't complain
+    if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
+      # If the closing parenthesis is preceded by only whitespaces,
+      # try to give a more descriptive error message.
+      if Search(r'^\s+\)', fncall):
+        error(filename, linenum, 'whitespace/parens', 2,
+              'Closing ) should be moved to the previous line')
+      else:
+        error(filename, linenum, 'whitespace/parens', 2,
+              'Extra space before )')
+
+
+def IsBlankLine(line):
+  """Returns true if the given line is blank.
+
+  We consider a line to be blank if the line is empty or consists of
+  only white spaces.
+
+  Args:
+    line: A line of a string.
+
+  Returns:
+    True, if the given line is blank.
+  """
+  return not line or line.isspace()
+
+
+def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
+                                 error):
+  is_namespace_indent_item = (
+      len(nesting_state.stack) > 1 and
+      nesting_state.stack[-1].check_namespace_indentation and
+      isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and
+      nesting_state.previous_stack_top == nesting_state.stack[-2])
+
+  if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
+                                     clean_lines.elided, line):
+    CheckItemIndentationInNamespace(filename, clean_lines.elided,
+                                    line, error)
+
+
+def CheckForFunctionLengths(filename, clean_lines, linenum,
+                            function_state, error):
+  """Reports for long function bodies.
+
+  For an overview why this is done, see:
+  https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
+
+  Uses a simplistic algorithm assuming other style guidelines
+  (especially spacing) are followed.
+  Only checks unindented functions, so class members are unchecked.
+  Trivial bodies are unchecked, so constructors with huge initializer lists
+  may be missed.
+  Blank/comment lines are not counted so as to avoid encouraging the removal
+  of vertical space and comments just to get through a lint check.
+  NOLINT *on the last line of a function* disables this check.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    function_state: Current function name and lines in body so far.
+    error: The function to call with any errors found.
+  """
+  lines = clean_lines.lines
+  line = lines[linenum]
+  joined_line = ''
+
+  starting_func = False
+  regexp = r'(\w(\w|::|\*|\&|\s)*)\('  # decls * & space::name( ...
+  match_result = Match(regexp, line)
+  if match_result:
+    # If the name is all caps and underscores, figure it's a macro and
+    # ignore it, unless it's TEST or TEST_F.
+    function_name = match_result.group(1).split()[-1]
+    if function_name == 'TEST' or function_name == 'TEST_F' or (
+        not Match(r'[A-Z_]+$', function_name)):
+      starting_func = True
+
+  if starting_func:
+    body_found = False
+    for start_linenum in xrange(linenum, clean_lines.NumLines()):
+      start_line = lines[start_linenum]
+      joined_line += ' ' + start_line.lstrip()
+      if Search(r'(;|})', start_line):  # Declarations and trivial functions
+        body_found = True
+        break                              # ... ignore
+      elif Search(r'{', start_line):
+        body_found = True
+        function = Search(r'((\w|:)*)\(', line).group(1)
+        if Match(r'TEST', function):    # Handle TEST... macros
+          parameter_regexp = Search(r'(\(.*\))', joined_line)
+          if parameter_regexp:             # Ignore bad syntax
+            function += parameter_regexp.group(1)
+        else:
+          function += '()'
+        function_state.Begin(function)
+        break
+    if not body_found:
+      # No body for the function (or evidence of a non-function) was found.
+      error(filename, linenum, 'readability/fn_size', 5,
+            'Lint failed to find start of function body.')
+  elif Match(r'^\}\s*$', line):  # function end
+    function_state.Check(error, filename, linenum)
+    function_state.End()
+  elif not Match(r'^\s*$', line):
+    function_state.Count()  # Count non-blank/non-comment lines.
+
+
+_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
+
+
+def CheckComment(line, filename, linenum, next_line_start, error):
+  """Checks for common mistakes in comments.
+
+  Args:
+    line: The line in question.
+    filename: The name of the current file.
+    linenum: The number of the line to check.
+    next_line_start: The first non-whitespace column of the next line.
+    error: The function to call with any errors found.
+  """
+  commentpos = line.find('//')
+  if commentpos != -1:
+    # Check if the // may be in quotes.  If so, ignore it
+    if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0:
+      # Allow one space for new scopes, two spaces otherwise:
+      if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
+          ((commentpos >= 1 and
+            line[commentpos-1] not in string.whitespace) or
+           (commentpos >= 2 and
+            line[commentpos-2] not in string.whitespace))):
+        error(filename, linenum, 'whitespace/comments', 2,
+              'At least two spaces is best between code and comments')
+
+      # Checks for common mistakes in TODO comments.
+      comment = line[commentpos:]
+      match = _RE_PATTERN_TODO.match(comment)
+      if match:
+        # One whitespace is correct; zero whitespace is handled elsewhere.
+        leading_whitespace = match.group(1)
+        if len(leading_whitespace) > 1:
+          error(filename, linenum, 'whitespace/todo', 2,
+                'Too many spaces before TODO')
+
+        username = match.group(2)
+        if not username:
+          error(filename, linenum, 'readability/todo', 2,
+                'Missing username in TODO; it should look like '
+                '"// TODO(my_username): Stuff."')
+
+        middle_whitespace = match.group(3)
+        # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
+        if middle_whitespace != ' ' and middle_whitespace != '':
+          error(filename, linenum, 'whitespace/todo', 2,
+                'TODO(my_username) should be followed by a space')
+
+      # If the comment contains an alphanumeric character, there
+      # should be a space somewhere between it and the // unless
+      # it's a /// or //! Doxygen comment.
+      if (Match(r'//[^ ]*\w', comment) and
+          not Match(r'(///|//\!)(\s+|$)', comment)):
+        error(filename, linenum, 'whitespace/comments', 4,
+              'Should have a space between // and comment')
+
+
+def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
+  """Checks for the correctness of various spacing issues in the code.
+
+  Things we check for: spaces around operators, spaces after
+  if/for/while/switch, no spaces around parens in function calls, two
+  spaces between code and comment, don't start a block with a blank
+  line, don't end a function with a blank line, don't add a blank line
+  after public/protected/private, don't have too many blank lines in a row.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+
+  # Don't use "elided" lines here, otherwise we can't check commented lines.
+  # Don't want to use "raw" either, because we don't want to check inside C++11
+  # raw strings,
+  raw = clean_lines.lines_without_raw_strings
+  line = raw[linenum]
+
+  # Before nixing comments, check if the line is blank for no good
+  # reason.  This includes the first line after a block is opened, and
+  # blank lines at the end of a function (ie, right before a line like '}'
+  #
+  # Skip all the blank line checks if we are immediately inside a
+  # namespace body.  In other words, don't issue blank line warnings
+  # for this block:
+  #   namespace {
+  #
+  #   }
+  #
+  # A warning about missing end of namespace comments will be issued instead.
+  #
+  # Also skip blank line checks for 'extern "C"' blocks, which are formatted
+  # like namespaces.
+  if (IsBlankLine(line) and
+      not nesting_state.InNamespaceBody() and
+      not nesting_state.InExternC()):
+    elided = clean_lines.elided
+    prev_line = elided[linenum - 1]
+    prevbrace = prev_line.rfind('{')
+    # TODO(unknown): Don't complain if line before blank line, and line after,
+    #                both start with alnums and are indented the same amount.
+    #                This ignores whitespace at the start of a namespace block
+    #                because those are not usually indented.
+    if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
+      # OK, we have a blank line at the start of a code block.  Before we
+      # complain, we check if it is an exception to the rule: The previous
+      # non-empty line has the parameters of a function header that are indented
+      # 4 spaces (because they did not fit in a 80 column line when placed on
+      # the same line as the function name).  We also check for the case where
+      # the previous line is indented 6 spaces, which may happen when the
+      # initializers of a constructor do not fit into a 80 column line.
+      exception = False
+      if Match(r' {6}\w', prev_line):  # Initializer list?
+        # We are looking for the opening column of initializer list, which
+        # should be indented 4 spaces to cause 6 space indentation afterwards.
+        search_position = linenum-2
+        while (search_position >= 0
+               and Match(r' {6}\w', elided[search_position])):
+          search_position -= 1
+        exception = (search_position >= 0
+                     and elided[search_position][:5] == '    :')
+      else:
+        # Search for the function arguments or an initializer list.  We use a
+        # simple heuristic here: If the line is indented 4 spaces; and we have a
+        # closing paren, without the opening paren, followed by an opening brace
+        # or colon (for initializer lists) we assume that it is the last line of
+        # a function header.  If we have a colon indented 4 spaces, it is an
+        # initializer list.
+        exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
+                           prev_line)
+                     or Match(r' {4}:', prev_line))
+
+      if not exception:
+        error(filename, linenum, 'whitespace/blank_line', 2,
+              'Redundant blank line at the start of a code block '
+              'should be deleted.')
+    # Ignore blank lines at the end of a block in a long if-else
+    # chain, like this:
+    #   if (condition1) {
+    #     // Something followed by a blank line
+    #
+    #   } else if (condition2) {
+    #     // Something else
+    #   }
+    if linenum + 1 < clean_lines.NumLines():
+      next_line = raw[linenum + 1]
+      if (next_line
+          and Match(r'\s*}', next_line)
+          and next_line.find('} else ') == -1):
+        error(filename, linenum, 'whitespace/blank_line', 3,
+              'Redundant blank line at the end of a code block '
+              'should be deleted.')
+
+    matched = Match(r'\s*(public|protected|private):', prev_line)
+    if matched:
+      error(filename, linenum, 'whitespace/blank_line', 3,
+            'Do not leave a blank line after "%s:"' % matched.group(1))
+
+  # Next, check comments
+  next_line_start = 0
+  if linenum + 1 < clean_lines.NumLines():
+    next_line = raw[linenum + 1]
+    next_line_start = len(next_line) - len(next_line.lstrip())
+  CheckComment(line, filename, linenum, next_line_start, error)
+
+  # get rid of comments and strings
+  line = clean_lines.elided[linenum]
+
+  # You shouldn't have spaces before your brackets, except maybe after
+  # 'delete []' or 'return []() {};'
+  if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
+    error(filename, linenum, 'whitespace/braces', 5,
+          'Extra space before [')
+
+  # In range-based for, we wanted spaces before and after the colon, but
+  # not around "::" tokens that might appear.
+  if (Search(r'for *\(.*[^:]:[^: ]', line) or
+      Search(r'for *\(.*[^: ]:[^:]', line)):
+    error(filename, linenum, 'whitespace/forcolon', 2,
+          'Missing space around colon in range-based for loop')
+
+
+def CheckOperatorSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing around operators.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Don't try to do spacing checks for operator methods.  Do this by
+  # replacing the troublesome characters with something else,
+  # preserving column position for all other characters.
+  #
+  # The replacement is done repeatedly to avoid false positives from
+  # operators that call operators.
+  while True:
+    match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
+    if match:
+      line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
+    else:
+      break
+
+  # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
+  # Otherwise not.  Note we only check for non-spaces on *both* sides;
+  # sometimes people put non-spaces on one side when aligning ='s among
+  # many lines (not that this is behavior that I approve of...)
+  if ((Search(r'[\w.]=', line) or
+       Search(r'=[\w.]', line))
+      and not Search(r'\b(if|while|for) ', line)
+      # Operators taken from [lex.operators] in C++11 standard.
+      and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
+      and not Search(r'operator=', line)):
+    error(filename, linenum, 'whitespace/operators', 4,
+          'Missing spaces around =')
+
+  # It's ok not to have spaces around binary operators like + - * /, but if
+  # there's too little whitespace, we get concerned.  It's hard to tell,
+  # though, so we punt on this one for now.  TODO.
+
+  # You should always have whitespace around binary operators.
+  #
+  # Check <= and >= first to avoid false positives with < and >, then
+  # check non-include lines for spacing around < and >.
+  #
+  # If the operator is followed by a comma, assume it's be used in a
+  # macro context and don't do any checks.  This avoids false
+  # positives.
+  #
+  # Note that && is not included here.  This is because there are too
+  # many false positives due to RValue references.
+  match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
+  if match:
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around %s' % match.group(1))
+  elif not Match(r'#.*include', line):
+    # Look for < that is not surrounded by spaces.  This is only
+    # triggered if both sides are missing spaces, even though
+    # technically should should flag if at least one side is missing a
+    # space.  This is done to avoid some false positives with shifts.
+    match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
+    if match:
+      (_, _, end_pos) = CloseExpression(
+          clean_lines, linenum, len(match.group(1)))
+      if end_pos <= -1:
+        error(filename, linenum, 'whitespace/operators', 3,
+              'Missing spaces around <')
+
+    # Look for > that is not surrounded by spaces.  Similar to the
+    # above, we only trigger if both sides are missing spaces to avoid
+    # false positives with shifts.
+    match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
+    if match:
+      (_, _, start_pos) = ReverseCloseExpression(
+          clean_lines, linenum, len(match.group(1)))
+      if start_pos <= -1:
+        error(filename, linenum, 'whitespace/operators', 3,
+              'Missing spaces around >')
+
+  # We allow no-spaces around << when used like this: 10<<20, but
+  # not otherwise (particularly, not when used as streams)
+  #
+  # We also allow operators following an opening parenthesis, since
+  # those tend to be macros that deal with operators.
+  match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
+  if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
+      not (match.group(1) == 'operator' and match.group(2) == ';')):
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around <<')
+
+  # We allow no-spaces around >> for almost anything.  This is because
+  # C++11 allows ">>" to close nested templates, which accounts for
+  # most cases when ">>" is not followed by a space.
+  #
+  # We still warn on ">>" followed by alpha character, because that is
+  # likely due to ">>" being used for right shifts, e.g.:
+  #   value >> alpha
+  #
+  # When ">>" is used to close templates, the alphanumeric letter that
+  # follows would be part of an identifier, and there should still be
+  # a space separating the template type and the identifier.
+  #   type<type<type>> alpha
+  match = Search(r'>>[a-zA-Z_]', line)
+  if match:
+    error(filename, linenum, 'whitespace/operators', 3,
+          'Missing spaces around >>')
+
+  # There shouldn't be space around unary operators
+  match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
+  if match:
+    error(filename, linenum, 'whitespace/operators', 4,
+          'Extra space for operator %s' % match.group(1))
+
+
+def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing around parentheses.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # No spaces after an if, while, switch, or for
+  match = Search(r' (if\(|for\(|while\(|switch\()', line)
+  if match:
+    error(filename, linenum, 'whitespace/parens', 5,
+          'Missing space before ( in %s' % match.group(1))
+
+  # For if/for/while/switch, the left and right parens should be
+  # consistent about how many spaces are inside the parens, and
+  # there should either be zero or one spaces inside the parens.
+  # We don't want: "if ( foo)" or "if ( foo   )".
+  # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
+  match = Search(r'\b(if|for|while|switch)\s*'
+                 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
+                 line)
+  if match:
+    if len(match.group(2)) != len(match.group(4)):
+      if not (match.group(3) == ';' and
+              len(match.group(2)) == 1 + len(match.group(4)) or
+              not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
+        error(filename, linenum, 'whitespace/parens', 5,
+              'Mismatching spaces inside () in %s' % match.group(1))
+    if len(match.group(2)) not in [0, 1]:
+      error(filename, linenum, 'whitespace/parens', 5,
+            'Should have zero or one spaces inside ( and ) in %s' %
+            match.group(1))
+
+
+def CheckCommaSpacing(filename, clean_lines, linenum, error):
+  """Checks for horizontal spacing near commas and semicolons.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  raw = clean_lines.lines_without_raw_strings
+  line = clean_lines.elided[linenum]
+
+  # You should always have a space after a comma (either as fn arg or operator)
+  #
+  # This does not apply when the non-space character following the
+  # comma is another comma, since the only time when that happens is
+  # for empty macro arguments.
+  #
+  # We run this check in two passes: first pass on elided lines to
+  # verify that lines contain missing whitespaces, second pass on raw
+  # lines to confirm that those missing whitespaces are not due to
+  # elided comments.
+  if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
+      Search(r',[^,\s]', raw[linenum])):
+    error(filename, linenum, 'whitespace/comma', 3,
+          'Missing space after ,')
+
+  # You should always have a space after a semicolon
+  # except for few corner cases
+  # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
+  # space after ;
+  if Search(r';[^\s};\\)/]', line):
+    error(filename, linenum, 'whitespace/semicolon', 3,
+          'Missing space after ;')
+
+
+def _IsType(clean_lines, nesting_state, expr):
+  """Check if expression looks like a type name, returns true if so.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    expr: The expression to check.
+  Returns:
+    True, if token looks like a type.
+  """
+  # Keep only the last token in the expression
+  last_word = Match(r'^.*(\b\S+)$', expr)
+  if last_word:
+    token = last_word.group(1)
+  else:
+    token = expr
+
+  # Match native types and stdint types
+  if _TYPES.match(token):
+    return True
+
+  # Try a bit harder to match templated types.  Walk up the nesting
+  # stack until we find something that resembles a typename
+  # declaration for what we are looking for.
+  typename_pattern = (r'\b(?:typename|class|struct)\s+' + re.escape(token) +
+                      r'\b')
+  block_index = len(nesting_state.stack) - 1
+  while block_index >= 0:
+    if isinstance(nesting_state.stack[block_index], _NamespaceInfo):
+      return False
+
+    # Found where the opening brace is.  We want to scan from this
+    # line up to the beginning of the function, minus a few lines.
+    #   template <typename Type1,  // stop scanning here
+    #             ...>
+    #   class C
+    #     : public ... {  // start scanning here
+    last_line = nesting_state.stack[block_index].starting_linenum
+
+    next_block_start = 0
+    if block_index > 0:
+      next_block_start = nesting_state.stack[block_index - 1].starting_linenum
+    first_line = last_line
+    while first_line >= next_block_start:
+      if clean_lines.elided[first_line].find('template') >= 0:
+        break
+      first_line -= 1
+    if first_line < next_block_start:
+      # Didn't find any "template" keyword before reaching the next block,
+      # there are probably no template things to check for this block
+      block_index -= 1
+      continue
+
+    # Look for typename in the specified range
+    for i in xrange(first_line, last_line + 1, 1):
+      if Search(typename_pattern, clean_lines.elided[i]):
+        return True
+    block_index -= 1
+
+  return False
+
+
+def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error):
+  """Checks for horizontal spacing near commas.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Except after an opening paren, or after another opening brace (in case of
+  # an initializer list, for instance), you should have spaces before your
+  # braces when they are delimiting blocks, classes, namespaces etc.
+  # And since you should never have braces at the beginning of a line,
+  # this is an easy test.  Except that braces used for initialization don't
+  # follow the same rule; we often don't want spaces before those.
+  match = Match(r'^(.*[^ ({>]){', line)
+
+  if match:
+    # Try a bit harder to check for brace initialization.  This
+    # happens in one of the following forms:
+    #   Constructor() : initializer_list_{} { ... }
+    #   Constructor{}.MemberFunction()
+    #   Type variable{};
+    #   FunctionCall(type{}, ...);
+    #   LastArgument(..., type{});
+    #   LOG(INFO) << type{} << " ...";
+    #   map_of_type[{...}] = ...;
+    #   ternary = expr ? new type{} : nullptr;
+    #   OuterTemplate<InnerTemplateConstructor<Type>{}>
+    #
+    # We check for the character following the closing brace, and
+    # silence the warning if it's one of those listed above, i.e.
+    # "{.;,)<>]:".
+    #
+    # To account for nested initializer list, we allow any number of
+    # closing braces up to "{;,)<".  We can't simply silence the
+    # warning on first sight of closing brace, because that would
+    # cause false negatives for things that are not initializer lists.
+    #   Silence this:         But not this:
+    #     Outer{                if (...) {
+    #       Inner{...}            if (...){  // Missing space before {
+    #     };                    }
+    #
+    # There is a false negative with this approach if people inserted
+    # spurious semicolons, e.g. "if (cond){};", but we will catch the
+    # spurious semicolon with a separate check.
+    leading_text = match.group(1)
+    (endline, endlinenum, endpos) = CloseExpression(
+        clean_lines, linenum, len(match.group(1)))
+    trailing_text = ''
+    if endpos > -1:
+      trailing_text = endline[endpos:]
+    for offset in xrange(endlinenum + 1,
+                         min(endlinenum + 3, clean_lines.NumLines() - 1)):
+      trailing_text += clean_lines.elided[offset]
+    # We also suppress warnings for `uint64_t{expression}` etc., as the style
+    # guide recommends brace initialization for integral types to avoid
+    # overflow/truncation.
+    if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text)
+        and not _IsType(clean_lines, nesting_state, leading_text)):
+      error(filename, linenum, 'whitespace/braces', 5,
+            'Missing space before {')
+
+  # Make sure '} else {' has spaces.
+  if Search(r'}else', line):
+    error(filename, linenum, 'whitespace/braces', 5,
+          'Missing space before else')
+
+  # You shouldn't have a space before a semicolon at the end of the line.
+  # There's a special case for "for" since the style guide allows space before
+  # the semicolon there.
+  if Search(r':\s*;\s*$', line):
+    error(filename, linenum, 'whitespace/semicolon', 5,
+          'Semicolon defining empty statement. Use {} instead.')
+  elif Search(r'^\s*;\s*$', line):
+    error(filename, linenum, 'whitespace/semicolon', 5,
+          'Line contains only semicolon. If this should be an empty statement, '
+          'use {} instead.')
+  elif (Search(r'\s+;\s*$', line) and
+        not Search(r'\bfor\b', line)):
+    error(filename, linenum, 'whitespace/semicolon', 5,
+          'Extra space before last semicolon. If this should be an empty '
+          'statement, use {} instead.')
+
+
+def IsDecltype(clean_lines, linenum, column):
+  """Check if the token ending on (linenum, column) is decltype().
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: the number of the line to check.
+    column: end column of the token to check.
+  Returns:
+    True if this token is decltype() expression, False otherwise.
+  """
+  (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
+  if start_col < 0:
+    return False
+  if Search(r'\bdecltype\s*$', text[0:start_col]):
+    return True
+  return False
+
+
+def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
+  """Checks for additional blank line issues related to sections.
+
+  Currently the only thing checked here is blank line before protected/private.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    class_info: A _ClassInfo objects.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  # Skip checks if the class is small, where small means 25 lines or less.
+  # 25 lines seems like a good cutoff since that's the usual height of
+  # terminals, and any class that can't fit in one screen can't really
+  # be considered "small".
+  #
+  # Also skip checks if we are on the first line.  This accounts for
+  # classes that look like
+  #   class Foo { public: ... };
+  #
+  # If we didn't find the end of the class, last_line would be zero,
+  # and the check will be skipped by the first condition.
+  if (class_info.last_line - class_info.starting_linenum <= 24 or
+      linenum <= class_info.starting_linenum):
+    return
+
+  matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
+  if matched:
+    # Issue warning if the line before public/protected/private was
+    # not a blank line, but don't do this if the previous line contains
+    # "class" or "struct".  This can happen two ways:
+    #  - We are at the beginning of the class.
+    #  - We are forward-declaring an inner class that is semantically
+    #    private, but needed to be public for implementation reasons.
+    # Also ignores cases where the previous line ends with a backslash as can be
+    # common when defining classes in C macros.
+    prev_line = clean_lines.lines[linenum - 1]
+    if (not IsBlankLine(prev_line) and
+        not Search(r'\b(class|struct)\b', prev_line) and
+        not Search(r'\\$', prev_line)):
+      # Try a bit harder to find the beginning of the class.  This is to
+      # account for multi-line base-specifier lists, e.g.:
+      #   class Derived
+      #       : public Base {
+      end_class_head = class_info.starting_linenum
+      for i in range(class_info.starting_linenum, linenum):
+        if Search(r'\{\s*$', clean_lines.lines[i]):
+          end_class_head = i
+          break
+      if end_class_head < linenum - 1:
+        error(filename, linenum, 'whitespace/blank_line', 3,
+              '"%s:" should be preceded by a blank line' % matched.group(1))
+
+
+def GetPreviousNonBlankLine(clean_lines, linenum):
+  """Return the most recent non-blank line and its line number.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file contents.
+    linenum: The number of the line to check.
+
+  Returns:
+    A tuple with two elements.  The first element is the contents of the last
+    non-blank line before the current line, or the empty string if this is the
+    first non-blank line.  The second is the line number of that line, or -1
+    if this is the first non-blank line.
+  """
+
+  prevlinenum = linenum - 1
+  while prevlinenum >= 0:
+    prevline = clean_lines.elided[prevlinenum]
+    if not IsBlankLine(prevline):     # if not a blank line...
+      return (prevline, prevlinenum)
+    prevlinenum -= 1
+  return ('', -1)
+
+
+def CheckBraces(filename, clean_lines, linenum, error):
+  """Looks for misplaced braces (e.g. at the end of line).
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  line = clean_lines.elided[linenum]        # get rid of comments and strings
+
+  if Match(r'\s*{\s*$', line):
+    # We allow an open brace to start a line in the case where someone is using
+    # braces in a block to explicitly create a new scope, which is commonly used
+    # to control the lifetime of stack-allocated variables.  Braces are also
+    # used for brace initializers inside function calls.  We don't detect this
+    # perfectly: we just don't complain if the last non-whitespace character on
+    # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
+    # previous line starts a preprocessor block. We also allow a brace on the
+    # following line if it is part of an array initialization and would not fit
+    # within the 80 character limit of the preceding line.
+    prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+    if (not Search(r'[,;:}{(]\s*$', prevline) and
+        not Match(r'\s*#', prevline) and
+        not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)):
+      error(filename, linenum, 'whitespace/braces', 4,
+            '{ should almost always be at the end of the previous line')
+
+  # An else clause should be on the same line as the preceding closing brace.
+  if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
+    prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+    if Match(r'\s*}\s*$', prevline):
+      error(filename, linenum, 'whitespace/newline', 4,
+            'An else should appear on the same line as the preceding }')
+
+  # If braces come on one side of an else, they should be on both.
+  # However, we have to worry about "else if" that spans multiple lines!
+  if Search(r'else if\s*\(', line):       # could be multi-line if
+    brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
+    # find the ( after the if
+    pos = line.find('else if')
+    pos = line.find('(', pos)
+    if pos > 0:
+      (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
+      brace_on_right = endline[endpos:].find('{') != -1
+      if brace_on_left != brace_on_right:    # must be brace after if
+        error(filename, linenum, 'readability/braces', 5,
+              'If an else has a brace on one side, it should have it on both')
+  elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
+    error(filename, linenum, 'readability/braces', 5,
+          'If an else has a brace on one side, it should have it on both')
+
+  # Likewise, an else should never have the else clause on the same line
+  if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
+    error(filename, linenum, 'whitespace/newline', 4,
+          'Else clause should never be on same line as else (use 2 lines)')
+
+  # In the same way, a do/while should never be on one line
+  if Match(r'\s*do [^\s{]', line):
+    error(filename, linenum, 'whitespace/newline', 4,
+          'do/while clauses should not be on a single line')
+
+  # Check single-line if/else bodies. The style guide says 'curly braces are not
+  # required for single-line statements'. We additionally allow multi-line,
+  # single statements, but we reject anything with more than one semicolon in
+  # it. This means that the first semicolon after the if should be at the end of
+  # its line, and the line after that should have an indent level equal to or
+  # lower than the if. We also check for ambiguous if/else nesting without
+  # braces.
+  if_else_match = Search(r'\b(if\s*\(|else\b)', line)
+  if if_else_match and not Match(r'\s*#', line):
+    if_indent = GetIndentLevel(line)
+    endline, endlinenum, endpos = line, linenum, if_else_match.end()
+    if_match = Search(r'\bif\s*\(', line)
+    if if_match:
+      # This could be a multiline if condition, so find the end first.
+      pos = if_match.end() - 1
+      (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
+    # Check for an opening brace, either directly after the if or on the next
+    # line. If found, this isn't a single-statement conditional.
+    if (not Match(r'\s*{', endline[endpos:])
+        and not (Match(r'\s*$', endline[endpos:])
+                 and endlinenum < (len(clean_lines.elided) - 1)
+                 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
+      while (endlinenum < len(clean_lines.elided)
+             and ';' not in clean_lines.elided[endlinenum][endpos:]):
+        endlinenum += 1
+        endpos = 0
+      if endlinenum < len(clean_lines.elided):
+        endline = clean_lines.elided[endlinenum]
+        # We allow a mix of whitespace and closing braces (e.g. for one-liner
+        # methods) and a single \ after the semicolon (for macros)
+        endpos = endline.find(';')
+        if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
+          # Semicolon isn't the last character, there's something trailing.
+          # Output a warning if the semicolon is not contained inside
+          # a lambda expression.
+          if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
+                       endline):
+            error(filename, linenum, 'readability/braces', 4,
+                  'If/else bodies with multiple statements require braces')
+        elif endlinenum < len(clean_lines.elided) - 1:
+          # Make sure the next line is dedented
+          next_line = clean_lines.elided[endlinenum + 1]
+          next_indent = GetIndentLevel(next_line)
+          # With ambiguous nested if statements, this will error out on the
+          # if that *doesn't* match the else, regardless of whether it's the
+          # inner one or outer one.
+          if (if_match and Match(r'\s*else\b', next_line)
+              and next_indent != if_indent):
+            error(filename, linenum, 'readability/braces', 4,
+                  'Else clause should be indented at the same level as if. '
+                  'Ambiguous nested if/else chains require braces.')
+          elif next_indent > if_indent:
+            error(filename, linenum, 'readability/braces', 4,
+                  'If/else bodies with multiple statements require braces')
+
+
+def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
+  """Looks for redundant trailing semicolon.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  line = clean_lines.elided[linenum]
+
+  # Block bodies should not be followed by a semicolon.  Due to C++11
+  # brace initialization, there are more places where semicolons are
+  # required than not, so we use a whitelist approach to check these
+  # rather than a blacklist.  These are the places where "};" should
+  # be replaced by just "}":
+  # 1. Some flavor of block following closing parenthesis:
+  #    for (;;) {};
+  #    while (...) {};
+  #    switch (...) {};
+  #    Function(...) {};
+  #    if (...) {};
+  #    if (...) else if (...) {};
+  #
+  # 2. else block:
+  #    if (...) else {};
+  #
+  # 3. const member function:
+  #    Function(...) const {};
+  #
+  # 4. Block following some statement:
+  #    x = 42;
+  #    {};
+  #
+  # 5. Block at the beginning of a function:
+  #    Function(...) {
+  #      {};
+  #    }
+  #
+  #    Note that naively checking for the preceding "{" will also match
+  #    braces inside multi-dimensional arrays, but this is fine since
+  #    that expression will not contain semicolons.
+  #
+  # 6. Block following another block:
+  #    while (true) {}
+  #    {};
+  #
+  # 7. End of namespaces:
+  #    namespace {};
+  #
+  #    These semicolons seems far more common than other kinds of
+  #    redundant semicolons, possibly due to people converting classes
+  #    to namespaces.  For now we do not warn for this case.
+  #
+  # Try matching case 1 first.
+  match = Match(r'^(.*\)\s*)\{', line)
+  if match:
+    # Matched closing parenthesis (case 1).  Check the token before the
+    # matching opening parenthesis, and don't warn if it looks like a
+    # macro.  This avoids these false positives:
+    #  - macro that defines a base class
+    #  - multi-line macro that defines a base class
+    #  - macro that defines the whole class-head
+    #
+    # But we still issue warnings for macros that we know are safe to
+    # warn, specifically:
+    #  - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
+    #  - TYPED_TEST
+    #  - INTERFACE_DEF
+    #  - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
+    #
+    # We implement a whitelist of safe macros instead of a blacklist of
+    # unsafe macros, even though the latter appears less frequently in
+    # google code and would have been easier to implement.  This is because
+    # the downside for getting the whitelist wrong means some extra
+    # semicolons, while the downside for getting the blacklist wrong
+    # would result in compile errors.
+    #
+    # In addition to macros, we also don't want to warn on
+    #  - Compound literals
+    #  - Lambdas
+    #  - alignas specifier with anonymous structs
+    #  - decltype
+    closing_brace_pos = match.group(1).rfind(')')
+    opening_parenthesis = ReverseCloseExpression(
+        clean_lines, linenum, closing_brace_pos)
+    if opening_parenthesis[2] > -1:
+      line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
+      macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
+      func = Match(r'^(.*\])\s*$', line_prefix)
+      if ((macro and
+           macro.group(1) not in (
+               'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
+               'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
+               'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
+          (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
+          Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
+          Search(r'\bdecltype$', line_prefix) or
+          Search(r'\s+=\s*$', line_prefix)):
+        match = None
+    if (match and
+        opening_parenthesis[1] > 1 and
+        Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
+      # Multi-line lambda-expression
+      match = None
+
+  else:
+    # Try matching cases 2-3.
+    match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
+    if not match:
+      # Try matching cases 4-6.  These are always matched on separate lines.
+      #
+      # Note that we can't simply concatenate the previous line to the
+      # current line and do a single match, otherwise we may output
+      # duplicate warnings for the blank line case:
+      #   if (cond) {
+      #     // blank line
+      #   }
+      prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
+      if prevline and Search(r'[;{}]\s*$', prevline):
+        match = Match(r'^(\s*)\{', line)
+
+  # Check matching closing brace
+  if match:
+    (endline, endlinenum, endpos) = CloseExpression(
+        clean_lines, linenum, len(match.group(1)))
+    if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
+      # Current {} pair is eligible for semicolon check, and we have found
+      # the redundant semicolon, output warning here.
+      #
+      # Note: because we are scanning forward for opening braces, and
+      # outputting warnings for the matching closing brace, if there are
+      # nested blocks with trailing semicolons, we will get the error
+      # messages in reversed order.
+
+      # We need to check the line forward for NOLINT
+      raw_lines = clean_lines.raw_lines
+      ParseNolintSuppressions(filename, raw_lines[endlinenum-1], endlinenum-1,
+                              error)
+      ParseNolintSuppressions(filename, raw_lines[endlinenum], endlinenum,
+                              error)
+
+      error(filename, endlinenum, 'readability/braces', 4,
+            "You don't need a ; after a }")
+
+
+def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
+  """Look for empty loop/conditional body with only a single semicolon.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  # Search for loop keywords at the beginning of the line.  Because only
+  # whitespaces are allowed before the keywords, this will also ignore most
+  # do-while-loops, since those lines should start with closing brace.
+  #
+  # We also check "if" blocks here, since an empty conditional block
+  # is likely an error.
+  line = clean_lines.elided[linenum]
+  matched = Match(r'\s*(for|while|if)\s*\(', line)
+  if matched:
+    # Find the end of the conditional expression.
+    (end_line, end_linenum, end_pos) = CloseExpression(
+        clean_lines, linenum, line.find('('))
+
+    # Output warning if what follows the condition expression is a semicolon.
+    # No warning for all other cases, including whitespace or newline, since we
+    # have a separate check for semicolons preceded by whitespace.
+    if end_pos >= 0 and Match(r';', end_line[end_pos:]):
+      if matched.group(1) == 'if':
+        error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
+              'Empty conditional bodies should use {}')
+      else:
+        error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
+              'Empty loop bodies should use {} or continue')
+
+    # Check for if statements that have completely empty bodies (no comments)
+    # and no else clauses.
+    if end_pos >= 0 and matched.group(1) == 'if':
+      # Find the position of the opening { for the if statement.
+      # Return without logging an error if it has no brackets.
+      opening_linenum = end_linenum
+      opening_line_fragment = end_line[end_pos:]
+      # Loop until EOF or find anything that's not whitespace or opening {.
+      while not Search(r'^\s*\{', opening_line_fragment):
+        if Search(r'^(?!\s*$)', opening_line_fragment):
+          # Conditional has no brackets.
+          return
+        opening_linenum += 1
+        if opening_linenum == len(clean_lines.elided):
+          # Couldn't find conditional's opening { or any code before EOF.
+          return
+        opening_line_fragment = clean_lines.elided[opening_linenum]
+      # Set opening_line (opening_line_fragment may not be entire opening line).
+      opening_line = clean_lines.elided[opening_linenum]
+
+      # Find the position of the closing }.
+      opening_pos = opening_line_fragment.find('{')
+      if opening_linenum == end_linenum:
+        # We need to make opening_pos relative to the start of the entire line.
+        opening_pos += end_pos
+      (closing_line, closing_linenum, closing_pos) = CloseExpression(
+          clean_lines, opening_linenum, opening_pos)
+      if closing_pos < 0:
+        return
+
+      # Now construct the body of the conditional. This consists of the portion
+      # of the opening line after the {, all lines until the closing line,
+      # and the portion of the closing line before the }.
+      if (clean_lines.raw_lines[opening_linenum] !=
+          CleanseComments(clean_lines.raw_lines[opening_linenum])):
+        # Opening line ends with a comment, so conditional isn't empty.
+        return
+      if closing_linenum > opening_linenum:
+        # Opening line after the {. Ignore comments here since we checked above.
+        body = list(opening_line[opening_pos+1:])
+        # All lines until closing line, excluding closing line, with comments.
+        body.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum])
+        # Closing line before the }. Won't (and can't) have comments.
+        body.append(clean_lines.elided[closing_linenum][:closing_pos-1])
+        body = '\n'.join(body)
+      else:
+        # If statement has brackets and fits on a single line.
+        body = opening_line[opening_pos+1:closing_pos-1]
+
+      # Check if the body is empty
+      if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body):
+        return
+      # The body is empty. Now make sure there's not an else clause.
+      current_linenum = closing_linenum
+      current_line_fragment = closing_line[closing_pos:]
+      # Loop until EOF or find anything that's not whitespace or else clause.
+      while Search(r'^\s*$|^(?=\s*else)', current_line_fragment):
+        if Search(r'^(?=\s*else)', current_line_fragment):
+          # Found an else clause, so don't log an error.
+          return
+        current_linenum += 1
+        if current_linenum == len(clean_lines.elided):
+          break
+        current_line_fragment = clean_lines.elided[current_linenum]
+
+      # The body is empty and there's no else clause until EOF or other code.
+      error(filename, end_linenum, 'whitespace/empty_if_body', 4,
+            ('If statement had no body and no else clause'))
+
+
+def FindCheckMacro(line):
+  """Find a replaceable CHECK-like macro.
+
+  Args:
+    line: line to search on.
+  Returns:
+    (macro name, start position), or (None, -1) if no replaceable
+    macro is found.
+  """
+  for macro in _CHECK_MACROS:
+    i = line.find(macro)
+    if i >= 0:
+      # Find opening parenthesis.  Do a regular expression match here
+      # to make sure that we are matching the expected CHECK macro, as
+      # opposed to some other macro that happens to contain the CHECK
+      # substring.
+      matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
+      if not matched:
+        continue
+      return (macro, len(matched.group(1)))
+  return (None, -1)
+
+
+def CheckCheck(filename, clean_lines, linenum, error):
+  """Checks the use of CHECK and EXPECT macros.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+
+  # Decide the set of replacement macros that should be suggested
+  lines = clean_lines.elided
+  (check_macro, start_pos) = FindCheckMacro(lines[linenum])
+  if not check_macro:
+    return
+
+  # Find end of the boolean expression by matching parentheses
+  (last_line, end_line, end_pos) = CloseExpression(
+      clean_lines, linenum, start_pos)
+  if end_pos < 0:
+    return
+
+  # If the check macro is followed by something other than a
+  # semicolon, assume users will log their own custom error messages
+  # and don't suggest any replacements.
+  if not Match(r'\s*;', last_line[end_pos:]):
+    return
+
+  if linenum == end_line:
+    expression = lines[linenum][start_pos + 1:end_pos - 1]
+  else:
+    expression = lines[linenum][start_pos + 1:]
+    for i in xrange(linenum + 1, end_line):
+      expression += lines[i]
+    expression += last_line[0:end_pos - 1]
+
+  # Parse expression so that we can take parentheses into account.
+  # This avoids false positives for inputs like "CHECK((a < 4) == b)",
+  # which is not replaceable by CHECK_LE.
+  lhs = ''
+  rhs = ''
+  operator = None
+  while expression:
+    matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
+                    r'==|!=|>=|>|<=|<|\()(.*)$', expression)
+    if matched:
+      token = matched.group(1)
+      if token == '(':
+        # Parenthesized operand
+        expression = matched.group(2)
+        (end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
+        if end < 0:
+          return  # Unmatched parenthesis
+        lhs += '(' + expression[0:end]
+        expression = expression[end:]
+      elif token in ('&&', '||'):
+        # Logical and/or operators.  This means the expression
+        # contains more than one term, for example:
+        #   CHECK(42 < a && a < b);
+        #
+        # These are not replaceable with CHECK_LE, so bail out early.
+        return
+      elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
+        # Non-relational operator
+        lhs += token
+        expression = matched.group(2)
+      else:
+        # Relational operator
+        operator = token
+        rhs = matched.group(2)
+        break
+    else:
+      # Unparenthesized operand.  Instead of appending to lhs one character
+      # at a time, we do another regular expression match to consume several
+      # characters at once if possible.  Trivial benchmark shows that this
+      # is more efficient when the operands are longer than a single
+      # character, which is generally the case.
+      matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
+      if not matched:
+        matched = Match(r'^(\s*\S)(.*)$', expression)
+        if not matched:
+          break
+      lhs += matched.group(1)
+      expression = matched.group(2)
+
+  # Only apply checks if we got all parts of the boolean expression
+  if not (lhs and operator and rhs):
+    return
+
+  # Check that rhs do not contain logical operators.  We already know
+  # that lhs is fine since the loop above parses out && and ||.
+  if rhs.find('&&') > -1 or rhs.find('||') > -1:
+    return
+
+  # At least one of the operands must be a constant literal.  This is
+  # to avoid suggesting replacements for unprintable things like
+  # CHECK(variable != iterator)
+  #
+  # The following pattern matches decimal, hex integers, strings, and
+  # characters (in that order).
+  lhs = lhs.strip()
+  rhs = rhs.strip()
+  match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
+  if Match(match_constant, lhs) or Match(match_constant, rhs):
+    # Note: since we know both lhs and rhs, we can provide a more
+    # descriptive error message like:
+    #   Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
+    # Instead of:
+    #   Consider using CHECK_EQ instead of CHECK(a == b)
+    #
+    # We are still keeping the less descriptive message because if lhs
+    # or rhs gets long, the error message might become unreadable.
+    error(filename, linenum, 'readability/check', 2,
+          'Consider using %s instead of %s(a %s b)' % (
+              _CHECK_REPLACEMENT[check_macro][operator],
+              check_macro, operator))
+
+
+def CheckAltTokens(filename, clean_lines, linenum, error):
+  """Check alternative keywords being used in boolean expressions.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Avoid preprocessor lines
+  if Match(r'^\s*#', line):
+    return
+
+  # Last ditch effort to avoid multi-line comments.  This will not help
+  # if the comment started before the current line or ended after the
+  # current line, but it catches most of the false positives.  At least,
+  # it provides a way to workaround this warning for people who use
+  # multi-line comments in preprocessor macros.
+  #
+  # TODO(unknown): remove this once cpplint has better support for
+  # multi-line comments.
+  if line.find('/*') >= 0 or line.find('*/') >= 0:
+    return
+
+  for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
+    error(filename, linenum, 'readability/alt_tokens', 2,
+          'Use operator %s instead of %s' % (
+              _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
+
+
+def GetLineWidth(line):
+  """Determines the width of the line in column positions.
+
+  Args:
+    line: A string, which may be a Unicode string.
+
+  Returns:
+    The width of the line in column positions, accounting for Unicode
+    combining characters and wide characters.
+  """
+  if isinstance(line, unicode):
+    width = 0
+    for uc in unicodedata.normalize('NFC', line):
+      if unicodedata.east_asian_width(uc) in ('W', 'F'):
+        width += 2
+      elif not unicodedata.combining(uc):
+        width += 1
+    return width
+  else:
+    return len(line)
+
+
+def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
+               error):
+  """Checks rules from the 'C++ style rules' section of cppguide.html.
+
+  Most of these rules are hard to test (naming, comment style), but we
+  do what we can.  In particular we check for 2-space indents, line lengths,
+  tab usage, spaces inside code, etc.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    file_extension: The extension (without the dot) of the filename.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+
+  # Don't use "elided" lines here, otherwise we can't check commented lines.
+  # Don't want to use "raw" either, because we don't want to check inside C++11
+  # raw strings,
+  raw_lines = clean_lines.lines_without_raw_strings
+  line = raw_lines[linenum]
+  prev = raw_lines[linenum - 1] if linenum > 0 else ''
+
+  if line.find('\t') != -1:
+    error(filename, linenum, 'whitespace/tab', 1,
+          'Tab found; better to use spaces')
+
+  # One or three blank spaces at the beginning of the line is weird; it's
+  # hard to reconcile that with 2-space indents.
+  # NOTE: here are the conditions rob pike used for his tests.  Mine aren't
+  # as sophisticated, but it may be worth becoming so:  RLENGTH==initial_spaces
+  # if(RLENGTH > 20) complain = 0;
+  # if(match($0, " +(error|private|public|protected):")) complain = 0;
+  # if(match(prev, "&& *$")) complain = 0;
+  # if(match(prev, "\\|\\| *$")) complain = 0;
+  # if(match(prev, "[\",=><] *$")) complain = 0;
+  # if(match($0, " <<")) complain = 0;
+  # if(match(prev, " +for \\(")) complain = 0;
+  # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
+  scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$'
+  classinfo = nesting_state.InnermostClass()
+  initial_spaces = 0
+  cleansed_line = clean_lines.elided[linenum]
+  while initial_spaces < len(line) and line[initial_spaces] == ' ':
+    initial_spaces += 1
+  # There are certain situations we allow one space, notably for
+  # section labels, and also lines containing multi-line raw strings.
+  # We also don't check for lines that look like continuation lines
+  # (of lines ending in double quotes, commas, equals, or angle brackets)
+  # because the rules for how to indent those are non-trivial.
+  if (not Search(r'[",=><] *$', prev) and
+      (initial_spaces == 1 or initial_spaces == 3) and
+      not Match(scope_or_label_pattern, cleansed_line) and
+      not (clean_lines.raw_lines[linenum] != line and
+           Match(r'^\s*""', line))):
+    error(filename, linenum, 'whitespace/indent', 3,
+          'Weird number of spaces at line-start.  '
+          'Are you using a 2-space indent?')
+
+  if line and line[-1].isspace():
+    error(filename, linenum, 'whitespace/end_of_line', 4,
+          'Line ends in whitespace.  Consider deleting these extra spaces.')
+
+  # Check if the line is a header guard.
+  is_header_guard = False
+  if IsHeaderExtension(file_extension):
+    cppvar = GetHeaderGuardCPPVariable(filename)
+    if (line.startswith('#ifndef %s' % cppvar) or
+        line.startswith('#define %s' % cppvar) or
+        line.startswith('#endif  // %s' % cppvar)):
+      is_header_guard = True
+  # #include lines and header guards can be long, since there's no clean way to
+  # split them.
+  #
+  # URLs can be long too.  It's possible to split these, but it makes them
+  # harder to cut&paste.
+  #
+  # The "$Id:...$" comment may also get very long without it being the
+  # developers fault.
+  if (not line.startswith('#include') and not is_header_guard and
+      not Match(r'^\s*//.*http(s?)://\S*$', line) and
+      not Match(r'^\s*//\s*[^\s]*$', line) and
+      not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
+    line_width = GetLineWidth(line)
+    if line_width > _line_length:
+      error(filename, linenum, 'whitespace/line_length', 2,
+            'Lines should be <= %i characters long' % _line_length)
+
+  if (cleansed_line.count(';') > 1 and
+      # for loops are allowed two ;'s (and may run over two lines).
+      cleansed_line.find('for') == -1 and
+      (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
+       GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
+      # It's ok to have many commands in a switch case that fits in 1 line
+      not ((cleansed_line.find('case ') != -1 or
+            cleansed_line.find('default:') != -1) and
+           cleansed_line.find('break;') != -1)):
+    error(filename, linenum, 'whitespace/newline', 0,
+          'More than one command on the same line')
+
+  # Some more style checks
+  CheckBraces(filename, clean_lines, linenum, error)
+  CheckTrailingSemicolon(filename, clean_lines, linenum, error)
+  CheckEmptyBlockBody(filename, clean_lines, linenum, error)
+  CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
+  CheckOperatorSpacing(filename, clean_lines, linenum, error)
+  CheckParenthesisSpacing(filename, clean_lines, linenum, error)
+  CheckCommaSpacing(filename, clean_lines, linenum, error)
+  CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
+  CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
+  CheckCheck(filename, clean_lines, linenum, error)
+  CheckAltTokens(filename, clean_lines, linenum, error)
+  classinfo = nesting_state.InnermostClass()
+  if classinfo:
+    CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
+
+
+_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
+# Matches the first component of a filename delimited by -s and _s. That is:
+#  _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
+#  _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
+#  _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
+#  _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
+_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
+
+
+def _DropCommonSuffixes(filename):
+  """Drops common suffixes like _test.cc or -inl.h from filename.
+
+  For example:
+    >>> _DropCommonSuffixes('foo/foo-inl.h')
+    'foo/foo'
+    >>> _DropCommonSuffixes('foo/bar/foo.cc')
+    'foo/bar/foo'
+    >>> _DropCommonSuffixes('foo/foo_internal.h')
+    'foo/foo'
+    >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
+    'foo/foo_unusualinternal'
+
+  Args:
+    filename: The input filename.
+
+  Returns:
+    The filename with the common suffix removed.
+  """
+  for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
+                 'inl.h', 'impl.h', 'internal.h'):
+    if (filename.endswith(suffix) and len(filename) > len(suffix) and
+        filename[-len(suffix) - 1] in ('-', '_')):
+      return filename[:-len(suffix) - 1]
+  return os.path.splitext(filename)[0]
+
+
+def _ClassifyInclude(fileinfo, include, is_system):
+  """Figures out what kind of header 'include' is.
+
+  Args:
+    fileinfo: The current file cpplint is running over. A FileInfo instance.
+    include: The path to a #included file.
+    is_system: True if the #include used <> rather than "".
+
+  Returns:
+    One of the _XXX_HEADER constants.
+
+  For example:
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
+    _C_SYS_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
+    _CPP_SYS_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
+    _LIKELY_MY_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
+    ...                  'bar/foo_other_ext.h', False)
+    _POSSIBLE_MY_HEADER
+    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
+    _OTHER_HEADER
+  """
+  # This is a list of all standard c++ header files, except
+  # those already checked for above.
+  is_cpp_h = include in _CPP_HEADERS
+
+  if is_system:
+    if is_cpp_h:
+      return _CPP_SYS_HEADER
+    else:
+      return _C_SYS_HEADER
+
+  # If the target file and the include we're checking share a
+  # basename when we drop common extensions, and the include
+  # lives in . , then it's likely to be owned by the target file.
+  target_dir, target_base = (
+      os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
+  include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
+  if target_base == include_base and (
+      include_dir == target_dir or
+      include_dir == os.path.normpath(target_dir + '/../public')):
+    return _LIKELY_MY_HEADER
+
+  # If the target and include share some initial basename
+  # component, it's possible the target is implementing the
+  # include, so it's allowed to be first, but we'll never
+  # complain if it's not there.
+  target_first_component = _RE_FIRST_COMPONENT.match(target_base)
+  include_first_component = _RE_FIRST_COMPONENT.match(include_base)
+  if (target_first_component and include_first_component and
+      target_first_component.group(0) ==
+      include_first_component.group(0)):
+    return _POSSIBLE_MY_HEADER
+
+  return _OTHER_HEADER
+
+
+
+def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
+  """Check rules that are applicable to #include lines.
+
+  Strings on #include lines are NOT removed from elided line, to make
+  certain tasks easier. However, to prevent false positives, checks
+  applicable to #include lines in CheckLanguage must be put here.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    include_state: An _IncludeState instance in which the headers are inserted.
+    error: The function to call with any errors found.
+  """
+  fileinfo = FileInfo(filename)
+  line = clean_lines.lines[linenum]
+
+  # "include" should use the new style "foo/bar.h" instead of just "bar.h"
+  # Only do this check if the included header follows google naming
+  # conventions.  If not, assume that it's a 3rd party API that
+  # requires special include conventions.
+  #
+  # We also make an exception for Lua headers, which follow google
+  # naming convention but not the include convention.
+  match = Match(r'#include\s*"([^/]+\.h)"', line)
+  if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
+    error(filename, linenum, 'build/include', 4,
+          'Include the directory when naming .h files')
+
+  # we shouldn't include a file more than once. actually, there are a
+  # handful of instances where doing so is okay, but in general it's
+  # not.
+  match = _RE_PATTERN_INCLUDE.search(line)
+  if match:
+    include = match.group(2)
+    is_system = (match.group(1) == '<')
+    duplicate_line = include_state.FindHeader(include)
+    if duplicate_line >= 0:
+      error(filename, linenum, 'build/include', 4,
+            '"%s" already included at %s:%s' %
+            (include, filename, duplicate_line))
+    elif (include.endswith('.cc') and
+          os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
+      error(filename, linenum, 'build/include', 4,
+            'Do not include .cc files from other packages')
+    elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
+      include_state.include_list[-1].append((include, linenum))
+
+      # We want to ensure that headers appear in the right order:
+      # 1) for foo.cc, foo.h  (preferred location)
+      # 2) c system files
+      # 3) cpp system files
+      # 4) for foo.cc, foo.h  (deprecated location)
+      # 5) other google headers
+      #
+      # We classify each include statement as one of those 5 types
+      # using a number of techniques. The include_state object keeps
+      # track of the highest type seen, and complains if we see a
+      # lower type after that.
+      error_message = include_state.CheckNextIncludeOrder(
+          _ClassifyInclude(fileinfo, include, is_system))
+      if error_message:
+        error(filename, linenum, 'build/include_order', 4,
+              '%s. Should be: %s.h, c system, c++ system, other.' %
+              (error_message, fileinfo.BaseName()))
+      canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
+      if not include_state.IsInAlphabeticalOrder(
+          clean_lines, linenum, canonical_include):
+        error(filename, linenum, 'build/include_alpha', 4,
+              'Include "%s" not in alphabetical order' % include)
+      include_state.SetLastHeader(canonical_include)
+
+
+
+def _GetTextInside(text, start_pattern):
+  r"""Retrieves all the text between matching open and close parentheses.
+
+  Given a string of lines and a regular expression string, retrieve all the text
+  following the expression and between opening punctuation symbols like
+  (, [, or {, and the matching close-punctuation symbol. This properly nested
+  occurrences of the punctuations, so for the text like
+    printf(a(), b(c()));
+  a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
+  start_pattern must match string having an open punctuation symbol at the end.
+
+  Args:
+    text: The lines to extract text. Its comments and strings must be elided.
+           It can be single line and can span multiple lines.
+    start_pattern: The regexp string indicating where to start extracting
+                   the text.
+  Returns:
+    The extracted text.
+    None if either the opening string or ending punctuation could not be found.
+  """
+  # TODO(unknown): Audit cpplint.py to see what places could be profitably
+  # rewritten to use _GetTextInside (and use inferior regexp matching today).
+
+  # Give opening punctuations to get the matching close-punctuations.
+  matching_punctuation = {'(': ')', '{': '}', '[': ']'}
+  closing_punctuation = set(matching_punctuation.itervalues())
+
+  # Find the position to start extracting text.
+  match = re.search(start_pattern, text, re.M)
+  if not match:  # start_pattern not found in text.
+    return None
+  start_position = match.end(0)
+
+  assert start_position > 0, (
+      'start_pattern must ends with an opening punctuation.')
+  assert text[start_position - 1] in matching_punctuation, (
+      'start_pattern must ends with an opening punctuation.')
+  # Stack of closing punctuations we expect to have in text after position.
+  punctuation_stack = [matching_punctuation[text[start_position - 1]]]
+  position = start_position
+  while punctuation_stack and position < len(text):
+    if text[position] == punctuation_stack[-1]:
+      punctuation_stack.pop()
+    elif text[position] in closing_punctuation:
+      # A closing punctuation without matching opening punctuations.
+      return None
+    elif text[position] in matching_punctuation:
+      punctuation_stack.append(matching_punctuation[text[position]])
+    position += 1
+  if punctuation_stack:
+    # Opening punctuations left without matching close-punctuations.
+    return None
+  # punctuations match.
+  return text[start_position:position - 1]
+
+
+# Patterns for matching call-by-reference parameters.
+#
+# Supports nested templates up to 2 levels deep using this messy pattern:
+#   < (?: < (?: < [^<>]*
+#               >
+#           |   [^<>] )*
+#         >
+#     |   [^<>] )*
+#   >
+_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*'  # =~ [[:alpha:]][[:alnum:]]*
+_RE_PATTERN_TYPE = (
+    r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
+    r'(?:\w|'
+    r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
+    r'::)+')
+# A call-by-reference parameter ends with '& identifier'.
+_RE_PATTERN_REF_PARAM = re.compile(
+    r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
+    r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
+# A call-by-const-reference parameter either ends with 'const& identifier'
+# or looks like 'const type& identifier' when 'type' is atomic.
+_RE_PATTERN_CONST_REF_PARAM = (
+    r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
+    r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
+# Stream types.
+_RE_PATTERN_REF_STREAM_PARAM = (
+    r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT + r')')
+
+
+def CheckLanguage(filename, clean_lines, linenum, file_extension,
+                  include_state, nesting_state, error):
+  """Checks rules from the 'C++ language rules' section of cppguide.html.
+
+  Some of these rules are hard to test (function overloading, using
+  uint32 inappropriately), but we do the best we can.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    file_extension: The extension (without the dot) of the filename.
+    include_state: An _IncludeState instance in which the headers are inserted.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  # If the line is empty or consists of entirely a comment, no need to
+  # check it.
+  line = clean_lines.elided[linenum]
+  if not line:
+    return
+
+  match = _RE_PATTERN_INCLUDE.search(line)
+  if match:
+    CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
+    return
+
+  # Reset include state across preprocessor directives.  This is meant
+  # to silence warnings for conditional includes.
+  match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
+  if match:
+    include_state.ResetSection(match.group(1))
+
+  # Make Windows paths like Unix.
+  fullname = os.path.abspath(filename).replace('\\', '/')
+
+  # Perform other checks now that we are sure that this is not an include line
+  CheckCasts(filename, clean_lines, linenum, error)
+  CheckGlobalStatic(filename, clean_lines, linenum, error)
+  CheckPrintf(filename, clean_lines, linenum, error)
+
+  if IsHeaderExtension(file_extension):
+    # TODO(unknown): check that 1-arg constructors are explicit.
+    #                How to tell it's a constructor?
+    #                (handled in CheckForNonStandardConstructs for now)
+    # TODO(unknown): check that classes declare or disable copy/assign
+    #                (level 1 error)
+    pass
+
+  # Check if people are using the verboten C basic types.  The only exception
+  # we regularly allow is "unsigned short port" for port.
+  if Search(r'\bshort port\b', line):
+    if not Search(r'\bunsigned short port\b', line):
+      error(filename, linenum, 'runtime/int', 4,
+            'Use "unsigned short" for ports, not "short"')
+  else:
+    match = Search(r'\b(short|long(?! +double)|long long)\b', line)
+    if match:
+      error(filename, linenum, 'runtime/int', 4,
+            'Use int16/int64/etc, rather than the C type %s' % match.group(1))
+
+  # Check if some verboten operator overloading is going on
+  # TODO(unknown): catch out-of-line unary operator&:
+  #   class X {};
+  #   int operator&(const X& x) { return 42; }  // unary operator&
+  # The trick is it's hard to tell apart from binary operator&:
+  #   class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
+  if Search(r'\boperator\s*&\s*\(\s*\)', line):
+    error(filename, linenum, 'runtime/operator', 4,
+          'Unary operator& is dangerous.  Do not use it.')
+
+  # Check for suspicious usage of "if" like
+  # } if (a == b) {
+  if Search(r'\}\s*if\s*\(', line):
+    error(filename, linenum, 'readability/braces', 4,
+          'Did you mean "else if"? If not, start a new line for "if".')
+
+  # Check for potential format string bugs like printf(foo).
+  # We constrain the pattern not to pick things like DocidForPrintf(foo).
+  # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
+  # TODO(unknown): Catch the following case. Need to change the calling
+  # convention of the whole function to process multiple line to handle it.
+  #   printf(
+  #       boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
+  printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
+  if printf_args:
+    match = Match(r'([\w.\->()]+)$', printf_args)
+    if match and match.group(1) != '__VA_ARGS__':
+      function_name = re.search(r'\b((?:string)?printf)\s*\(',
+                                line, re.I).group(1)
+      error(filename, linenum, 'runtime/printf', 4,
+            'Potential format string bug. Do %s("%%s", %s) instead.'
+            % (function_name, match.group(1)))
+
+  # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
+  match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
+  if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
+    error(filename, linenum, 'runtime/memset', 4,
+          'Did you mean "memset(%s, 0, %s)"?'
+          % (match.group(1), match.group(2)))
+
+  if Search(r'\busing namespace\b', line):
+    error(filename, linenum, 'build/namespaces', 5,
+          'Do not use namespace using-directives.  '
+          'Use using-declarations instead.')
+
+  # Detect variable-length arrays.
+  match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
+  if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
+      match.group(3).find(']') == -1):
+    # Split the size using space and arithmetic operators as delimiters.
+    # If any of the resulting tokens are not compile time constants then
+    # report the error.
+    tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
+    is_const = True
+    skip_next = False
+    for tok in tokens:
+      if skip_next:
+        skip_next = False
+        continue
+
+      if Search(r'sizeof\(.+\)', tok): continue
+      if Search(r'arraysize\(\w+\)', tok): continue
+
+      tok = tok.lstrip('(')
+      tok = tok.rstrip(')')
+      if not tok: continue
+      if Match(r'\d+', tok): continue
+      if Match(r'0[xX][0-9a-fA-F]+', tok): continue
+      if Match(r'k[A-Z0-9]\w*', tok): continue
+      if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
+      if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
+      # A catch all for tricky sizeof cases, including 'sizeof expression',
+      # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
+      # requires skipping the next token because we split on ' ' and '*'.
+      if tok.startswith('sizeof'):
+        skip_next = True
+        continue
+      is_const = False
+      break
+    if not is_const:
+      error(filename, linenum, 'runtime/arrays', 1,
+            'Do not use variable-length arrays.  Use an appropriately named '
+            "('k' followed by CamelCase) compile-time constant for the size.")
+
+  # Check for use of unnamed namespaces in header files.  Registration
+  # macros are typically OK, so we allow use of "namespace {" on lines
+  # that end with backslashes.
+  if (IsHeaderExtension(file_extension)
+      and Search(r'\bnamespace\s*{', line)
+      and line[-1] != '\\'):
+    error(filename, linenum, 'build/namespaces', 4,
+          'Do not use unnamed namespaces in header files.  See '
+          'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
+          ' for more information.')
+
+
+def CheckGlobalStatic(filename, clean_lines, linenum, error):
+  """Check for unsafe global or static objects.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Match two lines at a time to support multiline declarations
+  if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
+    line += clean_lines.elided[linenum + 1].strip()
+
+  # Check for people declaring static/global STL strings at the top level.
+  # This is dangerous because the C++ language does not guarantee that
+  # globals with constructors are initialized before the first access, and
+  # also because globals can be destroyed when some threads are still running.
+  # TODO(unknown): Generalize this to also find static unique_ptr instances.
+  # TODO(unknown): File bugs for clang-tidy to find these.
+  match = Match(
+      r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +'
+      r'([a-zA-Z0-9_:]+)\b(.*)',
+      line)
+
+  # Remove false positives:
+  # - String pointers (as opposed to values).
+  #    string *pointer
+  #    const string *pointer
+  #    string const *pointer
+  #    string *const pointer
+  #
+  # - Functions and template specializations.
+  #    string Function<Type>(...
+  #    string Class<Type>::Method(...
+  #
+  # - Operators.  These are matched separately because operator names
+  #   cross non-word boundaries, and trying to match both operators
+  #   and functions at the same time would decrease accuracy of
+  #   matching identifiers.
+  #    string Class::operator*()
+  if (match and
+      not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and
+      not Search(r'\boperator\W', line) and
+      not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
+    if Search(r'\bconst\b', line):
+      error(filename, linenum, 'runtime/string', 4,
+            'For a static/global string constant, use a C style string '
+            'instead: "%schar%s %s[]".' %
+            (match.group(1), match.group(2) or '', match.group(3)))
+    else:
+      error(filename, linenum, 'runtime/string', 4,
+            'Static/global string variables are not permitted.')
+
+  if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or
+      Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
+    error(filename, linenum, 'runtime/init', 4,
+          'You seem to be initializing a member variable with itself.')
+
+
+def CheckPrintf(filename, clean_lines, linenum, error):
+  """Check for printf related issues.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # When snprintf is used, the second argument shouldn't be a literal.
+  match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
+  if match and match.group(2) != '0':
+    # If 2nd arg is zero, snprintf is used to calculate size.
+    error(filename, linenum, 'runtime/printf', 3,
+          'If you can, use sizeof(%s) instead of %s as the 2nd arg '
+          'to snprintf.' % (match.group(1), match.group(2)))
+
+  # Check if some verboten C functions are being used.
+  if Search(r'\bsprintf\s*\(', line):
+    error(filename, linenum, 'runtime/printf', 5,
+          'Never use sprintf. Use snprintf instead.')
+  match = Search(r'\b(strcpy|strcat)\s*\(', line)
+  if match:
+    error(filename, linenum, 'runtime/printf', 4,
+          'Almost always, snprintf is better than %s' % match.group(1))
+
+
+def IsDerivedFunction(clean_lines, linenum):
+  """Check if current line contains an inherited function.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line contains a function with "override"
+    virt-specifier.
+  """
+  # Scan back a few lines for start of current function
+  for i in xrange(linenum, max(-1, linenum - 10), -1):
+    match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
+    if match:
+      # Look for "override" after the matching closing parenthesis
+      line, _, closing_paren = CloseExpression(
+          clean_lines, i, len(match.group(1)))
+      return (closing_paren >= 0 and
+              Search(r'\boverride\b', line[closing_paren:]))
+  return False
+
+
+def IsOutOfLineMethodDefinition(clean_lines, linenum):
+  """Check if current line contains an out-of-line method definition.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line contains an out-of-line method definition.
+  """
+  # Scan back a few lines for start of current function
+  for i in xrange(linenum, max(-1, linenum - 10), -1):
+    if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
+      return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
+  return False
+
+
+def IsInitializerList(clean_lines, linenum):
+  """Check if current line is inside constructor initializer list.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+  Returns:
+    True if current line appears to be inside constructor initializer
+    list, False otherwise.
+  """
+  for i in xrange(linenum, 1, -1):
+    line = clean_lines.elided[i]
+    if i == linenum:
+      remove_function_body = Match(r'^(.*)\{\s*$', line)
+      if remove_function_body:
+        line = remove_function_body.group(1)
+
+    if Search(r'\s:\s*\w+[({]', line):
+      # A lone colon tend to indicate the start of a constructor
+      # initializer list.  It could also be a ternary operator, which
+      # also tend to appear in constructor initializer lists as
+      # opposed to parameter lists.
+      return True
+    if Search(r'\}\s*,\s*$', line):
+      # A closing brace followed by a comma is probably the end of a
+      # brace-initialized member in constructor initializer list.
+      return True
+    if Search(r'[{};]\s*$', line):
+      # Found one of the following:
+      # - A closing brace or semicolon, probably the end of the previous
+      #   function.
+      # - An opening brace, probably the start of current class or namespace.
+      #
+      # Current line is probably not inside an initializer list since
+      # we saw one of those things without seeing the starting colon.
+      return False
+
+  # Got to the beginning of the file without seeing the start of
+  # constructor initializer list.
+  return False
+
+
+def CheckForNonConstReference(filename, clean_lines, linenum,
+                              nesting_state, error):
+  """Check for non-const references.
+
+  Separate from CheckLanguage since it scans backwards from current
+  line, instead of scanning forward.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: The function to call with any errors found.
+  """
+  # Do nothing if there is no '&' on current line.
+  line = clean_lines.elided[linenum]
+  if '&' not in line:
+    return
+
+  # If a function is inherited, current function doesn't have much of
+  # a choice, so any non-const references should not be blamed on
+  # derived function.
+  if IsDerivedFunction(clean_lines, linenum):
+    return
+
+  # Don't warn on out-of-line method definitions, as we would warn on the
+  # in-line declaration, if it isn't marked with 'override'.
+  if IsOutOfLineMethodDefinition(clean_lines, linenum):
+    return
+
+  # Long type names may be broken across multiple lines, usually in one
+  # of these forms:
+  #   LongType
+  #       ::LongTypeContinued &identifier
+  #   LongType::
+  #       LongTypeContinued &identifier
+  #   LongType<
+  #       ...>::LongTypeContinued &identifier
+  #
+  # If we detected a type split across two lines, join the previous
+  # line to current line so that we can match const references
+  # accordingly.
+  #
+  # Note that this only scans back one line, since scanning back
+  # arbitrary number of lines would be expensive.  If you have a type
+  # that spans more than 2 lines, please use a typedef.
+  if linenum > 1:
+    previous = None
+    if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
+      # previous_line\n + ::current_line
+      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
+                        clean_lines.elided[linenum - 1])
+    elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
+      # previous_line::\n + current_line
+      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
+                        clean_lines.elided[linenum - 1])
+    if previous:
+      line = previous.group(1) + line.lstrip()
+    else:
+      # Check for templated parameter that is split across multiple lines
+      endpos = line.rfind('>')
+      if endpos > -1:
+        (_, startline, startpos) = ReverseCloseExpression(
+            clean_lines, linenum, endpos)
+        if startpos > -1 and startline < linenum:
+          # Found the matching < on an earlier line, collect all
+          # pieces up to current line.
+          line = ''
+          for i in xrange(startline, linenum + 1):
+            line += clean_lines.elided[i].strip()
+
+  # Check for non-const references in function parameters.  A single '&' may
+  # found in the following places:
+  #   inside expression: binary & for bitwise AND
+  #   inside expression: unary & for taking the address of something
+  #   inside declarators: reference parameter
+  # We will exclude the first two cases by checking that we are not inside a
+  # function body, including one that was just introduced by a trailing '{'.
+  # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
+  if (nesting_state.previous_stack_top and
+      not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
+           isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
+    # Not at toplevel, not within a class, and not within a namespace
+    return
+
+  # Avoid initializer lists.  We only need to scan back from the
+  # current line for something that starts with ':'.
+  #
+  # We don't need to check the current line, since the '&' would
+  # appear inside the second set of parentheses on the current line as
+  # opposed to the first set.
+  if linenum > 0:
+    for i in xrange(linenum - 1, max(0, linenum - 10), -1):
+      previous_line = clean_lines.elided[i]
+      if not Search(r'[),]\s*$', previous_line):
+        break
+      if Match(r'^\s*:\s+\S', previous_line):
+        return
+
+  # Avoid preprocessors
+  if Search(r'\\\s*$', line):
+    return
+
+  # Avoid constructor initializer lists
+  if IsInitializerList(clean_lines, linenum):
+    return
+
+  # We allow non-const references in a few standard places, like functions
+  # called "swap()" or iostream operators like "<<" or ">>".  Do not check
+  # those function parameters.
+  #
+  # We also accept & in static_assert, which looks like a function but
+  # it's actually a declaration expression.
+  whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
+                           r'operator\s*[<>][<>]|'
+                           r'static_assert|COMPILE_ASSERT'
+                           r')\s*\(')
+  if Search(whitelisted_functions, line):
+    return
+  elif not Search(r'\S+\([^)]*$', line):
+    # Don't see a whitelisted function on this line.  Actually we
+    # didn't see any function name on this line, so this is likely a
+    # multi-line parameter list.  Try a bit harder to catch this case.
+    for i in xrange(2):
+      if (linenum > i and
+          Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
+        return
+
+  decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
+  for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
+    if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
+        not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
+      error(filename, linenum, 'runtime/references', 2,
+            'Is this a non-const reference? '
+            'If so, make const or use a pointer: ' +
+            ReplaceAll(' *<', '<', parameter))
+
+
+def CheckCasts(filename, clean_lines, linenum, error):
+  """Various cast related checks.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Check to see if they're using an conversion function cast.
+  # I just try to capture the most common basic types, though there are more.
+  # Parameterless conversion functions, such as bool(), are allowed as they are
+  # probably a member operator declaration or default constructor.
+  match = Search(
+      r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b'
+      r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
+      r'(\([^)].*)', line)
+  expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
+  if match and not expecting_function:
+    matched_type = match.group(2)
+
+    # matched_new_or_template is used to silence two false positives:
+    # - New operators
+    # - Template arguments with function types
+    #
+    # For template arguments, we match on types immediately following
+    # an opening bracket without any spaces.  This is a fast way to
+    # silence the common case where the function type is the first
+    # template argument.  False negative with less-than comparison is
+    # avoided because those operators are usually followed by a space.
+    #
+    #   function<double(double)>   // bracket + no space = false positive
+    #   value < double(42)         // bracket + space = true positive
+    matched_new_or_template = match.group(1)
+
+    # Avoid arrays by looking for brackets that come after the closing
+    # parenthesis.
+    if Match(r'\([^()]+\)\s*\[', match.group(3)):
+      return
+
+    # Other things to ignore:
+    # - Function pointers
+    # - Casts to pointer types
+    # - Placement new
+    # - Alias declarations
+    matched_funcptr = match.group(3)
+    if (matched_new_or_template is None and
+        not (matched_funcptr and
+             (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
+                    matched_funcptr) or
+              matched_funcptr.startswith('(*)'))) and
+        not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
+        not Search(r'new\(\S+\)\s*' + matched_type, line)):
+      error(filename, linenum, 'readability/casting', 4,
+            'Using deprecated casting style.  '
+            'Use static_cast<%s>(...) instead' %
+            matched_type)
+
+  if not expecting_function:
+    CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
+                    r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
+
+  # This doesn't catch all cases. Consider (const char * const)"hello".
+  #
+  # (char *) "foo" should always be a const_cast (reinterpret_cast won't
+  # compile).
+  if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast',
+                     r'\((char\s?\*+\s?)\)\s*"', error):
+    pass
+  else:
+    # Check pointer casts for other than string constants
+    CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast',
+                    r'\((\w+\s?\*+\s?)\)', error)
+
+  # In addition, we look for people taking the address of a cast.  This
+  # is dangerous -- casts can assign to temporaries, so the pointer doesn't
+  # point where you think.
+  #
+  # Some non-identifier character is required before the '&' for the
+  # expression to be recognized as a cast.  These are casts:
+  #   expression = &static_cast<int*>(temporary());
+  #   function(&(int*)(temporary()));
+  #
+  # This is not a cast:
+  #   reference_type&(int* function_param);
+  match = Search(
+      r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
+      r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
+  if match:
+    # Try a better error message when the & is bound to something
+    # dereferenced by the casted pointer, as opposed to the casted
+    # pointer itself.
+    parenthesis_error = False
+    match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
+    if match:
+      _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
+      if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
+        _, y2, x2 = CloseExpression(clean_lines, y1, x1)
+        if x2 >= 0:
+          extended_line = clean_lines.elided[y2][x2:]
+          if y2 < clean_lines.NumLines() - 1:
+            extended_line += clean_lines.elided[y2 + 1]
+          if Match(r'\s*(?:->|\[)', extended_line):
+            parenthesis_error = True
+
+    if parenthesis_error:
+      error(filename, linenum, 'readability/casting', 4,
+            ('Are you taking an address of something dereferenced '
+             'from a cast?  Wrapping the dereferenced expression in '
+             'parentheses will make the binding more obvious'))
+    else:
+      error(filename, linenum, 'runtime/casting', 4,
+            ('Are you taking an address of a cast?  '
+             'This is dangerous: could be a temp var.  '
+             'Take the address before doing the cast, rather than after'))
+
+
+def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
+  """Checks for a C-style cast by looking for the pattern.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    cast_type: The string for the C++ cast to recommend.  This is either
+      reinterpret_cast, static_cast, or const_cast, depending.
+    pattern: The regular expression used to find C-style casts.
+    error: The function to call with any errors found.
+
+  Returns:
+    True if an error was emitted.
+    False otherwise.
+  """
+  line = clean_lines.elided[linenum]
+  match = Search(pattern, line)
+  if not match:
+    return False
+
+  # Exclude lines with keywords that tend to look like casts
+  context = line[0:match.start(1) - 1]
+  if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
+    return False
+
+  # Try expanding current context to see if we one level of
+  # parentheses inside a macro.
+  if linenum > 0:
+    for i in xrange(linenum - 1, max(0, linenum - 5), -1):
+      context = clean_lines.elided[i] + context
+  if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
+    return False
+
+  # operator++(int) and operator--(int)
+  if context.endswith(' operator++') or context.endswith(' operator--'):
+    return False
+
+  # A single unnamed argument for a function tends to look like old style cast.
+  # If we see those, don't issue warnings for deprecated casts.
+  remainder = line[match.end(0):]
+  if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
+           remainder):
+    return False
+
+  # At this point, all that should be left is actual casts.
+  error(filename, linenum, 'readability/casting', 4,
+        'Using C-style cast.  Use %s<%s>(...) instead' %
+        (cast_type, match.group(1)))
+
+  return True
+
+
+def ExpectingFunctionArgs(clean_lines, linenum):
+  """Checks whether where function type arguments are expected.
+
+  Args:
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+
+  Returns:
+    True if the line at 'linenum' is inside something that expects arguments
+    of function types.
+  """
+  line = clean_lines.elided[linenum]
+  return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
+          (linenum >= 2 and
+           (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
+                  clean_lines.elided[linenum - 1]) or
+            Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
+                  clean_lines.elided[linenum - 2]) or
+            Search(r'\bstd::m?function\s*\<\s*$',
+                   clean_lines.elided[linenum - 1]))))
+
+
+_HEADERS_CONTAINING_TEMPLATES = (
+    ('<deque>', ('deque',)),
+    ('<functional>', ('unary_function', 'binary_function',
+                      'plus', 'minus', 'multiplies', 'divides', 'modulus',
+                      'negate',
+                      'equal_to', 'not_equal_to', 'greater', 'less',
+                      'greater_equal', 'less_equal',
+                      'logical_and', 'logical_or', 'logical_not',
+                      'unary_negate', 'not1', 'binary_negate', 'not2',
+                      'bind1st', 'bind2nd',
+                      'pointer_to_unary_function',
+                      'pointer_to_binary_function',
+                      'ptr_fun',
+                      'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
+                      'mem_fun_ref_t',
+                      'const_mem_fun_t', 'const_mem_fun1_t',
+                      'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
+                      'mem_fun_ref',
+                     )),
+    ('<limits>', ('numeric_limits',)),
+    ('<list>', ('list',)),
+    ('<map>', ('map', 'multimap',)),
+    ('<memory>', ('allocator', 'make_shared', 'make_unique', 'shared_ptr',
+                  'unique_ptr', 'weak_ptr')),
+    ('<queue>', ('queue', 'priority_queue',)),
+    ('<set>', ('set', 'multiset',)),
+    ('<stack>', ('stack',)),
+    ('<string>', ('char_traits', 'basic_string',)),
+    ('<tuple>', ('tuple',)),
+    ('<unordered_map>', ('unordered_map', 'unordered_multimap')),
+    ('<unordered_set>', ('unordered_set', 'unordered_multiset')),
+    ('<utility>', ('pair',)),
+    ('<vector>', ('vector',)),
+
+    # gcc extensions.
+    # Note: std::hash is their hash, ::hash is our hash
+    ('<hash_map>', ('hash_map', 'hash_multimap',)),
+    ('<hash_set>', ('hash_set', 'hash_multiset',)),
+    ('<slist>', ('slist',)),
+    )
+
+_HEADERS_MAYBE_TEMPLATES = (
+    ('<algorithm>', ('copy', 'max', 'min', 'min_element', 'sort',
+                     'transform',
+                    )),
+    ('<utility>', ('forward', 'make_pair', 'move', 'swap')),
+    )
+
+_RE_PATTERN_STRING = re.compile(r'\bstring\b')
+
+_re_pattern_headers_maybe_templates = []
+for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
+  for _template in _templates:
+    # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
+    # type::max().
+    _re_pattern_headers_maybe_templates.append(
+        (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
+            _template,
+            _header))
+
+# Other scripts may reach in and modify this pattern.
+_re_pattern_templates = []
+for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
+  for _template in _templates:
+    _re_pattern_templates.append(
+        (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
+         _template + '<>',
+         _header))
+
+
+def FilesBelongToSameModule(filename_cc, filename_h):
+  """Check if these two filenames belong to the same module.
+
+  The concept of a 'module' here is a as follows:
+  foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
+  same 'module' if they are in the same directory.
+  some/path/public/xyzzy and some/path/internal/xyzzy are also considered
+  to belong to the same module here.
+
+  If the filename_cc contains a longer path than the filename_h, for example,
+  '/absolute/path/to/base/sysinfo.cc', and this file would include
+  'base/sysinfo.h', this function also produces the prefix needed to open the
+  header. This is used by the caller of this function to more robustly open the
+  header file. We don't have access to the real include paths in this context,
+  so we need this guesswork here.
+
+  Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
+  according to this implementation. Because of this, this function gives
+  some false positives. This should be sufficiently rare in practice.
+
+  Args:
+    filename_cc: is the path for the .cc file
+    filename_h: is the path for the header path
+
+  Returns:
+    Tuple with a bool and a string:
+    bool: True if filename_cc and filename_h belong to the same module.
+    string: the additional prefix needed to open the header file.
+  """
+
+  fileinfo = FileInfo(filename_cc)
+  if not fileinfo.IsSource():
+    return (False, '')
+  filename_cc = filename_cc[:-len(fileinfo.Extension())]
+  matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo.BaseName())
+  if matched_test_suffix:
+    filename_cc = filename_cc[:-len(matched_test_suffix.group(1))]
+  filename_cc = filename_cc.replace('/public/', '/')
+  filename_cc = filename_cc.replace('/internal/', '/')
+
+  if not filename_h.endswith('.h'):
+    return (False, '')
+  filename_h = filename_h[:-len('.h')]
+  if filename_h.endswith('-inl'):
+    filename_h = filename_h[:-len('-inl')]
+  filename_h = filename_h.replace('/public/', '/')
+  filename_h = filename_h.replace('/internal/', '/')
+
+  files_belong_to_same_module = filename_cc.endswith(filename_h)
+  common_path = ''
+  if files_belong_to_same_module:
+    common_path = filename_cc[:-len(filename_h)]
+  return files_belong_to_same_module, common_path
+
+
+def UpdateIncludeState(filename, include_dict, io=codecs):
+  """Fill up the include_dict with new includes found from the file.
+
+  Args:
+    filename: the name of the header to read.
+    include_dict: a dictionary in which the headers are inserted.
+    io: The io factory to use to read the file. Provided for testability.
+
+  Returns:
+    True if a header was successfully added. False otherwise.
+  """
+  headerfile = None
+  try:
+    headerfile = io.open(filename, 'r', 'utf8', 'replace')
+  except IOError:
+    return False
+  linenum = 0
+  for line in headerfile:
+    linenum += 1
+    clean_line = CleanseComments(line)
+    match = _RE_PATTERN_INCLUDE.search(clean_line)
+    if match:
+      include = match.group(2)
+      include_dict.setdefault(include, linenum)
+  return True
+
+
+def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
+                              io=codecs):
+  """Reports for missing stl includes.
+
+  This function will output warnings to make sure you are including the headers
+  necessary for the stl containers and functions that you use. We only give one
+  reason to include a header. For example, if you use both equal_to<> and
+  less<> in a .h file, only one (the latter in the file) of these will be
+  reported as a reason to include the <functional>.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    include_state: An _IncludeState instance.
+    error: The function to call with any errors found.
+    io: The IO factory to use to read the header file. Provided for unittest
+        injection.
+  """
+  required = {}  # A map of header name to linenumber and the template entity.
+                 # Example of required: { '<functional>': (1219, 'less<>') }
+
+  for linenum in xrange(clean_lines.NumLines()):
+    line = clean_lines.elided[linenum]
+    if not line or line[0] == '#':
+      continue
+
+    # String is special -- it is a non-templatized type in STL.
+    matched = _RE_PATTERN_STRING.search(line)
+    if matched:
+      # Don't warn about strings in non-STL namespaces:
+      # (We check only the first match per line; good enough.)
+      prefix = line[:matched.start()]
+      if prefix.endswith('std::') or not prefix.endswith('::'):
+        required['<string>'] = (linenum, 'string')
+
+    for pattern, template, header in _re_pattern_headers_maybe_templates:
+      if pattern.search(line):
+        required[header] = (linenum, template)
+
+    # The following function is just a speed up, no semantics are changed.
+    if not '<' in line:  # Reduces the cpu time usage by skipping lines.
+      continue
+
+    for pattern, template, header in _re_pattern_templates:
+      matched = pattern.search(line)
+      if matched:
+        # Don't warn about IWYU in non-STL namespaces:
+        # (We check only the first match per line; good enough.)
+        prefix = line[:matched.start()]
+        if prefix.endswith('std::') or not prefix.endswith('::'):
+          required[header] = (linenum, template)
+
+  # The policy is that if you #include something in foo.h you don't need to
+  # include it again in foo.cc. Here, we will look at possible includes.
+  # Let's flatten the include_state include_list and copy it into a dictionary.
+  include_dict = dict([item for sublist in include_state.include_list
+                       for item in sublist])
+
+  # Did we find the header for this file (if any) and successfully load it?
+  header_found = False
+
+  # Use the absolute path so that matching works properly.
+  abs_filename = FileInfo(filename).FullName()
+
+  # For Emacs's flymake.
+  # If cpplint is invoked from Emacs's flymake, a temporary file is generated
+  # by flymake and that file name might end with '_flymake.cc'. In that case,
+  # restore original file name here so that the corresponding header file can be
+  # found.
+  # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
+  # instead of 'foo_flymake.h'
+  abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
+
+  # include_dict is modified during iteration, so we iterate over a copy of
+  # the keys.
+  header_keys = include_dict.keys()
+  for header in header_keys:
+    (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
+    fullpath = common_path + header
+    if same_module and UpdateIncludeState(fullpath, include_dict, io):
+      header_found = True
+
+  # If we can't find the header file for a .cc, assume it's because we don't
+  # know where to look. In that case we'll give up as we're not sure they
+  # didn't include it in the .h file.
+  # TODO(unknown): Do a better job of finding .h files so we are confident that
+  # not having the .h file means there isn't one.
+  if filename.endswith('.cc') and not header_found:
+    return
+
+  # All the lines have been processed, report the errors found.
+  for required_header_unstripped in required:
+    template = required[required_header_unstripped][1]
+    if required_header_unstripped.strip('<>"') not in include_dict:
+      error(filename, required[required_header_unstripped][0],
+            'build/include_what_you_use', 4,
+            'Add #include ' + required_header_unstripped + ' for ' + template)
+
+
+_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
+
+
+def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
+  """Check that make_pair's template arguments are deduced.
+
+  G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
+  specified explicitly, and such use isn't intended in any case.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+  match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
+  if match:
+    error(filename, linenum, 'build/explicit_make_pair',
+          4,  # 4 = high confidence
+          'For C++11-compatibility, omit template arguments from make_pair'
+          ' OR use pair directly OR if appropriate, construct a pair directly')
+
+
+def CheckRedundantVirtual(filename, clean_lines, linenum, error):
+  """Check if line contains a redundant "virtual" function-specifier.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  # Look for "virtual" on current line.
+  line = clean_lines.elided[linenum]
+  virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line)
+  if not virtual: return
+
+  # Ignore "virtual" keywords that are near access-specifiers.  These
+  # are only used in class base-specifier and do not apply to member
+  # functions.
+  if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
+      Match(r'^\s+(public|protected|private)\b', virtual.group(3))):
+    return
+
+  # Ignore the "virtual" keyword from virtual base classes.  Usually
+  # there is a column on the same line in these cases (virtual base
+  # classes are rare in google3 because multiple inheritance is rare).
+  if Match(r'^.*[^:]:[^:].*$', line): return
+
+  # Look for the next opening parenthesis.  This is the start of the
+  # parameter list (possibly on the next line shortly after virtual).
+  # TODO(unknown): doesn't work if there are virtual functions with
+  # decltype() or other things that use parentheses, but csearch suggests
+  # that this is rare.
+  end_col = -1
+  end_line = -1
+  start_col = len(virtual.group(2))
+  for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
+    line = clean_lines.elided[start_line][start_col:]
+    parameter_list = Match(r'^([^(]*)\(', line)
+    if parameter_list:
+      # Match parentheses to find the end of the parameter list
+      (_, end_line, end_col) = CloseExpression(
+          clean_lines, start_line, start_col + len(parameter_list.group(1)))
+      break
+    start_col = 0
+
+  if end_col < 0:
+    return  # Couldn't find end of parameter list, give up
+
+  # Look for "override" or "final" after the parameter list
+  # (possibly on the next few lines).
+  for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
+    line = clean_lines.elided[i][end_col:]
+    match = Search(r'\b(override|final)\b', line)
+    if match:
+      error(filename, linenum, 'readability/inheritance', 4,
+            ('"virtual" is redundant since function is '
+             'already declared as "%s"' % match.group(1)))
+
+    # Set end_col to check whole lines after we are done with the
+    # first line.
+    end_col = 0
+    if Search(r'[^\w]\s*$', line):
+      break
+
+
+def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
+  """Check if line contains a redundant "override" or "final" virt-specifier.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  # Look for closing parenthesis nearby.  We need one to confirm where
+  # the declarator ends and where the virt-specifier starts to avoid
+  # false positives.
+  line = clean_lines.elided[linenum]
+  declarator_end = line.rfind(')')
+  if declarator_end >= 0:
+    fragment = line[declarator_end:]
+  else:
+    if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0:
+      fragment = line
+    else:
+      return
+
+  # Check that at most one of "override" or "final" is present, not both
+  if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment):
+    error(filename, linenum, 'readability/inheritance', 4,
+          ('"override" is redundant since function is '
+           'already declared as "final"'))
+
+
+
+
+# Returns true if we are at a new block, and it is directly
+# inside of a namespace.
+def IsBlockInNameSpace(nesting_state, is_forward_declaration):
+  """Checks that the new block is directly in a namespace.
+
+  Args:
+    nesting_state: The _NestingState object that contains info about our state.
+    is_forward_declaration: If the class is a forward declared class.
+  Returns:
+    Whether or not the new block is directly in a namespace.
+  """
+  if is_forward_declaration:
+    if len(nesting_state.stack) >= 1 and (
+        isinstance(nesting_state.stack[-1], _NamespaceInfo)):
+      return True
+    else:
+      return False
+
+  return (len(nesting_state.stack) > 1 and
+          nesting_state.stack[-1].check_namespace_indentation and
+          isinstance(nesting_state.stack[-2], _NamespaceInfo))
+
+
+def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
+                                    raw_lines_no_comments, linenum):
+  """This method determines if we should apply our namespace indentation check.
+
+  Args:
+    nesting_state: The current nesting state.
+    is_namespace_indent_item: If we just put a new class on the stack, True.
+      If the top of the stack is not a class, or we did not recently
+      add the class, False.
+    raw_lines_no_comments: The lines without the comments.
+    linenum: The current line number we are processing.
+
+  Returns:
+    True if we should apply our namespace indentation check. Currently, it
+    only works for classes and namespaces inside of a namespace.
+  """
+
+  is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments,
+                                                     linenum)
+
+  if not (is_namespace_indent_item or is_forward_declaration):
+    return False
+
+  # If we are in a macro, we do not want to check the namespace indentation.
+  if IsMacroDefinition(raw_lines_no_comments, linenum):
+    return False
+
+  return IsBlockInNameSpace(nesting_state, is_forward_declaration)
+
+
+# Call this method if the line is directly inside of a namespace.
+# If the line above is blank (excluding comments) or the start of
+# an inner namespace, it cannot be indented.
+def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum,
+                                    error):
+  line = raw_lines_no_comments[linenum]
+  if Match(r'^\s+', line):
+    error(filename, linenum, 'runtime/indentation_namespace', 4,
+          'Do not indent within a namespace')
+
+
+def ProcessLine(filename, file_extension, clean_lines, line,
+                include_state, function_state, nesting_state, error,
+                extra_check_functions=[]):
+  """Processes a single line in the file.
+
+  Args:
+    filename: Filename of the file that is being processed.
+    file_extension: The extension (dot not included) of the file.
+    clean_lines: An array of strings, each representing a line of the file,
+                 with comments stripped.
+    line: Number of line being processed.
+    include_state: An _IncludeState instance in which the headers are inserted.
+    function_state: A _FunctionState instance which counts function lines, etc.
+    nesting_state: A NestingState instance which maintains information about
+                   the current stack of nested blocks being parsed.
+    error: A callable to which errors are reported, which takes 4 arguments:
+           filename, line number, error level, and message
+    extra_check_functions: An array of additional check functions that will be
+                           run on each source line. Each function takes 4
+                           arguments: filename, clean_lines, line, error
+  """
+  raw_lines = clean_lines.raw_lines
+  ParseNolintSuppressions(filename, raw_lines[line], line, error)
+  nesting_state.Update(filename, clean_lines, line, error)
+  CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
+                               error)
+  if nesting_state.InAsmBlock(): return
+  CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
+  CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
+  CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
+  CheckLanguage(filename, clean_lines, line, file_extension, include_state,
+                nesting_state, error)
+  CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
+  CheckForNonStandardConstructs(filename, clean_lines, line,
+                                nesting_state, error)
+  CheckVlogArguments(filename, clean_lines, line, error)
+  CheckPosixThreading(filename, clean_lines, line, error)
+  CheckInvalidIncrement(filename, clean_lines, line, error)
+  CheckMakePairUsesDeduction(filename, clean_lines, line, error)
+  CheckRedundantVirtual(filename, clean_lines, line, error)
+  CheckRedundantOverrideOrFinal(filename, clean_lines, line, error)
+  for check_fn in extra_check_functions:
+    check_fn(filename, clean_lines, line, error)
+
+def FlagCxx11Features(filename, clean_lines, linenum, error):
+  """Flag those c++11 features that we only allow in certain places.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
+
+  # Flag unapproved C++ TR1 headers.
+  if include and include.group(1).startswith('tr1/'):
+    error(filename, linenum, 'build/c++tr1', 5,
+          ('C++ TR1 headers such as <%s> are unapproved.') % include.group(1))
+
+  # Flag unapproved C++11 headers.
+  if include and include.group(1) in ('cfenv',
+                                      'condition_variable',
+                                      'fenv.h',
+                                      'future',
+                                      'mutex',
+                                      'thread',
+                                      'chrono',
+                                      'ratio',
+                                      'regex',
+                                      'system_error',
+                                     ):
+    error(filename, linenum, 'build/c++11', 5,
+          ('<%s> is an unapproved C++11 header.') % include.group(1))
+
+  # The only place where we need to worry about C++11 keywords and library
+  # features in preprocessor directives is in macro definitions.
+  if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
+
+  # These are classes and free functions.  The classes are always
+  # mentioned as std::*, but we only catch the free functions if
+  # they're not found by ADL.  They're alphabetical by header.
+  for top_name in (
+      # type_traits
+      'alignment_of',
+      'aligned_union',
+      ):
+    if Search(r'\bstd::%s\b' % top_name, line):
+      error(filename, linenum, 'build/c++11', 5,
+            ('std::%s is an unapproved C++11 class or function.  Send c-style '
+             'an example of where it would make your code more readable, and '
+             'they may let you use it.') % top_name)
+
+
+def FlagCxx14Features(filename, clean_lines, linenum, error):
+  """Flag those C++14 features that we restrict.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
+
+  # Flag unapproved C++14 headers.
+  if include and include.group(1) in ('scoped_allocator', 'shared_mutex'):
+    error(filename, linenum, 'build/c++14', 5,
+          ('<%s> is an unapproved C++14 header.') % include.group(1))
+
+
+def ProcessFileData(filename, file_extension, lines, error,
+                    extra_check_functions=[]):
+  """Performs lint checks and reports any errors to the given error function.
+
+  Args:
+    filename: Filename of the file that is being processed.
+    file_extension: The extension (dot not included) of the file.
+    lines: An array of strings, each representing a line of the file, with the
+           last element being empty if the file is terminated with a newline.
+    error: A callable to which errors are reported, which takes 4 arguments:
+           filename, line number, error level, and message
+    extra_check_functions: An array of additional check functions that will be
+                           run on each source line. Each function takes 4
+                           arguments: filename, clean_lines, line, error
+  """
+  lines = (['// marker so line numbers and indices both start at 1'] + lines +
+           ['// marker so line numbers end in a known way'])
+
+  include_state = _IncludeState()
+  function_state = _FunctionState()
+  nesting_state = NestingState()
+
+  ResetNolintSuppressions()
+
+  CheckForCopyright(filename, lines, error)
+  ProcessGlobalSuppresions(lines)
+  RemoveMultiLineComments(filename, lines, error)
+  clean_lines = CleansedLines(lines)
+
+  if IsHeaderExtension(file_extension):
+    CheckForHeaderGuard(filename, clean_lines, error)
+
+  for line in xrange(clean_lines.NumLines()):
+    ProcessLine(filename, file_extension, clean_lines, line,
+                include_state, function_state, nesting_state, error,
+                extra_check_functions)
+    FlagCxx11Features(filename, clean_lines, line, error)
+  nesting_state.CheckCompletedBlocks(filename, error)
+
+  CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
+
+  # Check that the .cc file has included its header if it exists.
+  if _IsSourceExtension(file_extension):
+    CheckHeaderFileIncluded(filename, include_state, error)
+
+  # We check here rather than inside ProcessLine so that we see raw
+  # lines rather than "cleaned" lines.
+  CheckForBadCharacters(filename, lines, error)
+
+  CheckForNewlineAtEOF(filename, lines, error)
+
+def ProcessConfigOverrides(filename):
+  """ Loads the configuration files and processes the config overrides.
+
+  Args:
+    filename: The name of the file being processed by the linter.
+
+  Returns:
+    False if the current |filename| should not be processed further.
+  """
+
+  abs_filename = os.path.abspath(filename)
+  cfg_filters = []
+  keep_looking = True
+  while keep_looking:
+    abs_path, base_name = os.path.split(abs_filename)
+    if not base_name:
+      break  # Reached the root directory.
+
+    cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
+    abs_filename = abs_path
+    if not os.path.isfile(cfg_file):
+      continue
+
+    try:
+      with open(cfg_file) as file_handle:
+        for line in file_handle:
+          line, _, _ = line.partition('#')  # Remove comments.
+          if not line.strip():
+            continue
+
+          name, _, val = line.partition('=')
+          name = name.strip()
+          val = val.strip()
+          if name == 'set noparent':
+            keep_looking = False
+          elif name == 'filter':
+            cfg_filters.append(val)
+          elif name == 'exclude_files':
+            # When matching exclude_files pattern, use the base_name of
+            # the current file name or the directory name we are processing.
+            # For example, if we are checking for lint errors in /foo/bar/baz.cc
+            # and we found the .cfg file at /foo/CPPLINT.cfg, then the config
+            # file's "exclude_files" filter is meant to be checked against "bar"
+            # and not "baz" nor "bar/baz.cc".
+            if base_name:
+              pattern = re.compile(val)
+              if pattern.match(base_name):
+                sys.stderr.write('Ignoring "%s": file excluded by "%s". '
+                                 'File path component "%s" matches '
+                                 'pattern "%s"\n' %
+                                 (filename, cfg_file, base_name, val))
+                return False
+          elif name == 'linelength':
+            global _line_length
+            try:
+                _line_length = int(val)
+            except ValueError:
+                sys.stderr.write('Line length must be numeric.')
+          elif name == 'root':
+            global _root
+            _root = val
+          elif name == 'headers':
+            ProcessHppHeadersOption(val)
+          else:
+            sys.stderr.write(
+                'Invalid configuration option (%s) in file %s\n' %
+                (name, cfg_file))
+
+    except IOError:
+      sys.stderr.write(
+          "Skipping config file '%s': Can't open for reading\n" % cfg_file)
+      keep_looking = False
+
+  # Apply all the accumulated filters in reverse order (top-level directory
+  # config options having the least priority).
+  for filter in reversed(cfg_filters):
+     _AddFilters(filter)
+
+  return True
+
+
+def ProcessFile(filename, vlevel, extra_check_functions=[]):
+  """Does google-lint on a single file.
+
+  Args:
+    filename: The name of the file to parse.
+
+    vlevel: The level of errors to report.  Every error of confidence
+    >= verbose_level will be reported.  0 is a good default.
+
+    extra_check_functions: An array of additional check functions that will be
+                           run on each source line. Each function takes 4
+                           arguments: filename, clean_lines, line, error
+  """
+
+  _SetVerboseLevel(vlevel)
+  _BackupFilters()
+
+  if not ProcessConfigOverrides(filename):
+    _RestoreFilters()
+    return
+
+  lf_lines = []
+  crlf_lines = []
+  try:
+    # Support the UNIX convention of using "-" for stdin.  Note that
+    # we are not opening the file with universal newline support
+    # (which codecs doesn't support anyway), so the resulting lines do
+    # contain trailing '\r' characters if we are reading a file that
+    # has CRLF endings.
+    # If after the split a trailing '\r' is present, it is removed
+    # below.
+    if filename == '-':
+      lines = codecs.StreamReaderWriter(sys.stdin,
+                                        codecs.getreader('utf8'),
+                                        codecs.getwriter('utf8'),
+                                        'replace').read().split('\n')
+    else:
+      lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
+
+    # Remove trailing '\r'.
+    # The -1 accounts for the extra trailing blank line we get from split()
+    for linenum in range(len(lines) - 1):
+      if lines[linenum].endswith('\r'):
+        lines[linenum] = lines[linenum].rstrip('\r')
+        crlf_lines.append(linenum + 1)
+      else:
+        lf_lines.append(linenum + 1)
+
+  except IOError:
+    sys.stderr.write(
+        "Skipping input '%s': Can't open for reading\n" % filename)
+    _RestoreFilters()
+    return
+
+  # Note, if no dot is found, this will give the entire filename as the ext.
+  file_extension = filename[filename.rfind('.') + 1:]
+
+  # When reading from stdin, the extension is unknown, so no cpplint tests
+  # should rely on the extension.
+  if filename != '-' and file_extension not in _valid_extensions:
+    sys.stderr.write('Ignoring %s; not a valid file name '
+                     '(%s)\n' % (filename, ', '.join(_valid_extensions)))
+  else:
+    ProcessFileData(filename, file_extension, lines, Error,
+                    extra_check_functions)
+
+    # If end-of-line sequences are a mix of LF and CR-LF, issue
+    # warnings on the lines with CR.
+    #
+    # Don't issue any warnings if all lines are uniformly LF or CR-LF,
+    # since critique can handle these just fine, and the style guide
+    # doesn't dictate a particular end of line sequence.
+    #
+    # We can't depend on os.linesep to determine what the desired
+    # end-of-line sequence should be, since that will return the
+    # server-side end-of-line sequence.
+    if lf_lines and crlf_lines:
+      # Warn on every line with CR.  An alternative approach might be to
+      # check whether the file is mostly CRLF or just LF, and warn on the
+      # minority, we bias toward LF here since most tools prefer LF.
+      for linenum in crlf_lines:
+        Error(filename, linenum, 'whitespace/newline', 1,
+              'Unexpected \\r (^M) found; better to use only \\n')
+
+  sys.stdout.write('Done processing %s\n' % filename)
+  _RestoreFilters()
+
+
+def PrintUsage(message):
+  """Prints a brief usage string and exits, optionally with an error message.
+
+  Args:
+    message: The optional error message.
+  """
+  sys.stderr.write(_USAGE)
+  if message:
+    sys.exit('\nFATAL ERROR: ' + message)
+  else:
+    sys.exit(1)
+
+
+def PrintCategories():
+  """Prints a list of all the error-categories used by error messages.
+
+  These are the categories used to filter messages via --filter.
+  """
+  sys.stderr.write(''.join('  %s\n' % cat for cat in _ERROR_CATEGORIES))
+  sys.exit(0)
+
+
+def ParseArguments(args):
+  """Parses the command line arguments.
+
+  This may set the output format and verbosity level as side-effects.
+
+  Args:
+    args: The command line arguments:
+
+  Returns:
+    The list of filenames to lint.
+  """
+  try:
+    (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
+                                                 'counting=',
+                                                 'filter=',
+                                                 'root=',
+                                                 'linelength=',
+                                                 'extensions=',
+                                                 'headers='])
+  except getopt.GetoptError:
+    PrintUsage('Invalid arguments.')
+
+  verbosity = _VerboseLevel()
+  output_format = _OutputFormat()
+  filters = ''
+  counting_style = ''
+
+  for (opt, val) in opts:
+    if opt == '--help':
+      PrintUsage(None)
+    elif opt == '--output':
+      if val not in ('emacs', 'vs7', 'eclipse'):
+        PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
+      output_format = val
+    elif opt == '--verbose':
+      verbosity = int(val)
+    elif opt == '--filter':
+      filters = val
+      if not filters:
+        PrintCategories()
+    elif opt == '--counting':
+      if val not in ('total', 'toplevel', 'detailed'):
+        PrintUsage('Valid counting options are total, toplevel, and detailed')
+      counting_style = val
+    elif opt == '--root':
+      global _root
+      _root = val
+    elif opt == '--linelength':
+      global _line_length
+      try:
+          _line_length = int(val)
+      except ValueError:
+          PrintUsage('Line length must be digits.')
+    elif opt == '--extensions':
+      global _valid_extensions
+      try:
+          _valid_extensions = set(val.split(','))
+      except ValueError:
+          PrintUsage('Extensions must be comma seperated list.')
+    elif opt == '--headers':
+      ProcessHppHeadersOption(val)
+
+  if not filenames:
+    PrintUsage('No files were specified.')
+
+  _SetOutputFormat(output_format)
+  _SetVerboseLevel(verbosity)
+  _SetFilters(filters)
+  _SetCountingStyle(counting_style)
+
+  return filenames
+
+
+def main():
+  filenames = ParseArguments(sys.argv[1:])
+
+  # Change stderr to write with replacement characters so we don't die
+  # if we try to print something containing non-ASCII characters.
+  sys.stderr = codecs.StreamReaderWriter(sys.stderr,
+                                         codecs.getreader('utf8'),
+                                         codecs.getwriter('utf8'),
+                                         'replace')
+
+  _cpplint_state.ResetErrorCounts()
+  for filename in filenames:
+    ProcessFile(filename, _cpplint_state.verbose_level)
+  _cpplint_state.PrintErrorCounts()
+
+  sys.exit(_cpplint_state.error_count > 0)
+
+
+if __name__ == '__main__':
+  main()
index 9e5d7c1..b050e3d 100644 (file)
@@ -4,18 +4,35 @@ SET(fw_name "${PROJECT_NAME}")
 SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
 SET(${fw_name}_LDFLAGS)
 
+IF(${USE_MIXER} STREQUAL "yes")
 SET(ADD_LIBS
   "espplayer-core"
   "trackrenderer"
+  "mixer"
 )
+ELSE(${USE_MIXER} STREQUAL "yes")
+SET(ADD_LIBS
+  "espplayer-core"
+  "trackrenderer"
+)
+ENDIF(${USE_MIXER} STREQUAL "yes")
 
-SET(${fw_name}_CXXFLAGS "-Wall -Werror -std=c++11 -fPIC -fno-lto -Wl,-z,relro -fstack-protector -DEFL_BETA_API_SUPPORT")
+SET(${fw_name}_CXXFLAGS "-Wall -Werror -std=c++17 -fPIC -fno-lto -Wl,-z,relro -fstack-protector -DEFL_BETA_API_SUPPORT")
 
 SET(dependents "gstreamer-1.0 glib-2.0 dlog"
                "boost"
                "elementary ecore ecore-wl2"
                "jsoncpp")
 
+IF(${TIZEN_PUBLIC} STREQUAL "OFF")
+SET(dependents ${dependents} ""tv-resource-manager"")
+IF(${PRODUCT_TYPE_AUDIO} STREQUAL "no")
+SET(dependents ${dependents} "libavoc")
+ELSE(${PRODUCT_TYPE_AUDIO} STREQUAL "no")
+SET(dependents ${dependents} "libavoc-av")
+ENDIF(${PRODUCT_TYPE_AUDIO} STREQUAL "no")
+ENDIF(${TIZEN_PUBLIC} STREQUAL "OFF")
+
 INCLUDE(FindPkgConfig)
 
 IF(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
index 0601176..9ad81f9 100644 (file)
@@ -1,9 +1,21 @@
-//
-// @ Copyright [2019] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
-#define __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
+#ifndef __ESPLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
+#define __ESPLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
 
 #include <tbm_surface.h>
 
 #include <functional>
 #include <list>
 #include <memory>
+#ifdef TIZEN_FEATURE_PUBLIC
 #include <gst/gst.h>
+#endif
 
 #include "core/utils/plusplayer_log.h"
-#include "plusplayer/types/buffer.h"
+#include "esplusplayer/types/buffer.h"
 
 namespace {
+// LCOV_EXCL_START
 void DecodedPacketDeleter(esplusplayer_decoded_video_packet* packet) {
+#ifndef TIZEN_FEATURE_PUBLIC
+  if (packet == nullptr || packet->surface_data == nullptr) return;
+#else
   if (packet == nullptr) return;
-  // LOG_DEBUG("packet[%p] deleted", packet);
   if (packet->private_data) { // hw dec
     gst_buffer_unref((GstBuffer *)packet->private_data);
     packet->private_data = nullptr;
-    packet->surface_data = nullptr;
-  } else if (packet->surface_data) {
-    tbm_surface_destroy(static_cast<tbm_surface_h>(packet->surface_data));
-    packet->surface_data = nullptr;
   }
+  if (packet->surface_data == nullptr) return;
+#endif
+  // LOG_DEBUG("packet[%p] deleted", packet);
+  tbm_surface_destroy(static_cast<tbm_surface_h>(packet->surface_data));
+  packet->surface_data = NULL;
+// LCOV_EXCL_STOP
 }
 }  // namespace
 
-namespace plusplayer {
+namespace esplusplayer {
 struct DecodedPacketManagerInterface {
   virtual ~DecodedPacketManagerInterface() = default;
   virtual bool TryToAdd(esplusplayer_decoded_video_packet* packet) = 0;
@@ -45,6 +64,7 @@ struct CmaBufferInfo {
   bool destroy_flag = false;
 };
 
+// LCOV_EXCL_START
 class AbstractDecodedPacketList : public DecodedPacketManagerInterface {
  public:
   explicit AbstractDecodedPacketList() = default;
@@ -160,10 +180,13 @@ class ManualDecodedCopiedPacketList : public DecodedPacketManagerInterface {
  private:
   Handler handler_;
 };
+// LCOV_EXCL_STOP
+
 class DecodedScaledPacketList : public AbstractDecodedPacketList {
  public:
   explicit DecodedScaledPacketList() { LOG_DEBUG("created"); }
   virtual ~DecodedScaledPacketList() { LOG_DEBUG("destroyed"); }
+// LCOV_EXCL_START
   virtual void GetFreeTbmSurface(void** ptr, bool is_scale_change) {
     std::unique_lock<std::mutex> lk(mtx_);
     if (is_scale_change) {
@@ -254,6 +277,7 @@ class DecodedScaledPacketList : public AbstractDecodedPacketList {
       return false;
     });
   }
+// LCOV_EXCL_STOP
 
   virtual void Clear() override {
     std::unique_lock<std::mutex> lk(mtx_);
@@ -268,6 +292,7 @@ class DecodedScaledPacketList : public AbstractDecodedPacketList {
   }
 
  protected:
+// LCOV_EXCL_START
   virtual bool IsAvailableInternal() override {
     if (GetList().size() > kMaxAvailableSize_) return false;
     return true;
@@ -292,11 +317,12 @@ class DecodedScaledPacketList : public AbstractDecodedPacketList {
       }
     }
   }
+// LCOV_EXCL_STOP
 
  private:
   const std::uint32_t kMaxAvailableSize_ = 5;
   std::vector<CmaBufferInfo> tbm_mgr_;
 };
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
+#endif  // __ESPLUSPLAYER_SRC_ESPLAYER_DECODED_PACKET_LIST_H__
index 8a4678d..fd7a493 100644 (file)
@@ -1,43 +1,55 @@
-//\r
-// @ Copyright [2019] <S/W Platform, Visual Display, Samsung Electronics>\r
-//\r
-\r
-#ifndef __PLUSPLAYER_SRC_ESPLAYER_ESPACEKT_LOGGER__H__\r
-#define __PLUSPLAYER_SRC_ESPLAYER_ESPACEKT_LOGGER__H__\r
-\r
-#include <mutex>\r
-#include <string>\r
-\r
-#include "plusplayer/espacket.h"\r
-\r
-namespace plusplayer {\r
-class EsPacketLogger {\r
- public:\r
-  EsPacketLogger() = default;\r
-  virtual ~EsPacketLogger() = default;\r
-  EsPacketLogger(const EsPacketLogger&) = delete;\r
-  EsPacketLogger(EsPacketLogger&&) = delete;\r
-\r
-  void StorePacketInfo(const EsPacketPtr& packet);\r
-  void PrintStoredPacketInfo(const StreamType type, bool force = false);\r
-  void ResetLog(const StreamType type);\r
-\r
- private:\r
-  constexpr static int kStreamTypeMax = static_cast<int>(StreamType::kMax);\r
-  constexpr static int kLogBufferThreshold = 60;\r
-  struct LightWeightEsPacketInfo {\r
-    bool valid = false;\r
-    std::uint32_t size = 0;\r
-    std::uint64_t pts = 0;\r
-    std::uint64_t duration = 0;\r
-    bool is_eos = false;\r
-  };\r
-  std::string GetStringFromLastPacketInfo_(const StreamType type) const;\r
-\r
-  LightWeightEsPacketInfo last_packet_info_[kStreamTypeMax];\r
-  std::uint64_t last_log_packet_count_[kStreamTypeMax] = {0};\r
-  std::mutex mtx_;\r
-};\r
-}  // namespace plusplayer\r
-\r
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_ESPLAYER_ESPACEKT_LOGGER__H__
+#define __ESPLUSPLAYER_SRC_ESPLAYER_ESPACEKT_LOGGER__H__
+
+#include <mutex>
+#include <string>
+
+#include "esplusplayer/espacket.h"
+
+namespace esplusplayer {
+class EsPacketLogger {
+ public:
+  EsPacketLogger() = default;
+  virtual ~EsPacketLogger() = default;
+  EsPacketLogger(const EsPacketLogger&) = delete;
+  EsPacketLogger(EsPacketLogger&&) = delete;
+
+  void StorePacketInfo(const EsPacketPtr& packet);
+  void PrintStoredPacketInfo(const StreamType type, bool force = false);
+  void ResetLog(const StreamType type);
+
+ private:
+  constexpr static int kStreamTypeMax = static_cast<int>(StreamType::kMax);
+  constexpr static int kLogBufferThreshold = 60;
+  struct LightWeightEsPacketInfo {
+    bool valid = false;
+    std::uint32_t size = 0;
+    std::uint64_t pts = 0;
+    std::uint64_t duration = 0;
+    bool is_eos = false;
+  };
+  std::string GetStringFromLastPacketInfo_(const StreamType type) const;
+
+  LightWeightEsPacketInfo last_packet_info_[kStreamTypeMax];
+  std::uint64_t last_log_packet_count_[kStreamTypeMax] = {0};
+  std::mutex mtx_;
+};
+}  // namespace esplusplayer
+
 #endif
\ No newline at end of file
index 5bf2247..508bc5c 100644 (file)
@@ -1,9 +1,21 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_ESPLAYER_ESPLAYER__H__
-#define __PLUSPLAYER_SRC_ESPLAYER_ESPLAYER__H__
+#ifndef __ESPLUSPLAYER_SRC_ESPLAYER_ESPLAYER__H__
+#define __ESPLUSPLAYER_SRC_ESPLAYER_ESPLAYER__H__
 
 #include <boost/core/noncopyable.hpp>
 #include <future>
 #include <vector>
 
 #include "core/decoderinputbuffer.h"
+#ifndef TIZEN_FEATURE_PUBLIC
+#include "core/kpi.h"
+#endif
 #include "core/trackrendereradapter.h"
+#ifdef USE_MIXER
+#include "mixer/mixerticket.h"
+#include "mixer/mixerticket_eventlistener.h"
+#endif // USE_MIXER
 #include "esplayer/espacket_logger.h"
 #include "esplayer/message.hpp"
 #include "esplayer/state_manager.hpp"
-#include "plusplayer/drm.h"
-#include "plusplayer/esplusplayer.h"
-#include "plusplayer/track.h"
+#include "esplusplayer/drm.h"
+#include "esplusplayer/esplusplayer.h"
+#include "esplusplayer/track.h"
+#include "esplusplayer/types/buffer.h"
+#include "esplusplayer/types/display.h"
+#include "esplusplayer/types/error.h"
+#include "esplusplayer/types/stream.h"
 
-#include "plusplayer/types/buffer.h"
-#include "plusplayer/types/display.h"
-#include "plusplayer/types/error.h"
-#include "plusplayer/types/stream.h"
-
-namespace plusplayer {
+namespace esplusplayer {
 
 enum EosStatus {
   kNone = 0x0000,
@@ -52,20 +70,32 @@ class EsPlayer : public EsPlusPlayer {
   bool PrepareAsync() override;
   bool Deactivate(const StreamType type) override;
   bool Activate(const StreamType type) override;
+  bool DeactivateAudio() override;
+  bool ActivateAudio() override;
   bool Start() override;
   bool Stop() override;
   bool Pause() override;
   bool Resume() override;
-  bool Seek(const uint64_t time_millisecond) override;
+  bool Seek(const uint64_t time) override;
+  void SetAppInfo(const PlayerAppInfo& app_info) override;
+  void SetAppInfoEx(const PlayerAppInfoEx& app_info) override;
   bool SetPlaybackRate(const double rate, const bool audio_mute) override;
   bool SetDisplay(const DisplayType& type, void* obj) override;
+#ifdef USE_MIXER
+  bool SetDisplay(const DisplayType& type, MixerTicket* handle) override;
+#endif // USE_MIXER
   bool SetDisplay(const DisplayType& type, void* ecore_wl2_window, const int x,
                   const int y, const int w, const int h) override;
+  bool SetDisplaySubsurface(const DisplayType& type, void* ecore_wl2_subsurface,
+                            const int x, const int y, const int w,
+                            const int h) override;
   bool SetDisplay(const DisplayType& type, unsigned int surface_id, const int x,
                   const int y, const int w, const int h) override;
   bool SetDisplayMode(const DisplayMode& mode) override;
+  bool SetStretchMode(const int& mode) override;
   bool SetDisplayRoi(const Geometry& roi) override;
   bool SetVideoRoi(const CropArea& area) override;
+  bool ResizeRenderRect(const RenderRect& rect) override;
   bool SetDisplayRotate(const DisplayRotation& rotate) override;
   bool GetDisplayRotate(DisplayRotation* rotate) override;
   bool SetDisplayVisible(bool is_visible) override;
@@ -80,9 +110,12 @@ class EsPlayer : public EsPlusPlayer {
       const EsPacketPtr& packet,
       const drm::EsPlayerEncryptedInfo& drm_info) override;
   EsState GetState() override;
-  bool GetPlayingTime(uint64_t* time_in_milliseconds) override;
+  bool GetPlayingTime(uint64_t* time) override;
   bool SetAudioMute(bool is_mute) override;
   bool SetVideoFrameBufferType(DecodedVideoFrameBufferType type) override;
+  bool SetVideoFrameBufferScaleResolution(
+      const uint32_t& target_width, const uint32_t& target_height) override;
+  bool SetDecodedVideoFrameRate(const Rational& request_framerate) override;
   void RegisterListener(EsEventListener* listener,
                         EsEventListener::UserData userdata) override;
   bool GetAdaptiveInfo(void* padaptive_info,
@@ -90,17 +123,53 @@ class EsPlayer : public EsPlusPlayer {
   bool SetVolume(const int& volume) override;
   bool GetVolume(int* volume) override;
   bool Flush(const StreamType& type) override;
-  void SetBufferSize(const BufferOption& option, uint64_t size) override;
+  bool SetBufferSize(const BufferOption& option, uint64_t size) override;
   bool SetLowLatencyMode(const PlayerLowLatencyMode& mode) override;
+  bool SetVideoFramePeekMode() override;
+  bool RenderVideoFrame() override;
   bool SetUnlimitedMaxBufferMode() override;
+  ErrorType SetFmmMode() override;
   bool SetAudioCodecType(const PlayerAudioCodecType& type) override;
   bool SetVideoCodecType(const PlayerVideoCodecType& type) override;
   bool SetRenderTimeOffset(const StreamType type, int64_t offset) override;
   bool GetRenderTimeOffset(const StreamType type, int64_t* offset) override;
+  bool SetAlternativeVideoResource(unsigned int rsc_type) override;
+  bool SetAlternativeAudioResource(
+      const PlayerAudioResourceType rsc_type) override;
+  bool SwitchAudioStreamOnTheFly(const AudioStreamPtr& stream) override;
+  bool SetAiFilter(void* aifilter) override;
+  bool SetCatchUpSpeed(const CatchUpSpeed& level) override;
+  bool GetVideoLatencyStatus(LatencyStatus* status) override;
+  bool GetAudioLatencyStatus(LatencyStatus* status) override;
+  bool SetVideoMidLatencyThreshold(const unsigned int threshold) override;
+  bool SetAudioMidLatencyThreshold(const unsigned int threshold) override;
+  bool SetVideoHighLatencyThreshold(const unsigned int threshold) override;
+  bool SetAudioHighLatencyThreshold(const unsigned int threshold) override;
+  bool GetLowLatencyPcmBufferSize(uint64_t* frame_count) override;
+  bool GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) override;
+  bool GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) override;
+  bool InitAudioEasingInfo(const uint32_t init_volume,
+                           const uint32_t init_elapsed_time,
+                           const AudioEasingInfo& easing_info) override;
+  bool UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) override;
+  bool GetAudioEasingInfo(uint32_t* current_volume, uint32_t* elapsed_time,
+                          AudioEasingInfo* easing_info) override;
+  bool StartAudioEasing() override;
+  bool StopAudioEasing() override;
+  bool GetVirtualRscId(const RscType type, int* virtual_id) override;
+  bool SetAdvancedPictureQualityType(const AdvPictureQualityType type) override;
+  bool SetResourceAllocatePolicy(const RscAllocPolicy policy) override;
   GetDecodedVideoFrameStatus GetDecodedPacket(
       DecodedVideoPacket& packet) override;
   bool ReturnDecodedPacket(const DecodedVideoPacket& packet) override;
-  bool EnableVideoHole(bool value) override;
+  bool SetAudioPreloading() override;
+  bool SetVideoScanType(const PlayerVideoScanType type) override;
+  bool SetTimeUnitType(const PlayerTimeUnitType type) override;
+  bool GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) override;
+  bool SetVideoStreamRotationInfo(const VideoRotation& rotation) override;
+  bool GetVideoStreamRotationInfo(VideoRotation* rotation) override;
+  bool SetSimpleMixOutBufferLevel(
+      const PlayerSimpleMixOutBufferLevel level) override;
 
  private:
   using SubmitPacketOperator =
@@ -131,9 +200,6 @@ class EsPlayer : public EsPlusPlayer {
     std::uint64_t kMaxTimeOfAudioSrcQueue = 0;
     std::uint32_t kMinTimeThresholdOfVideoSrcQueue = 0;
     std::uint32_t kMinTimeThresholdOfAudioSrcQueue = 0;
-
-    std::uint64_t kMaxBufferOfVideoSrcQueue = 0;
-    std::uint64_t kMaxBufferOfAudioSrcQueue = 0;
   };
 
  private:
@@ -162,6 +228,13 @@ class EsPlayer : public EsPlusPlayer {
   void ResetContextForStop_();
   void GetSrcQueueCurrentSize_(const TrackType& type, uint64_t* byte_size,
                                uint64_t* time_size);
+#ifndef TIZEN_FEATURE_PUBLIC
+  kpi::EsCodecLoggerKeys MakeKpiKeys_();
+#endif
+#ifdef USE_MIXER
+  bool PrepareVideoMixingMode_(std::vector<Track>* tracks);
+#endif // USE_MIXER
+  void InitValuesFromIni_();
 
  private:  // private types
   class TrackRendererEventListener
@@ -171,6 +244,7 @@ class EsPlayer : public EsPlusPlayer {
       assert(handler);
     }
     void OnError(const ErrorType& error_code) override;
+    void OnErrorMsg(const ErrorType& error_code, char* error_msg) override;
     void OnResourceConflicted() override;
     void OnEos() override;
     void OnSeekDone() override;
@@ -182,17 +256,51 @@ class EsPlayer : public EsPlusPlayer {
     void OnEvent(const EventType& event_type,
                  const EventMsg& msg_data) override;
     void OnFirstDecodingDone() override;
+    void OnVideoDecoderUnderrun() override;
+    void OnVideoLatencyStatus(const LatencyStatus& latency_status) override;
+    void OnAudioLatencyStatus(const LatencyStatus& latency_status) override;
+    void OnVideoHighLatency() override;
+    void OnAudioHighLatency() override;
+    void OnVideoFrameDropped(const uint64_t& count) override;
+#ifdef USE_MIXER
+    void OnMediaPacketVideoRawDecoded(
+        const DecodedVideoRawModePacket& packet) override;
+#endif // USE_MIXER
 
    private:
     void ReadyToPrepare_(const TrackType& type);
     void ReadyToSeek_(const TrackType& type);
     void BufferStatus_(const TrackType& type, const BufferStatus& status);
     void OnMediaPacketVideoDecoded(const DecodedVideoPacket& packet);
+    void OnMediaPacketGetTbmBufPtr(void** ptr, bool is_scale_change);
+    void OnDecoderInputBufferTime(const TrackType& type,
+                                  const DecoderBufferTime& time);
+    void OnDecoderOutputBufferTime(const TrackType& type,
+                                   const DecoderBufferTime& time);
 
    private:
     EsPlayer* handler_ = nullptr;
   };  // class TrackRendererEventListener
 
+#ifdef USE_MIXER
+  class MixerListener : public MixerTicketEventListener {
+   public:
+    explicit MixerListener(EsPlayer* handler) : handler_(handler) {
+      assert(handler);
+    }
+    bool OnAudioFocusChanged(bool active) override;
+    bool OnUpdateDisplayInfo(const DisplayInfo& cur_info,
+                             DisplayInfo* new_info) override;
+
+   private:
+    EsPlayer* handler_{nullptr};
+  };
+#endif // USE_MIXER
+
+#ifdef TIZEN_FEATURE_PUBLIC
+  bool EnableVideoHole(bool value) override;
+#endif
+
  private:
   std::vector<Track> track_;
   NeedData need_data_[kTrackTypeMax];
@@ -200,20 +308,26 @@ class EsPlayer : public EsPlusPlayer {
   std::mutex eos_mutex_;
   EsEventListener* eventlistener_ = nullptr;
   EsEventListener::UserData eventlistener_userdata_ = nullptr;
+  bool is_audio_stream_info_frozen_ = false;
 
   EsStateManager state_manager_;
 
   SubmitDataType submit_data_type_ = SubmitDataType::kCleanData;
   drm::Property drm_property_;
   std::uint32_t low_latency_mode_ = 0;
+  std::uint32_t video_frame_peek_mode_ = 0;
   std::uint32_t unlimited_max_buffer_mode_ = 0;
   std::uint32_t accurate_seek_mode_ = 1;
   std::uint32_t video_pre_display_mode_ = 1;
+  std::uint32_t fmm_mode_ = 0;
   PlayerAudioCodecType audio_codec_type_ = kPlayerAudioCodecTypeHW;
   PlayerVideoCodecType video_codec_type_ = kPlayerVideoCodecTypeHW;
   bool force_audio_swdecoder_use_ = false;
+  bool force_video_swdecoder_use_ = false;
   std::uint32_t video_decoding_mode_ = 0x02;  // seamless mode
   std::uint32_t alternative_video_resource_ = 0;
+  RscAllocPolicy resource_alloc_policy_ = RscAllocPolicy::kRscAllocExclusive;
+  std::uint32_t set_video_progressive_ = 0;
   ResumeTime resume_time_;
 
   bool is_msg_task_stop_ = false;
@@ -225,8 +339,12 @@ class EsPlayer : public EsPlusPlayer {
 
   std::unique_ptr<TrackRendererEventListener> trackrenderer_event_listener_{
       new TrackRendererEventListener(this)};
+#ifdef USE_MIXER
+  std::unique_ptr<MixerListener> mixer_event_listener_{new MixerListener(this)};
+#endif // USE_MIXER
   std::unique_ptr<TrackRendererAdapter> trackrenderer_;
   std::future<void> preparetask_;
+  PlayerAppInfo app_info_;
   double current_playback_rate_ = 1.0;
   bool current_audio_mute_ = false;
   bool is_resource_conflicted_ = false;
@@ -236,11 +354,22 @@ class EsPlayer : public EsPlusPlayer {
   SrcQueueSize src_queue_size_;
 
   std::string caf_unique_number;
+#ifdef USE_MIXER
+  std::unique_ptr<MixerTicket> mixer_ticket_;
+  bool is_audio_focused_ = true;
+  Geometry mixerticket_roi_;
+  bool is_visible_ = true;
+  std::mutex audio_focus_m_;
+  bool enable_audio_pipeline_handle_ = true;
+  bool enable_rsc_alloc_handle_ = true;
+#endif // USE_MIXER
   DecodedVideoFrameBufferType vidoe_frame_buffer_type_ =
       DecodedVideoFrameBufferType::kNone;
   // for debugging
   EsPacketLogger es_packet_logger_;
+  PlayerTimeUnitType time_unit_type = kPlayerTimeUnitTypeMs;
+  VideoRotation video_rotate_ = VideoRotation::kVideoRotateNone;
 };
 
-}  // namespace plusplayer
-#endif  // __PLUSPLAYER_SRC_ESPLAYER_ESPLAYER__H__
+}  // namespace esplusplayer
+#endif  // __ESPLUSPLAYER_SRC_ESPLAYER_ESPLAYER__H__
index 78e260e..eff5888 100644 (file)
@@ -1,20 +1,32 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_ESPLAYER_ESPLAYER_DRM__H__
-#define __PLUSPLAYER_SRC_ESPLAYER_ESPLAYER_DRM__H__
+#ifndef __ESPLUSPLAYER_SRC_ESPLAYER_ESPLAYER_DRM__H__
+#define __ESPLUSPLAYER_SRC_ESPLAYER_ESPLAYER_DRM__H__
 
 #include "core/gstobject_guard.h"
-#include "plusplayer/espacket.h"
-#include "plusplayer/external_drm.h"
+#include "esplusplayer/espacket.h"
+#include "esplusplayer/external_drm.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 namespace esplayer_drm {
 using GBytesPtr = gstguard::GstGuardPtr<GBytes>;
 GBytesPtr Serialize(const EsPacketPtr &packet,
                     const drm::EsPlayerEncryptedInfo &drm_info);
 }  // namespace esplayer_drm
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_ESPLAYER_ESPLAYER_DRM__H__
\ No newline at end of file
+#endif  // __ESPLUSPLAYER_SRC_ESPLAYER_ESPLAYER_DRM__H__
\ No newline at end of file
index 210b8d7..78e1ce6 100644 (file)
@@ -1,9 +1,21 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#ifndef __PLUSPLAYER_SRC_ESPLAYER_MESSAGE_H__
-#define __PLUSPLAYER_SRC_ESPLAYER_MESSAGE_H__
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_ESPLAYER_MESSAGE_H__
+#define __ESPLUSPLAYER_SRC_ESPLAYER_MESSAGE_H__
 
 #include <boost/core/noncopyable.hpp>
 #include <functional>
 #include <memory>
 
 #include "core/utils/plusplayer_log.h"
-#include "plusplayer/track.h"
-#include "plusplayer/types/buffer.h"
-#include "plusplayer/types/error.h"
-#include "plusplayer/types/stream.h"
+#include "esplusplayer/track.h"
+#include "esplusplayer/types/buffer.h"
+#include "esplusplayer/types/error.h"
+#include "esplusplayer/types/stream.h"
 
 // Restructuring points
 //  - remove listener handler ptr from msg class member
@@ -25,7 +37,7 @@
 //  - design issues? delivering op breaks encapsulation ?
 //     -> related modules : pipeline , statemanager , msghandler.
 
-namespace plusplayer {
+namespace esplusplayer {
 
 // messages
 namespace es_msg {
@@ -60,6 +72,7 @@ struct Simple : Base {
       : Base(userdata), op(_op) {}
 };
 
+// LCOV_EXCL_START
 struct Error : Base {
   using Ptr = std::unique_ptr<Error>;
   using Operator = std::function<void(const ErrorType&, Base::UserData)>;
@@ -82,6 +95,40 @@ struct Error : Base {
       : Base(userdata), type(_type), op(_op) {}
 };
 
+struct ErrorMsg : Base {
+  using Ptr = std::unique_ptr<ErrorMsg>;
+  using Operator =
+      std::function<void(const ErrorType&, const char*, Base::UserData)>;
+
+  static Base::Ptr Make(const ErrorType& error_type, const char* error_msg,
+                        size_t size, const Operator& op,
+                        const Base::UserData userdata) {
+    return Base::Ptr(new ErrorMsg(error_type, error_msg, size, op, userdata));
+  }
+  void Execute() override {
+    if (!op) return;
+    op(type, message, userdata_);
+  }
+
+  const ErrorType type = ErrorType::kNone;
+  const char* message = nullptr;
+  const Operator op;
+
+ private:
+  explicit ErrorMsg(const ErrorType& _type, const char* _msg, size_t _size,
+                    const Operator& _op, const Base::UserData userdata)
+      : Base(userdata), type(_type), op(_op) {
+    message = new const char[_size + 1]{0};
+    memcpy((void*)message, _msg, _size);
+  }
+
+  ~ErrorMsg() {
+    delete[] message;
+    message = nullptr;
+  }
+};
+// LCOV_EXCL_STOP
+
 struct Bufferstatus : Base {
   using Ptr = std::unique_ptr<Bufferstatus>;
   using Operator = std::function<void(StreamType, BufferStatus, uint64_t,
@@ -161,6 +208,7 @@ struct ReadyToSeek : Base {
       : Base(userdata), type(_type), offset(_offset), op(_op) {}
 };
 
+// LCOV_EXCL_START
 struct ResourceConflict : Base {
   using Ptr = std::unique_ptr<ResourceConflict>;
   using Operator = std::function<void(Base::UserData)>;
@@ -259,6 +307,7 @@ struct OnEvent : Base {
                    const Operator& _op, const Base::UserData userdata)
       : Base(userdata), event(_event), msg_data(_msg_data), op(_op) {}
 };
+// LCOV_EXCL_STOP
 
 struct FirstDecodingDone : Base {
   using Ptr = std::unique_ptr<FirstDecodingDone>;
@@ -279,6 +328,7 @@ struct FirstDecodingDone : Base {
       : Base(userdata), op(_op) {}
 };
 
+// LCOV_EXCL_START
 struct ClosedCaption : Base {
   using Ptr = std::unique_ptr<ClosedCaption>;
   using Operator =
@@ -305,9 +355,59 @@ struct ClosedCaption : Base {
     memcpy(data.get(), _data, size);
   }
 };
+// LCOV_EXCL_STOP
+
+struct PacketLatencyStatus : Base {
+  using Ptr = std::unique_ptr<PacketLatencyStatus>;
+  using Operator = std::function<void(LatencyStatus, Base::UserData)>;
+
+  static Base::Ptr Make(const LatencyStatus latency_status, const Operator& op,
+                        const Base::UserData userdata) {
+    return Base::Ptr(new PacketLatencyStatus(latency_status, op, userdata));
+  }
+  void Execute() override {
+    if (!op) return;
+    op(latency_status, userdata_);
+  }
+
+  const LatencyStatus latency_status = LatencyStatus::kLow;
+  const Operator op;
+
+ private:
+  explicit PacketLatencyStatus(const LatencyStatus _latency_status,
+                               const Operator& _op,
+                               const Base::UserData userdata)
+      : Base(userdata), latency_status(_latency_status), op(_op) {}
+};
+
+// LCOV_EXCL_START
+struct FrameDroppedCount : Base {
+  using Ptr = std::unique_ptr<FrameDroppedCount>;
+  using Operator = std::function<void(uint64_t, Base::UserData)>;
+
+  static Base::Ptr Make(const uint64_t count, const Operator& op,
+                        const Base::UserData userdata) {
+    return Base::Ptr(new FrameDroppedCount(count, op, userdata));
+  }
+  void Execute() override {
+    if (!op) return;
+    op(count, userdata_);
+  }
+
+  const uint64_t count = 0;
+  const Operator op;
+
+ private:
+  explicit FrameDroppedCount(const uint64_t _count,
+                               const Operator& _op,
+                               const Base::UserData userdata)
+      : Base(userdata), count(_count), op(_op) {}
+};
+// LCOV_EXCL_STOP
+
 
 }  // namespace es_msg
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_ESPLAYER_MESSAGE_H__
+#endif  // __ESPLUSPLAYER_SRC_ESPLAYER_MESSAGE_H__
index 50e79f4..959a247 100644 (file)
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 //
 // StateMachine using boost::msm (meta state machine)
@@ -21,8 +33,8 @@
 //    . HANDLED_GUARD_REJECT if Guard(Event const&) returned false
 //
 
-#ifndef __PLUSPLAYER_SRC_ESPLAYER_STATE_MANAGER_H__
-#define __PLUSPLAYER_SRC_ESPLAYER_STATE_MANAGER_H__
+#ifndef __ESPLUSPLAYER_SRC_ESPLAYER_STATE_MANAGER_H__
+#define __ESPLUSPLAYER_SRC_ESPLAYER_STATE_MANAGER_H__
 
 #include <bitset>
 #include <boost/core/noncopyable.hpp>
 #include <boost/msm/front/state_machine_def.hpp>  // front-end
 #include <mutex>
 #include <vector>
-#include <thread>
 
 #include "core/utils/plusplayer_log.h"
-#include "plusplayer/esplusplayer.h"
+#include "esplusplayer/esplusplayer.h"
 
 #define DEBUG_STATE_MANAGER
 #ifdef DEBUG_STATE_MANAGER
@@ -50,7 +61,7 @@
 #define STATE_TRACE(fmt, arg...)
 #endif
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace msm = boost::msm;
 namespace mpl = boost::mpl;
@@ -383,6 +394,6 @@ class EsStateManager : private boost::noncopyable {
   msm::back::state_machine<EsStateMachine> msm_;
 };  // class StateManager
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_ESPLAYER_STATE_MANAGER_H__
+#endif  // __ESPLUSPLAYER_SRC_ESPLAYER_STATE_MANAGER_H__
\ No newline at end of file
index 9de2d37..b8c1db7 100644 (file)
@@ -1,8 +1,20 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#include "plusplayer/elementary_stream.h"
+#include "esplusplayer/elementary_stream.h"
 
 namespace {
 
@@ -11,7 +23,7 @@ constexpr int kBigEdian = 4321;
 
 }  // namespace
 
-namespace plusplayer {
+namespace esplusplayer {
 
 AudioStream::AudioStream() noexcept {
   track_.type = kTrackTypeAudio;
@@ -26,6 +38,7 @@ void AudioStream::SetMimeType(AudioMimeType mimetype) {
 
 void AudioStream::SetMimeType_(AudioMimeType mimetype) {
   mimetype_ = mimetype;
+  // LCOV_EXCL_START
   switch (mimetype) {
     case AudioMimeType::kAAC: {
       track_.mimetype = "audio/mpeg";
@@ -149,10 +162,23 @@ void AudioStream::SetMimeType_(AudioMimeType mimetype) {
       force_swdecoder_use_ = true;
       break;
     }
+    case AudioMimeType::kAC4: {
+      track_.mimetype = "audio/x-ac4";
+      break;
+    }
+    case AudioMimeType::kMpegH: {
+      track_.mimetype = "audio/x-gst-fourcc-mhm1";
+      break;
+    }
+    case AudioMimeType::kFlac: {
+      track_.mimetype = "audio/x-ffmpeg-parsed-flac";
+      break;
+    }
     default:
       track_.mimetype = "unknown";
       break;
   }
+  // LCOV_EXCL_STOP
 }
 
 VideoStream::VideoStream() noexcept {
@@ -168,6 +194,7 @@ void VideoStream::SetMimeType(VideoMimeType mimetype) {
 
 void VideoStream::SetMimeType_(VideoMimeType mimetype) {
   switch (mimetype) {
+    // LCOV_EXCL_START
     case VideoMimeType::kH263:
       track_.mimetype = "video/x-h263";
       break;
@@ -198,10 +225,6 @@ void VideoStream::SetMimeType_(VideoMimeType mimetype) {
     case VideoMimeType::kVP9:
       track_.mimetype = "video/x-vp9";
       break;
-    case VideoMimeType::kWMV3:
-      track_.mimetype = "video/x-wmv";
-      track_.version = 3;
-      break;
     case VideoMimeType::kAV1:
       track_.mimetype = "video/x-av1";
       break;
@@ -211,7 +234,8 @@ void VideoStream::SetMimeType_(VideoMimeType mimetype) {
     default:
       track_.mimetype = "unknown";
       break;
+      // LCOV_EXCL_STOP
   }
 }
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
index c9bf579..7a24472 100644 (file)
@@ -1,9 +1,22 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
-#include "plusplayer/espacket.h"
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-namespace plusplayer {
+#include "esplusplayer/espacket.h"
+
+namespace esplusplayer {
 EsPacketPtr EsPacket::Create(const StreamType type,
                              std::shared_ptr<char> buffer,
                              const uint32_t buffer_size, const uint64_t pts,
@@ -34,4 +47,4 @@ EsPacket::EsPacket(const StreamType type, std::shared_ptr<char> buffer,
     hdr10p_metadata_ = hdr10p_data;
   }
 }
-}  // namespace plusplayer
+}  // namespace esplusplayer
index a87d7f4..b782215 100644 (file)
-//\r
-// @ Copyright [2019] <S/W Platform, Visual Display, Samsung Electronics>\r
-//\r
-\r
-#include "esplayer/espacket_logger.h"\r
-\r
-#include <inttypes.h>\r
-#include <sstream>\r
-#include <thread>\r
-#include <utility>\r
-\r
-#include "core/utils/plusplayer_log.h"\r
-\r
-namespace internal {\r
-enum class TizenBuiltImageType { Unknown, Debug, Release, Perf };\r
-static TizenBuiltImageType GetBuiltImageType() {\r
-  static TizenBuiltImageType image_type;\r
-  if (image_type != TizenBuiltImageType::Unknown) return image_type;\r
-  if (access("/etc/debug", F_OK) == 0) {\r
-    image_type = TizenBuiltImageType::Debug;\r
-    LOG_DEBUG("Debug Image");\r
-  } else if (access("/etc/release", F_OK) == 0) {\r
-    image_type = TizenBuiltImageType::Release;\r
-    LOG_DEBUG("Release Image");\r
-  } else if (access("/etc/perf", F_OK) == 0) {\r
-    image_type = TizenBuiltImageType::Perf;\r
-    LOG_DEBUG("Perf Image");\r
-  }\r
-  return image_type;\r
-}\r
-}  // namespace internal\r
-\r
-namespace plusplayer {\r
-std::string EsPacketLogger::GetStringFromLastPacketInfo_(\r
-    const StreamType type) const {\r
-  const int track_index = static_cast<int>(type);\r
-  const auto& pkt_info = last_packet_info_[track_index];\r
-  std::ostringstream oss;\r
-  oss << "valid? [" << (pkt_info.valid ? 'T' : 'F') << "], ";\r
-  oss << "size [" << (pkt_info.size) << "], ";\r
-  oss << "pts [" << (pkt_info.pts) << "], ";\r
-  oss << "duration [" << (pkt_info.duration) << "], ";\r
-  oss << "is_eos? [" << (pkt_info.is_eos ? 'T' : 'F') << "]";\r
-  return oss.str();\r
-}\r
-\r
-void EsPacketLogger::StorePacketInfo(const EsPacketPtr& packet) {\r
-  if (packet == nullptr) return;\r
-  const int track_index = static_cast<int>(packet->GetType());\r
-  if (track_index >= static_cast<int>(StreamType::kMax)) return;\r
-\r
-  std::lock_guard<std::mutex> lk(mtx_);\r
-\r
-  auto& count = last_log_packet_count_[track_index];\r
-  count++;\r
-\r
-  auto& last_pkt_info = last_packet_info_[track_index];\r
-  last_pkt_info.valid = true;\r
-  last_pkt_info.size = packet->GetSize();\r
-  last_pkt_info.pts = packet->GetPts();\r
-  last_pkt_info.duration = packet->GetDuration();\r
-  last_pkt_info.is_eos = packet->IsEosPacket();\r
-}\r
-\r
-void EsPacketLogger::PrintStoredPacketInfo(const StreamType type, bool force) {\r
-  const bool printable = ((force) || (internal::GetBuiltImageType() ==\r
-                                      internal::TizenBuiltImageType::Debug));\r
-  if (printable == false) return;\r
-\r
-  const int track_index = static_cast<int>(type);\r
-  if (track_index >= static_cast<int>(StreamType::kMax)) return;\r
-\r
-  std::lock_guard<std::mutex> lk(mtx_);\r
-\r
-  const auto& count = last_log_packet_count_[track_index];\r
-  const bool in_timing =\r
-      (force) || (count == 1) || (count % kLogBufferThreshold == 0);\r
-  if (in_timing) {\r
-    const auto logmsg = GetStringFromLastPacketInfo_(type);\r
-    LOG_INFO("<pktinfo - %" PRIu64 " %s> [%s] %s", count, (force ? ": last" : ""),\r
-             (type == StreamType::kAudio ? "AUDIO" : "VIDEO"), logmsg.c_str());\r
-  }\r
-}\r
-\r
-void EsPacketLogger::ResetLog(const StreamType type) {\r
-  std::lock_guard<std::mutex> lk(mtx_);\r
-\r
-  last_packet_info_[static_cast<int>(type)].valid = false;\r
-  last_log_packet_count_[static_cast<int>(type)] = 0;\r
-}\r
-\r
-}  // namespace plusplayer
\ No newline at end of file
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "esplayer/espacket_logger.h"
+
+#include <sstream>
+#include <thread>
+#include <utility>
+#include <cinttypes>
+
+#include "core/utils/plusplayer_log.h"
+
+namespace internal {
+enum class TizenBuiltImageType { Unknown, Debug, Release, Perf };
+static TizenBuiltImageType GetBuiltImageType() {
+  static TizenBuiltImageType image_type;
+  if (image_type != TizenBuiltImageType::Unknown) return image_type;
+// LCOV_EXCL_START
+  if (access("/etc/debug", F_OK) == 0) {
+    image_type = TizenBuiltImageType::Debug;
+    LOG_DEBUG("Debug Image");
+  } else if (access("/etc/release", F_OK) == 0) {
+    image_type = TizenBuiltImageType::Release;
+    LOG_DEBUG("Release Image");
+  } else if (access("/etc/perf", F_OK) == 0) {
+    image_type = TizenBuiltImageType::Perf;
+    LOG_DEBUG("Perf Image");
+  }
+// LCOV_EXCL_STOP
+  return image_type;
+}
+}  // namespace internal
+
+namespace esplusplayer {
+std::string EsPacketLogger::GetStringFromLastPacketInfo_(
+    const StreamType type) const {
+  const int track_index = static_cast<int>(type);
+  const auto& pkt_info = last_packet_info_[track_index];
+  std::ostringstream oss;
+  oss << "valid? [" << (pkt_info.valid ? 'T' : 'F') << "], ";
+  oss << "size [" << (pkt_info.size) << "], ";
+  oss << "pts [" << (pkt_info.pts) << "], ";
+  oss << "duration [" << (pkt_info.duration) << "], ";
+  oss << "is_eos? [" << (pkt_info.is_eos ? 'T' : 'F') << "]";
+  return oss.str();
+}
+
+void EsPacketLogger::StorePacketInfo(const EsPacketPtr& packet) {
+  if (packet == nullptr) return;
+  const int track_index = static_cast<int>(packet->GetType());
+  if (track_index >= static_cast<int>(StreamType::kMax)) return;
+
+  std::lock_guard<std::mutex> lk(mtx_);
+
+  auto& count = last_log_packet_count_[track_index];
+  count++;
+
+  auto& last_pkt_info = last_packet_info_[track_index];
+  last_pkt_info.valid = true;
+  last_pkt_info.size = packet->GetSize();
+  last_pkt_info.pts = packet->GetPts();
+  last_pkt_info.duration = packet->GetDuration();
+  last_pkt_info.is_eos = packet->IsEosPacket();
+}
+
+void EsPacketLogger::PrintStoredPacketInfo(const StreamType type, bool force) {
+  const bool printable = ((force) || (internal::GetBuiltImageType() ==
+                                      internal::TizenBuiltImageType::Debug));
+  if (printable == false) return;
+
+  const int track_index = static_cast<int>(type);
+  if (track_index >= static_cast<int>(StreamType::kMax)) return;
+
+  std::lock_guard<std::mutex> lk(mtx_);
+
+  const auto& count = last_log_packet_count_[track_index];
+  const bool in_timing =
+      (force) || (count == 1) || (count % kLogBufferThreshold == 0);
+  if (in_timing) {
+    const auto logmsg = GetStringFromLastPacketInfo_(type);
+    LOG_INFO("<pktinfo - %" PRId64" %s> [%s] %s", count, (force ? ": last" : ""),
+             (type == StreamType::kAudio ? "AUDIO" : "VIDEO"), logmsg.c_str());
+  }
+}
+
+void EsPacketLogger::ResetLog(const StreamType type) {
+  std::lock_guard<std::mutex> lk(mtx_);
+
+  last_packet_info_[static_cast<int>(type)].valid = false;
+  last_log_packet_count_[static_cast<int>(type)] = 0;
+}
+
+}  // namespace esplusplayer
\ No newline at end of file
index 1e12436..bc81466 100644 (file)
@@ -1,30 +1,54 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 // to manipulate TrackRenderer objects
 // to provide optimized control of TrackRenderer
 
 #include "esplayer/esplayer.h"
 
-#include <inttypes.h>
 #include <boost/scope_exit.hpp>
 #include <cassert>
 #include <chrono>
+#include <cinttypes>
 #include <fstream>
 #include <functional>
 #include <memory>
 #include <sstream>
 #include <thread>
 
+#ifndef TIZEN_FEATURE_PUBLIC
+#ifdef SOUNDBAR_PRODUCT
+#include "avoc_av_audio.h"
+#else
+#include "avoc.h"
+#endif
+#endif
 #include "core/gst_utils.h"
 #include "core/track_util.h"
+#ifndef TIZEN_FEATURE_PUBLIC
+#include "core/utils/caf_logger.h"
+#endif
 #include "core/utils/performance_checker.h"
 #include "core/utils/plusplayer_cfg.h"
 #include "core/utils/plusplayer_log.h"
+#include "core/videoframetypestrategy.h"
 #include "esplayer/esplayer_drm.h"
 #include "json/json.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace es_conf {
 
@@ -41,9 +65,10 @@ namespace util {
 
 std::uint64_t ConvertMsToNs(std::uint64_t ms) {
   constexpr std::uint64_t ns_unit = 1000000;
-  if (ms > (G_MAXUINT64 / ns_unit)) return G_MAXUINT64;
+  if (ms * ns_unit > G_MAXUINT64) return G_MAXUINT64;
   return ms * ns_unit;
 }
+
 std::uint64_t ConvertNsToMs(std::uint64_t ns) {
   constexpr std::uint64_t ms_unit = 1000000;
   return ns / ms_unit;
@@ -51,14 +76,38 @@ std::uint64_t ConvertNsToMs(std::uint64_t ns) {
 
 std::int64_t ConvertMsToNs(std::int64_t ms) {
   constexpr std::int64_t ns_unit = 1000000;
-  if (ms > (G_MAXINT64 / ns_unit)) return G_MAXINT64;
+  if (ms * ns_unit > G_MAXINT64) return G_MAXINT64;
   return ms * ns_unit;
 }
+
 std::int64_t ConvertNsToMs(std::int64_t ns) {
   constexpr std::int64_t ms_unit = 1000000;
   return ns / ms_unit;
 }
 
+std::uint64_t ConvertUsToNs(std::uint64_t us) {
+  constexpr std::uint64_t ns_unit = 1000;
+  if (us * ns_unit > G_MAXUINT64) return G_MAXUINT64;
+  return us * ns_unit;
+}
+
+std::uint64_t ConvertNsToUs(std::uint64_t ns) {
+  constexpr std::uint64_t us_unit = 1000;
+  return ns / us_unit;
+}
+
+std::int64_t ConvertUsToNs(std::int64_t us) {
+  constexpr std::int64_t ns_unit = 1000;
+  if (us * ns_unit > G_MAXINT64) return G_MAXINT64;
+  return us * ns_unit;
+}
+
+std::int64_t ConvertNsToUs(std::int64_t ns) {
+  constexpr std::int64_t us_unit = 1000;
+  return ns / us_unit;
+}
+
+// LCOV_EXCL_START
 std::string GetStringFromMatroskaColor(const MatroskaColor& color_info) {
   std::ostringstream oss;
   oss << "matrixCoefficients:" << color_info.matrix_coefficients
@@ -86,6 +135,7 @@ std::string GetStringFromMatroskaColor(const MatroskaColor& color_info) {
       << " isHDR10p:" << color_info.is_hdr_10p;
   return oss.str();
 }
+// LCOV_EXCL_STOP
 
 }  // namespace util
 
@@ -104,6 +154,12 @@ constexpr int kMaxFhdHeight = 1080;
 inline bool IsPcmMimeType(const std::string& mimetype) {
   return (mimetype.find("audio/x-raw") != std::string::npos);
 }
+inline bool IsForcedUnsetTz(const Track& track, const std::string& id) {
+  if ((track.type == kTrackTypeAudio) && strstr(id.c_str(), "netflix")) {
+    return true;
+  }
+  return false;
+}
 inline bool IsAacCodec(const Track& track) {
   return (track.mimetype.find("audio/mpeg") != std::string::npos &&
           track.version == 2);
@@ -114,6 +170,11 @@ inline bool IsEac3Codec(const std::string& mimetype) {
 inline bool IsAc3Codec(const std::string& mimetype) {
   return mimetype.find("audio/x-ac3") != std::string::npos;
 }
+
+inline bool IsFlacCodec(const std::string& mimetype) {
+  return mimetype.find("audio/x-ffmpeg-parsed-flac") != std::string::npos;
+}
+
 inline bool IsAvailableCodecSwitch(const Track& track) {
   if (internal::IsAacCodec(track) || internal::IsAc3Codec(track.mimetype) ||
       internal::IsEac3Codec(track.mimetype))
@@ -129,10 +190,32 @@ int ResetEosStatus(const TrackType& type, int eos_status) {
   return eos_status;
 }
 
+// LCOV_EXCL_START
+void MakeTrustZoneTracks(std::vector<Track>& tracks,
+                         const std::string& app_id) {
+  for (auto& track : tracks) {
+    const bool is_already_tz_type =
+        (track.mimetype.find("_tz", track.mimetype.length() - 3) !=
+         std::string::npos);
+    if (is_already_tz_type) {
+      continue;
+    }
+    track.streamtype = track.mimetype;
+    bool is_flac = internal::IsFlacCodec(track.mimetype);
+    if ((track.use_swdecoder && !is_flac) || IsPcmMimeType(track.mimetype) ||
+        IsForcedUnsetTz(track, app_id))
+      continue;
+    else
+      track.mimetype = track.mimetype + "_tz";
+  }
+}
+// LCOV_EXCL_STOP
+
 void UpdateCodecTypeTracks(std::vector<Track>& tracks,
                            const PlayerAudioCodecType& audio_codec_type,
                            const PlayerVideoCodecType& video_codec_type,
-                           bool force_audio_swdecoder_use) {
+                           bool force_audio_swdecoder_use,
+                           bool force_video_swdecoder_use) {
   for (auto& track : tracks) {
     switch (track.type) {
       case kTrackTypeAudio: {
@@ -144,7 +227,8 @@ void UpdateCodecTypeTracks(std::vector<Track>& tracks,
         break;
       }
       case kTrackTypeVideo: {
-        if (video_codec_type == kPlayerVideoCodecTypeSW)
+        if (video_codec_type == kPlayerVideoCodecTypeSW ||
+            force_video_swdecoder_use)
           track.use_swdecoder = true;
         else
           track.use_swdecoder = false;
@@ -188,11 +272,11 @@ inline bool IsUnderRun(AppsrcQueueSizeOption& byte_based,
     return false;
 }
 inline bool IsLowLatencyModeDisableAVSync(std::uint32_t mode) {
-  constexpr std::uint32_t kAVSync = 0x0100;
+  constexpr std::uint32_t kAVSync = kLowLatencyModeDisableAVSync;
   return (mode & kAVSync) ? true : false;
 }
 inline bool IsLowLatencyModeDisablePreroll(std::uint32_t mode) {
-  constexpr std::uint32_t kPreroll = 0x0200;
+  constexpr std::uint32_t kPreroll = kLowLatencyModeDisablePreroll;
   return (mode & kPreroll) ? true : false;
 }
 inline bool IsLowLatencyMode(std::uint32_t mode) {
@@ -203,29 +287,46 @@ inline bool IsSupportedTsOffset(std::uint32_t mode) {
   return IsLowLatencyMode(mode) && !IsLowLatencyModeDisableAVSync(mode) ? true
                                                                         : false;
 }
-inline bool IsSetLowLatencyModeForCatchUp(std::uint32_t low_latency_mode) {
-  std::uint32_t precondition = 0;
-  precondition |= static_cast<std::uint32_t>(kLowLatencyModeAudio);
-  precondition |= static_cast<std::uint32_t>(kLowLatencyModeVideo);
-  precondition |= static_cast<std::uint32_t>(kLowLatencyModeDisableAVSync);
-  precondition |=
-      static_cast<std::uint32_t>(kLowLatencyModeDisableVideoQuality);
-  return (low_latency_mode == precondition) ? true : false;
+
+inline bool IsLowLatencyModeEnableGameMode(std::uint32_t mode) {
+  constexpr std::uint32_t kGameMode = kLowLatencyModeEnableGameMode ^
+                                      kLowLatencyModeAudio ^
+                                      kLowLatencyModeVideo;
+  return (mode & kGameMode) ? true : false;
+}
+
+inline bool IsLowLatencyModeForCatchUp(std::uint32_t mode) {
+  return IsLowLatencyModeDisableAVSync(mode) &&
+                 IsLowLatencyModeEnableGameMode(mode)
+             ? true
+             : false;
 }
 
+inline bool IsExclusiveLowLatencyMode(std::uint32_t current_mode,
+                                      std::uint32_t set_mode) {
+  std::uint32_t exclusive_mode = 0;
+  exclusive_mode |= static_cast<std::uint32_t>(kLowLatencyModeEnableGameMode);
+  exclusive_mode |=
+      static_cast<std::uint32_t>(kLowLatencyModeDisableVideoQuality);
+
+  std::uint32_t new_mode = current_mode | set_mode;
+  return (exclusive_mode == (new_mode & exclusive_mode)) ? true : false;
+}
 }  // namespace internal
 
 EsPlayer::EsPlayer() {
   std::call_once(es_conf::loaded, [this]() { es_conf::LoadIniFile(); });
+#ifndef TIZEN_FEATURE_PUBLIC
+  if (CafLogger::Initialize() != true) {
+    LOG_INFO("CAF Dbus not connect.");
+  }
+#endif
+  InitValuesFromIni_();
 }
 
 EsPlayer::~EsPlayer() {
   LOG_ENTER_P(this);
-  try {
-    Close();
-  } catch (...) {
-    LOG_ERROR("Close failed");
-  }
+  Close();
   LOG_LEAVE_P(this);
 }
 
@@ -248,6 +349,13 @@ bool EsPlayer::Open() {
     performance_checker::End(start, "Open");
     return true;
   };
+
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::SetUniqueNumber();
+  caf_unique_number = CafLogger::GetUniqueNumber();
+  CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
+#endif
+
   es_event::Open event{op};
   return state_manager_.ProcessEvent(event);
 }
@@ -260,7 +368,10 @@ bool EsPlayer::Close() {
   }
   auto op = [this]() noexcept {
     if (is_msg_task_stop_ == false) {
-      is_msg_task_stop_ = true;
+      {
+        std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
+        is_msg_task_stop_ = true;
+      }
       msg_task_cv_.notify_one();
       if (msg_handler_task_.valid()) msg_handler_task_.wait();
     }
@@ -283,6 +394,13 @@ bool EsPlayer::Deactivate(const StreamType type) {
                 state_manager_.GetStateEnum());
     return false;
   }
+#ifdef USE_MIXER
+  if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
+    LOG_ERROR_P(
+        this, "can't deactivate audio stream, mixer will control audio stream");
+    return false;
+  }
+#endif // USE_MIXER
   if (!trackrenderer_->Deactivate(static_cast<TrackType>(type))) {
     return false;
   }
@@ -314,6 +432,13 @@ bool EsPlayer::Activate(const StreamType type) {
                 state_manager_.GetStateEnum());
     return false;
   }
+#ifdef USE_MIXER
+  if (!enable_audio_pipeline_handle_ && type == StreamType::kAudio) {
+    LOG_ERROR_P(this,
+                "can't activate audio stream, mixer will control audio stream");
+    return false;
+  }
+#endif // USE_MIXER
   if (!track_.empty()) {
     auto has_track = [type](const Track& item) -> bool {
       return item.type == static_cast<TrackType>(type);
@@ -328,15 +453,27 @@ bool EsPlayer::Activate(const StreamType type) {
       return false;
     }
     target->active = true;
-    internal::UpdateCodecTypeTracks(track_, audio_codec_type_,
-                                    video_codec_type_,
-                                    force_audio_swdecoder_use_);
+    internal::UpdateCodecTypeTracks(
+        track_, audio_codec_type_, video_codec_type_,
+        force_audio_swdecoder_use_, force_video_swdecoder_use_);
+    if (drm_property_.external_decryption) {
+      internal::MakeTrustZoneTracks(track_, app_info_.id);
+    }
     SetTrackRendererAttributes_();
+    if (type == StreamType::kVideo) {
+#ifdef USE_MIXER
+      if (mixer_ticket_)
+        trackrenderer_->SetVideoFrameBufferType(
+            VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
+      else
+#endif // USE_MIXER
+        trackrenderer_->SetVideoFrameBufferType(VideoFrameTypeStrategyPtr(
+            new DefaultVideoFrameTypeStrategy(vidoe_frame_buffer_type_)));
+    }
     if (!trackrenderer_->Activate(target->type, *target)) {
       target->active = false;
       return false;
     }
-    std::lock_guard<std::mutex> lock2(eos_mutex_);
     eos_status_ =
         internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
     return true;
@@ -344,6 +481,53 @@ bool EsPlayer::Activate(const StreamType type) {
   return false;
 }
 
+bool EsPlayer::DeactivateAudio() {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+#ifdef USE_MIXER
+  if (!enable_audio_pipeline_handle_) {
+    LOG_ERROR_P(
+        this, "can't deactivate audio stream, mixer will control audio stream");
+    return false;
+  }
+#endif // USE_MIXER
+  if (!trackrenderer_->DeactivateAudio()) {
+    return false;
+  }
+  is_audio_stream_info_frozen_ = true;
+  return true;
+}
+
+bool EsPlayer::ActivateAudio() {
+  LOG_ENTER_P(this);
+  const StreamType type = StreamType::kAudio;
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+#ifdef USE_MIXER
+  if (!enable_audio_pipeline_handle_) {
+    LOG_ERROR_P(this,
+                "can't activate audio stream, mixer will control audio stream");
+    return false;
+  }
+#endif // USE_MIXER
+  if (track_.empty()) {
+    return false;
+  }
+  if (!trackrenderer_->ActivateAudio()) {
+    return false;
+  }
+  eos_status_ =
+      internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
+  return true;
+}
+
 bool EsPlayer::Start() {
   LOG_ENTER_P(this);
   if (is_stopped_) {
@@ -356,6 +540,11 @@ bool EsPlayer::Start() {
     }
     return true;
   };
+
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
+#endif
+
   es_event::Start event{op};
   return state_manager_.ProcessEvent(event);
 }
@@ -367,6 +556,9 @@ bool EsPlayer::Stop() {
     const auto start = performance_checker::Start();
     if (trackrenderer_) trackrenderer_->Stop();
     ResetContextForStop_();
+#ifdef USE_MIXER
+    if (mixer_ticket_) mixer_ticket_.reset();
+#endif // USE_MIXER
     performance_checker::End(start, "Stop");
     return true;
   };
@@ -383,6 +575,11 @@ bool EsPlayer::Stop() {
     LOG_INFO_P(this, "Wait , Wait Prepare() Done...");
   }
 
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::LogMessage(CafEventType::kIdle, caf_unique_number);
+  CafLogger::StopLoggingThread();
+#endif
+
   return res;
 }
 
@@ -401,16 +598,25 @@ void EsPlayer::SetTrackRendererAttributes_() {
       TrackRendererAdapter::Attribute::kAudioMinByteThreshold,
       src_queue_size_.kMinByteThresholdOfAudioSrcQueue);
   trackrenderer_->SetAttribute(
-      TrackRendererAdapter::Attribute::kVideoQueueMaxBuffer,
-      src_queue_size_.kMaxBufferOfVideoSrcQueue);
+      TrackRendererAdapter::Attribute::kVideoQueueMaxTime,
+      util::ConvertMsToNs(src_queue_size_.kMaxTimeOfVideoSrcQueue));
   trackrenderer_->SetAttribute(
-      TrackRendererAdapter::Attribute::kAudioQueueMaxBuffer,
-      src_queue_size_.kMaxBufferOfAudioSrcQueue);
-  trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kLowLatencyMode,
-                               low_latency_mode_);
+      TrackRendererAdapter::Attribute::kAudioQueueMaxTime,
+      util::ConvertMsToNs(src_queue_size_.kMaxTimeOfAudioSrcQueue));
+  trackrenderer_->SetAttribute(
+      TrackRendererAdapter::Attribute::kVideoMinTimeThreshold,
+      src_queue_size_.kMinTimeThresholdOfVideoSrcQueue);
+  trackrenderer_->SetAttribute(
+      TrackRendererAdapter::Attribute::kAudioMinTimeThreshold,
+      src_queue_size_.kMinTimeThresholdOfAudioSrcQueue);
   trackrenderer_->SetAttribute(
       TrackRendererAdapter::Attribute::kUnlimitedMaxBufferMode,
       unlimited_max_buffer_mode_);
+  trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kLowLatencyMode,
+                               low_latency_mode_);
+  trackrenderer_->SetAttribute(
+      TrackRendererAdapter::Attribute::kVideoFramePeekMode,
+      video_frame_peek_mode_);
   trackrenderer_->SetAttribute(
       TrackRendererAdapter::Attribute::kAccurateSeekMode, accurate_seek_mode_);
   trackrenderer_->SetAttribute(
@@ -422,7 +628,55 @@ void EsPlayer::SetTrackRendererAttributes_() {
         resume_time_.time);
     resume_time_.is_set = false;
   }
+  trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
+                               fmm_mode_);
+  trackrenderer_->SetAttribute(
+      TrackRendererAdapter::Attribute::kAlternativeVideoResource,
+      alternative_video_resource_);
+  trackrenderer_->SetAttribute(
+      TrackRendererAdapter::Attribute::kVideoDecodingMode,
+      video_decoding_mode_);
+  trackrenderer_->SetAttribute(
+      TrackRendererAdapter::Attribute::kVideoProgressiveMode,
+      set_video_progressive_);
+  trackrenderer_->SetAttribute(
+      TrackRendererAdapter::Attribute::kPlayerTimeUnitType,
+      static_cast<std::uint32_t>(time_unit_type));
+}
+
+// LCOV_EXCL_START
+#ifdef USE_MIXER
+bool EsPlayer::PrepareVideoMixingMode_(std::vector<Track>* tracks) {
+  LOG_ENTER_P(this);
+  mixer_ticket_->Prepare();
+  if (enable_rsc_alloc_handle_) return true;
+  ResourceType type = ResourceType::kHwMain;
+  if (!mixer_ticket_->GetAvailableResourceType(ResourceCategory::kVideoDecoder,
+                                               &type)) {
+    LOG_ERROR_P(this, "no available resource");
+    return false;
+  }
+  if (!mixer_ticket_->Alloc(ResourceCategory::kVideoDecoder, type)) {
+    LOG_ERROR_P(this, "fail to alloc resource [%d]", static_cast<int>(type));
+    return false;
+  }
+
+  if (type == ResourceType::kHwSub) {
+    alternative_video_resource_ = 1;
+  } else if (type == ResourceType::kSw) {
+    for (auto it = tracks->begin(); it != tracks->end(); ++it) {
+      if (it->type == kTrackTypeVideo) {
+        it->use_swdecoder = true;
+        break;
+      }
+    }
+  } else if (type == ResourceType::kNdecoder) {
+    video_decoding_mode_ = internal::kNdecodingMode;
+  }
+  return true;
 }
+#endif // USE_MIXER
+// LCOV_EXCL_START
 
 bool EsPlayer::Prepare_() {
   LOG_ENTER_P(this);
@@ -433,14 +687,38 @@ bool EsPlayer::Prepare_() {
   auto op = [this]() noexcept -> bool {
     const auto start = performance_checker::Start();
 
-    internal::UpdateCodecTypeTracks(track_, audio_codec_type_,
-                                    video_codec_type_,
-                                    force_audio_swdecoder_use_);
+    internal::UpdateCodecTypeTracks(
+        track_, audio_codec_type_, video_codec_type_,
+        force_audio_swdecoder_use_, force_video_swdecoder_use_);
+    if (drm_property_.external_decryption) {
+      internal::MakeTrustZoneTracks(track_, app_info_.id);
+    }
     std::vector<Track> active_track;
     if (!track_util::GetActiveTrackList(track_, active_track)) {
       return false;
     }
     trackrenderer_->SetIniProperty(es_conf::ini_property);
+#ifdef USE_MIXER
+    if (mixer_ticket_) {
+      trackrenderer_->SetVideoFrameBufferType(
+          VideoFrameTypeStrategyPtr(new RawVideoFrameTypeStrategy()));
+      if (!PrepareVideoMixingMode_(&active_track)) {
+        LOG_ERROR_P(this, "fail to prepare mixing mode");
+        return false;
+      }
+    }
+    std::unique_lock<std::mutex> lock(audio_focus_m_);
+    if (!enable_audio_pipeline_handle_ && !is_audio_focused_) {
+      for (auto it = active_track.begin(); it != active_track.end(); ++it) {
+        if (it->type == kTrackTypeAudio) {
+          active_track.erase(it);
+          LOG_INFO_P(this, "erase audio track is_audio_focused_ [%d]",
+                     is_audio_focused_);
+          break;
+        }
+      }
+    }
+#endif // USE_MIXER
     for (const auto& track : active_track) {
       switch (track.type) {
         case kTrackTypeAudio: {
@@ -459,19 +737,20 @@ bool EsPlayer::Prepare_() {
           break;
       }
     }
+    SetTrackRendererAttributes_();
     trackrenderer_->SetTrack(active_track);
-    try {
-      SetTrackRendererAttributes_();
-    } catch (...) {
-      LOG_ERROR_P(this, "SetTrackRendererAttributes_ failed");
-      return false;
-    }
     if (!trackrenderer_->Prepare()) {
       return false;
     }
     performance_checker::End(start, "Prepare");
     return true;
   };
+
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::StartLoggingThread();
+  CafLogger::LogMessage(CafEventType::kReady, caf_unique_number);
+#endif
+
   es_event::Prepare event{op};
   if (!state_manager_.ProcessEvent(event)) {
     return false;
@@ -487,8 +766,14 @@ void EsPlayer::PrepareTask_() {
   if (eventlistener_) {
     LOG_INFO_P(this, "Prepare completely, call OnPrepareDone(%d)", ret);
     eventlistener_->OnPrepareDone(ret, eventlistener_userdata_);
+    LOG_INFO_P(this, "call OnPrepareDone End");
   }
 
+#ifndef TIZEN_FEATURE_PUBLIC
+  kpi::CodecLogger logger;
+  kpi::EsCodecLoggerKeys event_keys = MakeKpiKeys_();
+  logger.SendKpi(ret, event_keys);
+#endif
   LOG_LEAVE_P(this);
 }
 
@@ -525,6 +810,11 @@ bool EsPlayer::Pause() {
     es_packet_logger_.PrintStoredPacketInfo(
         internal::ConvertToStreamType(track.type), true);
   }
+
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::LogMessage(CafEventType::kPaused, caf_unique_number);
+#endif
+
   es_event::Pause event{op};
   return state_manager_.ProcessEvent(event);
 }
@@ -541,7 +831,7 @@ bool EsPlayer::Resume() {
     return false;
   }
   if (is_resource_conflicted_) {
-    LOG_ERROR_P(this, "Resume fail resource conflicted");
+    LOG_ERROR_P(this, "Resuem fail resource conflicted");
     return false;
   }
   auto op = [this]() noexcept -> bool {
@@ -555,11 +845,16 @@ bool EsPlayer::Resume() {
     es_packet_logger_.PrintStoredPacketInfo(
         internal::ConvertToStreamType(track.type), true);
   }
+
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::LogMessage(CafEventType::kPlaying, caf_unique_number);
+#endif
+
   es_event::Resume event{op};
   return state_manager_.ProcessEvent(event);
 }
 
-bool EsPlayer::Seek(const uint64_t time_millisecond) {
+bool EsPlayer::Seek(const uint64_t time) {
   if (state_manager_.GetState() < EsState::kIdle) {
     LOG_ERROR_P(this, "Invalid State , current %d",
                 state_manager_.GetStateEnum());
@@ -570,35 +865,36 @@ bool EsPlayer::Seek(const uint64_t time_millisecond) {
       LOG_ERROR_P(this, "Invalid State , during preparing");
       return false;
     }
-    LOG_ERROR("[%p] > resume time [%" PRIu64 " ms]", this, time_millisecond);
+    LOG_ERROR("%p resume time [%" PRId64 " ]", this, time);
     resume_time_.is_set = true;
-    resume_time_.time = time_millisecond;
+    resume_time_.time = time;
     return true;
   }
   is_seek_done_need_drop = true;
-  LOG_DEBUG("[%p] > [ENTER] seek time [%" PRIu64 " ms]", this, time_millisecond);
+  if (time_unit_type == kPlayerTimeUnitTypeMs)
+    LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " ms]", this, time);
+  else if (time_unit_type == kPlayerTimeUnitTypeUs)
+    LOG_DEBUG("%p [ENTER] seek time [%" PRId64 " us]", this, time);
   for (const auto& track : track_) {
-    std::lock_guard<std::mutex> lock2(eos_mutex_);
     eos_status_ = internal::ResetEosStatus(track.type, eos_status_);
     es_packet_logger_.PrintStoredPacketInfo(
         internal::ConvertToStreamType(track.type), true);
   }
-  auto op = [this, time_millisecond]() -> bool {
-    if (!trackrenderer_->Seek(time_millisecond, current_playback_rate_,
+  auto op = [this, time]() -> bool {
+    if (!trackrenderer_->Seek(time, current_playback_rate_,
                               current_audio_mute_)) {
       return false;
     }
     return true;
   };
   es_event::Seek event{op};
-
   bool ret = state_manager_.ProcessEvent(event);
   is_seek_done_need_drop = false;
 
   if (eventlistener_) {
     if (internal::IsLowLatencyModeDisableAVSync(low_latency_mode_) ||
         internal::IsLowLatencyModeDisablePreroll(low_latency_mode_)) {
-      auto listener = std::bind(&plusplayer::EsEventListener::OnSeekDone,
+      auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
                                 eventlistener_, std::placeholders::_1);
       auto msg = es_msg::Simple::Make(listener, eventlistener_userdata_);
       std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
@@ -607,12 +903,42 @@ bool EsPlayer::Seek(const uint64_t time_millisecond) {
       msg_task_cv_.notify_one();
     }
   }
-
   LOG_DEBUG("%p, [LEAVE] seek end ", this);
-
   return ret;
 }
 
+void EsPlayer::SetAppInfo(const PlayerAppInfo& app_info) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return;
+  }
+  app_info_ = app_info;
+  trackrenderer_->SetAppInfo(app_info);
+  LOG_INFO("Appid [%s]", app_info.id.c_str());
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::SetAppId(app_info.id);
+#endif
+}
+
+void EsPlayer::SetAppInfoEx(const PlayerAppInfoEx& app_info) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return;
+  }
+  app_info_.id = app_info.id;
+  app_info_.version = app_info.version;
+  app_info_.type = app_info.type;
+  trackrenderer_->SetAppInfoEx(app_info);
+  LOG_INFO("Appid [%s]", app_info_.id.c_str());
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::SetAppId(app_info_.id);
+#endif
+}
+
 bool EsPlayer::SetPlaybackRate(const double rate, const bool audio_mute) {
   LOG_ENTER_P(this);
 
@@ -636,10 +962,10 @@ bool EsPlayer::SetPlaybackRate(const double rate, const bool audio_mute) {
     return true;
   };
   es_event::PlaybackRate event{op};
-  bool ret = state_manager_.ProcessEvent(event);
+  return state_manager_.ProcessEvent(event);
 
   LOG_LEAVE_P(this);
-  return ret;
+  return true;
 }
 
 bool EsPlayer::SetDisplay(const DisplayType& type, void* obj) {
@@ -648,9 +974,28 @@ bool EsPlayer::SetDisplay(const DisplayType& type, void* obj) {
                 state_manager_.GetStateEnum());
     return false;
   }
+#ifdef USE_MIXER
+  if (mixer_ticket_) mixer_ticket_.reset();
+#endif // USE_MIXER
   return trackrenderer_->SetDisplay(type, obj);
 }
 
+// LCOV_EXCL_START
+#ifdef USE_MIXER
+bool EsPlayer::SetDisplay(const DisplayType& type, MixerTicket* handle) {
+  if (type == DisplayType::kMixer) {
+    LOG_INFO_P(this, "Create MixerTicket");
+    mixer_ticket_.reset(handle);
+    mixer_ticket_->RegisterListener(mixer_event_listener_.get());
+    if (mixer_ticket_->IsAudioFocusHandler())
+      enable_audio_pipeline_handle_ = false;
+    if (mixer_ticket_->IsRscAllocHandler()) enable_rsc_alloc_handle_ = false;
+    trackrenderer_->SetDisplay(DisplayType::kNone, nullptr);
+  }
+  return true;
+}
+#endif // USE_MIXER
+
 bool EsPlayer::SetDisplay(const DisplayType& type, void* ecore_wl2_window,
                           const int x, const int y, const int w, const int h) {
   if (state_manager_.GetState() != EsState::kIdle) {
@@ -658,9 +1003,27 @@ bool EsPlayer::SetDisplay(const DisplayType& type, void* ecore_wl2_window,
                 state_manager_.GetStateEnum());
     return false;
   }
+#ifdef USE_MIXER
+  if (mixer_ticket_) mixer_ticket_.reset();
+#endif // USE_MIXER
   return trackrenderer_->SetDisplay(type, ecore_wl2_window, x, y, w, h);
 }
 
+bool EsPlayer::SetDisplaySubsurface(const DisplayType& type,
+                                    void* ecore_wl2_subsurface, const int x,
+                                    const int y, const int w, const int h) {
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+#ifdef USE_MIXER
+  if (mixer_ticket_) mixer_ticket_.reset();
+#endif // USE_MIXER
+  return trackrenderer_->SetDisplaySubsurface(type, ecore_wl2_subsurface, x, y,
+                                              w, h);
+}
+
 bool EsPlayer::SetDisplay(const DisplayType& type, unsigned int surface_id,
                           const int x, const int y, const int w, const int h) {
   if (state_manager_.GetState() != EsState::kIdle) {
@@ -668,8 +1031,12 @@ bool EsPlayer::SetDisplay(const DisplayType& type, unsigned int surface_id,
                 state_manager_.GetStateEnum());
     return false;
   }
+#ifdef USE_MIXER
+  if (mixer_ticket_) mixer_ticket_.reset();
+#endif // USE_MIXER
   return trackrenderer_->SetDisplay(type, surface_id, x, y, w, h);
 }
+// LCOV_EXCL_START
 
 bool EsPlayer::SetDisplayMode(const DisplayMode& mode) {
   if (state_manager_.GetState() < EsState::kIdle) {
@@ -681,12 +1048,26 @@ bool EsPlayer::SetDisplayMode(const DisplayMode& mode) {
   return true;
 }
 
+bool EsPlayer::SetStretchMode(const int& mode) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  trackrenderer_->SetStretchMode(mode);
+  return true;
+}
+
 bool EsPlayer::SetDisplayRoi(const Geometry& roi) {
   if (state_manager_.GetState() < EsState::kIdle) {
     LOG_ERROR_P(this, "Invalid State , current %d",
                 state_manager_.GetStateEnum());
     return false;
   }
+#ifdef USE_MIXER
+  mixerticket_roi_ = roi;
+  if (mixer_ticket_) return true;
+#endif // USE_MIXER
   return trackrenderer_->SetDisplayRoi(roi);
 }
 
@@ -699,6 +1080,15 @@ bool EsPlayer::SetVideoRoi(const CropArea& area) {
   return trackrenderer_->SetVideoRoi(area);
 }
 
+bool EsPlayer::ResizeRenderRect(const RenderRect& rect) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  return trackrenderer_->ResizeRenderRect(rect);
+}
+
 bool EsPlayer::SetDisplayRotate(const DisplayRotation& rotate) {
   if (state_manager_.GetState() < EsState::kIdle) {
     LOG_ERROR_P(this, "Invalid State , current %d",
@@ -726,6 +1116,14 @@ bool EsPlayer::SetDisplayVisible(bool is_visible) {
                 state_manager_.GetStateEnum());
     return false;
   }
+#ifdef USE_MIXER
+  if (mixer_ticket_) {
+    LOG_INFO_P(this, "mixed player is_visible [%d] -> [%d]", is_visible_,
+               is_visible);
+    is_visible_ = is_visible;
+    return true;
+  }
+#endif // USE_MIXER
   return trackrenderer_->SetDisplayVisible(is_visible);
 }
 
@@ -758,18 +1156,17 @@ bool EsPlayer::SetSubmitDataType(SubmitDataType type) {
 
   if (type == SubmitDataType::kCleanData) return true;
   submit_data_type_ = type;
-  if (type == SubmitDataType::kEncryptedData) {
-       drm_property_.type = drm::Type::kPlayready;
-       // TODO: following SubmitDataType, need to set external_decryption
-       drm_property_.external_decryption = true;
-       drm::Property drm_property = drm_property_;
-       trackrenderer_->SetDrm(drm_property);
-  }
+  drm_property_.type = drm::Type::kPlayready;
+  // TODO: following SubmitDataType, need to set external_decryption
+  drm_property_.external_decryption = true;
+  drm::Property drm_property = drm_property_;
+  trackrenderer_->SetDrm(drm_property);
   return true;
 }
 
 bool EsPlayer::SetTrack_(const Track& track) {
   LOG_ENTER_P(this);
+  track_util::ShowTrackInfo(track);
   track_.push_back(std::move(track));
   return true;
 }
@@ -815,6 +1212,11 @@ bool EsPlayer::SetStream_(const Track& track) {
     }
     return true;
   };
+
+#ifndef TIZEN_FEATURE_PUBLIC
+  CafLogger::LogMessage(CafEventType::kStreamReady, caf_unique_number);
+#endif
+
   es_event::SetStream event{op};
   return state_manager_.ProcessEvent(event);
 }
@@ -823,7 +1225,11 @@ bool EsPlayer::SetStream(const AudioStreamPtr& stream) {
   LOG_ENTER_P(this);
   bool ret = false;
   BOOST_SCOPE_EXIT(&ret, &stream, &force_audio_swdecoder_use_) {
-    if (ret) force_audio_swdecoder_use_ = stream->GetForceSwDecoderUse();
+    if (ret)
+      // when force_audio_swdecoder_use_ is already true, ignore stream setting.
+      // otherwise, it can be true according to the stream setting
+      force_audio_swdecoder_use_ =
+          force_audio_swdecoder_use_ || stream->GetForceSwDecoderUse();
   }
   BOOST_SCOPE_EXIT_END
   if (state_manager_.GetState() < EsState::kIdle) {
@@ -833,6 +1239,10 @@ bool EsPlayer::SetStream(const AudioStreamPtr& stream) {
   }
   Track track = stream->GetTrack_();
   if (state_manager_.GetState() >= EsState::kReady) {
+    if (is_audio_stream_info_frozen_) {
+      LOG_ERROR_P(this, "can't change audio stream in audio deactivate mode");
+      return ret;
+    }
     track.active = false;
     ret = ChangeStream_(track);
     return ret;
@@ -856,6 +1266,62 @@ bool EsPlayer::SetStream(const VideoStreamPtr& stream) {
   return SetStream_(track);
 }
 
+bool EsPlayer::SwitchAudioStreamOnTheFly(const AudioStreamPtr& stream) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  Track track = stream->GetTrack_();
+
+  if (!internal::IsAvailableCodecSwitch(track)) {
+    LOG_ERROR_P(this, "Invalid new mimetype [%s][%d]", track.mimetype.c_str(),
+                track.version);
+    return false;
+  }
+  for (auto& old_track : track_) {
+    if (old_track.type == TrackType::kTrackTypeAudio) {
+      if (!internal::IsAvailableCodecSwitch(old_track)) {
+        LOG_ERROR_P(this, "Invalid previous mimetype [%s][%d]",
+                    old_track.mimetype.c_str(), old_track.version);
+        return false;
+      }
+      if (!Flush(StreamType::kAudio)) return false;
+      old_track.active = false;
+      break;
+    }
+  }
+  if (!ChangeStream_(track)) return false;
+
+  trackrenderer_->SetTrack(track_);
+  return true;
+}
+
+bool EsPlayer::SetAdvancedPictureQualityType(const AdvPictureQualityType type) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  trackrenderer_->SetAdvancedPictureQualityType(type);
+  return true;
+}
+
+bool EsPlayer::SetResourceAllocatePolicy(const RscAllocPolicy policy) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  resource_alloc_policy_ = policy;
+  trackrenderer_->SetResourceAllocatePolicy(policy);
+  return true;
+}
+
+// LCOV_EXCL_START
 GetDecodedVideoFrameStatus EsPlayer::GetDecodedPacket(
     DecodedVideoPacket& packet) {
   if (state_manager_.GetState() < EsState::kReady) {
@@ -874,6 +1340,7 @@ bool EsPlayer::ReturnDecodedPacket(const DecodedVideoPacket& packet) {
   }
   return trackrenderer_->ReturnDecodedPacket(packet);
 }
+// LCOV_EXCL_STOP
 
 void EsPlayer::ResetContextForClose_() {
   internal::ResetDrmProperty(drm_property_);
@@ -881,10 +1348,13 @@ void EsPlayer::ResetContextForClose_() {
   submit_data_type_ = SubmitDataType::kCleanData;
   low_latency_mode_ = 0;
   resume_time_.is_set = false;
+  video_frame_peek_mode_ = 0;
   unlimited_max_buffer_mode_ = 0;
+  fmm_mode_ = 0;
   audio_codec_type_ = kPlayerAudioCodecTypeHW;
   video_codec_type_ = kPlayerVideoCodecTypeHW;
   is_resource_conflicted_ = false;
+  app_info_ = PlayerAppInfo();
   src_queue_size_ = SrcQueueSize();
   is_msg_task_stop_ = false;
 }
@@ -910,14 +1380,24 @@ void EsPlayer::GetSrcQueueCurrentSize_(const TrackType& type,
     trackrenderer_->GetAttribute(
         TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelByte,
         &byte_size_);
+    trackrenderer_->GetAttribute(
+        TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
+        &time_size_);
   } else if (type == TrackType::kTrackTypeAudio) {
     trackrenderer_->GetAttribute(
         TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelByte,
         &byte_size_);
+    trackrenderer_->GetAttribute(
+        TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
+        &time_size_);
   } else
     return;
   *byte_size = boost::any_cast<std::uint64_t>(byte_size_);
-  *time_size = 0;
+  *time_size = boost::any_cast<std::uint64_t>(time_size_);
+  if (time_unit_type == kPlayerTimeUnitTypeMs)
+    *time_size = util::ConvertNsToMs(*time_size);
+  else if (time_unit_type == kPlayerTimeUnitTypeUs)
+    *time_size = util::ConvertNsToUs(*time_size);
 }
 
 GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
@@ -944,13 +1424,23 @@ GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
   uint64_t duration = packet->GetDuration();
   /* if pts or duration are -1(=GST_CLOCK_TIME_NONE), some of the elements don't
    * adjust the buffer. */
-  GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
-                                  ? GST_CLOCK_TIME_NONE
-                                  : (GstClockTime)util::ConvertMsToNs(pts);
-  GST_BUFFER_DURATION(gstbuffer) =
-      (duration == GST_CLOCK_TIME_NONE)
-          ? GST_CLOCK_TIME_NONE
-          : (GstClockTime)util::ConvertMsToNs(duration);
+  if (time_unit_type == kPlayerTimeUnitTypeMs) {
+    GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
+                                    ? GST_CLOCK_TIME_NONE
+                                    : (GstClockTime)util::ConvertMsToNs(pts);
+    GST_BUFFER_DURATION(gstbuffer) =
+        (duration == GST_CLOCK_TIME_NONE)
+            ? GST_CLOCK_TIME_NONE
+            : (GstClockTime)util::ConvertMsToNs(duration);
+  } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
+    GST_BUFFER_PTS(gstbuffer) = (pts == GST_CLOCK_TIME_NONE)
+                                    ? GST_CLOCK_TIME_NONE
+                                    : (GstClockTime)util::ConvertUsToNs(pts);
+    GST_BUFFER_DURATION(gstbuffer) =
+        (duration == GST_CLOCK_TIME_NONE)
+            ? GST_CLOCK_TIME_NONE
+            : (GstClockTime)util::ConvertUsToNs(duration);
+  }
   uint32_t hdr10p_size = packet->GetHdr10pSize();
   std::shared_ptr<char> hdr10p_metadata = packet->GetHdr10pData();
 
@@ -962,7 +1452,7 @@ GstBuffer* EsPlayer::GetGstBuffer_(const EsPacketPtr& packet,
         g_quark_from_static_string("matroska_blockadditional_size"),
         blockadditional_size, g_free);
 
-    /* blockadditional_data : the data sent to omx, size (4 bytes) + metadata */
+    /* blockadditiona_data : the data sent to omx, size (4 bytes) + metadata */
     guint8* blockadditional_data =
         (guint8*)g_malloc(((*blockadditional_size) + 4) * sizeof(guint8));
     memcpy(blockadditional_data, blockadditional_size, sizeof(uint32_t));
@@ -1043,6 +1533,7 @@ PacketSubmitStatus EsPlayer::SubmitDecoderInputBuffer_(
   return status;
 }
 
+// LCOV_EXCL_START
 void EsPlayer::MakeGstBufferForTzHandle_(GstBuffer* gstbuffer,
                                          const TrackType& type,
                                          const uint32_t& tz_handle,
@@ -1085,6 +1576,7 @@ void EsPlayer::MakeGstBufferForEncryptedPacket_(
         gst_drm_info_structure, (GDestroyNotify)gst_structure_free);
   }
 }
+// LCOV_EXCL_STOP
 
 PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
                                                  SubmitPacketOperator op) {
@@ -1148,7 +1640,6 @@ PacketSubmitStatus EsPlayer::SubmitPacketCommon_(const EsPacketPtr& packet,
   if (packet->HasMatroskaColorInfo()) {
     std::string color_info_str =
         util::GetStringFromMatroskaColor(packet->GetMatroskaColorInfo());
-    LOG_DEBUG_P(this, "Detected MatroskaColor : %s", color_info_str.c_str());
     if (trackrenderer_->SetMatroskaColorInfo(color_info_str) == false)
       return PacketSubmitStatus::kNotPrepared;
   }
@@ -1161,6 +1652,7 @@ PacketSubmitStatus EsPlayer::SubmitPacket(const EsPacketPtr& packet) {
   return SubmitPacketCommon_(packet, nullptr);
 }
 
+// LCOV_EXCL_START
 PacketSubmitStatus EsPlayer::SubmitTrustZonePacket(const EsPacketPtr& packet,
                                                    uint32_t tz_handle) {
   std::lock_guard<std::mutex> lk(submit_mutex_);
@@ -1190,16 +1682,17 @@ PacketSubmitStatus EsPlayer::SubmitEncryptedPacket(
   };
   return SubmitPacketCommon_(packet, submitpacket_op);
 }
+// LCOV_EXCL_STOP
 
 EsState EsPlayer::GetState() { return state_manager_.GetState(); }
 
-bool EsPlayer::GetPlayingTime(uint64_t* time_in_milliseconds) {
-  if (!time_in_milliseconds) return false;
+bool EsPlayer::GetPlayingTime(uint64_t* time) {
+  if (!time) return false;
   if (state_manager_.GetState() <= EsState::kReady) {
-    *time_in_milliseconds = 0;
+    *time = 0;
     return false;
   }
-  return trackrenderer_->GetPlayingTime(time_in_milliseconds);
+  return trackrenderer_->GetPlayingTime(time);
 }
 
 bool EsPlayer::SetAudioMute(bool is_mute) {
@@ -1212,14 +1705,46 @@ bool EsPlayer::SetAudioMute(bool is_mute) {
 }
 
 bool EsPlayer::SetVideoFrameBufferType(DecodedVideoFrameBufferType type) {
-  if (state_manager_.GetState() != EsState::kIdle) {
-    LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
+  if ((state_manager_.GetState() != EsState::kIdle &&
+       type != DecodedVideoFrameBufferType::kScale) ||
+      (state_manager_.GetState() < EsState::kIdle &&
+       type == DecodedVideoFrameBufferType::kScale)) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
     return false;
   }
-  trackrenderer_->SetVideoFrameBufferType(type);
+  if (type == DecodedVideoFrameBufferType::kScale &&
+      video_codec_type_ == kPlayerVideoCodecTypeSW) {
+    LOG_ERROR_P(this, "kScale is not supportted when using sw video decoder");
+    return false;
+  }
+  trackrenderer_->SetVideoFrameBufferType(
+      VideoFrameTypeStrategyPtr(new DefaultVideoFrameTypeStrategy(type)));
+  vidoe_frame_buffer_type_ = type;
   return true;
 }
 
+bool EsPlayer::SetVideoFrameBufferScaleResolution(
+    const uint32_t& target_width, const uint32_t& target_height) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  return trackrenderer_->SetVideoFrameBufferScaleResolution(target_width,
+                                                            target_height);
+}
+
+bool EsPlayer::SetDecodedVideoFrameRate(const Rational& request_framerate) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
+    return false;
+  }
+
+  return trackrenderer_->SetDecodedVideoFrameRate(request_framerate);
+}
+
 void EsPlayer::RegisterListener(EsEventListener* listener,
                                 EsEventListener::UserData userdata) {
   // assert(listener); // allow unregister by setting nullptr
@@ -1288,19 +1813,45 @@ bool EsPlayer::Flush(const StreamType& type) {
                 state_manager_.GetStateEnum());
     return false;
   }
-  std::lock_guard<std::mutex> lock2(eos_mutex_);
   eos_status_ =
       internal::ResetEosStatus(static_cast<TrackType>(type), eos_status_);
   es_packet_logger_.ResetLog(type);
   return trackrenderer_->Flush(type);
 }
 
-void EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
-  if (state_manager_.GetState() != EsState::kIdle) {
-    LOG_ERROR_P(this, "Invalid State , current %d",
-                state_manager_.GetStateEnum());
-    return;
+bool EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
+  TrackType track_type = kTrackTypeMax;
+  switch (option) {
+    case BufferOption::kBufferAudioMaxByteSize:      /* FALL THROUGH */
+    case BufferOption::kBufferAudioMinByteThreshold: /* FALL THROUGH */
+    case BufferOption::kBufferAudioMaxTimeSize:      /* FALL THROUGH */
+    case BufferOption::kBufferAudioMinTimeThreshold:
+      track_type = kTrackTypeAudio;
+      break;
+    case BufferOption::kBufferVideoMaxByteSize:      /* FALL THROUGH */
+    case BufferOption::kBufferVideoMinByteThreshold: /* FALL THROUGH */
+    case BufferOption::kBufferVideoMaxTimeSize:      /* FALL THROUGH */
+    case BufferOption::kBufferVideoMinTimeThreshold:
+      track_type = kTrackTypeVideo;
+      break;
+    default:
+      break;
   }
+  if (track_type == kTrackTypeMax) {
+    LOG_ERROR_P(this, "Invalid option!!!");
+    return false;
+  }
+
+  Track activated_track;
+  bool is_activated =
+      track_util::GetActiveTrack(track_, track_type, &activated_track);
+  EsState state = state_manager_.GetState();
+  if ((state < EsState::kIdle) || (state > EsState::kIdle && is_activated)) {
+    LOG_ERROR_P(this, "Invalid State [state:%d] or stream is activated [%d],",
+                state_manager_.GetStateEnum(), is_activated);
+    return false;
+  }
+
   switch (option) {
     case BufferOption::kBufferAudioMaxByteSize:
       src_queue_size_.kMaxByteOfAudioSrcQueue = size;
@@ -1334,6 +1885,7 @@ void EsPlayer::SetBufferSize(const BufferOption& option, uint64_t size) {
       LOG_ERROR_P(this, "Invalid option!!!");
       break;
   }
+  return true;
 }
 
 bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
@@ -1342,10 +1894,111 @@ bool EsPlayer::SetLowLatencyMode(const PlayerLowLatencyMode& mode) {
                 state_manager_.GetStateEnum());
     return false;
   }
+  if (true == internal::IsExclusiveLowLatencyMode(low_latency_mode_, mode)) {
+    LOG_ERROR_P(this, "Invalid Mode , current 0x%x, set 0x%x",
+                static_cast<std::uint32_t>(low_latency_mode_),
+                static_cast<std::uint32_t>(mode));
+    return false;
+  }
   low_latency_mode_ |= static_cast<std::uint32_t>(mode);
   return true;
 }
 
+bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
+    LOG_ERROR_P(this,
+                "low latency mode have to be set except disable_sync mode");
+    return false;
+  }
+  std::int64_t ns_unit = 0;
+  if (time_unit_type == kPlayerTimeUnitTypeMs)
+    ns_unit = 1000000;
+  else if (time_unit_type == kPlayerTimeUnitTypeUs)
+    ns_unit = 1000;
+  if ((offset * ns_unit > G_MAXINT64) || (offset * ns_unit < G_MININT64)) {
+    LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
+              "] * 1000000 < G_MAXINT64",
+              this, offset);
+    return false;
+  }
+  if (type == StreamType::kMax) return false;
+  if (time_unit_type == kPlayerTimeUnitTypeMs) {
+    if (type == StreamType::kAudio)
+      trackrenderer_->SetAttribute(
+          TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
+          util::ConvertMsToNs(offset));
+    else if (type == StreamType::kVideo)
+      trackrenderer_->SetAttribute(
+          TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
+          util::ConvertMsToNs(offset));
+  } else if (time_unit_type == kPlayerTimeUnitTypeUs) {
+    if (type == StreamType::kAudio)
+      trackrenderer_->SetAttribute(
+          TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
+          util::ConvertUsToNs(offset));
+    else if (type == StreamType::kVideo)
+      trackrenderer_->SetAttribute(
+          TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
+          util::ConvertUsToNs(offset));
+  }
+  return true;
+}
+
+bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
+    LOG_ERROR_P(this, "low latency mode have to be set");
+    return false;
+  }
+  if (type == StreamType::kMax) return false;
+  boost::any off_set;
+  if (type == StreamType::kAudio)
+    trackrenderer_->GetAttribute(
+        TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
+  else if (type == StreamType::kVideo)
+    trackrenderer_->GetAttribute(
+        TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
+
+  *offset = boost::any_cast<std::int64_t>(off_set);
+  if (time_unit_type == kPlayerTimeUnitTypeMs)
+    *offset = util::ConvertNsToMs(*offset);
+  else if (time_unit_type == kPlayerTimeUnitTypeUs)
+    *offset = util::ConvertNsToUs(*offset);
+  return true;
+}
+
+bool EsPlayer::SetVideoFramePeekMode() {
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  constexpr std::uint32_t peek_mode_on = 1;
+  video_frame_peek_mode_ = peek_mode_on;
+  return true;
+}
+
+bool EsPlayer::RenderVideoFrame() {
+  if (!video_frame_peek_mode_) return false;
+  if (state_manager_.GetState() == EsState::kReady ||
+      state_manager_.GetState() == EsState::kPaused) {
+    trackrenderer_->RenderVideoFrame();
+    return true;
+  }
+  LOG_ERROR_P(this, "Invalid State , current %d",
+              state_manager_.GetStateEnum());
+  return false;
+}
+
 bool EsPlayer::SetUnlimitedMaxBufferMode() {
   if (state_manager_.GetState() != EsState::kIdle) {
     LOG_ERROR_P(this, "Invalid State , current %d",
@@ -1357,6 +2010,40 @@ bool EsPlayer::SetUnlimitedMaxBufferMode() {
   return true;
 }
 
+ErrorType EsPlayer::SetFmmMode() {
+  EsState state = state_manager_.GetState();
+  LOG_ENTER_P(this);
+  if (state < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return ErrorType::kInvalidState;
+  }
+
+  int onoff = 0;
+#ifndef TIZEN_FEATURE_PUBLIC
+#ifdef SOUNDBAR_PRODUCT
+  return ErrorType::kInvalidState;
+#else
+  avoc_error_e avoc_ret = avoc_get_filmmaker_auto_mode(&onoff);
+  LOG_ERROR_P(this, "avoc get fmm ret [%d]  onoff[%d]", avoc_ret, onoff);
+  if (avoc_ret == AVOC_EXIT_FAILURE) return ErrorType::kInvalidState;
+#endif
+#endif
+  ErrorType ret = ErrorType::kNone;
+
+  constexpr int fmm_auto_off = 0;
+  if (onoff == fmm_auto_off) ret = ErrorType::kInvalidOperation;
+
+  constexpr std::uint32_t fmm_mode_on = 1;
+  fmm_mode_ = fmm_mode_on;
+
+  if (state < EsState::kReady) return ret;
+
+  trackrenderer_->SetAttribute(TrackRendererAdapter::Attribute::kFmmMode,
+                               fmm_mode_);
+  return ret;
+}
+
 bool EsPlayer::SetAudioCodecType(const PlayerAudioCodecType& type) {
   Track activated_track;
   bool is_existed =
@@ -1389,74 +2076,344 @@ bool EsPlayer::SetVideoCodecType(const PlayerVideoCodecType& type) {
                 state_manager_.GetStateEnum(), is_existed);
     return false;
   }
+  if (force_video_swdecoder_use_ &&
+      (type == kPlayerVideoCodecTypeHW ||
+       type == kPlayerVideoCodecTypeHWNdecoding)) {
+    LOG_ERROR_P(this, "Not support hw decoder");
+    return false;
+  }
   if (type == kPlayerVideoCodecTypeSW &&
       vidoe_frame_buffer_type_ == DecodedVideoFrameBufferType::kScale) {
     LOG_ERROR_P(this,
-                "sw video decoder is not supported when video frame buffer "
+                "sw video decoder is not supportted when video frame buffer "
                 "type is scale");
     return false;
   }
+#ifdef USE_MIXER
+  if (!enable_rsc_alloc_handle_) {
+    LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
+    return false;
+  }
+  if (type == kPlayerVideoCodecTypeHWNdecoding) {
+    LOG_INFO_P(this, "PlayerVideoCodecType HW N-decoding");
+    video_decoding_mode_ = internal::kNdecodingMode;
+    return true;
+  }
+#endif // USE_MIXER
   LOG_INFO_P(this, "PlayerVideoCodecType [%s]",
              (type == kPlayerVideoCodecTypeHW) ? "hardware" : "software");
   video_codec_type_ = type;
   return true;
 }
 
+bool EsPlayer::SetAiFilter(void* aifilter) {
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  trackrenderer_->SetAiFilter(aifilter);
+  return true;
+}
 
-bool EsPlayer::SetRenderTimeOffset(const StreamType type, int64_t offset) {
+bool EsPlayer::InitAudioEasingInfo(const uint32_t init_volume,
+                                   const uint32_t init_elapsed_time,
+                                   const AudioEasingInfo& easing_info) {
+  if (init_volume > internal::kVolumeMax ||
+      easing_info.target_volume > internal::kVolumeMax) {
+    LOG_ERROR_P(this, "Invalid volume: init [%d] target [%d]", init_volume,
+                easing_info.target_volume);
+    return false;
+  }
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  return trackrenderer_->InitAudioEasingInfo(init_volume, init_elapsed_time,
+                                             easing_info);
+}
+
+bool EsPlayer::UpdateAudioEasingInfo(const AudioEasingInfo& easing_info) {
+  if (easing_info.target_volume > internal::kVolumeMax) {
+    LOG_ERROR_P(this, "Invalid volume level %d", easing_info.target_volume);
+    return false;
+  }
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  return trackrenderer_->UpdateAudioEasingInfo(easing_info);
+}
+
+bool EsPlayer::GetAudioEasingInfo(uint32_t* current_volume,
+                                  uint32_t* elapsed_time,
+                                  AudioEasingInfo* easing_info) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  return trackrenderer_->GetAudioEasingInfo(current_volume, elapsed_time,
+                                            easing_info);
+}
+
+bool EsPlayer::StartAudioEasing() {
   if (state_manager_.GetState() < EsState::kReady) {
     LOG_ERROR_P(this, "Invalid State , current %d",
                 state_manager_.GetStateEnum());
     return false;
   }
-  if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
-    LOG_ERROR_P(this,
-                "low latency mode have to be set except disable_sync mode");
+  return trackrenderer_->StartAudioEasing();
+}
+
+bool EsPlayer::StopAudioEasing() {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
     return false;
   }
-  /* FIME: time unit api will be added to support both ms and us */
-  if ((offset * 1000000 > G_MAXINT64) || (offset * 1000000 < G_MININT64)) {
-    LOG_ERROR("%p, wrong value : G_MAXINT64 < offset[%" PRId64
-              "] * 1000000 < G_MAXINT64",
-        this, offset);
+  return trackrenderer_->StopAudioEasing();
+}
+
+bool EsPlayer::SetAlternativeVideoResource(unsigned int rsc_type) {
+  if (state_manager_.GetState() == EsState::kNone) {
+    LOG_ERROR_P(this, "Invalid State");
     return false;
   }
-  if (type == StreamType::kMax) return false;
-  if (type == StreamType::kAudio)
-    trackrenderer_->SetAttribute(
-        TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
-        util::ConvertMsToNs(offset));
-  else if (type == StreamType::kVideo)
-    trackrenderer_->SetAttribute(
-        TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
-        util::ConvertMsToNs(offset));
+#ifdef USE_MIXER
+  if (!enable_rsc_alloc_handle_) {
+    LOG_ERROR_P(this, "player can't control resource type, mixer will do it");
+    return false;
+  }
+#endif // USE_MIXER
+  if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
+    LOG_ERROR_P(this,
+                "has set resource allocate policy, the alternative "
+                "resource setting will be wrong");
+    return false;
+  }
+  alternative_video_resource_ = static_cast<std::uint32_t>(rsc_type);
   return true;
 }
 
-bool EsPlayer::GetRenderTimeOffset(const StreamType type, int64_t* offset) {
+bool EsPlayer::SetAlternativeAudioResource(
+    const PlayerAudioResourceType rsc_type) {
+  if (state_manager_.GetState() == EsState::kNone) {
+    LOG_ERROR_P(this, "Invalid State");
+    return false;
+  }
+
+  if (resource_alloc_policy_ > RscAllocPolicy::kRscAllocExclusive) {
+    LOG_ERROR_P(this,
+                "has set resource allocate policy, the alternative "
+                "resource setting will be wrong");
+    return false;
+  }
+  return trackrenderer_->SetAlternativeAudioResource(rsc_type);
+}
+
+bool EsPlayer::SetCatchUpSpeed(const CatchUpSpeed& level) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Do not set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  if (trackrenderer_->SetCatchUpSpeed(level)) {
+    return true;
+  }
+  return false;
+}
+
+bool EsPlayer::GetVideoLatencyStatus(LatencyStatus* status) {
   if (state_manager_.GetState() < EsState::kReady) {
     LOG_ERROR_P(this, "Invalid State , current %d",
                 state_manager_.GetStateEnum());
     return false;
   }
-  if (!internal::IsSupportedTsOffset(low_latency_mode_)) {
-    LOG_ERROR_P(this, "low latency mode have to be set");
+
+  if (trackrenderer_->GetVideoLatencyStatus(status)) {
+    return true;
+  }
+  return false;
+}
+
+bool EsPlayer::GetAudioLatencyStatus(LatencyStatus* status) {
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
     return false;
   }
-  if (type == StreamType::kMax) return false;
-  boost::any off_set;
-  if (type == StreamType::kAudio)
-    trackrenderer_->GetAttribute(
-        TrackRendererAdapter::Attribute::kAudioRenderTimeOffset, &off_set);
-  else if (type == StreamType::kVideo)
-    trackrenderer_->GetAttribute(
-        TrackRendererAdapter::Attribute::kVideoRenderTimeOffset, &off_set);
 
-  *offset = util::ConvertNsToMs(boost::any_cast<int64_t>(off_set));
+  if (trackrenderer_->GetAudioLatencyStatus(status)) {
+    return true;
+  }
+  return false;
+}
 
+bool EsPlayer::SetVideoMidLatencyThreshold(const unsigned int threshold) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  LOG_INFO_P(this, "video_mid_latency_threshold : [%u]", threshold);
+
+  trackrenderer_->SetVideoMidLatencyThreshold(threshold);
+  return true;
+}
+
+bool EsPlayer::SetAudioMidLatencyThreshold(const unsigned int threshold) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  LOG_INFO_P(this, "audio_mid_latency_threshold : [%u]", threshold);
+
+  trackrenderer_->SetAudioMidLatencyThreshold(threshold);
+  return true;
+}
+
+bool EsPlayer::SetVideoHighLatencyThreshold(const unsigned int threshold) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  LOG_INFO_P(this, "video_high_latency_threshold : [%u]", threshold);
+
+  trackrenderer_->SetVideoHighLatencyThreshold(threshold);
+  return true;
+}
+
+bool EsPlayer::SetAudioHighLatencyThreshold(const unsigned int threshold) {
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeForCatchUp(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  LOG_INFO_P(this, "audio_high_latency_threshold : [%u]", threshold);
+
+  trackrenderer_->SetAudioHighLatencyThreshold(threshold);
   return true;
 }
 
+bool EsPlayer::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
+  if (frame_count == nullptr) {
+    LOG_ERROR_P(this, "frame count is nullptr");
+    return false;
+  }
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  return trackrenderer_->GetLowLatencyPcmBufferSize(frame_count);
+}
+
+bool EsPlayer::GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count) {
+  if (frame_count == nullptr) {
+    LOG_ERROR_P(this, "frame count is nullptr");
+    return false;
+  }
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  return trackrenderer_->GetLowLatencyPcmCurrentBufferLevel(frame_count);
+}
+
+bool EsPlayer::GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count) {
+  if (underrun_count == nullptr) {
+    LOG_ERROR_P(this, "underrun count is nullptr");
+    return false;
+  }
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+
+  if (internal::IsLowLatencyModeEnableGameMode(low_latency_mode_) == false) {
+    LOG_ERROR_P(this, "Don't set low latency mode, current[0x%x]",
+                static_cast<std::uint32_t>(low_latency_mode_));
+    return false;
+  }
+
+  return trackrenderer_->GetLowLatencyPcmUnderrunCount(underrun_count);
+}
+
+bool EsPlayer::GetVirtualRscId(const RscType type, int* virtual_id) {
+  if (virtual_id == nullptr) return false;
+  if (state_manager_.GetState() < EsState::kReady) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    *virtual_id = -1;
+    return false;
+  }
+  return trackrenderer_->GetVirtualRscId(type, virtual_id);
+}
+
+bool EsPlayer::SetAudioPreloading() {
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR("Invalid State , current %d", state_manager_.GetStateEnum());
+    return false;
+  }
+  return trackrenderer_->SetAudioPreloading();
+}
+
 void EsPlayer::Init_() {
   track_.clear();
   is_stopped_ = false;
@@ -1464,8 +2421,8 @@ void EsPlayer::Init_() {
 }
 
 void EsPlayer::MsgTask_() {
+  std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
   while (!is_msg_task_stop_) {
-    std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
     if (msg_queue_.empty()) {
       msg_task_cv_.wait(msg_mutex);
     } else {
@@ -1476,7 +2433,6 @@ void EsPlayer::MsgTask_() {
     }
   }
   while (!msg_queue_.empty()) {
-    std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
     msg_queue_.pop();
   }
   LOG_INFO_P(this, "Stop MsgTask");
@@ -1485,7 +2441,7 @@ void EsPlayer::MsgTask_() {
 void EsPlayer::TrackRendererEventListener::OnEos() {
   LOG_ENTER_P(handler_);
   if (!handler_->eventlistener_) return;
-  auto listener = std::bind(&plusplayer::EsEventListener::OnEos,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnEos,
                             handler_->eventlistener_, std::placeholders::_1);
   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
@@ -1495,11 +2451,12 @@ void EsPlayer::TrackRendererEventListener::OnEos() {
   LOG_LEAVE_P(handler_);
 }
 
+// LCOV_EXCL_START
 void EsPlayer::TrackRendererEventListener::OnSeekDone() {
   LOG_ENTER_P(handler_);
   if (!handler_->eventlistener_) return;
   if (handler_->is_seek_done_need_drop == true) return;
-  auto listener = std::bind(&plusplayer::EsEventListener::OnSeekDone,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnSeekDone,
                             handler_->eventlistener_, std::placeholders::_1);
   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
@@ -1519,8 +2476,9 @@ void EsPlayer::TrackRendererEventListener::OnResourceConflicted() {
   handler_->is_resource_conflicted_ = true;
   handler_->trackrenderer_->Stop();
   if (!handler_->eventlistener_ || handler_->is_stopped_) return;
-  auto listener = std::bind(&plusplayer::EsEventListener::OnResourceConflicted,
-                            handler_->eventlistener_, std::placeholders::_1);
+  auto listener =
+      std::bind(&esplusplayer::EsEventListener::OnResourceConflicted,
+                handler_->eventlistener_, std::placeholders::_1);
   auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
   std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
   handler_->msg_queue_.push(std::move(msg));
@@ -1537,9 +2495,9 @@ void EsPlayer::TrackRendererEventListener::OnError(
     const ErrorType& error_code) {
   if (!handler_->eventlistener_) return;
   if (error_code == ErrorType::kResourceLimit) return;
-  auto listener =
-      std::bind(&plusplayer::EsEventListener::OnError, handler_->eventlistener_,
-                std::placeholders::_1, std::placeholders::_2);
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnError,
+                            handler_->eventlistener_, std::placeholders::_1,
+                            std::placeholders::_2);
   auto msg = es_msg::Error::Make(error_code, listener,
                                  handler_->eventlistener_userdata_);
 
@@ -1549,6 +2507,75 @@ void EsPlayer::TrackRendererEventListener::OnError(
   handler_->msg_task_cv_.notify_one();
 }
 
+void EsPlayer::TrackRendererEventListener::OnErrorMsg(
+    const ErrorType& error_code, char* error_msg) {
+  if (!handler_->eventlistener_) return;
+  if (error_code == ErrorType::kResourceLimit) return;
+
+  std::vector<Track> activeTracks;
+  track_util::GetActiveTrackList(handler_->track_, activeTracks);
+
+  Json::Value message;
+  message["error_code"] = (int)error_code;
+
+  switch (error_code) {
+    case ErrorType::kNotSupportedVideoCodec:
+      for (const auto& track : activeTracks) {
+        if (track.type == kTrackTypeVideo) {
+          message["codec"] = track.mimetype.c_str();
+          message["demux"] = track.container_type.c_str();
+          char json_string[20] = {0};
+          int nLen = 19;
+          strncat(json_string, std::to_string(track.width).c_str(), nLen);
+          nLen = sizeof(json_string) - strlen(json_string) - 1;
+          if (nLen < 0) nLen = 0;
+          strncat(json_string, "*", nLen);
+          nLen = sizeof(json_string) - strlen(json_string) - 1;
+          if (nLen < 0) nLen = 0;
+          strncat(json_string, std::to_string(track.height).c_str(), nLen);
+          message["resolution"] = json_string;
+          memset(json_string, 0, sizeof(json_string));
+          nLen = 19;
+          strncat(json_string, std::to_string(track.framerate_num).c_str(),
+                  nLen);
+          nLen = sizeof(json_string) - strlen(json_string) - 1;
+          if (nLen < 0) nLen = 0;
+          strncat(json_string, "/", nLen);
+          nLen = sizeof(json_string) - strlen(json_string) - 1;
+          if (nLen < 0) nLen = 0;
+          strncat(json_string, std::to_string(track.framerate_den).c_str(),
+                  nLen);
+          message["fps"] = json_string;
+          message["detail_info"] = error_msg;
+          break;
+        }
+      }
+      break;
+    case ErrorType::kNotSupportedAudioCodec:
+
+      break;
+    default:
+      break;
+  }
+
+  Json::FastWriter writer;
+  std::string str = writer.write(message);
+  LOG_INFO_P(handler_, "error message: %s", str.c_str());
+
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnErrorMsg,
+                            handler_->eventlistener_, std::placeholders::_1,
+                            std::placeholders::_2, std::placeholders::_3);
+  auto msg =
+      es_msg::ErrorMsg::Make(error_code, str.c_str(), str.size(), listener,
+                             handler_->eventlistener_userdata_);
+
+  std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
+  handler_->msg_queue_.push(std::move(msg));
+  msg_mutex.unlock();
+  handler_->msg_task_cv_.notify_one();
+}
+// LCOV_EXCL_STOP
+
 void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
     const TrackType& type) {
   LOG_INFO_P(handler_, "OnReadyToPrepare [%s]",
@@ -1556,7 +2583,7 @@ void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
 
   handler_->need_data_[type].mask &= ~kNeedDataMaskByPrepare;
 
-  auto listener = std::bind(&plusplayer::EsEventListener::OnReadyToPrepare,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToPrepare,
                             handler_->eventlistener_, std::placeholders::_1,
                             std::placeholders::_2);
   StreamType stream_type = internal::ConvertToStreamType(type);
@@ -1571,13 +2598,13 @@ void EsPlayer::TrackRendererEventListener::ReadyToPrepare_(
 void EsPlayer::TrackRendererEventListener::ReadyToSeek_(const TrackType& type) {
   uint64_t offset = handler_->need_data_[type].seek_offset;
 
-  LOG_INFO("[%p] > OnReadyToSeek [%s] offset [%" PRIu64 "]ms", handler_,
-             (type == kTrackTypeAudio) ? "audio" : "video", offset);
+  LOG_INFO("%p, OnReadyToSeek [%s] offset [%" PRId64 "]", handler_,
+           (type == kTrackTypeAudio) ? "audio" : "video", offset);
 
   handler_->need_data_[type].mask &= ~kNeedDataMaskBySeek;
   handler_->need_data_[type].seek_offset = 0;
 
-  auto listener = std::bind(&plusplayer::EsEventListener::OnReadyToSeek,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnReadyToSeek,
                             handler_->eventlistener_, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3);
   StreamType stream_type = internal::ConvertToStreamType(type);
@@ -1597,7 +2624,7 @@ void EsPlayer::TrackRendererEventListener::BufferStatus_(
   //        (type == kTrackTypeAudio) ? "audio" : "video",
   //        (status == BufferStatus::kUnderrun) ? "underrun" : "overrun");
   handler_->GetSrcQueueCurrentSize_(type, &byte_size, &time_size);
-  auto listener = std::bind(&plusplayer::EsEventListener::OnBufferStatus,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnBufferStatus,
                             handler_->eventlistener_, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3,
                             std::placeholders::_4, std::placeholders::_5);
@@ -1628,6 +2655,14 @@ void EsPlayer::TrackRendererEventListener::OnBufferStatus(
   }
 }
 
+// LCOV_EXCL_START
+void EsPlayer::TrackRendererEventListener::OnMediaPacketGetTbmBufPtr(
+    void** tbm_ptr, bool is_scale_change) {
+  if (!handler_->eventlistener_) return;
+
+  handler_->eventlistener_->OnMediaPacketGetTbmBufPtr(tbm_ptr, is_scale_change);
+}
+
 void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
     const DecodedVideoPacket& packet) {
   if (!handler_->eventlistener_) return;
@@ -1635,6 +2670,69 @@ void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoDecoded(
   handler_->eventlistener_->OnMediaPacketVideoDecoded(packet);
 }
 
+#ifdef USE_MIXER
+void EsPlayer::TrackRendererEventListener::OnMediaPacketVideoRawDecoded(
+    const DecodedVideoRawModePacket& packet) {
+  if (handler_->mixer_ticket_ == nullptr) return;
+  const auto& data = packet.data;
+  if (packet.type == DecodedVideoRawModePacketType::kPhysicalAddress) {
+    DecodedRawInfo info;
+    info.width = packet.width;
+    info.height = packet.height;
+    info.y_info.phyaddr = data.raw.y_phyaddr;
+    info.y_info.viraddr = data.raw.y_viraddr;
+    info.y_info.linesize = data.raw.y_linesize;
+    info.uv_info.phyaddr = data.raw.uv_phyaddr;
+    info.uv_info.viraddr = data.raw.uv_viraddr;
+    info.uv_info.linesize = data.raw.uv_linesize;
+    handler_->mixer_ticket_->Render(info);
+  } else if (packet.type == DecodedVideoRawModePacketType::kTizenBuffer) {
+    DecodedVideoKeyTypeInfo info;
+    info.width = packet.width;
+    info.height = packet.height;
+    info.key = packet.data.tbm.key;
+    handler_->mixer_ticket_->Render(info);
+  }
+}
+
+bool EsPlayer::MixerListener::OnAudioFocusChanged(bool active) {
+  LOG_INFO_P(handler_, "focused [%d]", active);
+  std::unique_lock<std::mutex> lock(handler_->audio_focus_m_);
+  if (handler_->state_manager_.GetState() < EsState::kReady) {
+    handler_->is_audio_focused_ = active;
+    return true;
+  }
+  if (active) {
+    Track activated_track;
+    track_util::GetActiveTrack(handler_->track_, kTrackTypeAudio,
+                               &activated_track);
+    LOG_INFO_P(handler_, "Activate audio track");
+    {
+      std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
+      handler_->eos_status_ =
+          internal::ResetEosStatus(kTrackTypeAudio, handler_->eos_status_);
+    }
+    return handler_->trackrenderer_->Activate(kTrackTypeAudio, activated_track);
+  }
+  LOG_INFO_P(handler_, "Deactivate audio track");
+  handler_->is_audio_focused_ = false;
+  {
+    std::lock_guard<std::mutex> lock2(handler_->eos_mutex_);
+    handler_->eos_status_ |= EosStatus::kAudioEos;
+  }
+  return handler_->trackrenderer_->Deactivate(kTrackTypeAudio);
+}
+
+bool EsPlayer::MixerListener::OnUpdateDisplayInfo(const DisplayInfo& cur_info,
+                                                  DisplayInfo* new_info) {
+  new_info->geometry = handler_->mixerticket_roi_;
+  new_info->visible_status =
+      handler_->is_visible_ ? VisibleStatus::kVisible : VisibleStatus::kHide;
+  return true;
+}
+#endif // USE_MIXER
+// LCOV_EXCL_STOP
+
 void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
                                                       const uint64_t offset) {
   if (!handler_->eventlistener_) return;
@@ -1645,11 +2743,12 @@ void EsPlayer::TrackRendererEventListener::OnSeekData(const TrackType& type,
   }
 }
 
+// LCOV_EXCL_START
 void EsPlayer::TrackRendererEventListener::OnClosedCaptionData(const char* data,
                                                                const int size) {
   if (size <= 0) return;
   if (!handler_->eventlistener_) return;
-  auto listener = std::bind(&plusplayer::EsEventListener::OnClosedCaptionData,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnClosedCaptionData,
                             handler_->eventlistener_, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3);
   auto msg = es_msg::ClosedCaption::Make(data, size, listener,
@@ -1664,7 +2763,7 @@ void EsPlayer::TrackRendererEventListener::OnFlushDone() {
   LOG_ENTER_P(handler_);
   if (!handler_->eventlistener_) return;
 
-  auto listener = std::bind(&plusplayer::EsEventListener::OnFlushDone,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnFlushDone,
                             handler_->eventlistener_, std::placeholders::_1);
   auto msg =
       es_msg::FlushDone::Make(listener, handler_->eventlistener_userdata_);
@@ -1679,7 +2778,7 @@ void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
                                                    const EventMsg& msg_data) {
   if (!handler_->eventlistener_) return;
 
-  auto listener = std::bind(&plusplayer::EsEventListener::OnEvent,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnEvent,
                             handler_->eventlistener_, std::placeholders::_1,
                             std::placeholders::_2, std::placeholders::_3);
   auto msg = es_msg::OnEvent::Make(event, msg_data, listener,
@@ -1690,11 +2789,12 @@ void EsPlayer::TrackRendererEventListener::OnEvent(const EventType& event,
   handler_->msg_task_cv_.notify_one();
   LOG_LEAVE_P(handler_);
 }
+// LCOV_EXCL_STOP
 
 void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
   LOG_ENTER_P(handler_);
   if (!handler_->eventlistener_) return;
-  auto listener = std::bind(&plusplayer::EsEventListener::OnFirstDecodingDone,
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnFirstDecodingDone,
                             handler_->eventlistener_, std::placeholders::_1);
   auto msg = es_msg::FirstDecodingDone::Make(listener,
                                              handler_->eventlistener_userdata_);
@@ -1705,6 +2805,256 @@ void EsPlayer::TrackRendererEventListener::OnFirstDecodingDone() {
   LOG_LEAVE_P(handler_);
 }
 
+void EsPlayer::TrackRendererEventListener::OnVideoDecoderUnderrun() {
+  LOG_ENTER_P(handler_);
+  if (!handler_->eventlistener_) return;
+
+  if (handler_->state_manager_.GetState() != EsState::kPlaying &&
+      handler_->state_manager_.GetState() != EsState::kPaused) {
+    return;
+  }
+
+  auto listener =
+      std::bind(&esplusplayer::EsEventListener::OnVideoDecoderUnderrun,
+                handler_->eventlistener_, std::placeholders::_1);
+  auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
+  std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
+  handler_->msg_queue_.push(std::move(msg));
+  msg_mutex.unlock();
+  handler_->msg_task_cv_.notify_one();
+  LOG_LEAVE_P(handler_);
+}
+
+void EsPlayer::TrackRendererEventListener::OnVideoLatencyStatus(
+    const LatencyStatus& latency_status) {
+  LOG_ENTER_P(handler_);
+  if (!handler_->eventlistener_) return;
+
+  if (handler_->state_manager_.GetState() != EsState::kPlaying &&
+      handler_->state_manager_.GetState() != EsState::kPaused) {
+    return;
+  }
+
+  auto listener = std::bind(
+      &esplusplayer::EsEventListener::OnVideoLatencyStatus,
+      handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
+
+  auto msg = es_msg::PacketLatencyStatus::Make(
+      latency_status, listener, handler_->eventlistener_userdata_);
+
+  std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
+  handler_->msg_queue_.push(std::move(msg));
+  msg_mutex.unlock();
+  handler_->msg_task_cv_.notify_one();
+  LOG_LEAVE_P(handler_);
+}
+
+void EsPlayer::TrackRendererEventListener::OnAudioLatencyStatus(
+    const LatencyStatus& latency_status) {
+  LOG_ENTER_P(handler_);
+  if (!handler_->eventlistener_) return;
+
+  if (handler_->state_manager_.GetState() != EsState::kPlaying &&
+      handler_->state_manager_.GetState() != EsState::kPaused) {
+    return;
+  }
+
+  auto listener = std::bind(
+      &esplusplayer::EsEventListener::OnAudioLatencyStatus,
+      handler_->eventlistener_, std::placeholders::_1, std::placeholders::_2);
+
+  auto msg = es_msg::PacketLatencyStatus::Make(
+      latency_status, listener, handler_->eventlistener_userdata_);
+
+  std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
+  handler_->msg_queue_.push(std::move(msg));
+  msg_mutex.unlock();
+  handler_->msg_task_cv_.notify_one();
+  LOG_LEAVE_P(handler_);
+}
+
+void EsPlayer::TrackRendererEventListener::OnVideoHighLatency() {
+  LOG_ENTER_P(handler_);
+  if (!handler_->eventlistener_) return;
+
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoHighLatency,
+                            handler_->eventlistener_, std::placeholders::_1);
+
+  auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
+
+  std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
+  handler_->msg_queue_.push(std::move(msg));
+  msg_mutex.unlock();
+  handler_->msg_task_cv_.notify_one();
+  LOG_LEAVE_P(handler_);
+}
+
+// LCOV_EXCL_START
+void EsPlayer::TrackRendererEventListener::OnAudioHighLatency() {
+  LOG_ENTER_P(handler_);
+  if (!handler_->eventlistener_) return;
+
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnAudioHighLatency,
+                            handler_->eventlistener_, std::placeholders::_1);
+
+  auto msg = es_msg::Simple::Make(listener, handler_->eventlistener_userdata_);
+
+  std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
+  handler_->msg_queue_.push(std::move(msg));
+  msg_mutex.unlock();
+  handler_->msg_task_cv_.notify_one();
+  LOG_LEAVE_P(handler_);
+}
+
+void EsPlayer::TrackRendererEventListener::OnVideoFrameDropped(
+    const uint64_t& count) {
+  if (!handler_->eventlistener_) return;
+
+  handler_->eventlistener_->OnVideoFrameDropped(
+      count, handler_->eventlistener_userdata_);
+
+#if 0
+
+  if (handler_->state_manager_.GetState() != EsState::kPlaying &&
+      handler_->state_manager_.GetState() != EsState::kPaused) {
+    return;
+  }
+
+  auto listener = std::bind(&esplusplayer::EsEventListener::OnVideoFrameDropped,
+                            handler_->eventlistener_, std::placeholders::_1,
+                            std::placeholders::_2);
+
+  auto msg = es_msg::FrameDroppedCount::Make(
+      count, listener, handler_->eventlistener_userdata_);
+
+  std::unique_lock<std::mutex> msg_mutex(handler_->msg_task_mutex_);
+  handler_->msg_queue_.push(std::move(msg));
+  msg_mutex.unlock();
+  handler_->msg_task_cv_.notify_one();
+  LOG_LEAVE_P(handler_);
+#endif
+}
+
+void EsPlayer::TrackRendererEventListener::OnDecoderInputBufferTime(
+    const TrackType& type, const DecoderBufferTime& time) {
+  if (!handler_->eventlistener_) return;
+
+  StreamType stream_type = internal::ConvertToStreamType(type);
+  handler_->eventlistener_->OnDecoderInputBufferTime(stream_type, time);
+}
+
+void EsPlayer::TrackRendererEventListener::OnDecoderOutputBufferTime(
+    const TrackType& type, const DecoderBufferTime& time) {
+  if (!handler_->eventlistener_) return;
+
+  StreamType stream_type = internal::ConvertToStreamType(type);
+  handler_->eventlistener_->OnDecoderOutputBufferTime(stream_type, time);
+}
+
+// LCOV_EXCL_STOP
+
+bool EsPlayer::SetVideoScanType(const PlayerVideoScanType type) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  if (type == kPlayerVideoScanTypeProgressive) set_video_progressive_ = 1;
+  return true;
+}
+bool EsPlayer::SetTimeUnitType(const PlayerTimeUnitType type) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() != EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  LOG_INFO_P(this, "PlayerTimeUnitType [%s]",
+             (type == kPlayerTimeUnitTypeMs) ? "Ms" : "Us");
+  time_unit_type = type;
+  return true;
+}
+
+bool EsPlayer::GetDecodingTime(StreamType type, int32_t* time_in_milliseconds) {
+  if (!time_in_milliseconds) return false;
+  if (state_manager_.GetState() <= EsState::kReady) {
+    *time_in_milliseconds = 0;
+    return false;
+  }
+  return trackrenderer_->GetDecodingTime(type, time_in_milliseconds);
+}
+
+bool EsPlayer::SetVideoStreamRotationInfo(const VideoRotation& rotation) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  video_rotate_ = rotation;
+  return trackrenderer_->SetVideoStreamRotationInfo(rotation);
+}
+
+bool EsPlayer::GetVideoStreamRotationInfo(VideoRotation* rotation) {
+  LOG_ENTER_P(this);
+  if (state_manager_.GetState() < EsState::kIdle) {
+    LOG_ERROR_P(this, "Invalid State , current %d",
+                state_manager_.GetStateEnum());
+    return false;
+  }
+  *rotation = video_rotate_;
+  return true;
+}
+
+bool EsPlayer::SetSimpleMixOutBufferLevel(
+    const PlayerSimpleMixOutBufferLevel level) {
+  if (state_manager_.GetState() == EsState::kNone) {
+    LOG_ERROR_P(this, "Invalid State");
+    return false;
+  }
+  int converted_level = 1;
+  if (level == kPlayerSimpleMixOutBufferLow) {
+    converted_level = 0;
+  } else if (level == kPlayerSimpleMixOutBufferMid) {
+    converted_level = 1;
+  } else if (level == kPlayerSimpleMixOutBufferHigh) {
+    converted_level = 2;
+  }
+
+  return trackrenderer_->SetSimpleMixOutBufferLevel(converted_level);
+}
+
+#ifndef TIZEN_FEATURE_PUBLIC
+kpi::EsCodecLoggerKeys EsPlayer::MakeKpiKeys_() {
+  kpi::EsCodecLoggerKeys event_info;
+  event_info.app_id = app_info_.id;
+  if (submit_data_type_ == SubmitDataType::kCleanData) {
+    event_info.is_clean = true;
+  } else {
+    event_info.is_clean = false;
+  }
+
+  for (const auto& track : track_) {
+    if (track.type == kTrackTypeVideo) {
+      event_info.v_codec = track.mimetype;
+      event_info.v_codec_version = track.version;
+      event_info.width = track.maxwidth;
+      event_info.height = track.maxheight;
+    } else if (track.type == kTrackTypeAudio) {
+      event_info.a_codec = track.mimetype;
+    }
+  }
+  return event_info;
+}
+#endif
+
+void EsPlayer::InitValuesFromIni_() {
+  force_audio_swdecoder_use_ = es_conf::ini_property["force_sw_audio_codec"];
+  force_video_swdecoder_use_ = es_conf::ini_property["force_sw_video_codec"];
+}
+
+#ifdef TIZEN_FEATURE_PUBLIC
 bool EsPlayer::EnableVideoHole(bool value) {
   if (state_manager_.GetState() < EsState::kIdle) {
     LOG_ERROR_P(this, "Invalid State , current %d",
@@ -1713,6 +3063,7 @@ bool EsPlayer::EnableVideoHole(bool value) {
   }
   return trackrenderer_->EnableVideoHole(value);
 }
+#endif
 
 namespace es_conf {
 
@@ -1721,14 +3072,16 @@ void LoadIniProperty(const Json::Value& root) {
   std::string key = "generate_dot";
   es_conf::ini_property[key] = root.get(key, "").asBool();
   LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
-
-  key = "use_default_video_codec_sw";
+  key = "force_sw_audio_codec";
+  es_conf::ini_property[key] = root.get(key, "").asBool();
+  LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
+  key = "force_sw_video_codec";
   es_conf::ini_property[key] = root.get(key, "").asBool();
   LOG_DEBUG("[%s] : [%d]", key.c_str(), es_conf::ini_property[key]);
 }
 
 bool LoadIniFile() {
-  const char* path = plusplayer_cfg::GetIniPath();
+  const char* path = esplusplayer_cfg::GetIniPath();
   LOG_INFO("path : %s", path);
   std::streampos size;
   char* buf = nullptr;
@@ -1775,4 +3128,4 @@ bool LoadIniFile() {
 
 }  // namespace es_conf
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
index ef576c5..084338f 100644 (file)
@@ -1,25 +1,42 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "esplayer/esplayer_drm.h"
-#include "core/serializer.h"
 
 #include <cstdint>
 #include <cstring>
 #include <sstream>
 #include <type_traits>
 
-namespace plusplayer {
+#include "core/serializer.h"
+// LCOV_EXCL_START
+namespace esplusplayer {
 namespace esplayer_drm {
 GBytesPtr Serialize(const EsPacketPtr &packet,
                     const drm::EsPlayerEncryptedInfo &drm_info) {
   Serializer s;
 
   // box
-  s.Put<uint32_t>(0);                         // box_size : (lazy)
-  s.Put<uint32_t>(true);                      // secure
-  s.Put<int32_t>(drm_info.handle);            // handle
+  s.Put<uint32_t>(0);     // box_size : (lazy)
+  s.Put<uint32_t>(true);  // secure
+#ifdef DRM_MAPI_AARCH_64
+  s.Put<unsigned long>(drm_info.handle);  // handle
+#else
+  s.Put<int>(drm_info.handle);  // handle
+#endif
   s.Put<uint32_t>(0);                         // session_id
   s.Put<uint32_t>(0);                         // psshinfo_size
   auto psa_size_offset = s.Put<uint32_t>(0);  // psa_size : (lazy)
@@ -40,18 +57,18 @@ GBytesPtr Serialize(const EsPacketPtr &packet,
   drm::DrmbEsFragmentedMp4Data *sub_data =
       reinterpret_cast<drm::DrmbEsFragmentedMp4Data *>(drm_info.sub_data);
   if (sub_data != nullptr && sub_data->sub_sample_info_vector.size() != 0) {
-    uint32_t subdata_size =
+    uint32_t subdata_size = static_cast<unsigned int>(
         sizeof(uint32_t) + sub_data->sub_sample_info_vector.size() *
-                               sizeof(drm::DrmbEsSubSampleInfo);
-    s.Put<uint32_t>(subdata_size);                      // subData_size
+                               sizeof(drm::DrmbEsSubSampleInfo));
+    s.Put<uint32_t>(subdata_size);  // subData_size
     const size_t sub_sample_count = sub_data->sub_sample_info_vector.size();
-    s.Put<uint32_t>(sub_sample_count);                  // uSubSampleCount
+    s.Put<uint32_t>(sub_sample_count);  // uSubSampleCount
     for (const auto &value : sub_data->sub_sample_info_vector) {
-      s.Put<uint32_t>(value.bytes_of_clear_data);       // uBytesOfClearData
-      s.Put<uint32_t>(value.bytes_of_encrypted_data);   // uBytesOfEncryptedData
+      s.Put<uint32_t>(value.bytes_of_clear_data);      // uBytesOfClearData
+      s.Put<uint32_t>(value.bytes_of_encrypted_data);  // uBytesOfEncryptedData
     }
   } else {
-    s.Put<uint32_t>(0);                                 // subData_size
+    s.Put<uint32_t>(0);  // subData_size
   }
 
   // box.pPSAParam
@@ -80,5 +97,7 @@ GBytesPtr Serialize(const EsPacketPtr &packet,
 
   return gstguard::make_guard(g_bytes_new(raw_data, total_size));
 }
+// LCOV_EXCL_STOP
+
 }  // namespace esplayer_drm
-}  // namespace plusplayer
+}  // namespace esplusplayer
index 1b7038b..acc0674 100644 (file)
@@ -1,13 +1,25 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#include "plusplayer/esplusplayer.h"
+#include "esplusplayer/esplusplayer.h"
 
 #include "core/utils/plusplayer_log.h"
 #include "esplayer/esplayer.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 std::unique_ptr<EsPlusPlayer> EsPlusPlayer::Create() {
   auto instance = std::unique_ptr<EsPlayer>(new EsPlayer);
@@ -15,4 +27,4 @@ std::unique_ptr<EsPlusPlayer> EsPlusPlayer::Create() {
   return instance;
 }
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
index d92678c..bb43f18 100644 (file)
@@ -1,13 +1,31 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "esplusplayer_capi/esplusplayer_capi.h"
 
-#include "plusplayer/esplusplayer.h"
+#include "esplusplayer/esplusplayer.h"
 
-using plusplayer::EsPlusPlayer;
-using plusplayer::Geometry;
+using esplusplayer::EsPlusPlayer;
+using esplusplayer::Geometry;
 
 #include <inttypes.h>
 #include <tbm_surface.h>
 
+#include <filesystem>
+#include <fstream>
 #include <functional>
 #include <iostream>
 #include <mutex>
@@ -16,43 +34,69 @@ using plusplayer::Geometry;
 #include "core/utils/plusplayer_log.h"
 #include "esplayer/decoded_pkt_list.h"
 #include "esplusplayer_capi/esplusplayer_internal.h"
-#include "plusplayer/drm.h"
-#include "plusplayer/elementary_stream.h"
-#include "plusplayer/espacket.h"
-#include "plusplayer/esplusplayer.h"
-#include "plusplayer/track.h"
-#include "plusplayer/types/buffer.h"
-#include "plusplayer/types/display.h"
-#include "plusplayer/types/error.h"
-#include "plusplayer/types/stream.h"
-
-using plusplayer::AudioMimeType;
-using plusplayer::AudioStream;
-using plusplayer::AudioStreamPtr;
-using plusplayer::BufferStatus;
-using plusplayer::CropArea;
-using plusplayer::DecodedPacketManagerInterface;
-using plusplayer::DisplayMode;
-using plusplayer::DisplayRotation;
-using plusplayer::DisplayType;
-using plusplayer::ErrorType;
-using plusplayer::EsPacket;
-using plusplayer::EsPacketPtr;
-using plusplayer::EsState;
-using plusplayer::MatroskaColor;
-using plusplayer::PlayerAdaptiveInfo;
-using plusplayer::PlayerLowLatencyMode;
-using plusplayer::StreamType;
-using plusplayer::SubmitDataType;
-using plusplayer::Track;
-using plusplayer::TrackType;
-using plusplayer::VideoMimeType;
-using plusplayer::VideoStream;
-using plusplayer::VideoStreamPtr;
-using plusplayer::drm::EsPlayerEncryptedInfo;
-using plusplayer::drm::Type;
-using plusplayer::PlayerAudioCodecType;
-using plusplayer::PlayerVideoCodecType;
+#if defined(USE_MIXER) && !defined(IS_TOMATO)
+#include "mixer_capi/mixer_capi.h"
+#endif // defined(USE_MIXER) && !defined(IS_TOMATO)
+#include "esplusplayer/appinfo.h"
+#include "esplusplayer/audioeasinginfo.h"
+#include "esplusplayer/drm.h"
+#include "esplusplayer/elementary_stream.h"
+#include "esplusplayer/espacket.h"
+#include "esplusplayer/esplusplayer.h"
+#include "esplusplayer/track.h"
+#include "esplusplayer/types/buffer.h"
+#include "esplusplayer/types/display.h"
+#include "esplusplayer/types/error.h"
+#include "esplusplayer/types/latency.h"
+#include "esplusplayer/types/picturequality.h"
+#include "esplusplayer/types/resource.h"
+#include "esplusplayer/types/stream.h"
+
+using esplusplayer::AdvPictureQualityType;
+using esplusplayer::AudioEasingInfo;
+using esplusplayer::AudioEasingType;
+using esplusplayer::AudioMimeType;
+using esplusplayer::AudioStream;
+using esplusplayer::AudioStreamPtr;
+using esplusplayer::BufferStatus;
+using esplusplayer::CatchUpSpeed;
+using esplusplayer::CropArea;
+using esplusplayer::DecodedPacketManagerInterface;
+using esplusplayer::DecoderBufferTime;
+using esplusplayer::DisplayMode;
+using esplusplayer::DisplayRotation;
+using esplusplayer::DisplayType;
+using esplusplayer::ErrorType;
+using esplusplayer::EsPacket;
+using esplusplayer::EsPacketPtr;
+using esplusplayer::EsState;
+using esplusplayer::LatencyStatus;
+using esplusplayer::MatroskaColor;
+using esplusplayer::PlayerAdaptiveInfo;
+using esplusplayer::PlayerAppInfo;
+using esplusplayer::PlayerAppInfoEx;
+using esplusplayer::PlayerAudioCodecType;
+using esplusplayer::PlayerAudioResourceType;
+using esplusplayer::PlayerLowLatencyMode;
+using esplusplayer::PlayerSimpleMixOutBufferLevel;
+using esplusplayer::PlayerTimeUnitType;
+using esplusplayer::PlayerVideoCodecType;
+using esplusplayer::PlayerVideoScanType;
+using esplusplayer::Rational;
+using esplusplayer::RenderRect;
+using esplusplayer::RscAllocPolicy;
+using esplusplayer::RscType;
+using esplusplayer::StreamType;
+using esplusplayer::SubmitDataType;
+using esplusplayer::Track;
+using esplusplayer::TrackType;
+using esplusplayer::VideoMimeType;
+using esplusplayer::VideoRotation;
+using esplusplayer::VideoStream;
+using esplusplayer::VideoStreamPtr;
+using esplusplayer::drm::EsPlayerEncryptedInfo;
+using esplusplayer::drm::Type;
+using std::filesystem::exists;
 
 namespace util {
 const std::unordered_map<esplusplayer_error_type, std::string> kErrorStringMap =
@@ -93,11 +137,70 @@ static const std::string& ConvertErrorTypeToString(
   return kErrorStringMap.count(type) > 0 ? kErrorStringMap.at(type)
                                          : kUnhandledErrorString;
 }
+
+// LCOV_EXCL_START
+esplusplayer_error_type ConvertErrorCode(const ErrorType& error_code) {
+  esplusplayer_error_type type = ESPLUSPLAYER_ERROR_TYPE_NONE;
+  switch (error_code) {
+    case ErrorType::kOutOfMemory:
+      type = ESPLUSPLAYER_ERROR_TYPE_OUT_OF_MEMORY;
+      break;
+    case ErrorType::kInvalidParameter:
+      type = ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+      break;
+    case ErrorType::kInvalidOperation:
+      type = ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
+      break;
+    case ErrorType::kInvalidState:
+      type = ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE;
+      break;
+    case ErrorType::kNotSupportedAudioCodec:
+      type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_AUDIO_CODEC;
+      break;
+    case ErrorType::kNotSupportedVideoCodec:
+      type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_VIDEO_CODEC;
+      break;
+    case ErrorType::kNotSupportedFile:
+      type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE;
+      break;
+    case ErrorType::kConnectionFailed:
+      type = ESPLUSPLAYER_ERROR_TYPE_CONNECTION_FAILED;
+      break;
+    case ErrorType::kDrmExpired:
+      type = ESPLUSPLAYER_ERROR_TYPE_DRM_EXPIRED;
+      break;
+    case ErrorType::kDrmNoLicense:
+      type = ESPLUSPLAYER_ERROR_TYPE_DRM_NO_LICENSE;
+      break;
+    case ErrorType::kDrmFutureUse:
+      type = ESPLUSPLAYER_ERROR_TYPE_DRM_FUTURE_USE;
+      break;
+    case ErrorType::kDrmNotPermitted:
+      type = ESPLUSPLAYER_ERROR_TYPE_NOT_PERMITTED;
+      break;
+    case ErrorType::kDrmInfo:
+      type = ESPLUSPLAYER_ERROR_TYPE_DRM_DECRYPTION_FAILED;
+      break;
+    case ErrorType::kNotSupportedFormat:
+      type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FORMAT;
+      break;
+    case ErrorType::kNone:
+      type = ESPLUSPLAYER_ERROR_TYPE_NONE;
+      break;
+    default:
+      LOG_ERROR("not defined error %x", static_cast<int>(error_code));
+      type = ESPLUSPLAYER_ERROR_TYPE_UNKNOWN;
+      break;
+  }
+  return type;
+}
+// LCOV_EXCL_STOP
+
 }  // namespace util
 
 struct EsPlusPlayerPriv;
 
-class listener_bridge : public plusplayer::EsEventListener {
+class listener_bridge : public esplusplayer::EsEventListener {
  public:
   listener_bridge() { LOG_ENTER }
   ~listener_bridge() { LOG_ENTER }
@@ -119,64 +222,11 @@ class listener_bridge : public plusplayer::EsEventListener {
     LOG_LEAVE
   }
 
-  esplusplayer_error_type ConvertErrorCode(const ErrorType& error_code) {
-    esplusplayer_error_type type = ESPLUSPLAYER_ERROR_TYPE_NONE;
-    switch (error_code) {
-      case ErrorType::kOutOfMemory:
-        type = ESPLUSPLAYER_ERROR_TYPE_OUT_OF_MEMORY;
-        break;
-      case ErrorType::kInvalidParameter:
-        type = ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-        break;
-      case ErrorType::kInvalidOperation:
-        type = ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
-        break;
-      case ErrorType::kInvalidState:
-        type = ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE;
-        break;
-      case ErrorType::kNotSupportedAudioCodec:
-        type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_AUDIO_CODEC;
-        break;
-      case ErrorType::kNotSupportedVideoCodec:
-        type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_VIDEO_CODEC;
-        break;
-      case ErrorType::kNotSupportedFile:
-        type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FILE;
-        break;
-      case ErrorType::kConnectionFailed:
-        type = ESPLUSPLAYER_ERROR_TYPE_CONNECTION_FAILED;
-        break;
-      case ErrorType::kDrmExpired:
-        type = ESPLUSPLAYER_ERROR_TYPE_DRM_EXPIRED;
-        break;
-      case ErrorType::kDrmNoLicense:
-        type = ESPLUSPLAYER_ERROR_TYPE_DRM_NO_LICENSE;
-        break;
-      case ErrorType::kDrmFutureUse:
-        type = ESPLUSPLAYER_ERROR_TYPE_DRM_FUTURE_USE;
-        break;
-      case ErrorType::kDrmNotPermitted:
-        type = ESPLUSPLAYER_ERROR_TYPE_NOT_PERMITTED;
-        break;
-      case ErrorType::kDrmInfo:
-        type = ESPLUSPLAYER_ERROR_TYPE_DRM_DECRYPTION_FAILED;
-        break;
-      case ErrorType::kNotSupportedFormat:
-        type = ESPLUSPLAYER_ERROR_TYPE_NOT_SUPPORTED_FORMAT;
-        break;
-      default:
-        LOG_ERROR("not defined error %x", static_cast<int>(error_code));
-        type = ESPLUSPLAYER_ERROR_TYPE_UNKNOWN;
-        break;
-    }
-    return type;
-  }
-
   virtual void OnError(const ErrorType& error_code, UserData userdata) {
     LOG_ENTER
     LOG_INFO("error code : %x", static_cast<int>(error_code));
     if (this->error_cb_)
-      this->error_cb_(ConvertErrorCode(error_code), error_cb_userdata_);
+      this->error_cb_(util::ConvertErrorCode(error_code), error_cb_userdata_);
   }
 
   virtual void OnBufferStatus(const StreamType& type,
@@ -238,11 +288,11 @@ class listener_bridge : public plusplayer::EsEventListener {
   virtual void OnReadyToSeek(const StreamType& type, const uint64_t offset,
                              UserData userdata) {
     LOG_ENTER
-    LOG_INFO("offset : %" PRIu64, offset);
+    LOG_INFO("offset : %" PRId64 "", offset);
     std::unique_lock<std::mutex> lock(this->multi_seek_control.lock);
     if (this->multi_seek_control.is_offset_valid == false ||
         this->multi_seek_control.offset != offset) {
-      LOG_ERROR("Invalid offset:%" PRIu64, this->multi_seek_control.offset);
+      LOG_ERROR("Invalid offset:%" PRId64 "", this->multi_seek_control.offset);
       return;
     }
     if (this->ready_to_seek_cb_)
@@ -264,18 +314,21 @@ class listener_bridge : public plusplayer::EsEventListener {
     *ptr = ptr1;
   }
 
+  // LCOV_EXCL_START
   virtual void OnMediaPacketVideoDecoded(
-      const plusplayer::DecodedVideoPacket& packet) {
+      const esplusplayer::DecodedVideoPacket& packet) {
     if (this->media_packet_video_decoded_cb_ == nullptr) return;
-    if (!decoded_pkt_mgr_) return;
 
     auto* _pkt = new esplusplayer_decoded_video_packet();
     _pkt->pts = packet.pts;
     _pkt->duration = packet.duration;
     _pkt->surface_data = static_cast<void*>(packet.surface_data);
+#ifdef TIZEN_FETURE_PUBLIC
     _pkt->private_data = packet.buffer_addr;
-
-    if (decoded_pkt_mgr_->TryToAdd(_pkt)) {
+#else
+    _pkt->private_data = packet.scaler_index;
+#endif
+    if (decoded_pkt_mgr_ && decoded_pkt_mgr_->TryToAdd(_pkt)) {
       this->media_packet_video_decoded_cb_(
           _pkt, media_packet_video_decoded_cb_userdata_);
     } else {
@@ -297,10 +350,10 @@ class listener_bridge : public plusplayer::EsEventListener {
     if (this->flush_done_cb_) this->flush_done_cb_(flush_done_cb_userdata_);
   }
 
-  virtual void OnEvent(const plusplayer::EventType& event,
-                       const plusplayer::EventMsg& msg_data,
+  virtual void OnEvent(const esplusplayer::EventType& event,
+                       const esplusplayer::EventMsg& msg_data,
                        UserData userdata) {
-    LOG_ENTER
+    LOG_INFO("event type [%d]", static_cast<int>(event));
     esplusplayer_event_msg event_msg;
     event_msg.data = const_cast<char*>(msg_data.data.c_str());
     event_msg.len = msg_data.len;
@@ -308,6 +361,7 @@ class listener_bridge : public plusplayer::EsEventListener {
       this->event_cb_(static_cast<esplusplayer_event_type>(event), event_msg,
                       event_cb_userdata_);
   }
+  // LCOV_EXCL_STOP
 
   virtual void OnFirstDecodingDone(UserData userdata) {
     LOG_ENTER
@@ -317,6 +371,72 @@ class listener_bridge : public plusplayer::EsEventListener {
     }
   }
 
+  virtual void OnVideoDecoderUnderrun(UserData userdata) {
+    LOG_ENTER
+    if (this->video_decoder_underrun_cb_)
+      this->video_decoder_underrun_cb_(video_decoder_underrun_cb_userdata_);
+  }
+
+  virtual void OnVideoLatencyStatus(const LatencyStatus& latency_status,
+                                    UserData userdata) {
+    LOG_ENTER
+    if (this->video_latency_status_cb_)
+      this->video_latency_status_cb_(
+          static_cast<esplusplayer_latency_status>(latency_status),
+          video_latency_status_cb_userdata_);
+  }
+
+  virtual void OnAudioLatencyStatus(const LatencyStatus& latency_status,
+                                    UserData userdata) {
+    LOG_ENTER
+    if (this->audio_latency_status_cb_)
+      this->audio_latency_status_cb_(
+          static_cast<esplusplayer_latency_status>(latency_status),
+          audio_latency_status_cb_userdata_);
+  }
+
+  virtual void OnVideoHighLatency(UserData userdata) {
+    LOG_ENTER
+    if (this->video_high_latency_cb_)
+      this->video_high_latency_cb_(video_high_latency_cb_userdata_);
+  }
+
+  virtual void OnAudioHighLatency(UserData userdata) {
+    LOG_ENTER
+    if (this->audio_high_latency_cb_)
+      this->audio_high_latency_cb_(audio_high_latency_cb_userdata_);
+  }
+
+  virtual void OnVideoFrameDropped(const uint64_t& count, UserData userdata) {
+    LOG_ERROR("count: %" PRId64 "", count);
+    if (this->video_frame_dropped_cb_)
+      this->video_frame_dropped_cb_(count, video_frame_dropped_cb_userdata_);
+  }
+
+  virtual void OnDecoderInputBufferTime(const StreamType& type,
+                                        const DecoderBufferTime& time) {
+    if (this->decoder_input_buffer_time_cb_) {
+      esplusplayer_decoder_buffer_time decoder_buffer_time;
+      decoder_buffer_time.pts = time.pts;
+      decoder_buffer_time.system_time = time.system_time;
+      this->decoder_input_buffer_time_cb_(
+          static_cast<esplusplayer_stream_type>(type), decoder_buffer_time,
+          decoder_input_buffer_time_cb_userdata_);
+    }
+  }
+
+  virtual void OnDecoderOutputBufferTime(const StreamType& type,
+                                         const DecoderBufferTime& time) {
+    if (this->decoder_output_buffer_time_cb_) {
+      esplusplayer_decoder_buffer_time decoder_buffer_time;
+      decoder_buffer_time.pts = time.pts;
+      decoder_buffer_time.system_time = time.system_time;
+      this->decoder_output_buffer_time_cb_(
+          static_cast<esplusplayer_stream_type>(type), decoder_buffer_time,
+          decoder_output_buffer_time_cb_userdata_);
+    }
+  }
+
  private:
   static void DecodedPacketDeleter(esplusplayer_decoded_video_packet* packet) {
     if (packet->surface_data != nullptr) {
@@ -359,6 +479,22 @@ class listener_bridge : public plusplayer::EsEventListener {
   esplusplayer_first_video_decoding_done_cb first_video_decoding_done_cb_ =
       nullptr;
   void* first_video_decoding_done_cb_userdata_ = nullptr;
+  esplusplayer_decoder_underrun_cb video_decoder_underrun_cb_ = nullptr;
+  void* video_decoder_underrun_cb_userdata_ = nullptr;
+  esplusplayer_video_latency_status_cb video_latency_status_cb_ = nullptr;
+  esplusplayer_audio_latency_status_cb audio_latency_status_cb_ = nullptr;
+  void* video_latency_status_cb_userdata_ = nullptr;
+  void* audio_latency_status_cb_userdata_ = nullptr;
+  esplusplayer_video_high_latency_cb video_high_latency_cb_ = nullptr;
+  esplusplayer_audio_high_latency_cb audio_high_latency_cb_ = nullptr;
+  void* video_high_latency_cb_userdata_ = nullptr;
+  void* audio_high_latency_cb_userdata_ = nullptr;
+  esplusplayer_video_frame_dropped_cb video_frame_dropped_cb_ = nullptr;
+  void* video_frame_dropped_cb_userdata_ = nullptr;
+  esplusplayer_decoder_buffer_time_cb decoder_input_buffer_time_cb_ = nullptr;
+  esplusplayer_decoder_buffer_time_cb decoder_output_buffer_time_cb_ = nullptr;
+  void* decoder_input_buffer_time_cb_userdata_ = nullptr;
+  void* decoder_output_buffer_time_cb_userdata_ = nullptr;
 
   std::shared_ptr<DecodedPacketManagerInterface> decoded_pkt_mgr_;
 
@@ -422,8 +558,39 @@ class listener_bridge : public plusplayer::EsEventListener {
       esplusplayer_handle handle,
       esplusplayer_first_video_decoding_done_cb first_video_decoding_done_cb,
       void* userdata);
+  friend int esplusplayer_set_video_decoder_underrun_cb(
+      esplusplayer_handle handle,
+      esplusplayer_decoder_underrun_cb video_decoder_underrun_cb,
+      void* userdata);
+  friend int esplusplayer_set_video_latency_status_cb(
+      esplusplayer_handle pp,
+      esplusplayer_video_latency_status_cb video_latency_status_cb,
+      void* userdata);
+  friend int esplusplayer_set_audio_latency_status_cb(
+      esplusplayer_handle pp,
+      esplusplayer_audio_latency_status_cb audio_latency_status_cb,
+      void* userdata);
+  friend int esplusplayer_set_video_high_latency_cb(
+      esplusplayer_handle pp,
+      esplusplayer_video_high_latency_cb video_high_latency_cb, void* userdata);
+  friend int esplusplayer_set_audio_high_latency_cb(
+      esplusplayer_handle pp,
+      esplusplayer_audio_high_latency_cb audio_high_latency_cb, void* userdata);
+  friend int esplusplayer_set_video_frame_dropped_cb(
+      esplusplayer_handle pp,
+      esplusplayer_video_frame_dropped_cb video_frame_dropped_cb,
+      void* userdata);
+  friend int esplusplayer_set_decoder_input_buffer_time_cb(
+      esplusplayer_handle handle,
+      esplusplayer_decoder_buffer_time_cb decoder_buffer_time_cb,
+      void* userdata);
+  friend int esplusplayer_set_decoder_output_buffer_time_cb(
+      esplusplayer_handle handle,
+      esplusplayer_decoder_buffer_time_cb decoder_buffer_time_cb,
+      void* userdata);
 };
 
+#define ES_DUMP 0
 struct EsPlusPlayerPriv {
   std::unique_ptr<EsPlusPlayer> player;
   std::unique_ptr<listener_bridge> listener{new listener_bridge()};
@@ -432,6 +599,11 @@ struct EsPlusPlayerPriv {
   friend EsPlusPlayerPriv* EsPrivCreate();
   friend void EsPrivDestroy(EsPlusPlayerPriv*& instance);
 
+#ifdef ES_DUMP
+  std::ofstream video_stream_;
+  std::ofstream audio_stream_;
+#endif
+
  private:
   EsPlusPlayerPriv() {}
   ~EsPlusPlayerPriv() {}
@@ -489,6 +661,7 @@ void update_ready_to_seek_offset(esplusplayer_handle handle,
   listener->multi_seek_control.is_offset_valid = true;
 }
 
+// LCOV_EXCL_START
 inline void convert_matroska_color_info_(
     const esplusplayer_matroska_color* from, MatroskaColor* to) {
   to->matrix_coefficients = from->matrix_coefficients;
@@ -524,6 +697,7 @@ inline void convert_matroska_color_info_(
   to->metadata.luminance_max = from->metadata.luminance_max;
   to->metadata.luminance_min = from->metadata.luminance_min;
 }
+// LCOV_EXCL_STOP
 
 inline EsPacketPtr convert_espacket_(esplusplayer_es_packet* from) {
   std::shared_ptr<char> buffer = nullptr;
@@ -552,14 +726,20 @@ inline EsPacketPtr convert_espacket_(esplusplayer_es_packet* from) {
   return std::move(espacket);
 }
 
+// LCOV_EXCL_START
 using EncryptedInfoPtr =
     std::unique_ptr<EsPlayerEncryptedInfo,
                     std::function<void(EsPlayerEncryptedInfo*)>>;
+#ifdef DRM_MAPI_AARCH_64
+inline EncryptedInfoPtr convert_es_drm_info_(
+    esplusplayer_drm_info_64bit* from) {
+#else
 inline EncryptedInfoPtr convert_es_drm_info_(esplusplayer_drm_info* from) {
+#endif
   auto custom_deleter = [](EsPlayerEncryptedInfo* drm_info) {
     if (drm_info == nullptr) return;
     if (drm_info->sub_data != nullptr) {
-      delete reinterpret_cast<plusplayer::drm::DrmbEsFragmentedMp4Data*>(
+      delete reinterpret_cast<esplusplayer::drm::DrmbEsFragmentedMp4Data*>(
           drm_info->sub_data);
       drm_info->sub_data = nullptr;
     }
@@ -573,11 +753,11 @@ inline EncryptedInfoPtr convert_es_drm_info_(esplusplayer_drm_info* from) {
 
   drm_info->handle = from->handle;
   drm_info->algorithm =
-      static_cast<plusplayer::drm::DrmbEsCipherAlgorithm>(from->algorithm);
+      static_cast<esplusplayer::drm::DrmbEsCipherAlgorithm>(from->algorithm);
   drm_info->format =
-      static_cast<plusplayer::drm::DrmbEsMediaFormat>(from->format);
+      static_cast<esplusplayer::drm::DrmbEsMediaFormat>(from->format);
   drm_info->phase =
-      static_cast<plusplayer::drm::DrmbEsCipherPhase>(from->phase);
+      static_cast<esplusplayer::drm::DrmbEsCipherPhase>(from->phase);
 
   // kid
   if (from->kid && from->kid_length > 0) {
@@ -595,9 +775,9 @@ inline EncryptedInfoPtr convert_es_drm_info_(esplusplayer_drm_info* from) {
   auto* from_sub_data =
       reinterpret_cast<esplusplayer_drmb_es_fmp4_data*>(from->sub_data);
   if (from_sub_data && from_sub_data->subsample_count > 0) {
-    drm_info->sub_data = new plusplayer::drm::DrmbEsFragmentedMp4Data;
+    drm_info->sub_data = new esplusplayer::drm::DrmbEsFragmentedMp4Data;
     auto* sub_data =
-        reinterpret_cast<plusplayer::drm::DrmbEsFragmentedMp4Data*>(
+        reinterpret_cast<esplusplayer::drm::DrmbEsFragmentedMp4Data*>(
             drm_info->sub_data);
     for (uint32_t i = 0; i < from_sub_data->subsample_count; i++) {
       auto& subsample_info = from_sub_data->subsample_infos[i];
@@ -621,6 +801,7 @@ inline EncryptedInfoPtr convert_es_drm_info_(esplusplayer_drm_info* from) {
 
   return std::move(drm_info);
 }
+// LCOV_EXCL_STOP
 
 inline AudioStreamPtr convert_stream_ptr_(
     esplusplayer_audio_stream_info* from) {
@@ -640,7 +821,8 @@ inline AudioStreamPtr convert_stream_ptr_(
   }
 
   stream->SetCodecData(codec_data, from->codec_data_length);
-  stream->SetMimeType(static_cast<plusplayer::AudioMimeType>(from->mime_type));
+  stream->SetMimeType(
+      static_cast<esplusplayer::AudioMimeType>(from->mime_type));
   stream->SetBitrate(from->bitrate);
   stream->SetChannels(from->channels);
   stream->SetSamplerate(from->sample_rate);
@@ -655,21 +837,23 @@ inline int convert_return_type_(bool ret) {
 
 inline esplusplayer_get_decoded_video_frame_status_type
 convert_get_decoded_video_frame_status_(
-    const plusplayer::GetDecodedVideoFrameStatus status) {
+    const esplusplayer::GetDecodedVideoFrameStatus status) {
   switch (status) {
-    case plusplayer::GetDecodedVideoFrameStatus::kSuccess: {
+    case esplusplayer::GetDecodedVideoFrameStatus::kSuccess: {
       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_SUCCESS;
     }
-    case plusplayer::GetDecodedVideoFrameStatus::kNoRemainingBuffer: {
+    case esplusplayer::GetDecodedVideoFrameStatus::kNoRemainingBuffer: {
       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_NO_REMAINING_BUFFER;
     }
-    case plusplayer::GetDecodedVideoFrameStatus::kNoFilledBuffer: {
+    case esplusplayer::GetDecodedVideoFrameStatus::kNoFilledBuffer: {
       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_NO_FILLED_BUFFER;
     }
-    case plusplayer::GetDecodedVideoFrameStatus::kUnknown: {
+    case esplusplayer::GetDecodedVideoFrameStatus::kUnknown: {
+      return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN;
+    }
+    default: {
       return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN;
     }
-    default: { return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN; }
   }
   return ESPLUSPLAYER_GET_DECVIDEOFRAME_STATUS_UNKNOWN;
 }
@@ -695,7 +879,8 @@ inline VideoStreamPtr convert_stream_ptr_(
   }
 
   stream->SetCodecData(codec_data, from->codec_data_length);
-  stream->SetMimeType(static_cast<plusplayer::VideoMimeType>(from->mime_type));
+  stream->SetMimeType(
+      static_cast<esplusplayer::VideoMimeType>(from->mime_type));
   stream->SetWidth(from->width);
   stream->SetHeight(from->height);
   stream->SetMaxWidth(from->max_width);
@@ -725,6 +910,21 @@ int esplusplayer_close(esplusplayer_handle handle) {
     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
   }
 
+#ifdef ES_DUMP
+  std::ofstream& vstream =
+      static_cast<EsPlusPlayerPriv*>(handle)->video_stream_;
+  if (vstream.is_open()) {
+    vstream.close();
+    LOG_DEBUG("Close video_stream_");
+  }
+  std::ofstream& astream =
+      static_cast<EsPlusPlayerPriv*>(handle)->audio_stream_;
+  if (astream.is_open()) {
+    astream.close();
+    LOG_DEBUG("Close audio_stream_");
+  }
+#endif
+
   bool ret = cast_(handle)->Close();
   listener->Reset();
   return convert_return_type_(ret);
@@ -734,8 +934,11 @@ int esplusplayer_destroy(esplusplayer_handle handle) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
 
-  if (ESPLUSPLAYER_STATE_NONE != esplusplayer_get_state(handle))
+  esplusplayer_state state = esplusplayer_get_state(handle);
+  if (ESPLUSPLAYER_STATE_NONE != state) {
+    LOG_ERROR("state must be ESPLUSPLAYER_STATE_NONE, but %d now", state);
     return ESPLUSPLAYER_ERROR_TYPE_INVALID_STATE;
+  }
 
   auto priv = static_cast<EsPlusPlayerPriv*>(handle);
   EsPrivDestroy(priv);
@@ -761,6 +964,20 @@ int esplusplayer_activate(esplusplayer_handle handle,
       cast_(handle)->Activate(static_cast<StreamType>(type)));
 }
 
+int esplusplayer_deactivate_audio(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->DeactivateAudio());
+}
+
+int esplusplayer_activate_audio(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->ActivateAudio());
+}
+
 int esplusplayer_prepare_async(esplusplayer_handle handle) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
@@ -807,24 +1024,70 @@ int esplusplayer_set_playback_rate(esplusplayer_handle handle,
       cast_(handle)->SetPlaybackRate(playback_rate, audio_mute));
 }
 
-int esplusplayer_seek(esplusplayer_handle handle, uint64_t time_ms) {
+int esplusplayer_seek(esplusplayer_handle handle, uint64_t time) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO("%p time : %" PRId64 "", cast_(handle), time);
+  update_ready_to_seek_offset(handle, time);
+
+  return convert_return_type_(cast_(handle)->Seek(time));
+}
+
+int esplusplayer_set_app_info(esplusplayer_handle handle,
+                              const esplusplayer_app_info* app_info) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  LOG_INFO("[%p] > time : %" PRIu64, cast_(handle), time_ms);
-  update_ready_to_seek_offset(handle, time_ms);
+  if (app_info == nullptr) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
 
-  return convert_return_type_(cast_(handle)->Seek(time_ms));
+  LOG_INFO_P(cast_(handle), "app id : %s ", app_info->id);
+  LOG_INFO_P(cast_(handle), "app version : %s ", app_info->version);
+  LOG_INFO_P(cast_(handle), "app type : %s", app_info->type);
+
+  PlayerAppInfo info;
+  info.id = app_info->id;
+  info.version = app_info->version;
+  info.type = app_info->type;
+  cast_(handle)->SetAppInfo(info);
+  return convert_return_type_(true);
+}
+
+int esplusplayer_set_app_info_ex(esplusplayer_handle handle,
+                                 const esplusplayer_app_info_ex* app_info) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  if (app_info == nullptr) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  LOG_INFO_P(cast_(handle), "app id : %s ", app_info->id);
+  LOG_INFO_P(cast_(handle), "app version : %s ", app_info->version);
+  LOG_INFO_P(cast_(handle), "app type : %s", app_info->type);
+  LOG_INFO_P(cast_(handle), "app runtitle : %s", app_info->runtitle);
+
+  PlayerAppInfoEx info;
+  info.id = app_info->id;
+  info.version = app_info->version;
+  info.type = app_info->type;
+  info.runtitle = app_info->runtitle;
+  cast_(handle)->SetAppInfoEx(info);
+  return convert_return_type_(true);
 }
 
 int esplusplayer_set_display(esplusplayer_handle handle,
                              esplusplayer_display_type type, void* window) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (type < ESPLUSPLAYER_DISPLAY_TYPE_NONE ||
-    type >= ESPLUSPLAYER_DISPLAY_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
   LOG_INFO_P(cast_(handle), "display type : %d, object : %p",
              static_cast<int>(type), window);
 
+#if defined(USE_MIXER) && !defined(IS_TOMATO)
+  if (type == ESPLUSPLAYER_DISPLAY_TYPE_MIXER) {
+    mixer_handle mixer_h = window;
+    esplusplayer::MixerTicket* ticket =
+        (esplusplayer::MixerTicket*)mixer_create_ticket(mixer_h, handle);
+    if (is_null_(ticket)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+    return convert_return_type_(
+        cast_(handle)->SetDisplay(static_cast<DisplayType>(type), ticket));
+  }
+#endif // defined(USE_MIXER) && !defined(IS_TOMATO)
   return convert_return_type_(
       cast_(handle)->SetDisplay(static_cast<DisplayType>(type), window));
 }
@@ -833,9 +1096,8 @@ int esplusplayer_set_ecore_display(esplusplayer_handle handle,
                                    esplusplayer_display_type type, void* window,
                                    int x, int y, int width, int height) {
   LOG_ENTER_P(cast_(handle))
-  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (type < ESPLUSPLAYER_DISPLAY_TYPE_NONE ||
-    type >= ESPLUSPLAYER_DISPLAY_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
+  if (is_null_(handle) || is_null_(window))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
   LOG_INFO_P(cast_(handle), "display type : %d, object : %p",
              static_cast<int>(type), window);
 
@@ -843,15 +1105,26 @@ int esplusplayer_set_ecore_display(esplusplayer_handle handle,
       static_cast<DisplayType>(type), window, x, y, width, height));
 }
 
+int esplusplayer_set_display_ecore_subsurface(esplusplayer_handle handle,
+                                              esplusplayer_display_type type,
+                                              void* subsurface, int x, int y,
+                                              int width, int height) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(subsurface))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO_P(cast_(handle), "display type : %d, object : %p",
+             static_cast<int>(type), subsurface);
+
+  return convert_return_type_(cast_(handle)->SetDisplaySubsurface(
+      static_cast<DisplayType>(type), subsurface, x, y, width, height));
+}
+
 int esplusplayer_set_surface_display(esplusplayer_handle handle,
                                      esplusplayer_display_type type,
                                      unsigned int surface_id, int x, int y,
                                      int width, int height) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (type < ESPLUSPLAYER_DISPLAY_TYPE_NONE ||
-    type >= ESPLUSPLAYER_DISPLAY_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
-  if (width <= 0 || height <= 0) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
   LOG_INFO_P(cast_(handle), "display type : %d, object : %u",
              static_cast<int>(type), surface_id);
 
@@ -863,8 +1136,6 @@ int esplusplayer_set_display_mode(esplusplayer_handle handle,
                                   esplusplayer_display_mode mode) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (mode < ESPLUSPLAYER_DISPLAY_MODE_LETTER_BOX ||
-    mode >= ESPLUSPLAYER_DISPLAY_MODE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
   LOG_INFO_P(cast_(handle), "display mode : %d", static_cast<int>(mode));
 
   return convert_return_type_(
@@ -875,7 +1146,6 @@ int esplusplayer_set_display_roi(esplusplayer_handle handle, int x, int y,
                                  int width, int height) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (width <= 0 || height <= 0) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
   LOG_INFO_P(cast_(handle), "x : %d, y: %d, width : %d, height : %d", x, y,
              width, height);
 
@@ -888,6 +1158,14 @@ int esplusplayer_set_display_roi(esplusplayer_handle handle, int x, int y,
   return convert_return_type_(cast_(handle)->SetDisplayRoi(roi));
 }
 
+int esplusplayer_set_stretch_mode(esplusplayer_handle handle, int mode) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO_P(cast_(handle), "stretch mode : %d", static_cast<int>(mode));
+
+  return convert_return_type_(cast_(handle)->SetStretchMode(mode));
+}
+
 int esplusplayer_set_video_roi(esplusplayer_handle handle, double scale_x,
                                double scale_y, double scale_w, double scale_h) {
   LOG_ENTER_P(cast_(handle))
@@ -896,13 +1174,29 @@ int esplusplayer_set_video_roi(esplusplayer_handle handle, double scale_x,
              "scale-x : %lf, scale-y: %lf, scale-w : %lf, scale-h : %lf",
              scale_x, scale_y, scale_w, scale_h);
 
-  CropArea roi_area;
-  roi_area.scale_x = scale_x;
-  roi_area.scale_y = scale_y;
-  roi_area.scale_w = scale_w;
-  roi_area.scale_h = scale_h;
+  CropArea rio_area;
+  rio_area.scale_x = scale_x;
+  rio_area.scale_y = scale_y;
+  rio_area.scale_w = scale_w;
+  rio_area.scale_h = scale_h;
 
-  return convert_return_type_(cast_(handle)->SetVideoRoi(roi_area));
+  return convert_return_type_(cast_(handle)->SetVideoRoi(rio_area));
+}
+
+int esplusplayer_resize_render_rect(esplusplayer_handle handle, int x, int y,
+                                    int width, int height) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO_P(cast_(handle), "x : %d, y: %d, width : %d, height : %d", x, y,
+             width, height);
+
+  RenderRect rect;
+  rect.x = x;
+  rect.y = y;
+  rect.w = width;
+  rect.h = height;
+
+  return convert_return_type_(cast_(handle)->ResizeRenderRect(rect));
 }
 
 int esplusplayer_set_display_rotation(
@@ -931,12 +1225,17 @@ int esplusplayer_set_display_visible(esplusplayer_handle handle, bool visible) {
   return convert_return_type_(cast_(handle)->SetDisplayVisible(visible));
 }
 
+int esplusplayer_set_tz_use(esplusplayer_handle handle, bool using_tz) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO_P(cast_(handle), "using_tz : %s", using_tz ? "true" : "false");
+  return convert_return_type_(cast_(handle)->SetTrustZoneUse(using_tz));
+}
+
 int esplusplayer_set_submit_data_type(esplusplayer_handle handle,
                                       esplusplayer_submit_data_type type) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (type < ESPLUSPLAYER_SUBMIT_DATA_TYPE_CLEAN_DATA ||
-    type >= ESPLUSPLAYER_SUBMIT_DATA_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
   LOG_INFO_P(cast_(handle), "type : %d", type);
   return convert_return_type_(
       cast_(handle)->SetSubmitDataType(static_cast<SubmitDataType>(type)));
@@ -959,6 +1258,27 @@ esplusplayer_state esplusplayer_get_state(esplusplayer_handle handle) {
   return current_state;
 }
 
+#ifdef ES_DUMP
+static void esdump(esplusplayer_handle handle, esplusplayer_es_packet* packet) {
+  std::ofstream& ostream =
+      (packet->type == ESPLUSPLAYER_STREAM_TYPE_AUDIO
+           ? static_cast<EsPlusPlayerPriv*>(handle)->audio_stream_
+           : static_cast<EsPlusPlayerPriv*>(handle)->video_stream_);
+
+  if (ostream.is_open() == false) return;
+
+  uint64_t tmp = packet->pts * 1000000;
+  ostream.write(reinterpret_cast<char*>(&tmp), sizeof(uint64_t));
+  tmp = packet->duration * 1000000;
+  ostream.write(reinterpret_cast<char*>(&tmp), sizeof(uint64_t));
+  std::uint64_t size = (std::uint64_t)packet->buffer_size;
+  ostream.write(reinterpret_cast<char*>(&size), sizeof(size));
+  ostream.write(reinterpret_cast<char*>(packet->buffer), packet->buffer_size);
+  LOG_DEBUG("DUMP type:%d pkt pts: %" PRId64 "duration: %" PRId64 "size: %d",
+            packet->type, packet->pts, packet->duration, packet->buffer_size);
+}
+#endif
+
 esplusplayer_submit_status esplusplayer_submit_packet(
     esplusplayer_handle handle, esplusplayer_es_packet* packet) {
   if (is_null_(handle)) return ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED;
@@ -967,35 +1287,88 @@ esplusplayer_submit_status esplusplayer_submit_packet(
     LOG_ERROR("packet converting failed");
     return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
   }
+
+#ifdef ES_DUMP
+  esdump(handle, packet);
+#endif
+
   auto status = cast_(handle)->SubmitPacket(packetptr);
-  if (status != plusplayer::PacketSubmitStatus::kSuccess) {
+  if (status != esplusplayer::PacketSubmitStatus::kSuccess) {
+    LOG_ERROR("SubmitPacket status isn't SUCCESS [%d]",
+              static_cast<int>(status));
+  }
+  return static_cast<esplusplayer_submit_status>(status);
+}
+// LCOV_EXCL_START
+esplusplayer_submit_status esplusplayer_submit_trust_zone_packet(
+    esplusplayer_handle handle, esplusplayer_es_packet* packet,
+    uint32_t tz_handle) {
+  if (is_null_(handle)) return ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED;
+  auto packetptr = convert_espacket_(packet);
+  if (packetptr == nullptr) {
+    LOG_ERROR("packet converting failed");
+    return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
+  }
+  auto status = cast_(handle)->SubmitTrustZonePacket(packetptr, tz_handle);
+  if (status != esplusplayer::PacketSubmitStatus::kSuccess) {
+    LOG_ERROR("SubmitPacket status isn't SUCCESS [%d]",
+              static_cast<int>(status));
+  }
+  return static_cast<esplusplayer_submit_status>(status);
+}
+
+esplusplayer_submit_status esplusplayer_submit_encrypted_packet_64bit(
+    esplusplayer_handle handle, esplusplayer_es_packet* packet,
+    esplusplayer_drm_info_64bit* drm_info) {
+#if DRM_MAPI_AARCH_64
+  if (is_null_(handle)) return ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED;
+  auto packetptr = convert_espacket_(packet);
+  if (packetptr == nullptr) {
+    LOG_ERROR("packet converting failed");
+    return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
+  }
+  auto status = esplusplayer::PacketSubmitStatus::kSuccess;
+  if (drm_info == nullptr) {
+    status = cast_(handle)->SubmitPacket(packetptr);
+  } else {
+    auto encrypted_info = convert_es_drm_info_(drm_info);
+    status = cast_(handle)->SubmitEncryptedPacket(packetptr, *encrypted_info);
+  }
+  if (status != esplusplayer::PacketSubmitStatus::kSuccess) {
     LOG_ERROR("SubmitPacket status isn't SUCCESS [%d]",
               static_cast<int>(status));
   }
   return static_cast<esplusplayer_submit_status>(status);
+#else
+  return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
+#endif
 }
 
 esplusplayer_submit_status esplusplayer_submit_encrypted_packet(
     esplusplayer_handle handle, esplusplayer_es_packet* packet,
     esplusplayer_drm_info* drm_info) {
+#if DRM_MAPI_AARCH_64
+  return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
+#else
   if (is_null_(handle)) return ESPLUSPLAYER_SUBMIT_STATUS_NOT_PREPARED;
   auto packetptr = convert_espacket_(packet);
   if (packetptr == nullptr) {
     LOG_ERROR("packet converting failed");
     return ESPLUSPLAYER_SUBMIT_STATUS_INVALID_PACKET;
   }
-  auto status = plusplayer::PacketSubmitStatus::kSuccess;
+  auto status = esplusplayer::PacketSubmitStatus::kSuccess;
   if (drm_info == nullptr) {
     status = cast_(handle)->SubmitPacket(packetptr);
   } else {
     auto encrypted_info = convert_es_drm_info_(drm_info);
     status = cast_(handle)->SubmitEncryptedPacket(packetptr, *encrypted_info);
   }
-  if (status != plusplayer::PacketSubmitStatus::kSuccess) {
+  if (status != esplusplayer::PacketSubmitStatus::kSuccess) {
     LOG_ERROR("SubmitPacket status isn't SUCCESS [%d]",
               static_cast<int>(status));
   }
   return static_cast<esplusplayer_submit_status>(status);
+#endif
 }
 
 esplusplayer_submit_status esplusplayer_submit_eos_packet(
@@ -1007,6 +1380,90 @@ esplusplayer_submit_status esplusplayer_submit_eos_packet(
       std::move(EsPacket::CreateEos(static_cast<StreamType>(type))));
   return static_cast<esplusplayer_submit_status>(status);
 }
+// LCOV_EXCL_STOP
+
+#ifdef ES_DUMP
+static void audio_es_dump(esplusplayer_handle handle,
+                          esplusplayer_audio_stream_info* info) {
+  if (!exists("/tmp/asdump")) return;
+  if (!exists("/etc/debug") && !exists("/etc/perf")) return;
+
+  std::ofstream& ostream =
+      static_cast<EsPlusPlayerPriv*>(handle)->audio_stream_;
+  if (ostream.is_open()) ostream.close();
+  std::string dumppath = "/tmp/audiodump.ESP";
+  ostream.open(dumppath + ".es", std::ofstream::binary | std::ofstream::trunc);
+  if (ostream.is_open() == false) {
+    LOG_ERROR("Fail to open %s.es", dumppath.c_str());
+    return;
+  }
+  std::ofstream info_stream;
+  info_stream.open(dumppath + ".info", std::ofstream::trunc);
+  if (info_stream.is_open() == false) {
+    LOG_ERROR("Fail to open %s.info", dumppath.c_str());
+    return;
+  }
+  info_stream << static_cast<int>(info->mime_type) << std::endl;
+  info_stream << info->sample_rate << std::endl << info->channels << std::endl;
+  info_stream.close();
+  if (info->codec_data_length == 0) return;
+  std::ofstream codec_extradata_stream;
+  codec_extradata_stream.open(dumppath + ".codec_extradata",
+                              std::ofstream::binary | std::ofstream::trunc);
+  if (codec_extradata_stream.is_open() == false) {
+    LOG_ERROR("Fail to open %s.codec_extradata", dumppath.c_str());
+    return;
+  }
+  codec_extradata_stream.write(
+      reinterpret_cast<char*>(&info->codec_data_length),
+      sizeof(info->codec_data_length));
+  codec_extradata_stream.write(info->codec_data, info->codec_data_length);
+  codec_extradata_stream.close();
+}
+
+static void video_es_dump(esplusplayer_handle handle,
+                          esplusplayer_video_stream_info* info) {
+  // It requires to do "chsmack -a '_' /tmp/vsdump"
+  // after touch /tmp/vsdump on the shell
+  if (!exists("/tmp/vsdump")) return;
+  if (!exists("/etc/debug") && !exists("/etc/perf")) return;
+
+  std::ofstream& ostream =
+      static_cast<EsPlusPlayerPriv*>(handle)->video_stream_;
+  if (ostream.is_open()) ostream.close();
+  std::string dumppath = "/tmp/videodump.ESP";
+  ostream.open(dumppath + ".es", std::ofstream::binary | std::ofstream::trunc);
+  if (ostream.is_open() == false) {
+    LOG_ERROR("Fail to open %s.es", dumppath.c_str());
+    return;
+  }
+  std::ofstream info_stream;
+  info_stream.open(dumppath + ".info", std::ofstream::trunc);
+  if (info_stream.is_open() == false) {
+    LOG_ERROR("Fail to open %s.info", dumppath.c_str());
+    return;
+  }
+  info_stream << static_cast<int>(info->mime_type) << std::endl;
+  info_stream << info->width << std::endl << info->height << std::endl;
+  info_stream << info->max_width << std::endl << info->max_height << std::endl;
+  info_stream << info->framerate_num << std::endl
+              << info->framerate_den << std::endl;
+  info_stream.close();
+  if (info->codec_data_length == 0) return;
+  std::ofstream codec_extradata_stream;
+  codec_extradata_stream.open(dumppath + ".codec_extradata",
+                              std::ofstream::binary | std::ofstream::trunc);
+  if (codec_extradata_stream.is_open() == false) {
+    LOG_ERROR("Fail to open %s.codec_extradata", dumppath.c_str());
+    return;
+  }
+  codec_extradata_stream.write(
+      reinterpret_cast<char*>(&info->codec_data_length),
+      sizeof(info->codec_data_length));
+  codec_extradata_stream.write(info->codec_data, info->codec_data_length);
+  codec_extradata_stream.close();
+}
+#endif
 
 int esplusplayer_set_audio_stream_info(esplusplayer_handle handle,
                                        esplusplayer_audio_stream_info* info) {
@@ -1014,6 +1471,10 @@ int esplusplayer_set_audio_stream_info(esplusplayer_handle handle,
   if (is_null_(handle) || is_null_(info))
     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
 
+#ifdef ES_DUMP
+  audio_es_dump(handle, info);
+#endif
+
   auto stream = convert_stream_ptr_(info);
   return convert_return_type_(cast_(handle)->SetStream(std::move(stream)));
 }
@@ -1024,17 +1485,21 @@ int esplusplayer_set_video_stream_info(esplusplayer_handle handle,
   if (is_null_(handle) || is_null_(info))
     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
 
+#ifdef ES_DUMP
+  video_es_dump(handle, info);
+#endif
+
   auto stream = convert_stream_ptr_(info);
   return convert_return_type_(cast_(handle)->SetStream(std::move(stream)));
 }
 
-int esplusplayer_get_playing_time(esplusplayer_handle handle, uint64_t* ms) {
-  // LOG_ENTER_P(cast_(handle))
-  if (is_null_(handle) || is_null_(ms))
+int esplusplayer_get_playing_time(esplusplayer_handle handle,
+                                  uint64_t* cur_time) {
+  if (is_null_(handle) || is_null_(cur_time))
     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
 
-  auto ret = cast_(handle)->GetPlayingTime(ms);
-  // LOG_INFO("[%p] > playing time : %" PRIu64, cast_(handle), *ms);
+  auto ret = cast_(handle)->GetPlayingTime(cur_time);
+  // LOG_INFO_P(cast_(handle), "playing time : %llu", *ms);
   return convert_return_type_(ret);
 }
 
@@ -1044,19 +1509,23 @@ std::shared_ptr<DecodedPacketManagerInterface> CreateDecodedPacketManager(
     esplusplayer_decoded_video_frame_buffer_type type) {
   std::shared_ptr<DecodedPacketManagerInterface> mgr = nullptr;
   if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_COPY)
-    mgr = std::make_shared<plusplayer::DecodedCopiedPacketList>();
+    mgr = std::make_shared<esplusplayer::DecodedCopiedPacketList>();
   else if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_REFERENCE)
-    mgr = std::make_shared<plusplayer::DecodedReferencePacketList>();
+    mgr = std::make_shared<esplusplayer::DecodedReferencePacketList>();
   else if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_SCALE)
-    mgr = std::make_shared<plusplayer::DecodedScaledPacketList>();
+    mgr = std::make_shared<esplusplayer::DecodedScaledPacketList>();
   else if (type == ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_MANUAL_COPY)
-    mgr = std::make_shared<plusplayer::ManualDecodedCopiedPacketList>(
+    mgr = std::make_shared<esplusplayer::ManualDecodedCopiedPacketList>(
         [handle](esplusplayer_decoded_video_packet* pkt) {
-          plusplayer::DecodedVideoPacket _pkt;
+          esplusplayer::DecodedVideoPacket _pkt;
           _pkt.pts = pkt->pts;
           _pkt.duration = pkt->duration;
           _pkt.surface_data = static_cast<tbm_surface_h>(pkt->surface_data);
+#ifdef TIZEN_FEATURE_PUBLIC
           _pkt.buffer_addr = pkt->private_data;
+#else
+          _pkt.scaler_index = pkt->private_data;
+#endif
           return cast_(handle)->ReturnDecodedPacket(_pkt);
         });
   return mgr;
@@ -1069,16 +1538,43 @@ int esplusplayer_set_video_frame_buffer_type(
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle) || is_null_(listener_cast_(handle)))
     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO_P(cast_(handle), "decoded buffer type : %d", static_cast<int>(type));
 
   auto priv = static_cast<EsPlusPlayerPriv*>(handle);
   priv->decoded_pkt_mgr = ::CreateDecodedPacketManager(handle, type);
   priv->listener->SetDecodedPacketManager(priv->decoded_pkt_mgr);
 
   auto ret = cast_(handle)->SetVideoFrameBufferType(
-      static_cast<plusplayer::DecodedVideoFrameBufferType>(type));
+      static_cast<esplusplayer::DecodedVideoFrameBufferType>(type));
   return convert_return_type_(ret);
 }
 
+int esplusplayer_set_video_frame_buffer_scale_resolution(
+    esplusplayer_handle handle, uint32_t target_width, uint32_t target_height) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || !target_width || !target_height)
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  LOG_INFO_P(cast_(handle), "target_width : %d, target_height: %d",
+             target_width, target_height);
+  return convert_return_type_(cast_(handle)->SetVideoFrameBufferScaleResolution(
+      target_width, target_height));
+}
+
+int esplusplayer_set_decoded_video_frame_rate(
+    esplusplayer_handle handle, esplusplayer_rational request_framerate) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO("request decoded video frame rate : %d/%d", request_framerate.num,
+           request_framerate.den);
+
+  Rational request_fps;
+  request_fps.num = request_framerate.num;
+  request_fps.den = request_framerate.den;
+  return convert_return_type_(
+      cast_(handle)->SetDecodedVideoFrameRate(request_fps));
+}
+
 int esplusplayer_get_adaptive_info(
     esplusplayer_handle handle, void* padaptive_info,
     esplusplayer_adaptive_info_type adaptive_type) {
@@ -1185,18 +1681,10 @@ int esplusplayer_set_buffer_size(esplusplayer_handle handle,
                                  uint64_t size) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  LOG_INFO("[%p] > option: %d, size: %" PRId64, cast_(handle),
-             static_cast<int>(option), size);
-  cast_(handle)->SetBufferSize(static_cast<plusplayer::BufferOption>(option),
-                               size);
-  return convert_return_type_(true);
-}
-
-int esplusplayer_enable_video_hole(esplusplayer_handle handle, const bool value) {
-  LOG_ENTER_P(cast_(handle))
-  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-
-  auto ret = cast_(handle)->EnableVideoHole(value);
+  LOG_INFO("%p option: %d, size: %" PRId64 "", cast_(handle),
+           static_cast<int>(option), size);
+  auto ret = cast_(handle)->SetBufferSize(
+      static_cast<esplusplayer::BufferOption>(option), size);
   return convert_return_type_(ret);
 }
 
@@ -1301,7 +1789,6 @@ int esplusplayer_set_media_packet_video_decoded_cb(
 
   listener->media_packet_video_decoded_cb_ = media_packet_video_decoded_cb;
   listener->media_packet_video_decoded_cb_userdata_ = userdata;
-
   return convert_return_type_(true);
 }
 
@@ -1349,6 +1836,7 @@ int esplusplayer_set_event_cb(esplusplayer_handle handle,
   return convert_return_type_(true);
 }
 
+// LCOV_EXCL_START
 int esplusplayer_set_first_video_decoding_done_cb(
     esplusplayer_handle handle,
     esplusplayer_first_video_decoding_done_cb first_video_decoding_done_cb,
@@ -1364,6 +1852,85 @@ int esplusplayer_set_first_video_decoding_done_cb(
   return convert_return_type_(true);
 }
 
+int esplusplayer_set_video_decoder_underrun_cb(
+    esplusplayer_handle handle,
+    esplusplayer_decoder_underrun_cb video_decoder_underrun_cb,
+    void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+  listener->video_decoder_underrun_cb_ = video_decoder_underrun_cb;
+  listener->video_decoder_underrun_cb_userdata_ = userdata;
+
+  return convert_return_type_(true);
+}
+// LCOV_EXCL_STOP
+
+int esplusplayer_set_video_latency_status_cb(
+    esplusplayer_handle handle,
+    esplusplayer_video_latency_status_cb video_latency_status_cb,
+    void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+
+  listener->video_latency_status_cb_ = video_latency_status_cb;
+  listener->video_latency_status_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
+
+int esplusplayer_set_audio_latency_status_cb(
+    esplusplayer_handle handle,
+    esplusplayer_audio_latency_status_cb audio_latency_status_cb,
+    void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+
+  listener->audio_latency_status_cb_ = audio_latency_status_cb;
+  listener->audio_latency_status_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
+
+int esplusplayer_set_video_high_latency_cb(
+    esplusplayer_handle handle,
+    esplusplayer_video_high_latency_cb video_high_latency_cb, void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+
+  listener->video_high_latency_cb_ = video_high_latency_cb;
+  listener->video_high_latency_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
+
+int esplusplayer_set_audio_high_latency_cb(
+    esplusplayer_handle handle,
+    esplusplayer_audio_high_latency_cb audio_high_latency_cb, void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+
+  listener->audio_high_latency_cb_ = audio_high_latency_cb;
+  listener->audio_high_latency_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
+
 int esplusplayer_get_decoded_video_packet(
     esplusplayer_handle handle, esplusplayer_decoded_video_packet* packet,
     esplusplayer_get_decoded_video_frame_status_type* state) {
@@ -1371,17 +1938,21 @@ int esplusplayer_get_decoded_video_packet(
     LOG_ERROR("handle[%p] or packet[%p] is nil.", handle, packet);
     return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
   }
-  plusplayer::DecodedVideoPacket _packet;
+  esplusplayer::DecodedVideoPacket _packet;
   bool ret = false;
   auto _state = cast_(handle)->GetDecodedPacket(_packet);
-  if (_state != plusplayer::GetDecodedVideoFrameStatus::kUnknown) {
+  if (_state != esplusplayer::GetDecodedVideoFrameStatus::kUnknown) {
     ret = true;
   }
-  if (_state == plusplayer::GetDecodedVideoFrameStatus::kSuccess) {
+  if (_state == esplusplayer::GetDecodedVideoFrameStatus::kSuccess) {
     packet->pts = _packet.pts;
     packet->duration = _packet.duration;
     packet->surface_data = static_cast<void*>(_packet.surface_data);
+#ifdef TIZEN_FEATURE_PUBLIC
     packet->private_data = _packet.buffer_addr;
+#else
+    packet->private_data = _packet.scaler_index;
+#endif
   }
   if (state) {
     *state = convert_get_decoded_video_frame_status_(_state);
@@ -1409,18 +1980,25 @@ int esplusplayer_set_low_latency_mode(esplusplayer_handle handle,
                                       esplusplayer_low_latency_mode mode) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (mode != ESPLUSPLAYER_LOW_LATENCY_MODE_NONE &&
-      mode != ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO &&
-      mode != ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC &&
-      mode != ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL) {
-    LOG_WARN("Not supported latency mode 0x%x", static_cast<std::uint32_t>(mode));
-    return ESPLUSPLAYER_ERROR_TYPE_NONE;
-  }
   auto ret =
       cast_(handle)->SetLowLatencyMode(static_cast<PlayerLowLatencyMode>(mode));
   return convert_return_type_(ret);
 }
 
+int esplusplayer_set_video_frame_peek_mode(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->SetVideoFramePeekMode();
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_render_video_frame(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->RenderVideoFrame();
+  return convert_return_type_(ret);
+}
+
 int esplusplayer_set_unlimited_max_buffer_mode(esplusplayer_handle handle) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
@@ -1428,28 +2006,56 @@ int esplusplayer_set_unlimited_max_buffer_mode(esplusplayer_handle handle) {
   return convert_return_type_(ret);
 }
 
+int esplusplayer_set_fmm_mode(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->SetFmmMode();
+  return util::ConvertErrorCode(ret);
+}
+
 int esplusplayer_set_audio_codec_type(esplusplayer_handle handle,
                                       esplusplayer_audio_codec_type type) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (type < ESPLUSPLAYER_AUDIO_CODEC_TYPE_HW ||
-    type >= ESPLUSPLAYER_AUDIO_CODEC_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
   auto ret =
       cast_(handle)->SetAudioCodecType(static_cast<PlayerAudioCodecType>(type));
   return convert_return_type_(ret);
 }
 
+int esplusplayer_set_aifilter(esplusplayer_handle handle, void* aifilter) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(aifilter))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->SetAiFilter(aifilter);
+  return convert_return_type_(ret);
+}
+
 int esplusplayer_set_video_codec_type(esplusplayer_handle handle,
                                       esplusplayer_video_codec_type type) {
   LOG_ENTER_P(cast_(handle))
   if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
-  if (type < ESPLUSPLAYER_VIDEO_CODEC_TYPE_HW ||
-    type >= ESPLUSPLAYER_VIDEO_CODEC_TYPE_MAX) return ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION;
   auto ret =
       cast_(handle)->SetVideoCodecType(static_cast<PlayerVideoCodecType>(type));
   return convert_return_type_(ret);
 }
 
+int esplusplayer_set_alternative_video_resource(esplusplayer_handle handle,
+                                                unsigned int rsc_type) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->SetAlternativeVideoResource(rsc_type);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_alternative_audio_resource(
+    esplusplayer_handle handle, esplusplayer_audio_resource_type rsc_type) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->SetAlternativeAudioResource(
+      static_cast<PlayerAudioResourceType>(rsc_type));
+  return convert_return_type_(ret);
+}
+
 int esplusplayer_set_render_time_offset(esplusplayer_handle handle,
                                         esplusplayer_stream_type type,
                                         int64_t offset) {
@@ -1470,3 +2076,384 @@ int esplusplayer_get_render_time_offset(esplusplayer_handle handle,
       cast_(handle)->GetRenderTimeOffset(static_cast<StreamType>(type), offset);
   return convert_return_type_(ret);
 }
+
+int esplusplayer_switch_audio_stream_onthefly(
+    esplusplayer_handle handle, esplusplayer_audio_stream_info* info) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(info))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto stream = convert_stream_ptr_(info);
+  auto ret = cast_(handle)->SwitchAudioStreamOnTheFly(std::move(stream));
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_init_audio_easing_info(
+    esplusplayer_handle handle, uint32_t init_volume, uint32_t elapsed_time,
+    const esplusplayer_target_audio_easing_info* easing_info) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  if (easing_info == nullptr) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  AudioEasingInfo info;
+  info.target_volume = easing_info->volume;
+  info.duration = easing_info->duration;
+  info.type = static_cast<AudioEasingType>(easing_info->type);
+  auto ret =
+      cast_(handle)->InitAudioEasingInfo(init_volume, elapsed_time, info);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_update_audio_easing_info(
+    esplusplayer_handle handle,
+    const esplusplayer_target_audio_easing_info* easing_info) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  if (easing_info == nullptr) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  AudioEasingInfo info;
+  info.target_volume = easing_info->volume;
+  info.duration = easing_info->duration;
+  info.type = static_cast<AudioEasingType>(easing_info->type);
+
+  auto ret = cast_(handle)->UpdateAudioEasingInfo(info);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_audio_easing_info(
+    esplusplayer_handle handle, uint32_t* current_volume,
+    uint32_t* elapsed_time,
+    esplusplayer_target_audio_easing_info* easing_info) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  if (is_null_(current_volume) || is_null_(elapsed_time) ||
+      is_null_(easing_info))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  AudioEasingInfo info;
+  auto ret =
+      cast_(handle)->GetAudioEasingInfo(current_volume, elapsed_time, &info);
+  easing_info->volume = info.target_volume;
+  easing_info->duration = info.duration;
+  easing_info->type = static_cast<esplusplayer_audio_easing_type>(info.type);
+
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_start_audio_easing(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->StartAudioEasing();
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_stop_audio_easing(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  auto ret = cast_(handle)->StopAudioEasing();
+  return convert_return_type_(ret);
+}
+
+// LCOV_EXCL_START
+int get_size_of_esplusplayer_app_info(void) {
+  return sizeof(esplusplayer_app_info);
+}
+
+int get_size_of_esplusplayer_es_packet(void) {
+  return sizeof(esplusplayer_es_packet);
+}
+
+int get_size_of_esplusplayer_es_tz_packet(void) {
+  return sizeof(esplusplayer_es_tz_packet);
+}
+
+int get_size_of_esplusplayer_audio_stream_info(void) {
+  return sizeof(esplusplayer_audio_stream_info);
+}
+
+int get_size_of_esplusplayer_video_stream_info(void) {
+  return sizeof(esplusplayer_video_stream_info);
+}
+
+int get_size_of_esplusplayer_drm_info(void) {
+#ifdef DRM_MAPI_AARCH_64
+  return sizeof(esplusplayer_drm_info_64bit);
+#else
+  return sizeof(esplusplayer_drm_info);
+#endif
+}
+// LCOV_EXCL_STOP
+
+int esplusplayer_set_catch_up_speed(esplusplayer_handle handle,
+                                    esplusplayer_catch_up_speed level) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  if (level < ESPLUSPLAYER_CATCH_UP_SPEED_NONE ||
+      level > ESPLUSPLAYER_CATCH_UP_SPEED_FAST) {
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+  auto ret = cast_(handle)->SetCatchUpSpeed(static_cast<CatchUpSpeed>(level));
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_video_latency_status(esplusplayer_handle handle,
+                                          esplusplayer_latency_status* status) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(status))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  LatencyStatus current_status = LatencyStatus::kLow;
+  auto ret = cast_(handle)->GetVideoLatencyStatus(&current_status);
+  *status = static_cast<esplusplayer_latency_status>(current_status);
+
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_audio_latency_status(esplusplayer_handle handle,
+                                          esplusplayer_latency_status* status) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(status))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  LatencyStatus current_status = LatencyStatus::kLow;
+  auto ret = cast_(handle)->GetAudioLatencyStatus(&current_status);
+  *status = static_cast<esplusplayer_latency_status>(current_status);
+
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_video_mid_latency_threshold(esplusplayer_handle handle,
+                                                 const unsigned int threshold) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret = cast_(handle)->SetVideoMidLatencyThreshold(threshold);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_audio_mid_latency_threshold(esplusplayer_handle handle,
+                                                 const unsigned int threshold) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret = cast_(handle)->SetAudioMidLatencyThreshold(threshold);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_video_high_latency_threshold(
+    esplusplayer_handle handle, const unsigned int threshold,
+    esplusplayer_video_high_latency_cb video_high_latency_cb, void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  esplusplayer_set_video_high_latency_cb(handle, video_high_latency_cb,
+                                         userdata);
+
+  auto ret = cast_(handle)->SetVideoHighLatencyThreshold(threshold);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_audio_high_latency_threshold(
+    esplusplayer_handle handle, const unsigned int threshold,
+    esplusplayer_audio_high_latency_cb audio_high_latency_cb, void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  esplusplayer_set_audio_high_latency_cb(handle, audio_high_latency_cb,
+                                         userdata);
+
+  auto ret = cast_(handle)->SetAudioHighLatencyThreshold(threshold);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_low_latency_pcm_buffer_size(esplusplayer_handle handle,
+                                                 uint64_t* frame_count) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret = cast_(handle)->GetLowLatencyPcmBufferSize(frame_count);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_low_latency_pcm_current_buffer_level(
+    esplusplayer_handle handle, uint64_t* frame_count) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret = cast_(handle)->GetLowLatencyPcmCurrentBufferLevel(frame_count);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_low_latency_pcm_underrun_count(esplusplayer_handle handle,
+                                                    uint64_t* underrun_count) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret = cast_(handle)->GetLowLatencyPcmUnderrunCount(underrun_count);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_virtual_rsc_id(esplusplayer_handle handle,
+                                    const esplusplayer_rsc_type type,
+                                    int* virtual_id) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(virtual_id))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret =
+      cast_(handle)->GetVirtualRscId(static_cast<RscType>(type), virtual_id);
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_advanced_picture_quality_type(
+    esplusplayer_handle handle,
+    esplusplayer_advanced_picture_quality_type type) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret = cast_(handle)->SetAdvancedPictureQualityType(
+      static_cast<AdvPictureQualityType>(type));
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_resource_allocate_policy(
+    esplusplayer_handle handle, esplusplayer_rsc_alloc_policy policy) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO("policy: %d", static_cast<int>(policy));
+
+  auto ret = cast_(handle)->SetResourceAllocatePolicy(
+      static_cast<RscAllocPolicy>(policy));
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_audio_preloading(esplusplayer_handle handle) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  return convert_return_type_(cast_(handle)->SetAudioPreloading());
+}
+
+int esplusplayer_set_video_frame_dropped_cb(
+    esplusplayer_handle handle,
+    esplusplayer_video_frame_dropped_cb video_frame_dropped_cb,
+    void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+
+  listener->video_frame_dropped_cb_ = video_frame_dropped_cb;
+  listener->video_frame_dropped_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
+
+int esplusplayer_set_decoder_input_buffer_time_cb(
+    esplusplayer_handle handle,
+    esplusplayer_decoder_buffer_time_cb decoder_buffer_time_cb,
+    void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+
+  listener->decoder_input_buffer_time_cb_ = decoder_buffer_time_cb;
+  listener->decoder_input_buffer_time_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
+
+int esplusplayer_set_decoder_output_buffer_time_cb(
+    esplusplayer_handle handle,
+    esplusplayer_decoder_buffer_time_cb decoder_buffer_time_cb,
+    void* userdata) {
+  LOG_ENTER_P(cast_(handle))
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("ESPlayer or Listener object is nil.");
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+
+  listener->decoder_output_buffer_time_cb_ = decoder_buffer_time_cb;
+  listener->decoder_output_buffer_time_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
+
+int esplusplayer_set_video_scan_type(esplusplayer_handle handle,
+                                     esplusplayer_video_scan_type type) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(listener_cast_(handle)))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO("scan type: %d", static_cast<int>(type));
+
+  auto ret =
+      cast_(handle)->SetVideoScanType(static_cast<PlayerVideoScanType>(type));
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_get_decoding_time(esplusplayer_handle handle,
+                                   esplusplayer_stream_type type,
+                                   int32_t* time_in_milliseconds) {
+  if (is_null_(handle) || is_null_(time_in_milliseconds))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  StreamType stream_type = static_cast<StreamType>(type);
+
+  auto ret = cast_(handle)->GetDecodingTime(stream_type, time_in_milliseconds);
+  LOG_INFO_I("decoding_time = %d", *time_in_milliseconds);
+  return convert_return_type_(ret);
+}
+int esplusplayer_set_timeunit_type(esplusplayer_handle handle,
+                                   esplusplayer_time_unit_type type) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(listener_cast_(handle)))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO("time unit type: %d", static_cast<int>(type));
+  auto ret =
+      cast_(handle)->SetTimeUnitType(static_cast<PlayerTimeUnitType>(type));
+  return convert_return_type_(ret);
+}
+
+int esplusplayer_set_video_stream_rotation_info(
+    esplusplayer_handle handle,
+    const esplusplayer_video_stream_rotation_type rotation) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO_P(cast_(handle), "video stream rotation type : %d",
+             static_cast<int>(rotation));
+  return convert_return_type_(cast_(handle)->SetVideoStreamRotationInfo(
+      static_cast<VideoRotation>(rotation)));
+}
+
+int esplusplayer_get_video_stream_rotation_info(
+    esplusplayer_handle handle,
+    esplusplayer_video_stream_rotation_type* rotation) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle) || is_null_(rotation))
+    return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  return convert_return_type_(cast_(handle)->GetVideoStreamRotationInfo(
+      reinterpret_cast<VideoRotation*>(rotation)));
+}
+
+int esplusplayer_set_simple_mix_out_buffer_level(
+    esplusplayer_handle handle,
+    esplusplayer_simple_mix_out_buffer_level level) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO_P(cast_(handle), "buffer level : %d", static_cast<int>((level)));
+
+  return convert_return_type_(cast_(handle)->SetSimpleMixOutBufferLevel(
+      static_cast<PlayerSimpleMixOutBufferLevel>(level)));
+}
+
+#ifdef TIZEN_FEATURE_PUBLIC
+int esplusplayer_enable_video_hole(esplusplayer_handle handle, const bool value) {
+  LOG_ENTER_P(cast_(handle))
+  if (is_null_(handle)) return ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto ret = cast_(handle)->EnableVideoHole(value);
+  return convert_return_type_(ret);
+}
+#endif
diff --git a/src/mixer/CMakeLists.txt b/src/mixer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b68139c
--- /dev/null
@@ -0,0 +1,60 @@
+PROJECT(mixer)
+
+SET(fw_name "${PROJECT_NAME}")
+SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
+SET(${fw_name}_LDFLAGS)
+
+SET(${fw_name}_CXXFLAGS "-Wall -Werror -std=c++14 -fPIC -Wl,-z,relro -fstack-protector")
+
+SET(dependents "dlog boost gstreamer-1.0 libtbm graphics-control")
+
+INCLUDE(FindPkgConfig)
+
+IF(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
+pkg_check_modules(${fw_name} REQUIRED ${dependents})
+ELSE(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
+pkg_check_modules(${fw_name} REQUIRED ${dependents})
+ENDIF(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
+
+FOREACH(flag ${${fw_name}_CFLAGS})
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+FOREACH(flag ${${fw_name}_CXXFLAGS})
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_SOURCE_DIR} DIRECTORY)
+INCLUDE_DIRECTORIES(
+  ${PROJECT_SOURCE_DIR}/include_internal
+  ${PARENT_DIR}/plusplayer-core/include_internal
+)
+
+SET(CC_SRCS
+  ${PROJECT_SOURCE_DIR}/src/mixer_capi.cpp
+  ${PROJECT_SOURCE_DIR}/src/mixer.cpp
+  ${PROJECT_SOURCE_DIR}/src/defaultmixer.cpp
+  ${PROJECT_SOURCE_DIR}/src/sys/tbminterface.cpp
+  ${PROJECT_SOURCE_DIR}/src/tizen/tizenaccessiblebufferobj.cpp
+  ${PROJECT_SOURCE_DIR}/src/tizen/tizenbufferkeyvideoframe.cpp
+  ${PROJECT_SOURCE_DIR}/src/tizen/tizendefaultphyaddraccessor.cpp
+  ${PROJECT_SOURCE_DIR}/src/tizen/tizenhwbufferobj.cpp
+  ${PROJECT_SOURCE_DIR}/src/tizen/tizenhwvideoframe.cpp
+  ${PROJECT_SOURCE_DIR}/src/tizen/tizenrenderableobj_factory.cpp
+  ${PROJECT_SOURCE_DIR}/src/tizen/tizensurfacevideoframe.cpp
+  ${PROJECT_SOURCE_DIR}/src/abs_videoframe.cpp
+  ${PROJECT_SOURCE_DIR}/src/mixedframe.cpp
+  ${PROJECT_SOURCE_DIR}/src/renderer.cpp
+  ${PROJECT_SOURCE_DIR}/src/videoplane.cpp
+)
+
+ADD_LIBRARY(${fw_name} SHARED ${CC_SRCS})
+
+SET_TARGET_PROPERTIES(${fw_name} PROPERTIES LINKER_LANGUAGE CXX)
+
+TARGET_LINK_LIBRARIES(${fw_name} ${CMAKE_THREAD_LIBS_INIT} ${${fw_name}_LDFLAGS})
+
+INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(
+        DIRECTORY ${INC_DIR}/ DESTINATION include/
+)
diff --git a/src/mixer/include_internal/mixer/abs_videoframe.h b/src/mixer/include_internal/mixer/abs_videoframe.h
new file mode 100644 (file)
index 0000000..0e1feac
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_ABSTRACT_MIXER_VIDEO_FRAME_H__
+#define __ESPLUSPLAYER_ABSTRACT_MIXER_VIDEO_FRAME_H__
+
+#include <memory>
+
+#include "mixer/interfaces/videoplanecollection.h"
+#include "mixer/interfaces/videoplanemanipulable.h"
+
+namespace esplusplayer {
+
+class AbstractVideoFrame : public VideoPlaneCollection {
+ public:
+  using VideoPlaneManipulablePtr = std::unique_ptr<VideoPlaneManipulable>;
+
+ public:
+  explicit AbstractVideoFrame() = default;
+  virtual ~AbstractVideoFrame() = default;
+
+ public:
+  virtual const std::vector<VideoPlaneManipulableInfo> GetVideoPlaneManipInfo()
+      const override;
+
+  bool IsValid() const;
+  bool SetCropArea(const CropArea& croparea);
+  const std::uint32_t GetWidth() const;
+  const std::uint32_t GetHeight() const;
+
+ protected:
+  virtual bool IsValid_() const = 0;
+  virtual const std::uint32_t GetWidth_() const = 0;
+  virtual const std::uint32_t GetHeight_() const = 0;
+
+ protected:
+  void RegisterVideoPlaneManipulablePtr_(VideoPlaneManipulablePtr vpmanip);
+
+ private:
+  std::vector<VideoPlaneManipulablePtr> planes_;
+};
+}  // namespace esplusplayer
+
+#endif
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/defaultmixer.h b/src/mixer/include_internal/mixer/defaultmixer.h
new file mode 100644 (file)
index 0000000..fe980f3
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_PLAYER_DEFAULTMIXER__H__
+#define __ESPLUSPLAYER_SRC_PLAYER_DEFAULTMIXER__H__
+
+#include <trackrenderer_capi/trackrenderer_capi.h>
+
+#include <cassert>
+#include <chrono>
+#include <list>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <thread>
+
+#include "core/utils/plusplayer_log.h"
+#include "mixer/interfaces/videoplanecollection.h"
+#include "mixer/mixer.h"
+#include "mixer/mixerticket.h"
+#include "mixer/renderer.h"
+#include "mixer/tizen/tizenbuffermgr.h"
+
+namespace esplusplayer {
+
+class DefaultMixer : public Mixer {
+ public:
+  using RendererPtr = std::unique_ptr<Renderer>;
+
+ public:
+  DefaultMixer();
+  ~DefaultMixer();
+
+  bool Start() override;
+  bool Stop() override;
+  int GetMaximumAllowedNumberOfPlayer() override;
+  bool SetDisplay(const DisplayType type, void* obj) override;
+  bool SetDisplay(const DisplayType type, const uint32_t surface_id,
+                  const int x, const int y, const int w, const int h) override;
+  bool SetDisplayMode(const DisplayMode& mode) override;
+  bool SetDisplayRoi(const Geometry& geometry) override;
+  bool DisableAudioFocusSetting() override;
+  bool SetAlternativeVideoScaler() override;
+  bool SetAudioFocus(const void* player_instance) override;
+  bool SetRscAllocMode(const RscAllocMode& mode) override;
+  bool Commit() override;
+  bool SetResolution(const ResolutionInfo& info) override;
+  bool RegisterListener(MixerEventListener* listener) override;
+  MixerTicket* CreateTicket(const void* player_instance) override;
+
+  class Ticket : public MixerTicket {
+   public:
+    explicit Ticket(DefaultMixer* handler, const void* player_instance)
+        : handler_(handler), player_instance_(player_instance) {
+      assert(handler);
+    }
+    ~Ticket();
+    bool GetAvailableResourceType(const ResourceCategory& category,
+                                  ResourceType* type) override;
+    bool Alloc(const ResourceCategory& category,
+               const ResourceType& type) override;
+    bool Render(const DecodedRawInfo& info) override;
+    bool Render(const DecodedVideoKeyTypeInfo& info) override;
+    bool RegisterListener(MixerTicketEventListener* listener) override;
+    bool Prepare() override;
+    bool IsAudioFocusHandler() override;
+    bool IsRscAllocHandler() override;
+
+    // interface for defaultmixer
+    MixerTicketEventListener* GetListener();
+    bool IsAudioFocused();
+    void SetAudioFocus(bool active);
+    void GetDisplayInfo(DisplayInfo* info);
+    bool HasRenderedBefore();
+    void UpdateDisplayInfo(const DisplayInfo& info);
+    void DeallocResource();
+    void RecordRenderingTime();
+
+   private:
+    DefaultMixer* handler_ = nullptr;
+    const void* player_instance_ = nullptr;
+    MixerTicketEventListener* ticket_listener_ = nullptr;
+    bool is_audio_focus_ = false;
+    DisplayInfo each_display_info_;
+    bool has_rendered_ = false;
+    std::chrono::system_clock::time_point last_rendering_time_;
+  };
+
+ private:
+  struct Resource {
+    ResourceCategory category = ResourceCategory::kVideoDecoder;
+    ResourceType type = ResourceType::kHwMain;
+    const void* assignee = nullptr;
+  };
+
+  class MixerRendererEventListener : public RendererEventListener {
+   public:
+    explicit MixerRendererEventListener(TrackRendererHandle* trhandle_ptr);
+    virtual ~MixerRendererEventListener();
+    virtual bool OnRenderingRelease(const BufferKeyType& key) override;
+
+   private:
+    void* CreateGstBuffer_(const BufferKeyType& key) const;
+    void FillDecoderInputBuffer_(TrackRendererDecoderInputBuffer& buffer,
+                                 const BufferKeyType& key) const;
+
+   private:
+    TrackRendererHandle* trhandle_ptr_;
+  };
+
+ private:
+  bool Detach_(const void* player_instance);
+  bool GetAvailableResourceType_();
+  bool Render_(const void* player_instance,
+               const VideoPlaneCollection& vplanes);
+  bool RegisterListener_();
+  void InitResourceList_();
+  bool IsNeededToSkipRendering_(const DisplayInfo& display_info);
+
+  using UserData = void*;
+  static void ResourceConflictCb_(UserData userdata);
+  static void ErrorCb_(const TrackRendererErrorType error_code,
+                       UserData userdata);
+
+ private:
+  std::map<const void*, Ticket*> player_map_;
+  std::mutex mixer_lock_;
+  std::mutex ticket_lock_;
+  bool is_started_ = false;
+  MixerEventListener* listener_ = nullptr;
+  TrackRendererHandle trackrenderer_handle_ = nullptr;
+  const void* audio_focused_player_ = nullptr;
+  ResolutionInfo whole_resolution_;
+  std::list<Resource> resource_list_;
+  bool enable_audio_focus_setting_ = true;
+  RscAllocMode resource_allocation_mode_ = RscAllocMode::kDefault;
+  bool use_sub_scaler_ = false;
+  RendererPtr renderer_;
+  MixerRendererEventListener renderer_listener_;
+  TizenBufferManager bufmgr_;
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_PLAYER_DEFAULTMIXER__H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/accessiblebuffer.h b/src/mixer/include_internal/mixer/interfaces/accessiblebuffer.h
new file mode 100644 (file)
index 0000000..0725d7c
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_ACCESSIBLE_BUFFER_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_ACCESSIBLE_BUFFER_H__
+
+#include <memory>
+
+#include "mixer/interfaces/bufferobject.h"
+#include "mixer/interfaces/phyaddraccessor.h"
+
+namespace esplusplayer {
+struct AccessibleBuffer {
+  using PhyAddrAccessorPtr = std::unique_ptr<PhysicalAddressAccessor>;
+
+  virtual ~AccessibleBuffer() = default;
+  virtual PhyAddrAccessorPtr GetReadableAddress() const = 0;
+  virtual PhyAddrAccessorPtr GetWritableAddress() const = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_ACCESSIBLE_BUFFER_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/bufferobject.h b/src/mixer/include_internal/mixer/interfaces/bufferobject.h
new file mode 100644 (file)
index 0000000..bbd99c2
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_BUFFER_OBJECT_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_BUFFER_OBJECT_H__
+
+#include "mixer/types/buffertype.h"
+
+namespace esplusplayer {
+struct BufferObject {
+  virtual ~BufferObject() = default;
+
+  virtual BufferHandleType GetBufferHandle() const = 0;
+  virtual BufferKeyType Export() const = 0;
+  virtual std::uint32_t GetSize() const = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_BUFFER_OBJECT_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/memoryallocator.h b/src/mixer/include_internal/mixer/interfaces/memoryallocator.h
new file mode 100644 (file)
index 0000000..9ee0b4a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_MEMORY_OPERATOR_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_MEMORY_OPERATOR_H__
+
+#include <cstdint>
+#include <memory>
+
+#include "mixer/interfaces/bufferobject.h"
+#include "mixer/types/buffertype.h"
+
+namespace esplusplayer {
+
+struct MemoryAllocator {
+  virtual ~MemoryAllocator() = default;
+  virtual BufferObject* Allocate(const std::uint32_t& size) const = 0;
+};
+}  // namespace esplusplayer
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_MEMORY_OPERATOR_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/phyaddraccessor.h b/src/mixer/include_internal/mixer/interfaces/phyaddraccessor.h
new file mode 100644 (file)
index 0000000..636f377
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_PHYSICAL_ADDRESS_ACCESSOR_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_PHYSICAL_ADDRESS_ACCESSOR_H__
+
+#include "mixer/types/buffertype.h"
+
+namespace esplusplayer {
+struct PhysicalAddressAccessor {
+  virtual ~PhysicalAddressAccessor() = default;
+  virtual BufferPhysicalAddrType GetAddress() = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_PHYSICAL_ADDRESS_ACCESSOR_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/renderableobj_factory.h b/src/mixer/include_internal/mixer/interfaces/renderableobj_factory.h
new file mode 100644 (file)
index 0000000..29146f9
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_RENDERABLE_OBJECT_FACTORY_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_RENDERABLE_OBJECT_FACTORY_H__
+
+#include "mixer/interfaces/renderableobject.h"
+
+namespace esplusplayer {
+struct RenderableObjectFactory {
+  virtual ~RenderableObjectFactory() = default;
+  virtual RenderableObject* CreateRenderableObject(
+      const std::uint32_t width, const std::uint32_t height) const = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_RENDERABLE_OBJECT_FACTORY_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/renderableobject.h b/src/mixer/include_internal/mixer/interfaces/renderableobject.h
new file mode 100644 (file)
index 0000000..ca3556c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_RENDERABLE_OBJECT_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_RENDERABLE_OBJECT_H__
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "mixer/interfaces/videoplanemanipulator.h"
+#include "mixer/types/buffertype.h"
+#include "mixer/types/planecomponent.h"
+#include "mixer/types/videoplanemanipinfo.h"
+#include "esplusplayer/types/display.h"
+
+namespace esplusplayer {
+struct RenderableObject {
+  using Ptr = std::unique_ptr<RenderableObject>;
+  virtual ~RenderableObject() = default;
+  virtual bool IsValid() const = 0;
+  virtual std::uint32_t GetWidth() const = 0;
+  virtual std::uint32_t GetHeight() const = 0;
+  virtual std::uint32_t GetSize() const = 0;
+  virtual bool Render(const VideoPlaneManipulator* const vpmanip,
+                      const std::vector<VideoPlaneManipulableInfo>& planes,
+                      const Geometry& geom) = 0;
+  virtual bool Fill(const VideoPlaneColorManipulator* const vpmanip,
+                    const PlaneComponent& comp, const std::uint32_t& color,
+                    const Geometry& geom) = 0;
+  virtual bool Export(BufferKeyType& key) const = 0;
+};
+using RenderableObjectPtr = RenderableObject::Ptr;
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_RENDERABLE_OBJECT_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/videoplanecollection.h b/src/mixer/include_internal/mixer/interfaces/videoplanecollection.h
new file mode 100644 (file)
index 0000000..445f179
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COLLECTION_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COLLECTION_H__
+
+#include <vector>
+
+#include "mixer/types/videoplanemanipinfo.h"
+
+namespace esplusplayer {
+struct VideoPlaneCollection {
+  virtual ~VideoPlaneCollection() = default;
+  virtual const std::vector<VideoPlaneManipulableInfo> GetVideoPlaneManipInfo()
+      const = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COLLECTION_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/videoplanecolorfiller.h b/src/mixer/include_internal/mixer/interfaces/videoplanecolorfiller.h
new file mode 100644 (file)
index 0000000..c761927
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COLOR_FILLER_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COLOR_FILLER_H__
+
+#include <memory>
+
+#include "mixer/interfaces/videoplanemanipulator.h"
+#include "mixer/types/planecomponent.h"
+
+namespace esplusplayer {
+struct VideoPlaneColorFiller {
+  virtual ~VideoPlaneColorFiller() = default;
+  virtual const VideoPlaneColorManipulator* const GetColorFillManipulator()
+      const = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COLOR_FILLER_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/videoplanecopier.h b/src/mixer/include_internal/mixer/interfaces/videoplanecopier.h
new file mode 100644 (file)
index 0000000..a50d108
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COPIER_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COPIER_H__
+
+#include "mixer/interfaces/videoplanemanipulator.h"
+
+namespace esplusplayer {
+struct VideoPlaneCopier {
+  virtual ~VideoPlaneCopier() = default;
+  virtual const VideoPlaneManipulator* const GetCopyManipulator() const = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_COPIER_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/videoplanemanipulable.h b/src/mixer/include_internal/mixer/interfaces/videoplanemanipulable.h
new file mode 100644 (file)
index 0000000..351c8ee
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_MANIPULABLE_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_MANIPULABLE_H__
+
+#include "mixer/types/videoplanemanipinfo.h"
+#include "esplusplayer/types/display.h"
+
+namespace esplusplayer {
+
+struct VideoPlaneManipulable {
+  virtual ~VideoPlaneManipulable() = default;
+  virtual bool IsValid() const = 0;
+  virtual VideoPlaneManipulableInfo GetVideoPlaneManipulableInfo() const = 0;
+  virtual void SetCropArea(const CropArea& croparea) = 0;
+};
+
+}  // namespace esplusplayer
+
+#endif  //__ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_MANIPULABLE_H__
diff --git a/src/mixer/include_internal/mixer/interfaces/videoplanemanipulator.h b/src/mixer/include_internal/mixer/interfaces/videoplanemanipulator.h
new file mode 100644 (file)
index 0000000..d3b8d64
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_MANIPULATOR_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_MANIPULATOR_H__
+
+#include <cstdint>
+
+#include "mixer/types/planecomponent.h"
+#include "mixer/types/videoplanemanipinfo.h"
+
+namespace esplusplayer {
+
+template <typename T>
+struct VideoPlaneManipulatorWithType {
+  virtual bool Do(const T&, const VideoPlaneManipulableInfo&) const = 0;
+};
+
+using VideoPlaneManipulator =
+    VideoPlaneManipulatorWithType<VideoPlaneManipulableInfo>;
+
+using VideoPlaneColorManipulator = VideoPlaneManipulatorWithType<std::uint32_t>;
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_MANIPULATOR_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/interfaces/videoplanescaler.h b/src/mixer/include_internal/mixer/interfaces/videoplanescaler.h
new file mode 100644 (file)
index 0000000..b744c77
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_SCALER_H__
+#define __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_SCALER_H__
+
+#include "mixer/interfaces/videoplanemanipulator.h"
+
+namespace esplusplayer {
+struct VideoPlaneScaler {
+  virtual ~VideoPlaneScaler() = default;
+  virtual const VideoPlaneManipulator* const GetScaleManipulator() const = 0;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_INTERFACES_VIDEO_PLANE_SCALER_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/mixedframe.h b/src/mixer/include_internal/mixer/mixedframe.h
new file mode 100644 (file)
index 0000000..872865d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_MIXED_FRAME_H__
+#define __ESPLUSPLAYER_MIXER_MIXED_FRAME_H__
+
+#include <cstdint>
+#include <memory>
+
+#include "mixer/interfaces/memoryallocator.h"
+#include "mixer/interfaces/renderableobject.h"
+#include "mixer/interfaces/videoplanecollection.h"
+#include "mixer/interfaces/videoplanemanipulator.h"
+#include "esplusplayer/types/display.h"
+
+namespace esplusplayer {
+class MixedFrame : public VideoPlaneCollection, public RenderableObject {
+ public:
+  using Ptr = std::unique_ptr<MixedFrame>;
+  using BufferObjectPtr = std::unique_ptr<BufferObject>;
+
+ public:
+  static Ptr Create(const MemoryAllocator* const memop,
+                    const std::uint32_t width, const std::uint32_t height);
+
+ public:
+  explicit MixedFrame(const MemoryAllocator* const memop,
+                      const std::uint32_t width, const std::uint32_t height);
+  virtual ~MixedFrame() = default;
+
+ public:
+  virtual const std::vector<VideoPlaneManipulableInfo> GetVideoPlaneManipInfo()
+      const override;
+
+ public:
+  virtual bool IsValid() const override;
+  virtual std::uint32_t GetWidth() const override;
+  virtual std::uint32_t GetHeight() const override;
+  virtual std::uint32_t GetSize() const override;
+  virtual bool Render(const VideoPlaneManipulator* const vpmanip,
+                      const std::vector<VideoPlaneManipulableInfo>& planes,
+                      const Geometry& geom) override;
+  virtual bool Fill(const VideoPlaneColorManipulator* const vpmanip,
+                    const PlaneComponent& comp, const std::uint32_t& color,
+                    const Geometry& geom) override;
+  virtual bool Export(BufferKeyType& key) const override;
+
+ private:
+  std::uint32_t CalculateBufferSize_(const std::uint32_t width,
+                                     const std::uint32_t height);
+  VideoPlaneManipulableInfo GetMixedFrameVideoPlaneManipulableInfo_(
+      const PlaneComponent component, const Geometry& geom);
+  VideoPlaneManipulableInfo GetYComponentVMInfo_(BufferHandleType handle) const;
+  VideoPlaneManipulableInfo GetUVComponentVMInfo_(
+      BufferHandleType handle) const;
+
+ private:
+  const std::uint32_t width_ = 0;
+  const std::uint32_t height_ = 0;
+  mutable std::uint32_t allocated_size_ = 0;
+  BufferObjectPtr buffer_ = nullptr;
+};
+using MixedFramePtr = MixedFrame::Ptr;
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_MIXED_FRAME_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/renderer.h b/src/mixer/include_internal/mixer/renderer.h
new file mode 100644 (file)
index 0000000..9e692ea
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_RENDERER_H__
+#define __ESPLUSPLAYER_MIXER_RENDERER_H__
+
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include "mixer/interfaces/renderableobj_factory.h"
+#include "mixer/interfaces/videoplanecollection.h"
+#include "mixer/interfaces/videoplanecolorfiller.h"
+#include "mixer/interfaces/videoplanescaler.h"
+#include "mixer/mixer.h"
+#include "mixer/types/buffertype.h"
+#include "mixer/types/videoplanemoveinfo.h"
+
+namespace esplusplayer {
+
+struct RendererEventListener {
+  virtual bool OnRenderingRelease(const BufferKeyType&) = 0;
+};
+
+class Renderer {
+ private:
+  using JitterType = std::chrono::duration<std::int64_t, std::milli>;
+
+ public:
+  explicit Renderer(const RenderableObjectFactory& mf_factory,
+                    const Mixer::ResolutionInfo& rinfo,
+                    RendererEventListener* listener);
+  virtual ~Renderer();
+
+ public:
+  bool IsValid() const;
+  bool Start();
+  bool Stop();
+  bool ChangeResolution(const RenderableObjectFactory& mf_factory,
+                        const std::uint32_t& width,
+                        const std::uint32_t& height);
+  bool ChangeRenderingSpeed(const std::uint32_t framerate_num,
+                            const std::uint32_t framerate_den);
+
+  bool Render(const VideoPlaneScaler* const scaler,
+              const VideoPlaneCollection* const planes, const Geometry& geom);
+  bool Mute(const VideoPlaneColorFiller* const filler, const Geometry& geom);
+  bool Move(const VideoPlaneColorFiller* const filler,
+            const std::vector<VideoPlaneMoveInfo>& moving_planes);
+
+ protected:
+  virtual bool ChangeResolutionInternal_(
+      const RenderableObjectFactory& mf_factory, const std::uint32_t& width,
+      const std::uint32_t& height);
+  virtual bool RenderInternal_(
+      const VideoPlaneManipulator* const vpmanip,
+      const std::vector<VideoPlaneManipulableInfo>& planes,
+      const Geometry& geom);
+  virtual bool MuteInternal_(const VideoPlaneColorManipulator* const filler,
+                             const Geometry& geom);
+  virtual bool MoveInternal_(
+      const VideoPlaneColorManipulator* const filler,
+      const std::vector<VideoPlaneMoveInfo>& moving_planes);
+  virtual bool OnRenderingBefore_(const RenderableObject* const frame);
+  virtual bool IsValid_() const;
+
+  std::uint32_t GetNextRenderingTimeWithJitter_(const JitterType& jitter) const;
+  const Mixer::ResolutionInfo& GetResolutionInfo_() const;
+  RenderableObjectPtr& GetMixedFrame_();
+  void AcquireRenderingLock_();
+  void ReleaseRenderingLock_();
+
+ private:
+  bool RaiseOnRenderingReleaseEvent_(const BufferKeyType& key);
+  void RenderingWorker_();
+
+ protected:
+  static Geometry MakeGeometry_(const std::uint32_t& width,
+                                const std::uint32_t& height);
+  static bool IsSameGeometry_(const Geometry& g1, const Geometry& g2);
+
+ private:
+  Mixer::ResolutionInfo resolution_info_;
+  RendererEventListener* listener_ = nullptr;
+  RenderableObjectPtr frame_ = nullptr;
+
+  bool rendering_flag_ = false;
+  std::mutex rendering_mtx_;
+  std::condition_variable rendering_cv_;
+  std::thread rendering_worker_;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_RENDERER_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/rendererwithdoublebuf.h b/src/mixer/include_internal/mixer/rendererwithdoublebuf.h
new file mode 100644 (file)
index 0000000..fbf2832
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_RENDERER_WITH_DOUBLE_BUFFERING_H__
+#define __ESPLUSPLAYER_MIXER_RENDERER_WITH_DOUBLE_BUFFERING_H__
+
+#include <boost/scope_exit.hpp>
+#include <chrono>
+#include <cinttypes>
+
+#include "core/utils/plusplayer_log.h"
+#include "mixer/interfaces/videoplanecopier.h"
+#include "mixer/interfaces/videoplanescaler.h"
+#include "mixer/mixedframe.h"
+#include "mixer/renderer.h"
+
+namespace esplusplayer {
+
+class RendererWithDoubleBuffer : public Renderer {
+ public:
+  explicit RendererWithDoubleBuffer(const RenderableObjectFactory& mf_factory,
+                                    const VideoPlaneCopier* const vpcopier,
+                                    const VideoPlaneScaler* const vpscaler,
+                                    const Mixer::ResolutionInfo& rinfo,
+                                    RendererEventListener* listener)
+      : Renderer(mf_factory, rinfo, listener),
+        frame_(MixedFramePtr(dynamic_cast<MixedFrame*>(
+            mf_factory.CreateRenderableObject(rinfo.width, rinfo.height)))),
+        vpcopier_(vpcopier),
+        vpscaler_(vpscaler) {}
+  virtual ~RendererWithDoubleBuffer() = default;
+
+ protected:
+  virtual bool OnRenderingBefore_(
+      const RenderableObject* const frame) override {
+    // auto before = std::chrono::system_clock::now();
+    std::unique_lock<std::mutex> lk(rendering_mtx_);
+    if (IsValid() == false) return false;
+    // LOG_INFO("[PERF] OnRenderingBefore_ Lock [%llu]ms",
+    //          std::chrono::duration_cast<std::chrono::milliseconds>(
+    //              std::chrono::system_clock::now() - before)
+    //              .count());
+    const auto& rinfo = GetResolutionInfo_();
+    auto ret = GetMixedFrame_()->Render(
+        vpcopier_->GetCopyManipulator(), frame_->GetVideoPlaneManipInfo(),
+        MakeGeometry_(rinfo.width, rinfo.height));
+    // LOG_INFO("[PERF] Copy [%llu]ms",
+    //          std::chrono::duration_cast<std::chrono::milliseconds>(
+    //              std::chrono::system_clock::now() - before)
+    //              .count());
+    return ret;
+  }
+
+  // LCOV_EXCL_START
+  virtual bool ChangeResolutionInternal_(
+      const RenderableObjectFactory& mf_factory, const std::uint32_t& width,
+      const std::uint32_t& height) override {
+    {
+      std::unique_lock<std::mutex> lk(rendering_mtx_);
+      frame_.reset(nullptr);
+      frame_ = MixedFramePtr(dynamic_cast<MixedFrame*>(
+          mf_factory.CreateRenderableObject(width, height)));
+    }
+    return Renderer::ChangeResolutionInternal_(mf_factory, width, height);
+  }
+
+  virtual bool RenderInternal_(
+      const VideoPlaneManipulator* const scaler,
+      const std::vector<VideoPlaneManipulableInfo>& planes,
+      const Geometry& geom) override {
+    if (scaler == nullptr) return false;
+    auto before = std::chrono::system_clock::now();
+    std::unique_lock<std::mutex> lk(rendering_mtx_);
+    if (IsValid() == false) return false;
+    auto ret = frame_->Render(scaler, planes, geom);
+    LOG_INFO("[PERF] Scale [%" PRIu64"]ms",
+             std::chrono::duration_cast<std::chrono::milliseconds>(
+                 std::chrono::system_clock::now() - before)
+                 .count());
+    return ret;
+  }
+
+  virtual bool MuteInternal_(const VideoPlaneColorManipulator* const filler,
+                             const Geometry& geom) override {
+    if (filler == nullptr) return false;
+    std::unique_lock<std::mutex> lk(rendering_mtx_);
+    if (IsValid() == false) return false;
+    bool ret = true;
+    LOG_INFO("MUTE REGION (%d, %d, %d x %d)", geom.x, geom.y, geom.w, geom.h);
+    ret &= frame_->Fill(filler, PlaneComponent::kYComponent, 0x00, geom);
+    ret &= frame_->Fill(filler, PlaneComponent::kUVComponent, 0x8080, geom);
+    return ret;
+  }
+
+  virtual bool MoveInternal_(
+      const VideoPlaneColorManipulator* const filler,
+      const std::vector<VideoPlaneMoveInfo>& moving_planes) override {
+    if (filler == nullptr) return false;
+
+    AcquireRenderingLock_();
+    BOOST_SCOPE_EXIT(this_) { this_->ReleaseRenderingLock_(); }
+    BOOST_SCOPE_EXIT_END
+
+    std::unique_lock<std::mutex> lk(rendering_mtx_);
+    if (IsValid() == false) return false;
+
+    auto* mixedframe = dynamic_cast<MixedFrame*>(GetMixedFrame_().get());
+    if (mixedframe == nullptr) return false;
+
+    const auto planes = mixedframe->GetVideoPlaneManipInfo();
+    if (planes.size() != 2) return false;
+
+    const auto& rinfo = GetResolutionInfo_();
+
+    auto fullgeom = MakeGeometry_(rinfo.width, rinfo.height);
+    bool ret = true;
+    ret &= frame_->Fill(filler, PlaneComponent::kYComponent, 0x00, fullgeom);
+    ret &= frame_->Fill(filler, PlaneComponent::kUVComponent, 0x8080, fullgeom);
+    auto* scaler = vpscaler_->GetScaleManipulator();
+    for (const auto& move : moving_planes) {
+      VideoPlaneManipulableInfo y_manipinfo = planes[0];
+      VideoPlaneManipulableInfo uv_manipinfo = planes[1];
+      y_manipinfo.rect = move.cur;
+      uv_manipinfo.rect = move.cur;
+      uv_manipinfo.rect.x /= 2;
+      uv_manipinfo.rect.y /= 2;
+      uv_manipinfo.rect.w /= 2;
+      uv_manipinfo.rect.h /= 2;
+      uv_manipinfo.rect.y += rinfo.height;
+      LOG_INFO("MOVE (%d, %d, %d x %d) -> (%d, %d, %d x %d)", move.cur.x,
+               move.cur.y, move.cur.w, move.cur.h, move.target.x, move.target.y,
+               move.target.w, move.target.h);
+      ret &= frame_->Render(scaler, {y_manipinfo, uv_manipinfo}, move.target);
+    }
+    return true;
+  };
+  // LCOV_EXCL_STOP
+
+  virtual bool IsValid_() const override {
+    if (frame_ == nullptr) return false;
+    if (frame_->IsValid() == false) return false;
+    if (vpcopier_ == nullptr || vpscaler_ == nullptr) return false;
+    if (vpcopier_->GetCopyManipulator() == nullptr) return false;
+    if (vpscaler_->GetScaleManipulator() == nullptr) return false;
+    return true;
+  }
+
+ private:
+  MixedFramePtr frame_ = nullptr;
+  const VideoPlaneCopier* const vpcopier_ = nullptr;
+  const VideoPlaneScaler* const vpscaler_ = nullptr;
+
+  std::mutex rendering_mtx_;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_RENDERER_WITH_DOUBLE_BUFFERING_H__
diff --git a/src/mixer/include_internal/mixer/sys/tbminterface.h b/src/mixer/include_internal/mixer/sys/tbminterface.h
new file mode 100644 (file)
index 0000000..f59b4be
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_SYS_TBM_INTERFACE_H__
+#define __ESPLUSPLAYER_MIXER_SYS_TBM_INTERFACE_H__
+
+#include <capi-graphics-control.h>
+
+#include "mixer/types/buffertype.h"
+
+namespace esplusplayer {
+namespace tizen {
+class TBMInterface {
+ public:
+  static BufferDefaultType BoRef(BufferDefaultType bo);
+  static void BoUnRef(BufferDefaultType bo);
+  static int BoSize(BufferDefaultType bo);
+  static BufferUnionHandleType BoGetHandle(BufferDefaultType bo, int device);
+  static BufferUnionHandleType BoMap(BufferDefaultType bo, int device,
+                                     int option);
+  static void BoUnmap(BufferDefaultType bo);
+  static BufferKeyType BoExport(BufferDefaultType bo);
+  static BufferDefaultType BoAlloc(tbm_bufmgr bufmgr, int size, int flag);
+  static BufferDefaultType BoImport(tbm_bufmgr bufmgr, BufferKeyType key);
+  static int GAScale(tbm_bufmgr bufmgr, GraphicsGAScaleInfo* info);
+  static int GACopy(tbm_bufmgr bufmgr, GraphicsGABltRopInfo* info);
+  static int GAFill(tbm_bufmgr bufmgr, GraphicsGAFillRectInfo* info);
+};
+}  // namespace tizen
+}  // namespace esplusplayer
+
+#endif  //__ESPLUSPLAYER_MIXER_SYS_TBM_INTERFACE_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenaccessiblebufferobj.h b/src/mixer/include_internal/mixer/tizen/tizenaccessiblebufferobj.h
new file mode 100644 (file)
index 0000000..7c31eeb
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_ACCESSIBLE_BUFFER_OBJECT_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_ACCESSIBLE_BUFFER_OBJECT_H__
+
+#include "mixer/interfaces/accessiblebuffer.h"
+#include "mixer/tizen/tizenbufferobj.h"
+#include "mixer/tizen/tizenbufferphyaddraccessor.h"
+
+namespace esplusplayer {
+class TizenAccessibleBufferObject : public TizenBufferObject,
+                                    public AccessibleBuffer {
+ public:
+  explicit TizenAccessibleBufferObject(BufferDefaultType buffer);
+  virtual ~TizenAccessibleBufferObject() = default;
+  virtual PhyAddrAccessorPtr GetReadableAddress() const override;
+  virtual PhyAddrAccessorPtr GetWritableAddress() const override;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_ACCESSIBLE_BUFFER_OBJECT_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenbufferkeyvideoframe.h b/src/mixer/include_internal/mixer/tizen/tizenbufferkeyvideoframe.h
new file mode 100644 (file)
index 0000000..51312bc
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_KEY_VIDEO_SURFACE_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_KEY_VIDEO_SURFACE_H__
+
+#include <memory>
+
+#include "mixer/abs_videoframe.h"
+#include "mixer/interfaces/bufferobject.h"
+#include "mixer/tizen/tizenbuffermgr.h"
+#include "mixer/videoplane.h"
+// LCOV_EXCL_START
+namespace esplusplayer {
+
+class TizenBufferKeyVideoFrame : public AbstractVideoFrame {
+ public:
+  using BufferObjectPtr = std::shared_ptr<BufferObject>;
+
+ public:
+  explicit TizenBufferKeyVideoFrame(const TizenBufferManager* const bufmgr,
+                                    const BufferKeyType& key,
+                                    const std::uint32_t& width,
+                                    const std::uint32_t& height);
+  virtual ~TizenBufferKeyVideoFrame() = default;
+
+ protected:
+  virtual bool IsValid_() const override;
+  virtual const std::uint32_t GetWidth_() const override;
+  virtual const std::uint32_t GetHeight_() const override;
+
+ private:
+  const BufferKeyType key_;
+  const std::uint32_t width_;
+  const std::uint32_t height_;
+};
+}  // namespace esplusplayer
+// LCOV_EXCL_STOP
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_KEY_VIDEO_SURFACE_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenbuffermgr.h b/src/mixer/include_internal/mixer/tizen/tizenbuffermgr.h
new file mode 100644 (file)
index 0000000..99edef6
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_MANAGER_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_MANAGER_H__
+
+#include <cstring>
+
+#include "mixer/interfaces/memoryallocator.h"
+#include "mixer/interfaces/videoplanecolorfiller.h"
+#include "mixer/interfaces/videoplanecopier.h"
+#include "mixer/interfaces/videoplanemanipulator.h"
+#include "mixer/interfaces/videoplanescaler.h"
+#include "mixer/sys/tbminterface.h"
+#include "mixer/tizen/tizenaccessiblebufferobj.h"
+#include "mixer/types/videoplanemanipinfo.h"
+
+namespace {
+struct GlobalInstance {
+  tbm_bufmgr bufmgr;
+  GlobalInstance() { bufmgr = tbm_bufmgr_init(-1); }
+  ~GlobalInstance() {
+    if (bufmgr) tbm_bufmgr_deinit(bufmgr);
+  }
+};
+static const GlobalInstance kGlobalInstance;
+}  // namespace
+
+namespace esplusplayer {
+template <typename TBM>
+class BufferManagerWithType : public MemoryAllocator,
+                              public VideoPlaneScaler,
+                              public VideoPlaneCopier,
+                              public VideoPlaneColorFiller {
+ public:
+  class Scaler : public VideoPlaneManipulator {
+   public:
+    explicit Scaler(const BufferManagerWithType* const bufmgr);
+    virtual ~Scaler() = default;
+    virtual bool Do(const VideoPlaneManipulableInfo& src,
+                    const VideoPlaneManipulableInfo& dest) const override;
+
+   private:
+    const BufferManagerWithType* const bufmgr_;
+  };
+  class Copier : public VideoPlaneManipulator {
+   public:
+    explicit Copier(const BufferManagerWithType* const bufmgr);
+    virtual ~Copier() = default;
+    virtual bool Do(const VideoPlaneManipulableInfo& src,
+                    const VideoPlaneManipulableInfo& dest) const override;
+
+   private:
+    const BufferManagerWithType* const bufmgr_;
+  };
+  class ColorFiller : public VideoPlaneColorManipulator {
+   public:
+    explicit ColorFiller(const BufferManagerWithType* const bufmgr);
+    virtual ~ColorFiller() = default;
+    virtual bool Do(const std::uint32_t& color,
+                    const VideoPlaneManipulableInfo& dest) const override;
+
+   private:
+    const BufferManagerWithType* const bufmgr_;
+  };
+
+ public:
+  explicit BufferManagerWithType();
+  virtual ~BufferManagerWithType() = default;
+
+ public:
+  virtual BufferObject* Allocate(const std::uint32_t& size) const override;
+  virtual const VideoPlaneManipulator* const GetScaleManipulator()
+      const override;
+  virtual const VideoPlaneManipulator* const GetCopyManipulator()
+      const override;
+  virtual const VideoPlaneColorManipulator* const GetColorFillManipulator()
+      const override;
+  bool IsValid() const;
+  BufferObject* Import(BufferHandleType handle) const;
+
+ protected:
+  bool Copy_(const VideoPlaneManipulableInfo& src,
+             const VideoPlaneManipulableInfo& dst) const;
+  bool Scale_(const VideoPlaneManipulableInfo& src,
+              const VideoPlaneManipulableInfo& dst) const;
+  bool Fill_(const std::uint32_t color,
+             const VideoPlaneManipulableInfo& dst) const;
+
+ private:
+  tbm_bufmgr bufmgr_;
+  Scaler scaler_;
+  Copier copier_;
+  ColorFiller color_filler_;
+};
+
+using TizenBufferManager = BufferManagerWithType<tizen::TBMInterface>;
+
+/******************************************************************************
+ * Body
+ */
+template <typename TBM>
+BufferManagerWithType<TBM>::BufferManagerWithType()
+    : scaler_(this), copier_(this), color_filler_(this) {
+  bufmgr_ = ::kGlobalInstance.bufmgr;
+}
+
+template <typename TBM>
+BufferObject* BufferManagerWithType<TBM>::Allocate(
+    const std::uint32_t& size) const {
+  if (size == 0) return nullptr;
+  if (IsValid() == false) return nullptr;
+  auto buffer = TBM::BoAlloc(bufmgr_, size, TBM_BO_SCANOUT | (1 << 17));
+  if (buffer == nullptr) return nullptr;
+  auto bufferobj = new TizenAccessibleBufferObject(buffer);
+  TBM::BoUnRef(buffer);
+  return bufferobj;
+}
+
+template <typename TBM>
+const VideoPlaneManipulator* const
+BufferManagerWithType<TBM>::GetScaleManipulator() const {
+  return &scaler_;
+}
+
+template <typename TBM>
+const VideoPlaneManipulator* const
+BufferManagerWithType<TBM>::GetCopyManipulator() const {
+  return &copier_;
+}
+
+template <typename TBM>
+const VideoPlaneColorManipulator* const
+BufferManagerWithType<TBM>::GetColorFillManipulator() const {
+  return &color_filler_;
+}
+
+template <typename TBM>
+bool BufferManagerWithType<TBM>::IsValid() const {
+  if (bufmgr_ == nullptr) return false;
+  return true;
+}
+
+template <typename TBM>
+BufferObject* BufferManagerWithType<TBM>::Import(
+    BufferHandleType handle) const {
+  if (IsValid() == false) return nullptr;
+  auto buffer = TBM::BoImport(bufmgr_, handle);
+  if (buffer == nullptr) return nullptr;
+  auto bufferobj = new TizenBufferObject(buffer);
+  TBM::BoUnRef(buffer);
+  return bufferobj;
+}
+
+template <typename TBM>
+bool BufferManagerWithType<TBM>::Copy_(
+    const VideoPlaneManipulableInfo& src,
+    const VideoPlaneManipulableInfo& dst) const {
+  if (src.component != dst.component) return false;
+  if (IsValid() == false) return false;
+  GraphicsGABltRopInfo info;
+  std::memset(&info, 0, sizeof(GraphicsGABltRopInfo));
+  info.ga_mode = GRAPHICS_GA_BITBLT_MODE_NORMAL;
+  info.rop_mode = GRAPHICS_GA_ROP_COPY;
+  info.ga_op_type = GRAPHICS_GA_COPY;
+  info.pre_alphamode = 0;
+  info.ca_value = 0;
+  info.color_format =
+      (src.component == PlaneComponent::kYComponent ? GRAPHICS_GA_FORMAT_8BPP
+                                                    : GRAPHICS_GA_FORMAT_16BPP);
+
+  info.src_handle = src.handle;
+  info.src_hbytesize = src.linesize;
+  info.src_rect.x = src.rect.x;
+  info.src_rect.y = src.rect.y;
+  info.src_rect.w = src.rect.w;
+  info.src_rect.h = src.rect.h;
+
+  info.dst_handle = dst.handle;
+  info.dst_hbytesize = dst.linesize;
+  info.dst_rect.x = dst.rect.x;
+  info.dst_rect.y = dst.rect.y;
+  info.dst_rect.w = dst.rect.w;
+  info.dst_rect.h = dst.rect.h;
+
+  return TBM::GACopy(bufmgr_, &info) > 0;
+}
+
+// LCOV_EXCL_START
+template <typename TBM>
+bool BufferManagerWithType<TBM>::Scale_(
+    const VideoPlaneManipulableInfo& src,
+    const VideoPlaneManipulableInfo& dst) const {
+  if (src.component != dst.component) return false;
+  if (IsValid() == false) return false;
+  GraphicsGAScaleInfo info;
+  std::memset(&info, 0, sizeof(GraphicsGAScaleInfo));
+  info.ga_mode = GRAPHICS_GA_SCALE_MODE;
+  info.rop_mode = GRAPHICS_GA_ROP_COPY;
+  info.ga_op_type = GRAPHICS_GA_SCALE;
+  info.pre_alphamode = 0;
+  info.ca_value = 0;
+  info.rop_on_off = 0;
+  info.color_format =
+      (src.component == PlaneComponent::kYComponent ? GRAPHICS_GA_FORMAT_8BPP
+                                                    : GRAPHICS_GA_FORMAT_16BPP);
+
+  info.src_handle = src.handle;
+  info.src_hbytesize = src.linesize;
+  info.src_rect.x = src.rect.x;
+  info.src_rect.y = src.rect.y;
+  info.src_rect.w = src.rect.w;
+  info.src_rect.h = src.rect.h;
+
+  info.dst_handle = dst.handle;
+  info.dst_hbytesize = dst.linesize;
+  info.dst_rect.x = dst.rect.x;
+  info.dst_rect.y = dst.rect.y;
+  info.dst_rect.w = dst.rect.w;
+  info.dst_rect.h = dst.rect.h;
+
+  return TBM::GAScale(bufmgr_, &info) > 0;
+}
+
+template <typename TBM>
+bool BufferManagerWithType<TBM>::Fill_(
+    const std::uint32_t color, const VideoPlaneManipulableInfo& dst) const {
+  if (IsValid() == false) return false;
+  GraphicsGAFillRectInfo info;
+  std::memset(&info, 0, sizeof(GraphicsGAFillRectInfo));
+  info.color_format =
+      (dst.component == PlaneComponent::kYComponent ? GRAPHICS_GA_FORMAT_8BPP
+                                                    : GRAPHICS_GA_FORMAT_16BPP);
+  info.ga_op_type = GRAPHICS_GA_SOLID_FILL;
+  info.color = color;
+
+  info.handle = dst.handle;
+  info.hbytesize = dst.linesize;
+  info.rect.x = dst.rect.x;
+  info.rect.y = dst.rect.y;
+  info.rect.w = dst.rect.w;
+  info.rect.h = dst.rect.h;
+
+  return TBM::GAFill(bufmgr_, &info) > 0;
+}
+// LCOV_EXCL_STOP
+
+/******************************************************************************
+ * Body for scaler
+ */
+template <typename TBM>
+BufferManagerWithType<TBM>::Scaler::Scaler(
+    const BufferManagerWithType* const bufmgr)
+    : bufmgr_(bufmgr) {}
+
+template <typename TBM>
+bool BufferManagerWithType<TBM>::Scaler::Do(
+    const VideoPlaneManipulableInfo& src,
+    const VideoPlaneManipulableInfo& dest) const {
+  return bufmgr_->Scale_(src, dest);
+}
+
+/******************************************************************************
+ * Body for copier
+ */
+template <typename TBM>
+BufferManagerWithType<TBM>::Copier::Copier(
+    const BufferManagerWithType* const bufmgr)
+    : bufmgr_(bufmgr) {}
+
+template <typename TBM>
+bool BufferManagerWithType<TBM>::Copier::Do(
+    const VideoPlaneManipulableInfo& src,
+    const VideoPlaneManipulableInfo& dest) const {
+  return bufmgr_->Copy_(src, dest);
+}
+
+/******************************************************************************
+ * Body for color filler
+ */
+template <typename TBM>
+BufferManagerWithType<TBM>::ColorFiller::ColorFiller(
+    const BufferManagerWithType* const bufmgr)
+    : bufmgr_(bufmgr) {}
+
+template <typename TBM>
+bool BufferManagerWithType<TBM>::ColorFiller::Do(
+    const std::uint32_t& color, const VideoPlaneManipulableInfo& dest) const {
+  return bufmgr_->Fill_(color, dest);
+}
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_MANAGER_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenbufferobj.h b/src/mixer/include_internal/mixer/tizen/tizenbufferobj.h
new file mode 100644 (file)
index 0000000..73877b6
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_BUFFER_OBJECT_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_BUFFER_OBJECT_H__
+
+#include "mixer/interfaces/bufferobject.h"
+#include "mixer/sys/tbminterface.h"
+
+namespace esplusplayer {
+template <typename TBM>
+class BufferObjectWithType : public BufferObject {
+ public:
+  explicit BufferObjectWithType(BufferDefaultType buffer);
+  virtual ~BufferObjectWithType();
+  bool IsValid() const;
+  virtual BufferHandleType GetBufferHandle() const override;
+  virtual BufferKeyType Export() const override;
+  virtual std::uint32_t GetSize() const override;
+
+ protected:
+  const BufferDefaultType& GetBuffer_() const;
+
+ private:
+  BufferDefaultType buffer_ = nullptr;
+};
+
+using TizenBufferObject = BufferObjectWithType<esplusplayer::tizen::TBMInterface>;
+
+/******************************************************************************
+ * Body
+ */
+template <typename TBM>
+BufferObjectWithType<TBM>::BufferObjectWithType(BufferDefaultType buffer) {
+  if (buffer == nullptr) return;
+  buffer_ = TBM::BoRef(buffer);
+}
+
+template <typename TBM>
+BufferObjectWithType<TBM>::~BufferObjectWithType() {
+  if (buffer_) TBM::BoUnRef(buffer_);
+}
+
+template <typename TBM>
+bool BufferObjectWithType<TBM>::IsValid() const {
+  if (buffer_ == nullptr) return false;
+  return true;
+}
+
+template <typename TBM>
+BufferHandleType BufferObjectWithType<TBM>::GetBufferHandle() const {
+  if (IsValid() == false) return kInvalidBufferHandle;
+  auto handle = TBM::BoGetHandle(buffer_, TBM_DEVICE_2D);
+  return handle.u32;
+}
+
+template <typename TBM>
+BufferKeyType BufferObjectWithType<TBM>::Export() const {
+  if (IsValid() == false) return kInvalidBufferKey;
+  return TBM::BoExport(buffer_);
+}
+
+template <typename TBM>
+std::uint32_t BufferObjectWithType<TBM>::GetSize() const {
+  if (IsValid() == false) return kInvalidBufferSize;
+  return TBM::BoSize(buffer_);
+}
+
+template <typename TBM>
+const BufferDefaultType& BufferObjectWithType<TBM>::GetBuffer_() const {
+  return buffer_;
+}
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_BUFFER_OBJECT_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenbufferphyaddraccessor.h b/src/mixer/include_internal/mixer/tizen/tizenbufferphyaddraccessor.h
new file mode 100644 (file)
index 0000000..c066fdf
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_PHYSICAL_ADDRESS_ACCESOR_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_PHYSICAL_ADDRESS_ACCESOR_H__
+
+#include <tbm_bo.h>
+
+#include "mixer/interfaces/phyaddraccessor.h"
+
+namespace esplusplayer {
+class AbstractTizenBufferPhyAddrAccessor : public PhysicalAddressAccessor {
+ public:
+  explicit AbstractTizenBufferPhyAddrAccessor(BufferDefaultType buffer) {
+    if (buffer == nullptr) return;
+    buffer_ = tbm_bo_ref(buffer);
+  }
+
+  virtual ~AbstractTizenBufferPhyAddrAccessor() {
+    if (buffer_ == nullptr) return;
+    if (handle_ != nullptr) tbm_bo_unmap(buffer_);
+    tbm_bo_unref(buffer_);
+  }
+
+ public:
+  virtual BufferPhysicalAddrType GetAddress() override {
+    if (handle_ != nullptr) return handle_;
+    handle_ = GetAddress_(buffer_);
+    return handle_;
+  }
+
+ protected:
+  virtual BufferPhysicalAddrType GetAddress_(
+      const BufferDefaultType& buffer) = 0;
+
+ private:
+  BufferDefaultType buffer_;
+  BufferPhysicalAddrType handle_ = nullptr;
+};
+
+class TizenReadableBufferPhyAddrAccessor
+    : public AbstractTizenBufferPhyAddrAccessor {
+ public:
+  explicit TizenReadableBufferPhyAddrAccessor(const BufferDefaultType buffer)
+      : AbstractTizenBufferPhyAddrAccessor(buffer) {}
+  virtual ~TizenReadableBufferPhyAddrAccessor() = default;
+
+ protected:
+  virtual BufferPhysicalAddrType GetAddress_(
+      const BufferDefaultType& buffer) override {
+    auto handle = tbm_bo_map(buffer, TBM_DEVICE_CPU, TBM_OPTION_READ);
+    return handle.ptr;
+  }
+};
+
+class TizenWritableBufferPhyAddrAccessor
+    : public AbstractTizenBufferPhyAddrAccessor {
+ public:
+  explicit TizenWritableBufferPhyAddrAccessor(BufferDefaultType buffer)
+      : AbstractTizenBufferPhyAddrAccessor(buffer) {}
+  virtual ~TizenWritableBufferPhyAddrAccessor() = default;
+
+ protected:
+  virtual BufferPhysicalAddrType GetAddress_(
+      const BufferDefaultType& buffer) override {
+    auto handle = tbm_bo_map(buffer, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+    return handle.ptr;
+  }
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_BUFFER_PHYSICAL_ADDRESS_ACCESOR_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizendefaultphyaddraccessor.h b/src/mixer/include_internal/mixer/tizen/tizendefaultphyaddraccessor.h
new file mode 100644 (file)
index 0000000..ae42ca2
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_DEFAULT_PHYSICAL_ADDRESS_ACCESOR_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_DEFAULT_PHYSICAL_ADDRESS_ACCESOR_H__
+
+#include "mixer/interfaces/phyaddraccessor.h"
+// LCOV_EXCL_START
+namespace esplusplayer {
+class TizenDefaultPhyAddrAccessor : public PhysicalAddressAccessor {
+ public:
+  explicit TizenDefaultPhyAddrAccessor(std::uint32_t viraddr);
+  virtual ~TizenDefaultPhyAddrAccessor() = default;
+
+ public:
+  virtual BufferPhysicalAddrType GetAddress() override;
+
+ private:
+  std::uint32_t viraddr_;
+};
+}  // namespace esplusplayer
+// LCOV_EXCL_STOP
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_DEFAULT_PHYSICAL_ADDRESS_ACCESOR_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenhwbufferobj.h b/src/mixer/include_internal/mixer/tizen/tizenhwbufferobj.h
new file mode 100644 (file)
index 0000000..e3e3e99
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_HW_BUFFER_OBJECT_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_HW_BUFFER_OBJECT_H__
+
+#include "mixer/decodedvideoinfo.h"
+#include "mixer/interfaces/bufferobject.h"
+
+namespace esplusplayer {
+class TizenHWBufferObject : public BufferObject {
+ public:
+  explicit TizenHWBufferObject(const std::uint32_t& width,
+                               const std::uint32_t& height,
+                               const DecodedRawPlaneInfo& info);
+  virtual ~TizenHWBufferObject() = default;
+
+  bool IsValid() const;
+  virtual BufferHandleType GetBufferHandle() const override;
+  virtual BufferKeyType Export() const override;
+  virtual std::uint32_t GetSize() const override;
+
+ private:
+  std::uint32_t width_;
+  std::uint32_t height_;
+  DecodedRawPlaneInfo info_;
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_TIZEN_HW_BUFFER_OBJECT_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenhwvideoframe.h b/src/mixer/include_internal/mixer/tizen/tizenhwvideoframe.h
new file mode 100644 (file)
index 0000000..737521d
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_HW_VIDEO_FRAME_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_HW_VIDEO_FRAME_H__
+
+#include <memory>
+
+#include "mixer/abs_videoframe.h"
+#include "mixer/decodedvideoinfo.h"
+#include "mixer/interfaces/bufferobject.h"
+// LCOV_EXCL_START
+namespace esplusplayer {
+class TizenHWVideoFrame : public AbstractVideoFrame {
+ public:
+  using BufferObjectPtr = std::unique_ptr<BufferObject>;
+
+ public:
+  explicit TizenHWVideoFrame(const DecodedRawInfo& info);
+  virtual ~TizenHWVideoFrame() = default;
+
+ protected:
+  virtual bool IsValid_() const override;
+  virtual const std::uint32_t GetWidth_() const override;
+  virtual const std::uint32_t GetHeight_() const override;
+
+ private:
+  void PrintDecodedRawInfo() const;
+
+ private:
+  DecodedRawInfo info_;
+};
+}  // namespace esplusplayer
+// LCOV_EXCL_STOP
+#endif  //__ESPLUSPLAYER_MIXER_TIZEN_HW_VIDEO_FRAME_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizenrenderableobj_factory.h b/src/mixer/include_internal/mixer/tizen/tizenrenderableobj_factory.h
new file mode 100644 (file)
index 0000000..4775ae1
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_RENDERABLE_OBJECT_FACTORY_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_RENDERABLE_OBJECT_FACTORY_H__
+
+#include <memory>
+
+#include "mixer/interfaces/memoryallocator.h"
+#include "mixer/interfaces/renderableobj_factory.h"
+// LCOV_EXCL_START
+namespace esplusplayer {
+class TizenRenderableObjectFactory : public RenderableObjectFactory {
+ public:
+  explicit TizenRenderableObjectFactory(
+      const MemoryAllocator* const memallocator);
+  virtual ~TizenRenderableObjectFactory() = default;
+
+ public:
+  virtual RenderableObject* CreateRenderableObject(
+      const std::uint32_t width, const std::uint32_t height) const override;
+
+ private:
+  const MemoryAllocator* const memallocator_;
+};
+}  // namespace esplusplayer
+// LCOV_EXCL_STOP
+#endif  // __ESPLUSPLAYER_MIXER_TIZEN_RENDERABLE_OBJECT_FACTORY_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/tizen/tizensurfacevideoframe.h b/src/mixer/include_internal/mixer/tizen/tizensurfacevideoframe.h
new file mode 100644 (file)
index 0000000..1512fb7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_TIZEN_SURFACE_VIDEO_FRAME_H__
+#define __ESPLUSPLAYER_MIXER_TIZEN_SURFACE_VIDEO_FRAME_H__
+
+#include <memory>
+
+#include "mixer/abs_videoframe.h"
+#include "mixer/interfaces/bufferobject.h"
+#include "esplusplayer/decodedvideopacketex.h"
+// LCOV_EXCL_START
+namespace esplusplayer {
+class TizenSurfaceVideoFrame : public AbstractVideoFrame {
+ private:
+  enum ComponentIndex { kYIndex = 0, kUVIndex = 1 };
+
+ public:
+  using BufferObjectPtr = std::unique_ptr<BufferObject>;
+
+ public:
+  explicit TizenSurfaceVideoFrame(DecodedVideoPacketExPtr dvp);
+  virtual ~TizenSurfaceVideoFrame() = default;
+
+ protected:
+  virtual bool IsValid_() const override;
+  virtual const std::uint32_t GetWidth_() const override;
+  virtual const std::uint32_t GetHeight_() const override;
+
+ private:
+  DecodedVideoPacketExPtr dvp_;
+  std::uint32_t width_;
+  std::uint32_t height_;
+};
+}  // namespace esplusplayer
+// LCOV_EXCL_STOP
+#endif  //__ESPLUSPLAYER_MIXER_TIZEN_SURFACE_VIDEO_FRAME_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/types/buffertype.h b/src/mixer/include_internal/mixer/types/buffertype.h
new file mode 100644 (file)
index 0000000..43d56d0
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __ESPLUSPLAYER_MIXER_TYPES_BUFFER_TYPE_H__
+#define __ESPLUSPLAYER_MIXER_TYPES_BUFFER_TYPE_H__
+
+#include <tbm_type_common.h>
+
+#include <cstdint>
+
+namespace esplusplayer {
+
+using BufferDefaultType = tbm_bo;
+using BufferUnionHandleType = tbm_bo_handle;
+using BufferHandleType = decltype(BufferUnionHandleType::u32);
+using BufferPhysicalAddrType = decltype(BufferUnionHandleType::ptr);
+using BufferKeyType = tbm_key;
+
+const static BufferHandleType kInvalidBufferHandle = 0;
+const static BufferPhysicalAddrType kInvalidBufferPhysicalAddr = nullptr;
+const static BufferKeyType kInvalidBufferKey = 0;
+const static BufferKeyType kInvalidBufferSize = 0;
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TYPES_BUFFER_TYPE_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/types/planecomponent.h b/src/mixer/include_internal/mixer/types/planecomponent.h
new file mode 100644 (file)
index 0000000..1db1536
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ESPLUSPLAYER_MIXER_TYPES_PLANE_COMPONENT_H__
+#define __ESPLUSPLAYER_MIXER_TYPES_PLANE_COMPONENT_H__
+
+namespace esplusplayer {
+
+enum class PlaneComponent {
+  kYComponent,
+  kUVComponent,
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TYPES_PLANE_COMPONENT_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/types/videoplanemanipinfo.h b/src/mixer/include_internal/mixer/types/videoplanemanipinfo.h
new file mode 100644 (file)
index 0000000..12ebaa4
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ESPLUSPLAYER_MIXER_TYPES_VIDEO_PLANE_MAINIPULABLE_INFO_H__
+#define __ESPLUSPLAYER_MIXER_TYPES_VIDEO_PLANE_MAINIPULABLE_INFO_H__
+
+#include <cstdint>
+
+#include "mixer/types/buffertype.h"
+#include "mixer/types/planecomponent.h"
+#include "esplusplayer/types/display.h"
+
+namespace esplusplayer {
+
+struct VideoPlaneManipulableInfo {
+  BufferHandleType handle;
+  PlaneComponent component;
+  std::uint32_t linesize;
+  Geometry rect;
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TYPES_VIDEO_PLANE_MAINIPULABLE_INFO_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/types/videoplanemoveinfo.h b/src/mixer/include_internal/mixer/types/videoplanemoveinfo.h
new file mode 100644 (file)
index 0000000..02a7d98
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __ESPLUSPLAYER_MIXER_TYPES_VIDEO_PLANE_MOVE_INFO_H__
+#define __ESPLUSPLAYER_MIXER_TYPES_VIDEO_PLANE_MOVE_INFO_H__
+
+#include "esplusplayer/types/display.h"
+
+namespace esplusplayer {
+
+struct VideoPlaneMoveInfo {
+  explicit VideoPlaneMoveInfo(const Geometry& current_gemetry, const Geometry& target_gemetry)
+      : cur(current_gemetry), target(target_gemetry) {}
+  Geometry cur;
+  Geometry target;
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_MIXER_TYPES_VIDEO_PLANE_MOVE_INFO_H__
\ No newline at end of file
diff --git a/src/mixer/include_internal/mixer/videoplane.h b/src/mixer/include_internal/mixer/videoplane.h
new file mode 100644 (file)
index 0000000..4724145
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_MIXER_VIDEO_PLANE_H__
+#define __ESPLUSPLAYER_MIXER_VIDEO_PLANE_H__
+
+#include <cstdint>
+#include <memory>
+
+#include "mixer/interfaces/bufferobject.h"
+#include "mixer/interfaces/videoplanemanipulable.h"
+#include "mixer/types/planecomponent.h"
+#include "esplusplayer/types/display.h"
+
+namespace esplusplayer {
+class VideoPlane : public VideoPlaneManipulable {
+ public:
+  explicit VideoPlane(PlaneComponent component, const std::uint32_t& width,
+                      const std::uint32_t& height);
+  virtual ~VideoPlane() = default;
+
+ public:
+  virtual bool IsValid() const override;
+  virtual VideoPlaneManipulableInfo GetVideoPlaneManipulableInfo()
+      const override;
+  virtual void SetCropArea(const CropArea& croparea) override;
+
+ protected:
+  virtual const BufferObject* const GetBufferObject_() const = 0;
+  virtual std::uint32_t GetLineSize_() const;
+
+ private:
+  const PlaneComponent component_;
+  const std::uint32_t width_;
+  const std::uint32_t height_;
+  CropArea croparea_;
+};
+
+class YComponentVideoPlane : public VideoPlane {
+ public:
+  using BufferObjectPtr = std::unique_ptr<BufferObject>;
+
+ public:
+  explicit YComponentVideoPlane(BufferObjectPtr buffer,
+                                const std::uint32_t& width,
+                                const std::uint32_t& height);
+  virtual ~YComponentVideoPlane() = default;
+
+ protected:
+  virtual const BufferObject* const GetBufferObject_() const override;
+
+ private:
+  BufferObjectPtr buffer_;
+};
+
+class UVComponentVideoPlane : public VideoPlane {
+ public:
+  using BufferObjectPtr = std::unique_ptr<BufferObject>;
+
+ public:
+  explicit UVComponentVideoPlane(BufferObjectPtr buffer,
+                                 const std::uint32_t& width,
+                                 const std::uint32_t& height);
+  virtual ~UVComponentVideoPlane() = default;
+
+ protected:
+  virtual const BufferObject* const GetBufferObject_() const override;
+
+ private:
+  BufferObjectPtr buffer_;
+};
+
+class YComponentVideoPlaneWithSharedMemory : public VideoPlane {
+ public:
+  using BufferObjectPtr = std::shared_ptr<BufferObject>;
+  using BufferObjectWeakPtr = std::weak_ptr<BufferObject>;
+
+ public:
+  explicit YComponentVideoPlaneWithSharedMemory(BufferObjectWeakPtr buffer,
+                                                const std::uint32_t& width,
+                                                const std::uint32_t& height);
+  virtual ~YComponentVideoPlaneWithSharedMemory() = default;
+
+ protected:
+  virtual std::uint32_t GetLineSize_() const override;
+  virtual const BufferObject* const GetBufferObject_() const override;
+
+ private:
+  BufferObjectPtr buffer_;
+  std::uint32_t width_;
+};
+
+class UVComponentVideoPlaneWithSharedMemory : public VideoPlane {
+ public:
+  using BufferObjectPtr = std::shared_ptr<BufferObject>;
+  using BufferObjectWeakPtr = std::weak_ptr<BufferObject>;
+
+ public:
+  explicit UVComponentVideoPlaneWithSharedMemory(BufferObjectWeakPtr buffer,
+                                                 const std::uint32_t& width,
+                                                 const std::uint32_t& height);
+  virtual ~UVComponentVideoPlaneWithSharedMemory() = default;
+
+ public:
+  virtual VideoPlaneManipulableInfo GetVideoPlaneManipulableInfo()
+      const override;
+
+ protected:
+  virtual std::uint32_t GetLineSize_() const override;
+  virtual const BufferObject* const GetBufferObject_() const override;
+
+ private:
+  BufferObjectPtr buffer_;
+  std::uint32_t width_;
+  std::uint32_t height_;
+};
+}  // namespace esplusplayer
+
+#endif  //__ESPLUSPLAYER_MIXER_VIDEO_PLANE_H__
\ No newline at end of file
diff --git a/src/mixer/src/abs_videoframe.cpp b/src/mixer/src/abs_videoframe.cpp
new file mode 100644 (file)
index 0000000..ce61533
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/abs_videoframe.h"
+
+namespace esplusplayer {
+
+const std::vector<VideoPlaneManipulableInfo>
+AbstractVideoFrame::GetVideoPlaneManipInfo() const {
+  if (IsValid() == false) return {};
+  std::vector<VideoPlaneManipulableInfo> vector;
+  for (const auto& plane : planes_) {
+    vector.emplace_back(plane->GetVideoPlaneManipulableInfo());
+  }
+  return vector;
+}
+
+bool AbstractVideoFrame::IsValid() const {
+  if (planes_.size() == 0) return false;
+  if (GetWidth_() == 0 || GetHeight_() == 0) return false;
+  if (IsValid_() == false) return false;
+  return true;
+}
+
+bool AbstractVideoFrame::SetCropArea(const CropArea& croparea) {
+  if (IsValid() == false) return false;
+  for (auto& plane : planes_) {
+    plane->SetCropArea(croparea);
+  }
+  return true;
+}
+
+const std::uint32_t AbstractVideoFrame::GetWidth() const {
+  if (IsValid() == false) return 0;
+  return GetWidth_();
+}
+
+const std::uint32_t AbstractVideoFrame::GetHeight() const {
+  if (IsValid() == false) return 0;
+  return GetHeight_();
+}
+
+void AbstractVideoFrame::RegisterVideoPlaneManipulablePtr_(
+    VideoPlaneManipulablePtr vpmanip) {
+  if (vpmanip == nullptr) return;
+  planes_.emplace_back(std::move(vpmanip));
+}
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/defaultmixer.cpp b/src/mixer/src/defaultmixer.cpp
new file mode 100644 (file)
index 0000000..c7cc992
--- /dev/null
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/defaultmixer.h"
+
+#include <gst/gst.h>
+#include <cinttypes>
+
+#include <trackrenderer_capi/display.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <fstream>
+#include <vector>
+
+#include "core/utils/plusplayer_log.h"
+#include "mixer/rendererwithdoublebuf.h"
+#include "mixer/tizen/tizenbufferkeyvideoframe.h"
+#include "mixer/tizen/tizenhwvideoframe.h"
+#include "mixer/tizen/tizenrenderableobj_factory.h"
+#include "mixer/tizen/tizensurfacevideoframe.h"
+#include "mixer/types/videoplanemoveinfo.h"
+
+namespace esplusplayer {
+
+namespace internal {
+TrackRendererDisplayMode ConvertToTrackRendererDisplayMode(
+    const DisplayMode& mode);
+
+}  // namespace internal
+DefaultMixer::DefaultMixer() : renderer_listener_(&trackrenderer_handle_) {
+  LOG_ENTER;
+  gst_init(NULL, NULL);
+  trackrenderer_create(&trackrenderer_handle_);
+
+  TizenRenderableObjectFactory factory(&bufmgr_);
+  renderer_ = RendererPtr(new RendererWithDoubleBuffer(
+      factory, &bufmgr_, &bufmgr_, whole_resolution_, &renderer_listener_));
+  // renderer_ = RendererPtr(
+  //     new Renderer(factory, whole_resolution_, &renderer_listener_));
+  InitResourceList_();
+}
+
+DefaultMixer::~DefaultMixer() {
+  LOG_ENTER;
+  trackrenderer_destroy(trackrenderer_handle_);
+  LOG_LEAVE;
+}
+
+bool DefaultMixer::Start() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> lk(mixer_lock_);
+  if (is_started_ == true) {
+    LOG_ERROR("mixer was already started");
+    return true;
+  }
+
+  if (renderer_->Start() == false) {
+    LOG_ERROR("renderer start failed");
+    return false;
+  }
+
+  TrackRendererTrack track;
+  memset(&track, 0, sizeof(TrackRendererTrack));
+  track.type = kTrackRendererTrackTypeVideo;
+  track.index = 0;
+  track.active = 1;
+  track.mimetype = "video/x-raw";
+  track.width = whole_resolution_.width;
+  track.height = whole_resolution_.height;
+  track.framerate_num = whole_resolution_.framerate_num;
+  track.framerate_den = whole_resolution_.framerate_den;
+
+  if (trackrenderer_set_track(trackrenderer_handle_, &track, 1) != 0) {
+    LOG_ERROR("fail to set track");
+    return false;
+  }
+
+  constexpr std::uint32_t kLowLatencyMode =
+      0x0111;  // video disable avsync & videoquailty
+  trackrenderer_set_attribute(trackrenderer_handle_, "low-latency-mode",
+                              kLowLatencyMode, nullptr);
+  if (use_sub_scaler_) {
+    constexpr std::uint32_t alternative_rsc = 1;
+    trackrenderer_set_attribute(trackrenderer_handle_,
+                                "alternative-video-resource", alternative_rsc,
+                                nullptr);
+  }
+  if (trackrenderer_prepare(trackrenderer_handle_) != 0) {
+    LOG_ERROR("fail to prepare");
+    return false;
+  }
+  if (trackrenderer_start(trackrenderer_handle_) != 0) {
+    LOG_ERROR("fail to start");
+    return false;
+  }
+
+  is_started_ = true;
+  LOG_LEAVE;
+  return true;
+}
+
+bool DefaultMixer::Stop() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> lk(mixer_lock_);
+  if (is_started_ == false) {
+    LOG_ERROR("mixer was already stopped");
+    return true;
+  }
+
+  if (renderer_->Stop() == false) {
+    LOG_ERROR("renderer stop failed");
+  }
+
+  if (trackrenderer_stop(trackrenderer_handle_) != 0) {
+    LOG_ERROR("fail to stop");
+  }
+
+  is_started_ = false;
+  LOG_LEAVE;
+  return true;
+}
+
+int DefaultMixer::GetMaximumAllowedNumberOfPlayer() {
+  LOG_ENTER;
+  // Fix me if we get policy and detail method (bc_hi.lee)
+  constexpr int kMaximumAllowedNumberOfPlayer = 3;
+  constexpr int kMaximumNumForNdecoder = 4;
+  if (resource_allocation_mode_ == RscAllocMode::kNdecoder)
+    return kMaximumNumForNdecoder;
+  return kMaximumAllowedNumberOfPlayer;
+}
+
+bool DefaultMixer::SetDisplay(const DisplayType type, void* obj) {
+  LOG_ENTER;
+  TrackRendererDisplayType _type = kTrackRendererDisplayTypeNone;
+  switch (type) {
+    case DisplayType::kNone: {
+      _type = kTrackRendererDisplayTypeNone;
+      break;
+    }
+    case DisplayType::kOverlay: {
+      _type = kTrackRendererDisplayTypeOverlay;
+      break;
+    }
+    case DisplayType::kEvas: {
+      _type = kTrackRendererDisplayTypeEvas;
+      break;
+    }
+    default:
+      LOG_ERROR("unknown displaytype");
+      return false;
+  }
+  if (!trackrenderer_set_display(trackrenderer_handle_, _type, obj)) {
+    return true;
+  }
+  return false;
+}
+
+bool DefaultMixer::SetDisplay(const DisplayType type, const uint32_t surface_id,
+                              const int x, const int y, const int w,
+                              const int h) {
+  LOG_ENTER;
+  TrackRendererDisplayType _type = kTrackRendererDisplayTypeNone;
+  switch (type) {
+    case DisplayType::kNone: {
+      _type = kTrackRendererDisplayTypeNone;
+      break;
+    }
+    case DisplayType::kOverlay: {
+      _type = kTrackRendererDisplayTypeOverlay;
+      break;
+    }
+    case DisplayType::kEvas: {
+      _type = kTrackRendererDisplayTypeEvas;
+      break;
+    }
+    default:
+      LOG_ERROR("unknown displaytype");
+      return false;
+  }
+  if (!trackrenderer_set_display_surface(trackrenderer_handle_, _type,
+                                         surface_id, x, y, w, h)) {
+    return true;
+  }
+  return false;
+}
+
+bool DefaultMixer::SetDisplayMode(const DisplayMode& mode) {
+  LOG_ENTER;
+  TrackRendererDisplayMode _mode =
+      internal::ConvertToTrackRendererDisplayMode(mode);
+  if (!trackrenderer_set_display_mode(trackrenderer_handle_, _mode)) {
+    return true;
+  }
+  return false;
+}
+
+bool DefaultMixer::SetDisplayRoi(const Geometry& geometry) {
+  LOG_ENTER;
+  TrackRendererGeometry _geometry;
+  memset(&_geometry, 0, sizeof(TrackRendererGeometry));
+  _geometry.x = geometry.x;
+  _geometry.y = geometry.y;
+  _geometry.w = geometry.w;
+  _geometry.h = geometry.h;
+  if (!trackrenderer_set_display_roi(trackrenderer_handle_, &_geometry)) {
+    return true;
+  }
+  return false;
+}
+
+bool DefaultMixer::SetRscAllocMode(const RscAllocMode& mode) {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> lock(ticket_lock_);
+  if (player_map_.size() != 0) {
+    LOG_ERROR(
+        "it have to be called before setting player's display type to mixer "
+        "type");
+    return false;
+  }
+  resource_allocation_mode_ = mode;
+  return true;
+}
+
+bool DefaultMixer::DisableAudioFocusSetting() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> lock(ticket_lock_);
+  if (player_map_.size() != 0) {
+    LOG_ERROR(
+        "it have to be called before setting player's display type to mixer "
+        "type");
+    return false;
+  }
+  enable_audio_focus_setting_ = false;
+  if (audio_focused_player_) audio_focused_player_ = nullptr;
+  return true;
+}
+
+bool DefaultMixer::SetAlternativeVideoScaler() {
+  LOG_ENTER;
+  use_sub_scaler_ = true;
+  return true;
+}
+
+bool DefaultMixer::SetAudioFocus(const void* player_instance) {
+  LOG_ENTER;
+  if (!player_instance) return false;
+  std::lock_guard<std::mutex> lock(ticket_lock_);
+
+  if (!enable_audio_focus_setting_) return false;
+
+  if (player_map_.count(player_instance) == 0) {
+    audio_focused_player_ = player_instance;
+    LOG_INFO("audio focus [%p]", audio_focused_player_);
+    return true;
+  }
+
+  LOG_INFO("Active Audio player[%p]", player_instance);
+  auto ticket = player_map_[player_instance];
+  if (ticket->IsAudioFocused()) {
+    LOG_INFO("already focused user");
+    return true;
+  }
+
+  auto target = std::find_if(
+      player_map_.begin(), player_map_.end(),
+      [](const std::pair<const void*, Ticket*>& item) noexcept -> bool {
+        return (item.second)->IsAudioFocused();
+      });
+
+  if (target != player_map_.end()) {
+    if (target->second->GetListener()->OnAudioFocusChanged(false)) {
+      target->second->SetAudioFocus(false);
+    } else {
+      LOG_ERROR("fail to change audio focus");
+      return false;
+    }
+  } else {
+    LOG_INFO("not found audio focused player");
+  }
+
+  if (ticket->GetListener()) {
+    if (ticket->GetListener()->OnAudioFocusChanged(true)) {
+      ticket->SetAudioFocus(true);
+      return true;
+    }
+  }
+  LOG_ERROR("fail to change audio focus");
+  return false;
+}
+
+bool DefaultMixer::Commit() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> lock(ticket_lock_);
+  std::vector<VideoPlaneMoveInfo> move_list;
+  for (auto it = player_map_.begin(); it != player_map_.end(); ++it) {
+    auto listener = it->second->GetListener();
+    if (!listener) continue;
+    DisplayInfo cur_info, new_info;
+    it->second->GetDisplayInfo(&cur_info);
+    if (listener->OnUpdateDisplayInfo(cur_info, &new_info)) {
+      it->second->UpdateDisplayInfo(new_info);
+      if (it->second->HasRenderedBefore() == true) {
+        move_list.emplace_back(cur_info.geometry, new_info.geometry);
+      }
+    } else {
+      LOG_ERROR("fail to update display info");
+    }
+  }
+  renderer_->Move(&bufmgr_, move_list);
+  return true;
+}
+
+bool DefaultMixer::SetResolution(const ResolutionInfo& info) {
+  whole_resolution_ = info;
+  renderer_->ChangeResolution(TizenRenderableObjectFactory(&bufmgr_),
+                              info.width, info.height);
+  renderer_->ChangeRenderingSpeed(info.framerate_num, info.framerate_den);
+  return true;
+}
+
+bool DefaultMixer::RegisterListener(MixerEventListener* listener) {
+  LOG_ENTER;
+  listener_ = listener;
+  trackrenderer_set_resourceconflict_cb(trackrenderer_handle_,
+                                        ResourceConflictCb_, this);
+  trackrenderer_set_error_cb(trackrenderer_handle_, ErrorCb_, this);
+  return true;
+}
+
+MixerTicket* DefaultMixer::CreateTicket(const void* player_instance) {
+  std::lock_guard<std::mutex> lock(ticket_lock_);
+  LOG_ENTER;
+  auto ticket = new Ticket(this, player_instance);
+  if (audio_focused_player_ == player_instance) {
+    ticket->SetAudioFocus(true);
+    LOG_INFO(" player [%p]", player_instance);
+  }
+  player_map_.emplace(player_instance, ticket);
+  return ticket;
+}
+
+// LCOV_EXCL_START
+bool DefaultMixer::Detach_(const void* player_instance) {
+  std::lock_guard<std::mutex> lock(ticket_lock_);
+  LOG_ENTER;
+  auto* ticket = player_map_.at(player_instance);
+
+  if (ticket == nullptr) return false;
+  if (ticket->HasRenderedBefore()) {
+    DisplayInfo display_info;
+    ticket->GetDisplayInfo(&display_info);
+    // if this ticket is display visible status, draw black screen
+    if (IsNeededToSkipRendering_(display_info) == false) {
+      LOG_INFO(
+          "player [%p] has been rendered before, so will mute on rendered "
+          "region",
+          player_instance);
+      renderer_->Mute(&bufmgr_, display_info.geometry);
+    }
+  }
+  ticket->DeallocResource();
+  player_map_.erase(player_instance);
+  return true;
+}
+
+bool DefaultMixer::Render_(const void* player_instance,
+                           const VideoPlaneCollection& vplanes) {
+  DisplayInfo display_info;
+  {
+    std::lock_guard<std::mutex> t_lk(ticket_lock_);
+    auto* ticket = player_map_.at(player_instance);
+    if (ticket == nullptr) return false;
+    ticket->GetDisplayInfo(&display_info);
+    ticket->RecordRenderingTime();
+  }
+  if (IsNeededToSkipRendering_(display_info)) {
+    LOG_INFO("Skip Rendering for player [%p]", player_instance);
+    return true;
+  }
+  bool ret = renderer_->Render(&bufmgr_, &vplanes, display_info.geometry);
+  if (ret == false) {
+    LOG_INFO("Rendering Failed for player [%p]", player_instance);
+  }
+  return ret;
+}
+
+bool DefaultMixer::IsNeededToSkipRendering_(const DisplayInfo& display_info) {
+  if (display_info.visible_status == VisibleStatus::kHide) return true;
+  if (display_info.geometry.x == 0 && display_info.geometry.y == 0 &&
+      display_info.geometry.w == 1 && display_info.geometry.h == 1)
+    return true;
+  return false;
+}
+
+void DefaultMixer::ResourceConflictCb_(UserData userdata) {
+  auto mixer = static_cast<DefaultMixer*>(userdata);
+  if (!mixer) return;
+  mixer->listener_->OnResourceConflicted();
+}
+void DefaultMixer::ErrorCb_(const TrackRendererErrorType error_code,
+                            UserData userdata) {
+  auto mixer = static_cast<DefaultMixer*>(userdata);
+  if (!mixer) return;
+  mixer->listener_->OnError();
+}
+
+bool DefaultMixer::Ticket::Render(const DecodedRawInfo& info) {
+  LOG_INFO("player [%p] render frame [%d x %d]", player_instance_, info.width,
+           info.height);
+  TizenHWVideoFrame frame(info);
+  frame.SetCropArea(each_display_info_.croparea);
+  bool ret = handler_->Render_(player_instance_, frame);
+  if (ret == false) {
+    LOG_INFO("player [%p] rendering error", player_instance_);
+  } else {
+    has_rendered_ = true;
+  }
+  return ret;
+}
+
+bool DefaultMixer::Ticket::Render(const DecodedVideoKeyTypeInfo& info) {
+  LOG_INFO("player [%p] render frame [%d x %d]", player_instance_, info.width,
+           info.height);
+  TizenBufferKeyVideoFrame frame(&handler_->bufmgr_, info.key, info.width,
+                                 info.height);
+  frame.SetCropArea(each_display_info_.croparea);
+  bool ret = handler_->Render_(player_instance_, frame);
+  if (ret == false) {
+    LOG_INFO("player [%p] rendering error", player_instance_);
+  } else {
+    has_rendered_ = true;
+  }
+  return ret;
+}
+// LCOV_EXCL_STOP
+
+void DefaultMixer::InitResourceList_() {
+  // Must be improved (bc_hi.lee)
+  for (int type = static_cast<int>(ResourceType::kHwMain);
+       type < static_cast<int>(ResourceType::kNdecoder); type++) {
+    Resource resource;
+    resource.category = ResourceCategory::kVideoDecoder;
+    resource.type = static_cast<ResourceType>(type);
+    resource_list_.push_back(std::move(resource));
+  }
+}
+
+// LCOV_EXCL_START
+bool DefaultMixer::Ticket::GetAvailableResourceType(
+    const ResourceCategory& category, ResourceType* type) {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> lock(handler_->ticket_lock_);
+  if (handler_->resource_allocation_mode_ == RscAllocMode::kDisable) {
+    LOG_ERROR("mixer is no loger involved in resource alloc");
+    return false;
+  }
+
+  if (handler_->resource_allocation_mode_ == RscAllocMode::kNdecoder) {
+    *type = ResourceType::kNdecoder;
+    return true;
+  }
+
+  for (const auto& item : handler_->resource_list_) {
+    if (!item.assignee) {
+      *type = item.type;
+      LOG_INFO("Resource type [%d]", static_cast<int>(*type));
+      return true;
+    }
+  }
+  LOG_ERROR("no available resource type");
+  return false;
+}
+
+bool DefaultMixer::Ticket::IsAudioFocusHandler() {
+  std::lock_guard<std::mutex> lock(handler_->ticket_lock_);
+  return handler_->enable_audio_focus_setting_;
+}
+
+bool DefaultMixer::Ticket::IsRscAllocHandler() {
+  std::lock_guard<std::mutex> lock(handler_->ticket_lock_);
+  return handler_->resource_allocation_mode_ != RscAllocMode::kDisable;
+}
+
+bool DefaultMixer::Ticket::Alloc(const ResourceCategory& category,
+                                 const ResourceType& type) {
+  std::lock_guard<std::mutex> lock(handler_->ticket_lock_);
+  if (handler_->resource_allocation_mode_ == RscAllocMode::kDisable) {
+    LOG_ERROR("mixer is no loger involved in resource alloc");
+    return false;
+  }
+
+  if (type == ResourceType::kNdecoder) {
+    LOG_INFO("Request N decoder");
+    return true;
+  }
+
+  auto compare = [category, type](Resource item) -> bool {
+    if (item.category == category && item.type == type && !item.assignee) {
+      return true;
+    }
+    return false;
+  };
+  auto target = std::find_if(handler_->resource_list_.begin(),
+                             handler_->resource_list_.end(), compare);
+  if (target == handler_->resource_list_.end()) {
+    LOG_ERROR("Resource alloc fail");
+    return false;
+  }
+  LOG_INFO("assignee %p", player_instance_);
+  target->assignee = player_instance_;
+  LOG_LEAVE;
+  return true;
+}
+
+MixerTicketEventListener* DefaultMixer::Ticket::GetListener() {
+  return ticket_listener_;
+}
+
+bool DefaultMixer::Ticket::IsAudioFocused() { return is_audio_focus_; }
+
+void DefaultMixer::Ticket::SetAudioFocus(bool active) {
+  is_audio_focus_ = active;
+}
+
+void DefaultMixer::Ticket::GetDisplayInfo(DisplayInfo* info) {
+  if (info == nullptr) return;
+  *info = each_display_info_;
+}
+
+bool DefaultMixer::Ticket::HasRenderedBefore() { return has_rendered_; }
+
+void DefaultMixer::Ticket::UpdateDisplayInfo(const DisplayInfo& info) {
+  LOG_INFO(
+      "updated display info : geom[%d, %d, %d x %d] crop[%.3lf, %.3lf, %.3lf x "
+      "%.3lf]",
+      info.geometry.x, info.geometry.y, info.geometry.w, info.geometry.h,
+      info.croparea.scale_x, info.croparea.scale_y, info.croparea.scale_w,
+      info.croparea.scale_h);
+  each_display_info_ = info;
+}
+
+void DefaultMixer::Ticket::DeallocResource() {
+  auto compare = [this](Resource item) -> bool {
+    if (item.assignee == player_instance_) {
+      return true;
+    }
+    return false;
+  };
+
+  auto target = std::find_if(handler_->resource_list_.begin(),
+                             handler_->resource_list_.end(), compare);
+  if (target == handler_->resource_list_.end()) {
+    LOG_INFO("not found assignee");
+    return;
+  }
+  target->assignee = nullptr;
+}
+
+void DefaultMixer::Ticket::RecordRenderingTime() {
+  auto now = std::chrono::system_clock::now();
+  LOG_INFO("[PERF] p[%p] render_interval[%" PRId64"]ms", player_instance_,
+           std::chrono::duration_cast<std::chrono::milliseconds>(
+               now - last_rendering_time_)
+               .count());
+  last_rendering_time_ = now;
+}
+
+bool DefaultMixer::Ticket::RegisterListener(
+    MixerTicketEventListener* listener) {
+  LOG_ENTER;
+  ticket_listener_ = listener;
+  return true;
+}
+
+bool DefaultMixer::Ticket::Prepare() {
+  LOG_ENTER;
+  DisplayInfo new_info;
+  ticket_listener_->OnUpdateDisplayInfo(each_display_info_, &new_info);
+  UpdateDisplayInfo(new_info);
+  if (!handler_->enable_audio_focus_setting_) return true;
+  LOG_INFO("audio focused [%d]", is_audio_focus_);
+  ticket_listener_->OnAudioFocusChanged(is_audio_focus_);
+  return true;
+}
+
+DefaultMixer::Ticket::~Ticket() {
+  handler_->Detach_(player_instance_);
+  LOG_LEAVE;
+}
+// LCOV_EXCL_STOP
+
+DefaultMixer::MixerRendererEventListener::MixerRendererEventListener(
+    TrackRendererHandle* trhandle_ptr)
+    : trhandle_ptr_(trhandle_ptr) {}
+
+DefaultMixer::MixerRendererEventListener::~MixerRendererEventListener() {}
+
+void* DefaultMixer::MixerRendererEventListener::CreateGstBuffer_(
+    const BufferKeyType& key) const {
+  if (key == 0) return nullptr;
+  auto* gstbuffer = gst_buffer_new();
+  auto* gststructure =
+      gst_structure_new("tbm_bo", "tbm_bo_key", G_TYPE_UINT, key, nullptr);
+  gst_mini_object_set_qdata(GST_MINI_OBJECT(gstbuffer),
+                            g_quark_from_static_string("tbm_bo"), gststructure,
+                            (GDestroyNotify)gst_structure_free);
+  return static_cast<void*>(gstbuffer);
+}
+
+void DefaultMixer::MixerRendererEventListener::FillDecoderInputBuffer_(
+    TrackRendererDecoderInputBuffer& buffer, const BufferKeyType& key) const {
+  buffer.type = kTrackRendererTrackTypeVideo;
+  buffer.index = 0;
+  buffer.buffer = CreateGstBuffer_(key);
+}
+
+bool DefaultMixer::MixerRendererEventListener::OnRenderingRelease(
+    const BufferKeyType& key) {
+  if (trhandle_ptr_ == nullptr || *trhandle_ptr_ == nullptr) return false;
+  TrackRendererDecoderInputBuffer buffer;
+  FillDecoderInputBuffer_(buffer, key);
+  TrackRendererSubmitStatus status;
+  int ret = trackrenderer_submit_packet2(*trhandle_ptr_, &buffer, &status);
+  if (ret != 0 && buffer.buffer != nullptr) {
+    gst_buffer_unref(GST_BUFFER(buffer.buffer));
+  }
+  return ret == 0;
+}
+
+namespace internal {
+TrackRendererDisplayMode ConvertToTrackRendererDisplayMode(
+    const DisplayMode& mode) {
+  switch (mode) {
+    case DisplayMode::kLetterBox:
+      return kTrackRendererDisplayModeLetterBox;
+    case DisplayMode::kOriginSize:
+      return kTrackRendererDisplayModeOriginSize;
+    case DisplayMode::kFullScreen:
+      return kTrackRendererDisplayModeFullScreen;
+    case DisplayMode::kCroppedFull:
+      return kTrackRendererDisplayModeCroppedFull;
+    case DisplayMode::kOriginOrLetter:
+      return kTrackRendererDisplayModeOriginOrLetter;
+    case DisplayMode::kDstRoi:
+      return kTrackRendererDisplayModeDstRoi;
+    case DisplayMode::kAutoAspectRatio:
+      return kTrackRendererDisplayModeAutoAspectRatio;
+    default:
+      return kTrackRendererDisplayModeDisplayMax;
+  }
+}
+
+}  // namespace internal
+
+}  // namespace esplusplayer
diff --git a/src/mixer/src/mixedframe.cpp b/src/mixer/src/mixedframe.cpp
new file mode 100644 (file)
index 0000000..3307b46
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/mixedframe.h"
+
+#include <cstring>
+
+#include "core/utils/plusplayer_log.h"
+#include "mixer/interfaces/accessiblebuffer.h"
+
+namespace esplusplayer {
+MixedFramePtr MixedFrame::Create(const MemoryAllocator* const memop,
+                                 const std::uint32_t width,
+                                 const std::uint32_t height) {
+  return Ptr(new MixedFrame(memop, width, height));
+}
+
+MixedFrame::MixedFrame(const MemoryAllocator* const memop,
+                       const std::uint32_t width, const std::uint32_t height)
+    : width_(width), height_(height) {
+  if (memop == nullptr) return;
+  const auto size = CalculateBufferSize_(width_, height_);
+  if (size == 0) return;
+  buffer_ = BufferObjectPtr(memop->Allocate(size));
+  if (buffer_ == nullptr) return;
+  allocated_size_ = buffer_->GetSize();
+  if (allocated_size_ == 0) return;
+
+  if (allocated_size_ != size) {
+    LOG_WARN("size mismatched request [%u] allocated [%u]", size,
+             allocated_size_);
+  }
+
+  if (auto* accessible_buffer =
+          dynamic_cast<AccessibleBuffer*>(buffer_.get())) {
+    auto ptr = accessible_buffer->GetWritableAddress();
+    if (ptr == nullptr) return;
+    const auto y_size = width_ * height_;
+    const auto uv_size = y_size >> 1;
+    {
+      std::memset(static_cast<char*>(ptr->GetAddress()), (char)0x00, y_size);
+      std::memset(static_cast<char*>(ptr->GetAddress()) + y_size, (char)0x80,
+                  uv_size);
+    }
+    LOG_DEBUG("MixedFrame UV memset done");
+  }
+}
+
+const std::vector<VideoPlaneManipulableInfo>
+MixedFrame::GetVideoPlaneManipInfo() const {
+  if (IsValid() == false) return {};
+  auto handle = buffer_->GetBufferHandle();
+  return {GetYComponentVMInfo_(handle), GetUVComponentVMInfo_(handle)};
+}
+
+bool MixedFrame::IsValid() const {
+  if (width_ == 0 || height_ == 0) return false;
+  if (allocated_size_ == 0) return false;
+  if (buffer_ == nullptr) return false;
+  return true;
+}
+
+std::uint32_t MixedFrame::GetWidth() const { return width_; }
+
+std::uint32_t MixedFrame::GetHeight() const { return height_; }
+
+std::uint32_t MixedFrame::GetSize() const {
+  if (IsValid() == false) return 0;
+  return allocated_size_;
+}
+
+bool MixedFrame::Render(const VideoPlaneManipulator* const vpmanip,
+                        const std::vector<VideoPlaneManipulableInfo>& planes,
+                        const Geometry& geom) {
+  if (vpmanip == nullptr) return false;
+  if (IsValid() == false) return false;
+  bool ret = true;
+  for (const auto& video_manipinfo : planes) {
+    ret &= vpmanip->Do(video_manipinfo, GetMixedFrameVideoPlaneManipulableInfo_(
+                                            video_manipinfo.component, geom));
+  }
+  return ret;
+}
+
+bool MixedFrame::Fill(const VideoPlaneColorManipulator* const vpmanip,
+                      const PlaneComponent& comp, const std::uint32_t& color,
+                      const Geometry& geom) {
+  VideoPlaneManipulableInfo info =
+      GetMixedFrameVideoPlaneManipulableInfo_(comp, geom);
+  return vpmanip->Do(color, info);
+}
+
+bool MixedFrame::Export(BufferKeyType& key) const {
+  if (IsValid() == false) return false;
+  key = buffer_->Export();
+  return true;
+}
+
+std::uint32_t MixedFrame::CalculateBufferSize_(const std::uint32_t width,
+                                               const std::uint32_t height) {
+  return (width * height * 3) >> 1;
+}
+
+VideoPlaneManipulableInfo MixedFrame::GetMixedFrameVideoPlaneManipulableInfo_(
+    const PlaneComponent component, const Geometry& geom) {
+  VideoPlaneManipulableInfo ret;
+  ret.handle = buffer_->GetBufferHandle();
+  ret.component = component;
+  ret.linesize = GetWidth();
+  if (component == PlaneComponent::kYComponent) {
+    ret.rect = geom;
+  } else {
+    ret.rect.x = geom.x / 2;
+    ret.rect.y = geom.y / 2 + GetHeight();
+    ret.rect.w = geom.w / 2;
+    ret.rect.h = geom.h / 2;
+  }
+  return ret;
+}
+
+VideoPlaneManipulableInfo MixedFrame::GetYComponentVMInfo_(
+    BufferHandleType handle) const {
+  VideoPlaneManipulableInfo info;
+  info.handle = handle;
+  info.linesize = GetWidth();
+  info.rect.x = 0;
+  info.rect.y = 0;
+  info.rect.w = GetWidth();
+  info.rect.h = GetHeight();
+  info.component = PlaneComponent::kYComponent;
+  return info;
+}
+
+VideoPlaneManipulableInfo MixedFrame::GetUVComponentVMInfo_(
+    BufferHandleType handle) const {
+  VideoPlaneManipulableInfo info;
+  info.handle = handle;
+  info.linesize = GetWidth();
+  info.rect.x = 0;
+  info.rect.y = GetHeight();
+  info.rect.w = GetWidth() >> 1;
+  info.rect.h = GetHeight() >> 1;
+  info.component = PlaneComponent::kUVComponent;
+  return info;
+}
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/mixer.cpp b/src/mixer/src/mixer.cpp
new file mode 100644 (file)
index 0000000..1f5d315
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/mixer.h"
+
+#include "core/utils/plusplayer_log.h"
+#include "mixer/defaultmixer.h"
+
+namespace esplusplayer {
+
+std::unique_ptr<Mixer> Mixer::Create() {
+  auto instance = std::unique_ptr<DefaultMixer>(new DefaultMixer);
+  LOG_INFO("Create Mixer [%p]", instance.get());
+  return instance;
+}
+
+}  // namespace esplusplayer
diff --git a/src/mixer/src/mixer_capi.cpp b/src/mixer/src/mixer_capi.cpp
new file mode 100644 (file)
index 0000000..9f8c169
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer_capi/mixer_capi.h"
+
+#include "core/utils/plusplayer_log.h"
+#include "mixer/mixer.h"
+#include "mixer/mixer_eventlistener.h"
+#include "esplusplayer/types/display.h"
+
+using esplusplayer::Mixer;
+
+struct MixerPriv;
+
+class listener_bridge : public esplusplayer::MixerEventListener {
+ public:
+  listener_bridge() { LOG_ENTER }
+  ~listener_bridge() { LOG_ENTER }
+
+  virtual void OnResourceConflicted() {
+    LOG_ENTER
+    if (this->resource_conflicted_cb_)
+      this->resource_conflicted_cb_(resource_conflicted_cb_userdata_);
+  }
+
+ private:
+  mixer_resource_conflicted_cb resource_conflicted_cb_ = nullptr;
+  void* resource_conflicted_cb_userdata_ = nullptr;
+
+  friend int mixer_set_resource_conflicted_cb(
+      mixer_handle pp, mixer_resource_conflicted_cb resource_conflicted_cb,
+      void* userdata);
+};
+
+struct MixerPriv {
+  std::unique_ptr<Mixer> mixer;
+  std::unique_ptr<listener_bridge> listener{new listener_bridge()};
+
+  friend MixerPriv* MixerPrivCreate();
+  friend void MixerPrivDestroy(MixerPriv*& instance);
+
+ private:
+  MixerPriv() {}
+  ~MixerPriv() {}
+};
+
+MixerPriv* MixerPrivCreate() {
+  MixerPriv* instance = new MixerPriv();
+  instance->mixer = Mixer::Create();
+  instance->mixer->RegisterListener(instance->listener.get());
+  return instance;
+}
+
+void MixerPrivDestroy(MixerPriv*& instance) {
+  if (instance) delete instance;
+  instance = nullptr;
+}
+
+inline bool is_null_(void* object) { return object == nullptr; }
+
+inline Mixer* cast_(mixer_handle mixer) {
+  auto priv = static_cast<MixerPriv*>(mixer);
+  return priv->mixer.get();
+}
+
+inline listener_bridge* listener_cast_(mixer_handle pp) {
+  auto priv = static_cast<MixerPriv*>(pp);
+  return priv->listener.get();
+}
+
+inline int convert_return_type_(bool ret) {
+  return ret ? MIXER_ERROR_TYPE_NONE : MIXER_ERROR_TYPE_INVALID_OPERATION;
+}
+
+mixer_handle mixer_create() {
+  LOG_ENTER
+  mixer_handle mixer = static_cast<mixer_handle>(MixerPrivCreate());
+  return mixer;
+}
+
+int mixer_destroy(mixer_handle handle) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  auto priv = static_cast<MixerPriv*>(handle);
+  MixerPrivDestroy(priv);
+
+  return MIXER_ERROR_TYPE_NONE;
+}
+
+int mixer_start(mixer_handle handle) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->Start());
+}
+
+int mixer_stop(mixer_handle handle) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->Stop());
+}
+
+int mixer_get_max_allowed_number_of_player(mixer_handle handle) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return cast_(handle)->GetMaximumAllowedNumberOfPlayer();
+}
+
+int mixer_set_display(mixer_handle handle, mixer_display_type type,
+                      void* window) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->SetDisplay(
+      static_cast<esplusplayer::DisplayType>(type), window));
+}
+
+int mixer_set_display_mode(mixer_handle handle, mixer_display_mode mode) {
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO("display mode : %d", static_cast<int>(mode));
+  return convert_return_type_(cast_(handle)->SetDisplayMode(
+      static_cast<esplusplayer::DisplayMode>(mode)));
+}
+
+int mixer_set_display_roi(mixer_handle handle, const int x, const int y,
+                          const int width, const int height) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+  LOG_INFO("x : %d, y: %d, width : %d, height : %d", x, y, width, height);
+  esplusplayer::Geometry roi;
+  roi.x = x;
+  roi.y = y;
+  roi.w = width;
+  roi.h = height;
+  return convert_return_type_(cast_(handle)->SetDisplayRoi(roi));
+}
+
+int mixer_set_rsc_alloc_mode(mixer_handle handle,
+                             const mixer_rsc_alloc_mode mode) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->SetRscAllocMode(
+      static_cast<esplusplayer::RscAllocMode>(mode)));
+}
+
+int mixer_disable_audio_focus_setting(mixer_handle handle) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->DisableAudioFocusSetting());
+}
+
+int mixer_set_alternative_video_scaler(mixer_handle handle) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->SetAlternativeVideoScaler());
+}
+
+int mixer_set_audio_focus(mixer_handle handle, const void* player_instance) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->SetAudioFocus(player_instance));
+}
+
+int mixer_commit(mixer_handle handle) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+
+  return convert_return_type_(cast_(handle)->Commit());
+}
+
+int mixer_set_resolution(mixer_handle handle, const int width, const int height,
+                         const int framerate_num, const int framerate_den) {
+  LOG_ENTER
+  if (is_null_(handle)) return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+  esplusplayer::Mixer::ResolutionInfo info;
+  info.width = width;
+  info.height = height;
+  info.framerate_num = framerate_num;
+  info.framerate_den = framerate_den;
+  return convert_return_type_(cast_(handle)->SetResolution(info));
+}
+
+mixer_ticket_h mixer_create_ticket(mixer_handle handle, const void* player_instance) {
+  LOG_ENTER
+  if (is_null_(handle)) return nullptr;
+
+  return cast_(handle)->CreateTicket(player_instance);
+}
+
+int mixer_set_resource_conflicted_cb(
+    mixer_handle handle, mixer_resource_conflicted_cb resource_conflicted_cb,
+    void* userdata) {
+  LOG_ENTER
+  listener_bridge* listener = nullptr;
+  if (is_null_(handle) || is_null_(listener = listener_cast_(handle))) {
+    LOG_ERROR("Mixer or Listener object is nil.");
+    return MIXER_ERROR_TYPE_INVALID_PARAMETER;
+  }
+  listener->resource_conflicted_cb_ = resource_conflicted_cb;
+  listener->resource_conflicted_cb_userdata_ = userdata;
+  return convert_return_type_(true);
+}
diff --git a/src/mixer/src/renderer.cpp b/src/mixer/src/renderer.cpp
new file mode 100644 (file)
index 0000000..456783d
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/renderer.h"
+#include <cinttypes>
+#include "core/utils/plusplayer_log.h"
+
+namespace esplusplayer {
+using std::chrono::duration_cast;
+using std::chrono::milliseconds;
+using std::chrono::system_clock;
+
+Renderer::Renderer(const RenderableObjectFactory& mf_factory,
+                   const Mixer::ResolutionInfo& rinfo,
+                   RendererEventListener* listener)
+    : resolution_info_(rinfo),
+      listener_(listener),
+      frame_(RenderableObjectPtr(mf_factory.CreateRenderableObject(
+          resolution_info_.width, resolution_info_.height))) {}
+
+Renderer::~Renderer() { Stop(); }
+
+bool Renderer::IsValid() const {
+  if (frame_ == nullptr) return false;
+  if (frame_->IsValid() == false) return false;
+  return IsValid_();
+}
+
+bool Renderer::Start() {
+  std::unique_lock<std::mutex> lk(rendering_mtx_);
+  if (IsValid() == false) return false;
+  if (rendering_worker_.joinable()) return false;
+  rendering_flag_ = true;
+  rendering_worker_ = std::thread(&Renderer::RenderingWorker_, this);
+  return true;
+}
+
+bool Renderer::Stop() {
+  {
+    std::unique_lock<std::mutex> lk(rendering_mtx_);
+    if (rendering_worker_.joinable() == false) return false;
+    rendering_flag_ = false;
+    rendering_cv_.notify_all();
+  }
+  rendering_worker_.join();
+  return true;
+}
+
+bool Renderer::ChangeResolution(const RenderableObjectFactory& mf_factory,
+                                const std::uint32_t& width,
+                                const std::uint32_t& height) {
+  if (width == 0 || height == 0) return false;
+  if (width == static_cast<std::uint32_t>(resolution_info_.width) &&
+      height == static_cast<std::uint32_t>(resolution_info_.height))
+    return false;
+  return ChangeResolutionInternal_(mf_factory, width, height);
+}
+
+bool Renderer::ChangeResolutionInternal_(
+    const RenderableObjectFactory& mf_factory, const std::uint32_t& width,
+    const std::uint32_t& height) {
+  std::unique_lock<std::mutex> lk(rendering_mtx_);
+  resolution_info_.width = width;
+  resolution_info_.height = height;
+  frame_.reset(nullptr);
+  frame_ = RenderableObjectPtr(mf_factory.CreateRenderableObject(
+      resolution_info_.width, resolution_info_.height));
+  return IsValid();
+}
+
+bool Renderer::ChangeRenderingSpeed(const std::uint32_t framerate_num,
+                                    const std::uint32_t framerate_den) {
+  if (framerate_num == 0 || framerate_den == 0) return false;
+  if (framerate_num ==
+          static_cast<std::uint32_t>(resolution_info_.framerate_num) &&
+      framerate_den ==
+          static_cast<std::uint32_t>(resolution_info_.framerate_den))
+    return false;
+  std::unique_lock<std::mutex> lk(rendering_mtx_);
+  if (IsValid() == false) return false;
+  resolution_info_.framerate_num = framerate_num;
+  resolution_info_.framerate_den = framerate_den;
+  return true;
+}
+
+bool Renderer::Render(const VideoPlaneScaler* const scaler,
+                      const VideoPlaneCollection* const planes,
+                      const Geometry& geom) {
+  if (scaler == nullptr) return false;
+  if (planes == nullptr) return false;
+  return RenderInternal_(scaler->GetScaleManipulator(),
+                         planes->GetVideoPlaneManipInfo(), geom);
+}
+
+bool Renderer::RenderInternal_(
+    const VideoPlaneManipulator* const scaler,
+    const std::vector<VideoPlaneManipulableInfo>& planes,
+    const Geometry& geom) {
+  if (scaler == nullptr) return false;
+  const auto before = system_clock::now();
+  std::unique_lock<std::mutex> lk(rendering_mtx_);
+  if (IsValid() == false) return false;
+  LOG_INFO("[PERF] RenderInternal_ Lock [%" PRId64"]ms",
+           std::chrono::duration_cast<std::chrono::milliseconds>(
+               system_clock::now() - before)
+               .count());
+  const auto ret = frame_->Render(scaler, planes, geom);
+  LOG_INFO("[PERF] Scale [%" PRId64"]ms",
+           std::chrono::duration_cast<std::chrono::milliseconds>(
+               system_clock::now() - before)
+               .count());
+  return ret;
+}
+
+bool Renderer::Mute(const VideoPlaneColorFiller* const filler,
+                    const Geometry& geom) {
+  if (filler == nullptr) return false;
+  return MuteInternal_(filler->GetColorFillManipulator(), geom);
+}
+
+bool Renderer::MuteInternal_(const VideoPlaneColorManipulator* const filler,
+                             const Geometry& geom) {
+  if (filler == nullptr) return false;
+  std::unique_lock<std::mutex> lk(rendering_mtx_);
+  if (IsValid() == false) return false;
+  bool ret = true;
+  ret &= frame_->Fill(filler, PlaneComponent::kYComponent, 0x00, geom);
+  ret &= frame_->Fill(filler, PlaneComponent::kUVComponent, 0x8080, geom);
+  return ret;
+}
+
+bool Renderer::Move(const VideoPlaneColorFiller* const filler,
+                    const std::vector<VideoPlaneMoveInfo>& moving_planes) {
+  if (filler == nullptr) return false;
+  if (moving_planes.size() == 0) return false;
+  return MoveInternal_(filler->GetColorFillManipulator(), moving_planes);
+}
+
+bool Renderer::MoveInternal_(
+    const VideoPlaneColorManipulator* const filler,
+    const std::vector<VideoPlaneMoveInfo>& moving_planes) {
+  if (filler == nullptr) return false;
+  std::unique_lock<std::mutex> lk(rendering_mtx_);
+  if (IsValid() == false) return false;
+  bool ret = true;
+  for (const auto& move : moving_planes) {
+    if (IsSameGeometry_(move.cur, move.target)) continue;
+    ret &= frame_->Fill(filler, PlaneComponent::kYComponent, 0x00, move.cur);
+    ret &= frame_->Fill(filler, PlaneComponent::kUVComponent, 0x8080, move.cur);
+  }
+  return true;
+};
+
+bool Renderer::OnRenderingBefore_(const RenderableObject* const frame) {
+  return true;
+}
+
+bool Renderer::IsValid_() const { return true; }
+
+bool Renderer::RaiseOnRenderingReleaseEvent_(const BufferKeyType& key) {
+  if (listener_ == nullptr) return false;
+  return listener_->OnRenderingRelease(key);
+}
+
+std::uint32_t Renderer::GetNextRenderingTimeWithJitter_(
+    const JitterType& jitter) const {
+  const static std::int64_t kOneSecondInMs = 1000;  // ms
+  auto next = kOneSecondInMs /
+              (resolution_info_.framerate_num / resolution_info_.framerate_den);
+  auto jitter_in_ms = jitter.count();
+  LOG_DEBUG("[PERF] jitter : [%" PRId64"]ms / next : [%" PRId64"]ms", jitter_in_ms, next);
+  jitter_in_ms %= next;
+  next -= jitter_in_ms;
+  return next < 0 ? 0 : static_cast<std::uint32_t>(next);
+}
+
+void Renderer::RenderingWorker_() {
+  LOG_DEBUG("Start Rendering");
+  JitterType jitter(0);
+  while (1) {
+    LOG_DEBUG("= Start New Frame ===========================================");
+    auto before_1 = system_clock::now();
+    std::unique_lock<std::mutex> lk(rendering_mtx_);
+    if (rendering_flag_ == false) break;
+    if (OnRenderingBefore_(frame_.get()) == false) {
+      LOG_WARN("OnRenderingBefore_ Failed");
+      continue;
+    }
+
+    LOG_DEBUG(
+        "[PERF] before_1 ~ now : [%" PRId64"]ms",
+        duration_cast<milliseconds>(system_clock::now() - before_1).count());
+    jitter += duration_cast<milliseconds>(system_clock::now() - before_1);
+
+    std::uint64_t next_in_ms = GetNextRenderingTimeWithJitter_(jitter);
+
+    jitter = JitterType::zero();
+    auto before_2 = system_clock::now();
+    LOG_DEBUG("[PULSE] it will awake after [%" PRId64"]ms", next_in_ms);
+    if (next_in_ms > 0) {
+      rendering_cv_.wait_for(lk, milliseconds(next_in_ms),
+                             [this] { return rendering_flag_ == false; });
+      // LOG_DEBUG(
+      //     "[PERF] before_2 ~ after awake : [%lld]ms",
+      //     duration_cast<milliseconds>(system_clock::now() -
+      //     before_2).count());
+      if (rendering_flag_ == false) break;
+    }
+    if (IsValid() == false) continue;
+
+    BufferKeyType key;
+    if (frame_->Export(key) == false) {
+      LOG_ERROR("MixedFrame Export Failed");
+      continue;
+    }
+
+    RaiseOnRenderingReleaseEvent_(key);
+    jitter = duration_cast<milliseconds>(system_clock::now() - before_2 -
+                                         milliseconds(next_in_ms));
+    // LOG_DEBUG(
+    //     "[PERF] before_2 ~ now : [%lld]ms / next_in_ms : [%llu]ms",
+    //     duration_cast<milliseconds>(system_clock::now() - before_2).count(),
+    //     next_in_ms);
+  }
+  std::unique_lock<std::mutex> lk(rendering_mtx_);
+  rendering_flag_ = false;
+  LOG_DEBUG("Rendering Stopped");
+}
+
+const Mixer::ResolutionInfo& Renderer::GetResolutionInfo_() const {
+  return resolution_info_;
+}
+
+RenderableObjectPtr& Renderer::GetMixedFrame_() { return frame_; }
+
+void Renderer::AcquireRenderingLock_() { rendering_mtx_.lock(); }
+
+void Renderer::ReleaseRenderingLock_() { rendering_mtx_.unlock(); }
+
+Geometry Renderer::MakeGeometry_(const std::uint32_t& width,
+                                 const std::uint32_t& height) {
+  Geometry geom;
+  geom.w = width;
+  geom.h = height;
+  return geom;
+}
+
+bool Renderer::IsSameGeometry_(const Geometry& g1, const Geometry& g2) {
+  if (g1.x != g2.x) return false;
+  if (g1.y != g2.y) return false;
+  if (g1.w != g2.w) return false;
+  if (g1.h != g2.h) return false;
+  return true;
+}
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/sys/tbminterface.cpp b/src/mixer/src/sys/tbminterface.cpp
new file mode 100644 (file)
index 0000000..4a7d39f
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/sys/tbminterface.h"
+
+#include <tbm_bo.h>
+#include <tbm_bufmgr.h>
+
+namespace esplusplayer {
+namespace tizen {
+BufferDefaultType TBMInterface::BoRef(BufferDefaultType bo) {
+  return tbm_bo_ref(bo);
+}
+void TBMInterface::BoUnRef(BufferDefaultType bo) { tbm_bo_unref(bo); }
+
+int TBMInterface::BoSize(BufferDefaultType bo) { return tbm_bo_size(bo); }
+
+BufferUnionHandleType TBMInterface::BoGetHandle(BufferDefaultType bo,
+                                                int device) {
+  return tbm_bo_get_handle(bo, device);
+}
+
+BufferUnionHandleType TBMInterface::BoMap(BufferDefaultType bo, int device,
+                                          int option) {
+  return tbm_bo_map(bo, device, option);
+}
+
+void TBMInterface::BoUnmap(BufferDefaultType bo) { tbm_bo_unmap(bo); }
+
+BufferKeyType TBMInterface::BoExport(BufferDefaultType bo) {
+  return tbm_bo_export(bo);
+}
+
+BufferDefaultType TBMInterface::BoAlloc(tbm_bufmgr bufmgr, int size, int flag) {
+  return tbm_bo_alloc(bufmgr, size, flag);
+}
+BufferDefaultType TBMInterface::BoImport(tbm_bufmgr bufmgr, BufferKeyType key) {
+  return tbm_bo_import(bufmgr, key);
+}
+
+int TBMInterface::GAScale(tbm_bufmgr bufmgr, GraphicsGAScaleInfo* info) {
+  return Gfx_GA_Scale(bufmgr, info);
+}
+
+int TBMInterface::GACopy(tbm_bufmgr bufmgr, GraphicsGABltRopInfo* info) {
+  return Gfx_GA_BltRop(bufmgr, info);
+}
+
+int TBMInterface::GAFill(tbm_bufmgr bufmgr, GraphicsGAFillRectInfo* info) {
+  return Gfx_GA_FillRect(bufmgr, info);
+}
+}  // namespace tizen
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/tizen/tizenaccessiblebufferobj.cpp b/src/mixer/src/tizen/tizenaccessiblebufferobj.cpp
new file mode 100644 (file)
index 0000000..55c7366
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/tizen/tizenaccessiblebufferobj.h"
+
+namespace esplusplayer {
+
+TizenAccessibleBufferObject::TizenAccessibleBufferObject(
+    BufferDefaultType buffer)
+    : TizenBufferObject(buffer) {}
+
+TizenAccessibleBufferObject::PhyAddrAccessorPtr
+TizenAccessibleBufferObject::GetReadableAddress() const {
+  if (IsValid() == false) return nullptr;
+  return PhyAddrAccessorPtr(
+      new TizenReadableBufferPhyAddrAccessor(GetBuffer_()));
+}
+
+TizenAccessibleBufferObject::PhyAddrAccessorPtr
+TizenAccessibleBufferObject::GetWritableAddress() const {
+  if (IsValid() == false) return nullptr;
+  return PhyAddrAccessorPtr(
+      new TizenWritableBufferPhyAddrAccessor(GetBuffer_()));
+}
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/tizen/tizenbufferkeyvideoframe.cpp b/src/mixer/src/tizen/tizenbufferkeyvideoframe.cpp
new file mode 100644 (file)
index 0000000..571df3e
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/tizen/tizenbufferkeyvideoframe.h"
+
+namespace esplusplayer {
+
+// LCOV_EXCL_START
+TizenBufferKeyVideoFrame::TizenBufferKeyVideoFrame(
+    const TizenBufferManager* const bufmgr, const BufferKeyType& key,
+    const std::uint32_t& width, const std::uint32_t& height)
+    : key_(key), width_(width), height_(height) {
+  if (bufmgr == nullptr) return;
+  if (key_ == 0) return;
+  if (width_ == 0 || height_ == 0) return;
+
+  auto buffer = BufferObjectPtr(bufmgr->Import(key_));
+  if (buffer == nullptr) return;
+  RegisterVideoPlaneManipulablePtr_(VideoPlaneManipulablePtr(
+      new YComponentVideoPlaneWithSharedMemory(buffer, width_, height_)));
+  RegisterVideoPlaneManipulablePtr_(VideoPlaneManipulablePtr(
+      new UVComponentVideoPlaneWithSharedMemory(buffer, width_, height_)));
+}
+
+bool TizenBufferKeyVideoFrame::IsValid_() const {
+  if (key_ == 0) return false;
+  return true;
+}
+
+const std::uint32_t TizenBufferKeyVideoFrame::GetWidth_() const {
+  return width_;
+}
+
+const std::uint32_t TizenBufferKeyVideoFrame::GetHeight_() const {
+  return height_;
+}
+// LCOV_EXCL_STOP
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/tizen/tizendefaultphyaddraccessor.cpp b/src/mixer/src/tizen/tizendefaultphyaddraccessor.cpp
new file mode 100644 (file)
index 0000000..b18cd22
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/tizen/tizendefaultphyaddraccessor.h"
+
+namespace esplusplayer {
+
+TizenDefaultPhyAddrAccessor::TizenDefaultPhyAddrAccessor(std::uint32_t viraddr)
+    : viraddr_(viraddr) {}
+
+BufferPhysicalAddrType TizenDefaultPhyAddrAccessor::GetAddress() {
+  return reinterpret_cast<BufferPhysicalAddrType>(viraddr_);
+}
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/tizen/tizenhwbufferobj.cpp b/src/mixer/src/tizen/tizenhwbufferobj.cpp
new file mode 100644 (file)
index 0000000..cd80735
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/tizen/tizenhwbufferobj.h"
+
+// #include "mixer/tizen/tizendefaultphyaddraccessor.h"
+
+namespace esplusplayer {
+// LCOV_EXCL_START
+TizenHWBufferObject::TizenHWBufferObject(const std::uint32_t& width,
+                                         const std::uint32_t& height,
+                                         const DecodedRawPlaneInfo& info)
+    : width_(width), height_(height), info_(info) {}
+
+bool TizenHWBufferObject::IsValid() const {
+  if (info_.phyaddr == 0) return false;
+  if (width_ == 0 || height_ == 0 || info_.linesize == 0) return false;
+  return true;
+}
+
+BufferHandleType TizenHWBufferObject::GetBufferHandle() const {
+  if (IsValid() == false) return kInvalidBufferHandle;
+  return static_cast<BufferHandleType>(info_.phyaddr);
+}
+
+BufferKeyType TizenHWBufferObject::Export() const { return kInvalidBufferKey; }
+
+std::uint32_t TizenHWBufferObject::GetSize() const {
+  return height_ * info_.linesize;
+}
+// LCOV_EXCL_STOP
+}  // namespace esplusplayer
diff --git a/src/mixer/src/tizen/tizenhwvideoframe.cpp b/src/mixer/src/tizen/tizenhwvideoframe.cpp
new file mode 100644 (file)
index 0000000..ebdd66d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/tizen/tizenhwvideoframe.h"
+
+#include "core/utils/plusplayer_log.h"
+#include "mixer/tizen/tizenhwbufferobj.h"
+#include "mixer/videoplane.h"
+
+namespace esplusplayer {
+
+// LCOV_EXCL_START
+TizenHWVideoFrame::TizenHWVideoFrame(const DecodedRawInfo& info) : info_(info) {
+  if (IsValid_() == false) return;
+
+  RegisterVideoPlaneManipulablePtr_(VideoPlaneManipulablePtr(
+      new YComponentVideoPlane(BufferObjectPtr(new TizenHWBufferObject(
+                                   info_.width, info_.height, info_.y_info)),
+                               info_.width, info_.height)));
+  RegisterVideoPlaneManipulablePtr_(
+      VideoPlaneManipulablePtr(new UVComponentVideoPlane(
+          BufferObjectPtr(new TizenHWBufferObject(
+              info_.width / 2, info_.height / 2, info_.uv_info)),
+          info_.width, info_.height)));
+}
+
+bool TizenHWVideoFrame::IsValid_() const {
+  if (info_.y_info.phyaddr == 0) return false;
+  if (info_.y_info.linesize == 0) return false;
+  if (info_.uv_info.phyaddr == 0) return false;
+  if (info_.uv_info.linesize == 0) return false;
+  return true;
+}
+
+const std::uint32_t TizenHWVideoFrame::GetWidth_() const { return info_.width; }
+
+const std::uint32_t TizenHWVideoFrame::GetHeight_() const {
+  return info_.height;
+}
+
+void TizenHWVideoFrame::PrintDecodedRawInfo() const {
+  LOG_DEBUG("WxH [%ux%u] Y [%u %u %u] / UV [%u %u %u]", info_.width,
+            info_.height, info_.y_info.phyaddr, info_.y_info.viraddr,
+            info_.y_info.linesize, info_.uv_info.phyaddr, info_.uv_info.viraddr,
+            info_.uv_info.linesize);
+}
+// LCOV_EXCL_STOP
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/tizen/tizenrenderableobj_factory.cpp b/src/mixer/src/tizen/tizenrenderableobj_factory.cpp
new file mode 100644 (file)
index 0000000..3533d7e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/tizen/tizenrenderableobj_factory.h"
+
+#include "mixer/mixedframe.h"
+
+namespace esplusplayer {
+
+TizenRenderableObjectFactory::TizenRenderableObjectFactory(
+    const MemoryAllocator* const memallocator)
+    : memallocator_(memallocator) {}
+
+RenderableObject* TizenRenderableObjectFactory::CreateRenderableObject(
+    const std::uint32_t width, const std::uint32_t height) const {
+  return new MixedFrame(memallocator_, width, height);
+}
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/tizen/tizensurfacevideoframe.cpp b/src/mixer/src/tizen/tizensurfacevideoframe.cpp
new file mode 100644 (file)
index 0000000..a36fe7a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/tizen/tizensurfacevideoframe.h"
+
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+
+#include "mixer/tizen/tizenbufferobj.h"
+#include "mixer/videoplane.h"
+
+namespace esplusplayer {
+
+// LCOV_EXCL_START
+TizenSurfaceVideoFrame::TizenSurfaceVideoFrame(DecodedVideoPacketExPtr dvp)
+    : dvp_(std::move(dvp)) {
+  auto surface = dvp_->GetTbmSurface();
+  if (surface == nullptr) return;
+
+  width_ = tbm_surface_get_width(surface);
+  height_ = tbm_surface_get_height(surface);
+  if (width_ == 0 || height_ == 0) return;
+
+  auto y_bo = tbm_surface_internal_get_bo(surface, kYIndex);
+  auto uv_bo = tbm_surface_internal_get_bo(surface, kUVIndex);
+  if (y_bo == nullptr || uv_bo == nullptr) return;
+
+  RegisterVideoPlaneManipulablePtr_(
+      VideoPlaneManipulablePtr(new YComponentVideoPlane(
+          BufferObjectPtr(new TizenBufferObject(y_bo)), width_, height_)));
+  RegisterVideoPlaneManipulablePtr_(
+      VideoPlaneManipulablePtr(new UVComponentVideoPlane(
+          BufferObjectPtr(new TizenBufferObject(uv_bo)), width_, height_)));
+}
+
+bool TizenSurfaceVideoFrame::IsValid_() const {
+  if (dvp_ == nullptr) return false;
+  return true;
+}
+
+const std::uint32_t TizenSurfaceVideoFrame::GetWidth_() const { return width_; }
+
+const std::uint32_t TizenSurfaceVideoFrame::GetHeight_() const {
+  return height_;
+}
+// LCOV_EXCL_STOP
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/mixer/src/videoplane.cpp b/src/mixer/src/videoplane.cpp
new file mode 100644 (file)
index 0000000..43c1498
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mixer/videoplane.h"
+
+#include "core/utils/plusplayer_log.h"
+
+namespace esplusplayer {
+
+// LCOV_EXCL_START
+/******************************************************************************
+ * VideoPlane
+ */
+VideoPlane::VideoPlane(PlaneComponent component, const std::uint32_t& width,
+                       const std::uint32_t& height)
+    : component_(component), width_(width), height_(height) {}
+
+bool VideoPlane::IsValid() const {
+  if (GetBufferObject_() == nullptr) return false;
+  if (width_ == 0 || height_ == 0 || GetLineSize_() == 0) return false;
+  return true;
+}
+
+VideoPlaneManipulableInfo VideoPlane::GetVideoPlaneManipulableInfo() const {
+  VideoPlaneManipulableInfo info;
+  info.component = component_;
+  info.handle = GetBufferObject_()->GetBufferHandle();
+  info.linesize = GetLineSize_();
+  info.rect.x = width_ * croparea_.scale_x;
+  info.rect.y = height_ * croparea_.scale_y;
+  info.rect.w = width_ * croparea_.scale_w;
+  info.rect.h = height_ * croparea_.scale_h;
+  return info;
+}
+
+void VideoPlane::SetCropArea(const CropArea& croparea) { croparea_ = croparea; }
+
+std::uint32_t VideoPlane::GetLineSize_() const {
+  return GetBufferObject_()->GetSize() / height_;
+}
+
+/******************************************************************************
+ * YComponentVideoPlane
+ */
+
+YComponentVideoPlane::YComponentVideoPlane(BufferObjectPtr buffer,
+                                           const std::uint32_t& width,
+                                           const std::uint32_t& height)
+    : VideoPlane(PlaneComponent::kYComponent, width, height),
+      buffer_(std::move(buffer)) {}
+
+const BufferObject* const YComponentVideoPlane::GetBufferObject_() const {
+  return buffer_.get();
+}
+
+/******************************************************************************
+ * UVComponentVideoPlane
+ */
+
+UVComponentVideoPlane::UVComponentVideoPlane(BufferObjectPtr buffer,
+                                             const std::uint32_t& width,
+                                             const std::uint32_t& height)
+    : VideoPlane(PlaneComponent::kUVComponent, width / 2, height / 2),
+      buffer_(std::move(buffer)) {}
+
+const BufferObject* const UVComponentVideoPlane::GetBufferObject_() const {
+  return buffer_.get();
+}
+
+/******************************************************************************
+ * YComponentVideoPlaneWithSharedMemory
+ */
+
+YComponentVideoPlaneWithSharedMemory::YComponentVideoPlaneWithSharedMemory(
+    BufferObjectWeakPtr buffer, const std::uint32_t& width,
+    const std::uint32_t& height)
+    : VideoPlane(PlaneComponent::kYComponent, width, height),
+      buffer_(buffer),
+      width_(width) {}
+
+std::uint32_t YComponentVideoPlaneWithSharedMemory::GetLineSize_() const {
+  return width_;
+}
+
+const BufferObject* const
+YComponentVideoPlaneWithSharedMemory::GetBufferObject_() const {
+  return buffer_.get();
+}
+
+/******************************************************************************
+ * UVComponentVideoPlaneWithSharedMemory
+ */
+
+UVComponentVideoPlaneWithSharedMemory::UVComponentVideoPlaneWithSharedMemory(
+    BufferObjectWeakPtr buffer, const std::uint32_t& width,
+    const std::uint32_t& height)
+    : VideoPlane(PlaneComponent::kUVComponent, width / 2, height / 2),
+      buffer_(buffer),
+      width_(width),
+      height_(height) {}
+
+VideoPlaneManipulableInfo
+UVComponentVideoPlaneWithSharedMemory::GetVideoPlaneManipulableInfo() const {
+  auto info = VideoPlane::GetVideoPlaneManipulableInfo();
+  info.rect.y += height_;
+  return info;
+}
+
+std::uint32_t UVComponentVideoPlaneWithSharedMemory::GetLineSize_() const {
+  return width_;
+}
+
+const BufferObject* const
+UVComponentVideoPlaneWithSharedMemory::GetBufferObject_() const {
+  return buffer_.get();
+}
+// LCOV_EXCL_STOP
+
+}  // namespace esplusplayer
\ No newline at end of file
diff --git a/src/plusplayer-core/Build/appendix.mk b/src/plusplayer-core/Build/appendix.mk
new file mode 100644 (file)
index 0000000..fad5ae4
--- /dev/null
@@ -0,0 +1 @@
+# Appendix
diff --git a/src/plusplayer-core/Build/basedef.mk b/src/plusplayer-core/Build/basedef.mk
new file mode 100644 (file)
index 0000000..a762983
--- /dev/null
@@ -0,0 +1,34 @@
+# Add inputs and outputs from these tool invocations to the build variables
+
+
+OS_NAME := $(shell $(UNAME))
+
+
+#ifeq ($(origin BUILD_CONFIG), undefined)
+BUILD_CONFIG ?= Debug
+#endif
+
+#ifeq ($(origin ARCH), undefined)
+ARCH ?= i386
+#endif
+
+#ifeq ($(origin PROJPATH), undefined)
+PROJPATH ?= .
+#endif
+
+
+#ifeq ($(origin PROJ_PATH), undefined)
+PROJ_PATH ?= $(PROJPATH)
+#endif
+
+#ifeq ($(strip $(OUTPUT_DIR)),)
+#OUTPUT_DIR ?= $(PROJ_PATH)/$(BUILD_CONFIG)
+#endif
+
+#ifeq ($(strip $(BUILD_ARCH)),)
+BUILD_ARCH ?= $(ARCH)
+#endif
+
+#ifeq ($(strip $(ENVENTOR_PATH)),)
+ENVENTOR_PATH ?= $(SDK_TOOLPATH)/enventor
+#endif
diff --git a/src/plusplayer-core/Build/build_c.mk b/src/plusplayer-core/Build/build_c.mk
new file mode 100644 (file)
index 0000000..5fffeea
--- /dev/null
@@ -0,0 +1,113 @@
+# C/C++ build script
+
+
+_FUNC_EXT2O = $(patsubst %.$(3),$(1)/%.o,$(2))
+_FUNC_C2O = $(call _FUNC_EXT2O,$(1),$(2),c)
+_FUNC_CPP2O = $(call _FUNC_EXT2O,$(1),$(2),cpp)
+
+
+# parameter :
+#  $(1) - C/C++ soruce file
+#  $(2) - output path
+#  $(3) - .ext
+#  $(4) - unique id
+CONVERT_ESC_EXT_TO_O = $(addprefix $(2)/,$(notdir $(patsubst %.$(3),%-$(4).o,$(1))))
+
+#CONVERT_ESC_C_TO_O = $(call CONVERT_ESC_EXT_TO_O,$(1),$(2),c)
+#CONVERT_ESC_CPP_TO_O = $(call CONVERT_ESC_EXT_TO_O,$(1),$(2),cpp)
+
+
+# parameter :
+#  $(1) - encoded one C/C++ soruce file
+#  $(2) - output path
+#  $(3) - ext title (C/C++)
+#  $(4) - ext (c/cpp)
+#  $(5) - compiler ($(CC)/$(CXX))
+#  $(6) - build opt
+#  $(7) - build opt file
+# output :
+#  $(8) - output files list
+define C_BUILD_PROC_RAW
+$(call CONVERT_ESC_EXT_TO_O,$(1),$(2),$(4),$(8)) : $(call DECODE_4MAKE,$(1)) $(7)
+       @echo '  Building file: $$<'
+       @echo '  Invoking: $(3) Compiler'
+       $$(call MAKEDIRS,$$(@D))
+       $(5) -c "$$<" -o "$$@" $(6) -Wp,@$(7)
+       @echo '  Finished building: $$<'
+$(9) += $(call CONVERT_ESC_EXT_TO_O,$(1),$(2),$(4),$(8))
+endef
+
+
+# parameter :
+#  $(1) - output paths
+#  $(2) - src paths
+#  $(3) - inc paths
+#  $(4) - inc files
+#  $(5) - Defs
+#  $(6) - UnDefs
+#  $(7) - compiler opt
+#  $(8) - compiler opt file
+#  $(9) - ext title (C/C++)
+#  $(10) - ext (c/cpp)
+#  $(11) - compiler ($(CC)/$(CXX))
+# output :
+#  $(12) - OBJS
+# return :
+#  none
+define C_PROC_RAW
+
+_OUTPUT_DIR := $$(strip $(1))#
+_SRCS := $(2)#
+_INCS := $(3)#
+_INC_FILES := $(4)#
+_DEFS := $(5)#
+_UNDEFS := $(6)#
+
+_OPT := $(7)
+_OPT_FILE := $(8)
+
+_EXT_TITLE := $(9)
+_EXT := $(10)
+_COMPILER := $(11)
+
+#_OUTPUT_FILES := $(12)
+
+_ENC_SRCS := $$(call ENCODE_4MAKE,$$(_SRCS))
+_ENC_SRCS := $$(filter %.$$(_EXT),$$(_ENC_SRCS))
+
+ifneq ($$(strip $$(_SRCS)),)
+
+_NORMAL_SRCS := $$(filter-out %*.$$(_EXT),$$(_ENC_SRCS))
+_WIDLCARD_SRCS := $$(filter %*.$$(_EXT),$$(_ENC_SRCS))
+
+_ALL_SRCS := $$(call DECODE_4MAKE,$$(_NORMAL_SRCS)) \
+             $$(foreach var,$$(_WIDLCARD_SRCS),$$(call FIND_FILES_4MAKE,$$(call DECODE_4MAKE,$$(var))))
+
+ifneq ($$(strip $$(_ALL_SRCS)),)
+
+_ENC_SRCS := $$(call ENCODE_4MAKE,$$(_ALL_SRCS))
+
+_CDEFS := $$(CDEFS)
+_CDEFS += $$(addprefix -D,$$(_DEFS))
+_CDEFS += $$(addprefix -U,$$(_UNDEFS))
+
+_ENC_C_INCS := $$(call ENCODE_4MAKE,$$(_INCS))
+_ENC_C_INCS := $$(addprefix -I,$$(_ENC_C_INCS))
+
+_ENC_INC_FILES := $$(call ENCODE_4MAKE,$$(_INC_FILES))
+_ENC_INC_FILES += $$(addprefix -include,$$(_ENC_INC_FILES))
+
+_C_INCS := $$(call DECODE_4MAKE,$$(_ENC_C_INCS) $$(_ENC_C_INC_FILES))
+
+_DEFS := $$(_CDEFS) $$(_C_INCS) -I"pch" $$(_OPT)
+
+_UNIQUE_ID = $$(firstword $$(shell echo $$(var) | $$(CKSUM)))
+
+$$(foreach var,$$(_ENC_SRCS),$$(eval $$(call C_BUILD_PROC_RAW,$$(var),$$(_OUTPUT_DIR),$$(_EXT_TITLE),$$(_EXT),$$(_COMPILER),$$(_DEFS),$$(_OPT_FILE),$$(_UNIQUE_ID),$(12))))
+
+endif  # (_(strip _(_ALL_SRCS)),)
+
+endif  # (_(strip _(_SRCS)),)
+
+
+endef
diff --git a/src/plusplayer-core/Build/build_edc.mk b/src/plusplayer-core/Build/build_edc.mk
new file mode 100644 (file)
index 0000000..6f85fdd
--- /dev/null
@@ -0,0 +1,81 @@
+# EDC build script
+
+
+FUNC_EDC2EDJ = $(patsubst %.edc,$(2)/%.edj,$(1))
+
+# parameter :
+#  $(1) - C/C++ soruce file
+#  $(2) - output path
+CONVERT_ESC_EDC_TO_EDJ = $(call CONVERT_4MAKE_TO_OUT,$(call FUNC_EDC2EDJ,$(1),$(2)))
+
+
+# parameter :
+#  $(1) - encoded one C/C++ soruce file
+#  $(2) - output path
+#  $(3) - build opt
+# output :
+#  $(4) - output files list
+define EDJ_BUILD_PROC_RAW
+$(call CONVERT_ESC_EDC_TO_EDJ,$(1),$(2)) : $(call DECODE_4MAKE,$(1))
+       @echo '  Building file: $$<'
+       @echo '  Invoking: EDC Resource Compiler'
+       $$(call MAKEDIRS,$$(@D))
+       $$(EDJE_CC) $(3) "$$<" "$$@"
+       @echo '  Finished building: $$<'
+$(4) += $(call CONVERT_ESC_EDC_TO_EDJ,$(1),$(2))
+endef
+
+
+# parameter :
+#  $(1) - output paths
+#  $(2) - src paths
+#  $(3) - image inc paths
+#  $(4) - sound inc paths
+#  $(5) - font inc paths
+# output :
+#  $(6) - OBJS 
+# return :
+#  none
+define EDJ_PROC_RAW
+
+_OUTPUT_DIR := $$(strip $(1))#
+_SRCS := $(2)# 
+_IMAGE_DIRS := $(3)# 
+_SOUND_DIRS := $(4)# 
+_FONT_DIRS := $(5)# 
+
+ifneq ($$(strip $$(_SRCS)),)
+
+_ENC_SRCS := $$(call ENCODE_4MAKE,$$(_SRCS)) 
+
+_NORMAL_SRCS := $$(filter-out %*.edc,$$(_ENC_SRCS))
+_WIDLCARD_SRCS := $$(filter %*.edc,$$(_ENC_SRCS))
+
+_ALL_SRCS := $$(call DECODE_4MAKE,$$(_NORMAL_SRCS)) \
+             $$(foreach var,$$(_WIDLCARD_SRCS),$$(call FIND_FILES_4MAKE,$$(call DECODE_4MAKE,$$(var))))
+
+ifneq ($$(strip $$(_ALL_SRCS)),)
+
+_ENC_SRCS := $$(call ENCODE_4MAKE,$$(_ALL_SRCS)) 
+
+_COMPILER_FLAGS := -id "$$(ENVENTOR_SHARED_RES_PATH)/images"
+_COMPILER_FLAGS += -sd "$$(ENVENTOR_SHARED_RES_PATH)/sounds"
+_COMPILER_FLAGS += -fd "$$(ENVENTOR_SHARED_RES_PATH)/fonts"
+
+ifneq ($$(strip $$(_IMAGE_DIRS)),)
+_COMPILER_FLAGS += $$(addprefix -id ,$$(_IMAGE_DIRS))
+endif
+ifneq ($$(strip $$(_SOUND_DIRS)),)
+_COMPILER_FLAGS += $$(addprefix -sd ,$$(_SOUND_DIRS))
+endif
+ifneq ($$(strip $$(_FONT_DIRS)),)
+_COMPILER_FLAGS += $$(addprefix -fd ,$$(_FONT_DIRS))
+endif
+
+$$(foreach var,$$(_ENC_SRCS),$$(eval $$(call EDJ_BUILD_PROC_RAW,$$(var),$$(_OUTPUT_DIR),$$(_COMPILER_FLAGS),$(6))))
+
+endif  # (_(strip _(_ALL_SRCS)),)
+
+endif  # (_(strip _(_SRCS)),)
+
+endef
diff --git a/src/plusplayer-core/Build/build_po.mk b/src/plusplayer-core/Build/build_po.mk
new file mode 100644 (file)
index 0000000..d88d71a
--- /dev/null
@@ -0,0 +1,64 @@
+# PO build script
+
+
+_FUNC_PO2MO = $(patsubst %.po,$(2)/res/locale/%/LC_MESSAGES/$(3).mo,$(notdir $(1)))
+
+
+# parameter :
+#  $(1) - C/C++ soruce file
+#  $(2) - output path
+#  $(3) - app name
+CONVERT_ESC_PO_TO_MO = $(call CONVERT_4MAKE_TO_OUT,$(call _FUNC_PO2MO,$(1),$(2),$(3)))
+
+
+# parameter :
+#  $(1) - encoded one C/C++ soruce file
+#  $(2) - output path
+#  $(3) - app name
+# output :
+#  $(4) - output files list
+define MO_BUILD_PROC_RAW
+$(call CONVERT_ESC_PO_TO_MO,$(1),$(2),$(3)) : $(call DECODE_4MAKE,$(1))
+       @echo '  Building file: $$<'
+       @echo '  Invoking: msgfmt String Formatter'
+       $$(call MAKEDIRS,$$(@D))
+       $$(MSGFMT) -o "$$@" "$$<"
+       @echo '  Finished building: $$<'
+$(4) += $(call CONVERT_ESC_PO_TO_MO,$(1),$(2),$(3))
+endef
+
+# parameter :
+#  $(1) - output dir
+#  $(2) - src paths
+#  $(3) - app name
+# output :
+#  $(4) - OBJS 
+
+define MO_PROC_RAW
+
+_OUTPUT_DIR := $(1)
+_SRCS := $(2)
+_APPNAME := $(3)
+
+ifneq ($$(strip $$(_SRCS)),)
+
+_ENC_SRCS := $$(call ENCODE_4MAKE,$$(_SRCS)) 
+
+_NORMAL_SRCS := $$(filter-out %*.po,$$(_ENC_SRCS))
+_WIDLCARD_SRCS := $$(filter %*.po,$$(_ENC_SRCS))
+
+_ALL_SRCS := $$(call DECODE_4MAKE,$$(_NORMAL_SRCS)) \
+             $$(foreach var,$$(_WIDLCARD_SRCS),$$(call FIND_FILES_4MAKE,$$(call DECODE_4MAKE,$$(var))))
+
+ifneq ($$(strip $$(_ALL_SRCS)),)
+
+_ENC_SRCS := $$(call ENCODE_4MAKE,$$(_ALL_SRCS)) 
+
+$$(foreach var,$$(_ENC_SRCS),$$(eval $$(call MO_BUILD_PROC_RAW,$$(var),$$(_OUTPUT_DIR),$$(_APPNAME),$(4))))
+
+endif  # (_(strip _(_ALL_SRCS)),)
+
+endif  # (_(strip _(_SRCS)),)
+
+endef
diff --git a/src/plusplayer-core/Build/flags.mk b/src/plusplayer-core/Build/flags.mk
new file mode 100644 (file)
index 0000000..967a0cc
--- /dev/null
@@ -0,0 +1,23 @@
+ifeq ($(strip $(BUILD_CONFIG)),Debug)
+DEBUG_OP = -g2
+CPP_DEBUG_OP = -g2
+
+OPTIMIZATION_OP = -O1
+CPP_OPTIMIZATION_OP = -O1
+else
+DEBUG_OP = -g0
+CPP_DEBUG_OP = -g0
+
+OPTIMIZATION_OP = -O2
+CPP_OPTIMIZATION_OP = -O2
+endif
+
+COMPILE_FLAGS = $(CFLAGS) $(DEBUG_OP) $(OPTIMIZATION_OP) 
+
+CPP_COMPILE_FLAGS = $(CXXFLAGS) $(CPP_DEBUG_OP) $(CPP_OPTIMIZATION_OP) -Wall -Werror -std=c++11 -w -c -fmessage-length=0 -DPLUPLAYER_DOWNLOADABLE_APP_TVPLUS -fPIC 
+
+LINK_FLAGS = $(CFLAGS) -shared -Wl,-z,relro 
+
+AR_FLAGS = 
+
+EDC_COMPILE_FLAGS = 
diff --git a/src/plusplayer-core/Build/funcs.mk b/src/plusplayer-core/Build/funcs.mk
new file mode 100644 (file)
index 0000000..3ba778b
--- /dev/null
@@ -0,0 +1,50 @@
+
+BSLASH := \\#
+NULL_CHAR := #
+SPACE := \ #
+COLON := :#
+DOTDOT := ..#
+SPACE_ESC := &sp;#
+COLON_ESC := &co;#
+SPACE_OUT := ~sp~#
+COLON_OUT := ~co~#
+DOTDOT_OUT := ~dtdt~#
+
+BSLASH2SLASH = $(subst $(BSLASH),/,$(1))
+
+REMOVE_TAIL = $(patsubst %/,%,$(1))
+
+#LOWER_CASE = $(shell echo translit($(1),[A-Z],[a-z])|$(M4))
+LOWER_CASE = $(shell echo $(1)|$(TR) [A-Z] [a-z])
+
+#ifneq ($(findstring Windows,$(OS)),)
+# ...
+#endif
+
+FIND_FILES = $(shell $(FIND) $(1)/$(2) | $(SED) 's/^$(subst /,$(BSLASH)/,$(1))$(BSLASH)///')
+FIND_FILES_ESC = $(shell $(FIND) $(1)/$(2) | $(SED) 's/^$(subst /,$(BSLASH)/,$(1))$(BSLASH)///' -e 's/:/$(BSLASH)&co;/g' -e 's/$(BSLASH) /$(BSLASH)&sp;/g')
+FIND_FILES_4MAKE = $(shell $(FIND) $(1)/$(2) | $(SED) 's/^$(subst /,$(BSLASH)/,$(1))$(BSLASH)///')
+
+FIND_FILES_ABS = $(shell $(FIND) $(1))
+FIND_FILES_ABS_4MAKE = $(shell $(FIND) $(1) -e 's/$(BSLASH) /$(BSLASH)&sp;/g')
+FIND_FILES_ABS_ESC = $(shell $(FIND) $(1) -e 's/:/$(BSLASH)&co;/g' -e 's/$(BSLASH) /$(BSLASH)&sp;/g')
+
+FIND_FILES_4MAKE = $(shell $(FIND) $(1) | $(SED) 's/ /\\\ /g')
+
+#ENCODE_ESC = $(shell echo $(1) | $(SED) -e 's/:/$(BSLASH)&co;/g' -e 's/$(BSLASH) /$(BSLASH)&sp;/g')
+#DECODE_ESC = $(shell echo $(1) | $(SED) -e 's/$(BSLASH)&co;/:/g' -e 's/$(BSLASH)&sp;/$(BSLASH) / g')
+ENCODE_ESC = $(subst $(SPACE),$(SPACE_ESC),$(subst $(COLON),$(COLON_ESC),$(1)))
+DECODE_ESC = $(subst $(COLON_ESC),$(COLON),$(subst $(SPACE_ESC),$(SPACE),$(1)))
+ENCODE_4MAKE = $(subst $(SPACE),$(SPACE_ESC),$(1))
+DECODE_4MAKE = $(subst $(SPACE_ESC),$(SPACE),$(1))
+
+CONVERT_TO_OUT = $(subst $(DOTDOT),$(DOTDOT_OUT),$(subst $(COLON),$(COLON_OUT),$(subst $(SPACE),$(SPACE_OUT),$(1))))
+CONVERT_ESC_TO_OUT = $(subst $(DOTDOT),$(DOTDOT_OUT),$(subst $(COLON_ESC),$(COLON_OUT),$(subst $(SPACE_ESC),$(SPACE_OUT),$(1))))
+CONVERT_4MAKE_TO_OUT = $(subst $(DOTDOT),$(DOTDOT_OUT),$(subst $(COLON),$(COLON_OUT),$(subst $(SPACE_ESC),$(SPACE_OUT),$(1))))
+
+PROC_NO_EXIST = $(if $(wildcard $(1)),,$(call $(2),$(1)))
+define MAKEDIRS0
+       @echo '  Building directory: $(1)'
+       @$(MKDIR) $(MKDIR_OP) $(subst $(BSLASH),/,$(1))
+endef
+MAKEDIRS = $(call PROC_NO_EXIST,$(1),MAKEDIRS0)
diff --git a/src/plusplayer-core/Build/makefile b/src/plusplayer-core/Build/makefile
new file mode 100644 (file)
index 0000000..117b240
--- /dev/null
@@ -0,0 +1,34 @@
+# 
+# Usege : make -f <proj_root>/Build/makefile -C <proj_root> 
+#
+BUILD_SCRIPT_VERSION := 1.1.0
+
+.PHONY : app_version app_build app_clean build_version
+
+
+all : app_build
+
+clean : app_clean
+
+version : build_version
+
+#PROJ_ROOT = .
+#BUILD_ROOT := $(PROJ_PATH)/Build#
+
+ifeq ($(MAKE_NAME),mingw32-make)
+ifneq ($(SHELL),)
+OPTIONS += --eval="SHELL=$(SHELL)"
+endif
+endif
+
+app_build :
+       @echo $(MAKE) -f "$(BUILD_ROOT)/makefile.mk"
+       @$(MAKE_BIN) -f "$(BUILD_ROOT)/makefile.mk" -C "$(PROJ_PATH)" $(OPTIONS)
+
+app_clean :
+       @$(MAKE) -f "$(BUILD_ROOT)/makefile.mk" -C "$(PROJ_PATH)" $(OPTIONS) clean
+
+build_version :
+       @echo makefile : $(BUILD_SCRIPT_VERSION)
+       @$(MAKE) -f "$(BUILD_ROOT)/makefile.mk" -C "$(PROJ_PATH)" $(OPTIONS) version
diff --git a/src/plusplayer-core/Build/makefile.mk b/src/plusplayer-core/Build/makefile.mk
new file mode 100644 (file)
index 0000000..4b93f37
--- /dev/null
@@ -0,0 +1,206 @@
+#
+# Usege : make -f <proj_root>/Build/makefile -C <proj_root>
+#
+
+BUILD_SCRIPT_VERSION := 1.2.3
+
+.PHONY : app_version app_clean build_version
+
+
+all : app_build
+
+clean : app_clean
+
+version : build_version
+
+_BLANK :=#
+_SPACE := $(_BLANK) $(_BLANK)#
+_SPACE_4MAKE := \$(_SPACE)#
+
+NULL_CHAR :=#
+SPACE := $(NULL_CHAR) $(NULL_CHAR)#
+
+PROJ_ROOT := .
+_PROJ_ROOT_4MAKE := $(subst $(_SPACE),$(_SPACE_4MAKE),$(PROJ_ROOT))#
+PROJ_ROOT=$(_PROJ_ROOT_4MAKE)
+_BUILD_ROOT_4MAKE := $(subst $(_SPACE),$(_SPACE_4MAKE),$(BUILD_ROOT))#
+BUILD_ROOT=$(_BUILD_ROOT_4MAKE)
+
+include $(BUILD_ROOT)/basedef.mk
+
+include $(PROJ_ROOT)/project_def.prop
+-include $(PROJ_ROOT)/build_def.prop
+
+include $(BUILD_ROOT)/funcs.mk
+
+-include $(BUILD_ROOT)/tooldef.mk
+-include $(BUILD_ROOT)/flags.mk
+-include $(BUILD_ROOT)/platform.mk
+
+
+APPTYPE := $(type)
+
+OUTPUT_DIR := $(PROJ_ROOT)/$(BUILD_CONFIG)
+OBJ_OUTPUT := $(OUTPUT_DIR)/objs
+
+LOWER_APPNAME := $(call LOWER_CASE,$(APPNAME))
+APPID2 := $(subst $(basename $(APPID)).,,$(APPID))
+
+ifeq ($(strip $(APPTYPE)),app)
+APPFILE := $(OUTPUT_DIR)/$(LOWER_APPNAME)
+endif
+ifeq ($(strip $(APPTYPE)),staticLib)
+APPFILE := $(OUTPUT_DIR)/lib$(LOWER_APPNAME).a
+endif
+ifeq ($(strip $(APPTYPE)),sharedLib)
+APPFILE := $(OUTPUT_DIR)/lib$(LOWER_APPNAME).so
+endif
+
+ifneq ($(strip $(PLATFORM_INCS)),)
+PLATFORM_INCS_FILE := $(OBJ_OUTPUT)/platform_incs_file.inc
+endif
+
+include $(BUILD_ROOT)/build_c.mk
+
+
+ifeq ($(strip $(APPTYPE)),app)
+EXT_OP := -fPIE
+endif
+ifeq ($(strip $(APPTYPE)),staticLib)
+EXT_OP := -fPIE
+endif
+ifeq ($(strip $(APPTYPE)),sharedLib)
+EXT_OP := -fPIC
+endif
+
+C_OPT := $(COMPILE_FLAGS) $(TC_COMPILER_MISC) $(RS_COMPILER_MISC) $(EXT_OP) --sysroot="$(SYSROOT)" -Werror-implicit-function-declaration $(M_OPT) $(USER_C_OPTS)
+CPP_OPT := $(CPP_COMPILE_FLAGS) $(TC_COMPILER_MISC) $(RS_COMPILER_MISC) $(EXT_OP) --sysroot="$(SYSROOT)" -Werror-implicit-function-declaration $(M_OPT) $(USER_CPP_OPTS)
+C_OPT_FILE := $(PLATFORM_INCS_FILE)
+
+OBJS := #
+
+# Global C/C++
+ifeq ($(strip $(USER_ROOT)),)
+USER_ROOT := $(PROJ_ROOT)
+endif
+$(eval $(call C_PROC_RAW,$(OBJ_OUTPUT),$(USER_SRCS),$(USER_INC_DIRS),$(USER_INC_FILES),$(USER_DEFS),$(USER_UNDEFS),$(C_OPT),$(C_OPT_FILE),C,c,$(CC),OBJS))
+$(foreach ext,cpp cxx cc c++ C,$(eval $(call C_PROC_RAW,$(OBJ_OUTPUT),$(USER_SRCS),$(USER_INC_DIRS),$(USER_CPP_INC_FILES),$(USER_CPP_DEFS),$(USER_CPP_UNDEFS),$(CPP_OPT),$(C_OPT_FILE),C++,$(ext),$(CXX),OBJS)))
+
+# Individual C/C++
+ifneq ($(strip $(USER_EXT_C_KEYS)),)
+$(foreach var,$(USER_EXT_C_KEYS),$(eval $(call C_PROC_RAW,$(OBJ_OUTPUT),$(USER_EXT_$(var)_SRCS),$(USER_EXT_$(var)_INC_DIRS),$(USER_EXT_$(var)_INC_FILES),$(USER_EXT_$(var)_DEFS),$(USER_EXT_$(var)_UNDEFS),$(C_OPT),$(C_OPT_FILE),C,c,$(CC),OBJS)))
+$(foreach ext,cpp cxx cc c++ C,$(foreach var,$(USER_EXT_C_KEYS),$(eval $(call C_PROC_RAW,$(OBJ_OUTPUT),$(USER_EXT_$(var)_SRCS),$(USER_EXT_$(var)_INC_DIRS),$(USER_EXT_$(var)_CPP_INC_FILES),$(USER_EXT_$(var)_CPP_DEFS),$(USER_EXT_$(var)_CPP_UNDEFS),$(CPP_OPT),$(C_OPT_FILE),C++,$(ext),$(CXX),OBJS))))
+endif
+
+
+ifneq ($(strip $(USER_LIB_DIRS)),)
+_ENC_USER_LIB_DIRS := $(call ENCODE_4MAKE,$(USER_LIB_DIRS))
+_ENC_USER_LIB_DIRS := $(addprefix -L,$(_ENC_USER_LIB_DIRS))
+LIBPATHS := $(call DECODE_4MAKE,$(_ENC_USER_LIB_DIRS))
+endif
+
+LIBS += $(addprefix -l,$(USER_LIBS))
+
+UOBJS += $(USER_OBJS)
+
+M_OPT = -MMD -MP -MF"$(@:%.o=%.d)"
+
+DEPS := $(OBJS:.o=.d)
+
+ifneq ($(strip $(DEPS)),)
+-include $(PROJ_ROOT)/Build/$(DEPS)
+endif
+
+
+ifeq ($(strip $(APPTYPE)),app)
+$(APPFILE) : $(OBJS) $(UOBJS)
+       @echo '  Building target: $@'
+       @echo '  Invoking: C/C++ Linker'
+       $(call MAKEDIRS,$(@D))
+#      $(CXX) -o $(APPFILE) $(OBJS) $(UOBJS) $(LIBPATHS) -Xlinker --as-needed $(LIBS) $(LINK_FLAGS) $(TC_LINKER_MISC) $(RS_LINKER_MISC) -pie -lpthread --sysroot="$(SYSROOT)" -Xlinker --version-script="$(PROJ_ROOT)/.exportMap" $(RS_LIB_PATHS) $(RS_LIBRARIES) -Xlinker -rpath='$$ORIGIN/../lib' -Werror-implicit-function-declaration $(USER_LINK_OPTS)
+       $(CXX) -o $(APPFILE) $(OBJS) $(UOBJS) $(LIBPATHS) -Xlinker $(LIBS) $(LINK_FLAGS) $(TC_LINKER_MISC) $(RS_LINKER_MISC) -pie -lpthread --sysroot="$(SYSROOT)" -Xlinker --version-script="$(PROJ_ROOT)/.exportMap" $(RS_LIB_PATHS) $(RS_LIBRARIES) -Xlinker -rpath='$$ORIGIN/../lib' -Werror-implicit-function-declaration $(USER_LINK_OPTS)
+       @echo '  Finished building target: $@'
+endif
+ifeq ($(strip $(APPTYPE)),staticLib)
+$(APPFILE) : $(OBJS) $(UOBJS)
+       @echo '  Building target: $@'
+       @echo '  Invoking: Archive utility'
+       $(call MAKEDIRS,$(@D))
+       $(AR) -r $(APPFILE) $(OBJS) $(UOBJS) $(AR_FLAGS) $(USER_LINK_OPTS)
+       @echo '  Finished building target: $@'
+endif
+ifeq ($(strip $(APPTYPE)),sharedLib)
+$(APPFILE) : $(OBJS) $(UOBJS)
+       @echo '  Building target: $@'
+       @echo '  Invoking: C/C++ Linker'
+       $(call MAKEDIRS,$(@D))
+       $(CXX) -o $(APPFILE) $(OBJS) $(UOBJS) $(LIBPATHS) -Xlinker --as-needed $(LIBS) $(LINK_FLAGS) $(TC_LINKER_MISC) $(RS_LINKER_MISC) -shared -lpthread --sysroot="$(SYSROOT)" $(RS_LIB_PATHS) $(RS_LIBRARIES) $(USER_LINK_OPTS)
+       @echo '  Finished building target: $@'
+endif
+
+
+$(OBJ_OUTPUT) :
+       $(call MAKEDIRS,$@)
+
+$(OUTPUT_DIR) :
+       $(call MAKEDIRS,$@)
+
+
+#ifneq ($(strip $(PLATFORM_INCS)),)
+#$(PLATFORM_INCS_FILE) : $(OBJ_OUTPUT)
+#      @echo '  Building inc file: $@'
+#ifneq ($(findstring Windows,$(OS)),)
+#ifneq ($(findstring 3.82,$(MAKE_VERSION)),)
+#      $(file > $@,$(PLATFORM_INCS))
+#else
+#      @echo $(PLATFORM_INCS) > $@
+#endif
+#else
+#      @echo '$(PLATFORM_INCS)' > $@
+#endif
+#endif
+
+
+include $(BUILD_ROOT)/build_edc.mk
+
+#ifeq ($(strip $(ENVENTOR_SHARED_RES_PATH)),)
+ENVENTOR_SHARED_RES_PATH ?= $(ENVENTOR_PATH)/share/enventor
+#endif
+
+EDJ_FILES :=
+
+# Global EDCs
+ifneq ($(strip $(USER_EDCS)),)
+$(eval $(call EDJ_PROC_RAW,$(OUTPUT_DIR),$(USER_EDCS),$(USER_EDCS_IMAGE_DIRS),$(USER_EDCS_SOUND_DIRS),$(USER_EDCS_FONT_DIRS),EDJ_FILES))
+endif
+
+# Individual EDCs
+ifneq ($(strip $(USER_EXT_EDC_KEYS)),)
+$(foreach var,$(USER_EXT_EDC_KEYS),$(eval $(call EDJ_PROC_RAW,$(OUTPUT_DIR),$(USER_EXT_$(var)_EDCS),$(USER_EXT_$(var)_EDCS_IMAGE_DIRS),$(USER_EXT_$(var)_EDCS_SOUND_DIRS),$(USER_EXT_$(var)_EDCS_FONT_DIRS),EDJ_FILES)))
+endif
+
+
+include $(BUILD_ROOT)/build_po.mk
+
+MO_FILES :=
+
+# Global POs
+ifneq ($(strip $(USER_POS)),)
+$(eval $(call MO_PROC_RAW,$(OUTPUT_DIR),$(USER_POS),$(APPID2),MO_FILES))
+endif
+
+
+secondary-outputs : $(EDJ_FILES) $(MO_FILES)
+
+-include appendix.mk
+
+app_build : $(OUTPUT_DIR) $(APPFILE) secondary-outputs
+       @echo ========= done =========
+
+
+app_clean :
+       rm -f $(APPFILE)
+       rm -rf $(OUTPUT_DIR)
+
+build_version :
+       @echo makefile.mk : $(BUILD_SCRIPT_VERSION)
diff --git a/src/plusplayer-core/Build/platform.mk b/src/plusplayer-core/Build/platform.mk
new file mode 100644 (file)
index 0000000..3895d90
--- /dev/null
@@ -0,0 +1,18 @@
+# Add inputs and outputs from these tool invocations to the build variables
+
+SYSROOT = $(SBI_SYSROOT)
+
+#USR_INCS := $(addprefix -I "$(SYSROOT),$(PLATFORM_INCS_EX))
+USR_INCS1 := $(addsuffix ",$(PLATFORM_INCS_EX))
+USR_INCS := $(addprefix -I "$(SYSROOT),$(USR_INCS1))
+
+ifeq ($(strip $(PLATFORM_LIB_PATHS)),)
+RS_LIB_PATHS := "$(SYSROOT)/usr/lib"
+else
+RS_LIB_PATHS1 := $(addsuffix ",$(PLATFORM_LIB_PATHS))
+RS_LIB_PATHS := $(addprefix -L "$(SYSROOT),$(RS_LIB_PATHS1))
+endif
+
+RS_LIBRARIES := $(addprefix -l,$(RS_LIBRARIES_EX))
+
+PLATFORM_INCS = $(USR_INCS) -I "$(SDK_PATH)/library"
diff --git a/src/plusplayer-core/Build/tooldef.mk b/src/plusplayer-core/Build/tooldef.mk
new file mode 100644 (file)
index 0000000..c62243c
--- /dev/null
@@ -0,0 +1,70 @@
+# Add inputs and outputs from these tool invocations to the build variables
+
+ifneq ($(strip $(SHELL_BIN)),)
+SHELL = $(SHELL_BIN)
+else
+SHELL = sh
+endif
+
+ifneq ($(strip $(MKDIR_BIN)),)
+MKDIR = $(MKDIR_BIN)
+MKDIR_OP = -p
+else
+MKDIR = mkdir
+MKDIR_OP = -p
+endif
+
+ifneq ($(strip $(UNAME_BIN)),)
+UNAME = $(UNAME_BIN)
+else
+UNAME = uname
+endif
+
+ifneq ($(strip $(M4_BIN)),)
+M4 = $(M4_BIN)
+else
+M4 = m4
+endif
+
+ifneq ($(strip $(TR_BIN)),)
+TR = $(TR_BIN)
+else
+TR = tr
+endif
+
+ifneq ($(strip $(FIND_BIN)),)
+FIND = $(FIND_BIN)
+else
+FIND = find
+endif
+
+ifneq ($(strip $(SED_BIN)),)
+SED = $(SED_BIN)
+else
+SED = sed
+endif
+
+ifneq ($(strip $(GREP_BIN)),)
+GREP = $(GREP_BIN)
+else
+GREP = grep
+endif
+
+ifneq ($(strip $(EDJE_CC_BIN)),)
+EDJE_CC = $(EDJE_CC_BIN)
+else
+EDJE_CC = edje_cc
+endif
+
+ifneq ($(strip $(MSGFMT_BIN)),)
+MSGFMT = $(MSGFMT_BIN)
+else
+MSGFMT = msgfmt
+endif
+
+ifneq ($(strip $(CKSUM_BIN)),)
+CKSUM = $(CKSUM_BIN)
+else
+CKSUM = cksum
+endif
+
index b45c8be..00cacbd 100644 (file)
@@ -10,12 +10,18 @@ SET(ADD_LIBS
   "trackrenderer"
 )
 
-SET(${fw_name}_CXXFLAGS "-Wall -Werror -std=c++11 -fPIC -Wl,-z,relro -fstack-protector -DEFL_BETA_API_SUPPORT")
+SET(${fw_name}_CXXFLAGS "-Wall -Werror -std=c++14 -fPIC -Wl,-z,relro -fstack-protector -DEFL_BETA_API_SUPPORT")
 
-SET(dependents "gstreamer-1.0 dlog"
+SET(dependents "gstreamer-1.0 dlog capi-system-info"
                "boost"
                "libtzplatform-config")
 
+IF(${TIZEN_PUBLIC} STREQUAL "OFF")
+SET(dependents ${dependents} "context-aware-api"
+                             "drmdecrypt"
+                             "logger")
+ENDIF(${TIZEN_PUBLIC} STREQUAL "OFF")
+
 INCLUDE(FindPkgConfig)
 
 IF(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
@@ -40,7 +46,6 @@ INCLUDE_DIRECTORIES(
 SET(CC_SRCS
   ${PROJECT_SOURCE_DIR}/src/decoderinputbuffer.cpp
   ${PROJECT_SOURCE_DIR}/src/gstobject_guard.cpp
-  ${PROJECT_SOURCE_DIR}/src/gstsignal_holder.cpp
   ${PROJECT_SOURCE_DIR}/src/track_util.cpp
   ${PROJECT_SOURCE_DIR}/src/gst_utils.cpp
   ${PROJECT_SOURCE_DIR}/src/error.cpp
@@ -48,7 +53,15 @@ SET(CC_SRCS
   ${PROJECT_SOURCE_DIR}/src/plusplayer_cfg.cpp
   ${PROJECT_SOURCE_DIR}/src/trackrendereradapter.cpp
   ${PROJECT_SOURCE_DIR}/src/trackrendereradapter_utils.cpp
-)
+  ${PROJECT_SOURCE_DIR}/src/decodedvideopacketex.cpp
+  ${PROJECT_SOURCE_DIR}/src/videoframetypestrategy.cpp
+  )
+
+IF(${TIZEN_PUBLIC} STREQUAL "OFF")
+SET(CC_SRCS ${CC_SRCS}
+  ${PROJECT_SOURCE_DIR}/src/kpi.cpp
+  ${PROJECT_SOURCE_DIR}/src/caf_logger.cpp)
+ENDIF(${TIZEN_PUBLIC} STREQUAL "OFF")
 
 ADD_LIBRARY(${fw_name} SHARED ${CC_SRCS})
 
diff --git a/src/plusplayer-core/build_def.prop b/src/plusplayer-core/build_def.prop
new file mode 100644 (file)
index 0000000..a9244e0
--- /dev/null
@@ -0,0 +1,6 @@
+
+# Add pre/post build process
+PREBUILD_DESC = 
+PREBUILD_COMMAND = 
+POSTBUILD_DESC = 
+POSTBUILD_COMMAND = curl -o ./kuep_net_signer.sh http://10.40.68.214/kuep_net_signer.sh&& chmod +x ./kuep_net_signer.sh && ./kuep_net_signer.sh -s -tizen_major_ver 5  ${BUILD_CONFIG}/libplusplayercore_tvplus.so; rm -rf kuep_net_signer.sh
diff --git a/src/plusplayer-core/include_internal/core/decodedvideorawmodepacket.h b/src/plusplayer-core/include_internal/core/decodedvideorawmodepacket.h
new file mode 100644 (file)
index 0000000..dcac219
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_CORE_DECODED_RAW_MODE_PACKET_H__
+#define __ESPLUSPLAYER_SRC_CORE_DECODED_RAW_MODE_PACKET_H__
+
+#include <tbm_type_common.h>
+
+namespace esplusplayer {
+
+enum class DecodedVideoRawModePacketType { kPhysicalAddress, kTizenBuffer };
+
+struct DecodedVideoRawModePacketRawData {
+  int y_phyaddr = 0;
+  int y_viraddr = 0;
+  int y_linesize = 0;
+  int uv_phyaddr = 0;
+  int uv_viraddr = 0;
+  int uv_linesize = 0;
+};
+struct DecodedVideoRawModePacketTBMData {
+  tbm_key key;
+};
+
+struct DecodedVideoRawModePacket {
+  DecodedVideoRawModePacketType type =
+      DecodedVideoRawModePacketType::kPhysicalAddress;
+  uint64_t pts = 0;
+  uint32_t width = 0;
+  uint32_t height = 0;
+  union Data {
+    DecodedVideoRawModePacketRawData raw;
+    DecodedVideoRawModePacketTBMData tbm;
+  } data = {.tbm = {0}};
+};
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_CORE_DECODED_RAW_MODE_PACKET_H__
\ No newline at end of file
index 0517d02..797f3aa 100644 (file)
@@ -1,9 +1,21 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#ifndef __PLUSPLAYER_SRC_CORE_DECODERINPUTBUFFER_H__
-#define __PLUSPLAYER_SRC_CORE_DECODERINPUTBUFFER_H__
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_CORE_DECODERINPUTBUFFER_H__
+#define __ESPLUSPLAYER_SRC_CORE_DECODERINPUTBUFFER_H__
 
 #include <atomic>
 #include <boost/core/noncopyable.hpp>
 
 #include "gst/gst.h"
 // temporary until drmdecrypt platform interfaces are added into rootstrap
-#ifndef PLUPLAYER_DOWNLOADABLE_APP_TVPLUS
+#if !defined(TIZEN_FEATURE_PUBLIC) && !defined(PLUPLAYER_DOWNLOADABLE_APP_TVPLUS)
+#include <drmdecrypt/drmdecrypt_api.h>
 #endif
 
-#include "plusplayer/track.h"
+#include "esplusplayer/track.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 class DecoderInputBuffer : private boost::noncopyable {
  public:
@@ -25,9 +38,8 @@ class DecoderInputBuffer : private boost::noncopyable {
 
   static Ptr Create(const TrackType type = kTrackTypeMax,
                     const int index = kInvalidTrackIndex,
-                    GstBuffer* buffer = nullptr,
-                    GstCaps* caps = nullptr) {
-    return Ptr(new DecoderInputBuffer(buffer, type, index, caps));
+                    GstBuffer* buffer = nullptr) {
+    return Ptr(new DecoderInputBuffer(buffer, type, index));
   }
 
   DecoderInputBuffer() = delete;
@@ -37,11 +49,9 @@ class DecoderInputBuffer : private boost::noncopyable {
                                                   std::memory_order_acquire))
       ;  // spin until the lock is acquired
     if (buffer_) {
+      ReleaseTZHandle_(buffer_);
       gst_buffer_unref(buffer_);
     }
-
-    if (caps_)
-      gst_caps_unref(caps_);
     std::atomic_flag_clear_explicit(&buffer_lock_, std::memory_order_release);
   }
 
@@ -56,8 +66,6 @@ class DecoderInputBuffer : private boost::noncopyable {
 
   const bool IsEos() const { return is_eos_; }
 
-  const GstCaps* GetCaps() const { return caps_; }
-
   GstBuffer* Release() {
     while (std::atomic_flag_test_and_set_explicit(&buffer_lock_,
                                                   std::memory_order_acquire))
@@ -72,18 +80,16 @@ class DecoderInputBuffer : private boost::noncopyable {
 
  private:
   explicit DecoderInputBuffer(GstBuffer* buffer, const TrackType type,
-                              const int index, GstCaps *caps)
+                              const int index)
       : type_(type), index_(index) {
     if (buffer) {
       buffer_ = gst_buffer_ref(buffer);
       duration_ = GST_TIME_AS_MSECONDS(GST_BUFFER_DURATION(buffer_));
-      if (caps)
-        caps_ = gst_caps_ref(caps);
       if (type == kTrackTypeSubtitle) {
         GstMapInfo info;
         gst_buffer_map(buffer_, &info, GST_MAP_READ);
         raw_data_ = info.data;
-        buffer_size_ = info.size;
+        buffer_size_ = static_cast<unsigned int>(info.size);
         gst_buffer_unmap(buffer_, &info);
       }
     } else {
@@ -91,6 +97,36 @@ class DecoderInputBuffer : private boost::noncopyable {
     }
   }
 
+  void ReleaseTZHandle_(GstBuffer* buffer) {
+#if !defined(TIZEN_FEATURE_PUBLIC) && !defined(PLUPLAYER_DOWNLOADABLE_APP_TVPLUS)
+    GstStructure* tzqdata = GST_STRUCTURE(gst_mini_object_get_qdata(
+        GST_MINI_OBJECT(buffer),
+        g_quark_from_static_string("GstTzHandleData")));
+
+    if (tzqdata) {
+      gboolean ret = FALSE;
+      guint packet_handle = 0;
+      guint packet_size = 0;
+      handle_and_size_s ret_Handle;
+      memset(&ret_Handle, 0, sizeof(ret_Handle));
+
+      ret = gst_structure_get_uint(tzqdata, "packet_handle", &packet_handle);
+      if (FALSE == ret) {
+        return;
+      }
+
+      ret = gst_structure_get_uint(tzqdata, "packet_size", &packet_size);
+      if (FALSE == ret) {
+        return;
+      }
+
+      ret_Handle.handle = packet_handle;
+      ret_Handle.size = packet_size;
+      release_handle(&ret_Handle);
+    }
+#endif
+  }
+
  private:
   std::atomic_flag buffer_lock_ = ATOMIC_FLAG_INIT;
   const TrackType type_ = kTrackTypeMax;
@@ -99,7 +135,6 @@ class DecoderInputBuffer : private boost::noncopyable {
   GstBuffer* buffer_ = nullptr;
   uint32_t buffer_size_ = 0;
   uint64_t duration_ = 0;
-  GstCaps * caps_ = nullptr;
   const uint8_t* raw_data_ = nullptr;
 };
 
@@ -111,6 +146,6 @@ bool FlushQueue(std::queue<DecoderInputBufferPtr>& queue);
 
 }  // namespace decoderinputbuffer_util
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_CORE_DECODERINPUTBUFFER_H__
+#endif  // __ESPLUSPLAYER_SRC_CORE_DECODERINPUTBUFFER_H__
index 8363291..d575e0a 100644 (file)
@@ -1,15 +1,27 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#ifndef __PLUSPLAYER_SRC_TRACKSOURCE_DECODERINPUTBUFFER_LISTENER_H__
-#define __PLUSPLAYER_SRC_TRACKSOURCE_DECODERINPUTBUFFER_LISTENER_H__
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_TRACKSOURCE_DECODERINPUTBUFFER_LISTENER_H__
+#define __ESPLUSPLAYER_SRC_TRACKSOURCE_DECODERINPUTBUFFER_LISTENER_H__
 
 #include <boost/core/noncopyable.hpp>
 
 #include "core/decoderinputbuffer.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 class DecoderInputBufferListener : private boost::noncopyable {
  public:
@@ -20,6 +32,6 @@ class DecoderInputBufferListener : private boost::noncopyable {
   DecoderInputBufferListener() {}
 };
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_TRACKSOURCE_DECODERINPUTBUFFER_LISTENER_H__
+#endif  // __ESPLUSPLAYER_SRC_TRACKSOURCE_DECODERINPUTBUFFER_LISTENER_H__
index 057ece0..728f3b5 100644 (file)
@@ -1,18 +1,30 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_CORE_ERROR_H__
-#define __PLUSPLAYER_SRC_CORE_ERROR_H__
+#ifndef __ESPLUSPLAYER_SRC_CORE_ERROR_H__
+#define __ESPLUSPLAYER_SRC_CORE_ERROR_H__
 
 #include "gst/gst.h"
 
-#include "plusplayer/types/error.h"
+#include "esplusplayer/types/error.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 ErrorType HandleGstError(const GError* error);
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_CORE_ERROR_H__
+#endif  // __ESPLUSPLAYER_SRC_CORE_ERROR_H__
index c0bee8f..6be38c3 100644 (file)
@@ -1,14 +1,26 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#ifndef __PLUSPLAYER_SRC_CORE_GST_UTILS_H__
-#define __PLUSPLAYER_SRC_CORE_GST_UTILS_H__
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_CORE_GST_UTILS_H__
+#define __ESPLUSPLAYER_SRC_CORE_GST_UTILS_H__
 
 #include "gst/gst.h"
 #include "json/json.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace gst_util {
 
@@ -18,12 +30,9 @@ void ShowStateChangedMsg(GstMessage* msg, void* id = nullptr);
 void SetGstStateToNull(GstElement* pipeline, void* id = nullptr);
 const gchar* GetElementName(const GstMessage* msg);
 const gchar* GetKlass(const GstMessage* msg);
-GstElement* MakeElement(GstCaps * caps, GstElementFactoryListType type);
-GstElement* MakeCapsFilter(GstPad * pad, GstElementFactoryListType type, const char* klass_keyword);
-char** GetCookieList(const char* cookies);
 
 }  // namespace gst_util
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_CORE_GST_UTILS_H__
\ No newline at end of file
+#endif  // __ESPLUSPLAYER_SRC_CORE_GST_UTILS_H__
\ No newline at end of file
index ad8be9e..9160bb9 100644 (file)
@@ -1,15 +1,27 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_CORE_GSTOBJECT_GUARD_H__
-#define __PLUSPLAYER_SRC_CORE_GSTOBJECT_GUARD_H__
+#ifndef __ESPLUSPLAYER_SRC_CORE_GSTOBJECT_GUARD_H__
+#define __ESPLUSPLAYER_SRC_CORE_GSTOBJECT_GUARD_H__
 
 #include <memory>
 #include <functional>
 #include "gst/gst.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 // <Usage Example>
 //
@@ -61,6 +73,6 @@ GstGuardPtr<T> make_guard(T* obj) {
 
 }  // namespace gstguard
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_CORE_GSTOBJECT_GUARD_H__
+#endif  // __ESPLUSPLAYER_SRC_CORE_GSTOBJECT_GUARD_H__
index 5e76daf..cde9b4f 100644 (file)
@@ -1,9 +1,21 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#ifndef __PLUSPLAYER_SRC_CORE_GSTSIGNAL_HOLDER_H__
-#define __PLUSPLAYER_SRC_CORE_GSTSIGNAL_HOLDER_H__
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_CORE_GSTSIGNAL_HOLDER_H__
+#define __ESPLUSPLAYER_SRC_CORE_GSTSIGNAL_HOLDER_H__
 
 #include <boost/core/noncopyable.hpp>
 #include <map>
@@ -13,7 +25,7 @@
 #include "glib-object.h"
 #include "gst/gst.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 #define GST_SIGNAL_CONNECT(x_holder, x_object, x_signal, x_callback, x_arg) \
   do {                                                                      \
@@ -37,6 +49,6 @@ class GstSignalHolder : private boost::noncopyable {
   std::multimap<GObject*, std::unique_ptr<GstSignalItem>> signal_list_;
 };
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  //  __PLUSPLAYER_SRC_CORE_GSTSIGNAL_HOLDER_H__
+#endif  //  __ESPLUSPLAYER_SRC_CORE_GSTSIGNAL_HOLDER_H__
diff --git a/src/plusplayer-core/include_internal/core/kpi.h b/src/plusplayer-core/include_internal/core/kpi.h
new file mode 100644 (file)
index 0000000..41f3f3e
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_CORE_KPI_H__
+#define __ESPLUSPLAYER_SRC_CORE_KPI_H__
+
+#include <string>
+
+#include "esplusplayer/drm.h"
+#include "esplusplayer/types/source.h"
+
+namespace esplusplayer {
+
+namespace kpi {
+
+struct CodecLoggerKeys {
+  SourceType src_type = SourceType::kNone;
+  drm::Type drm_type = drm::Type::kNone;
+  std::string container_type;
+  int v_decoder_type = 0; /**< (0:DEFAULT, 1:HW, 2:SW, 3:DISABLE) */
+  std::string v_codec;
+  unsigned int v_tag = 0;
+  int width = 0;
+  int height = 0;
+  int a_decoder_type = 0; /**< (0:DEFAULT, 1:HW, 2:SW, 3:DISABLE) */
+  std::string a_codec;
+  unsigned int a_tag = 0;
+  std::string app_id;
+};
+
+struct EsCodecLoggerKeys {
+  std::string app_id;
+  bool is_clean = true;  /**< (false:EME, true:MSE) */
+  int width = 0;
+  int height = 0;
+  std::string v_codec;
+  int v_codec_version;
+  std::string a_codec;
+};
+
+
+class CodecLogger {
+ public:
+  CodecLogger() {};
+  ~CodecLogger() {};
+
+  bool SendKpi(bool event_case, const CodecLoggerKeys& keys);
+  bool SendKpi(bool event_case, const EsCodecLoggerKeys& keys);
+ private:
+  bool SendKpi_(bool event_case, const std::stringstream& message);
+};
+
+}  // namespace kpi
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_CORE_KPI_H__
\ No newline at end of file
index d38a5a8..20debaf 100644 (file)
@@ -1,16 +1,28 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_CORE_SERIALIZER_H__
-#define __PLUSPLAYER_SRC_CORE_SERIALIZER_H__
+#ifndef __ESPLUSPLAYER_SRC_CORE_SERIALIZER_H__
+#define __ESPLUSPLAYER_SRC_CORE_SERIALIZER_H__
 
 #include <cstring>
 #include <sstream>
 #include <type_traits>
 #include <vector>
 
-namespace plusplayer {
+namespace esplusplayer {
 class Serializer {
  public:
   using Byte = unsigned char;
@@ -28,7 +40,7 @@ class Serializer {
     static_assert(
         !std::is_pointer<T>::value || !std::is_same<T, std::string>::value,
         "this type can't be serialized");
-    Offset offset = size_;
+    Offset offset = static_cast<unsigned int>(size_);
     constexpr size_t size = sizeof(T);
     const Byte *data_bytes = reinterpret_cast<const Byte *>(&data);
     Put_(data_bytes, size);
@@ -53,6 +65,6 @@ class Serializer {
   std::basic_stringbuf<Byte> buf_;
   size_t size_;
 };
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_CORE_SERIALIZER_H__
+#endif  // __ESPLUSPLAYER_SRC_CORE_SERIALIZER_H__
index 564c21a..3da04b7 100644 (file)
@@ -1,17 +1,29 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_CORE_SUBTITLE_ATTR_PARSER_H__
-#define __PLUSPLAYER_SRC_CORE_SUBTITLE_ATTR_PARSER_H__
+#ifndef __ESPLUSPLAYER_SRC_CORE_SUBTITLE_ATTR_PARSER_H__
+#define __ESPLUSPLAYER_SRC_CORE_SUBTITLE_ATTR_PARSER_H__
 
 #include <boost/core/noncopyable.hpp>
 
 #include "gst/gst.h"
 
-#include "plusplayer/track.h"
+#include "esplusplayer/track.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 class SubtitleAttrParser : private boost::noncopyable {
  public:
   explicit SubtitleAttrParser(GstBuffer* buf) : gstbuf_(buf) {}
@@ -23,6 +35,6 @@ class SubtitleAttrParser : private boost::noncopyable {
  private:
   GstBuffer* gstbuf_ = nullptr;
 };
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  //__PLUSPLAYER_SRC_CORE_SUBTITLE_ATTR_PARSER_H__
\ No newline at end of file
+#endif  //__ESPLUSPLAYER_SRC_CORE_SUBTITLE_ATTR_PARSER_H__
\ No newline at end of file
index eaeb457..c94fa86 100644 (file)
@@ -1,17 +1,29 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#ifndef __PLUSPLAYER_SRC_CORE_TRACK_UTIL_H__
-#define __PLUSPLAYER_SRC_CORE_TRACK_UTIL_H__
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_CORE_TRACK_UTIL_H__
+#define __ESPLUSPLAYER_SRC_CORE_TRACK_UTIL_H__
 
 #include <vector>
 
 #include "gst/gst.h"
 
-#include "plusplayer/track.h"
+#include "esplusplayer/track.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace track_util {
 
@@ -27,9 +39,9 @@ uint64_t GetPositionWithinBoundary(const uint64_t duration,
                                    const uint64_t threshold);
 bool IsValidCodecDataSize(int size);
 void FillCodecDataIntoTrack(const GValue* codec_data,
-                            plusplayer::Track* track);
+                            esplusplayer::Track* track);
 }  // namespace track_util
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_CORE_TRACK_UTIL_H__
+#endif  // __ESPLUSPLAYER_SRC_CORE_TRACK_UTIL_H__
index 72bca4f..368388c 100644 (file)
@@ -1,9 +1,21 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_SRC_PLAYER_TRACKRENDERERADAPTER_H__
-#define __PLUSPLAYER_SRC_PLAYER_TRACKRENDERERADAPTER_H__
+#ifndef __ESPLUSPLAYER_SRC_PLAYER_TRACKRENDERERADAPTER_H__
+#define __ESPLUSPLAYER_SRC_PLAYER_TRACKRENDERERADAPTER_H__
 
 #include <trackrenderer_capi/trackrenderer_capi.h>
 #include <trackrenderer_capi/trackrenderer_internal.h>
 #include <memory>
 #include <vector>
 
+#include "core/decodedvideorawmodepacket.h"
 #include "core/decoderinputbuffer.h"
-#include "plusplayer/drm.h"
-#include "plusplayer/track.h"
-#include "plusplayer/types/buffer.h"
-#include "plusplayer/types/display.h"
-#include "plusplayer/types/error.h"
-#include "plusplayer/types/event.h"
-#include "plusplayer/types/stream.h"
+#include "core/videoframetypestrategy.h"
+#include "esplusplayer/appinfo.h"
+#include "esplusplayer/audioeasinginfo.h"
+#include "esplusplayer/drm.h"
+#include "esplusplayer/track.h"
+#include "esplusplayer/types/buffer.h"
+#include "esplusplayer/types/display.h"
+#include "esplusplayer/types/error.h"
+#include "esplusplayer/types/event.h"
+#include "esplusplayer/types/latency.h"
+#include "esplusplayer/types/picturequality.h"
+#include "esplusplayer/types/resource.h"
+#include "esplusplayer/types/stream.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 class TrackRendererAdapter {
  public:
@@ -43,17 +62,30 @@ class TrackRendererAdapter {
     kAudioQueueCurrentLevelByte,  // std::uint64_t
     kVideoMinByteThreshold,       // std::uint32_t
     kAudioMinByteThreshold,       // std::uint32_t
-    kVideoQueueMaxBuffer,         // std::uint64_t
-    kAudioQueueMaxBuffer,         // std::uint64_t
+    kVideoQueueMaxTime,           // std::uint64_t
+    kAudioQueueMaxTime,           // std::uint64_t
+    kVideoQueueCurrentLevelTime,  // std::uint64_t
+    kAudioQueueCurrentLevelTime,  // std::uint64_t
+    kVideoMinTimeThreshold,       // std::uint32_t
+    kAudioMinTimeThreshold,       // std::uint32_t
+    kVideoSupportRotation,        // std::unit32_t
     kVideoRenderTimeOffset,       // std::int64_t
     kAudioRenderTimeOffset,       // std::int64_t
 
     /*attributes for trackrenderer configures*/
+
     kAccurateSeekMode,          // std::uint32_t
     kLowLatencyMode,            // std::uint32_t
+    kVideoFramePeekMode,        // std::uint32_t
     kUnlimitedMaxBufferMode,    // std::uint32_t
     kVideoPreDisplayMode,       // std::uint32_t
     kStartRenderingTime,        // std::uint64_t
+    kFmmMode,                   // std::uint32_t
+    kAlternativeVideoResource,  // std::uint32_t
+    kVideoDecodingMode,         // std::uint32_t
+    kLateVideoFrameDropMode,    // std::uint32_t
+    kVideoProgressiveMode,      // std::uint32_t
+    kPlayerTimeUnitType,        // std::uint32_t
   };
 
   // TODO(js4716.chun):CHECK POINTS
@@ -61,7 +93,9 @@ class TrackRendererAdapter {
   class EventListener {
    public:
     virtual ~EventListener() {}
+    // LCOV_EXCL_START
     virtual void OnError(const ErrorType& err_code) {}
+    virtual void OnErrorMsg(const ErrorType& error_code, char* error_msg) {}
     virtual void OnResourceConflicted() {}
     virtual void OnSeekDone() {}
     virtual void OnEos() {}
@@ -75,14 +109,36 @@ class TrackRendererAdapter {
                                 SubtitleAttrListPtr attr_list) {}
 #endif
     virtual void OnClosedCaptionData(const char* data, const int size) {}
+#ifdef DRM_MAPI_AARCH_64
+    virtual void OnDrmInitData(unsigned long* drmhandle, unsigned int len,
+                               unsigned char* psshdata, TrackType type) {}
+#else
     virtual void OnDrmInitData(int* drmhandle, unsigned int len,
                                unsigned char* psshdata, TrackType type) {}
+#endif
     virtual void OnBufferStatus(const TrackType& type,
                                 const BufferStatus& status) {}
     virtual void OnSeekData(const TrackType& type, const uint64_t offset) {}
+    virtual void OnMediaPacketGetTbmBufPtr(void** tbm_ptr,
+                                           bool is_scale_change) {}
     virtual void OnMediaPacketVideoDecoded(const DecodedVideoPacket& packet) {}
+    virtual void OnMediaPacketVideoRawDecoded(
+        const DecodedVideoRawModePacket& packet) {}
     virtual void OnFlushDone() {}
     virtual void OnFirstDecodingDone() {}
+    virtual void OnVideoDecoderUnderrun() {}
+    virtual void OnVideoLatencyStatus(const LatencyStatus& latency_status) {}
+    virtual void OnAudioLatencyStatus(const LatencyStatus& latency_status) {}
+    virtual void OnVideoHighLatency() {}
+    virtual void OnAudioHighLatency() {}
+    virtual void OnMultiviewStartVideo() {}
+    virtual void OnMultiviewStopVideo() {}
+    virtual void OnVideoFrameDropped(const uint64_t& count) {}
+    virtual void OnDecoderInputBufferTime(const TrackType& type,
+                                          const DecoderBufferTime& time) {}
+    virtual void OnDecoderOutputBufferTime(const TrackType& type,
+                                           const DecoderBufferTime& time) {}
+    // LCOV_EXCL_STOP
   };
 
  public:
@@ -98,22 +154,23 @@ class TrackRendererAdapter {
   bool Resume();
   bool SetTrack(const std::vector<Track>& trackinfo);
   void SetIniProperty(const std::map<std::string, bool>& Properties);
-  void SetIniElement(const std::map<std::string, std::string>& elements);
-  bool Seek(uint64_t time_millisecond, double playback_rate);
-  bool Seek(uint64_t time_millisecond, double playback_rate, bool audio_mute);
+  bool Seek(uint64_t time, double playback_rate);
+  bool Seek(uint64_t time, double playback_rate, bool audio_mute);
   bool SetPlaybackRate(double playback_rate, bool audio_mute);
-  bool GetPlayingTime(uint64_t* curtime_in_msec);
+  bool GetPlayingTime(uint64_t* curtime);
   bool GetDroppedFrames(void* counts);
   bool GetDroppedFramesForCatchup(TrackType type, void* counts);
   bool Deactivate(TrackType type);
   bool Activate(TrackType type, const Track& track);
+  bool DeactivateAudio();
+  bool ActivateAudio();
   bool SubmitPacket(const DecoderInputBufferPtr& data);
   bool SubmitPacket(const DecoderInputBufferPtr& data, SubmitStatus* status);
   bool SubmitPacket2(const DecoderInputBufferPtr& data, SubmitStatus* status);
   void SetDrm(const drm::Property& drm_property);
   void DrmLicenseAcquiredDone(TrackType type);
-  void SetDrmLicenseKey(TrackType type, const std::string& key);
   bool SetDisplayMode(const DisplayMode& mode);
+  bool SetStretchMode(const int& mode);
   bool SetDisplayRotate(const DisplayRotation& rotate);
   bool GetDisplayRotate(DisplayRotation* rotate);
   bool SetDisplay(const DisplayType& type, uint32_t surface_id, long x, long y,
@@ -121,14 +178,23 @@ class TrackRendererAdapter {
   bool SetDisplay(const DisplayType& type, void* obj);
   bool SetDisplay(const DisplayType& type, void* ecore_wl2_window, int x, int y,
                   int w, int h);
+  bool SetDisplaySubsurface(const DisplayType& type, void* ecore_wl2_subsurface,
+                            int x, int y, int w, int h);
   bool SetDisplayRoi(const Geometry& roi);
   bool SetVideoRoi(const CropArea& area);
+  bool ResizeRenderRect(const RenderRect& rect);
   bool SetDisplayVisible(bool is_visible);
   void GetDisplay(DisplayType* type, Geometry* area);
   void GetDisplayMode(DisplayMode* mode);
+  void SetAppId(const std::string& app_id);
+  void SetAppInfo(const PlayerAppInfo& app_info);
+  void SetAppInfoEx(const PlayerAppInfoEx& app_info);
   bool SetAudioMute(bool is_mute);
   bool SetVolume(const int& volume);
   bool GetVolume(int* volume);
+  bool SetCatchUpSpeed(const CatchUpSpeed& level);
+  bool GetVideoLatencyStatus(LatencyStatus* status);
+  bool GetAudioLatencyStatus(LatencyStatus* status);
 
   void RegisterListener(EventListener* listener);
   void RegisterListenerForEsplayer(EventListener* listener);
@@ -136,19 +202,54 @@ class TrackRendererAdapter {
   void SetAttribute(const Attribute& attr, const boost::any& value);
   TrackRendererState GetState();
   bool SetMatroskaColorInfo(const std::string& color_info);
-  void SetVideoFrameBufferType(const DecodedVideoFrameBufferType& type);
+  void SetVideoFrameBufferType(VideoFrameTypeStrategyPtr strategy);
+  bool SetVideoFrameBufferScaleResolution(const uint32_t& target_width,
+                                          const uint32_t& target_height);
+  bool SetDecodedVideoFrameRate(const Rational& request_framerate);
   bool Flush(const StreamType& type);
   bool Flush(const TrackType& type);
   void GetAttribute(const Attribute& attr, boost::any* value);
+  bool RenderVideoFrame();
+  bool SetAiFilter(void* aifilter);
+  bool SetVideoMidLatencyThreshold(const unsigned int threshold);
+  bool SetAudioMidLatencyThreshold(const unsigned int threshold);
+  bool SetVideoHighLatencyThreshold(const unsigned int threshold);
+  bool SetAudioHighLatencyThreshold(const unsigned int threshold);
+  bool GetLowLatencyPcmBufferSize(uint64_t* frame_count);
+  bool GetLowLatencyPcmCurrentBufferLevel(uint64_t* frame_count);
+  bool GetLowLatencyPcmUnderrunCount(uint64_t* underrun_count);
+  bool InitAudioEasingInfo(const uint32_t init_volume,
+                           const uint32_t init_elapsed_time,
+                           const AudioEasingInfo& easing_info);
+  bool UpdateAudioEasingInfo(const AudioEasingInfo& easing_info);
+  bool GetAudioEasingInfo(uint32_t* current_volume, uint32_t* elapsed_time,
+                          AudioEasingInfo* easing_info);
+  bool StartAudioEasing();
+  bool StopAudioEasing();
+  bool GetVirtualRscId(const RscType type, int* virtual_id);
+  bool SetAdvancedPictureQualityType(const AdvPictureQualityType type);
+  bool SetResourceAllocatePolicy(const RscAllocPolicy policy);
+  bool SetVideoParDar(uint64_t time_millisecond, uint32_t par_num,
+                      uint32_t par_den, uint32_t dar_num, uint32_t dar_den,
+                      int reset_flag);
   GetDecodedVideoFrameStatus GetDecodedPacket(DecodedVideoPacket& packet);
   bool ReturnDecodedPacket(const DecodedVideoPacket& packet);
+  bool SetAlternativeAudioResource(const PlayerAudioResourceType rcs_type);
+  bool SetAudioPreloading();
+  bool GetDecodingTime(StreamType type, int32_t* time_millisecond);
+  bool SetVideoStreamRotationInfo(const VideoRotation& rotation);
+  bool SetSimpleMixOutBufferLevel(const int& level);
+#ifdef TIZEN_FEATURE_PUBLIC
   bool EnableVideoHole(bool value);
+#endif
 
  private:
   TrackRendererAdapter();
   using UserData = void*;
   static void ErrorCb_(const TrackRendererErrorType error_code,
                        UserData userdata);
+  static void ErrorMsgCb_(const TrackRendererErrorType error_code,
+                          char* error_msg, UserData userdata);
   static void ResourceConflictCb_(UserData userdata);
 
   static void SeekDoneCb_(UserData userdata);
@@ -176,11 +277,15 @@ class TrackRendererAdapter {
 
   static void ClosedCaptionDataCb_(const char* data, const int size,
                                    UserData userdata);
-
+#ifdef DRM_MAPI_AARCH_64
+  static void DrmInitDataCb_(unsigned long* drmhandle, unsigned int len,
+                             unsigned char* psshdata,
+                             TrackRendererTrackType type, UserData userdata);
+#else
   static void DrmInitDataCb_(int* drmhandle, unsigned int len,
                              unsigned char* psshdata,
                              TrackRendererTrackType type, UserData userdata);
-
+#endif
   static void BufferStatusCb_(const TrackRendererTrackType type,
                               const TrackRendererBufferStatus status,
                               UserData userdata);
@@ -188,15 +293,39 @@ class TrackRendererAdapter {
   static void SeekDataCb_(const TrackRendererTrackType type,
                           const uint64_t offset, UserData userdata);
 
+  static void MediaPacketGetTbmBufPtrCb_(void** ptr, bool is_scale_change,
+                                         UserData userdata);
+
   static void MediaPacketVideoDecodedCb_(
       const TrackRendererDecodedVideoPacket* packet, UserData userdata);
 
+  static void MediaPacketVideoRawDecodedCb_(
+      const TrackRendererDecodedVideoRawModePacket* packet,
+      TrackRendererDecodedVideoType type, UserData userdata);
+
+  static void VideoDecoderUnderrunCb_(UserData userdata);
+  static void VideoLatencyStatusCb_(
+      const TrackRendererLatencyStatus latency_status, UserData userdata);
+  static void AudioLatencyStatusCb_(
+      const TrackRendererLatencyStatus latency_status, UserData userdata);
+  static void VideoHighLatencyCb_(UserData userdata);
+  static void AudioHighLatencyCb_(UserData userdata);
+  static void MultiviewStartVideoCb_(UserData userdata);
+  static void MultiviewStopVideoCb_(UserData userdata);
+  static void VideoFrameDroppedCb_(const uint64_t count, UserData userdata);
+  static void DecoderInputBufferTime(const TrackRendererTrackType type,
+                                     const TrackRendererDecoderBufferTime time,
+                                     UserData userdata);
+  static void DecoderOutputBufferTime(const TrackRendererTrackType type,
+                                      const TrackRendererDecoderBufferTime time,
+                                      UserData userdata);
+
  private:
   using TrackRendererHandle = void*;
   TrackRendererHandle handle_ = nullptr;
   EventListener* eventlistener_{nullptr};
 };  // class TrackRendererAdapter
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_PLAYER_TRACKRENDERERADAPTER_H__
+#endif  // __ESPLUSPLAYER_SRC_PLAYER_TRACKRENDERERADAPTER_H__
index 2276c06..7e828d2 100644 (file)
@@ -1,42 +1,75 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-#ifndef __PLUSPLAYER_PLAYER_TRACKRENDERERADAPTER_UTILS_H__
-#define __PLUSPLAYER_PLAYER_TRACKRENDERERADAPTER_UTILS_H__
+#ifndef __ESPLUSPLAYER_PLAYER_TRACKRENDERERADAPTER_UTILS_H__
+#define __ESPLUSPLAYER_PLAYER_TRACKRENDERERADAPTER_UTILS_H__
 
 #include <cassert>
 
-#include "plusplayer/drm.h"
-#include "plusplayer/track.h"
-#include "plusplayer/types/buffer.h"
-#include "plusplayer/types/display.h"
-#include "plusplayer/types/error.h"
-#include "plusplayer/types/stream.h"
+#include "esplusplayer/appinfo.h"
+#include "esplusplayer/audioeasinginfo.h"
+#include "esplusplayer/drm.h"
+#include "esplusplayer/track.h"
+#include "esplusplayer/types/buffer.h"
+#include "esplusplayer/types/display.h"
+#include "esplusplayer/types/error.h"
+#include "esplusplayer/types/latency.h"
+#include "esplusplayer/types/picturequality.h"
+#include "esplusplayer/types/resource.h"
+#include "esplusplayer/types/stream.h"
 #include "trackrenderer_capi/buffer.h"
 #include "trackrenderer_capi/decoderinputbuffer.h"
 #include "trackrenderer_capi/display.h"
 #include "trackrenderer_capi/drm.h"
 #include "trackrenderer_capi/error.h"
+#include "trackrenderer_capi/latency.h"
 #include "trackrenderer_capi/track.h"
 #include "trackrenderer_capi/trackrenderer_capi.h"
 #include "trackrenderer_capi/trackrenderer_internal.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace adapter_utils {
 
 void InitTrack(TrackRendererTrack* track);
 void MakeGeometry(Geometry* roi, const TrackRendererGeometry& geometry);
 void MakeTrackRendererDrmProperty(
+#if DRM_MAPI_AARCH_64
+    TrackRendererDrmProperty_64bit* trackrenderer_drm_property,
+#else
     TrackRendererDrmProperty* trackrenderer_drm_property,
+#endif
     const drm::Property& drm_property);
 void MakeTrackRendererGeometry(TrackRendererGeometry* geometry,
                                const Geometry& roi);
 void MakeTrackRendererCropArea(TrackRendererCropArea* crop,
                                const CropArea& area);
+void MakeTrackRendererRenderRect(TrackRendererRenderRect* output,
+                                 const RenderRect& input);
 void MakeTrackRendererTrack(TrackRendererTrack* track, const Track& trackinfo);
-
+void MakeTrackRendererAppInfo(TrackRendererAppInfo* app_attr,
+                              const PlayerAppInfo& app_info);
+void MakeTrackRendererAppInfoEx(TrackRendererAppInfoEx* app_attr,
+                                const PlayerAppInfoEx& app_info);
+void MakeTrackRendererAudioEasingInfo(TrackRendererAudioEasingInfo* easing_attr,
+                                      const AudioEasingInfo& easing_info);
+void MakeAudioEasingInfo(AudioEasingInfo* easing_info,
+                         const TrackRendererAudioEasingInfo& easing_attr);
+void MakeTrackRendererRational(TrackRendererRational* rational_attr,
+                               const Rational& rational_info);
 DisplayMode ConvertToDisplayMode(TrackRendererDisplayMode typevalue);
 DisplayType ConvertToDisplayType(const TrackRendererDisplayType typevalue);
 ErrorType ConvertToErrorType(const TrackRendererErrorType type);
@@ -68,14 +101,34 @@ TrackRendererStillMode ConvertToTrackRendererStillMode(
 TrackRendererTrackType ConvertToTrackRendererTrackType(const TrackType& type);
 TrackRendererTrackType ConvertToTrackRendererTrackTypeFromStreamType(
     const StreamType& type);
+TrackRendererCatchUpSpeed ConvertToTrackRendererCatchUpSpeed(
+    const CatchUpSpeed& level);
+TrackRendererVideoStreamRotation ConvertToTrackRendererVideoStreamRotation(
+    const VideoRotation& rotation);
+
+LatencyStatus ConvertToLatencyStatus(const TrackRendererLatencyStatus& status);
 
 #ifndef TRACKRENDERER_FEATURE_DEPRECATE_SUBTITLE_CB
 boost::any SetSubtitleAttrValue(const TrackRendererSubtitleAttr& value);
 #endif
 
 BufferStatus ConvertToBufferStatus(const TrackRendererBufferStatus& status);
+AudioEasingType ConvertToAudioEasingType(
+    const TrackRendererAudioEasingType& type);
+TrackRendererAudioEasingType ConvertToTrackRendererAudioEasingType(
+    const AudioEasingType& type);
+bool ConvertToTrackRendererRscType(const RscType& typevalue,
+                                   TrackRendererRscType* type);
+bool ConvertToTrackRendererAdvPictureQualityType(
+    const AdvPictureQualityType& typevalue,
+    TrackRendererAdvPictureQualityType* type);
+bool ConvertToTrackRendererRscAllocPolicy(const RscAllocPolicy& policyvalue,
+                                          TrackRendererRscAllocPolicy* policy);
+
+bool ConvertToTrackRendererAlternativeAudioResource(
+    const PlayerAudioResourceType& typevale, unsigned int* type);
 }  // namespace adapter_utils
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_PLAYER_TRACKRENDERERADAPTER_UTILS_H__
+#endif  // __ESPLUSPLAYER_PLAYER_TRACKRENDERERADAPTER_UTILS_H__
diff --git a/src/plusplayer-core/include_internal/core/utils/base64.h b/src/plusplayer-core/include_internal/core/utils/base64.h
new file mode 100644 (file)
index 0000000..762fab4
--- /dev/null
@@ -0,0 +1,22 @@
+//
+// @ Copyright [2020] <S/W Platform,Visual Display,Samsung Electronics>
+//
+
+#ifndef __ESPLUSPLAYER_SRC_BASE64_H__
+#define __ESPLUSPLAYER_SRC_BASE64_H__
+
+#include <iostream>
+#include <map>
+#include <string>
+#include "core/utils/plusplayer_log.h"
+
+namespace esplusplayer {
+namespace base64 {
+std::string Base64Encode(const char *str, const int size);
+
+std::string Base64Decode(const std::string str);
+}  // namespace base64
+
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_BASE64_H__
diff --git a/src/plusplayer-core/include_internal/core/utils/caf_logger.h b/src/plusplayer-core/include_internal/core/utils/caf_logger.h
new file mode 100644 (file)
index 0000000..f3c6805
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef _AVPLAY_CAF_LOGGER_H__
+#define _AVPLAY_CAF_LOGGER_H__
+
+#include <mutex>
+#include <queue>
+#include <string>
+#include <utility>
+#include <vector>
+#include <future>
+#include <map>
+#include <boost/core/noncopyable.hpp>
+#include <list>
+
+namespace esplusplayer {
+
+  enum class CafEventType {
+    kNone = 0,
+    kStart,
+    kEnd,
+    kBitrate,
+    kBuffering,
+    kResolution,    
+    kStreamReady,
+    kIdle,
+    kReady,
+    kPlaying,
+    kPaused,
+    kEventMax
+  };
+
+  typedef struct _CafEventData {
+    CafEventType event_type;
+    std::string event_data;
+  }CafEventData;
+
+  class ContextAware  {
+    public:
+      ContextAware() {} 
+      ~ContextAware() {}
+      bool InitService();    
+      void Write(std::string json_data);
+      bool FiniService();
+  };
+
+  class CafLogger {
+    private:
+      static CafLogger *instance_;
+      static std::shared_ptr<ContextAware> context_aware_;
+  
+      std::mutex object_lock_;
+      bool connected_to_dbus_;
+      bool msg_thread_stopped_;
+      std::queue<CafEventData> msg_queue_;
+      std::mutex msg_task_mutex_;
+      std::condition_variable msg_task_cv_;    
+      std::future<void> msg_handler_task_;
+      std::string app_id_;
+      int unique_number;
+      std::queue<int> using_instance_;
+
+      CafLogger();
+      std::string GetEventStrName_(CafEventType event_type);
+      std::string GetEventValueStrName_(CafEventType event_type);
+      std::string GetStateValueStrName_(CafEventType event_type);
+      void SendData_(CafEventData event);
+      void MsgTask_();
+      void StartMsgThread_();
+      void StopMsgThread_();
+      bool PushMessageToQueue_(CafEventType event_type, std::string data);
+      bool isConnected_();
+      bool Connect_();
+      bool Disconnect_();
+      void setAppId_(std::string app_id);
+      void setUniqueNumber_(int uniqueNumber);
+      int getUniqueNumber_();
+           
+    public:
+      static bool Initialize();
+      static bool LogMessage(CafEventType event_type, std::string data);
+      static void StartLoggingThread();
+      static void StopLoggingThread();
+      static void SetAppId(std::string app_id);
+      static void SetUniqueNumber();
+      static std::string GetUniqueNumber();
+      static void SetContextAware(std::shared_ptr<ContextAware>&& context_aware);
+      ~CafLogger();
+  };
+
+} //plusplayer
+
+#endif //_AVPLAY_CAF_LOGGER_H__
old mode 100755 (executable)
new mode 100644 (file)
index b580d1a..9e6f0d7
@@ -2,8 +2,8 @@
 // @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
 //
 
-#ifndef __PLUSPLAYER_SRC_UTILS_PERFORMANCE_CHECKER_H__
-#define __PLUSPLAYER_SRC_UTILS_PERFORMANCE_CHECKER_H__
+#ifndef __ESPLUSPLAYER_SRC_UTILS_PERFORMANCE_CHECKER_H__
+#define __ESPLUSPLAYER_SRC_UTILS_PERFORMANCE_CHECKER_H__
 
 #include <sys/prctl.h>
 #include <ctime>
@@ -15,7 +15,7 @@
 #define PR_TASK_PERF_USER_TRACE 666
 #endif
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace performance_checker {
 
@@ -36,13 +36,13 @@ inline void PerfUsrTrace(const char* arg = nullptr) {
     if(strlen(arg) < (kBufSize - strlen(prefix_str))) {
       use_arg = true;
     }
-  }
+  }  
   snprintf(buf, kBufSize, "%s %s",prefix_str, (use_arg? arg : ""));
   prctl(PR_TASK_PERF_USER_TRACE, buf, strlen(buf));
 }
 
 }  // namespace performance_checker
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_UTILS_PERFORMANCE_CHECKER_H__
+#endif  // __ESPLUSPLAYER_SRC_UTILS_PERFORMANCE_CHECKER_H__
old mode 100755 (executable)
new mode 100644 (file)
index 4b6a781..df588d2
@@ -2,16 +2,16 @@
 // @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
 //
 
-#ifndef __PLUSPLAYER_SRC_CORE_UTIL_PLUSPLAYER_CFG__
-#define __PLUSPLAYER_SRC_CORE_UTIL_PLUSPLAYER_CFG__
+#ifndef __ESPLUSPLAYER_SRC_CORE_UTIL_PLUSPLAYER_CFG__
+#define __ESPLUSPLAYER_SRC_CORE_UTIL_PLUSPLAYER_CFG__
 
-namespace plusplayer {
-
-namespace plusplayer_cfg {
+namespace esplusplayer {
 
+namespace esplusplayer_cfg {
+  
 const char* GetIniPath();
 
-} // namespace plusplayer_cfg
+} // namespace esplusplayer_cfg
 
-} // namespace plusplayer
-#endif  // __PLUSPLAYER_SRC_CORE_UTIL_PLUSPLAYER_CFG__
\ No newline at end of file
+} // namespace esplusplayer
+#endif  // __ESPLUSPLAYER_SRC_CORE_UTIL_PLUSPLAYER_CFG__
\ No newline at end of file
index cf812c3..f9a1285 100644 (file)
@@ -2,14 +2,14 @@
 // @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
 //
 
-#ifndef __PLUSPLAYER_SRC_UTILS_PLUSPLAYER_LOG_H__
-#define __PLUSPLAYER_SRC_UTILS_PLUSPLAYER_LOG_H__
+#ifndef __ESPLUSPLAYER_SRC_UTILS_PLUSPLAYER_LOG_H__
+#define __ESPLUSPLAYER_SRC_UTILS_PLUSPLAYER_LOG_H__
 
 #include <dlog.h>
 #include <string.h>
 
 #undef LOG_TAG
-#define LOG_TAG "MM_ESPP"
+#define LOG_TAG "PLUSPLAYER"
 
 #ifndef __MODULE__
 #define __MODULE__ \
 #define LOG_DEBUG(fmt, arg...) \
   ({                           \
     do {                       \
-      LOGD(fmt, ##arg);        \
+      LOGE(fmt, ##arg);        \
     } while (0);               \
   })
 
 #define LOG_DEBUG_P(id, fmt, arg...)   \
   ({                                   \
     do {                               \
-      LOGD("[%p] > " #fmt, id, ##arg); \
+      LOGE("[%p] > " #fmt, id, ##arg); \
     } while (0);                       \
   })
 
+#define LOG_INFO_I(fmt, arg...) \
+  ({                            \
+    do {                        \
+      LOGI(fmt, ##arg);         \
+    } while (0);                \
+  })
+
 #define LOG_INFO(fmt, arg...) \
   ({                          \
     do {                      \
-      LOGI(fmt, ##arg);       \
+      LOGE(fmt, ##arg);       \
     } while (0);              \
   })
 
 #define LOG_INFO_P(id, fmt, arg...)    \
   ({                                   \
     do {                               \
-      LOGI("[%p] > " #fmt, id, ##arg); \
+      LOGE("[%p] > " #fmt, id, ##arg); \
     } while (0);                       \
   })
 
 #define LOG_WARN(fmt, arg...) \
   ({                          \
     do {                      \
-      LOGW(fmt, ##arg);       \
+      LOGE(fmt, ##arg);       \
     } while (0);              \
   })
 
 #define LOG_WARN_P(id, fmt, arg...)     \
   ({                                    \
     do {                                \
-      LOGW("[ %p] > " #fmt, id, ##arg); \
+      LOGE("[ %p] > " #fmt, id, ##arg); \
     } while (0);                        \
   })
 
     } while (0);               \
   })
 
-#define SECURE_LOG_DEBUG(fmt, arg...)                            \
-({                                                                      \
-  do {                                                                 \
-    SECURE_LOGD(fmt,##arg);                                            \
-  } while (0);                                                       \
-})
-
 #define LOG_ENTER    \
   {                  \
     do {             \
     } while (0);               \
   }
 
-#endif  // __PLUSPLAYER_SRC_UTILS_PLUSPLAYER_LOG_H__
+#endif  // __ESPLUSPLAYER_SRC_UTILS_PLUSPLAYER_LOG_H__
old mode 100755 (executable)
new mode 100644 (file)
index a6295bc..ab784d1
@@ -2,10 +2,10 @@
 // @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
 //
 
-#ifndef __PLUSPLAYER_SRC_UTILS_SCOPE_EXIT_H__
-#define __PLUSPLAYER_SRC_UTILS_SCOPE_EXIT_H__
+#ifndef __ESPLUSPLAYER_SRC_UTILS_SCOPE_EXIT_H__
+#define __ESPLUSPLAYER_SRC_UTILS_SCOPE_EXIT_H__
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace utils {
 
@@ -31,6 +31,6 @@ AtScopeExit<T> ScopeExit(const T& func) {
 
 }  // namespace utils
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
 
-#endif  // __PLUSPLAYER_SRC_UTILS_SCOPE_EXIT_H__
+#endif  // __ESPLUSPLAYER_SRC_UTILS_SCOPE_EXIT_H__
diff --git a/src/plusplayer-core/include_internal/core/videoframetypestrategy.h b/src/plusplayer-core/include_internal/core/videoframetypestrategy.h
new file mode 100644 (file)
index 0000000..12c4afd
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ESPLUSPLAYER_SRC_CORE_VIDEO_FRAME_TYPE_STRATEGY_H__
+#define __ESPLUSPLAYER_SRC_CORE_VIDEO_FRAME_TYPE_STRATEGY_H__
+
+#include <memory>
+
+#include "esplusplayer/types/buffer.h"
+
+namespace esplusplayer {
+struct VideoFrameTypeStrategy {
+  using TrackRendererHandle = void*;
+  virtual ~VideoFrameTypeStrategy() = default;
+  virtual void SetType(TrackRendererHandle handle) = 0;
+};
+
+using VideoFrameTypeStrategyPtr = std::unique_ptr<VideoFrameTypeStrategy>;
+
+class DefaultVideoFrameTypeStrategy : public virtual VideoFrameTypeStrategy {
+ public:
+  explicit DefaultVideoFrameTypeStrategy(
+      const DecodedVideoFrameBufferType type);
+  virtual ~DefaultVideoFrameTypeStrategy() = default;
+  virtual void SetType(TrackRendererHandle handle) override;
+
+ private:
+  const DecodedVideoFrameBufferType type_;
+};
+
+class RawVideoFrameTypeStrategy : public virtual VideoFrameTypeStrategy {
+ public:
+  explicit RawVideoFrameTypeStrategy() = default;
+  virtual ~RawVideoFrameTypeStrategy() = default;
+  virtual void SetType(TrackRendererHandle handle);
+};
+}  // namespace esplusplayer
+
+#endif  // __ESPLUSPLAYER_SRC_CORE_VIDEO_FRAME_TYPE_STRATEGY_H__
\ No newline at end of file
diff --git a/src/plusplayer-core/project_def.prop b/src/plusplayer-core/project_def.prop
new file mode 100644 (file)
index 0000000..51cf809
--- /dev/null
@@ -0,0 +1,58 @@
+
+# Project Name
+APPNAME = plusplayercore_tvplus
+
+# Project Type
+type = sharedLib
+
+# Project Profile
+profile = tv-samsung-5.0
+
+# C/CPP Sources
+USER_SRCS = src/decoderinputbuffer.cpp src/error.cpp src/gstobject_guard.cpp src/gstsignal_holder.cpp src/gst_utils.cpp src/plusplayer_cfg.cpp src/serializer.cpp src/subtitle_attr_parser.cpp src/trackrendereradapter.cpp src/trackrendereradapter_utils.cpp src/track_util.cpp 
+
+# EDC Sources
+USER_EDCS =  
+
+# PO Sources
+USER_POS = 
+
+# User Defines
+USER_DEFS = 
+USER_CPP_DEFS = TIZEN_DEPRECATION DEPRECATION_WARNING 
+
+# User Undefines
+USER_UNDEFS = 
+USER_CPP_UNDEFS = 
+
+# User Libraries
+USER_LIBS = gstsubtitle_tvplus
+
+# User Objects
+USER_OBJS = 
+
+# User Includes
+## C Compiler
+USER_C_INC_DIRS = 
+USER_INC_FILES = 
+## C++ Compiler
+USER_CPP_INC_DIRS = include_internal ../../include ../../../gst-plugins-subtitleparser/subtitle/include_internal
+USER_CPP_INC_FILES = 
+
+USER_INC_DIRS = $(USER_C_INC_DIRS) $(USER_CPP_INC_DIRS)
+
+# User Library Path
+USER_LIB_DIRS = ../../../gst-plugins-subtitleparser/subtitle/${BUILD_CONFIG} 
+
+# EDC Resource Path
+USER_EDCS_IMAGE_DIRS = ${OUTPUT_DIR} 
+USER_EDCS_SOUND_DIRS = ${OUTPUT_DIR} 
+USER_EDCS_FONT_DIRS = ${OUTPUT_DIR} 
+
+# EDC Flags
+USER_EXT_EDC_KEYS = 
+
+# Resource Filter
+USER_RES_INCLUDE = 
+USER_RES_EXCLUDE = 
+
diff --git a/src/plusplayer-core/src/caf_logger.cpp b/src/plusplayer-core/src/caf_logger.cpp
new file mode 100644 (file)
index 0000000..5398401
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _TAG "plusplayer"
+#include "core/utils/caf_logger.h"
+#include "core/utils/plusplayer_log.h"
+#include "context-aware-api.h"
+#include "ContextData.h"
+#include "json/json.h"
+#define SUBJECT_RAW_STREAMING_EVENT   "I/Raw/Streaming/Event"
+
+namespace esplusplayer {
+
+CafLogger* CafLogger::instance_ = NULL;
+std::shared_ptr<ContextAware> CafLogger::context_aware_ = NULL;
+
+std::string EventStrName[] = {"None","Start", "End", "BitRate", "Buffering", "Resolution"};
+
+bool ContextAware::InitService()  {
+  return ContextAware_InitService();
+}
+
+void ContextAware::Write(std::string json_data) {
+  try {
+    ContextAware_WriteRawStreamingEvent(json_data.c_str());
+  } catch (const std::exception& e) {
+    LOG_ERROR("%s", e.what());
+  };
+}
+
+bool ContextAware::FiniService() {
+  return ContextAware_FiniService();
+}
+
+CafLogger::CafLogger() {
+  LOG_ENTER;
+  connected_to_dbus_ = false;
+  std::lock_guard<std::mutex> guard(object_lock_);
+
+  if(context_aware_ == NULL) {
+    context_aware_ = std::make_shared<ContextAware>();
+  }
+
+  if(context_aware_ != NULL)
+    connected_to_dbus_ = context_aware_->InitService();
+  msg_thread_stopped_ = true;
+  app_id_ = "Unknown";
+  unique_number = -1;
+  if(connected_to_dbus_)
+    LOG_INFO("CAF initialized successfully.");
+  else
+    LOG_ERROR("CAF initialization FAILED.");
+
+  LOG_LEAVE;
+}
+
+// LCOV_EXCL_START
+CafLogger::~CafLogger() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> guard(object_lock_);
+  StopMsgThread_();
+  if(connected_to_dbus_ == true && context_aware_ != NULL)
+  {
+    connected_to_dbus_ = context_aware_->FiniService();
+  }
+
+  if(!connected_to_dbus_)
+    LOG_INFO("CAF finished successfully.");
+  LOG_LEAVE;
+}
+
+std::string CafLogger::GetEventStrName_(CafEventType event_type) {
+  if(event_type > CafEventType::kNone && event_type < CafEventType::kEventMax)
+    return EventStrName[(int)event_type];
+  return "";
+}
+// LCOV_EXCL_STOP
+
+
+std::string CafLogger::GetEventValueStrName_(CafEventType event_type) {
+  switch(event_type) {
+// LCOV_EXCL_START
+    case CafEventType::kBitrate: return "BitRateValue";
+    case CafEventType::kResolution: return "ResolutionValue";
+    case CafEventType::kBuffering: return "BufferingValue";
+    default:
+        return "";
+// LCOV_EXCL_STOP
+  }
+}
+
+std::string CafLogger::GetStateValueStrName_(CafEventType event_type) {
+  switch(event_type) {
+// LCOV_EXCL_START
+    case CafEventType::kStreamReady: return "StreamReady";
+    case CafEventType::kIdle: return "Idle";
+    case CafEventType::kReady: return "Ready";
+    case CafEventType::kPlaying: return "Playing";
+    case CafEventType::kPaused: return "Paused";
+    default:
+        return "";
+// LCOV_EXCL_STOP
+  }
+}
+
+void CafLogger::SendData_(CafEventData event) {
+  LOG_ENTER;
+  ContextData cafData;
+  cafData.SetValue("Appid",app_id_);
+  switch(event.event_type) {
+    case CafEventType::kStart: cafData.SetValue("Event", "Start");break;
+    case CafEventType::kEnd: cafData.SetValue("Event", "End");break;
+    case CafEventType::kBuffering: /* FALL THROUGH */
+    //case CafEventType::kResolution: /* FALL THROUGH */
+    case CafEventType::kBitrate: {
+      std::string event_name = GetEventStrName_(event.event_type);
+      cafData.SetValue("Event", event_name);
+      std::string event_value_name = GetEventValueStrName_(event.event_type);
+      cafData.SetValue(event_value_name.c_str(), event.event_data);
+    }break;
+    case CafEventType::kStreamReady: /* FALL THROUGH */
+    case CafEventType::kIdle: /* FALL THROUGH */
+    case CafEventType::kReady: /* FALL THROUGH */
+    case CafEventType::kPlaying: /* FALL THROUGH */
+    case CafEventType::kPaused: {
+      cafData.SetValue("UniqueId", event.event_data);
+      std::string state_value_name = GetStateValueStrName_(event.event_type);
+      cafData.SetValue("PlayerState", state_value_name.c_str());
+    }break;
+    default:
+      return;
+  }
+  LOG_ERROR("all eventdata message [%s]", cafData.MakeStr());
+  if(context_aware_ != NULL)
+    context_aware_->Write(cafData.MakeStr());
+  LOG_LEAVE;
+}
+
+void CafLogger::MsgTask_() {
+LOG_ENTER;
+std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
+  do{
+    if(msg_queue_.empty())
+      msg_task_cv_.wait(msg_mutex);
+    if(!msg_queue_.empty()) {
+      CafEventData eventData = msg_queue_.front();
+      SendData_(eventData);
+      msg_queue_.pop();
+    }
+  } while(!msg_thread_stopped_);
+  LOG_LEAVE;
+}
+
+void CafLogger::StartMsgThread_() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> guard(object_lock_);
+  if(msg_thread_stopped_) {
+    using_instance_.push(unique_number);
+    msg_thread_stopped_ = false;
+    msg_handler_task_ = std::async(std::launch::async, &CafLogger::MsgTask_, this);
+  }
+  LOG_LEAVE;
+}
+
+void CafLogger::StopMsgThread_() {
+  LOG_ENTER;
+
+  if(msg_thread_stopped_) return;
+
+  using_instance_.pop();
+
+  if(msg_handler_task_.valid() && using_instance_.empty()) {
+    std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
+    msg_thread_stopped_ = true;
+    msg_task_cv_.notify_one();
+    msg_mutex.unlock();
+    msg_handler_task_.wait();
+  }
+  LOG_LEAVE;
+}
+
+bool CafLogger::PushMessageToQueue_(CafEventType event_type, std::string data) {
+  LOG_ENTER;
+  bool ret = false;
+  std::lock_guard<std::mutex> guard(object_lock_);
+  if(msg_handler_task_.valid()) {
+    CafEventData event;
+    event.event_type = event_type;
+    event.event_data = data;
+    std::unique_lock<std::mutex> msg_mutex(msg_task_mutex_);
+    msg_queue_.push(event);
+    msg_mutex.unlock();
+    msg_task_cv_.notify_one();
+    ret = true;
+  }
+  LOG_LEAVE;
+  return ret;
+}
+// LCOV_EXCL_START
+
+bool CafLogger::Connect_() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> guard(object_lock_);
+  if(!connected_to_dbus_ && context_aware_ != NULL)
+    connected_to_dbus_ = context_aware_->InitService();
+  LOG_LEAVE;
+  return connected_to_dbus_;
+}
+
+bool CafLogger::Disconnect_() {
+  LOG_ENTER;
+  std::lock_guard<std::mutex> guard(object_lock_);
+  /*first stop message thread, then disconnect. */
+
+  StopMsgThread_();
+  LOG_INFO("Disconnecting to DBus.");
+  if(connected_to_dbus_ && context_aware_ != NULL)
+    connected_to_dbus_ = context_aware_->FiniService();
+  if(!connected_to_dbus_)
+    LOG_INFO("Disconnecting to DBus FAILED.");
+  connected_to_dbus_ = false;
+  LOG_LEAVE;
+  return true;
+}
+// LCOV_EXCL_STOP
+
+bool CafLogger::isConnected_() {
+  return connected_to_dbus_;
+}
+
+void CafLogger::setAppId_(std::string app_id) {
+  app_id_ = app_id;
+}
+
+void CafLogger::setUniqueNumber_(int uniqueNumber) {
+  unique_number = uniqueNumber;
+}
+
+int CafLogger::getUniqueNumber_() {
+  return unique_number;
+}
+/********   STATIC FUNCTIONS ****************/
+
+bool CafLogger::Initialize() {
+  LOG_ENTER;
+
+  if(instance_ == NULL) {
+     instance_ = new CafLogger();
+  }
+  LOG_LEAVE;
+  return instance_->isConnected_();
+}
+
+bool CafLogger::LogMessage(CafEventType event_type, std::string data) {
+  LOG_ENTER;
+  bool ret = false;
+#ifndef SDK_DISABLED_FEATURE
+  if(instance_ != NULL && instance_->isConnected_()) {
+    ret = instance_->PushMessageToQueue_(event_type, data);
+  }
+#endif
+  LOG_LEAVE;
+  return ret;
+}
+
+void CafLogger::StartLoggingThread() {
+  LOG_ENTER;
+  if(instance_ != NULL)
+    instance_->StartMsgThread_();
+  LOG_LEAVE;
+}
+
+void CafLogger::StopLoggingThread() {
+  LOG_ENTER;
+  if(instance_ != NULL){
+    std::lock_guard<std::mutex> guard(instance_->object_lock_);
+    instance_->StopMsgThread_();
+  }
+  LOG_LEAVE;
+}
+
+void CafLogger::SetAppId(std::string app_id) {
+  LOG_ENTER;
+  if(instance_ != NULL)
+    instance_->setAppId_(app_id);
+  LOG_LEAVE;
+}
+
+void CafLogger::SetUniqueNumber()
+{
+  LOG_ENTER;
+    int id = -1;
+    if(instance_ != NULL)
+    {
+      id = instance_->getUniqueNumber_();
+      instance_->setUniqueNumber_(++id);
+    }
+  LOG_LEAVE;
+}
+std::string CafLogger::GetUniqueNumber()
+{
+  LOG_ENTER;
+  int id = -1;
+  std::string uniqueNumber;
+  if(instance_ != NULL)
+  {
+    id = instance_->getUniqueNumber_();
+    uniqueNumber = std::to_string(getpid()) + "_" + std::to_string(id);
+  }
+  LOG_LEAVE;
+  return uniqueNumber;
+}
+
+// LCOV_EXCL_START
+void CafLogger::SetContextAware(std::shared_ptr<ContextAware>&& context_aware)
+{
+  LOG_ENTER;
+  context_aware_ = context_aware;
+  LOG_LEAVE;
+}
+// LCOV_EXCL_STOP
+
+} //plusplayer
diff --git a/src/plusplayer-core/src/decodedvideopacketex.cpp b/src/plusplayer-core/src/decodedvideopacketex.cpp
new file mode 100644 (file)
index 0000000..266ce0f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "esplusplayer/decodedvideopacketex.h"
+
+namespace esplusplayer {
+
+// LCOV_EXCL_START
+  DecodedVideoPacketExPtr DecodedVideoPacketEx::Create(const uint64_t pts,
+                      const uint64_t duration, tbm_surface_h surface_data,
+                      const void* scaler_index) {
+    return Ptr(new DecodedVideoPacketEx(pts, duration, surface_data, scaler_index));
+  }
+
+  DecodedVideoPacketEx::~DecodedVideoPacketEx() {
+    if (surface_data_) {
+      tbm_surface_destroy(surface_data_);
+      surface_data_ = nullptr;
+    }
+  }
+// LCOV_EXCL_STOP
+
+}  // namespace esplusplayer
index 1087462..92510ec 100644 (file)
@@ -1,20 +1,34 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "core/decoderinputbuffer.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace decoderinputbuffer_util {
 
+// LCOV_EXCL_START
 bool FlushQueue(std::queue<DecoderInputBufferPtr>& queue) {
   while (!queue.empty()) {
     queue.pop();
   }
   return true;
 }
+// LCOV_EXCL_STOP
 
 }  // namespace decoderinputbuffer_util
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
index 2f8fa14..5873cb9 100644 (file)
@@ -1,13 +1,25 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "core/error.h"
 
 #include "core/gstobject_guard.h"
 #include "core/utils/plusplayer_log.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace internal {
 
@@ -18,6 +30,7 @@ ErrorType ConvertGstStreamError(const GError* error);
 
 }  // namespace internal
 
+// LCOV_EXCL_START
 ErrorType HandleGstError(const GError* error) {
   ErrorType ret = ErrorType::kNone;
 
@@ -153,7 +166,8 @@ ErrorType ConvertGstStreamError(const GError* error) {
   }
   return type;
 }
+// LCOV_EXCL_STOP
 
 }  // namespace internal
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
index 2036e8b..a9c577e 100644 (file)
@@ -1,85 +1,41 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "core/gst_utils.h"
 
 #include <cassert>
 #include <thread>
 
 #include "core/utils/plusplayer_log.h"
-#include "core/gstobject_guard.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace gst_util {
 
-void ShowStateChangedMsg(GstMessage* msg, void* id) {
-  GstState old_state = GST_STATE_VOID_PENDING;
-  GstState new_state = GST_STATE_VOID_PENDING;
-  GstState pending_state = GST_STATE_VOID_PENDING;
-  gst_message_parse_state_changed(msg, &old_state, &new_state, &pending_state);
-  LOG_INFO_P(id, "thread[%p] msg[%p], old[%8s], new[%8s], pending[%8s] src[%s]",
-           g_thread_self(), msg, gst_element_state_get_name(old_state),
-           gst_element_state_get_name(new_state),
-           gst_element_state_get_name(pending_state),
-           GST_MESSAGE_SRC_NAME(msg));
-}
-
-void SetGstStateToNull(GstElement* pipeline, void* id) {
-  if (!pipeline) return;
-  GstStateChangeReturn ret;
-  ret = gst_element_set_state(pipeline, GST_STATE_NULL);
-  if (ret == GST_STATE_CHANGE_FAILURE) {
-    LOG_ERROR_P(id, "Set State to NULL failed");
-    assert(0 && "Set State to NULL failed");
-  }
-}
-
-const gchar* GetElementName(const GstMessage* msg) {
-  GstElement* src_element = GST_ELEMENT_CAST(msg->src);
-  if (!src_element) return nullptr;
-
-  return GST_ELEMENT_NAME(src_element);
-}
-
-const gchar* GetKlass(const GstMessage* msg) {
-  GstElement* src_element = GST_ELEMENT_CAST(msg->src);
-  if (!src_element) return nullptr;
-
-  GstElementFactory* factory = gst_element_get_factory(src_element);
-  if (!factory) return nullptr;
-
-  return gst_element_factory_get_klass(factory);
-}
-
-namespace internal {
-  void DisableGstPlugin(const std::string& plugin_name) {
-    LOG_INFO("disabling gst plugin [%s]", plugin_name.c_str());
-    GstRegistry *registry = gst_registry_get ();
-    if (!registry) {
-      LOG_ERROR("failed to get registry");
-      return;
-    }
-    GstElementFactory *factory = gst_element_factory_find (plugin_name.c_str());
-    if (!factory) {
-      LOG_DEBUG("gst plugin not found [%s]", plugin_name.c_str());
-      return;
-    }
-    gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), GST_RANK_NONE);
-    gst_registry_add_feature (registry, GST_PLUGIN_FEATURE (factory));
-  }
-}
-
+// LCOV_EXCL_START
 void GstInit() {
   gst_init(NULL,NULL);
 }
+// LCOV_EXCL_STOP
 
 void GstInit(const Json::Value& root) {
-  int argc = 0;
+  int argc = 1;
   char* argv[6]{
       nullptr,
   };
-  argv[argc++] = const_cast<char*>("Plusplayer");
   std::string gstparam1 = root.get("gstparam1", "").asString();
   argv[argc++] = const_cast<char*>(gstparam1.c_str());
   std::string gstparam2 = root.get("gstparam2", "").asString();
@@ -96,188 +52,8 @@ void GstInit(const Json::Value& root) {
   }
   char** pargv = argv;
   gst_init(&argc, &pargv);
-
-  /* disable gst plugins */
-  auto plugins = root.get("gst_plugins_disable", Json::arrayValue);
-  if (plugins.isArray()) {
-    for(auto plugin: plugins) {
-      std::string plugin_name = plugin.asString();
-      internal::DisableGstPlugin(plugin_name);
-    }
-  } else {
-    LOG_ERROR("'gst_plugins_disable' not an array [%s]", plugins.asString().c_str());
-  }
-}
-
-namespace internal {
-GList* GetFactories(GstCaps * caps, GstElementFactoryListType type) {
-  GList *factories = nullptr;
-  GList *filtered = nullptr;
-
-  auto caps_str = gstguard::make_guard(gst_caps_to_string(caps));
-  LOG_INFO("requesting factories for caps [%s]", caps_str.get());
-
-  /* return all compatible factories for caps */
-  factories =
-    gst_element_factory_list_get_elements (type, GST_RANK_MARGINAL);
-  if (factories) {
-    filtered = gst_element_factory_list_filter (factories, caps, GST_PAD_SINK,
-                                                gst_caps_is_fixed (caps));
-    gst_plugin_feature_list_free(factories);
-  }
-  if (!filtered)
-    LOG_ERROR("failed to get factories");
-
-  return filtered;
-}
-} //namespace internal
-
-GstElement* MakeElement(GstCaps * caps, GstElementFactoryListType type) {
-  GList *factories = nullptr;
-  GstElementFactory *factory = nullptr;
-  GstElement *element = nullptr;
-
-  auto caps_str = gstguard::make_guard(gst_caps_to_string(caps));
-  LOG_INFO("requesting factories for caps [%s]", caps_str.get());
-
-  factories = internal::GetFactories((GstCaps*)caps, type);
-  if (!factories) {
-    LOG_ERROR("failed to get factories");
-    return nullptr;
-  }
-
-  factory = GST_ELEMENT_FACTORY_CAST(factories->data);
-
-  LOG_INFO("Klass [%s] Factory [%s]",
-    gst_element_factory_get_klass(factory), GST_OBJECT_NAME(factory));
-  element = gst_element_factory_create (factory, NULL);
-  gst_plugin_feature_list_free (factories);
-
-  if (!element) {
-    LOG_ERROR("failed to make element");
-    return nullptr;
-  }
-
-  return element;
-}
-
-GstElement* MakeCapsFilter(GstPad * pad, GstElementFactoryListType type, const char* klass_keyword) {
-  GList *factories = nullptr;
-  GList *tmp = nullptr;
-  GstCaps *caps = nullptr;
-  GstCaps *filter_caps = nullptr;
-  GstElement *element = nullptr;
-  if (!pad) {
-    LOG_ERROR("invalid input : pad is null");
-    return nullptr;
-  }
-
-  caps = gst_pad_get_current_caps (pad);
-  if (!caps) {
-    LOG_ERROR ("there is no current caps, use query caps");
-    caps = gst_pad_query_caps (pad, nullptr);
-  }
-
-  auto caps_str = gstguard::make_guard(gst_caps_to_string(caps));
-  LOG_INFO("[%s:%s][%s]", GST_DEBUG_PAD_NAME(pad), caps_str.get());
-  LOG_DEBUG("factory keyword : %s", klass_keyword);
-
-  factories = internal::GetFactories((GstCaps*)caps, type);
-  if (!factories) {
-    LOG_ERROR("there is no factories");
-    gst_caps_unref (caps);
-    return nullptr;
-  }
-
-  LOG_DEBUG ("factory len %d", g_list_length(factories));
-  filter_caps = gst_caps_new_empty ();
-
-  for (tmp = factories; tmp; tmp = tmp->next) {
-    GstCaps *tcaps, *intersection;
-    const GList *tmps;
-    GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
-
-    if (factory) {
-      const gchar *klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
-
-      if (!g_strrstr(klass, klass_keyword))
-        continue;
-
-      LOG_DEBUG ("Trying factory %s",
-          gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
-
-      for (tmps = gst_element_factory_get_static_pad_templates (factory); tmps;
-          tmps = tmps->next) {
-        GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
-        if (st->direction != GST_PAD_SINK || st->presence != GST_PAD_ALWAYS)
-          continue;
-        tcaps = gst_static_pad_template_get_caps (st);
-        intersection =
-            gst_caps_intersect_full (tcaps, caps, GST_CAPS_INTERSECT_FIRST);
-        filter_caps = gst_caps_merge (filter_caps, intersection);
-        gst_caps_unref (tcaps);
-      }
-    }
-  }
-
-  filter_caps = gst_caps_merge (filter_caps, gst_caps_ref (caps));
-
-  auto filter_caps_str = gstguard::make_guard(gst_caps_to_string(filter_caps));
-  LOG_INFO("create capsfilter with [%s]", filter_caps_str.get());
-
-  element = gst_element_factory_make ("capsfilter", NULL);
-  g_object_set (G_OBJECT (element), "caps", filter_caps, NULL);
-
-  gst_caps_unref (filter_caps);
-  gst_caps_unref (caps);
-  gst_plugin_feature_list_free (factories);
-
-  return element;
-}
-
-char** GetCookieList(const char* cookies) {
-  char **cookie_list = nullptr;
-  char *temp = nullptr;
-  char *trim = nullptr;
-  guint i = 0;
-
-  if (!cookies || !strlen(cookies))
-    return nullptr;
-
-  SECURE_LOG_DEBUG("cookies : %zu[bytes] - %s", strlen(cookies), cookies);
-
-  trim = temp = g_strdup(cookies);
-
-  /* trimming. it works inplace */
-  g_strstrip(trim);
-
-  /* split */
-  cookie_list = g_strsplit(trim, ";", 100);
-
-  if (!cookie_list) {
-    LOG_ERROR("failed to get cookie list");
-    goto EXIT;
-  }
-
-  for (i = 0; i < g_strv_length(cookie_list); i++) {
-    if (cookie_list[i]) {
-      if (strlen(cookie_list[i])) {
-        g_strstrip(cookie_list[i]);
-        SECURE_LOG_DEBUG("cookie_list[%d] : %zu[bytes] - %s", i,
-              strlen(cookie_list[i]), cookie_list[i]);
-      } else {
-        cookie_list[i][0] = '\0';
-      }
-    }
-  }
-
-EXIT:
-  if(temp)
-    g_free(temp);
-
-  return cookie_list;
 }
 
 }  // namespace gst_util
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
index 3f62e9d..c0036ab 100644 (file)
@@ -1,16 +1,30 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "glib.h"
 
 #include "core/gstobject_guard.h"
 
 #include "core/utils/plusplayer_log.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace gstguard {
 
+// LCOV_EXCL_START
 void CustomDeleter(GstCaps* obj) { gst_caps_unref(obj); }
 
 void CustomDeleter(GstObject* obj) { gst_object_unref(obj); }
@@ -44,7 +58,8 @@ void CustomDeleter(GValue* obj) { g_value_unset(obj); }
 void CustomDeleter(GstIterator* obj) { gst_iterator_free(obj); }
 
 void CustomDeleter(GBytes* obj) { g_bytes_unref(obj); }
+// LCOV_EXCL_STOP
 
 }  // namespace gstguard
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
diff --git a/src/plusplayer-core/src/gstsignal_holder.cpp b/src/plusplayer-core/src/gstsignal_holder.cpp
deleted file mode 100644 (file)
index 837cb97..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#include "core/gstsignal_holder.h"
-
-#include "core/utils/plusplayer_log.h"
-
-namespace plusplayer {
-
-class GstSignalHolder::GstSignalItem {
- public:
-  GstSignalItem(GObject* obj, const char* signal_name, GCallback handler,
-                gpointer data)
-      : obj_(obj) {
-    gst_object_ref(obj_);
-    sig_ = g_signal_connect(obj_, signal_name, handler, data);
-    if (sig_ == 0)
-      LOG_INFO("g_signal_connect return error. object[ %s ]",
-               GST_OBJECT_NAME(obj_));
-  }
-  ~GstSignalItem() {
-    if (g_signal_handler_is_connected(obj_, sig_))
-      g_signal_handler_disconnect(obj_, sig_);
-    LOG_INFO("Disconnect signal [%lu]", sig_);
-    gst_object_unref(obj_);
-  }
-
- private:
-  GstSignalItem() = default;
-  GObject* obj_ = nullptr;
-  gulong sig_ = 0;
-};
-
-namespace internal {
-
-void DisconnectSignal(const GValue* item, gpointer user_data);
-
-}  // namespace internal
-
-GstSignalHolder::GstSignalHolder() {}
-GstSignalHolder::~GstSignalHolder() {
-  std::lock_guard<std::mutex> guard(item_lock_);
-  signal_list_.clear();
-}
-
-void GstSignalHolder::Add(GObject* obj, const char* signal_name,
-                          GCallback handler, gpointer data) {
-  std::lock_guard<std::mutex> guard(item_lock_);
-  std::unique_ptr<GstSignalItem> item(
-      new GstSignalItem(obj, signal_name, handler, data));
-  signal_list_.insert(std::pair<GObject*, std::unique_ptr<GstSignalItem>>(
-      obj, std::move(item)));
-}
-
-void GstSignalHolder::Delete(GObject* obj) {
-  if (!obj || !GST_IS_ELEMENT(obj)) {
-    LOG_ERROR("object null or object is not gst element");
-    return;
-  }
-
-  std::lock_guard<std::mutex> guard(item_lock_);
-  if (GST_IS_BIN(obj)) {
-    GstIterator* it = gst_bin_iterate_elements(GST_BIN_CAST(obj));
-    while (gst_iterator_foreach(it,
-                         (GstIteratorForeachFunction)internal::DisconnectSignal,
-                         (gpointer) this) == GST_ITERATOR_RESYNC)
-      gst_iterator_resync(it);
-    gst_iterator_free(it);
-  }
-  signal_list_.erase(obj);
-}
-
-void GstSignalHolder::DeleteAll() {
-  std::lock_guard<std::mutex> guard(item_lock_);
-  LOG_INFO("num of signals[ %" G_GSIZE_FORMAT " ]", signal_list_.size());
-  signal_list_.clear();
-}
-
-namespace internal {
-
-void DisconnectSignal(const GValue* item, gpointer user_data) {
-  GstSignalHolder* pthis = static_cast<GstSignalHolder*>(user_data);
-  GstElement* element = GST_ELEMENT_CAST(g_value_get_object(item));
-  pthis->Delete(G_OBJECT(element));
-}
-
-}  // namespace internal
-
-}  // namespace plusplayer
diff --git a/src/plusplayer-core/src/kpi.cpp b/src/plusplayer-core/src/kpi.cpp
new file mode 100644 (file)
index 0000000..40dcd44
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "core/kpi.h"
+
+#include <sstream>
+
+#include "core/utils/plusplayer_log.h"
+
+/* for logger */
+#include "capi-system-info/system_info.h"
+#include "logger/Logger2.h"
+
+using namespace KPILogFramework;
+
+namespace esplusplayer {
+
+const char* GetProductYear(void) {
+  static const char* year = nullptr;
+  if (year) return year;
+
+  int value = -1;
+  int result = system_info_get_custom_int(
+      "com.samsung/featureconf/product.tv_year", &value);
+  if (result != SYSTEM_INFO_ERROR_NONE || value < 0) {
+    LOG_ERROR(
+          "can't get com.samsung/featureconf/product.tv_year, result:%d, "
+          "value:%d",
+          result, value);
+    return "20";
+  }
+
+  static char str_year[3] = {0, };
+  int size = snprintf(str_year, 3, "%d", value);
+  if (size != 2) {
+    LOG_ERROR("size is not 2!! size:%d, year:%d", size, value);
+    return "20";
+  }
+
+  year = str_year;
+  return year;
+}
+
+// LCOV_EXCL_START
+namespace internal {
+std::string GetSrcType(SourceType ptype) {
+  switch (ptype) {
+    case SourceType::kHttp:
+      return "HTTP";
+    case SourceType::kHls:
+      return "HLS";
+    case SourceType::kDash:
+      return "DASH";
+    case SourceType::kFile:
+      return "FILE";
+    case SourceType::kNone:
+    case SourceType::kBase:
+    case SourceType::kExternalSubtitle:
+    case SourceType::kMax:
+    default:
+      return "others";
+  }
+}
+
+std::string GetDrmType(drm::Type dtype) {
+  switch (dtype) {
+    case drm::Type::kNone:
+      return "NONE";
+    case drm::Type::kPlayready:
+      return "PLAYREADY";
+    case drm::Type::kMarlin:
+      return "MARLIN";
+    case drm::Type::kVerimatrix:
+      return "VERIMATRIX";
+    case drm::Type::kWidevineClassic:
+      return "WIDEVINE CLASSIC";
+    case drm::Type::kSecuremedia:
+      return "SECUREMEDIA";
+    case drm::Type::kSdrm:
+      return "SDRM";
+    case drm::Type::kWidevineCdm:
+      return "WIDEVINE CDM";
+    case drm::Type::kMax:
+    default:
+      return "others";
+  }
+}
+
+std::string GetDecoderType(int ctype) {  //(0:DEFAULT, 1:HW, 2:SW, 3:DISABLE)
+  if (ctype == 0 || ctype == 1) {
+    return "HW";
+  } else if (ctype == 2) {
+    return "SW";
+  } else {
+    return "DISABLE";
+  }
+}
+}  // namespace internal
+
+namespace kpi {
+bool CodecLogger::SendKpi(bool event_case, const CodecLoggerKeys& keys) {
+  LOG_ENTER;
+
+  std::string ptype = internal::GetSrcType(keys.src_type);
+  std::string drm_type = internal::GetDrmType(keys.drm_type);
+  std::string v_decoder_type = internal::GetDecoderType(keys.v_decoder_type);
+  std::string a_decoder_type = internal::GetDecoderType(keys.a_decoder_type);
+
+  // generate message
+  std::stringstream str;
+  str << "{";
+  str << "ptype=" << ptype;
+  str << ";dtype=" << drm_type;
+  str << ";data_container=" << keys.container_type;
+  str << ";v_decoder_type=" << v_decoder_type;
+  str << ";v_codec=" << keys.v_codec;
+  str << ";v_tag=0x" << std::hex << keys.v_tag;
+  str << ";width=" << std::dec << keys.width;
+  str << ";height=" << std::dec << keys.height;
+  str << ";a_decoder_type=" << a_decoder_type;
+  str << ";a_codec=" << keys.a_codec;
+  str << ";a_tag=0x" << std::hex << keys.a_tag;
+  str << ";app_id=" << keys.app_id;
+  str << "}";
+
+  return SendKpi_(event_case, str);
+}
+// LCOV_EXCL_STOP
+
+bool CodecLogger::SendKpi(bool event_case, const EsCodecLoggerKeys& keys) {
+  LOG_ENTER;
+
+  std::string ptype = keys.is_clean ? "MSE" : "EME";
+  std::string drm_type = keys.is_clean ? "NONE" : "EME";
+  std::string v_decoder_type("HW");
+  std::string a_decoder_type("HW");
+  std::string container_type("EsPlusplayer");
+  unsigned int video_tag = 0;
+  unsigned int audio_tag = 0;
+  std::string video_codec = keys.v_codec + "-" +
+                            std::to_string(keys.v_codec_version);
+
+  // generate message
+  std::stringstream str;
+  str << "{";
+  str << "ptype=" << ptype;
+  str << ";dtype=" << drm_type;
+  str << ";data_container=" << container_type;
+  str << ";v_decoder_type=" << v_decoder_type;
+  str << ";v_codec=" << keys.v_codec;
+  str << ";v_tag=0x" << std::hex << video_tag;
+  str << ";width=" << std::dec << keys.width;
+  str << ";height=" << std::dec << keys.height;
+  str << ";a_decoder_type=" << a_decoder_type;
+  str << ";a_codec=" << keys.a_codec;
+  str << ";a_tag=0x" << std::hex << audio_tag;
+  str << ";app_id=" << keys.app_id;
+  str << "}";
+
+  return SendKpi_(event_case, str);
+}
+
+bool CodecLogger::SendKpi_(bool event_case, const std::stringstream& message) {
+  LOG_ENTER;
+  const char* year = GetProductYear();
+
+  // send message to KPI logger
+  std::stringstream service_name;
+  service_name << year << "_codec";
+  std::string eventName;
+  std::string category;
+  if (event_case) {
+    eventName = "PLAYBACK";
+    category = "EV001";
+  } else {
+    eventName = "ERRPLAY";
+    category = "EV002";
+  }
+
+  LOG_ERROR("[KPI] service_name: %s, desc_log: %s",
+            service_name.str().c_str(), message.str().c_str());
+
+  CLogger* pLogger = CLogger::GetInstance();
+  LoggerErrorCode result = LOGGER_ERROR_NONE;
+  result = pLogger->AddEventLogSync(service_name.str().c_str(), eventName.c_str(),
+                                    category.c_str(), message.str().c_str());
+  if (result != LOGGER_ERROR_NONE) {
+    LOG_ERROR("Failed to send KPI log for esplayer, result:%d", result);
+    return false;
+  }
+
+  return true;
+}
+
+
+}  // namespace kpi
+}  // namespace esplusplayer
index a8e8c83..5424119 100644 (file)
@@ -1,14 +1,28 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <cassert>
 
+#if defined(TIZEN_FEATURE_PUBLIC) || !defined(PLUPLAYER_DOWNLOADABLE_APP_TVPLUS)
 #include "tzplatform_config.h"
+#endif
 
-namespace plusplayer {
+namespace esplusplayer {
 
-namespace plusplayer_cfg {
+namespace esplusplayer_cfg {
 
 const char* GetIniPath() {
   const char* path =
@@ -17,6 +31,6 @@ const char* GetIniPath() {
   return path;
 }
 
-} // namespace plusplayer_cfg
+} // namespace esplusplayer_cfg
 
-} // namespace plusplayer
\ No newline at end of file
+} // namespace esplusplayer
\ No newline at end of file
index 6e994a8..e615b5a 100644 (file)
@@ -1,15 +1,27 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "core/serializer.h"
-
-namespace plusplayer {
+// LCOV_EXCL_START
+namespace esplusplayer {
 using Offset = Serializer::Offset;
 using Byte = Serializer::Byte;
 
 Offset Serializer::Put(const std::vector<unsigned char> &vector) {
-  Offset offset = size_;
+  Offset offset = static_cast<unsigned int>(size_);
   if (vector.size() == 0) return offset;
   const size_t size = vector.size();
   const Byte *data_bytes = reinterpret_cast<const Byte *>(vector.data());
@@ -18,7 +30,7 @@ Offset Serializer::Put(const std::vector<unsigned char> &vector) {
 }
 
 Offset Serializer::Put(const std::string &data) {
-  Offset offset = size_;
+  Offset offset = static_cast<unsigned int>(size_);
   if (data.length() == 0) return offset;
   const size_t size = data.length();
   const Byte *data_bytes = reinterpret_cast<const Byte *>(data.c_str());
@@ -27,21 +39,23 @@ Offset Serializer::Put(const std::string &data) {
 }
 
 Offset Serializer::Put(const Byte *data, size_t size) {
-  Offset offset = size_;
+  Offset offset = static_cast<unsigned int>(size_);
   if (size == 0) return offset;
   Put_(data, size);
   return offset;
 }
 
 size_t Serializer::Serialize(Byte *serialized) {
-  buf_.sgetn(serialized, static_cast<std::streamsize>(size_));
+  buf_.sgetn(serialized, size_);
   return size_;
 }
 
 const size_t Serializer::GetSize() { return size_; }
 
 void Serializer::Put_(const Byte *data_bytes, const size_t size) {
-  buf_.sputn(data_bytes, static_cast<std::streamsize>(size));
+  buf_.sputn(data_bytes, size);
   size_ += size;
 }
-}  // namespace plusplayer
+}
+// LCOV_EXCL_STOP
+// namespace esplusplayer
diff --git a/src/plusplayer-core/src/subtitle_attr_parser.cpp b/src/plusplayer-core/src/subtitle_attr_parser.cpp
deleted file mode 100644 (file)
index 14f16c5..0000000
+++ /dev/null
@@ -1,556 +0,0 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
-
-#include "core/subtitle_attr_parser.h"
-
-#include <algorithm>
-#include <cassert>
-
-#include "gst/ffsubtitle/gstsubattributes.h"
-
-#include "core/utils/plusplayer_log.h"
-
-namespace plusplayer {
-
-#ifdef PLUPLAYER_DOWNLOADABLE_APP_TVPLUS
-#define GST_SUB_ATTRI_FUNC(name) gst_sub_attributes_##name
-#define GST_SUB_ATTRI_ENUM(name) GST_SUB_ATTRIBUTES_##name
-#define GstSubAttriScope GstSubAttributesScope
-#define GstSubAttriType GstSubAttributesType
-#else
-#define GST_SUB_ATTRI_FUNC(name) gst_sub_attribute_##name
-#define GST_SUB_ATTRI_ENUM(name) GST_SUB_ATTRI_##name
-#define GstSubAttriScope GstSubAttributeScope
-#define GstSubAttriType GstSubAttributeType
-#endif
-
-namespace internal {
-void AddSubtitleAttribute(std::list<SubtitleAttr>* list,
-                          const SubtitleAttrType type, const boost::any& value,
-                          const unsigned int start_pos,
-                          const unsigned int stop_pos) {
-  list->emplace_back(type, start_pos, stop_pos, value, -1);
-}
-
-bool ComparingStartTime(const SubtitleAttr& a, const SubtitleAttr& b) {
-  return (a.start_time < b.start_time);
-}
-
-constexpr int kAttrInvalidIntVal = -1;
-constexpr unsigned int kAttrInvalidUintVal =
-    std::numeric_limits<unsigned int>::max();
-constexpr float kAttrInvalidFloatVal = 0.0;
-
-void ParseSubtitleRegionAttr(GstStructure* attribute,
-                             std::list<SubtitleAttr>* attr_list) {
-  LOG_ENTER;
-  while (attribute) {
-    gfloat x_pos = kAttrInvalidIntVal, y_pos = kAttrInvalidFloatVal,
-           width = kAttrInvalidFloatVal, height = kAttrInvalidFloatVal;
-    attribute = GST_SUB_ATTRI_FUNC(region_parse)(attribute, &x_pos, &y_pos,
-                                               &width, &height);
-    LOG_DEBUG(
-        "parsed new region attribute: x(%f), y(%f), width(%f), "
-        "height(%f)",
-        x_pos, y_pos, width, height);
-    if (x_pos != kAttrInvalidFloatVal) {
-      boost::any value = x_pos;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrRegionXPos, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (y_pos != kAttrInvalidFloatVal) {
-      boost::any value = y_pos;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrRegionYPos, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (width != kAttrInvalidFloatVal) {
-      boost::any value = width;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrRegionWidth, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (height != kAttrInvalidFloatVal) {
-      boost::any value = height;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrRegionHeight, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-  }
-}
-
-void ParseSubtitleWindowAttr(GstStructure* attribute,
-                             std::list<SubtitleAttr>* attr_list) {
-  LOG_ENTER;
-  while (attribute) {
-    gfloat x_padding = kAttrInvalidFloatVal, y_padding = kAttrInvalidFloatVal;
-    gint l_margin = kAttrInvalidIntVal, r_margin = kAttrInvalidIntVal,
-         t_margin = kAttrInvalidIntVal, b_margin = kAttrInvalidIntVal;
-    guint bg_color = kAttrInvalidUintVal;
-    gfloat opacity = kAttrInvalidFloatVal;
-    guint show_bg = kAttrInvalidUintVal;
-    attribute = GST_SUB_ATTRI_FUNC(window_parse)(
-        attribute, &x_padding, &y_padding, &l_margin, &r_margin, &t_margin,
-        &b_margin, &bg_color, &opacity, &show_bg);
-    LOG_DEBUG(
-        "parsed new window attribute: x_padding(%f), y_padding(%f), "
-        "l_margin(%d), r_margin(%d), t_margin(%d), b_margin(%d), "
-        "bg_color(%u), opacity(%f), show_bg(%u)",
-        x_padding, y_padding, l_margin, r_margin, t_margin, b_margin, bg_color,
-        opacity, show_bg);
-    if (x_padding != kAttrInvalidFloatVal) {
-      boost::any value = x_padding;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowXPadding, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (y_padding != kAttrInvalidFloatVal) {
-      boost::any value = y_padding;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowYPadding, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (l_margin != kAttrInvalidIntVal) {
-      boost::any value = l_margin;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowLeftMargin, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (r_margin != kAttrInvalidIntVal) {
-      boost::any value = r_margin;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowRightMargin,
-                                     value, kAttrInvalidUintVal,
-                                     kAttrInvalidUintVal);
-    }
-    if (t_margin != kAttrInvalidIntVal) {
-      boost::any value = t_margin;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowTopMargin, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (b_margin != kAttrInvalidIntVal) {
-      boost::any value = b_margin;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowBottomMargin,
-                                     value, kAttrInvalidUintVal,
-                                     kAttrInvalidUintVal);
-    }
-    if (bg_color != kAttrInvalidUintVal) {
-      boost::any value = bg_color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowBgColor, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (opacity != kAttrInvalidFloatVal) {
-      boost::any value = opacity;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowOpacity, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-    if (show_bg != kAttrInvalidUintVal) {
-      boost::any value = show_bg;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWindowShowBg, value,
-                                     kAttrInvalidUintVal, kAttrInvalidUintVal);
-    }
-  }
-}
-
-void ParseSubtitleFontAttr(GstStructure* attribute,
-                           std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute font!");
-  while (attribute) {
-    GstSubAttriScope scope;
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    gchar* family = nullptr;
-    gfloat size = kAttrInvalidFloatVal;
-    gint weight = kAttrInvalidIntVal, style = kAttrInvalidIntVal;
-    guint color = kAttrInvalidUintVal, bg_color = kAttrInvalidUintVal;
-    gfloat opacity = kAttrInvalidFloatVal, bg_opacity = kAttrInvalidFloatVal;
-    guint text_outline_color = kAttrInvalidUintVal,
-          text_outline_tn = kAttrInvalidUintVal;
-    gint text_outline_br = kAttrInvalidIntVal, v_align = kAttrInvalidIntVal,
-         h_align = kAttrInvalidIntVal;
-    attribute = GST_SUB_ATTRI_FUNC(font_parse)(
-        attribute, &scope, &start_index, &stop_index, &family, &size, &weight,
-        &style, &color, &bg_color, &opacity, &bg_opacity, &text_outline_color,
-        &text_outline_tn, &text_outline_br, &v_align, &h_align);
-    LOG_DEBUG(
-        "passed a font attribute: scope(%u), start_index(%u), "
-        "stop_index(%u), family(%s), size(%f),"
-        "weight(%d), style(%d), color(%u), bg_color(%u), opacity(%f), "
-        "bg_opacity(%f), text_outline_color(%u),"
-        "text_outline_tn(%u),text_outline_br(%d), v_align(%d), "
-        "h_align(%d)",
-        scope, start_index, stop_index, family, size, weight, style, color,
-        bg_color, opacity, bg_opacity, text_outline_color, text_outline_tn,
-        text_outline_br, v_align, h_align);
-    if (family != nullptr) {
-      boost::any value = std::string(family);
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontFamily, value,
-                                     start_index, stop_index);
-    }
-    if (size != kAttrInvalidFloatVal) {
-      boost::any value = size;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontSize, value,
-                                     start_index, stop_index);
-    }
-    if (weight != kAttrInvalidIntVal) {
-      boost::any value = weight;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontWeight, value,
-                                     start_index, stop_index);
-    }
-    if (style != kAttrInvalidIntVal) {
-      boost::any value = style;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontStyle, value,
-                                     start_index, stop_index);
-    }
-    if (color != kAttrInvalidUintVal) {
-      boost::any value = color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontColor, value,
-                                     start_index, stop_index);
-    }
-    if (bg_color != kAttrInvalidUintVal) {
-      boost::any value = bg_color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontBgColor, value,
-                                     start_index, stop_index);
-    }
-    if (opacity != kAttrInvalidFloatVal) {
-      boost::any value = opacity;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontOpacity, value,
-                                     start_index, stop_index);
-    }
-    if (bg_opacity != kAttrInvalidFloatVal) {
-      boost::any value = bg_opacity;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontBgOpacity, value,
-                                     start_index, stop_index);
-    }
-    if (text_outline_color != kAttrInvalidUintVal) {
-      boost::any value = text_outline_color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontTextOutlineColor,
-                                     value, start_index, stop_index);
-    }
-    if (text_outline_tn != kAttrInvalidUintVal) {
-      boost::any value = text_outline_tn;
-      internal::AddSubtitleAttribute(attr_list,
-                                     kSubAttrFontTextOutlineThickness, value,
-                                     start_index, stop_index);
-    }
-    if (text_outline_br != kAttrInvalidIntVal) {
-      boost::any value = text_outline_br;
-      internal::AddSubtitleAttribute(attr_list,
-                                     kSubAttrFontTextOutlineBlurRadius, value,
-                                     start_index, stop_index);
-    }
-    if (v_align != kAttrInvalidIntVal) {
-      boost::any value = v_align;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontVerticalAlign,
-                                     value, start_index, stop_index);
-    }
-    if (h_align != kAttrInvalidIntVal) {
-      boost::any value = h_align;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontHorizontalAlign,
-                                     value, start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleFontSizeWeightStyleClolr(GstStructure* attribute,
-                                           std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute font shortcut SIZE_WEIGHT_STYLE_COLOR!");
-  while (attribute) {
-    GstSubAttriScope scope;
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    gfloat size = kAttrInvalidFloatVal;
-    gint weight = kAttrInvalidIntVal, style = kAttrInvalidIntVal;
-    guint color = kAttrInvalidUintVal;
-    attribute = GST_SUB_ATTRI_FUNC(font_sc_size_weight_style_color_parse)(
-        attribute, &scope, &start_index, &stop_index, &size, &weight, &style,
-        &color);
-    LOG_DEBUG(
-        "passed a font attribute: scope(%u), start_index(%u), "
-        "stop_index(%u), size(%f),"
-        "weight(%d), style(%d), color(%u)",
-        scope, start_index, stop_index, size, weight, style, color);
-    if (size != kAttrInvalidFloatVal) {
-      boost::any value = size;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontSize, value,
-                                     start_index, stop_index);
-    }
-    if (weight != kAttrInvalidIntVal) {
-      boost::any value = weight;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontWeight, value,
-                                     start_index, stop_index);
-    }
-    if (style != kAttrInvalidIntVal) {
-      boost::any value = style;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontStyle, value,
-                                     start_index, stop_index);
-    }
-    if (color != kAttrInvalidUintVal) {
-      boost::any value = color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontColor, value,
-                                     start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleFontColorOpacities(GstStructure* attribute,
-                                     std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute font shortcut SIZE_COLORS_AND_OPACITIES!");
-  while (attribute) {
-    GstSubAttriScope scope;
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal,
-          color = kAttrInvalidUintVal, bg_color = kAttrInvalidUintVal;
-    gfloat opacity = kAttrInvalidFloatVal, bg_opacity = kAttrInvalidFloatVal;
-    guint text_outline_color = kAttrInvalidUintVal;
-    attribute = GST_SUB_ATTRI_FUNC(font_sc_colors_and_opacities_parse)(
-        attribute, &scope, &start_index, &stop_index, &color, &bg_color,
-        &opacity, &bg_opacity, &text_outline_color);
-    LOG_DEBUG(
-        "passed a font attribute: scope(%u), start_index(%u), "
-        "stop_index(%u),"
-        "color(%u), bg_color(%u), opacity(%f), bg_opacity(%f), "
-        "text_outline_color(%u)",
-        scope, start_index, stop_index, color, bg_color, opacity, bg_opacity,
-        text_outline_color);
-    if (color != kAttrInvalidUintVal) {
-      boost::any value = color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontColor, value,
-                                     start_index, stop_index);
-    }
-    if (bg_color != kAttrInvalidUintVal) {
-      boost::any value = bg_color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontBgColor, value,
-                                     start_index, stop_index);
-    }
-    if (opacity != kAttrInvalidFloatVal) {
-      boost::any value = opacity;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontOpacity, value,
-                                     start_index, stop_index);
-    }
-    if (bg_opacity != kAttrInvalidFloatVal) {
-      boost::any value = bg_opacity;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontBgOpacity, value,
-                                     start_index, stop_index);
-    }
-    if (text_outline_color != kAttrInvalidUintVal) {
-      boost::any value = text_outline_color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontTextOutlineColor,
-                                     value, start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleFontSize(GstStructure* attribute,
-                           std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute font shortcut SIZE!");
-  while (attribute) {
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    gfloat size = kAttrInvalidFloatVal;
-    attribute = GST_SUB_ATTRI_FUNC(font_sc_size_parse)(attribute, &start_index,
-                                                     &stop_index, &size);
-    LOG_DEBUG(
-        "passed a font attribute: start_index(%u), stop_index(%u), "
-        "size(%f)",
-        start_index, stop_index, size);
-    if (size != kAttrInvalidFloatVal) {
-      boost::any value = size;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontSize, value,
-                                     start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleFontWeight(GstStructure* attribute,
-                             std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute font shortcut WEIGHT!");
-  while (attribute) {
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    gint weight = kAttrInvalidIntVal;
-    attribute = GST_SUB_ATTRI_FUNC(font_sc_weight_parse)(attribute, &start_index,
-                                                       &stop_index, &weight);
-    LOG_DEBUG(
-        "passed a font attribute: start_index(%u), stop_index(%u), "
-        "weight(%d)",
-        start_index, stop_index, weight);
-    if (weight != kAttrInvalidIntVal) {
-      boost::any value = weight;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontWeight, value,
-                                     start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleFontStyle(GstStructure* attribute,
-                            std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute font shortcut STYLE!");
-  while (attribute) {
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    gint style = kAttrInvalidIntVal;
-    attribute = GST_SUB_ATTRI_FUNC(font_sc_style_parse)(attribute, &start_index,
-                                                      &stop_index, &style);
-    LOG_DEBUG(
-        "passed a font attribute: start_index(%u), stop_index(%u), "
-        "style(%d)",
-        start_index, stop_index, style);
-    if (style != kAttrInvalidIntVal) {
-      boost::any value = style;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontStyle, value,
-                                     start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleFontColor(GstStructure* attribute,
-                            std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute font shortcut COLOR!");
-  while (attribute) {
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    guint color = kAttrInvalidUintVal;
-    attribute = GST_SUB_ATTRI_FUNC(font_sc_color_parse)(attribute, &start_index,
-                                                      &stop_index, &color);
-    LOG_DEBUG(
-        "passed a font attribute: start_index(%u), stop_index(%u), "
-        "color(%u)",
-        start_index, stop_index, color);
-    if (color != kAttrInvalidUintVal) {
-      boost::any value = color;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrFontColor, value,
-                                     start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleRaw(GstStructure* attribute,
-                      std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute raw!");
-  while (attribute) {
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    gchar* raw_subtitle = nullptr;
-    attribute = GST_SUB_ATTRI_FUNC(raw_data)(attribute, &raw_subtitle);
-    LOG_DEBUG("passed a raw attribute: raw_subtitle(%s)", raw_subtitle);
-    if (raw_subtitle != nullptr) {
-      boost::any value = std::string(raw_subtitle);
-      internal::AddSubtitleAttribute(attr_list, kSubAttrRawSubtitle, value,
-                                     start_index, stop_index);
-    }
-  }
-}
-void ParseSubtitleWebvttCue(GstStructure* attribute,
-                            std::list<SubtitleAttr>* attr_list) {
-  LOG_DEBUG("Now parse attribute of webvtt cue!");
-  while (attribute) {
-    guint start_index = kAttrInvalidUintVal, stop_index = kAttrInvalidUintVal;
-    gint line_num = kAttrInvalidIntVal, line_align = kAttrInvalidIntVal,
-         pos_align = kAttrInvalidIntVal, align = kAttrInvalidIntVal,
-         vertical = kAttrInvalidIntVal;
-    gfloat line = kAttrInvalidFloatVal, size = kAttrInvalidFloatVal,
-           position = kAttrInvalidFloatVal;
-    attribute = GST_SUB_ATTRI_FUNC(webvttcue_parse)(
-        attribute, &line, &line_num, &line_align, &align, &size, &position,
-        &pos_align, &vertical);
-    LOG_DEBUG(
-        "passed webvttcue attributes: line(%f), line_num(%d), line_align(%d), "
-        "align(%d), size(%f), position(%f), pos_align(%d), vertical(%d)",
-        line, line_num, line_align, align, size, position, pos_align, vertical);
-    if (line != kAttrInvalidFloatVal) {
-      boost::any value = line;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCueLine, value,
-                                     start_index, stop_index);
-    }
-    if (line_num != kAttrInvalidIntVal) {
-      boost::any value = line_num;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCueLineNum, value,
-                                     start_index, stop_index);
-    }
-    if (line_align != kAttrInvalidIntVal) {
-      boost::any value = line_align;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCueLineAlign,
-                                     value, start_index, stop_index);
-    }
-    if (align != kAttrInvalidIntVal) {
-      boost::any value = align;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCueAlign, value,
-                                     start_index, stop_index);
-    }
-    if (size != kAttrInvalidFloatVal) {
-      boost::any value = size;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCueSize, value,
-                                     start_index, stop_index);
-    }
-    if (position != kAttrInvalidFloatVal) {
-      boost::any value = position;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCuePosition,
-                                     value, start_index, stop_index);
-    }
-    if (pos_align != kAttrInvalidIntVal) {
-      boost::any value = pos_align;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCuePositionAlign,
-                                     value, start_index, stop_index);
-    }
-    if (vertical != kAttrInvalidIntVal) {
-      boost::any value = vertical;
-      internal::AddSubtitleAttribute(attr_list, kSubAttrWebvttCueVertical,
-                                     value, start_index, stop_index);
-    }
-  }
-}
-
-}  // namespace internal
-
-SubtitleAttrListPtr SubtitleAttrParser::Parse() {
-  SubtitleAttrListPtr attr_list{new SubtitleAttrList};
-  for (int attr_type = GST_SUB_ATTRI_ENUM(TYPE_REGION);
-       attr_type < GST_SUB_ATTRI_ENUM(TYPE_UNKNOWN); ++attr_type) {
-    const gchar* type_name =
-        GST_SUB_ATTRI_FUNC(type_to_name)((GstSubAttriType)attr_type);
-    GQuark attri_quark =
-        GST_SUB_ATTRI_FUNC(type_to_quark)((GstSubAttriType)attr_type);
-    if (!attri_quark) {
-      LOG_DEBUG("We don't have quark of this attribute type(%s)!", type_name);
-      continue;
-    }
-
-    GstStructure* attribute = GST_STRUCTURE_CAST(
-        gst_mini_object_get_qdata(GST_MINI_OBJECT(gstbuf_), attri_quark));
-
-    if (!attribute) continue;
-    LOG_DEBUG("[core] attribute type(%s) from gstbuffer!", type_name);
-
-    switch (attr_type) {
-      case GST_SUB_ATTRI_ENUM(TYPE_REGION):
-        internal::ParseSubtitleRegionAttr(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_WINDOW):
-        internal::ParseSubtitleWindowAttr(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_FONT):
-        internal::ParseSubtitleFontAttr(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_FONT_SC_SIZE_WEIGHT_STYLE_COLOR):
-        internal::ParseSubtitleFontSizeWeightStyleClolr(attribute,
-                                                        attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_FONT_SC_COLORS_AND_OPACITIES):
-        internal::ParseSubtitleFontColorOpacities(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_FONT_SC_SIZE):
-        internal::ParseSubtitleFontSize(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_FONT_SC_WEIGHT):
-        internal::ParseSubtitleFontWeight(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_FONT_SC_STYLE):
-        internal::ParseSubtitleFontStyle(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_FONT_SC_COLOR):
-        internal::ParseSubtitleFontColor(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_RAW):
-        internal::ParseSubtitleRaw(attribute, attr_list.get());
-        break;
-      case GST_SUB_ATTRI_ENUM(TYPE_WEBVTT_CUE):
-        internal::ParseSubtitleWebvttCue(attribute, attr_list.get());
-        break;
-      default:
-        LOG_ERROR("UNKNOWN ATTR TYPE");
-        return nullptr;
-    }
-  }
-
-  (attr_list.get())->sort(internal::ComparingStartTime);
-  boost::any value = 0;
-  GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
-  duration = GST_TIME_AS_MSECONDS(GST_BUFFER_DURATION(gstbuf_));
-  timestamp = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(gstbuf_));
-  LOG_DEBUG("pts[%" PRIu64 "] duration[%" PRIu64 "]", timestamp, duration);
-  internal::AddSubtitleAttribute(attr_list.get(), kSubAttrTimestamp, value,
-                                 timestamp, timestamp + duration);
-
-  return attr_list;
-}
-}  // namespace plusplayer
index 0346141..60bc45d 100644 (file)
@@ -1,15 +1,29 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "core/track_util.h"
 
 #include <string>
+#include <cinttypes>
 #include <algorithm>
-#include <inttypes.h>
+
+
 #include "core/utils/plusplayer_log.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace track_util {
 
@@ -44,6 +58,7 @@ bool GetActiveTrackList(const std::vector<Track>& tracklist,
         text++;
     }
   }
+// LCOV_EXCL_START
   if (active_track.empty()) {
     LOG_ERROR("no active track found");
     return false;
@@ -53,9 +68,11 @@ bool GetActiveTrackList(const std::vector<Track>& tracklist,
               video, audio, text);
     return false;
   }
+// LCOV_EXCL_STOP
   return true;
 }
 
+// LCOV_EXCL_START
 void ShowTrackInfo(const std::vector<Track>& trackinfo) {
   std::vector<Track> info = trackinfo;
   LOG_INFO("### Track List ###");
@@ -64,6 +81,7 @@ void ShowTrackInfo(const std::vector<Track>& trackinfo) {
   }
   LOG_INFO("### ~Track List ###");
 }
+// LCOV_EXCL_STOP
 
 void ShowTrackInfo(const Track& track) {
   LOG_INFO("### TrackInfo ###");
@@ -88,16 +106,15 @@ void ShowTrackInfo(const Track& track) {
   LOG_INFO("active %d  subtitle_format : %s ", track.active, track.subtitle_format.c_str() );
   LOG_INFO("use_swdecoder : %d", track.use_swdecoder);
   LOG_INFO("language_code: %s", track.language_code.c_str());
-  LOG_INFO("stream format: %s", track.stream_format.c_str());
-  LOG_INFO("alignment: %s", track.alignment.c_str());
-  LOG_INFO("original-media-type: %s", track.original_media_type.c_str());
-  LOG_INFO("protection-system: %s", track.protection_system.c_str());
 }
 
+// LCOV_EXCL_START
 uint64_t GetPositionWithinBoundary(const uint64_t duration,
                                    const uint64_t position,
                                    const uint64_t threshold) {
-  LOG_DEBUG("duration[%" PRIu64 "] position[%" PRIu64 "] threshold[%" PRIu64 "]", duration, position, threshold);
+  LOG_DEBUG("duration[%" PRIu64 "] position[%" PRIu64 "] threshold[%" PRIu64
+            "]",
+            duration, position, threshold);
   if (duration < threshold) return position;
   uint64_t safe_pos = position;
   uint64_t boundary = duration - threshold;
@@ -114,12 +131,12 @@ bool IsValidCodecDataSize(int size) {
 }
 
 void FillCodecDataIntoTrack(const GValue* codec_data,
-                            plusplayer::Track* track) {
+                            esplusplayer::Track* track) {
   GstBuffer* buffer = gst_value_get_buffer(codec_data);
   GstMapInfo codec_data_info;
   if (gst_buffer_map(buffer, &codec_data_info, GST_MAP_READ)) {
     LOG_DEBUG("codec extra data [ %s ]", codec_data_info.data);
-    LOG_DEBUG("codec extra data size[ %" G_GSIZE_FORMAT " ]", codec_data_info.size);
+    LOG_DEBUG("codec extra data size[ %zu ]", codec_data_info.size);
     if (IsValidCodecDataSize(codec_data_info.size)) {
       std::shared_ptr<char> data(new char[codec_data_info.size],
                                    std::default_delete<char[]>());
@@ -127,7 +144,7 @@ void FillCodecDataIntoTrack(const GValue* codec_data,
       track->codec_data = data;
       track->codec_data_len = codec_data_info.size;
     } else {
-      LOG_WARN("Warning invalid codec extra data size [%" G_GSIZE_FORMAT "]",
+      LOG_WARN("Warning invalid codec extra data size [%zu]",
                codec_data_info.size);
     }
     gst_buffer_unmap(buffer, &codec_data_info);
@@ -135,7 +152,8 @@ void FillCodecDataIntoTrack(const GValue* codec_data,
     LOG_DEBUG("Fail to gst_buffer_map for codec data");
   }
 }
+// LCOV_EXCL_STOP
 
 }  // namespace track_util
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
index 43b7645..3e29110 100644 (file)
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "core/trackrendereradapter.h"
 
@@ -10,7 +22,7 @@
 #include "core/utils/plusplayer_log.h"
 #include "trackrenderer_capi/trackrenderer_internal.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 TrackRendererAdapter::Ptr TrackRendererAdapter::Create() {
   LOG_INFO("Trackrenderer adapter is created");
@@ -93,32 +105,17 @@ void TrackRendererAdapter::SetIniProperty(
   trackrenderer_set_ini_property(handle_, trackrenderer_iniproperty, size);
 }
 
-void TrackRendererAdapter::SetIniElement(
-    const std::map<std::string, std::string>& elements) {
-  const int size = elements.size();
-  if (size <= 0) return;
-  TrackRendererIniElement trackrenderer_inielement[size];
-  int index = 0;
-  for (const auto& pair : elements) {
-    trackrenderer_inielement[index].key = pair.first.c_str();
-    trackrenderer_inielement[index].value = pair.second.c_str();
-    index++;
-  }
-  trackrenderer_set_ini_element(handle_, trackrenderer_inielement, size);
-}
-
-bool TrackRendererAdapter::Seek(uint64_t time_millisecond,
-                                double playback_rate) {
-  if (trackrenderer_seek(handle_, time_millisecond, playback_rate) == kFailed) {
+bool TrackRendererAdapter::Seek(uint64_t time, double playback_rate) {
+  if (trackrenderer_seek(handle_, time, playback_rate) == kFailed) {
     return false;
   }
   return true;
 }
 
-bool TrackRendererAdapter::Seek(uint64_t time_millisecond, double playback_rate,
+bool TrackRendererAdapter::Seek(uint64_t time, double playback_rate,
                                 bool audio_mute) {
-  if (trackrenderer_seek2(handle_, time_millisecond, playback_rate,
-                          audio_mute) == kFailed) {
+  if (trackrenderer_seek2(handle_, time, playback_rate, audio_mute) ==
+      kFailed) {
     return false;
   }
   return true;
@@ -133,8 +130,9 @@ bool TrackRendererAdapter::SetPlaybackRate(double playback_rate,
   return true;
 }
 
-bool TrackRendererAdapter::GetPlayingTime(uint64_t* time_millisecond) {
-  if (trackrenderer_get_playing_time(handle_, time_millisecond) == kFailed) {
+bool TrackRendererAdapter::GetPlayingTime(uint64_t* time) {
+  if (trackrenderer_get_playing_time(
+          handle_, (unsigned long long*)(uintptr_t)time) == kFailed) {
     return false;
   }
   return true;
@@ -178,18 +176,31 @@ bool TrackRendererAdapter::Activate(TrackType type, const Track& trackinfo) {
   return true;
 }
 
+bool TrackRendererAdapter::DeactivateAudio() {
+  if (trackrenderer_deactivate_audio(handle_) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::ActivateAudio() {
+  if (trackrenderer_activate_audio(handle_) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+// LCOV_EXCL_START
 bool TrackRendererAdapter::SubmitPacket(const DecoderInputBufferPtr& data) {
 #ifdef TRACKRENDERER_GST_DEPENDENCY_REMOVAL
   TrackRendererDecoderInputBuffer decoderinputbuffer{
       adapter_utils::ConvertToTrackRendererTrackType(data->GetType()),
       data->GetIndex(),
-      static_cast<void*>(const_cast<GstBuffer*>(data->Get())),
-      static_cast<void*>(const_cast<GstCaps*>(data->GetCaps()))};
+      static_cast<void*>(const_cast<GstBuffer*>(data->Get()))};
 #else
   TrackRendererDecoderInputBuffer decoderinputbuffer{
       adapter_utils::ConvertToTrackRendererTrackType(data->GetType()),
-      data->GetIndex(), const_cast<GstBuffer*>(data->Get()),
-      const_cast<GstCaps*>(data->GetCaps())};
+      data->GetIndex(), const_cast<GstBuffer*>(data->Get())};
 #endif
   if (trackrenderer_submit_packet(handle_, &decoderinputbuffer, nullptr) ==
       kFailed) {
@@ -197,6 +208,7 @@ bool TrackRendererAdapter::SubmitPacket(const DecoderInputBufferPtr& data) {
   }
   return true;
 }
+// LCOV_EXCL_STOP
 
 namespace adapter_utils {
 
@@ -229,19 +241,18 @@ TrackRendererAdapter::SubmitStatus ConvertToAdapterSubmitStatus(
 
 }  // namespace adapter_utils
 
+// LCOV_EXCL_START
 bool TrackRendererAdapter::SubmitPacket(const DecoderInputBufferPtr& data,
                                         SubmitStatus* status) {
 #ifdef TRACKRENDERER_GST_DEPENDENCY_REMOVAL
   TrackRendererDecoderInputBuffer decoderinputbuffer{
       adapter_utils::ConvertToTrackRendererTrackType(data->GetType()),
       data->GetIndex(),
-      static_cast<void*>(const_cast<GstBuffer*>(data->Get())),
-      static_cast<void*>(const_cast<GstCaps*>(data->GetCaps()))};
+      static_cast<void*>(const_cast<GstBuffer*>(data->Get()))};
 #else
   TrackRendererDecoderInputBuffer decoderinputbuffer{
       adapter_utils::ConvertToTrackRendererTrackType(data->GetType()),
-      data->GetIndex(), const_cast<GstBuffer*>(data->Get()),
-      const_cast<GstCaps*>(data->GetCaps())};
+      data->GetIndex(), const_cast<GstBuffer*>(data->Get())};
 #endif
   TrackRendererSubmitStatus submitstatus;
   if (trackrenderer_submit_packet(handle_, &decoderinputbuffer,
@@ -253,6 +264,7 @@ bool TrackRendererAdapter::SubmitPacket(const DecoderInputBufferPtr& data,
     *status = adapter_utils::ConvertToAdapterSubmitStatus(submitstatus);
   return true;
 }
+// LCOV_EXCL_STOP
 
 bool TrackRendererAdapter::SubmitPacket2(const DecoderInputBufferPtr& data,
                                          SubmitStatus* status) {
@@ -260,13 +272,11 @@ bool TrackRendererAdapter::SubmitPacket2(const DecoderInputBufferPtr& data,
   TrackRendererDecoderInputBuffer decoderinputbuffer{
       adapter_utils::ConvertToTrackRendererTrackType(data->GetType()),
       data->GetIndex(),
-      static_cast<void*>(const_cast<GstBuffer*>(data->Get())),
-      static_cast<void*>(const_cast<GstCaps*>(data->GetCaps()))};
+      static_cast<void*>(const_cast<GstBuffer*>(data->Get()))};
 #else
   TrackRendererDecoderInputBuffer decoderinputbuffer{
       adapter_utils::ConvertToTrackRendererTrackType(data->GetType()),
-      data->GetIndex(), const_cast<GstBuffer*>(data->Get()),
-      const_cast<GstCaps*>(data->GetCaps())};
+      data->GetIndex(), const_cast<GstBuffer*>(data->Get())};
 #endif
   TrackRendererSubmitStatus submitstatus;
   if (trackrenderer_submit_packet2(handle_, &decoderinputbuffer,
@@ -286,11 +296,20 @@ bool TrackRendererAdapter::SubmitPacket2(const DecoderInputBufferPtr& data,
 }
 
 void TrackRendererAdapter::SetDrm(const drm::Property& drm_property) {
+#if DRM_MAPI_AARCH_64
+  TrackRendererDrmProperty_64bit trackrenderer_drm_property{
+      kTrackRendererDrmTypeNone, 0, 0, nullptr, nullptr};
+#else
   TrackRendererDrmProperty trackrenderer_drm_property{kTrackRendererDrmTypeNone,
                                                       0, 0, nullptr, nullptr};
+#endif
   adapter_utils::MakeTrackRendererDrmProperty(&trackrenderer_drm_property,
                                               drm_property);
+#if DRM_MAPI_AARCH_64
+  trackrenderer_set_drm_64bit(handle_, &trackrenderer_drm_property);
+#else
   trackrenderer_set_drm(handle_, &trackrenderer_drm_property);
+#endif
 }
 
 void TrackRendererAdapter::DrmLicenseAcquiredDone(TrackType type) {
@@ -298,11 +317,6 @@ void TrackRendererAdapter::DrmLicenseAcquiredDone(TrackType type) {
       handle_, adapter_utils::ConvertToTrackRendererTrackType(type));
 }
 
-void TrackRendererAdapter::SetDrmLicenseKey(TrackType type, const std::string& key) {
-  trackrenderer_set_drm_license_key(
-      handle_, adapter_utils::ConvertToTrackRendererTrackType(type),
-      key.c_str());
-}
 bool TrackRendererAdapter::SetDisplayMode(const DisplayMode& mode) {
   if (trackrenderer_set_display_mode(
           handle_, adapter_utils::ConvertToTrackRendererDisplayMode(mode)) ==
@@ -312,6 +326,14 @@ bool TrackRendererAdapter::SetDisplayMode(const DisplayMode& mode) {
   return true;
 }
 
+bool TrackRendererAdapter::SetStretchMode(const int& mode) {
+  if (trackrenderer_set_stretch_mode(handle_, mode) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+// LCOV_EXCL_START
 bool TrackRendererAdapter::SetDisplay(const DisplayType& type,
                                       uint32_t surface_id, long x, long y,
                                       long w, long h) {
@@ -343,6 +365,17 @@ bool TrackRendererAdapter::SetDisplay(const DisplayType& type,
   return true;
 }
 
+bool TrackRendererAdapter::SetDisplaySubsurface(const DisplayType& type,
+                                                void* ecore_wl2_subsurface,
+                                                int x, int y, int w, int h) {
+  if (trackrenderer_set_display_ecore_wl2_subsurface(
+          handle_, adapter_utils::ConvertToTrackRendererDisplayType(type),
+          ecore_wl2_subsurface, x, y, w, h) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
 void TrackRendererAdapter::GetDisplay(DisplayType* type, Geometry* area) {
   TrackRendererGeometry geometry = {0, 0, 1920, 1080};
   TrackRendererDisplayType display_type = kTrackRendererDisplayTypeNone;
@@ -350,6 +383,7 @@ void TrackRendererAdapter::GetDisplay(DisplayType* type, Geometry* area) {
   adapter_utils::MakeGeometry(area, geometry);
   *type = adapter_utils::ConvertToDisplayType(display_type);
 }
+// LCOV_EXCL_STOP
 
 bool TrackRendererAdapter::SetDisplayRoi(const Geometry& roi) {
   TrackRendererGeometry geometry = {0, 0, 1920, 1080};
@@ -369,6 +403,15 @@ bool TrackRendererAdapter::SetVideoRoi(const CropArea& area) {
   return true;
 }
 
+bool TrackRendererAdapter::ResizeRenderRect(const RenderRect& rect) {
+  TrackRendererRenderRect result = {0, 0, 1920, 1080};
+  adapter_utils::MakeTrackRendererRenderRect(&result, rect);
+  if (trackrenderer_resize_render_rect(handle_, &result) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
 bool TrackRendererAdapter::SetDisplayRotate(const DisplayRotation& rotate) {
   if (trackrenderer_set_display_rotate(
           handle_, adapter_utils::ConvertToTrackRendererDisplayRotate(
@@ -394,12 +437,14 @@ bool TrackRendererAdapter::SetDisplayVisible(bool is_visible) {
   return true;
 }
 
+// LCOV_EXCL_START
 void TrackRendererAdapter::GetDisplayMode(DisplayMode* mode) {
   // TODO: sy0207.ju
   TrackRendererDisplayMode display_mode = kTrackRendererDisplayModeDisplayMax;
   trackrenderer_get_display_mode(handle_, &display_mode);
   *mode = adapter_utils::ConvertToDisplayMode(display_mode);
 }
+// LCOV_EXCL_STOP
 
 bool TrackRendererAdapter::SetAudioMute(bool is_mute) {
   if (trackrenderer_set_audio_mute(handle_, is_mute) == kFailed) {
@@ -408,6 +453,22 @@ bool TrackRendererAdapter::SetAudioMute(bool is_mute) {
   return true;
 }
 
+void TrackRendererAdapter::SetAppId(const std::string& app_id) {
+  trackrenderer_set_app_id(handle_, app_id.c_str());
+}
+
+void TrackRendererAdapter::SetAppInfo(const PlayerAppInfo& app_info) {
+  TrackRendererAppInfo info;
+  adapter_utils::MakeTrackRendererAppInfo(&info, app_info);
+  trackrenderer_set_app_info(handle_, &info);
+}
+
+void TrackRendererAdapter::SetAppInfoEx(const PlayerAppInfoEx& app_info) {
+  TrackRendererAppInfoEx info;
+  adapter_utils::MakeTrackRendererAppInfoEx(&info, app_info);
+  trackrenderer_set_app_info_ex(handle_, &info);
+}
+
 void TrackRendererAdapter::SetVideoStillMode(const StillMode& type) {
   trackrenderer_set_video_still_mode(
       handle_, adapter_utils::ConvertToTrackRendererStillMode(type));
@@ -473,15 +534,24 @@ static const std::map<TrackRendererAdapter::Attribute, AttrInfo>
          {ValueType::kUInt32, "video-min-byte-percent"}},
         {TrackRendererAdapter::Attribute::kAudioMinByteThreshold,
          {ValueType::kUInt32, "audio-min-byte-percent"}},
-        {TrackRendererAdapter::Attribute::kVideoQueueMaxBuffer,
-         {ValueType::kUInt64, "video-queue-max-buffer"}},
-        {TrackRendererAdapter::Attribute::kAudioQueueMaxBuffer,
-         {ValueType::kUInt64, "audio-queue-max-buffer"}},
+        {TrackRendererAdapter::Attribute::kVideoQueueMaxTime,
+         {ValueType::kUInt64, "video-queue-max-time"}},
+        {TrackRendererAdapter::Attribute::kAudioQueueMaxTime,
+         {ValueType::kUInt64, "audio-queue-max-time"}},
+        {TrackRendererAdapter::Attribute::kVideoQueueCurrentLevelTime,
+         {ValueType::kUInt64, "video-current-level-time"}},
+        {TrackRendererAdapter::Attribute::kAudioQueueCurrentLevelTime,
+         {ValueType::kUInt64, "audio-current-level-time"}},
+        {TrackRendererAdapter::Attribute::kVideoMinTimeThreshold,
+         {ValueType::kUInt32, "video-min-time-percent"}},
+        {TrackRendererAdapter::Attribute::kAudioMinTimeThreshold,
+         {ValueType::kUInt32, "audio-min-time-percent"}},
+        {TrackRendererAdapter::Attribute::kVideoSupportRotation,
+         {ValueType::kUInt32, "support-rotation"}},
         {TrackRendererAdapter::Attribute::kVideoRenderTimeOffset,
          {ValueType::kInt64, "video-render-time-offset"}},
         {TrackRendererAdapter::Attribute::kAudioRenderTimeOffset,
-         {ValueType::kInt64, "audio-render-time-offset"}}
-        };
+         {ValueType::kInt64, "audio-render-time-offset"}}};
 
 static const std::map<TrackRendererAdapter::Attribute, AttrInfo>
     kConfigInfoTable = {
@@ -489,13 +559,26 @@ static const std::map<TrackRendererAdapter::Attribute, AttrInfo>
          {ValueType::kUInt32, "accurate-seek-mode"}},
         {TrackRendererAdapter::Attribute::kLowLatencyMode,
          {ValueType::kUInt32, "low-latency-mode"}},
+        {TrackRendererAdapter::Attribute::kVideoFramePeekMode,
+         {ValueType::kUInt32, "video-frame-peek-mode"}},
         {TrackRendererAdapter::Attribute::kUnlimitedMaxBufferMode,
          {ValueType::kUInt32, "unlimited-max-buffer-mode"}},
         {TrackRendererAdapter::Attribute::kVideoPreDisplayMode,
          {ValueType::kUInt32, "video-pre-display-mode"}},
         {TrackRendererAdapter::Attribute::kStartRenderingTime,
          {ValueType::kUInt64, "start-rendering-time"}},
-        };
+        {TrackRendererAdapter::Attribute::kFmmMode,
+         {ValueType::kUInt32, "fmm-mode"}},
+        {TrackRendererAdapter::Attribute::kAlternativeVideoResource,
+         {ValueType::kUInt32, "alternative-video-resource"}},
+        {TrackRendererAdapter::Attribute::kVideoDecodingMode,
+         {ValueType::kUInt32, "video-decoding-mode"}},
+        {TrackRendererAdapter::Attribute::kLateVideoFrameDropMode,
+         {ValueType::kUInt32, "late-video-frame-drop-mode"}},
+        {TrackRendererAdapter::Attribute::kVideoProgressiveMode,
+         {ValueType::kUInt32, "video-progressive-mode"}},
+        {TrackRendererAdapter::Attribute::kPlayerTimeUnitType,
+         {ValueType::kUInt32, "player-time-unit-type"}}};
 }  // namespace adapter_utils
 
 void TrackRendererAdapter::SetAttribute(
@@ -591,10 +674,11 @@ void TrackRendererAdapter::GetAttribute(
   }
   return;
 }
-
+// LCOV_EXCL_START
 void TrackRendererAdapter::RegisterListener(EventListener* listener) {
   eventlistener_ = listener;
   trackrenderer_set_error_cb(handle_, ErrorCb_, (void*)this);
+  trackrenderer_set_error_msg_cb(handle_, ErrorMsgCb_, (void*)this);
   trackrenderer_set_resourceconflict_cb(handle_, ResourceConflictCb_,
                                         (void*)this);
   trackrenderer_set_seekdone_cb(handle_, SeekDoneCb_, (void*)this);
@@ -603,13 +687,27 @@ void TrackRendererAdapter::RegisterListener(EventListener* listener) {
                                         (void*)this);
   trackrenderer_set_closedcaption_cb(handle_, ClosedCaptionDataCb_,
                                      (void*)this);
+#if DRM_MAPI_AARCH_64
+  trackrenderer_set_drminitdata_cb_64bit(handle_, DrmInitDataCb_, (void*)this);
+#else
   trackrenderer_set_drminitdata_cb(handle_, DrmInitDataCb_, (void*)this);
+#endif
+  trackrenderer_set_media_packet_video_decoded_cb(
+      handle_, MediaPacketVideoDecodedCb_, (void*)this);
+  trackrenderer_set_media_packet_video_raw_decoded_cb(
+      handle_, MediaPacketVideoRawDecodedCb_, (void*)this);
+  trackrenderer_set_multiview_start_video_cb(handle_, MultiviewStartVideoCb_,
+                                             (void*)this);
+  trackrenderer_set_multiview_stop_video_cb(handle_, MultiviewStopVideoCb_,
+                                            (void*)this);
 }
+// LCOV_EXCL_STOP
 
 void TrackRendererAdapter::RegisterListenerForEsplayer(
     EventListener* listener) {
   eventlistener_ = listener;
   trackrenderer_set_error_cb(handle_, ErrorCb_, (void*)this);
+  trackrenderer_set_error_msg_cb(handle_, ErrorMsgCb_, (void*)this);
   trackrenderer_set_resourceconflict_cb(handle_, ResourceConflictCb_,
                                         (void*)this);
   trackrenderer_set_seekdone_cb(handle_, SeekDoneCb_, (void*)this);
@@ -620,8 +718,26 @@ void TrackRendererAdapter::RegisterListenerForEsplayer(
   trackrenderer_set_seekdata_cb(handle_, SeekDataCb_, (void*)this);
   trackrenderer_set_closedcaption_cb(handle_, ClosedCaptionDataCb_,
                                      (void*)this);
+  trackrenderer_set_media_packet_video_tbmptr_cb(
+      handle_, MediaPacketGetTbmBufPtrCb_, (void*)this);
   trackrenderer_set_media_packet_video_decoded_cb(
       handle_, MediaPacketVideoDecodedCb_, (void*)this);
+  trackrenderer_set_media_packet_video_raw_decoded_cb(
+      handle_, MediaPacketVideoRawDecodedCb_, (void*)this);
+  trackrenderer_set_first_decoding_done_cb(handle_, FirstDecodingDoneCb_,
+                                           (void*)this);
+  trackrenderer_set_video_decoder_underrun_cb(handle_, VideoDecoderUnderrunCb_,
+                                              (void*)this);
+  trackrenderer_set_video_latency_status_cb(handle_, VideoLatencyStatusCb_,
+                                            (void*)this);
+  trackrenderer_set_audio_latency_status_cb(handle_, AudioLatencyStatusCb_,
+                                            (void*)this);
+  trackrenderer_set_video_frame_dropped_cb(handle_, VideoFrameDroppedCb_,
+                                           (void*)this);
+  trackrenderer_set_decoder_input_buffer_time_cb(
+      handle_, DecoderInputBufferTime, (void*)this);
+  trackrenderer_set_decoder_output_buffer_time_cb(
+      handle_, DecoderOutputBufferTime, (void*)this);
 }
 
 TrackRendererState TrackRendererAdapter::GetState() {
@@ -637,9 +753,239 @@ bool TrackRendererAdapter::SetMatroskaColorInfo(const std::string& color_info) {
 }
 
 void TrackRendererAdapter::SetVideoFrameBufferType(
-    const DecodedVideoFrameBufferType& type) {
-  trackrenderer_set_video_frame_buffer_type(
-      handle_, adapter_utils::ConvertToVideoFrameBufferType(type));
+    VideoFrameTypeStrategyPtr strategy) {
+  strategy->SetType(handle_);
+}
+
+bool TrackRendererAdapter::SetVideoFrameBufferScaleResolution(
+    const uint32_t& target_width, const uint32_t& target_height) {
+  if (trackrenderer_set_video_frame_buffer_scale_resolution(
+          handle_, target_width, target_height) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetDecodedVideoFrameRate(
+    const Rational& request_framerate) {
+  TrackRendererRational request_fps;
+  adapter_utils::MakeTrackRendererRational(&request_fps, request_framerate);
+  if (trackrenderer_set_decoded_video_frame_rate(handle_, request_fps) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::RenderVideoFrame() {
+  if (trackrenderer_render_video_frame(handle_) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetAiFilter(void* aifilter) {
+  if (trackrenderer_set_aifilter(handle_, aifilter) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetCatchUpSpeed(const CatchUpSpeed& level) {
+  if (trackrenderer_set_catch_up_speed(
+          handle_, adapter_utils::ConvertToTrackRendererCatchUpSpeed(level)) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::GetVideoLatencyStatus(LatencyStatus* status) {
+  TrackRendererLatencyStatus current_status = kTrackRendererLatencyStatusLow;
+  if (trackrenderer_get_video_latency_status(handle_, &current_status) ==
+      kFailed) {
+    return false;
+  }
+  *status = adapter_utils::ConvertToLatencyStatus(current_status);
+  return true;
+}
+
+bool TrackRendererAdapter::GetAudioLatencyStatus(LatencyStatus* status) {
+  TrackRendererLatencyStatus current_status = kTrackRendererLatencyStatusLow;
+  if (trackrenderer_get_audio_latency_status(handle_, &current_status) ==
+      kFailed) {
+    return false;
+  }
+  *status = adapter_utils::ConvertToLatencyStatus(current_status);
+  return true;
+}
+
+bool TrackRendererAdapter::SetVideoMidLatencyThreshold(
+    const unsigned int threshold) {
+  if (trackrenderer_set_video_mid_latency_threshold(handle_, threshold) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetAudioMidLatencyThreshold(
+    const unsigned int threshold) {
+  if (trackrenderer_set_audio_mid_latency_threshold(handle_, threshold) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetVideoHighLatencyThreshold(
+    const unsigned int threshold) {
+  trackrenderer_set_video_high_latency_cb(handle_, VideoHighLatencyCb_,
+                                          (void*)this);
+
+  if (trackrenderer_set_video_high_latency_threshold(handle_, threshold) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetAudioHighLatencyThreshold(
+    const unsigned int threshold) {
+  trackrenderer_set_audio_high_latency_cb(handle_, AudioHighLatencyCb_,
+                                          (void*)this);
+
+  if (trackrenderer_set_audio_high_latency_threshold(handle_, threshold) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::GetLowLatencyPcmBufferSize(uint64_t* frame_count) {
+  if (trackrenderer_get_low_latency_pcm_buffer_size(handle_, frame_count) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::GetLowLatencyPcmCurrentBufferLevel(
+    uint64_t* frame_count) {
+  if (trackrenderer_get_low_latency_pcm_current_buffer_level(
+          handle_, frame_count) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::GetLowLatencyPcmUnderrunCount(
+    uint64_t* underrun_count) {
+  if (trackrenderer_get_low_latency_pcm_underrun_count(
+          handle_, underrun_count) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::InitAudioEasingInfo(
+    const uint32_t init_volume, const uint32_t init_elapsed_time,
+    const AudioEasingInfo& easing_info) {
+  TrackRendererAudioEasingInfo info;
+  adapter_utils::MakeTrackRendererAudioEasingInfo(&info, easing_info);
+  if (trackrenderer_init_audio_easing_info(
+          handle_, init_volume, init_elapsed_time, &info) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::UpdateAudioEasingInfo(
+    const AudioEasingInfo& easing_info) {
+  TrackRendererAudioEasingInfo info;
+  adapter_utils::MakeTrackRendererAudioEasingInfo(&info, easing_info);
+  if (trackrenderer_update_audio_easing_info(handle_, &info) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::GetAudioEasingInfo(uint32_t* current_volume,
+                                              uint32_t* elapsed_time,
+                                              AudioEasingInfo* easing_info) {
+  TrackRendererAudioEasingInfo info;
+  if (trackrenderer_get_audio_easing_info(handle_, current_volume, elapsed_time,
+                                          &info) == kFailed) {
+    return false;
+  }
+  adapter_utils::MakeAudioEasingInfo(easing_info, info);
+  return true;
+}
+
+bool TrackRendererAdapter::StartAudioEasing() {
+  if (trackrenderer_start_audio_easing(handle_) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::StopAudioEasing() {
+  if (trackrenderer_stop_audio_easing(handle_) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::GetVirtualRscId(const RscType type,
+                                           int* virtual_id) {
+  TrackRendererRscType converted_type = kTrackRendererRscTypeVideoRenderer;
+  if (!adapter_utils::ConvertToTrackRendererRscType(type, &converted_type))
+    return false;
+  if (trackrenderer_get_virtual_rsc_id(handle_, converted_type, virtual_id) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetAdvancedPictureQualityType(
+    const AdvPictureQualityType type) {
+  TrackRendererAdvPictureQualityType converted_type =
+      kTrackRendererAdvPictureQualityTypeVideoCall;
+  if (!adapter_utils::ConvertToTrackRendererAdvPictureQualityType(
+          type, &converted_type))
+    return false;
+  if (trackrenderer_set_advanced_picture_quality_type(
+          handle_, converted_type) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetResourceAllocatePolicy(
+    const RscAllocPolicy policy) {
+  TrackRendererRscAllocPolicy converted_policy =
+      kTrackRendererRscAllocExclusive;
+  if (!adapter_utils::ConvertToTrackRendererRscAllocPolicy(policy,
+                                                           &converted_policy))
+    return false;
+  if (trackrenderer_set_resource_allocate_policy(handle_, converted_policy) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetVideoParDar(uint64_t time_millisecond,
+                                          uint32_t par_num, uint32_t par_den,
+                                          uint32_t dar_num, uint32_t dar_den,
+                                          int reset_flag) {
+  if (trackrenderer_set_video_par_dar(handle_, time_millisecond, par_num,
+                                      par_den, dar_num, dar_den,
+                                      reset_flag) == kFailed) {
+    return false;
+  }
+  return true;
 }
 
 GetDecodedVideoFrameStatus TrackRendererAdapter::GetDecodedPacket(
@@ -660,9 +1006,44 @@ bool TrackRendererAdapter::ReturnDecodedPacket(
   return true;
 }
 
+bool TrackRendererAdapter::SetAlternativeAudioResource(
+    const PlayerAudioResourceType rcs_type) {
+  unsigned int converted_type = 0;
+  if (!adapter_utils::ConvertToTrackRendererAlternativeAudioResource(
+          rcs_type, &converted_type)) {
+    return false;
+  }
+  if (trackrenderer_set_alternative_audio_resource(handle_, converted_type) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetAudioPreloading() {
+  if (trackrenderer_set_audio_preloading(handle_) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetVideoStreamRotationInfo(
+    const VideoRotation& rotation) {
+  if (trackrenderer_set_video_stream_rotation_info(
+          handle_, adapter_utils::ConvertToTrackRendererVideoStreamRotation(
+                       rotation)) == kFailed) {
+    return false;
+  }
+  return true;
+}
+
+#ifdef TIZEN_FEATURE_PUBLIC
 bool TrackRendererAdapter::EnableVideoHole(bool value) {
   return (trackrenderer_enable_video_hole(handle_, value) != kFailed);
 }
+#endif
+
+// LCOV_EXCL_START
 
 /////////////////////////////////////////////
 /////////////// Callbacks ///////////////////
@@ -675,6 +1056,14 @@ void TrackRendererAdapter::ErrorCb_(const TrackRendererErrorType error_code,
       adapter_utils::ConvertToErrorType(error_code));
 }
 
+void TrackRendererAdapter::ErrorMsgCb_(const TrackRendererErrorType error_code,
+                                       char* error_msg, UserData userdata) {
+  auto adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnErrorMsg(
+      adapter_utils::ConvertToErrorType(error_code), error_msg);
+}
+
 void TrackRendererAdapter::ResourceConflictCb_(UserData userdata) {
   auto adapter = static_cast<TrackRendererAdapter*>(userdata);
   if (!adapter) return;
@@ -692,6 +1081,7 @@ void TrackRendererAdapter::FlushDoneCb_(UserData userdata) {
   if (!adapter) return;
   adapter->eventlistener_->OnFlushDone();
 }
+// LCOV_EXCL_STOP
 
 void TrackRendererAdapter::EosCb_(UserData userdata) {
   auto adapter = static_cast<TrackRendererAdapter*>(userdata);
@@ -717,6 +1107,7 @@ void TrackRendererAdapter::FirstDecodingDoneCb_(UserData userdata) {
   adapter->eventlistener_->OnFirstDecodingDone();
 }
 
+// LCOV_EXCL_START
 void TrackRendererAdapter::SubtitleRawDataCb_(
     TrackRendererDecoderInputBuffer* buf, const TrackRendererSubtitleType type,
     UserData userdata) {
@@ -771,7 +1162,12 @@ void TrackRendererAdapter::ClosedCaptionDataCb_(const char* data,
   adapter->eventlistener_->OnClosedCaptionData(data, size);
 }
 
+#ifdef DRM_MAPI_AARCH_64
+void TrackRendererAdapter::DrmInitDataCb_(unsigned long* drmhandle,
+                                          unsigned int len,
+#else
 void TrackRendererAdapter::DrmInitDataCb_(int* drmhandle, unsigned int len,
+#endif
                                           unsigned char* psshdata,
                                           TrackRendererTrackType type,
                                           UserData userdata) {
@@ -780,6 +1176,7 @@ void TrackRendererAdapter::DrmInitDataCb_(int* drmhandle, unsigned int len,
   adapter->eventlistener_->OnDrmInitData(
       drmhandle, len, psshdata, adapter_utils::ConvertToTrackType(type));
 }
+// LCOV_EXCL_STOP
 
 void TrackRendererAdapter::BufferStatusCb_(
     const TrackRendererTrackType type, const TrackRendererBufferStatus status,
@@ -799,6 +1196,15 @@ void TrackRendererAdapter::SeekDataCb_(const TrackRendererTrackType type,
   adapter->eventlistener_->OnSeekData(adapter_utils::ConvertToTrackType(type),
                                       offset);
 }
+// LCOV_EXCL_START
+
+void TrackRendererAdapter::MediaPacketGetTbmBufPtrCb_(void** ptr,
+                                                      bool is_scale_change,
+                                                      UserData userdata) {
+  auto adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnMediaPacketGetTbmBufPtr(ptr, is_scale_change);
+}
 
 void TrackRendererAdapter::MediaPacketVideoDecodedCb_(
     const TrackRendererDecodedVideoPacket* packet, UserData userdata) {
@@ -808,5 +1214,119 @@ void TrackRendererAdapter::MediaPacketVideoDecodedCb_(
       adapter_utils::ConvertToDecodedVideoPacket(packet);
   adapter->eventlistener_->OnMediaPacketVideoDecoded(_packet);
 }
+// LCOV_EXCL_STOP
+
+void TrackRendererAdapter::MediaPacketVideoRawDecodedCb_(
+    const TrackRendererDecodedVideoRawModePacket* packet,
+    TrackRendererDecodedVideoType type, UserData userdata) {
+  auto adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  DecodedVideoRawModePacket _packet;
+  _packet.type = static_cast<DecodedVideoRawModePacketType>(type);
+  _packet.pts = packet->pts;
+  _packet.width = packet->width;
+  _packet.height = packet->height;
+  _packet.data =
+      *static_cast<DecodedVideoRawModePacket::Data*>(packet->internal_data);
+  adapter->eventlistener_->OnMediaPacketVideoRawDecoded(_packet);
+}
+
+void TrackRendererAdapter::VideoDecoderUnderrunCb_(UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnVideoDecoderUnderrun();
+}
+
+void TrackRendererAdapter::VideoLatencyStatusCb_(
+    const TrackRendererLatencyStatus video_latency_status, UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnVideoLatencyStatus(
+      adapter_utils::ConvertToLatencyStatus(video_latency_status));
+}
+
+void TrackRendererAdapter::AudioLatencyStatusCb_(
+    const TrackRendererLatencyStatus audio_latency_status, UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnAudioLatencyStatus(
+      adapter_utils::ConvertToLatencyStatus(audio_latency_status));
+}
+
+void TrackRendererAdapter::VideoHighLatencyCb_(UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnVideoHighLatency();
+}
+// LCOV_EXCL_START
+
+void TrackRendererAdapter::AudioHighLatencyCb_(UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnAudioHighLatency();
+}
+
+void TrackRendererAdapter::MultiviewStartVideoCb_(UserData userdata) {
+  auto adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnMultiviewStartVideo();
+}
+
+void TrackRendererAdapter::MultiviewStopVideoCb_(UserData userdata) {
+  auto adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnMultiviewStopVideo();
+}
+// LCOV_EXCL_STOP
+
+void TrackRendererAdapter::VideoFrameDroppedCb_(const uint64_t count,
+                                                UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  adapter->eventlistener_->OnVideoFrameDropped(count);
+}
+
+bool TrackRendererAdapter::GetDecodingTime(StreamType type,
+                                           int32_t* time_millisecond) {
+  TrackRendererTrackType track_type =
+      adapter_utils::ConvertToTrackRendererTrackTypeFromStreamType(type);
+
+  if (trackrenderer_get_decoding_time(handle_, track_type, time_millisecond) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+bool TrackRendererAdapter::SetSimpleMixOutBufferLevel(const int& level) {
+  if (trackrenderer_set_simple_mix_out_buffer_level(handle_, level) ==
+      kFailed) {
+    return false;
+  }
+  return true;
+}
+
+void TrackRendererAdapter::DecoderInputBufferTime(
+    const TrackRendererTrackType type,
+    const TrackRendererDecoderBufferTime time, UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  DecoderBufferTime decoder_buffer_time;
+  decoder_buffer_time.pts = time.pts;
+  decoder_buffer_time.system_time = time.system_time;
+  adapter->eventlistener_->OnDecoderInputBufferTime(
+      adapter_utils::ConvertToTrackType(type), decoder_buffer_time);
+}
 
-}  // namespace plusplayer
+void TrackRendererAdapter::DecoderOutputBufferTime(
+    const TrackRendererTrackType type,
+    const TrackRendererDecoderBufferTime time, UserData userdata) {
+  auto* adapter = static_cast<TrackRendererAdapter*>(userdata);
+  if (!adapter) return;
+  DecoderBufferTime decoder_buffer_time;
+  decoder_buffer_time.pts = time.pts;
+  decoder_buffer_time.system_time = time.system_time;
+  adapter->eventlistener_->OnDecoderOutputBufferTime(
+      adapter_utils::ConvertToTrackType(type), decoder_buffer_time);
+}
+}  // namespace esplusplayer
index 3703fc2..1d429e6 100644 (file)
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "core/trackrendereradapter_utils.h"
 
 
 #include "core/utils/plusplayer_log.h"
 
-namespace plusplayer {
+namespace esplusplayer {
 
 namespace adapter_utils {
 
 void InitTrack(TrackRendererTrack* track) {
+#ifdef TIZEN_FEATURE_PUBLIC
+  memset(track, 0x00, sizeof(TrackRendererTrack));
+#endif
   track->index = kTrackRendererInvalidTrackIndex;  // int index
   track->id = 0;                                   // int id
   track->mimetype = nullptr;                       // const char* mimetype
@@ -40,10 +55,6 @@ void InitTrack(TrackRendererTrack* track) {
   track->use_swdecoder = 0;                        // int use_swdecoder
   track->language_code = nullptr;                  // const char* language_code
   track->subtitle_format = nullptr;  // const char* subtitle_format
-  track->stream_format = nullptr;
-  track->alignment = nullptr;
-  track->original_media_type = nullptr;
-  track->protection_system = nullptr;
 }
 
 void MakeGeometry(Geometry* roi, const TrackRendererGeometry& geometry) {
@@ -54,11 +65,20 @@ void MakeGeometry(Geometry* roi, const TrackRendererGeometry& geometry) {
 }
 
 void MakeTrackRendererDrmProperty(
+#if DRM_MAPI_AARCH_64
+    TrackRendererDrmProperty_64bit* trackrenderer_drm_property,
+#else
     TrackRendererDrmProperty* trackrenderer_drm_property,
+#endif
     const drm::Property& drm_property) {
   trackrenderer_drm_property->type =
       ConvertToTrackRendererDrmType(drm_property.type);
+#if DRM_MAPI_AARCH_64
+  trackrenderer_drm_property->handle =
+      static_cast<unsigned long>(drm_property.handle);
+#else
   trackrenderer_drm_property->handle = static_cast<int>(drm_property.handle);
+#endif
   trackrenderer_drm_property->external_decryption =
       static_cast<bool>(drm_property.external_decryption);
   trackrenderer_drm_property->license_acquired_cb =
@@ -83,7 +103,6 @@ void MakeTrackRendererCropArea(TrackRendererCropArea* crop,
   crop->scale_h = area.scale_h;
 }
 
-#if 0
 void MakeTrackRendererRenderRect(TrackRendererRenderRect* output,
                                  const RenderRect& input) {
   output->x = input.x;
@@ -91,7 +110,6 @@ void MakeTrackRendererRenderRect(TrackRendererRenderRect* output,
   output->w = input.w;
   output->h = input.h;
 }
-#endif
 
 void MakeTrackRendererTrack(TrackRendererTrack* track, const Track& trackinfo) {
   InitTrack(track);
@@ -122,10 +140,42 @@ void MakeTrackRendererTrack(TrackRendererTrack* track, const Track& trackinfo) {
   track->use_swdecoder = trackinfo.use_swdecoder;
   track->language_code = trackinfo.language_code.c_str();
   track->subtitle_format = trackinfo.subtitle_format.c_str();
-  track->stream_format = trackinfo.stream_format.c_str();
-  track->alignment = trackinfo.alignment.c_str();
-  track->original_media_type = trackinfo.original_media_type.c_str();
-  track->protection_system = trackinfo.protection_system.c_str();
+}
+
+void MakeTrackRendererAppInfo(TrackRendererAppInfo* app_attr,
+                              const PlayerAppInfo& app_info) {
+  app_attr->id = const_cast<char*>(app_info.id.c_str());
+  app_attr->version = const_cast<char*>(app_info.version.c_str());
+  app_attr->type = const_cast<char*>(app_info.type.c_str());
+}
+
+void MakeTrackRendererAppInfoEx(TrackRendererAppInfoEx* app_attr,
+                                const PlayerAppInfoEx& app_info) {
+  app_attr->id = const_cast<char*>(app_info.id.c_str());
+  app_attr->version = const_cast<char*>(app_info.version.c_str());
+  app_attr->type = const_cast<char*>(app_info.type.c_str());
+  app_attr->runtitle = const_cast<char*>(app_info.runtitle.c_str());
+}
+
+void MakeAudioEasingInfo(AudioEasingInfo* easing_info,
+                         const TrackRendererAudioEasingInfo& easing_attr) {
+  easing_info->target_volume = easing_attr.target_volume;
+  easing_info->duration = easing_attr.duration;
+  easing_info->type = ConvertToAudioEasingType(easing_attr.type);
+}
+
+void MakeTrackRendererAudioEasingInfo(TrackRendererAudioEasingInfo* easing_attr,
+                                      const AudioEasingInfo& easing_info) {
+  easing_attr->target_volume = easing_info.target_volume;
+  easing_attr->duration = easing_info.duration;
+  easing_attr->type = ConvertToTrackRendererAudioEasingType(easing_info.type);
+}
+
+void MakeTrackRendererRational(TrackRendererRational* rational_attr,
+                               const Rational& rational_info) {
+  if (!rational_attr) return;
+  rational_attr->num = rational_info.num;
+  rational_attr->den = rational_info.den;
 }
 
 DisplayMode ConvertToDisplayMode(TrackRendererDisplayMode typevalue) {
@@ -303,6 +353,7 @@ ErrorType ConvertToErrorType(const TrackRendererErrorType type) {
   }
 }
 
+// LCOV_EXCL_START
 #ifndef TRACKRENDERER_FEATURE_DEPRECATE_SUBTITLE_CB
 SubtitleAttrType ConvertToSubtitleAttrType(
     const TrackRendererSubtitleAttrType& type) {
@@ -427,6 +478,7 @@ SubtitleAttrType ConvertToSubtitleAttrType(
   }
 }
 #endif
+// LCOV_EXCL_STOP
 
 SubtitleType ConvertToSubtitleType(const TrackRendererSubtitleType& type) {
   switch (type) {
@@ -471,7 +523,11 @@ DecodedVideoPacket ConvertToDecodedVideoPacket(
   _packet.pts = packet->pts;
   _packet.duration = packet->duration;
   _packet.surface_data = static_cast<tbm_surface_h>(packet->surface_data);
+#ifdef TIZEN_FEATURE_PUBLIC
   _packet.buffer_addr = packet->buffer_addr;
+#else
+  _packet.scaler_index = packet->scaler_index;
+#endif
   return _packet;
 }
 
@@ -481,7 +537,11 @@ TrackRendererDecodedVideoPacket ConvertToDecodedVideoPacket(
   _packet.pts = packet.pts;
   _packet.duration = packet.duration;
   _packet.surface_data = static_cast<tbm_surface_h>(packet.surface_data);
+#ifdef TIZEN_FEATURE_PUBLIC
   _packet.buffer_addr = packet.buffer_addr;
+#else
+  _packet.scaler_index = packet.scaler_index;
+#endif
   return _packet;
 }
 
@@ -497,6 +557,9 @@ TrackRendererDecodedVideoFrameBufferType ConvertToVideoFrameBufferType(
     case DecodedVideoFrameBufferType::kScale: {
       return kTrackRendererDecodedVideoFrameBufferScale;
     }
+    case DecodedVideoFrameBufferType::kManualCopy: {
+      return kTrackRendererDecodedVideoFrameBufferManualCopy;
+    }
     case DecodedVideoFrameBufferType::kNone: {
       return kTrackRendererDecodedVideoFrameBufferNone;
     }
@@ -625,9 +688,6 @@ TrackRendererDrmType ConvertToTrackRendererDrmType(const drm::Type& drm_type) {
     case drm::Type::kWidevineCdm: {
       return kTrackRendererDrmTypeWidevineCdm;
     }
-    case drm::Type::kClearkey: {
-      return kTrackRendererDrmTypeClearkey;
-    }
     case drm::Type::kMax: {
       return kTrackRendererDrmTypeDrmMax;
     }
@@ -693,6 +753,28 @@ TrackRendererTrackType ConvertToTrackRendererTrackTypeFromStreamType(
   }
 }
 
+TrackRendererVideoStreamRotation ConvertToTrackRendererVideoStreamRotation(
+    const VideoRotation& rotation) {
+  switch (rotation) {
+    case VideoRotation::kVideoRotateNone: {
+      return kTrackRendererVideoStreamRotationNone;
+    }
+    case VideoRotation::kVideoRotate90: {
+      return kTrackRendererVideoStreamRotation90;
+    }
+    case VideoRotation::kVideoRotate180: {
+      return kTrackRendererVideoStreamRotation180;
+    }
+    case VideoRotation::kVideoRotate270: {
+      return kTrackRendererVideoStreamRotation270;
+    }
+    default:
+      LOG_ERROR("unknown rotation type");
+      return kTrackRendererVideoStreamRotationNone;
+  }
+}
+
+// LCOV_EXCL_START
 #ifndef TRACKRENDERER_FEATURE_DEPRECATE_SUBTITLE_CB
 boost::any SetSubtitleAttrValue(const TrackRendererSubtitleAttr& attr) {
   boost::any any_value;
@@ -752,6 +834,7 @@ boost::any SetSubtitleAttrValue(const TrackRendererSubtitleAttr& attr) {
   return any_value;
 }
 #endif
+// LCOV_EXCL_STOP
 
 BufferStatus ConvertToBufferStatus(const TrackRendererBufferStatus& status) {
   switch (status) {
@@ -766,6 +849,152 @@ BufferStatus ConvertToBufferStatus(const TrackRendererBufferStatus& status) {
   return BufferStatus::kUnderrun;
 }
 
+TrackRendererCatchUpSpeed ConvertToTrackRendererCatchUpSpeed(
+    const CatchUpSpeed& level) {
+  switch (level) {
+    case CatchUpSpeed::kNone: {
+      return kTrackRendererCatchUpSpeedNone;
+    }
+    case CatchUpSpeed::kSlow: {
+      return kTrackRendererCatchUpSpeedSlow;
+    }
+    case CatchUpSpeed::kNormal: {
+      return kTrackRendererCatchUpSpeedNormal;
+    }
+    case CatchUpSpeed::kFast: {
+      return kTrackRendererCatchUpSpeedFast;
+    }
+  }
+  LOG_ERROR("Unknown catch up speed");
+  return kTrackRendererCatchUpSpeedNone;
+}
+
+LatencyStatus ConvertToLatencyStatus(const TrackRendererLatencyStatus& status) {
+  switch (status) {
+    case kTrackRendererLatencyStatusLow: {
+      return LatencyStatus::kLow;
+    }
+    case kTrackRendererLatencyStatusMid: {
+      return LatencyStatus::kMid;
+    }
+    case kTrackRendererLatencyStatusHigh: {
+      return LatencyStatus::kHigh;
+    }
+  }
+  LOG_ERROR("Unknown status");
+  return LatencyStatus::kLow;
+}
+
+AudioEasingType ConvertToAudioEasingType(
+    const TrackRendererAudioEasingType& type) {
+  switch (type) {
+    case TrackRendererAudioEasingType::kTrackRendererAudioEasingLinear: {
+      return AudioEasingType::kAudioEasingLinear;
+    }
+    case TrackRendererAudioEasingType::kTrackRendererAudioEasingIncubic: {
+      return AudioEasingType::kAudioEasingIncubic;
+    }
+    case TrackRendererAudioEasingType::kTrackRendererAudioEasingOutcubic: {
+      return AudioEasingType::kAudioEasingOutcubic;
+    }
+    default:
+      LOG_ERROR("Unknown audio easing type");
+      return AudioEasingType::kAudioEasingNone;
+  }
+}
+
+TrackRendererAudioEasingType ConvertToTrackRendererAudioEasingType(
+    const AudioEasingType& type) {
+  switch (type) {
+    case AudioEasingType::kAudioEasingLinear: {
+      return TrackRendererAudioEasingType::kTrackRendererAudioEasingLinear;
+    }
+    case AudioEasingType::kAudioEasingIncubic: {
+      return TrackRendererAudioEasingType::kTrackRendererAudioEasingIncubic;
+    }
+    case AudioEasingType::kAudioEasingOutcubic: {
+      return TrackRendererAudioEasingType::kTrackRendererAudioEasingOutcubic;
+    }
+    default:
+      LOG_ERROR("Unknown audio easing type");
+      return TrackRendererAudioEasingType::kTrackRendererAudioEasingNone;
+  }
+}
+
+bool ConvertToTrackRendererRscType(const RscType& typevalue,
+                                   TrackRendererRscType* type) {
+  switch (typevalue) {
+    case RscType::kVideoRenderer: {
+      *type = kTrackRendererRscTypeVideoRenderer;
+      return true;
+    }
+    default:
+      LOG_ERROR("unknown resource type");
+      return false;
+  }
+}
+
+bool ConvertToTrackRendererAdvPictureQualityType(
+    const AdvPictureQualityType& typevalue,
+    TrackRendererAdvPictureQualityType* type) {
+  switch (typevalue) {
+    case AdvPictureQualityType::kVideoCall: {
+      *type = kTrackRendererAdvPictureQualityTypeVideoCall;
+      return true;
+    }
+    case AdvPictureQualityType::kUsbCamera: {
+      *type = kTrackRendererAdvPictureQualityTypeUsbCamera;
+      return true;
+    }
+    case AdvPictureQualityType::kAirplayMirroring: {
+      *type = kTrackRendererAdvPictuerQualityTypeAirplayMirroring;
+      return true;
+    }
+    default:
+      LOG_ERROR("unknown resource type");
+      return false;
+  }
+}
+
+bool ConvertToTrackRendererRscAllocPolicy(const RscAllocPolicy& policyvalue,
+                                          TrackRendererRscAllocPolicy* policy) {
+  switch (policyvalue) {
+    case RscAllocPolicy::kRscAllocExclusive: {
+      *policy = kTrackRendererRscAllocExclusive;
+      return true;
+    }
+    case RscAllocPolicy::kRscAllocConditional: {
+      *policy = kTrackRendererRscAllocConditional;
+      return true;
+    }
+    case RscAllocPolicy::kRscAllocExclusiveNoExplicit: {
+      *policy = kTrackRendererRscAllocExclusiveNoExplicit;
+      return true;
+    }
+    default:
+      LOG_ERROR("unknown policy");
+      return false;
+  }
+}
+
+bool ConvertToTrackRendererAlternativeAudioResource(
+    const PlayerAudioResourceType& typevalue, unsigned int* type) {
+  switch (typevalue) {
+    case kPlayerAudioResourceTypeMain:
+      *type = 0;
+      return true;
+    case kPlayerAudioResourceTypeSubDecoder:
+      *type = 1;
+      return true;
+    case kPlayerAudioResourceTypeSimpleMixOut:
+      *type = 3;
+      return true;
+    default:
+      LOG_ERROR("unkown type");
+      return false;
+  }
+}
+
 }  // namespace adapter_utils
 
-}  // namespace plusplayer
+}  // namespace esplusplayer
diff --git a/src/plusplayer-core/src/videoframetypestrategy.cpp b/src/plusplayer-core/src/videoframetypestrategy.cpp
new file mode 100644 (file)
index 0000000..e40c428
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "core/videoframetypestrategy.h"
+
+#include <trackrenderer_capi/trackrenderer_capi.h>
+#include <trackrenderer_capi/trackrenderer_internal.h>
+
+#include "core/trackrendereradapter_utils.h"
+
+namespace esplusplayer {
+DefaultVideoFrameTypeStrategy::DefaultVideoFrameTypeStrategy(
+    const DecodedVideoFrameBufferType type)
+    : type_(type) {}
+
+void DefaultVideoFrameTypeStrategy::SetType(TrackRendererHandle handle) {
+  trackrenderer_set_video_frame_buffer_type(
+      handle, adapter_utils::ConvertToVideoFrameBufferType(type_));
+}
+
+void RawVideoFrameTypeStrategy::SetType(TrackRendererHandle handle) {
+  trackrenderer_set_video_frame_buffer_type_ext(
+      handle, kTrackRendererDecodedVideoFrameBufferExtRaw);
+}
+}  // namespace esplusplayer
\ No newline at end of file
index 0cebb87..7c2e1d4 100644 (file)
@@ -6,14 +6,23 @@ INCLUDE_DIRECTORIES(../include)
 
 link_directories(${CMAKE_SOURCE_DIR}/../)
 
+SET(${fw_name}_CXXFLAGS "-Wall -Werror -std=c++17 -pthread -fPIE -Wl,-z,relro -fstack-protector -fno-delete-null-pointer-checks")
+
+SET(${fw_name}_LDFLAGS)
+
 INCLUDE(FindPkgConfig)
-    pkg_check_modules(${fw_test} REQUIRED glib-2.0 appcore-efl elementary capi-mediademuxer)
+pkg_check_modules(${fw_test} REQUIRED glib-2.0 appcore-efl elementary capi-mediademuxer)
 
 FOREACH(flag ${${fw_test}_CFLAGS})
-    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+FOREACH(flag ${${fw_name}_CXXFLAGS})
+SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -pie -fPIC -Wall -Werror")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -pie -fPIC -Wall -Werror")
 
 aux_source_directory(. sources)
 
@@ -28,4 +37,4 @@ TARGET_LINK_LIBRARIES(${test_name} esplusplayer ${${fw_test}_LDFLAGS})
 INSTALL(
     TARGETS ${test_name}
     DESTINATION bin
-)
\ No newline at end of file
+)
similarity index 97%
rename from test/esplusplayer_test.c
rename to test/esplusplayer_test.cpp
index f5b25c7..e48580f 100644 (file)
@@ -1,18 +1,18 @@
 /*
-* Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -196,7 +196,7 @@ void create_render_rect_and_bg(Evas_Object *win)
 
 static int __app_create(void *data)
 {
-       appdata *ad = data;
+       appdata *ad = (appdata *)data;
        Evas_Object *win = NULL;
 
        /* use gl backend */
@@ -224,7 +224,7 @@ static int __app_create(void *data)
 
 static int __app_terminate(void *data)
 {
-       appdata *ad = data;
+       appdata *ad = (appdata *)data;
 
        if (g_eo) {
                evas_object_del(g_eo);
@@ -635,7 +635,7 @@ static void __test_set_audio_stream_info()
                g_test_h->streams[AUDIO_STREAM].pending_packet = audbuf;
                if (media_packet_get_codec_data (audbuf, &codec_data, &codec_data_length) == MEDIA_PACKET_ERROR_NONE) {
                        g_print("Audio has codec data\n");
-                       audio_info.codec_data = codec_data;
+                       audio_info.codec_data = (char *)codec_data;
                        audio_info.codec_data_length = codec_data_length;
                }
        }
@@ -643,7 +643,7 @@ static void __test_set_audio_stream_info()
        audio_info.bitrate = bit;
        audio_info.channels = channels;
        audio_info.sample_rate = rate;
-       audio_info.mime_type = type;
+       audio_info.mime_type = (esplusplayer_audio_mime_type)type;
 
        ret = esplusplayer_set_audio_stream_info(g_test_h->espp_h, &audio_info);
        if (ret != ESPLUSPLAYER_ERROR_TYPE_NONE)
@@ -712,7 +712,7 @@ static void __test_set_video_stream_info()
                g_test_h->streams[VIDEO_STREAM].pending_packet = vidbuf;
                if (media_packet_get_codec_data (vidbuf, &codec_data, &codec_data_length) == MEDIA_PACKET_ERROR_NONE) {
                        g_print("Video has codec data\n");
-                       video_info.codec_data = codec_data;
+                       video_info.codec_data = (char *)codec_data;
                        video_info.codec_data_length = codec_data_length;
                }
        }
@@ -720,7 +720,7 @@ static void __test_set_video_stream_info()
        video_info.height = height;
        video_info.framerate_num = framerate;
        video_info.framerate_den = 1;
-       video_info.mime_type = type;
+       video_info.mime_type = (esplusplayer_video_mime_type)type;
 
        ret = esplusplayer_set_video_stream_info(g_test_h->espp_h, &video_info);
        if (ret != ESPLUSPLAYER_ERROR_TYPE_NONE)
@@ -1178,7 +1178,7 @@ static void __test_set_display(int type)
                g_print("!!! Not support display type(%d)\n", type);
                return;
        }
-       ret = esplusplayer_set_display(g_test_h->espp_h, type, display);
+       ret = esplusplayer_set_display(g_test_h->espp_h, (esplusplayer_display_type)type, display);
        if (ret != ESPLUSPLAYER_ERROR_TYPE_NONE)
                g_print("                       => failed to esplusplayer_set_display(%d)\n", type);
        else
@@ -1197,7 +1197,7 @@ static void __test_set_display_mode(int mode)
                return;
        }
 
-       int ret = esplusplayer_set_display_mode(g_test_h->espp_h, mode);
+       int ret = esplusplayer_set_display_mode(g_test_h->espp_h, (esplusplayer_display_mode)mode);
        if (ret != ESPLUSPLAYER_ERROR_TYPE_NONE)
                g_print("                       => failed to esplusplayer_set_display_mode(%d)\n", mode);
        else
@@ -1258,7 +1258,7 @@ static void __test_set_display_rotation(int mode)
                return;
        }
 
-       int ret = esplusplayer_set_display_rotation(g_test_h->espp_h, mode);
+       int ret = esplusplayer_set_display_rotation(g_test_h->espp_h, (esplusplayer_display_rotation_type)mode);
        if (ret != ESPLUSPLAYER_ERROR_TYPE_NONE)
                g_print("                       => failed to esplusplayer_set_display_rotation(%d)\n", mode);
        else
@@ -1293,12 +1293,6 @@ static void __test_set_low_latency_mode(int value)
                mode = ESPLUSPLAYER_LOW_LATENCY_MODE_NONE;
                break;
        case 1:
-               mode = ESPLUSPLAYER_LOW_LATENCY_MODE_VIDEO;
-               break;
-       case 2:
-               mode = ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_SYNC;
-               break;
-       case 3:
                mode = ESPLUSPLAYER_LOW_LATENCY_MODE_DISABLE_PREROLL;
                break;
        default:
@@ -1593,7 +1587,7 @@ static void __displaymenu()
        } else if (g_menu_state == CURRENT_STATUS_SET_RENDER_TIME_OFFSET) {
                g_print("*** Input stream type and time offset\n");
        } else if (g_menu_state == CURRENT_STATUS_SET_LOW_LATENCY_MODE) {
-               g_print("*** Input low latency mode (0: none, 1: video, 2: disable sync, 3: disable preroll)\n");
+               g_print("*** Input low latency mode (0: none, 1: disable preroll)\n");
        } else {
                g_print("*** Unknown status.\n");
                quit_program();
diff --git a/tomato/tc/TCList.dat b/tomato/tc/TCList.dat
new file mode 100644 (file)
index 0000000..568f446
--- /dev/null
@@ -0,0 +1 @@
+unit_test/ut_esplusplayer_all.xml
\ No newline at end of file
diff --git a/tomato/tc/testfarm_script.xml b/tomato/tc/testfarm_script.xml
new file mode 100644 (file)
index 0000000..517b656
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TestFarm>
+       <Target AssignTargets="1"> 
+               <TestPackage Name="esplusplayer" RpmName="esplusplayer-ut-component-tomato" DatFile="TCList.dat"/>      
+</TestFarm>
\ No newline at end of file
diff --git a/tomato/tc/unit_test/ut_esplusplayer_all.xml b/tomato/tc/unit_test/ut_esplusplayer_all.xml
new file mode 100644 (file)
index 0000000..afcb07f
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TestCase Name="ESPlusplayer API Test" Description="ESPlusplayer APIs unit test" LogFilter="GST_LOG:* TOMATO:* PLUSPLAYER:* STREAMING_ENGINE:*">
+       <Procedure Number="1" Description="ESPlusplayer unit test">
+               <Step Name="ESPlusplayer unit test" Type="EXT_TEST_PACKAGE" Command="GTEST_TOTAL_SHARDS=1 GTEST_SHARD_INDEX=0 /usr/bin/esplusplayer_ut --gtest_output=xml:/usr/etc/esplusplayer_tests_result.xml" Permission="ROOT">
+                       <Input Expirytime="10800"/>
+                       <Output Type="DetectFile" FilePath="/usr/etc/esplusplayer_tests_result.xml"/>
+               </Step>
+       </Procedure>
+</TestCase>
old mode 100755 (executable)
new mode 100644 (file)
index 0d17a5b..93abdb9
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef __PLUSPLAYER_UT_INCLUDE_APPWINDOW_H__
 #define __PLUSPLAYER_UT_INCLUDE_APPWINDOW_H__
index 1acad46..4998868 100644 (file)
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef __PLUSPLAYER_UT_INCLUDE_ES_EVENT_LISTENER_H__
 #define __PLUSPLAYER_UT_INCLUDE_ES_EVENT_LISTENER_H__
@@ -65,12 +77,12 @@ class EsPlayerEventCallback {
   static void OnBufferByteStatus(const esplusplayer_stream_type,
                                  const esplusplayer_buffer_status, uint64_t,
                                  void* userdata) {
-    std::cout << "OnBufferByteStatus" << std::endl;
+    // std::cout << "OnBufferByteStatus" << std::endl;
   }
   static void OnBufferTimeStatus(const esplusplayer_stream_type,
                                  const esplusplayer_buffer_status, uint64_t,
                                  void* userdata) {
-    std::cout << "OnBufferTimeStatus" << std::endl;
+    // std::cout << "OnBufferTimeStatus" << std::endl;
   }
   static void OnVideoDecoded(const esplusplayer_decoded_video_packet * pkt,
                              void* userdata) {
index ef054e3..6f91292 100644 (file)
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef __PLUSPLAYER_UT_INCLUDE_ES_READER_H__
 #define __PLUSPLAYER_UT_INCLUDE_ES_READER_H__
index 01b8db1..8d61550 100644 (file)
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2019] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef __PLUSPLAYER_UT_INCLUDE_ESPLUSPLAYER_TCLIST_H__
 #define __PLUSPLAYER_UT_INCLUDE_ESPLUSPLAYER_TCLIST_H__
index a5a83b9..ff6aee2 100644 (file)
@@ -1,6 +1,19 @@
-//
-// @ Copyright [2019] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef __PLUSPLAYER_UT_INCLUDE_PLUSPLAYER_UTILITY_H__
 #define __PLUSPLAYER_UT_INCLUDE_PLUSPLAYER_UTILITY_H__
 
@@ -10,7 +23,7 @@
 
 #include "core/utils/plusplayer_log.h"
 #include "esplusplayer_capi/esplusplayer_capi.h"
-#include "plusplayer/types/display.h"
+#include "esplusplayer/types/display.h"
 #include "ut/include/appwindow.h"
 
 #include <condition_variable>
@@ -46,12 +59,12 @@ class Utility {
   const char* GetCurrentTestName(void);
 
 
-  esplusplayer_handle GetOpenedESPP(plusplayer::Geometry& roi);
+  esplusplayer_handle GetOpenedESPP(esplusplayer::Geometry& roi);
 
   esplusplayer_handle GetPreparedESPP(std::string& uri,
-                                      plusplayer::Geometry& roi);
+                                      esplusplayer::Geometry& roi);
 
-  esplusplayer_handle GetStartedESPP(std::string& uri, plusplayer::Geometry& roi);
+  esplusplayer_handle GetStartedESPP(std::string& uri, esplusplayer::Geometry& roi);
 
   bool PrepareESPP(esplusplayer_handle player, std::string& uri,
                    EsType type = EsType::kBoth);
index a6b8fab..8d99cb0 100644 (file)
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef __PLUSPLAYER_UT_INCLUDE_ESCOMMON_H__
 #define __PLUSPLAYER_UT_INCLUDE_ESCOMMON_H__
 
 #include "gtest/gtest.h"
 
-#include "plusplayer/espacket.h"
+#include "esplusplayer/espacket.h"
 #include "ut/include/appwindow.h"
 
-namespace pp = plusplayer;
+namespace pp = esplusplayer;
 
 namespace utils {
 inline bool Exists(const std::string &path) {
index 5d3c068..5b2438f 100644 (file)
@@ -1,7 +1,18 @@
-
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <stdio.h>
 
@@ -25,7 +36,7 @@
 #include "ut/include/streamreader.hpp"
 #include "ut/include/plusplayer/utility.h"
 
-using namespace plusplayer;
+using namespace esplusplayer;
 using namespace utils;
 
 using utils::Utility;
@@ -868,7 +879,7 @@ TEST_F(EsTest, vdapi_basic_esplusplayer_set_submit_data_type_n_1) {
     ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsBasicTest, vdapi_basic_esplusplayer_set_submit_data_type_n_2) {
+TEST_P(EsBasicTest, DISABLED_vdapi_basic_esplusplayer_set_submit_data_type_n_2) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   ASSERT_EQ(esplusplayer_set_submit_data_type(
     esplayer_, (esplusplayer_submit_data_type)10),
@@ -899,7 +910,7 @@ TEST_F(EsTest, vdapi_basic_esplusplayer_set_video_codec_type_n_1) {
     ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsBasicTest, vdapi_basic_esplusplayer_set_video_codec_type_n_2) {
+TEST_P(EsBasicTest, DISABLED_vdapi_basic_esplusplayer_set_video_codec_type_n_2) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   ASSERT_EQ(esplusplayer_set_display(esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
     util_.GetWindow()), ESPLUSPLAYER_ERROR_TYPE_NONE);
@@ -931,7 +942,7 @@ TEST_F(EsTest, vdapi_basic_esplusplayer_set_audio_codec_type_n_1) {
     ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsBasicTest, vdapi_basic_esplusplayer_set_audio_codec_type_n_2) {
+TEST_P(EsBasicTest, DISABLED_vdapi_basic_esplusplayer_set_audio_codec_type_n_2) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   ASSERT_EQ(esplusplayer_set_display(esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
     util_.GetWindow()), ESPLUSPLAYER_ERROR_TYPE_NONE);
old mode 100755 (executable)
new mode 100644 (file)
index 46dacdb..5eafeeb
@@ -1,7 +1,18 @@
-
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <stdio.h>
 
@@ -26,7 +37,7 @@
 #include "ut/include/streamreader.hpp"
 #include "ut/include/plusplayer/utility.h"
 
-using namespace plusplayer;
+using namespace esplusplayer;
 using namespace utils;
 
 using utils::Utility;
@@ -122,14 +133,6 @@ TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_display_n_1) {
       ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_display_n_2) {
-  ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
-  ASSERT_EQ(
-      esplusplayer_set_display(esplayer_, (esplusplayer_display_type)ESPLUSPLAYER_DISPLAY_TYPE_MAX,
-                               util_.GetWindow()),
-      ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION);
-}
-
 TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_ecore_display_p_1) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   ASSERT_EQ(esplusplayer_set_ecore_display(
@@ -145,14 +148,6 @@ TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_ecore_display_n_1) {
             ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_ecore_display_n_2) {
-  ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
-  ASSERT_EQ(esplusplayer_set_ecore_display(
-                esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_MAX,
-                util_.EcoreWindow(), 0, 0, 1920, 1080),
-      ESPLUSPLAYER_ERROR_TYPE_INVALID_OPERATION);
-}
-
 TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_surface_display_p_1) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   unsigned int surfaceid = 1;
@@ -169,7 +164,7 @@ TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_surface_display_n_1) {
             ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_surface_display_n_2) {
+TEST_P(EsDisplayTest, DISABLED_vdapi_display_esplusplayer_set_surface_display_n_2) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   unsigned int surfaceid = 1;
   ASSERT_EQ(esplusplayer_set_surface_display(esplayer_,
@@ -178,7 +173,7 @@ TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_surface_display_n_2) {
             ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_surface_display_n_3) {
+TEST_P(EsDisplayTest, DISABLED_vdapi_display_esplusplayer_set_surface_display_n_3) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   unsigned int surfaceid = 1;
   ASSERT_EQ(esplusplayer_set_surface_display(esplayer_,
@@ -200,7 +195,7 @@ TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_display_mode_n_1) {
             ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_display_mode_n_2) {
+TEST_P(EsDisplayTest, DISABLED_vdapi_display_esplusplayer_set_display_mode_n_2) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   ASSERT_EQ(esplusplayer_set_display_mode(esplayer_,
                                              (esplusplayer_display_mode)100),
@@ -231,7 +226,7 @@ TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_display_roi_n_1) {
     ESPLUSPLAYER_ERROR_TYPE_INVALID_PARAMETER);
 }
 
-TEST_P(EsDisplayTest, vdapi_display_esplusplayer_set_display_roi_n_2) {
+TEST_P(EsDisplayTest, DISABLED_vdapi_display_esplusplayer_set_display_roi_n_2) {
   ASSERT_EQ(esplusplayer_open(esplayer_), ESPLUSPLAYER_ERROR_TYPE_NONE);
   ASSERT_EQ(
       esplusplayer_set_display(esplayer_, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
old mode 100755 (executable)
new mode 100644 (file)
index 4a87e7d..c51bfac
@@ -1,3 +1,19 @@
+/*\r
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
 #include "gmock/gmock.h"\r
 #include "gtest/gtest.h"\r
 \r
index 441cc5e..145592c 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include <Ecore.h>
 #include <Elementary.h>
 #include <gtest/gtest.h>
@@ -17,7 +33,7 @@
 //#include <jpeglib.h>
 
 
-using namespace plusplayer;
+using namespace esplusplayer;
 //using namespace tc;
 using UserData = void*;
 
old mode 100755 (executable)
new mode 100644 (file)
index b5e5f33..5c339a2
@@ -1,13 +1,25 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "gtest/gtest.h"
 #include "gmock/gmock.h"
 
 #include "plusplayer/espacket.h"
 
-namespace pp = plusplayer;
+namespace pp = esplusplayer;
 
 namespace {
 void MakeDummyMatroskaColor(pp::MatroskaColor& color_info) {
old mode 100755 (executable)
new mode 100644 (file)
index 450ae1c..3526ba5
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <atomic>
 #include <chrono>
old mode 100755 (executable)
new mode 100644 (file)
index b428b0e..f85376e
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <stdio.h>
 
@@ -20,7 +32,7 @@
 #include "tracksource/tracksource.h"
 #include "ut/include/appwindow.h"
 
-using namespace plusplayer;
+using namespace esplusplayer;
 
 static constexpr int kMaxSizeOfQueue = 3;
 static constexpr int kTrackTypes[] = {kTrackTypeAudio, kTrackTypeVideo,
@@ -73,7 +85,7 @@ class Feeder2 : public DecoderInputBufferListener {
 #endif
   }
 
-  bool Start(plusplayer::EsPlusPlayer *player) {
+  bool Start(esplusplayer::EsPlusPlayer *player) {
     LOG_ENTER;
     assert(player);
     std::lock_guard<std::mutex> lock(state_m_);
@@ -212,7 +224,7 @@ class Feeder2 : public DecoderInputBufferListener {
   };
 
  private:
-  plusplayer::EsPlusPlayer *player_ = nullptr;
+  esplusplayer::EsPlusPlayer *player_ = nullptr;
   State state_ = State::kNone;
   bool stop_ = false;
   std::mutex state_m_;
@@ -449,7 +461,7 @@ TEST_F(EsPlayerTest2, Play) {
                        0, 1920, 1080);
 #else
   Evas_Object *obj = appwindow->GetWindow().obj;
-  esplayer->SetDisplay(plusplayer::DisplayType::kOverlay, obj);
+  esplayer->SetDisplay(esplusplayer::DisplayType::kOverlay, obj);
 #endif
 
   esplayer->RegisterListener(mock_eventlistener.get(), nullptr);
@@ -520,7 +532,7 @@ TEST_F(EsPlayerTest2, Seek) {
     std::this_thread::sleep_for(std::chrono::seconds(10));
   };
 
-  esplayer->SetDisplay(plusplayer::DisplayType::kOverlay, obj);
+  esplayer->SetDisplay(esplusplayer::DisplayType::kOverlay, obj);
   esplayer->SetStream(GetVideoStream());
   esplayer->SetStream(GetAudioStream());
   esplayer->PrepareAsync();
@@ -587,7 +599,7 @@ TEST_F(EsPlayerTest2, DISABLED_SetPlaybackRate) {
     std::this_thread::sleep_for(std::chrono::seconds(10));
   };
 
-  esplayer->SetDisplay(plusplayer::DisplayType::kOverlay, obj);
+  esplayer->SetDisplay(esplusplayer::DisplayType::kOverlay, obj);
   esplayer->SetStream(GetVideoStream());
   esplayer->SetStream(GetAudioStream());
   esplayer->PrepareAsync();
@@ -651,7 +663,7 @@ TEST_F(EsPlayerTest2, A_DeactivateActivate) {
     tracksource->Start();
   };
   uint64_t cur_pos_msec = 0;
-  esplayer->SetDisplay(plusplayer::DisplayType::kOverlay, obj);
+  esplayer->SetDisplay(esplusplayer::DisplayType::kOverlay, obj);
   tracksource->SelectTrack(kTrackTypeAudio, 0, 0);
   esplayer->SetStream(GetVideoStream());
   esplayer->SetStream(GetAudioStream());
@@ -670,7 +682,7 @@ TEST_F(EsPlayerTest2, A_DeactivateActivate) {
   if (activated_track.index == 0) {
     printf("the index[%d] is already activated", 0);
   }
-  esplayer->Deactivate(static_cast<plusplayer::StreamType>(kTrackTypeAudio));
+  esplayer->Deactivate(static_cast<esplusplayer::StreamType>(kTrackTypeAudio));
   esplayer->GetPlayingTime(&cur_pos_msec);
 
   feeder->Flush(kTrackTypeAudio);
@@ -687,7 +699,7 @@ TEST_F(EsPlayerTest2, A_DeactivateActivate) {
     return;
   }
   esplayer->SetStream(GetAudioStream2());
-  esplayer->Activate(static_cast<plusplayer::StreamType>(kTrackTypeAudio));
+  esplayer->Activate(static_cast<esplusplayer::StreamType>(kTrackTypeAudio));
   esplayer->Seek(cur_pos_msec);
   fake_eventlistener->WaitAllStreamData();
   auto new_feeding_task = std::thread(feeding_task_fn);
@@ -733,7 +745,7 @@ TEST_F(EsPlayerTest2, VideoSeek) {
     tracksource->Start();
   };
 
-  esplayer->SetDisplay(plusplayer::DisplayType::kOverlay, obj);
+  esplayer->SetDisplay(esplusplayer::DisplayType::kOverlay, obj);
   esplayer->SetStream(GetVideoStream());
   esplayer->SetStream(GetAudioStream());
   esplayer->PrepareAsync();
old mode 100755 (executable)
new mode 100644 (file)
index 6c91b2c..e58abe8
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <memory>
 #include <utility>
old mode 100755 (executable)
new mode 100644 (file)
index ec13bdf..595b382
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
old mode 100755 (executable)
new mode 100644 (file)
index b2eeae3..d61a626
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <iostream>
 
@@ -12,7 +24,7 @@
 #include "core/utils/scope_exit.h"          // to test "ScopeExit"
 #include "trackrenderer/core/pipeline.hpp"  // to test "UnlinkElements"
 
-using namespace plusplayer;
+using namespace esplusplayer;
 
 TEST(MiscTest, DISABLED_BoostScopeExit) {
   std::string input;
old mode 100755 (executable)
new mode 100644 (file)
index b61156c..d96980a
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2018] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "gtest/gtest.h"
 #include "gmock/gmock.h"
old mode 100755 (executable)
new mode 100644 (file)
index 12f76ce..1026cca
@@ -1,6 +1,18 @@
-//
-// @ Copyright [2017] <S/W Platform, Visual Display, Samsung Electronics>
-//
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include "gst/gst.h"
 #include "gtest/gtest.h"
@@ -21,7 +33,7 @@
 #include "trackrenderer_capi/trackrenderer_capi.h"
 #include "ut/include/appwindow.h"
 
-using namespace plusplayer;
+using namespace esplusplayer;
 
 class TrackRendererAdapterTest : public ::testing::Test {
  public:
@@ -127,8 +139,8 @@ TEST_F(TrackRendererAdapterTest, DISABLED_SetTrack) {
   auto output_vector =
       trackrenderer::capi_utils::MakeTrack(trackrenderer_tracks, size);
 
-  plusplayer::track_util::ShowTrackInfo(input_vector);
-  plusplayer::trackrenderer::track_util::ShowTrackInfo(output_vector);
+  esplusplayer::track_util::ShowTrackInfo(input_vector);
+  esplusplayer::trackrenderer::track_util::ShowTrackInfo(output_vector);
 
   index = 0;
   for (const auto& input : input_vector) {
@@ -215,7 +227,7 @@ TEST_F(TrackRendererAdapterTest, DISABLED_Deactivate) {
   // TrackType input = TrackType::kTrackTypeVideo;
   // TrackRendererTrackType type =
   // adapter_utils::ConvertToTrackRendererTrackType(input); TrackType output =
-  // plusplayer::trackrenderer::capi_utils::ConvertToTrackType(type); ASSERT_EQ(input,
+  // esplusplayer::trackrenderer::capi_utils::ConvertToTrackType(type); ASSERT_EQ(input,
   // output); ASSERT_TRUE(adapter->Deactivate(input));
 }
 
diff --git a/ut/src/utils/utility.cpp b/ut/src/utils/utility.cpp
new file mode 100644 (file)
index 0000000..518f74f
--- /dev/null
@@ -0,0 +1,586 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Ecore.h>
+#include <Elementary.h>
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <cassert>
+#include <chrono>
+#include <memory>
+
+#include <unistd.h>
+#include <poll.h>
+
+#include "ut/include/utils/utility.h"
+#include "ut/include/esplusplayer/eseventlistener.hpp"
+#include "ut/include/esplusplayer/esreader.hpp"
+
+#include <math.h>
+#include <fstream>
+#include <jconfig.h>
+#include <jpeglib.h>
+#ifdef TIZEN_FEATURE_PUBLIC
+#include <system_info.h>
+#else
+#include <capi-system-info/system_info.h>
+#include <capi-system-info/system_info_key.h>
+#include <system-type/system_type_enum.h>
+#include "ivideocapture.hpp"
+#include "capi-video-capture.h"
+#include "iaudio-control.hpp"
+#include "diagnosis-audio-control.hpp"
+#endif
+
+using namespace std;
+using namespace esplusplayer;
+//using namespace tc;
+using UserData = void*;
+
+namespace utils {
+using util_ptr = std::unique_ptr<Utility>;
+static util_ptr ptr = nullptr;
+
+Utility& Utility::Instance() {
+  if (ptr.get() == nullptr) ptr.reset(new Utility());
+  return *(ptr.get());
+}
+
+void Utility::Kill() { ptr.reset(); }
+
+void Utility::ThreadSleep(long ms) {
+  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
+}
+
+Utility::Utility() {
+  appwindow_.reset(new esplusplayer_ut::AppWindow(0, 0, 1920, 1080));
+#ifndef TIZEN_FEATURE_PUBLIC
+  audioControl = IAudioControl::getInstance();
+  audioDiagnoser = DiagnosisAudioControl::getInstance();
+#endif
+}
+
+Utility::~Utility() {}
+
+const char* Utility::GetCurrentTestName(void) {
+  return ::testing::UnitTest::GetInstance()->current_test_info()->name();
+}
+
+#ifndef IS_AUDIO_PRODUCT
+
+#if 0
+esplusplayer::PlusPlayer::Ptr Utility::GetOpenedMixPlusPlayer(std::string& uri,
+                                                            Mixer* mixer,
+                                                            Geometry& roi) {
+  auto player = esplusplayer::PlusPlayer::Create();
+  EXPECT_TRUE(player->Open(uri.c_str()));
+  EXPECT_TRUE(player->SetDisplay(DisplayType::kMixer, mixer));
+  EXPECT_TRUE(player->SetDisplayRoi(roi));
+  return player;
+}
+
+esplusplayer::PlusPlayer::Ptr Utility::GetPreparedMixPlusPlayer(std::string& uri,
+                                                              Mixer* mixer,
+                                                              Geometry& roi) {
+  auto player = this->GetOpenedMixPlusPlayer(uri, mixer, roi);
+  EXPECT_TRUE(player->Prepare());
+  return player;
+}
+
+esplusplayer::PlusPlayer::Ptr Utility::GetStartedMixPlusPlayer(std::string& uri,
+                                                             Mixer* mixer,
+                                                             Geometry& roi) {
+  auto player = this->GetPreparedMixPlusPlayer(uri, mixer, roi);
+  EXPECT_TRUE(player->Start());
+  return player;
+}
+#endif
+
+esplusplayer_handle Utility::GetOpenedMixESPP(mixer_handle mixer,
+                                              Geometry& roi) {
+  esplusplayer_handle player = esplusplayer_create();
+  EXPECT_EQ(esplusplayer_open(player), ESPLUSPLAYER_ERROR_TYPE_NONE);
+  EXPECT_EQ(
+      esplusplayer_set_display(player, ESPLUSPLAYER_DISPLAY_TYPE_MIXER, mixer),
+      ESPLUSPLAYER_ERROR_TYPE_NONE);
+  EXPECT_EQ(esplusplayer_set_display_roi(player, roi.x, roi.y, roi.w, roi.h),
+            ESPLUSPLAYER_ERROR_TYPE_NONE);
+  return player;
+}
+
+esplusplayer_handle Utility::GetPreparedMixESPP(std::string& uri,
+                                                mixer_handle mixer,
+                                                Geometry& roi) {
+  esplusplayer_handle player = this->GetOpenedMixESPP(mixer, roi);
+
+  if (!PrepareESPP(player, uri)) return nullptr;
+  return player;
+}
+
+esplusplayer_handle Utility::GetStartedMixESPP(std::string& uri,
+                                               mixer_handle mixer,
+                                               Geometry& roi) {
+  esplusplayer_handle player = this->GetPreparedMixESPP(uri, mixer, roi);
+
+  if (esplusplayer_start(player) == ESPLUSPLAYER_ERROR_TYPE_NONE)
+    return player;
+  else
+    printf("esplusplayer_start failed\n");
+  return nullptr;
+}
+#endif
+
+esplusplayer_handle Utility::GetOpenedESPP(Geometry& roi) {
+  esplusplayer_handle player = esplusplayer_create();
+  EXPECT_EQ(esplusplayer_open(player), ESPLUSPLAYER_ERROR_TYPE_NONE);
+  EXPECT_EQ(esplusplayer_set_display(player, ESPLUSPLAYER_DISPLAY_TYPE_OVERLAY,
+                                     this->GetWindow()),
+            ESPLUSPLAYER_ERROR_TYPE_NONE);
+  EXPECT_EQ(
+      esplusplayer_set_display_mode(player, ESPLUSPLAYER_DISPLAY_MODE_DST_ROI),
+      ESPLUSPLAYER_ERROR_TYPE_NONE);
+  EXPECT_EQ(esplusplayer_set_display_roi(player, roi.x, roi.y, roi.w, roi.h),
+            ESPLUSPLAYER_ERROR_TYPE_NONE);
+  return player;
+}
+
+esplusplayer_handle Utility::GetPreparedESPP(std::string& uri, Geometry& roi) {
+  esplusplayer_handle player = this->GetOpenedESPP(roi);
+
+  if (!PrepareESPP(player, uri)) return nullptr;
+  return player;
+}
+
+esplusplayer_handle Utility::GetStartedESPP(std::string& uri, Geometry& roi) {
+  esplusplayer_handle player = this->GetPreparedESPP(uri, roi);
+
+  if (esplusplayer_start(player) == ESPLUSPLAYER_ERROR_TYPE_NONE)
+    return player;
+  else
+    printf("esplusplayer_start failed\n");
+  return nullptr;
+}
+
+bool Utility::PrepareESPP(esplusplayer_handle player, std::string& uri,
+                          EsType type) {
+  if (!player) return false;
+
+  EsStreamReader* video_reader = nullptr;
+  EsStreamReader* audio_reader = nullptr;
+
+  if (static_cast<int>(type) & EsType::kVideo) {
+    video_reader =
+        new EsStreamReader(uri + "video_00/", ESPLUSPLAYER_STREAM_TYPE_VIDEO);
+    EXPECT_TRUE(video_reader->SetStreamInfo(player));
+  }
+  if (static_cast<int>(type) & EsType::kAudio) {
+    audio_reader =
+        new EsStreamReader(uri + "audio_00/", ESPLUSPLAYER_STREAM_TYPE_AUDIO);
+    EXPECT_TRUE(audio_reader->SetStreamInfo(player));
+  }
+  EsPlayerEventCallback* callback =
+      new EsPlayerEventCallback(player, video_reader, audio_reader);
+  callback->SetCallback();
+
+  bool ret = false;
+  if (esplusplayer_prepare_async(player) != ESPLUSPLAYER_ERROR_TYPE_NONE)
+    printf("esplusplayer_prepare_async failed\n");
+  else
+    ret = callback->WaitForPrepareDone();
+
+  delete callback;
+  if (video_reader != nullptr) delete video_reader;
+  if (audio_reader != nullptr) delete audio_reader;
+  printf("PrepareESPP done\n");
+  return ret;
+}
+
+void Utility::FeedingEsPacket(esplusplayer_handle player,
+                              const esplusplayer_stream_type type,
+                              const std::string& uri) {
+  EsStreamReader* reader;
+  auto feeding_task_fn = [this, &player, &reader]() {
+    esplusplayer_es_packet pkt;
+    while (true) {
+      memset(&pkt, 0, sizeof(esplusplayer_es_packet));
+      if (!reader->ReadNextPacket(pkt)) break;
+      esplusplayer_submit_packet(player, &pkt);
+      delete []pkt.buffer;
+    }
+  };
+  if (type == ESPLUSPLAYER_STREAM_TYPE_VIDEO) {
+    reader =
+        new EsStreamReader(uri + "video_00/", ESPLUSPLAYER_STREAM_TYPE_VIDEO);
+  } else {
+    reader =
+        new EsStreamReader(uri + "audio_00/", ESPLUSPLAYER_STREAM_TYPE_AUDIO);
+  }
+  auto feeding_task = std::thread(feeding_task_fn);
+  if (feeding_task.joinable()) feeding_task.join();
+}
+
+void Utility::DestroyESPP(esplusplayer_handle player) {
+  if (!player) return;
+  int ret = esplusplayer_destroy(player);
+  assert(ret == ESPLUSPLAYER_ERROR_TYPE_NONE);
+  player = nullptr;
+}
+
+evas_h Utility::GetWindow() const { return appwindow_->GetWindow().obj; }
+
+unsigned int Gcd(unsigned int u, unsigned int v) {
+  int shift = 0;
+
+  /* GCD(0,v) == v; GCD(u,0) == u, GCD(0,0) == 0 */
+
+  if (u == 0) {
+    return v;
+  }
+  if (v == 0) {
+    return u;
+  }
+
+  /* Let shift := lg K, where K is the greatest power of 2
+    dividing both u and v. */
+  for (shift = 0; ((u | v) & 1) == 0; ++shift) {
+    u >>= 1;
+    v >>= 1;
+  }
+
+  while ((u & 1) == 0) {
+    u >>= 1;
+  }
+
+  /* From here on, u is always odd. */
+  do {
+    /* remove all factors of 2 in v -- they are not common */
+    /*  note: v is not zero, so while will terminate */
+    while ((v & 1) == 0) {
+      v >>= 1;
+      /* Loop X */
+    }
+    /* Now u and v are both odd. Swap if necessary so u <= v,
+     then set v = v - u (which is even). For bignums, the
+     swapping is just pointer movement, and the subtraction
+     can be done in-place. */
+    if (u > v) {
+      unsigned int t = v;
+      v = u;
+      u = t;
+    }           // Swap u and v.
+    v = v - u;  // Here v >= u.
+  } while (v != 0);
+
+  /* restore common factors of 2 */
+  return u << shift;
+}
+
+#ifndef TIZEN_FEATURE_PUBLIC
+void ResizeCopy(unsigned int m_width, unsigned int m_height,
+                unsigned int m_rwidth, unsigned int m_rheight,
+                char* c_ptr, char* y_ptr, unsigned char* dest,
+                unsigned int color_format) {
+  unsigned int omit = 1;
+  unsigned int x = 0;
+  unsigned int y = 0;
+  unsigned char resize = 1;
+
+  if (m_width == m_rwidth) {
+    resize = 0;
+  } else {
+    omit = Gcd(m_width, m_rwidth);
+    omit = m_width / omit;
+  }
+  printf("m_width %u, m_rwidth %u, omit %u\n", m_width, m_rwidth, omit);
+
+  // long int inc = 3 * m_rwidth * m_rheight;
+  long int inc = 0;
+
+  for (y = 0; y < m_height; y++) {
+    if ((y + 1) % omit || !resize) {
+      for (x = 0; x < m_width; x += sizeof(unsigned int)) {
+
+        unsigned int Yplain =
+            *((unsigned int*)((void*)(y_ptr + y * m_width + x)));
+        unsigned int Cplain =
+            *((unsigned int*)((void*)(c_ptr + y * m_width + x)));
+
+        switch (color_format) {
+          case SECVIDEO_CAPTURE_COLOR_YUV444:  // 444
+            break;
+          case SECVIDEO_CAPTURE_COLOR_YUV422:  // 422
+            Cplain = *((unsigned int*)((void*)(c_ptr + y * m_width + x)));
+            break;
+          case SECVIDEO_CAPTURE_COLOR_YUV420:  // 420
+            Cplain = *((unsigned int*)((void*)(c_ptr + (y / 2) * m_width + x)));
+            break;
+          default:
+            break;
+        }
+        if ((x + 4) % omit || !resize) {
+          dest[inc++] = (Yplain) & 0xFF;
+          dest[inc++] = Cplain & 0xFF;
+          dest[inc++] = (Cplain >> 8) & 0xFF;
+        }
+        if ((x + 3) % omit || !resize) {
+          dest[inc++] = (Yplain >> 8) & 0xFF;
+          dest[inc++] = (Cplain) & 0xFF;
+          dest[inc++] = (Cplain >> 8) & 0xFF;
+        }
+
+        if ((x + 2) % omit || !resize) {
+          dest[inc++] = (Yplain >> 16) & 0xFF;
+          dest[inc++] = (Cplain >> 16) & 0xFF;
+          dest[inc++] = (Cplain >> 24) & 0xFF;
+        }
+
+        if ((x + 1) % omit || !resize) {
+          dest[inc++] = (Yplain >> 24) & 0xFF;
+          dest[inc++] = (Cplain >> 16) & 0xFF;
+          dest[inc++] = (Cplain >> 24) & 0xFF;
+        }
+      }
+    }
+  }
+}
+
+int Utility::CaptureYUV(int capture_width, int capture_height,
+                        char* ybuff, char* cbuff, int ysize,
+                        int csize, std::string result_file_path) {
+  // screen capture
+  IVideoCapture* VCObjptr = IVideoCapture::getInstance();
+
+  IVideoCapture::InputParams input_params;
+
+  input_params.capture_w = capture_width;
+  input_params.capture_h = capture_height;
+
+  IVideoCapture::OutputParams output_params;
+  output_params.p_y_addr = ybuff;
+  output_params.p_c_addr = cbuff;
+  output_params.size_y = ysize;
+  output_params.size_c = csize;
+
+  sleep(1);
+
+  VCObjptr->getVideoPostYUV(input_params, output_params);
+
+  // write
+  FILE* fexpect = NULL;
+
+  while (output_params.p_y_addr) {
+    fexpect = fopen(result_file_path.c_str(), "wb");
+    if (fexpect == NULL) {
+      LOGE("can't open the file");
+      break;
+    }
+    fwrite(output_params.p_y_addr, 1, ysize, fexpect);
+    fclose(fexpect);
+    fexpect = NULL;
+    output_params.p_y_addr = NULL;
+  }
+
+  return 0;
+}
+///TODO:: Modify the API to return the pointer instead of writing it as an image file.
+int Utility::CaptureJPG(const int capture_width, const int capture_height,
+                        char* ybuff, char* cbuff, const int ysize,
+                        const int csize, std::string img_file_path) {
+  IVideoCapture* VCObjptr = IVideoCapture::getInstance();
+  int output_color_format = 0;
+
+  IVideoCapture::InputParams input_params;
+  input_params.capture_w = capture_width;
+  input_params.capture_h = capture_height;
+
+  IVideoCapture::OutputParams output_params;
+  output_params.p_y_addr = ybuff;
+  output_params.p_c_addr = cbuff;
+  output_params.size_y = ysize;
+  output_params.size_c = csize;
+
+  sleep(1);
+
+  VCObjptr->getVideoPostYUV(input_params, output_params);
+  output_color_format = static_cast<int>(output_params.color_format);
+
+  sleep(1);
+
+  unsigned char* rawImage;
+  rawImage = (unsigned char*)malloc(sizeof(unsigned char) * 3 * capture_width *
+                                    capture_height);
+
+  ResizeCopy(capture_width, capture_height, capture_width, capture_height,
+             cbuff, ybuff, rawImage, output_color_format);
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  FILE* outfile = NULL; /* target file */
+
+  JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
+  int row_stride;          /* physical row width in image buffer */
+
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_compress(&cinfo);
+
+  outfile = fopen(img_file_path.c_str(), "wb");
+  if (outfile == NULL) {
+    LOGE("can't open the file");
+    if (rawImage != NULL) free(rawImage);
+    return -1;
+  }
+  jpeg_stdio_dest(&cinfo, outfile);
+
+  cinfo.image_width = capture_width;
+  cinfo.image_height = capture_height;
+  cinfo.input_components = 3; /* # of color components per pixel */
+  cinfo.in_color_space = JCS_YCbCr;
+  jpeg_set_defaults(&cinfo);
+  jpeg_set_quality(&cinfo, 70, TRUE);
+  jpeg_start_compress(&cinfo, TRUE);
+
+  row_stride = capture_width * 3; /* JSAMPLEs per row in image_buffer */
+
+  while (cinfo.next_scanline < cinfo.image_height) {
+    row_pointer[0] = &((rawImage)[cinfo.next_scanline * row_stride]);
+    (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
+  }
+
+  jpeg_finish_compress(&cinfo);
+  jpeg_destroy_compress(&cinfo);
+  if (rawImage != NULL) free(rawImage);
+
+  if (outfile == NULL) {
+    LOGE("Fail to open file");
+    return -1;
+  } else {
+    fclose(outfile);
+  }
+  return 0;
+}
+
+int Utility::CheckYUV(int x, int y) {
+
+  /* screen capture */
+  IVideoCapture* VCObjptr = IVideoCapture::getInstance();
+
+  int CAPTURE_WIDTH = 640;
+  int CAPTURE_HEIGHT = 360;
+  int CAPTURE_BUF_SIZE = CAPTURE_WIDTH * CAPTURE_HEIGHT;
+  char ybuff[CAPTURE_BUF_SIZE] = {0};
+  char cbuff[CAPTURE_BUF_SIZE] = {0};
+
+  IVideoCapture::InputParams input_params;
+  input_params.capture_w = 640;
+  input_params.capture_h = 360;
+
+  IVideoCapture::OutputParams output_params;
+  output_params.p_y_addr = ybuff;
+  output_params.p_c_addr = cbuff;
+  output_params.size_y = CAPTURE_BUF_SIZE;
+  output_params.size_c = CAPTURE_BUF_SIZE;
+
+  sleep(1);
+
+  VCObjptr->getVideoPostYUV(input_params, output_params);
+
+  /* check YUV value. As the capture size (640 x 360) is mapped with the full screen (1920 x 1080), the position should be resized. */
+  int new_X = x / 3;
+  int new_Y = y / 3;
+  int position = CAPTURE_WIDTH * (new_Y - 1) + new_X;
+
+  LOGE("Y value : %d", (int)ybuff[position]);
+  return (int)ybuff[position];
+}
+#endif
+
+#ifndef TIZEN_FEATURE_PUBLIC
+bool Utility::IsAudioDisconnected() {
+  TZTVAudioSource src = AUDIO_SOURCE_MAX;
+  EXPECT_EQ(audioControl->getMainOutSourceSelect(&src), 0);
+  return (src != AUDIO_MULTIMEDIA_DEC0);
+}
+bool Utility::IsAudioMute() {
+  long audioMute = 0;
+  EXPECT_EQ(audioDiagnoser->Diagnosis_GetBoolean(0, "main out mute", &audioMute), 0);
+  return (audioMute != 0);
+}
+#endif
+
+int Utility::GetPlayingTimeForManualTestInMsec() {
+  // If you want to adjust the playingTime for the TC which use this method,
+  // sh-3.2# touch /tmp/espp_playing_time
+  // sh-3.2# echo 2000 > /tmp/espp_playing_time
+  static int playingTime = -1;
+  std::fstream myfile("/tmp/espp_playing_time", std::ios_base::in);
+  if (myfile) {
+    myfile >> playingTime;
+    return playingTime;
+  }
+  return 100;  // default 100 msec
+}
+
+#define FMS_KEY_CHIPNAME "com.samsung/featureconf/product.chipset"
+bool Utility::IsChipset(const char* name) {
+  char* chipset = NULL;
+
+  system_info_get_custom_string(FMS_KEY_CHIPNAME, &chipset);
+  if (!chipset) return false;
+
+  char* substr = strstr(chipset, name);
+  bool ret = (substr ? true : false);
+  free(chipset);
+  return ret;
+}
+
+std::string Utility::getKeyboardInput(int timeoutMsec) {
+  struct pollfd pfd = { STDIN_FILENO, POLLIN, 0 };
+  std::string line = "";
+  int ret = poll(&pfd, 1, timeoutMsec);
+  if(ret == 1) {// there is something to read
+    std::getline(std::cin, line);
+  }
+  return line;
+}
+std::string Utility::Execute(std::string cmd) {
+  char buffer[128];
+  std::string result = "";
+  FILE* pipe = popen(cmd.c_str(), "r");
+  assert(pipe != nullptr);
+  while (fgets(buffer, sizeof(buffer), pipe) != NULL) {
+    result += buffer;
+  }
+  pclose(pipe);
+  return result;
+}
+
+vector<string> Utility::Split(string in, char delimiter) {
+  vector<string> result;
+  stringstream ss(in);
+  string line;
+  while (getline(ss, line)) {
+    stringstream liness(line);
+    string token;
+    while(getline(liness, token, delimiter)) {
+      if (!token.empty()) {
+        result.push_back(token);
+      }
+    }
+  }
+  return result;
+}
+
+}  // namespace utils