Merge branch 'tizen_line_coverage' into tizen 93/228993/1
authorJeongmo Yang <jm80.yang@samsung.com>
Fri, 27 Mar 2020 03:19:09 +0000 (12:19 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Fri, 27 Mar 2020 03:22:47 +0000 (12:22 +0900)
Change-Id: I8c1650e5c788fce1860d6101affa159d634f51ab
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
15 files changed:
CMakeLists.txt [changed mode: 0755->0644]
doc/media_codec_doc.h
include/media_codec.h [changed mode: 0755->0644]
include/media_codec_ini.h
include/media_codec_port.h [changed mode: 0755->0644]
include/media_codec_port_gst.h [changed mode: 0755->0644]
include/media_codec_private.h
include/media_codec_sync_internal.h [new file with mode: 0644]
include/media_codec_sync_private.h [new file with mode: 0644]
packaging/capi-media-codec.spec [changed mode: 0755->0644]
src/media_codec.c
src/media_codec_ini.c
src/media_codec_port.c [changed mode: 0755->0644]
src/media_codec_port_gst.c [changed mode: 0755->0644]
src/media_codec_sync_internal.c [new file with mode: 0644]

old mode 100755 (executable)
new mode 100644 (file)
index 217ee07..f2b7204
@@ -10,8 +10,11 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(INC_DIR include)
 INCLUDE_DIRECTORIES(${INC_DIR})
 
-SET(dependents "dlog glib-2.0 mm-common libtbm capi-media-tool iniparser gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 capi-system-info mm-resource-manager gstreamer-allocators-1.0" )
-SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 mm-resource-manager gstreamer-allocators-1.0" )
+SET(dependents "dlog glib-2.0 mm-common libtbm capi-media-tool iniparser gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 capi-system-info gstreamer-allocators-1.0")
+SET(pc_dependents "capi-base-common capi-media-tool")
+IF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
+SET(dependents "${dependents} mm-resource-manager")
+ENDIF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${dependents})
@@ -28,6 +31,9 @@ ENDIF("${ARCH}" STREQUAL "arm")
 
 ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
 ADD_DEFINITIONS("-DTIZEN_DEBUG")
+IF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
+ADD_DEFINITIONS("-DUSE_MM_RESOURCE_MANAGER")
+ENDIF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}")
 
index 1c41347..365e30b 100755 (executable)
@@ -43,7 +43,7 @@
  *
  * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n
  *
- * More details on featuring your application can be found from <a href="https://developer.tizen.org/development/tizen-studio/native-tools/configuring-your-app/manifest-text-editor#feature"><b>Feature Element</b>.</a>
+ * More details on featuring your application can be found from <a href="https://docs.tizen.org/application/tizen-studio/native-tools/manifest-text-editor#feature-element"><b>Feature Element</b>.</a>
  *
  * MEDIA CODEC API allows :
  * The API allows you to direct access to the media codec on device. It operates on "raw" data, so any file headers
old mode 100755 (executable)
new mode 100644 (file)
index 5626215..fd6da1e
@@ -157,8 +157,8 @@ typedef void (*mediacodec_input_buffer_used_cb)(media_packet_h packet, void *use
 typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h packet, void *user_data);
 
 /**
- * @brief Called when the error has occured.
- * @details It will be invoked when the error has occured.
+ * @brief Called when the error has occurred.
+ * @details It will be invoked when the error has occurred.
  *          Following error codes can be delivered.
  *          #MEDIACODEC_ERROR_INTERNAL,
  *          #MEDIACODEC_ERROR_INVALID_STREAM,
@@ -167,7 +167,7 @@ typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h packet, voi
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @param[in] error The error code
  * @param[in] user_data  The user data passed from the callback registration function
- * @pre It will be invoked when the error has occured if you register this callback using mediacodec_set_error_cb().
+ * @pre It will be invoked when the error has occurred if you register this callback using mediacodec_set_error_cb().
  * @see mediacodec_set_error_cb()
  * @see mediacodec_unset_error_cb()
  */
index ba0704f..ee05257 100644 (file)
@@ -28,6 +28,7 @@ extern "C" {
 
 #define MEDIA_CODEC_INI_DEFAULT_PATH   SYSCONFDIR"/multimedia/mmfw_media_codec.ini"
 #define MEDIA_CODEC_INI_MAX_STRLEN     256
+#define MEDIA_CODEC_INI_CNAME_LEN      16
 #define DEFAULT_PORT "GST_PORT"
 #define MEDIA_CODEC_MAX_CODEC_TYPE 100
 #define MEDIA_CODEC_MAX_CODEC_ROLE 4
@@ -42,7 +43,7 @@ typedef struct _codec_t codec_t;
 typedef struct _mc_ini_t mc_ini_t;
 
 struct _codec_list_t {
-       gchar cname[MEDIA_CODEC_INI_MAX_STRLEN];
+       gchar cname[MEDIA_CODEC_INI_CNAME_LEN];
        mediacodec_codec_type_e ctype;
 };
 
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 18010d4..f3fe9a5
 #define __TIZEN_MEDIA_CODEC_PORT_GST_H__
 
 #include <unistd.h>
-#include <tizen.h>
 #include <media_codec.h>
 #include <media_codec_private.h>
 #include <media_codec_port.h>
 #include <media_codec_bitstream.h>
 
-#include <tbm_type.h>
 #include <tbm_surface.h>
-#include <tbm_bufmgr.h>
 #include <tbm_surface_internal.h>
 #include <gst/video/video-format.h>
 #include <gst/allocators/gsttizenmemory.h>
@@ -39,14 +36,6 @@ extern "C" {
 #define GST_INIT_STRUCTURE(param) \
        memset(&(param), 0, sizeof(param));
 
-#define MEDIACODEC_ELEMENT_SET_STATE(x_element, x_state)                                          \
-       do {                                                                                            \
-               LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME(x_element)); \
-               if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(x_element, x_state)) {                    \
-                       LOGE("failed to set state %s to %s\n", #x_state, GST_ELEMENT_NAME(x_element));        \
-                       goto STATE_CHANGE_FAILED;                                                               \
-               }                                                                                           \
-       } while (0)
 
 #define SCMN_IMGB_MAX_PLANE 4
 #define TBM_API_CHANGE
@@ -168,30 +157,11 @@ struct _GstMCBuffer {
 };
 
 enum { fill_inbuf, fill_outbuf };
-
-int __mc_fill_input_buffer(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
-int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
-
-int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
-int __mc_fill_input_buffer_with_adec_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
-int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
-
-int __mc_fill_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
-int __mc_fill_aenc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
-int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
-int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
-
-mc_gst_core_t *mc_gst_core_new();
-void mc_gst_core_free(mc_gst_core_t *core);
-
-mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core);
-void mc_gst_port_free(mc_gst_port_t *port);
-
 mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle);
 mc_ret_e mc_gst_unprepare(mc_handle_t *mc_handle);
 
-mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeOutUs);
-mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeOutUs);
+mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeout_us);
+mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeout_us);
 
 mc_ret_e mc_gst_flush_buffers(mc_handle_t *mc_handle);
 
index c574563..bc196ec 100644 (file)
@@ -24,7 +24,9 @@
 #include <media_codec.h>
 
 #include <mm_types.h>
+#ifdef USE_MM_RESOURCE_MANAGER
 #include <mm_resource_manager.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,8 +39,7 @@ extern "C" {
 
 
 #define MEDIACODEC_CHECK_CONDITION(condition, error, msg)     \
-       if (condition) {} else \
-       {LOGE("[%s] %s(0x%08x)", __FUNCTION__, msg, error); return error; }; \
+       if (!(condition)) {LOGE("%s(0x%08x)", msg, error); return error; }
 
 #define MEDIACODEC_INSTANCE_CHECK(mediacodec)   \
        MEDIACODEC_CHECK_CONDITION(mediacodec != NULL, MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER")
@@ -102,7 +103,9 @@ typedef struct _mediacodec_s {
        int state;
        bool is_omx;
        char *m_mime;
+#ifdef USE_MM_RESOURCE_MANAGER
        mm_resource_manager_res_h codec_resource;
+#endif
 
        mediacodec_input_buffer_used_cb empty_buffer_cb;
        void* empty_buffer_cb_userdata;
diff --git a/include/media_codec_sync_internal.h b/include/media_codec_sync_internal.h
new file mode 100644 (file)
index 0000000..c193bb0
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2019 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 __TIZEN_MEDIA_CODEC_SYNC_INTERNAL_H__
+#define __TIZEN_MEDIA_CODEC_SYNC_INTERNAL_H__
+
+#include <media_codec.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @file media_codec_sync_internal.h
+* @brief This file contains the internal capi media codec sync API.
+*/
+
+/**
+* @addtogroup CAPI_MEDIA_CODEC_SYNC_MODULE
+* @{
+*/
+
+/**
+ * @brief Media Codec Sync type handle.
+ * @since_tizen 5.5
+ */
+typedef struct mediacodecsync_s *mediacodecsync_h;
+
+
+typedef enum {
+       MEDIACODECSYNC_STATE_CREATED = 0,   /**< Media codec sync is created */
+       MEDIACODECSYNC_STATE_READY,         /**< Media codec sync is ready to run */
+       MEDIACODECSYNC_STATE_RUNNING,       /**< Media codec sync is running */
+       MEDIACODECSYNC_STATE_PAUSED         /**< Media codec sync is paused */
+} mediacodecsync_state_e;
+
+typedef enum {
+       MEDIACODECSYNC_PACKET_TYPE_AUDIO = 0,
+       MEDIACODECSYNC_PACKET_TYPE_VIDEO
+} mediacodecsync_packet_type_e;
+
+typedef void (*mediacodecsync_buffer_used_cb)(media_packet_h packet, mediacodecsync_packet_type_e type, void *user_data);
+
+/**
+ * @brief Creates a mediacodecsync handle for synchronous AV rendering.
+ * @since_tizen 5.5
+ * @remarks you must release @a mediacodecsync using mediacodecsync_destroy().\n
+ *          Although you can create multiple mediacodecsync handles at the same time,
+ *          the mediacodec cannot guarantee proper operation because of limited resources, like
+ *          audio or display device.
+ *
+ * @param[in] callback   The callback function to register
+ * @param[in] user_data  The user data to be passed to the callback function
+ * @param[out] mediacodecsync  A new handle to mediacodecsync
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @post   If it succeeds, the state will be #MEDIACODECSYNC_STATE_CREATED.
+ */
+int mediacodecsync_create(mediacodecsync_buffer_used_cb callback, void *userdata, mediacodecsync_h *mediacodecsync);
+
+/**
+ * @brief Destroys the mediacodecsync handle and releases all its resources.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync to be destroyed.
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The state should be #MEDIACODECSYNC_STATE_CREATED.
+ */
+int mediacodecsync_destroy(mediacodecsync_h mediacodecsync);
+
+/**
+ * @brief Sets the media format to be rendered.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The mediacodecsync handle
+ * @param[in] audio_format   The #media_format_h of audio data
+ * @param[in] video_format   The #media_format_h of video data
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device
+ * @pre The state should be #MEDIACODECSYNC_STATE_CREATED.
+ * @pre The media format has been created and the required values have been set.
+ * @see media_format_set_video_mime()
+ * @see media_format_set_audio_mime()
+ * @see media_format_set_video_width()
+ * @see media_format_set_video_height()
+ * @see media_format_set_video_avg_bps()
+ * @see media_format_set_video_frame_rate()
+ * @see media_format_set_audio_channel()
+ * @see media_format_set_audio_samplerate()
+ * @see media_format_set_audio_bit()
+ * @see media_format_set_audio_avg_bps()
+ */
+int mediacodecsync_set_format(mediacodecsync_h mediacodecsync, media_format_h audio_format, media_format_h video_format);
+
+/**
+ * @brief Prepares @a mediacodecsync for synchronous rendering.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #MEDIACODEC_ERROR_RESOURCE_OVERLOADED Exceed the instance limits
+ * @retval #MEDIACODEC_ERROR_INTERNAL Internal error
+ * @pre The mediacodecsync should call mediacodecsync_set_format() before calling mediacodec_prepare().
+ * @pre The state should be #MEDIACODECSYNC_STATE_CREATED.
+ * @post   If it succeeds, the state will be #MEDIACODECSYNC_STATE_READY.
+ */
+int mediacodecsync_prepare(mediacodecsync_h mediacodecsync);
+
+/**
+ * @brief Unprepares @a mediacodecsync.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The state should be #MEDIACODECSYNC_STATE_READY.
+ * @post   If it succeeds, the state will be #MEDIACODECSYNC_STATE_CREATED.
+ */
+int mediacodecsync_unprepare(mediacodecsync_h mediacodecsync);
+
+/**
+ * @brief Runs @a mediacodecsync.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The state should be #MEDIACODECSYNC_STATE_READY or #MEDIACODECSYNC_STATE_PAUSED.
+ * @post   If it succeeds, the state will be #MEDIACODECSYNC_STATE_RUNNING.
+ */
+int mediacodecsync_run(mediacodecsync_h mediacodecsync);
+
+/**
+ * @brief Stops @a mediacodecsync.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The state should be #MEDIACODECSYNC_STATE_RUN or #MEDIACODECSYNC_STATE_PAUSED.
+ * @post   If it succeeds, the state will be #MEDIACODECSYNC_STATE_READY.
+ */
+int mediacodecsync_stop(mediacodecsync_h mediacodecsync);
+
+/**
+ * @brief Pauses @a mediacodecsync.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The state should be #MEDIACODECSYNC_STATE_RUN.
+ * @post   If it succeeds, the state will be #MEDIACODECSYNC_STATE_PAUSED.
+ */
+int mediacodecsync_pause(mediacodecsync_h mediacodecsync);
+
+/**
+ * @brief Pushes packets to render.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync
+ * @param[in] packet The packet to render
+ * @param[in] type The type of packet
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The state should be #MEDIACODECSYNC_STATE_RUN.
+ */
+int mediacodecsync_push_packet(mediacodecsync_h mediacodecsync, media_packet_h packet, mediacodecsync_packet_type_e type);
+
+/**
+ * @brief Gets state of @a mediacodecsync.
+ * @since_tizen 5.5
+ * @param[in] mediacodecsync The handle to mediacodecsync
+ * @param[out] state The state of mediacodecsync
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIACODEC_ERROR_NONE Successful
+ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation
+ */
+int mediacodecsync_get_state(mediacodecsync_h mediacodecsync, mediacodecsync_state_e *state);
+
+/**
+ * @}
+ */
+#ifdef __cplusplus
+}
+#endif
+#endif /*__TIZEN_MEDIA_CODEC_INTERNAL_H__*/
diff --git a/include/media_codec_sync_private.h b/include/media_codec_sync_private.h
new file mode 100644 (file)
index 0000000..2f6fa53
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019 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 __TIZEN_MEDIA_CODEC_SYNC_PRIVATE_H__
+#define __TIZEN_MEDIA_CODEC_SYNC_PRIVATE_H__
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gst/gst.h>
+#include <gst/allocators/gsttizenmemory.h>
+#include <gst/app/gstappsrc.h>
+#include <media_codec_private.h>
+#include <media_codec_sync_internal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+       MEDIACODECSYNC_PIPELINE = 0,
+       MEDIACODECSYNC_ELEMENT_APPSRC,
+       MEDIACODECSYNC_ELEMENT_CAPS,
+       MEDIACODECSYNC_ELEMENT_QUE,
+       MEDIACODECSYNC_ELEMENT_SINK,
+       MEDIACODECSYNC_ELEMENT_NUM
+};
+
+#define AUDIO_FORMAT_TABLE_SIZE 15
+#define VIDEO_FORMAT_TABLE_SIZE 8
+
+typedef struct _format_table {
+       media_format_mimetype_e mime_type;
+       char *format_string;
+} format_table;
+
+typedef struct _packet_info {
+       bool has_tbm_surface;
+       void *data;
+       uint64_t data_size;
+       uint64_t dts;
+       uint64_t pts;
+       uint64_t duration;
+} packet_info;
+
+typedef struct _mediacodecsync_s {
+       GMutex lock;
+       media_format_h audio_format;
+       media_format_h video_format;
+
+       GstAllocator *allocator;
+       GstClock *clock;
+       GstElement *audio_pipe[MEDIACODECSYNC_ELEMENT_NUM];
+       GstElement *video_pipe[MEDIACODECSYNC_ELEMENT_NUM];
+       GstCaps *video_caps;
+       GstVideoInfo video_info;
+
+       mediacodecsync_buffer_used_cb buffer_used_cb;
+       void *buffer_used_cb_userdata;
+
+       mediacodecsync_state_e state;
+} mediacodecsync_s;
+
+typedef struct _GstMCSBuffer {
+       GstBuffer *gst_buffer;
+       int type;
+       mediacodecsync_s *handle;
+       media_packet_h packet;
+} GstMCSBuffer;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_MEDIA_CODEC_SYNC_PRIVATE_H__ */
old mode 100755 (executable)
new mode 100644 (file)
index f74b8b7..ebb1f6f
@@ -4,7 +4,7 @@
 
 Name:       capi-media-codec
 Summary:    A Media Codec library in Tizen Native API
-Version:    0.6.0
+Version:    0.6.10
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -21,7 +21,9 @@ BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
 BuildRequires:  pkgconfig(gstreamer-app-1.0)
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(iniparser)
+%if "%{tizen_profile_name}" != "tv"
 BuildRequires:  pkgconfig(mm-resource-manager)
+%endif
 #BuildRequires:  pkgconfig(capi-media-camera)
 #BuildRequires:  pkgconfig(capi-mediademuxer)
 #BuildRequires:  pkgconfig(capi-mediamuxer)
@@ -39,6 +41,15 @@ Requires: %{name} = %{version}-%{release}
 
 %description devel
 
+%if 0%{?gcov:1}
+%package gcov
+Summary: Line Coverage of Media Codec library in Tizen Native API
+Group: Development/Multimedia
+
+%description gcov
+Collection of files related to Line Coverage. It is tested as gcov for a media codec library in Tizen native API
+%endif
+
 %prep
 %setup -q
 
@@ -54,11 +65,20 @@ export LDFLAGS+=" -lgcov"
 %endif
 
 MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
-%cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
-
+%cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER} \
+%if "%{tizen_profile_name}" == "tv"
+  -DTIZEN_FEATURE_MM_RESOURCE_MANAGER=NO
+%else
+  -DTIZEN_FEATURE_MM_RESOURCE_MANAGER=YES
+%endif
 
 make %{?jobs:-j%jobs}
 
+%if 0%{?gcov:1}
+mkdir -p gcov-obj
+find . -name '*.gcno' -exec cp '{}' gcov-obj ';'
+%endif
+
 %install
 rm -rf %{buildroot}
 mkdir -p %{buildroot}/usr/bin
@@ -66,6 +86,12 @@ cp test/media_codec_test %{buildroot}/usr/bin
 
 %make_install
 
+%if 0%{?gcov:1}
+mkdir -p %{buildroot}%{_datadir}/gcov/obj
+install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj
+%endif
+
+
 %post
 /sbin/ldconfig
 
@@ -85,4 +111,8 @@ cp test/media_codec_test %{buildroot}/usr/bin
 %{_libdir}/pkgconfig/*.pc
 %{_libdir}/libcapi-media-codec.so
 
+%if 0%{?gcov:1}
+%files gcov
+%{_datadir}/gcov/obj/*
+%endif
 
index a78a76b..cff7fc1 100644 (file)
 
 #define MC_PREALLOCATED_HANDLE_ARRAY_SIZE 16
 
-static mm_resource_manager_h resource_manager;
-static GPtrArray *mediacodec_handles;
-static GMutex mediacodec_handles_lock;
+#ifdef USE_MM_RESOURCE_MANAGER
+static mm_resource_manager_h g_mc_resource_manager;
+static GPtrArray *g_mediacodec_handles;
+static GMutex g_mediacodec_lock;
+#endif
 
 static gboolean  __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data);
 static gboolean __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data);
@@ -36,10 +38,12 @@ static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data)
 static gboolean __mediacodec_eos_cb(void *user_data);
 static gboolean __mediacodec_supported_codec_cb(mediacodec_codec_type_e codec_type, void *user_data);
 static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data);
+#ifdef USE_MM_RESOURCE_MANAGER
 static void __mediacodec_init_lib() __attribute__((constructor));
 static void __mediacodec_deinit_lib() __attribute__((destructor));
 static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
                mm_resource_manager_res_h resource_h, void *user_data);
+#endif
 
 /*
  * Internal Implementation
@@ -131,8 +135,21 @@ int mediacodec_create(mediacodec_h *mediacodec)
 
        LOGD("mediacodec_create..");
 
-       if (resource_manager == NULL)
-               return MEDIACODEC_ERROR_INTERNAL;
+#ifdef USE_MM_RESOURCE_MANAGER
+       g_mutex_lock(&g_mediacodec_lock);
+
+       if (!g_mc_resource_manager) {
+               int mm_ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
+                       __mediacodec_resource_release_cb, NULL, &g_mc_resource_manager);
+               if (mm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+                       g_mutex_unlock(&g_mediacodec_lock);
+                       LOGE("mm_resource_manager_create failed 0x%x", mm_ret);
+                       return MEDIACODEC_ERROR_INTERNAL;
+               }
+       }
+
+       g_mutex_unlock(&g_mediacodec_lock);
+#endif
 
        handle = (mediacodec_s *)malloc(sizeof(mediacodec_s));
        if (handle != NULL) {
@@ -164,9 +181,11 @@ int mediacodec_create(mediacodec_h *mediacodec)
        mc_set_buffer_status_cb(handle->mc_handle, (mediacodec_buffer_status_cb)__mediacodec_buffer_status_cb, handle);
        mc_set_supported_codec_cb(handle->mc_handle, (mediacodec_supported_codec_cb)__mediacodec_supported_codec_cb, handle);
 
-       g_mutex_lock(&mediacodec_handles_lock);
-       g_ptr_array_insert(mediacodec_handles, -1, *mediacodec);
-       g_mutex_unlock(&mediacodec_handles_lock);
+#ifdef USE_MM_RESOURCE_MANAGER
+       g_mutex_lock(&g_mediacodec_lock);
+       g_ptr_array_insert(g_mediacodec_handles, -1, *mediacodec);
+       g_mutex_unlock(&g_mediacodec_lock);
+#endif
 
        return MEDIACODEC_ERROR_NONE;
 
@@ -183,9 +202,11 @@ int mediacodec_destroy(mediacodec_h mediacodec)
                LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION); //LCOV_EXCL_LINE
                return MEDIACODEC_ERROR_INVALID_OPERATION;
        } else {
-               g_mutex_lock(&mediacodec_handles_lock);
-               g_ptr_array_remove_fast(mediacodec_handles, mediacodec);
-               g_mutex_unlock(&mediacodec_handles_lock);
+#ifdef USE_MM_RESOURCE_MANAGER
+               g_mutex_lock(&g_mediacodec_lock);
+               g_ptr_array_remove_fast(g_mediacodec_handles, mediacodec);
+               g_mutex_unlock(&g_mediacodec_lock);
+#endif
 
                handle->state = MEDIACODEC_STATE_NONE;
                free(handle);
@@ -294,11 +315,14 @@ int mediacodec_prepare(mediacodec_h mediacodec)
 {
        MEDIACODEC_INSTANCE_CHECK(mediacodec);
        mediacodec_s *handle = (mediacodec_s *)mediacodec;
+#ifdef USE_MM_RESOURCE_MANAGER
        mc_handle_t *mc_handle = (mc_handle_t *) handle->mc_handle;
        int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
        mm_resource_manager_res_h resource;
+#endif
        MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
 
+#ifdef USE_MM_RESOURCE_MANAGER
        if (mc_handle->is_hw && mc_handle->is_video) {
 
                if (handle->codec_resource) {
@@ -321,14 +345,14 @@ int mediacodec_prepare(mediacodec_h mediacodec)
                 * Additional info can be found in doxygen comments of mm_resource_manager.h
                 */
 //LCOV_EXCL_START
-               rm_ret = mm_resource_manager_mark_for_acquire(resource_manager,
+               rm_ret = mm_resource_manager_mark_for_acquire(g_mc_resource_manager,
                                mc_handle->is_encoder ?
                                MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_ENCODER :
                                MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
                                1, &resource);
-               if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE)
-                       switch (rm_ret) {
+               if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
                        LOGE("Failed to acquire resource manager %x", rm_ret);
+                       switch (rm_ret) {
                        case MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED:
                                return MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE;
                        case MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH:
@@ -336,16 +360,18 @@ int mediacodec_prepare(mediacodec_h mediacodec)
                        default:
                                return MEDIACODEC_ERROR_INTERNAL;
                        }
+               }
 
-               rm_ret = mm_resource_manager_commit(resource_manager);
+               rm_ret = mm_resource_manager_commit(g_mc_resource_manager);
                if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-                       mm_resource_manager_mark_for_release(resource_manager, resource);
+                       mm_resource_manager_mark_for_release(g_mc_resource_manager, resource);
                        LOGE("Failed to commit resource manager : %x", rm_ret);
                        return MEDIACODEC_ERROR_INTERNAL;
                }
                handle->codec_resource = resource;
 //LCOV_EXCL_STOP
        }
+#endif
 
        int ret = mc_prepare(handle->mc_handle);
 
@@ -361,21 +387,24 @@ int mediacodec_unprepare(mediacodec_h mediacodec)
 {
        MEDIACODEC_INSTANCE_CHECK(mediacodec);
        mediacodec_s *handle = (mediacodec_s *)mediacodec;
+#ifdef USE_MM_RESOURCE_MANAGER
        int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
+#endif
 
        int ret = mc_unprepare(handle->mc_handle);
 
        if (ret != MEDIACODEC_ERROR_NONE) {
                return __convert_error_code(ret, (char *)__FUNCTION__);
        } else {
+#ifdef USE_MM_RESOURCE_MANAGER
                if (handle->codec_resource != NULL) {
 //LCOV_EXCL_START
-                       mm_resource_manager_mark_for_release(resource_manager,
+                       mm_resource_manager_mark_for_release(g_mc_resource_manager,
                                        handle->codec_resource);
                        handle->codec_resource = NULL;
-                       rm_ret = mm_resource_manager_commit(resource_manager);
+                       rm_ret = mm_resource_manager_commit(g_mc_resource_manager);
                        if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-                               mm_resource_manager_mark_for_release(resource_manager, handle->codec_resource);
+                               mm_resource_manager_mark_for_release(g_mc_resource_manager, handle->codec_resource);
                                switch (rm_ret) {
                                case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY:
                                        return MEDIACODEC_ERROR_RESOURCE_OVERLOADED;
@@ -387,6 +416,7 @@ int mediacodec_unprepare(mediacodec_h mediacodec)
                } else {
                        LOGD("No codec resource to release. Probably resource release cb called\n");
                }
+#endif
 
                handle->state = MEDIACODEC_STATE_IDLE;
                return MEDIACODEC_ERROR_NONE;
@@ -691,6 +721,7 @@ static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *
        return 1;
 }
 
+#ifdef USE_MM_RESOURCE_MANAGER
 //LCOV_EXCL_START
 static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
                mm_resource_manager_res_h resource_h, void *user_data)
@@ -698,9 +729,9 @@ static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
        int i;
        mediacodec_s *handle;
 
-       g_mutex_lock(&mediacodec_handles_lock);
-       for (i = 0; i < mediacodec_handles->len; i++) {
-               handle = g_ptr_array_index(mediacodec_handles, i);
+       g_mutex_lock(&g_mediacodec_lock);
+       for (i = 0; i < g_mediacodec_handles->len; i++) {
+               handle = g_ptr_array_index(g_mediacodec_handles, i);
                if (handle->codec_resource == resource_h) {
                        /*
                         * TODO
@@ -715,26 +746,34 @@ static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
                        break;
                }
        }
-       g_mutex_unlock(&mediacodec_handles_lock);
+       g_mutex_unlock(&g_mediacodec_lock);
 
        return FALSE;
 }
 //LCOV_EXCL_STOP
 
+
 static void __mediacodec_init_lib()
 {
-       mediacodec_handles = g_ptr_array_sized_new(MC_PREALLOCATED_HANDLE_ARRAY_SIZE);
+       LOGD("START");
 
-       if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
-                       __mediacodec_resource_release_cb, NULL, &resource_manager)) {
-               LOGE("Failed to initialize resource manager");  //LCOV_EXCL_LINE
-               g_ptr_array_unref(mediacodec_handles);
-       }
+       g_mutex_init(&g_mediacodec_lock);
+       g_mediacodec_handles = g_ptr_array_sized_new(MC_PREALLOCATED_HANDLE_ARRAY_SIZE);
+
+       LOGD("DONE");
 }
 
 static void __mediacodec_deinit_lib()
 {
-       if (resource_manager != NULL)
-               mm_resource_manager_destroy(resource_manager);
-       g_ptr_array_unref(mediacodec_handles);
+       LOGD("START");
+
+       if (g_mc_resource_manager != NULL)
+               mm_resource_manager_destroy(g_mc_resource_manager);
+
+       g_ptr_array_unref(g_mediacodec_handles);
+       g_mutex_clear(&g_mediacodec_lock);
+
+       LOGD("DONE");
 }
+#endif
+
index b9d4d14..ce51083 100644 (file)
@@ -83,14 +83,14 @@ static void _mc_ini_check_ini_status(void);
 /* macro */
 #define MEDIA_CODEC_INI_GET_STRING(x_dict, x_item, x_ini, x_default) \
 do {\
-       gchar* str = iniparser_getstring(x_dict, x_ini, x_default); \
+       const char *str = iniparser_getstring(x_dict, x_ini, x_default); \
        \
        if (str &&  \
                        (strlen(str) > 0) && \
                        (strlen(str) < MEDIA_CODEC_INI_MAX_STRLEN)) \
-               strncpy(x_item, str, strlen(str) + 1); \
+               strncpy(x_item, str, MEDIA_CODEC_INI_MAX_STRLEN - 1); \
        else \
-               strncpy(x_item, x_default, strlen(x_default) + 1); \
+               strncpy(x_item, x_default, MEDIA_CODEC_INI_MAX_STRLEN - 1); \
 } while (0)
 
 #define MEDIA_CODEC_INI_GET_STRING_FROM_LIST(x_dict, x_list, x_ini, x_default) \
@@ -116,7 +116,7 @@ do {\
 
 #define MEDIA_CODEC_INI_GET_COLOR(x_dict, x_item, x_ini, x_default) \
 do {\
-       gchar* str = iniparser_getstring(x_dict, x_ini, x_default); \
+       const char *str = iniparser_getstring(x_dict, x_ini, x_default); \
        \
        if (str &&  \
                        (strlen(str) > 0) && \
old mode 100755 (executable)
new mode 100644 (file)
index 804a7cb..d78a1d4
@@ -800,7 +800,6 @@ int mc_set_supported_codec_cb(MMHandleType mediacodec, mediacodec_supported_code
 
 int _mediacodec_foreach_supported_codec(mediacodec_supported_codec_cb callback, void *user_data)
 {
-       int ret = MEDIACODEC_NONE;
        int i;
        int index;
 
@@ -814,19 +813,16 @@ int _mediacodec_foreach_supported_codec(mediacodec_supported_codec_cb callback,
        for (i = 0; i < CODEC_NR_ITEMS; i++) {
                if (codec[i]) {
                        index = (int)simple_to_codec_type_enumeration(i);
-                       if (!callback(index, user_data))
-                               goto CALLBACK_ERROR;
+                       if (!callback(index, user_data)) {
+                               LOGW("stop foreach callback");
+                               break;
+                       }
                }
        }
 
-       if (!callback(-1, user_data)) {
-               ret = MEDIACODEC_ERROR_INTERNAL;
-               goto CALLBACK_ERROR;
-       }
+       LOGD("done");
 
-CALLBACK_ERROR:
-       LOGD("foreach callback returned error");
-       return ret;
+       return MEDIACODEC_ERROR_NONE;
 }
 
 int mc_get_packet_pool(MMHandleType mediacodec, media_packet_pool_h *pool)
old mode 100755 (executable)
new mode 100644 (file)
index bd28393..bd2cf50
@@ -84,6 +84,23 @@ static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool c
 GstCaps *_mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index);
 GstCaps *_mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index);
 
+static int __mc_fill_input_buffer(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
+static int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
+
+static int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
+static int __mc_fill_input_buffer_with_adec_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
+static int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
+
+static int __mc_fill_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
+static int __mc_fill_aenc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
+static int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
+static int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
+
+static mc_gst_core_t *mc_gst_core_new();
+static void mc_gst_core_free(mc_gst_core_t *core);
+
+static mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core);
+static void mc_gst_port_free(mc_gst_port_t *port);
 /* video vtable */
 int(*vdec_vtable[])() = {&__mc_fill_input_buffer_with_packet, &__mc_fill_packet_with_output_buffer};
 int(*venc_vtable[])() = {&__mc_fill_input_buffer_with_packet, &__mc_fill_packet_with_output_buffer};
@@ -155,6 +172,14 @@ int(*adec_flac_vtable[])() = {&__mc_fill_input_buffer_with_packet,
 int(*adec_wma_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* WMA Decoder Vtable */
                                                        &__mc_fill_packet_with_output_buffer};
 
+#define MEDIACODEC_ELEMENT_SET_STATE(x_element, x_state)                                          \
+       do {                                                                                            \
+               LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME(x_element)); \
+               if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(x_element, x_state)) {                    \
+                       LOGE("failed to set state %s to %s\n", #x_state, GST_ELEMENT_NAME(x_element));        \
+                       goto STATE_CHANGE_FAILED;                                                               \
+               }                                                                                           \
+       } while (0)
 
 /*
  * fill_inbuf virtual functions
@@ -195,7 +220,7 @@ int __mc_fill_inbuf_with_mm_video_buffer(mc_gst_core_t *core, media_packet_h pac
        return ret;
 }
 
-int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
+static int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
 {
        gint ret = MC_ERROR_NONE;
        void *buf_data = NULL;
@@ -223,7 +248,7 @@ int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_h packe
        return ret;
 }
 
-int __mc_fill_input_buffer_with_adec_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
+static int __mc_fill_input_buffer_with_adec_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
 {
        gint ret = MC_ERROR_NONE;
        uint64_t buf_size = 0;
@@ -268,7 +293,7 @@ int __mc_fill_input_buffer_with_adec_packet(mc_gst_core_t *core, media_packet_h
        return ret;
 }
 
-int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
+static int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
 {
        gint ret = MC_ERROR_NONE;
        gint i;
@@ -372,12 +397,12 @@ int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h
  * fill_outbuf virtual functions
  */
 
-int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
+static int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
 {
        return core->vtable[fill_outbuf](core, data, size, mcbuffer);
 }
 
-int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
+static int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
 {
        int i;
        int stride_width;
@@ -449,7 +474,7 @@ int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, in
        return MC_ERROR_NONE;
 }
 
-int __mc_fill_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
+static int __mc_fill_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
 {
        gint ret = MC_ERROR_NONE;
        gchar *ext_mem = NULL;
@@ -481,7 +506,7 @@ int __mc_fill_packet_with_output_buffer(mc_gst_core_t *core, void *data, int siz
        return MC_ERROR_NONE;
 }
 
-int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
+static int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
 {
        gint ret = MC_ERROR_NONE;
        bool codec_config = FALSE;
@@ -542,7 +567,7 @@ int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, in
        return ret;
 }
 
-int __mc_fill_aenc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
+static int __mc_fill_aenc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
 {
        int ret = MC_ERROR_NONE;
        gint mem_size = 0;
@@ -882,7 +907,7 @@ int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, m
 /*
  * mc_gst_core functions
  */
-mc_gst_core_t *mc_gst_core_new()
+static mc_gst_core_t *mc_gst_core_new()
 {
        mc_gst_core_t *core;
 
@@ -898,7 +923,6 @@ mc_gst_core_t *mc_gst_core_new()
 
        core->available_queue = g_new0(mc_aqueue_t, 1);
        core->available_queue->input = mc_async_queue_new();
-       mc_async_queue_enable(core->available_queue->input);
 
        g_mutex_init(&core->eos_mutex);
        g_cond_init(&core->eos_cond);
@@ -930,7 +954,7 @@ mc_gst_core_t *mc_gst_core_new()
        return core;
 }
 
-void mc_gst_core_free(mc_gst_core_t *core)
+static void mc_gst_core_free(mc_gst_core_t *core)
 {
        MEDIACODEC_FENTER();
 
@@ -980,7 +1004,7 @@ void mc_gst_core_free(mc_gst_core_t *core)
 /*
  * mc_gst_port functions
  */
-mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core)
+static mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core)
 {
        MEDIACODEC_FENTER();
 
@@ -1001,7 +1025,7 @@ mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core)
        return port;
 }
 
-void mc_gst_port_free(mc_gst_port_t *port)
+static void mc_gst_port_free(mc_gst_port_t *port)
 {
        MEDIACODEC_FENTER();
 
@@ -1796,7 +1820,7 @@ mc_ret_e mc_gst_unprepare(mc_handle_t *mc_handle)
        return ret;
 }
 
-mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeOutUs)
+mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeout_us)
 {
        MEDIACODEC_FENTER();
 
@@ -1840,7 +1864,7 @@ mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint
        return ret;
 }
 
-mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeOutUs)
+mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeout_us)
 {
        gint ret = MC_ERROR_NONE;
        gint64 end_time = -1;
@@ -1849,7 +1873,7 @@ mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint6
        media_packet_h out_packet = NULL;
 
        MEDIACODEC_FENTER();
-       end_time = g_get_monotonic_time() + timeOutUs;
+       end_time = g_get_monotonic_time() + timeout_us;
 
        if (!mc_handle)
                return MC_PARAM_ERROR;
@@ -2369,7 +2393,7 @@ GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet
                 * will not be invoked
                 */
                gst_buffer_unref(mcbuffer->buffer);
-               free(mcbuffer);
+               g_free(mcbuffer);
                return NULL;
        }
 
@@ -2441,8 +2465,8 @@ int __mc_gst_create_eos_packet(media_format_h fmt, GstMCBuffer *mcbuffer)
        media_packet_h packet = NULL;
 
        MEDIACODEC_FENTER();
-       if (media_packet_create_alloc(fmt, __mc_output_buffer_finalize_cb, mcbuffer, &packet)) {
-               LOGE("media_packet_create_alloc failed\n");
+       if (media_packet_create(fmt, __mc_output_buffer_finalize_cb, mcbuffer, &packet)) {
+               LOGE("media_packet_create failed\n");
                ret = MC_ERROR;
                goto ERROR;
        }
@@ -2665,16 +2689,12 @@ static void __mc_input_buffer_finalize_cb(GstMCBuffer *mcbuffer)
                return;
 
        LOGD("============>>>>>  _finalize_cb  : %p, %p", mcbuffer, mcbuffer->packet);
-       mc_gst_core_t *core = (mc_gst_core_t *)mcbuffer->core;
 
-       _mc_gst_handle_input_buffer_used(core, mcbuffer->packet);
+       _mc_gst_handle_input_buffer_used(mcbuffer->core, mcbuffer->packet);
 
        g_free(mcbuffer);
-       mcbuffer = NULL;
 
        MEDIACODEC_FLEAVE();
-
-       return;
 }
 
 static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h packet, uint64_t size)
@@ -2683,11 +2703,6 @@ static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_
 
        mcbuffer = (GstMCBuffer *)g_malloc0(sizeof(GstMCBuffer));
 
-       if (mcbuffer == NULL) {
-               LOGE("malloc fail");
-               return NULL;
-       }
-
        mcbuffer->buffer = gst_buffer_new();
        mcbuffer->buf_size = 0;
 
diff --git a/src/media_codec_sync_internal.c b/src/media_codec_sync_internal.c
new file mode 100644 (file)
index 0000000..e17390b
--- /dev/null
@@ -0,0 +1,955 @@
+/*
+ * Copyright (c) 2019 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 <inttypes.h>
+#include <dlog.h>
+#include <media_codec_sync_private.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "TIZEN_N_MEDIACODECSYNC"
+
+#define PIPELINE_NAME_AUDIO "MEDIACODECSYNC_AUDIO"
+#define PIPELINE_NAME_VIDEO "MEDIACODECSYNC_VIDEO"
+
+#define _MEDIACODECSYNC_PIPELINE_MAKE(handle, pipeline, name) \
+       do { \
+               if (pipeline) { \
+                       gst_object_unref(pipeline); \
+                       pipeline = NULL; \
+               } \
+               pipeline = gst_pipeline_new(name); \
+               if (!pipeline) { \
+                       LOGE("create pipeline[%s] failed", name); \
+                       goto _CREATE_PIPELINE_FAILED; \
+               } \
+               g_object_weak_ref(G_OBJECT(pipeline), (GWeakNotify)__mediacodecsync_element_release_noti, handle); \
+               LOGD("create pipeline [%s] done", name); \
+       } while (0)
+
+#define _MEDIACODECSYNC_ELEMENT_MAKE(handle, element, name, prefix, nick) \
+       do { \
+               char nick_name[24]; \
+               if (element) { \
+                       gst_object_unref(element); \
+                       element = NULL; \
+               } \
+               snprintf(nick_name, sizeof(nick_name), "%s%s", prefix, nick); \
+               element = gst_element_factory_make(name, nick_name); \
+               if (!element) { \
+                       LOGE("create element[%s,%s] failed", name, nick_name); \
+                       goto _CREATE_PIPELINE_FAILED; \
+               } \
+               g_object_weak_ref(G_OBJECT(element), (GWeakNotify)__mediacodecsync_element_release_noti, handle); \
+               LOGD("create element [%s,%s] done", name, nick_name); \
+       } while (0)
+
+#define _MEDIACODECSYNC_ELEMENT_REMOVE(element) \
+       do { \
+               if (element != NULL) \
+                       gst_object_unref(element); \
+       } while (0)
+
+
+
+static void __mediacodecsync_need_audio_data_cb(GstElement *appsrc, guint size, gpointer data)
+{
+       /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/
+
+       LOGI("audio data is needed");
+}
+
+
+static void __mediacodecsync_enough_audio_data_cb(GstElement *appsrc, gpointer data)
+{
+       /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/
+
+       LOGI("audio data is enough");
+}
+
+
+static void __mediacodecsync_need_video_data_cb(GstElement *appsrc, guint size, gpointer data)
+{
+       /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/
+
+       LOGI("video data is needed");
+}
+
+
+static void __mediacodecsync_enough_video_data_cb(GstElement *appsrc, gpointer data)
+{
+       /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/
+
+       LOGI("video data is enough");
+}
+
+
+static int _mediacodecsync_get_packet_info(media_packet_h packet, packet_info *info)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       bool has_tbm_surface = false;
+       void *data = NULL;
+       uint64_t data_size = 0;
+       uint64_t dts = 0;
+       uint64_t pts = 0;
+       uint64_t duration = 0;
+
+       if (!packet || !info) {
+               LOGE("NULL params %p %p", packet, info);
+               return MEDIACODEC_ERROR_INVALID_PARAMETER;
+       }
+
+       /* get packet info */
+       ret = media_packet_has_tbm_surface_buffer(packet, &has_tbm_surface);
+       ret |= media_packet_get_buffer_data_ptr(packet, &data);
+       ret |= media_packet_get_buffer_size(packet, &data_size);
+       ret |= media_packet_get_dts(packet, &dts);
+       ret |= media_packet_get_pts(packet, &pts);
+       ret |= media_packet_get_duration(packet, &duration);
+
+       if (ret == MEDIACODEC_ERROR_NONE) {
+               info->has_tbm_surface = has_tbm_surface;
+               info->data = data;
+               info->data_size = data_size;
+               info->dts = dts;
+               info->pts = pts;
+               info->duration = duration;
+
+               LOGI("packet info[%u], %p, size %"PRIu64", dts %"PRIu64", pts %"PRIu64", duration %"PRIu64,
+                       has_tbm_surface, data, data_size, dts, pts, duration);
+       }
+
+       return ret;
+}
+
+
+static void _mediacodecsync_gst_buffer_finalize(GstMCSBuffer *mcs_buffer)
+{
+       mediacodecsync_s *handle = NULL;
+
+       if (!mcs_buffer || !mcs_buffer->handle) {
+               LOGE("NULL buffer(%p) or handle", mcs_buffer);
+               return;
+       }
+
+       handle = mcs_buffer->handle;
+
+       LOGI("[type %d] mcs_buffer %p, gst buffer %p, packet %p",
+               mcs_buffer->type, mcs_buffer, mcs_buffer->gst_buffer, mcs_buffer->packet);
+
+       if (mcs_buffer->packet) {
+               if (handle->buffer_used_cb)
+                       handle->buffer_used_cb(mcs_buffer->packet, mcs_buffer->type, handle->buffer_used_cb_userdata);
+               else
+                       LOGE("No buffer used callback");
+       }
+
+       free(mcs_buffer);
+}
+
+
+static GstMCSBuffer *_mediacodecsync_gst_buffer_new(mediacodecsync_s *handle, media_packet_h packet, int type)
+{
+       GstMCSBuffer *new_buffer = NULL;
+       GstMemory *memory = NULL;
+       tbm_surface_h tbm_surface = NULL;
+       packet_info info;
+
+       if (!handle || !packet) {
+               LOGE("invalid params %p, %p", handle, packet);
+               return NULL;
+       }
+
+       /* get packet info */
+       if (_mediacodecsync_get_packet_info(packet, &info) != MEDIA_PACKET_ERROR_NONE) {
+               LOGE("_mediacodecsync_get_packet_info failed");
+               return NULL;
+       }
+
+       new_buffer = (GstMCSBuffer *)calloc(1, sizeof(GstMCSBuffer));
+       if (!new_buffer) {
+               LOGE("GstMCSBuffer alloc failed");
+               return NULL;
+       }
+
+       new_buffer->gst_buffer = gst_buffer_new();
+       new_buffer->type = type;
+       new_buffer->packet = packet;
+       new_buffer->handle = handle;
+
+       if (info.has_tbm_surface) {
+               /* get tbm surface from packet */
+               if (media_packet_get_tbm_surface(packet, &tbm_surface) != MEDIA_PACKET_ERROR_NONE) {
+                       LOGE("get tbm surface failed");
+                       goto _BUFFER_NEW_FAILED;
+               }
+
+               /* create tizen memory for gst buffer with tbm surface */
+               memory = gst_tizen_allocator_alloc_surface(handle->allocator,
+                       &handle->video_info, tbm_surface, (gpointer)new_buffer,
+                       (GDestroyNotify)_mediacodecsync_gst_buffer_finalize);
+       } else {
+               /* If tbm is not used, the data from packet will be used. */
+               memory = gst_memory_new_wrapped(0, info.data, (gsize)info.data_size,
+                       0, (gsize)info.data_size, (gpointer)new_buffer,
+                       (GDestroyNotify)_mediacodecsync_gst_buffer_finalize);
+       }
+
+       if (!memory) {
+               LOGE("GstMemory failed");
+               goto _BUFFER_NEW_FAILED;
+       }
+
+       gst_buffer_append_memory(new_buffer->gst_buffer, memory);
+
+       /* set buffer meta */
+       gst_buffer_set_size(new_buffer->gst_buffer, info.data_size);
+       GST_BUFFER_DTS(new_buffer->gst_buffer) = info.dts;
+       GST_BUFFER_PTS(new_buffer->gst_buffer) = info.pts;
+       GST_BUFFER_DURATION(new_buffer->gst_buffer) = info.duration;
+       GST_BUFFER_OFFSET(new_buffer->gst_buffer) = 0;
+       GST_BUFFER_OFFSET_END(new_buffer->gst_buffer) = info.data_size;
+
+       return new_buffer;
+
+_BUFFER_NEW_FAILED:
+       gst_buffer_unref(new_buffer->gst_buffer);
+       free(new_buffer);
+       return NULL;
+}
+
+static void __mediacodecsync_element_release_noti(gpointer data, GObject *obj)
+{
+       int i = 0;
+       mediacodecsync_s *handle = (mediacodecsync_s *)data;
+
+       if (!handle) {
+               LOGE("NULL handle");
+               return;
+       }
+
+       for (i = 0 ; i < MEDIACODECSYNC_ELEMENT_NUM ; i++) {
+               if (handle->audio_pipe[i] && G_OBJECT(handle->audio_pipe[i]) == obj) {
+                       LOGD("audio element[%d] was released", i);
+                       handle->audio_pipe[i] = NULL;
+                       return;
+               }
+       }
+
+       for (i = 0 ; i < MEDIACODECSYNC_ELEMENT_NUM ; i++) {
+               if (handle->video_pipe[i] && G_OBJECT(handle->video_pipe[i]) == obj) {
+                       LOGD("video element[%d] was released", i);
+                       handle->video_pipe[i] = NULL;
+                       return;
+               }
+       }
+
+       LOGW("no matched element [%p]", obj);
+}
+
+
+static GstCaps *_mediacodecsync_make_caps_from_mediaformat(media_format_h format)
+{
+       int i = 0;
+       GstCaps *new_caps = NULL;
+       media_format_type_e type = MEDIA_FORMAT_NONE;
+       media_format_mimetype_e mime_type = 0;
+
+       format_table audio_table[AUDIO_FORMAT_TABLE_SIZE] = {
+               {MEDIA_FORMAT_PCM,       "S16LE"},
+               {MEDIA_FORMAT_PCM_S16LE, "S16LE"},
+               {MEDIA_FORMAT_PCM_S24LE, "S24LE"},
+               {MEDIA_FORMAT_PCM_S32LE, "S32LE"},
+               {MEDIA_FORMAT_PCM_S16BE, "S16BE"},
+               {MEDIA_FORMAT_PCM_S24BE, "S24BE"},
+               {MEDIA_FORMAT_PCM_S32BE, "S32BE"},
+               {MEDIA_FORMAT_PCM_F32LE, "F32LE"},
+               {MEDIA_FORMAT_PCM_F32BE, "F32BE"},
+               {MEDIA_FORMAT_PCM_U16LE, "U16LE"},
+               {MEDIA_FORMAT_PCM_U24LE, "U24LE"},
+               {MEDIA_FORMAT_PCM_U32LE, "U32LE"},
+               {MEDIA_FORMAT_PCM_U16BE, "U16BE"},
+               {MEDIA_FORMAT_PCM_U24BE, "U24BE"},
+               {MEDIA_FORMAT_PCM_U32BE, "U32BE"}
+       };
+       format_table video_table[VIDEO_FORMAT_TABLE_SIZE] = {
+               {MEDIA_FORMAT_I420,  "I420"},
+               {MEDIA_FORMAT_NV12,  "SN12"},
+               {MEDIA_FORMAT_NV12T, "NV12T"},
+               {MEDIA_FORMAT_YV12,  "YV12"},
+               {MEDIA_FORMAT_NV21,  "NV21"},
+               {MEDIA_FORMAT_NV16,  "NV16"},
+               {MEDIA_FORMAT_YUYV,  "YUYV"},
+               {MEDIA_FORMAT_UYVY,  "UYVY"}
+       };
+
+       if (media_format_get_type(format, &type) != MEDIA_FORMAT_ERROR_NONE) {
+               LOGE("get type failed");
+               return NULL;
+       }
+
+       if (type & MEDIA_FORMAT_AUDIO) {
+               int channel;
+               int samplerate;
+               int bit;
+
+               if (media_format_get_audio_info(format, &mime_type, &channel,
+                               &samplerate, &bit, NULL) != MEDIA_FORMAT_ERROR_NONE) {
+                       LOGE("get audio info failed");
+                       return NULL;
+               }
+
+               for (i = 0 ; i < AUDIO_FORMAT_TABLE_SIZE ; i++) {
+                       if (audio_table[i].mime_type == mime_type) {
+                               new_caps = gst_caps_new_simple("audio/x-raw",
+                                       "rate", G_TYPE_INT, samplerate,
+                                       "channels", G_TYPE_INT, channel,
+                                       "format", G_TYPE_STRING, audio_table[i].format_string,
+                                       NULL);
+                               break;
+                       }
+               }
+       } else if (type & MEDIA_FORMAT_VIDEO) {
+               int width;
+               int height;
+
+               if (media_format_get_video_info(format, &mime_type,
+                               &width, &height, NULL, NULL) != MEDIA_FORMAT_ERROR_NONE) {
+                       LOGE("get video info failed");
+                       return NULL;
+               }
+
+               for (i = 0 ; i < VIDEO_FORMAT_TABLE_SIZE ; i++) {
+                       if (video_table[i].mime_type == mime_type) {
+                               new_caps = gst_caps_new_simple("video/x-raw",
+                                       "format", G_TYPE_STRING, video_table[i].format_string,
+                                       "width", G_TYPE_INT, width,
+                                       "height", G_TYPE_INT, height,
+                                       "framerate", GST_TYPE_FRACTION, 30, 1,
+                                       NULL);
+                               break;
+                       }
+               }
+       }
+
+       if (new_caps) {
+               gchar *caps_string = gst_caps_to_string(new_caps);
+               if (caps_string) {
+                       LOGD("caps [%s]", caps_string);
+                       g_free(caps_string);
+               }
+       } else {
+               LOGE("new caps failed [type:0x%x,0x%x]", type, mime_type);
+       }
+
+       return new_caps;
+}
+
+
+static void _mediacodecsync_destroy_pipeline(GstElement *pipeline[MEDIACODECSYNC_ELEMENT_NUM])
+{
+       GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+
+       if (!pipeline[MEDIACODECSYNC_PIPELINE]) {
+               LOGW("NULL pipeline");
+               return;
+       }
+
+       result = gst_element_set_state(pipeline[MEDIACODECSYNC_PIPELINE], GST_STATE_NULL);
+
+       LOGD("set state NULL : %d", result);
+
+       _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_PIPELINE]);
+       _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC]);
+       _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_CAPS]);
+       _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_QUE]);
+       _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_SINK]);
+}
+
+
+static int _mediacodecsync_create_pipeline(mediacodecsync_s *handle, media_format_h format,
+       GstElement *pipeline[MEDIACODECSYNC_ELEMENT_NUM], const char *pipe_name, const char *nick_prefix,
+       GCallback need_data_cb, GCallback enough_data_cb, GstCaps **out_caps)
+{
+       GstCaps *caps = NULL;
+
+       LOGD("name : %s", pipe_name);
+
+       /* main pipeline */
+       _MEDIACODECSYNC_PIPELINE_MAKE(handle, pipeline[MEDIACODECSYNC_PIPELINE], pipe_name);
+
+       /* elements */
+       _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], "appsrc", nick_prefix, "src");
+       _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_CAPS], "capsfilter", nick_prefix, "caps");
+
+       if (!strncmp(nick_prefix, "audio", 5)) {
+               _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_QUE], "queue", nick_prefix, "queue");
+               _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_SINK], "pulsesink", nick_prefix, "sink");
+               g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "qos", 1, NULL);
+               g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "provide-clock", 0, NULL);
+               g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "slave-method", 2, NULL); /* GST_AUDIO_BASE_SINK_SLAVE_NONE */
+       } else {
+               _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_QUE], "queue", nick_prefix, "queue");
+               _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_SINK], "tizenwlsink", nick_prefix, "sink");
+
+               g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "use-tbm", 1, NULL);
+               g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "enable-last-sample", 0, NULL);
+               g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "show-preroll-frame", 0, NULL);
+       }
+
+       g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC]), "max-bytes", (guint64)0, NULL); /* unlimited */
+       g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_QUE]), "max-size-time", 0, NULL);
+       g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_QUE]), "max-size-bytes", 0, NULL);
+       g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_QUE]), "max-size-buffers", 0, NULL);
+       g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC]), "format", 3, NULL); /* GST_FORMAT_TIME */
+       g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "sync", 1, NULL);
+
+       /* add elements to pipeline */
+       gst_bin_add_many(GST_BIN(pipeline[MEDIACODECSYNC_PIPELINE]),
+               pipeline[MEDIACODECSYNC_ELEMENT_APPSRC],
+               pipeline[MEDIACODECSYNC_ELEMENT_CAPS],
+               pipeline[MEDIACODECSYNC_ELEMENT_QUE],
+               pipeline[MEDIACODECSYNC_ELEMENT_SINK],
+               NULL);
+
+       /* link elements */
+       if (!(gst_element_link_many(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC],
+               pipeline[MEDIACODECSYNC_ELEMENT_CAPS],
+               pipeline[MEDIACODECSYNC_ELEMENT_QUE],
+               pipeline[MEDIACODECSYNC_ELEMENT_SINK],
+               NULL))) {
+               LOGE("link elements failed");
+               goto _CREATE_PIPELINE_FAILED;
+       }
+
+       /* set capsfilter */
+       caps = _mediacodecsync_make_caps_from_mediaformat(format);
+       if (!caps) {
+               LOGE("pipeline caps failed");
+               goto _CREATE_PIPELINE_FAILED;
+       }
+
+       g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_CAPS]), "caps", caps, NULL);
+
+       if (out_caps) {
+               if (*out_caps) {
+                       LOGD("unref previous video_caps %p", *out_caps);
+                       gst_caps_unref(*out_caps);
+                       *out_caps = NULL;
+               }
+
+               *out_caps = caps;
+       } else {
+               gst_caps_unref(caps);
+               caps = NULL;
+       }
+
+       g_signal_connect(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], "need-data", need_data_cb, handle);
+       g_signal_connect(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], "enough-data", enough_data_cb, handle);
+
+       LOGD("done");
+
+       return MEDIACODEC_ERROR_NONE;
+
+_CREATE_PIPELINE_FAILED:
+       LOGE("[%s] failed", pipe_name);
+
+       _mediacodecsync_destroy_pipeline(pipeline);
+
+       return MEDIACODEC_ERROR_INTERNAL;
+}
+
+
+static int _mediacodecsync_prepare_pipeline(mediacodecsync_s *handle)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       GstClock *clock = NULL;
+       GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+
+       LOGD("enter");
+
+       if (handle->audio_format) {
+               /* create audio pipeline */
+               ret = _mediacodecsync_create_pipeline(handle, handle->audio_format,
+                       handle->audio_pipe, PIPELINE_NAME_AUDIO, "audio",
+                       (GCallback)__mediacodecsync_need_audio_data_cb,
+                       (GCallback)__mediacodecsync_enough_audio_data_cb,
+                       NULL);
+               if (ret != MEDIACODEC_ERROR_NONE)
+                       return ret;
+
+               /* set state */
+               result = gst_element_set_state(handle->audio_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PAUSED);
+               if (result == GST_STATE_CHANGE_FAILURE) {
+                       LOGE("state change failed - VIDEO pipeline");
+                       ret = MEDIACODEC_ERROR_INTERNAL;
+                       goto _PREPARE_FAILED;
+               }
+
+               LOGD("audio pipeline done");
+       }
+
+       if (handle->video_format) {
+               /* create video pipeline */
+               ret = _mediacodecsync_create_pipeline(handle, handle->video_format,
+                       handle->video_pipe, PIPELINE_NAME_VIDEO, "video",
+                       (GCallback)__mediacodecsync_need_video_data_cb,
+                       (GCallback)__mediacodecsync_enough_video_data_cb,
+                       &handle->video_caps);
+               if (ret != MEDIACODEC_ERROR_NONE)
+                       goto _PREPARE_FAILED;
+
+               /* get video info */
+               if (!gst_video_info_from_caps(&handle->video_info, handle->video_caps)) {
+                       LOGE("failed to get video info");
+                       goto _PREPARE_FAILED;
+               }
+
+               /* set state */
+               result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PAUSED);
+               if (result == GST_STATE_CHANGE_FAILURE) {
+                       LOGE("state change failed - VIDEO pipeline");
+                       ret = MEDIACODEC_ERROR_INTERNAL;
+                       goto _PREPARE_FAILED;
+               }
+
+               LOGD("video pipeline done");
+
+               /* share clock to synchronize */
+               if (handle->audio_pipe[MEDIACODECSYNC_PIPELINE]) {
+                       LOGD("set clock of audio pipeline to video pipeline");
+
+                       clock = gst_pipeline_get_clock(GST_PIPELINE(handle->audio_pipe[MEDIACODECSYNC_PIPELINE]));
+
+                       if (!gst_pipeline_set_clock(GST_PIPELINE(handle->video_pipe[MEDIACODECSYNC_PIPELINE]), clock))
+                               LOGW("failed to set clock to video pipeline");
+
+                       gst_object_unref(clock);
+                       clock = NULL;
+               }
+       }
+
+       LOGD("done");
+
+       return ret;
+
+_PREPARE_FAILED:
+       _mediacodecsync_destroy_pipeline(handle->audio_pipe);
+       _mediacodecsync_destroy_pipeline(handle->video_pipe);
+
+       return ret;
+}
+
+
+static void _mediacodecsync_unprepare_pipeline(mediacodecsync_s *handle)
+{
+       _mediacodecsync_destroy_pipeline(handle->audio_pipe);
+       _mediacodecsync_destroy_pipeline(handle->video_pipe);
+}
+
+
+
+int mediacodecsync_create(mediacodecsync_buffer_used_cb callback, void *userdata, mediacodecsync_h *mediacodecsync)
+{
+       mediacodecsync_s *new_handle = NULL;
+
+       MEDIACODEC_NULL_ARG_CHECK(mediacodecsync);
+       MEDIACODEC_NULL_ARG_CHECK(callback);
+
+       LOGD("enter");
+
+       new_handle = (mediacodecsync_s *)malloc(sizeof(mediacodecsync_s));
+       if (new_handle == NULL) {
+               LOGE("handle allocation failed");
+               return MEDIACODEC_ERROR_OUT_OF_MEMORY;
+       }
+
+       memset(new_handle, 0x0, sizeof(mediacodecsync_s));
+
+       new_handle->buffer_used_cb = callback;
+       new_handle->buffer_used_cb_userdata = userdata;
+       new_handle->state = MEDIACODECSYNC_STATE_CREATED;
+       new_handle->allocator = gst_tizen_allocator_new();
+       g_mutex_init(&new_handle->lock);
+
+       *mediacodecsync = (mediacodecsync_h)new_handle;
+
+       LOGD("new handle : %p", *mediacodecsync);
+
+       return MEDIACODEC_ERROR_NONE;
+}
+
+
+int mediacodecsync_destroy(mediacodecsync_h mediacodecsync)
+{
+       mediacodecsync_s *handle = NULL;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       LOGD("handle to destroy : %p", handle);
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state != MEDIACODECSYNC_STATE_CREATED) {
+               LOGE("invalid state %d", handle->state);
+               g_mutex_unlock(&handle->lock);
+               return MEDIACODEC_ERROR_INVALID_STATE;
+       }
+
+       if (handle->audio_format) {
+               media_format_unref(handle->audio_format);
+               handle->audio_format = NULL;
+       }
+
+       if (handle->video_format) {
+               media_format_unref(handle->video_format);
+               handle->video_format = NULL;
+       }
+
+       if (handle->video_caps) {
+               gst_caps_unref(handle->video_caps);
+               handle->video_caps = NULL;
+       }
+
+       g_mutex_unlock(&handle->lock);
+
+       g_mutex_clear(&handle->lock);
+
+       free(handle);
+
+       LOGD("done");
+
+       return MEDIACODEC_ERROR_NONE;
+}
+
+
+int mediacodecsync_set_format(mediacodecsync_h mediacodecsync, media_format_h audio_format, media_format_h video_format)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       mediacodecsync_s *handle = NULL;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       if (!audio_format && !video_format) {
+               LOGE("all formats are NULL");
+               return MEDIACODEC_ERROR_INVALID_PARAMETER;
+       }
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state != MEDIACODECSYNC_STATE_CREATED) {
+               LOGE("invalid state %d", handle->state);
+               ret = MEDIACODEC_ERROR_INVALID_STATE;
+               goto _SET_FORMAT_DONE;
+       }
+
+       if (audio_format) {
+               LOGD("set audio format : %p", audio_format);
+
+               if (media_format_ref(audio_format) != MEDIACODEC_ERROR_NONE) {
+                       LOGE("audio format ref failed");
+                       ret = MEDIACODEC_ERROR_INTERNAL;
+                       goto _SET_FORMAT_DONE;
+               }
+
+               if (handle->audio_format)
+                       media_format_unref(handle->audio_format);
+
+               handle->audio_format = audio_format;
+       }
+
+       if (video_format) {
+               LOGD("set video format : %p", video_format);
+
+               if (media_format_ref(video_format) != MEDIACODEC_ERROR_NONE) {
+                       LOGE("video format ref failed");
+                       ret = MEDIACODEC_ERROR_INTERNAL;
+                       goto _SET_FORMAT_DONE;
+               }
+
+               if (handle->video_format)
+                       media_format_unref(handle->video_format);
+
+               handle->video_format = video_format;
+       }
+
+_SET_FORMAT_DONE:
+       g_mutex_unlock(&handle->lock);
+
+       return ret;
+}
+
+
+int mediacodecsync_prepare(mediacodecsync_h mediacodecsync)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       mediacodecsync_s *handle = NULL;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state != MEDIACODECSYNC_STATE_CREATED) {
+               LOGE("invalid state %d", handle->state);
+               g_mutex_unlock(&handle->lock);
+               return MEDIACODEC_ERROR_INVALID_STATE;
+       }
+
+       ret = _mediacodecsync_prepare_pipeline(handle);
+       if (ret == MEDIACODEC_ERROR_NONE)
+               handle->state = MEDIACODECSYNC_STATE_READY;
+
+       g_mutex_unlock(&handle->lock);
+
+       return ret;
+}
+
+
+int mediacodecsync_unprepare(mediacodecsync_h mediacodecsync)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       mediacodecsync_s *handle = NULL;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state != MEDIACODECSYNC_STATE_READY) {
+               LOGE("invalid state %d", handle->state);
+               g_mutex_unlock(&handle->lock);
+               return MEDIACODEC_ERROR_INVALID_STATE;
+       }
+
+       _mediacodecsync_unprepare_pipeline(handle);
+       handle->state = MEDIACODECSYNC_STATE_CREATED;
+
+       g_mutex_unlock(&handle->lock);
+
+       return ret;
+}
+
+
+int mediacodecsync_run(mediacodecsync_h mediacodecsync)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       mediacodecsync_s *handle = NULL;
+       GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state != MEDIACODECSYNC_STATE_READY &&
+               handle->state != MEDIACODECSYNC_STATE_PAUSED) {
+               LOGE("invalid state %d", handle->state);
+               ret = MEDIACODEC_ERROR_INVALID_STATE;
+               goto _RUN_DONE;
+       }
+
+       /* set state */
+       if (handle->audio_pipe[MEDIACODECSYNC_PIPELINE]) {
+               result = gst_element_set_state(handle->audio_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PLAYING);
+               if (result == GST_STATE_CHANGE_FAILURE) {
+                       LOGE("state change failed - AUDIO pipeline");
+                       ret = MEDIACODEC_ERROR_INTERNAL;
+                       goto _RUN_DONE;
+               }
+       }
+
+       if (handle->video_pipe[MEDIACODECSYNC_PIPELINE]) {
+               result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PLAYING);
+               if (result == GST_STATE_CHANGE_FAILURE) {
+                       LOGE("state change failed - VIDEO pipeline");
+                       ret = MEDIACODEC_ERROR_INTERNAL;
+                       goto _RUN_DONE;
+               }
+       }
+
+       LOGD("pipeline is now playing");
+       handle->state = MEDIACODECSYNC_STATE_RUNNING;
+
+_RUN_DONE:
+       g_mutex_unlock(&handle->lock);
+
+       return ret;
+}
+
+
+int mediacodecsync_stop(mediacodecsync_h mediacodecsync)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       mediacodecsync_s *handle = NULL;
+       GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state < MEDIACODECSYNC_STATE_RUNNING) {
+               LOGE("invalid state %d", handle->state);
+               g_mutex_unlock(&handle->lock);
+               return MEDIACODEC_ERROR_INVALID_STATE;
+       }
+
+       /* set state */
+       result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_READY);
+       if (result == GST_STATE_CHANGE_FAILURE) {
+               LOGE("state change failed - VIDEO pipeline");
+               ret = MEDIACODEC_ERROR_INTERNAL;
+       } else {
+               LOGD("pipeline is ready");
+               handle->state = MEDIACODECSYNC_STATE_READY;
+       }
+
+       g_mutex_unlock(&handle->lock);
+
+       return ret;
+}
+
+
+int mediacodecsync_pause(mediacodecsync_h mediacodecsync)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       mediacodecsync_s *handle = NULL;
+       GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state != MEDIACODECSYNC_STATE_RUNNING) {
+               LOGE("invalid state %d", handle->state);
+               g_mutex_unlock(&handle->lock);
+               return MEDIACODEC_ERROR_INVALID_STATE;
+       }
+
+       /* set state */
+       result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PAUSED);
+       if (result == GST_STATE_CHANGE_FAILURE) {
+               LOGE("state change failed - VIDEO pipeline");
+               ret = MEDIACODEC_ERROR_INTERNAL;
+       } else {
+               LOGD("pipeline is paused");
+               handle->state = MEDIACODECSYNC_STATE_PAUSED;
+       }
+
+       g_mutex_unlock(&handle->lock);
+
+       return ret;
+}
+
+
+static int _mediacodecsync_push_packet_to_pipeline(GstElement *appsrc, GstBuffer *buffer)
+{
+       GstFlowReturn gst_ret = GST_FLOW_OK;
+
+       if (!appsrc || !buffer) {
+               LOGE("NULL params %p,%p", appsrc, buffer);
+               return MEDIACODEC_ERROR_INTERNAL;
+       }
+
+       gst_ret = gst_app_src_push_buffer((GstAppSrc *)appsrc, buffer);
+       if (gst_ret != GST_FLOW_OK) {
+               LOGE("appsrc push failed %d", gst_ret);
+               return MEDIACODEC_ERROR_INTERNAL;
+       }
+
+       return MEDIACODEC_ERROR_NONE;
+}
+
+
+int mediacodecsync_push_packet(mediacodecsync_h mediacodecsync, media_packet_h packet, mediacodecsync_packet_type_e type)
+{
+       int ret = MEDIACODEC_ERROR_NONE;
+       mediacodecsync_s *handle = NULL;
+       GstMCSBuffer *mcs_buffer = NULL;
+       GstElement *appsrc = NULL;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       g_mutex_lock(&handle->lock);
+
+       if (handle->state != MEDIACODECSYNC_STATE_RUNNING) {
+               LOGE("invalid state %d", handle->state);
+               ret = MEDIACODEC_ERROR_INVALID_STATE;
+               goto _PUSH_PACKET_DONE;
+       }
+
+       mcs_buffer = _mediacodecsync_gst_buffer_new(handle, packet, type);
+       if (!mcs_buffer) {
+               LOGE("mediacodecsync new buffer failed");
+               ret = MEDIACODEC_ERROR_INTERNAL;
+               goto _PUSH_PACKET_DONE;
+       }
+
+       LOGI("type %u, new buffer %p [gst %p][packet %p]",
+               type, mcs_buffer, mcs_buffer->gst_buffer, packet);
+
+       switch (type) {
+       case MEDIACODECSYNC_PACKET_TYPE_AUDIO:
+               appsrc = handle->audio_pipe[MEDIACODECSYNC_ELEMENT_APPSRC];
+               break;
+       case MEDIACODECSYNC_PACKET_TYPE_VIDEO:
+               appsrc = handle->video_pipe[MEDIACODECSYNC_ELEMENT_APPSRC];
+               break;
+       default:
+               LOGE("unhandled packet type %u, release created buffer", type);
+               gst_buffer_unref(mcs_buffer->gst_buffer);
+               ret = MEDIACODEC_ERROR_INTERNAL;
+               goto _PUSH_PACKET_DONE;
+       }
+
+       ret = _mediacodecsync_push_packet_to_pipeline(appsrc, mcs_buffer->gst_buffer);
+
+_PUSH_PACKET_DONE:
+       g_mutex_unlock(&handle->lock);
+
+       return ret;
+}
+
+
+int mediacodecsync_get_state(mediacodecsync_h mediacodecsync, mediacodecsync_state_e *state)
+{
+       mediacodecsync_s *handle = NULL;
+
+       MEDIACODEC_INSTANCE_CHECK(mediacodecsync);
+       MEDIACODEC_NULL_ARG_CHECK(state);
+
+       handle = (mediacodecsync_s *)mediacodecsync;
+
+       *state = handle->state;
+
+       LOGI("state %u", *state);
+
+       return MEDIACODEC_ERROR_NONE;
+}