Add initial code for mediamuxer 32/43632/6 submit/tizen/20150722.060525
authorJoungkook Seo <jk7704.seo@samsung.com>
Mon, 13 Jul 2015 00:25:39 +0000 (09:25 +0900)
committerJoungkook Seo <jk7704.seo@samsung.com>
Tue, 21 Jul 2015 09:35:02 +0000 (18:35 +0900)
[1] Update the code according to the ACR review
[2] Fixed review comment of patch set(#3)
[3] Sync with 2.4 and Refine code (2nd)
[4] Fixed review comment of patch set(#5)

Change-Id: I82544b53d0057dec8c42640f8635a905cb70cf2d
Signed-off-by: Joungkook Seo <jk7704.seo@samsung.com>
26 files changed:
AUTHORS [new file with mode: 0755]
CMakeLists.txt [new file with mode: 0755]
LICENSE.APLv2 [new file with mode: 0755]
NOTICE [new file with mode: 0755]
capi-mediamuxer.manifest [new file with mode: 0755]
capi-mediamuxer.pc.in [new file with mode: 0755]
doc/mediamuxer_doc.h [new file with mode: 0755]
include/mediamuxer.h [new file with mode: 0755]
include/mediamuxer_error.h [new file with mode: 0755]
include/mediamuxer_ini.h [new file with mode: 0755]
include/mediamuxer_port.h [new file with mode: 0755]
include/mediamuxer_private.h [new file with mode: 0755]
include/mediamuxer_util.h [new file with mode: 0755]
include/port_custom/mediamuxer_port_custom.h [new file with mode: 0755]
include/port_ffmpeg/mediamuxer_port_ffmpeg.h [new file with mode: 0755]
include/port_gst/mediamuxer_port_gst.h [new file with mode: 0755]
packaging/capi-mediamuxer.spec [new file with mode: 0755]
src/CMakeLists.txt [new file with mode: 0755]
src/mediamuxer.c [new file with mode: 0644]
src/mediamuxer_ini.c [new file with mode: 0644]
src/mediamuxer_port.c [new file with mode: 0644]
src/port_custom/mediamuxer_port_custom.c [new file with mode: 0644]
src/port_ffmpeg/mediamuxer_port_ffmpeg.c [new file with mode: 0644]
src/port_gst/mediamuxer_port_gst.c [new file with mode: 0644]
test/CMakeLists.txt [new file with mode: 0644]
test/mediamuxer_test.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100755 (executable)
index 0000000..205b4f2
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Satheesan E N <satheesan.en@samsung.com>\r
+Joungkook Seo <jk7704.seo@samsung.com>\r
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..35a7cf0
--- /dev/null
@@ -0,0 +1,112 @@
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(fw_name "capi-mediamuxer")
+
+PROJECT(${fw_name})
+
+SET(CMAKE_INSTALL_PREFIX /usr)
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+
+SET(INC_DIR include)
+SET(INC_PORT_GST_DIR include/port_gst)
+SET(INC_PORT_CUSTOM_DIR include/port_custom)
+SET(INC_PORT_FFMPEG_DIR include/port_ffmpeg)
+INCLUDE_DIRECTORIES(${INC_DIR} ${INC_PORT_GST_DIR} ${INC_PORT_CUSTOM_DIR} ${INC_PORT_FFMPEG_DIR})
+
+SET(dependents "dlog glib-2.0 mm-common capi-media-tool iniparser gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0")
+SET(pc_dependents "capi-base-common capi-media-tool")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_name} REQUIRED ${dependents})
+FOREACH(flag ${${fw_name}_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "-I./include -I./include/headers ${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+
+IF("${ARCH}" STREQUAL "arm")
+    ADD_DEFINITIONS("-DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DTIZEN_DEBUG")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}")
+
+AUX_SOURCE_DIRECTORY (src MAIN_SRC)
+AUX_SOURCE_DIRECTORY (src/port_gst PORT_GST_SRC)
+AUX_SOURCE_DIRECTORY (src/port_custom PORT_CUST_SRC)
+AUX_SOURCE_DIRECTORY (src/port_ffmpeg PORT_FFMPEG_SRC)
+
+LIST (APPEND SOURCES
+     ${MAIN_SRC}
+     ${PORT_FFMPEG_SRC}
+     ${PORT_CUST_SRC}
+     ${PORT_GST_SRC}
+     )
+
+ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
+
+TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${fw_name}
+     PROPERTIES
+     VERSION ${FULLVER}
+     SOVERSION ${MAJORVER}
+     CLEAN_DIRECT_OUTPUT 1
+)
+
+INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(
+        DIRECTORY ${INC_DIR}/ DESTINATION include/media
+        FILES_MATCHING
+        PATTERN "mediamuxer_*.h" EXCLUDE
+        PATTERN "${INC_DIR}/*.h"
+        )
+
+SET(PC_NAME ${fw_name})
+SET(PC_REQUIRED ${pc_dependents})
+SET(PC_LDFLAGS -l${fw_name})
+SET(PC_CFLAGS -I\${includedir}/media)
+
+CONFIGURE_FILE(
+    ${fw_name}.pc.in
+    ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc
+    @ONLY
+)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION lib/pkgconfig)
+
+ADD_SUBDIRECTORY(test)
+
+IF(UNIX)
+
+ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution)
+ADD_CUSTOM_COMMAND(
+        DEPENDS clean
+        COMMENT "distribution clean"
+        COMMAND find
+        ARGS    .
+        -not -name config.cmake -and \(
+        -name tester.c -or
+        -name Testing -or
+        -name CMakeFiles -or
+        -name cmake.depends -or
+        -name cmake.check_depends -or
+        -name CMakeCache.txt -or
+        -name cmake.check_cache -or
+        -name *.cmake -or
+        -name Makefile -or
+        -name core -or
+        -name core.* -or
+        -name gmon.out -or
+        -name install_manifest.txt -or
+        -name *.pc -or
+        -name *~ \)
+        | grep -v TC | xargs rm -rf
+        TARGET  distclean
+        VERBATIM
+)
+
+ENDIF(UNIX)
+
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100755 (executable)
index 0000000..9c13a9b
--- /dev/null
@@ -0,0 +1,204 @@
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+\r
+                                 Apache License\r
+                           Version 2.0, January 2004\r
+                        http://www.apache.org/licenses/\r
+\r
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+   1. Definitions.\r
+\r
+      "License" shall mean the terms and conditions for use, reproduction,\r
+      and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+      "Licensor" shall mean the copyright owner or entity authorized by\r
+      the copyright owner that is granting the License.\r
+\r
+      "Legal Entity" shall mean the union of the acting entity and all\r
+      other entities that control, are controlled by, or are under common\r
+      control with that entity. For the purposes of this definition,\r
+      "control" means (i) the power, direct or indirect, to cause the\r
+      direction or management of such entity, whether by contract or\r
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+      outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+      "You" (or "Your") shall mean an individual or Legal Entity\r
+      exercising permissions granted by this License.\r
+\r
+      "Source" form shall mean the preferred form for making modifications,\r
+      including but not limited to software source code, documentation\r
+      source, and configuration files.\r
+\r
+      "Object" form shall mean any form resulting from mechanical\r
+      transformation or translation of a Source form, including but\r
+      not limited to compiled object code, generated documentation,\r
+      and conversions to other media types.\r
+\r
+      "Work" shall mean the work of authorship, whether in Source or\r
+      Object form, made available under the License, as indicated by a\r
+      copyright notice that is included in or attached to the work\r
+      (an example is provided in the Appendix below).\r
+\r
+      "Derivative Works" shall mean any work, whether in Source or Object\r
+      form, that is based on (or derived from) the Work and for which the\r
+      editorial revisions, annotations, elaborations, or other modifications\r
+      represent, as a whole, an original work of authorship. For the purposes\r
+      of this License, Derivative Works shall not include works that remain\r
+      separable from, or merely link (or bind by name) to the interfaces of,\r
+      the Work and Derivative Works thereof.\r
+\r
+      "Contribution" shall mean any work of authorship, including\r
+      the original version of the Work and any modifications or additions\r
+      to that Work or Derivative Works thereof, that is intentionally\r
+      submitted to Licensor for inclusion in the Work by the copyright owner\r
+      or by an individual or Legal Entity authorized to submit on behalf of\r
+      the copyright owner. For the purposes of this definition, "submitted"\r
+      means any form of electronic, verbal, or written communication sent\r
+      to the Licensor or its representatives, including but not limited to\r
+      communication on electronic mailing lists, source code control systems,\r
+      and issue tracking systems that are managed by, or on behalf of, the\r
+      Licensor for the purpose of discussing and improving the Work, but\r
+      excluding communication that is conspicuously marked or otherwise\r
+      designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+      "Contributor" shall mean Licensor and any individual or Legal Entity\r
+      on behalf of whom a Contribution has been received by Licensor and\r
+      subsequently incorporated within the Work.\r
+\r
+   2. Grant of Copyright License. Subject to the terms and conditions of\r
+      this License, each Contributor hereby grants to You a perpetual,\r
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+      copyright license to reproduce, prepare Derivative Works of,\r
+      publicly display, publicly perform, sublicense, and distribute the\r
+      Work and such Derivative Works in Source or Object form.\r
+\r
+   3. Grant of Patent License. Subject to the terms and conditions of\r
+      this License, each Contributor hereby grants to You a perpetual,\r
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+      (except as stated in this section) patent license to make, have made,\r
+      use, offer to sell, sell, import, and otherwise transfer the Work,\r
+      where such license applies only to those patent claims licensable\r
+      by such Contributor that are necessarily infringed by their\r
+      Contribution(s) alone or by combination of their Contribution(s)\r
+      with the Work to which such Contribution(s) was submitted. If You\r
+      institute patent litigation against any entity (including a\r
+      cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+      or a Contribution incorporated within the Work constitutes direct\r
+      or contributory patent infringement, then any patent licenses\r
+      granted to You under this License for that Work shall terminate\r
+      as of the date such litigation is filed.\r
+\r
+   4. Redistribution. You may reproduce and distribute copies of the\r
+      Work or Derivative Works thereof in any medium, with or without\r
+      modifications, and in Source or Object form, provided that You\r
+      meet the following conditions:\r
+\r
+      (a) You must give any other recipients of the Work or\r
+          Derivative Works a copy of this License; and\r
+\r
+      (b) You must cause any modified files to carry prominent notices\r
+          stating that You changed the files; and\r
+\r
+      (c) You must retain, in the Source form of any Derivative Works\r
+          that You distribute, all copyright, patent, trademark, and\r
+          attribution notices from the Source form of the Work,\r
+          excluding those notices that do not pertain to any part of\r
+          the Derivative Works; and\r
+\r
+      (d) If the Work includes a "NOTICE" text file as part of its\r
+          distribution, then any Derivative Works that You distribute must\r
+          include a readable copy of the attribution notices contained\r
+          within such NOTICE file, excluding those notices that do not\r
+          pertain to any part of the Derivative Works, in at least one\r
+          of the following places: within a NOTICE text file distributed\r
+          as part of the Derivative Works; within the Source form or\r
+          documentation, if provided along with the Derivative Works; or,\r
+          within a display generated by the Derivative Works, if and\r
+          wherever such third-party notices normally appear. The contents\r
+          of the NOTICE file are for informational purposes only and\r
+          do not modify the License. You may add Your own attribution\r
+          notices within Derivative Works that You distribute, alongside\r
+          or as an addendum to the NOTICE text from the Work, provided\r
+          that such additional attribution notices cannot be construed\r
+          as modifying the License.\r
+\r
+      You may add Your own copyright statement to Your modifications and\r
+      may provide additional or different license terms and conditions\r
+      for use, reproduction, or distribution of Your modifications, or\r
+      for any such Derivative Works as a whole, provided Your use,\r
+      reproduction, and distribution of the Work otherwise complies with\r
+      the conditions stated in this License.\r
+\r
+   5. Submission of Contributions. Unless You explicitly state otherwise,\r
+      any Contribution intentionally submitted for inclusion in the Work\r
+      by You to the Licensor shall be under the terms and conditions of\r
+      this License, without any additional terms or conditions.\r
+      Notwithstanding the above, nothing herein shall supersede or modify\r
+      the terms of any separate license agreement you may have executed\r
+      with Licensor regarding such Contributions.\r
+\r
+   6. Trademarks. This License does not grant permission to use the trade\r
+      names, trademarks, service marks, or product names of the Licensor,\r
+      except as required for reasonable and customary use in describing the\r
+      origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+   7. Disclaimer of Warranty. Unless required by applicable law or\r
+      agreed to in writing, Licensor provides the Work (and each\r
+      Contributor provides its Contributions) on an "AS IS" BASIS,\r
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+      implied, including, without limitation, any warranties or conditions\r
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+      PARTICULAR PURPOSE. You are solely responsible for determining the\r
+      appropriateness of using or redistributing the Work and assume any\r
+      risks associated with Your exercise of permissions under this License.\r
+\r
+   8. Limitation of Liability. In no event and under no legal theory,\r
+      whether in tort (including negligence), contract, or otherwise,\r
+      unless required by applicable law (such as deliberate and grossly\r
+      negligent acts) or agreed to in writing, shall any Contributor be\r
+      liable to You for damages, including any direct, indirect, special,\r
+      incidental, or consequential damages of any character arising as a\r
+      result of this License or out of the use or inability to use the\r
+      Work (including but not limited to damages for loss of goodwill,\r
+      work stoppage, computer failure or malfunction, or any and all\r
+      other commercial damages or losses), even if such Contributor\r
+      has been advised of the possibility of such damages.\r
+\r
+   9. Accepting Warranty or Additional Liability. While redistributing\r
+      the Work or Derivative Works thereof, You may choose to offer,\r
+      and charge a fee for, acceptance of support, warranty, indemnity,\r
+      or other liability obligations and/or rights consistent with this\r
+      License. However, in accepting such obligations, You may act only\r
+      on Your own behalf and on Your sole responsibility, not on behalf\r
+      of any other Contributor, and only if You agree to indemnify,\r
+      defend, and hold each Contributor harmless for any liability\r
+      incurred by, or claims asserted against, such Contributor by reason\r
+      of your accepting any such warranty or additional liability.\r
+\r
+   END OF TERMS AND CONDITIONS\r
+\r
+   APPENDIX: How to apply the Apache License to your work.\r
+\r
+      To apply the Apache License to your work, attach the following\r
+      boilerplate notice, with the fields enclosed by brackets "[]"\r
+      replaced with your own identifying information. (Don't include\r
+      the brackets!)  The text should be enclosed in the appropriate\r
+      comment syntax for the file format. We also recommend that a\r
+      file or class name and description of purpose be included on the\r
+      same "printed page" as the copyright notice for easier\r
+      identification within third-party archives.\r
+\r
+   Copyright [yyyy] [name of copyright owner]\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
diff --git a/NOTICE b/NOTICE
new file mode 100755 (executable)
index 0000000..ccdad52
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
diff --git a/capi-mediamuxer.manifest b/capi-mediamuxer.manifest
new file mode 100755 (executable)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/capi-mediamuxer.pc.in b/capi-mediamuxer.pc.in
new file mode 100755 (executable)
index 0000000..2d56d71
--- /dev/null
@@ -0,0 +1,13 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=@LIB_INSTALL_DIR@
+includedir=/usr/include/media
+
+Name: @PC_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @VERSION@
+Requires: @PC_REQUIRED@
+Libs: -L${libdir} @PC_LDFLAGS@
+Cflags: -I${includedir}
\ No newline at end of file
diff --git a/doc/mediamuxer_doc.h b/doc/mediamuxer_doc.h
new file mode 100755 (executable)
index 0000000..d955b47
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_DOC_H__
+#define __TIZEN_MEDIAMUXER_DOC_H__
+
+/**
+ * @file mediamuxer_doc.h
+ * @brief This file contains high level documentation of the CAPI MEDIAMUXER.
+ */
+
+/**
+ * @ingroup CAPI_MEDIA_FRAMEWORK
+ * @defgroup CAPI_MEDIAMUXER_MODULE Media Muxer
+ * @brief  The @ref CAPI_MEDIAMUXER_MODULE  APIs provides functions for muxing media data
+ *
+ * @section CAPI_MEDIAMUXER_MODULE_HEADER Required Header
+ *   \#include <mediamuxer.h>
+ *
+ * @section CAPI_MEDIAMUXER_MODULE_OVERVIEW Overview
+ *
+ * MEDIAMUXER API set allows :
+ * The API set allows one to directly access media muxer on device.
+ * Application can create, add relevent media track(s) and write corresponding
+ * samples to get muxed media files. mediamuxer takes encoded media as input
+ * and gives muxed media in a compatable container format.
+ *
+ * Typical Call Flow of mediamuxer APIs is:
+ * mediamuxer_create()
+ * mediamuxer_set_data_sink()
+ * mediamuxer_add_track(1)
+ * mediamuxer_add_track(2)     [add more tracks, if needed]
+ * mediamuxer_start()
+ * while()
+ *     if (is_track(1)_data_available)
+ *             mediamuxer_write_sample(track(1)),
+ *     else
+ *             mediamuxer_close_track(1)
+ *     if (is_track(2)_data_available)
+ *             mediamuxer_write_sample(track(2))
+ *     else
+ *             mediamuxer_close_track(2)
+ * mediamuxer_stop()
+ * mediamuxer_destroy()
+ */
+
+#endif  /* __TIZEN_MEDIAMUXER_DOC_H__ */
diff --git a/include/mediamuxer.h b/include/mediamuxer.h
new file mode 100755 (executable)
index 0000000..0a382b1
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_H__
+#define __TIZEN_MEDIAMUXER_H__
+
+#include <tizen.h>
+#include <stdint.h>
+#include <media_format.h>
+#include <media_packet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef TIZEN_ERROR_MEDIA_MUXER
+#define TIZEN_ERROR_MEDIA_MUXER -0x05000000
+#endif
+
+/**
+* @file mediamuxer.h
+* @brief This file contains the capi media muxer API.
+*/
+
+/**
+* @addtogroup CAPI_MEDIAMUXER_MODULE
+* @
+*/
+
+/**
+ * @brief Media Muxer handle type
+ * @since_tizen 3.0
+ */
+typedef struct mediamuxer_s *mediamuxer_h;
+
+/**
+ * @brief Enumeration for media muxer state
+ * @since_tizen 3.0
+ */
+typedef enum {
+       MEDIAMUXER_STATE_NONE,          /**< The mediamuxer is not created */
+       MEDIAMUXER_STATE_IDLE,          /**< The mediamuxer is created, but not prepared */
+       MEDIAMUXER_STATE_READY,         /**< The mediamuxer is ready to mux media */
+       MEDIAMUXER_STATE_MUXING,        /**< The mediamuxer is muxing media */
+       MEDIAMUXER_STATE_PAUSED         /**< The mediamuxer is paused while muxing media */
+} mediamuxer_state_e;
+
+/**
+ * @brief Enumeration for media muxer error
+ * @since_tizen 3.0
+ */
+typedef enum {
+       MEDIAMUXER_ERROR_NONE = TIZEN_ERROR_NONE,                                       /**< Successful */
+       MEDIAMUXER_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY,
+       MEDIAMUXER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER,             /**< Invalid parameter */
+       MEDIAMUXER_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION,             /**< Invalid operation */
+       MEDIAMUXER_ERROR_NOT_SUPPORTED  = TIZEN_ERROR_NOT_SUPPORTED,                     /**< Not supported */
+       MEDIAMUXER_ERROR_PERMISSION_DENIED  = TIZEN_ERROR_PERMISSION_DENIED,            /**< Permission denied */
+       MEDIAMUXER_ERROR_INVALID_STATE = TIZEN_ERROR_MEDIA_MUXER | 0x01,                /**< Invalid state */
+       MEDIAMUXER_ERROR_INVALID_PATH = TIZEN_ERROR_MEDIA_MUXER | 0x02,                 /**< Invalid path */
+       MEDIAMUXER_ERROR_RESOURCE_LIMIT = TIZEN_ERROR_MEDIA_MUXER | 0x03                /**< Resource limit */
+} mediamuxer_error_e;
+
+/**
+ * @brief Enumeration for media muxer output format
+ * @since_tizen 3.0
+ */
+typedef enum {
+       MEDIAMUXER_CONTAINER_FORMAT_MP4 = MEDIA_FORMAT_CONTAINER_MP4,       /**< The mediamuxer output format is MP4 container */
+} mediamuxer_output_format_e;
+
+/**
+ * @brief Called when error occurs in media muxer.
+ * @details Following error codes can be delivered.
+ *          #MEDIAMUXER_ERROR_INVALID_OPERATION,
+ *          #MEDIAMUXER_ERROR_NOT_SUPPORTED,
+ *          #MEDIAMUXER_ERROR_INVALID_PATH,
+ *          #MEDIAMUXER_ERROR_RESOURCE_LIMIT
+ * @since_tizen 3.0
+ * @param[in] error  The error that occurred in media muxer
+ * @param[in] user_data   The user data passed from the code where
+ *                         mediamuxer_set_error_cb() was invoked
+ *                         This data will be accessible from @a mediamuxer_error_cb
+ * @pre Create media muxer handle by calling mediamuxer_create() function.
+ * @see mediamuxer_set_error_cb()
+ * @see mediamuxer_unset_error_cb()
+ */
+typedef void (*mediamuxer_error_cb)(mediamuxer_error_e error, void *user_data);
+
+/**
+ * @brief Creates a media muxer handle for muxing.
+ * @since_tizen 3.0
+ * @param[out] muxer  A new handle to media muxer
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @post The media muxer state will be #MEDIAMUXER_STATE_IDLE.
+ * @see mediamuxer_destroy()
+ */
+int mediamuxer_create(mediamuxer_h *muxer);
+
+/**
+ * @brief Sets the sink path of output stream.
+ * @since_tizen 3.0
+ * @remarks The mediastorage privilege(http://tizen.org/privilege/mediastorage) should be added if any video/audio files are to be saved in the internal storage.
+ * @remarks The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are to be saved in the external storage.
+ * @param[in] muxer  A new handle to media muxer
+ * @param[in] path  The location of the output media file, such as the file path
+               This is the path at which the muxed file should be saved.
+ * @param[in] format  The format of the output media file
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIAMUXER_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MEDIAMUXER_ERROR_INVALID_PATH Invalid path
+ * @pre The media muxer state will be #MEDIAMUXER_STATE_IDLE by calling mediamuxer_create
+ * @see #mediamuxer_output_format_e
+ */
+int mediamuxer_set_data_sink(mediamuxer_h muxer, char *path, mediamuxer_output_format_e format);
+
+/**
+ * @brief Adds the media track of interest to the muxer handle.
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @param[in] media_format  The format of media muxer
+ * @param[out] track_index  The index of the media track
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media muxer state must be set to #MEDIAMUXER_STATE_IDLE.
+ * @see #media_format_h
+ * @see mediamuxer_create()
+ * @see mediamuxer_start()
+ * */
+int mediamuxer_add_track(mediamuxer_h muxer, media_format_h media_format, int *track_index);
+
+/**
+ * @brief Starts the media muxer.
+ * @remarks Initiates the necessary parameters, and keeps the muxer ready for writing data.
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media muxer state must be set to #MEDIAMUXER_STATE_IDLE.
+ * @post The media muxer state will be #MEDIAMUXER_STATE_READY.
+ * @see mediamuxer_create()
+ * @see mediamuxer_stop()
+ * */
+int mediamuxer_start(mediamuxer_h muxer);
+
+/**
+ * @brief Writes the media packet of interest to the muxer handle.
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @param[in] track_index  The index of the media track
+ * @param[in] inbuf  The packet of media muxer
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media muxer state must be set to #MEDIAMUXER_STATE_READY by calling mediamuxer_start() or
+ *      set to #MEDIAMUXER_STATE_PAUSED by calling mediamuxer_pause().
+ * @post The media muxer state will be #MEDIAMUXER_STATE_MUXING.
+ * @see mediamuxer_start()
+ * @see mediamuxer_close_track()
+ * @see mediamuxer_pause()
+ * @see #media_packet_h
+ * */
+int mediamuxer_write_sample(mediamuxer_h muxer, int track_index, media_packet_h inbuf);
+
+/**
+ * @brief Closes the track from further writing of data.
+ * @remarks For each added track, user needs to call this API to indicate the end of stream.
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @param[in] track_index the selected track index
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media muxer state must be set to #MEDIAMUXER_STATE_MUXING.
+ * @see mediamuxer_write_sample()
+ * @see mediamuxer_pause()
+ * @see mediamuxer_stop()
+ * @see #mediamuxer_error_e
+ * */
+int mediamuxer_close_track(mediamuxer_h muxer, int track_index);
+
+/**
+ * @brief Pauses the media muxer.
+ * @remarks To temporarily disable writing data for muxing. This API pauses a playing muxer
+               If the prior state of the muxer is not in PLAYING, no action will be taken.
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media muxer state must be set to #MEDIAMUXER_STATE_MUXING.
+ * @post The media muxer state will be #MEDIAMUXER_STATE_PAUSED.
+ * @see mediamuxer_write_sample()
+ * @see mediamuxer_resume()
+ * */
+int mediamuxer_pause(mediamuxer_h muxer);
+
+/**
+ * @brief Resumes the media muxer.
+ * @remarks Make it ready for any further writing. This API will resume a paused muxer.
+               If the prior state of the muxer is not playing, no action will be taken.
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media muxer state must be set to #MEDIAMUXER_STATE_PAUSED.
+ * @post The media muxer state will be #MEDIAMUXER_STATE_MUXING.
+ * @see mediamuxer_pause()
+ * */
+int mediamuxer_resume(mediamuxer_h muxer);
+
+/**
+ * @brief Stops the media muxer.
+ * @remarks Unrefs the variables created after calling mediamuxer_start().
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media muxer state must be set to #MEDIAMUXER_STATE_MUXING by calling mediamuxer_start() or
+ *      set to #MEDIAMUXER_STATE_PAUSED by calling mediamuxer_pause().
+ * @post The media muxer state will be #MEDIAMUXER_STATE_IDLE.
+ * @see mediamuxer_write_sample()
+ * @see mediamuxer_pause()
+ * @see mediamuxer_destroy()
+ * */
+int mediamuxer_stop(mediamuxer_h muxer);
+
+/**
+ * @brief Removes the instance of media muxer and clear all its context memory.
+ * @since_tizen 3.0
+ * @param[in] muxer     The media muxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre Create a media muxer handle by calling mediamuxer_create() function.
+ * @post The media muxer state will be #MEDIAMUXER_STATE_NONE.
+ * @see mediamuxer_create()
+ * */
+int mediamuxer_destroy(mediamuxer_h muxer);
+
+/**
+ * @brief Gets media muxer state.
+ * @since_tizen 3.0
+ * @param[in] muxer   The media muxer handle
+ * @param[out] state   The media muxer sate
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIAMUXER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media muxer handle by calling mediamuxer_create() function.
+ * @see #mediamuxer_state_e
+ * */
+int mediamuxer_get_state(mediamuxer_h muxer, mediamuxer_state_e *state);
+
+/**
+ * @brief Registers a error callback function to be invoked when an error occurs.
+ * @details Following error codes can be delivered.
+ *          #MEDIAMUXER_ERROR_INVALID_OPERATION,
+ *          #MEDIAMUXER_ERROR_NOT_SUPPORTED,
+ *          #MEDIAMUXER_ERROR_INVALID_PATH,
+ *          #MEDIAMUXER_ERROR_RESOURCE_LIMIT
+ * @since_tizen 3.0
+ * @param[in] muxer   The media muxer handle
+ * @param[in] callback  Callback function pointer
+ * @param[in] user_data   The user data passed from the code where
+ *                         mediamuxer_set_error_cb() was invoked
+ *                         This data will be accessible from @a mediamuxer_error_cb
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media muxer handle by calling mediamuxer_create() function.
+ * @post mediamuxer_error_cb() will be invoked.
+ * @see mediamuxer_unset_error_cb()
+ * @see mediamuxer_error_cb()
+ * */
+int mediamuxer_set_error_cb(mediamuxer_h muxer, mediamuxer_error_cb callback, void* user_data);
+
+/**
+ * @brief Unregisters the error callback function.
+ * @since_tizen 3.0
+ * @param[in] muxer   The media muxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIAMUXER_ERROR_NONE Successful
+ * @retval #MEDIAMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see mediamuxer_error_cb()
+ * */
+int mediamuxer_unset_error_cb(mediamuxer_h muxer);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_H__ */
diff --git a/include/mediamuxer_error.h b/include/mediamuxer_error.h
new file mode 100755 (executable)
index 0000000..bad4cc7
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_ERROR_H__
+#define __TIZEN_MEDIAMUXER_ERROR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**< Definition of number describing error group */
+#define MX_ERROR_CLASS              0x80000000
+/**< Category for describing common error group */
+#define MX_ERROR_COMMON_CLASS       0x80000100
+/**< Category for describing gst_port error group */
+#define MX_ERROR_GST_PORT_CLASS     0x80000200
+/**< Category for describing ffmpeg port error group */
+#define MX_ERROR_FFMPEG_PORT_CLASS  0x80000300
+/**< Category for describing custom error group */
+#define MX_ERROR_CUSTOM_PORT_CLASS       0x80000400
+
+/*
+   MX_ERROR_CLASS
+ */
+/**< Unclassified error */
+#define MX_ERROR_UNKNOWN            (MX_ERROR_CLASS | 0x00)
+/**< Invalid argument */
+#define MX_ERROR_INVALID_ARGUMENT       (MX_ERROR_CLASS | 0x01)
+/**< Out of memory */
+#define MX_ERROR_OUT_OF_MEMORY          (MX_ERROR_CLASS | 0x02)
+/**< Out of storage */
+#define MX_ERROR_OUT_OF_STORAGE         (MX_ERROR_CLASS | 0x03)
+/**< Invalid handle */
+#define MX_ERROR_INVALID_HANDLE         (MX_ERROR_CLASS | 0x04)
+/**< Cannot find file */
+#define MX_ERROR_FILE_NOT_FOUND         (MX_ERROR_CLASS | 0x05)
+/**< Fail to read data from file */
+#define MX_ERROR_FILE_READ          (MX_ERROR_CLASS | 0x06)
+/**< Fail to write data to file */
+#define MX_ERROR_FILE_WRITE         (MX_ERROR_CLASS | 0x07)
+/**< End of file */
+#define MX_ERROR_END_OF_FILE        (MX_ERROR_CLASS | 0x08)
+/**< Not supported API*/
+#define MX_ERROR_NOT_SUPPORT_API        (MX_ERROR_CLASS | 0x09)
+/**< port regitstration failed error */
+#define MX_ERROR_PORT_REG_FAILED        (MX_ERROR_CLASS | 0x0a)
+
+/*
+   MX_ERROR_COMMON_CLASS
+ */
+/**< Invalid argument */
+#define MX_ERROR_COMMON_INVALID_ARGUMENT    (MX_ERROR_COMMON_CLASS | 1)
+/**< Out of storage */
+#define MX_ERROR_COMMON_NO_FREE_SPACE       (MX_ERROR_COMMON_CLASS | 2)
+/**< Out of memory */
+#define MX_ERROR_COMMON_OUT_OF_MEMORY       (MX_ERROR_COMMON_CLASS | 3)
+/**< Unknown error */
+#define MX_ERROR_COMMON_UNKNOWN             (MX_ERROR_COMMON_CLASS | 4)
+/**< Invalid argument */
+#define MX_ERROR_COMMON_INVALID_ATTRTYPE    (MX_ERROR_COMMON_CLASS | 5)
+/**< Invalid permission */
+#define MX_ERROR_COMMON_INVALID_PERMISSION  (MX_ERROR_COMMON_CLASS | 6)
+/**< Out of array */
+#define MX_ERROR_COMMON_OUT_OF_ARRAY        (MX_ERROR_COMMON_CLASS | 7)
+/**< Out of value range*/
+#define MX_ERROR_COMMON_OUT_OF_RANGE        (MX_ERROR_COMMON_CLASS | 8)
+/**< Attribute doesn't exist. */
+#define MX_ERROR_COMMON_ATTR_NOT_EXIST      (MX_ERROR_COMMON_CLASS | 9)
+
+/*
+ *      MX_ERROR_GST_PORT_CLASS
+ */
+/**< GST Port  instance is not initialized */
+#define MX_ERROR_GST_PORT_NOT_INITIALIZED   (MX_ERROR_GST_PORT_CLASS | 0x01)
+
+/*
+   MX_ERROR_FFMPEG_PORT_CLASS
+ */
+/**< FFMPEG Port instance is not initialized */
+#define MX_ERROR_FFMPEG_PORT_NOT_INITIALIZED (MX_ERROR_FFMPEG_PORT_CLASS | 0x01)
+
+/*
+   MX_ERROR_CUSTOM_PORT_CLASS
+ */
+/**< CUSTOM Port instance is not initialized */
+#define MX_ERROR_CUSTOM_PORT_NOT_INITIALIZED  MX_ERROR_CUSTOM_PORT_CLASS | 0x01)
+
+typedef enum {
+       MX_ERROR_NONE = 0,
+       MX_ERROR = -1,                  /**< muxer happens error */
+       MX_MEMORY_ERROR = -2,           /**< muxer memory is not enough */
+       MX_PARAM_ERROR = -3,            /**< muxer parameter is error */
+       MX_INVALID_ARG = -4,            /**< muxer has invalid arguments */
+       MX_PERMISSION_DENIED = -5,
+       MX_INVALID_STATUS = -6,         /**< muxer works at invalid status */
+       MX_NOT_SUPPORTED = -7,          /**< muxer can't support this specific video format */
+       MX_INVALID_IN_BUF = -8,
+       MX_INVALID_OUT_BUF = -9,
+       MX_INTERNAL_ERROR = -10,
+       MX_HW_ERROR = -11,              /**< muxer happens hardware error */
+       MX_NOT_INITIALIZED = -12,
+       MX_INVALID_STREAM = -13,
+       MX_OUTPUT_BUFFER_EMPTY = -14,
+       MX_OUTPUT_BUFFER_OVERFLOW = -15,/**< muxer output buffer is overflow */
+       MX_MEMORY_ALLOCED = -16,        /**< muxer has got memory and can decode one frame */
+       MX_COURRPTED_INI = -17,         /**< value in the ini file is not valid */
+} mx_ret_e;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_ERROR_H__ */
diff --git a/include/mediamuxer_ini.h b/include/mediamuxer_ini.h
new file mode 100755 (executable)
index 0000000..b493d26
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_INI_H__
+#define __TIZEN_MEDIAMUXER_INI_H__
+
+#include <glib.h>
+#include <mm_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MEDIAMUXER_INI_DEFAULT_PATH   "/usr/etc/mmfw_mediamuxer.ini"
+#define MEDIAMUXER_INI_MAX_STRLEN     100
+#define DEFAULT_PORT "GST_PORT"
+
+/* NOTE : following content should be same with above default values */
+/* FIXIT : need smarter way to generate default ini file. */
+/* FIXIT : finally, it should be an external file */
+#define MEDIAMUXER_DEFAULT_INI \
+       "\
+[general] \n\
+\n\
+;Add general config parameters here\n\
+\n\
+\n\
+\n\
+[port_in_use] \n\
+\n\
+;mediamuxer_port = GST_PORT \n\
+;mediamuxer_port = FFMPEG_PORT \n\
+;mediamuxer_port = CUSTOM_PORT \n\
+mediamuxer_port = GST_PORT \n\
+\n\
+[gst_port] \n\
+\n\
+;Add gst port specific config paramters here\n\
+\n\
+\n\
+[ffmpeg_port] \n\
+\n\
+;Add ffmpeg port specific config paramters here\n\
+\n\
+\n\
+[custom_port] \n\
+\n\
+;Add custom port specific config paramters here\n\
+\n\
+\n\
+\n\
+"
+
+typedef enum {
+       GST_PORT = 0,
+       FFMPEG_PORT,
+       CUSTOM_PORT,
+} port_mode;
+
+/* @ mark means the item has tested */
+typedef struct __mx_ini {
+       port_mode port_type;
+       /* general */
+       gchar port_name[MEDIAMUXER_INI_MAX_STRLEN];
+} mx_ini_t;
+
+int mx_ini_load(mx_ini_t *ini);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__TIZEN_MEDIAMUXER_INI_H__*/
diff --git a/include/mediamuxer_port.h b/include/mediamuxer_port.h
new file mode 100755 (executable)
index 0000000..191aaf7
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_PORT_H__
+#define __TIZEN_MEDIAMUXER_PORT_H__
+
+/*=============================================================================
+|                                                                              |
+|  INCLUDE FILES                                                               |
+|                                                                              |
+==============================================================================*/
+
+#include <glib.h>
+#include <mm_types.h>
+#include <mm_message.h>
+#include <mediamuxer_util.h>
+#include <mediamuxer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+    @addtogroup MEDIAMUXER
+    @{
+
+    @par
+    This part describes APIs used for playback of multimedia contents.
+    All multimedia contents are created by a media muxer through handle of
+    playback. In creating a muxer, it displays the muxer's status or information
+    by registering callback function.
+
+    @par
+    In case of streaming playback, network has to be opend by using datanetwork
+    API. If proxy, cookies and the other attributes for streaming playback are
+    needed, set those attributes using mx_set_attribute() before create muxer.
+
+    @par
+    The subtitle for local video playback is supported. Set "subtitle_uri"
+    attribute using mx_set_attribute() before the application creates the muxer.
+    Then the application could receive MMMessageParamType which includes
+    subtitle string and duration.
+
+    @par
+    MediaMuxer can have 5 states, and each state can be changed by calling
+    described functions on "Figure1. State of MediaMuxer".
+
+    @par
+    @image html         muxer_state.jpg "Figure1. State of MediaMuxer" width=12cm
+    @image latex muxer_state.jpg "Figure1. State of MediaMuxer"        width=12cm
+
+    @par
+    Most of functions which change muxer state work as synchronous. But,
+    mx_start() should be used asynchronously. Both mx_pause() and mx__resume()
+    should also be used asynchronously in the case of streaming data.
+    So, application have to confirm the result of those APIs through message
+    callback function.
+
+    @par
+    Note that "None" and Null" state could be reached from any state
+    by calling mx_destroy() and mx_unrealize().
+
+    @par
+    <div><table>
+    <tr>
+    <td><B>FUNCTION</B></td>
+    <td><B>PRE-STATE</B></td>
+    <td><B>POST-STATE</B></td>
+    <td><B>SYNC TYPE</B></td>
+    </tr>
+    <tr>
+    <td>mx_create()</td>
+    <td>NONE</td>
+    <td>NULL</td>
+    <td>SYNC</td>
+    </tr>
+    <tr>
+    <td>mx_destroy()</td>
+    <td>NULL</td>
+    <td>NONE</td>
+    <td>SYNC</td>
+    </tr>
+    <tr>
+    <td>mx_set_data_sink()</td>
+    <td>NULL</td>
+    <td>READY</td>
+    <td>SYNC</td>
+    </tr>
+    </table></div>
+
+    @par
+    Following are the attributes supported in muxer which may be set after
+    initialization. Those are handled as a string.
+
+    @par
+    <div><table>
+    <tr>
+    <td>PROPERTY</td>
+    <td>TYPE</td>
+    <td>VALID TYPE</td>
+    </tr>
+    <tr>
+    <td>"profile_uri"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"content_duration"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"content_video_width"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"content_video_height"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"profile_user_param"</td>
+    <td>data</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"profile_play_count"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"streaming_type"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"streaming_udp_timeout"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"streaming_user_agent"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"streaming_wap_profile"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"streaming_network_bandwidth"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"streaming_cookie"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"streaming_proxy_ip"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"streaming_proxy_port"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"subtitle_uri"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    </table></div>
+
+    @par
+    Following attributes are supported for playing stream data. Those value can
+    be readable only and valid after starting playback.
+    Please use mm_fileinfo for local playback.
+
+    @par
+    <div><table>
+    <tr>
+    <td>PROPERTY</td>
+    <td>TYPE</td>
+    <td>VALID TYPE</td>
+    </tr>
+    <tr>
+    <td>"content_video_found"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"content_video_codec"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"content_video_track_num"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"content_audio_found"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"content_audio_codec"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"content_audio_bitrate"</td>
+    <td>int</td>
+    <td>array</td>
+    </tr>
+    <tr>
+    <td>"content_audio_channels"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"content_audio_samplerate"</td>
+    <td>int</td>
+    <td>array</td>
+    </tr>
+    <tr>
+    <td>"content_audio_track_num"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"content_text_track_num"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    <tr>
+    <td>"tag_artist"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_title"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_album"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_genre"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_author"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_copyright"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_date"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_description"</td>
+    <td>string</td>
+    <td>N/A</td>
+    </tr>
+    <tr>
+    <td>"tag_track_num"</td>
+    <td>int</td>
+    <td>range</td>
+    </tr>
+    </table></div>
+
+ */
+
+/*=============================================================================|
+|                                                                              |
+|  GLOBAL DEFINITIONS AND DECLARATIONS                                         |
+|                                                                              |
+==============================================================================*/
+/**
+ * @brief Called when error occurs in media muxer.
+ * @details Following error codes can be delivered.
+ *          #MEDIAMUXER_ERROR_INVALID_OPERATION,
+ *          #MEDIAMUXER_ERROR_NOT_SUPPORTED,
+ *          #MEDIAMUXER_ERROR_INVALID_PATH,
+ *          #MEDIAMUXER_ERROR_RESOURCE_LIMIT
+ * @since_tizen 3.0
+ * @param[in] error  The error that occurred in media muxer
+ * @param[in] user_data   The user data passed from the code where
+ *                         mediamuxer_set_error_cb() was invoked
+ *                         This data will be accessible from @a mediamuxer_error_cb
+ * @pre Create media muxer handle by calling mediamuxer_create() function.
+ * @see mediamuxer_set_error_cb()
+ * @see mediamuxer_unset_error_cb()
+ */
+typedef void (*mx_error_cb)(mediamuxer_error_e error, void *user_data);
+
+/**
+ * Attribute validity structure
+ */
+typedef struct _media_port_muxer_ops {
+       unsigned int n_size;
+       int (*init)(MMHandleType *pHandle);
+       /* Add new ops at the end of structure, no order change */
+       int (*set_data_sink)(MMHandleType pHandle, char *uri, mediamuxer_output_format_e format);
+       int (*add_track)(MMHandleType pHandle, media_format_h media_format, int *track_index);
+       int (*start)(MMHandleType pHandle);
+       int (*write_sample)(MMHandleType pHandle, int track_index, media_packet_h inbuf);
+       int (*close_track)(MMHandleType pHandle, int track_index);
+       int (*pause)(MMHandleType pHandle);
+       int (*resume)(MMHandleType pHandle);
+       int (*stop)(MMHandleType pHandle);
+       int (*destroy)(MMHandleType pHandle);
+       int (*set_error_cb)(MMHandleType pHandle, mx_error_cb callback, void* user_data);
+} media_port_muxer_ops;
+
+/*=============================================================================
+|                                                                              |
+|  GLOBAL FUNCTION PROTOTYPES                                                  |
+|                                                                              |
+==============================================================================*/
+
+/**
+ * This function creates a muxer object for parsing multimedia contents. \n
+ * The attributes of muxer are created to get/set some values with application.
+ * And, proper port is selected to do the actual parsing of the mdia.
+ *
+ * @param   muxer [out]   Handle of muxer
+ * @param   op_uri        uri at which muxed file should be stored
+ * @param   format        container format of the muxed data
+ *
+ * @return  This function returns zero on success, or negative value with error
+ *          code. Please refer 'mx_error.h' to know it in detail.
+ *
+ * @par Example
+ * @code
+  mx_create(&muxer, char *op_uri, mediamuxer_output_format_e format);
+  ...
+  mx_destroy(&muxer);
+ * @endcode
+ */
+int mx_create(MMHandleType *muxer);
+
+/**
+ * This function sets the input data source to parse. \n
+ * The source can be a local file or remote
+ *
+ * @param   muxer      Handle of muxer
+ * @param   uri        uri at which muxed file should be stored
+ * @param   format     container format of the muxed data
+ *
+ * @return  This function returns zero on success, or negative value with error
+ *          code. Please refer 'mx_error.h' to know it in detail.
+ *
+ * @par Example
+ * @code
+    if (mx_set_data_sink(muxer, uri, format) != MM_ERROR_NONE)
+       {
+               MX_E("failed to set the source \n");
+       }
+ * @endcode
+ */
+int mx_set_data_sink(MMHandleType muxer, char *uri, mediamuxer_output_format_e format);
+
+/**
+ * This function releases muxer object and all resources which were created by
+ *     mx_create(). And, muxer handle will also be destroyed.
+ *
+ * @param   muxer     [in]    Handle of muxer
+ *
+ * @return  This function returns zero on success, or negative value with error
+ *             code.
+ * @see     mx_destroy
+ *
+ * @par Example
+ * @code
+if (mx_destroy(g_muxer) != MM_ERROR_NONE)
+{
+    MX_E("failed to destroy muxer\n");
+}
+ * @endcode
+ */
+int mx_destroy(MMHandleType muxer);
+
+/**
+ * This function starts/prepares the muxer object. \n
+ * For GST-port, this function creates necessary gst elemetns
+ *
+ * @param   muxer     [in]    Handle of muxer
+ *
+ * @return  This function returns zero on success, or negative value with error
+               code.
+ * @see     mx_create
+ *
+ * @par Example
+ * @code
+if (mx_start(g_muxer) != MX_ERROR_NONE)
+{
+    MX_E("failed to start muxer\n");
+}
+ * @endcode
+ */
+int mx_start(MMHandleType muxer);
+
+/**
+ * This function adds Audio/Vidoe/Subtitle track in muxer handle \n
+ *
+ * @param   muxer     [in]    Handle of muxer
+ *          media_format  [in]   media format of A/V/S
+ *          track_index  [out]   index of the media track
+ *
+ * @return  This function returns zero on success, or negative value with error
+               code.
+ * @see     mx_create
+ *
+ * @par Example
+ * @code
+if (mx_add_track(g_muxer,media_format,&track_index) != MX_ERROR_NONE)
+{
+    MX_E("failed to add track to muxer handle\n");
+}
+ * @endcode
+ */
+int mx_add_track(MMHandleType muxer, media_format_h media_format, int *track_index);
+
+/**
+ * This function writes Audio/Vidoe/Subtitle track to file using muxer handle \n
+ *
+ * @param   muxer     [in]    Handle of muxer
+ *          track_index       index of the media track
+ *         inbuf            buffer to be muxed
+ *
+ * @return  This function returns zero on success, or negative value with error
+               code.
+ * @see     mx_write_sample
+ *
+ * @par Example
+ * @code
+if (mx_write_sample(g_muxer,track_id, inbuf) != MX_ERROR_NONE)
+{
+    MX_E("failed to write sample\n");
+}
+ * @endcode
+ */
+int mx_write_sample(MMHandleType mediamuxer, int track_index, media_packet_h inbuf);
+
+/**
+ * This function close the selected track. \n
+ * For GST-port, this function send the eos to the specific appsrc element
+ *
+ * @param   muxer     [in]    Handle of muxer
+ * @param   track_index [in]  selected track
+ *
+ * @return  This function returns zero on success, or negative value with error
+                code.
+ * @see     mx_stop
+ *
+ * @par Example
+ * @code
+if (mx_close_track(g_muxer,1) != MX_ERROR_NONE)
+{
+    MX_E("failed to close audio track\n");
+}
+ * @endcode
+ */
+int mx_close_track(MMHandleType mediamuxer, int track_index);
+
+/**
+ * This function stops/un-prepares the muxer object. \n
+ * For GST-port, this function unrefs necessary gst elemetns
+ *
+ * @param   muxer     [in]    Handle of muxer
+ *
+ * @return  This function returns zero on success, or negative value with error
+               code.
+ * @see     mx_stop
+ *
+ * @par Example
+ * @code
+if (mx_stop(g_muxer) != MX_ERROR_NONE)
+{
+    MX_E("failed to stop muxer\n");
+}
+ * @endcode
+ */
+int mx_stop(MMHandleType mediamuxer);
+
+/**
+ * This function pauses the muxing operation. \n
+ * For GST-port, this function pauses the pipeline
+ *
+ * @param   muxer     [in]    Handle of muxer
+ *
+ * @return  This function returns zero on success, or negative value with error
+               code.
+ * @see     mx_resume
+ *
+ * @par Example
+ * @code
+if (mx_pause(g_muxer) != MX_ERROR_NONE)
+{
+    MX_E("failed to pause muxer\n");
+}
+ * @endcode
+ */
+int mx_pause(MMHandleType mediamuxer);
+
+/**
+ * This function resumes the muxing operation. \n
+ * For GST-port, this function sets the pipeline back to playing
+ *
+ * @param   muxer     [in]    Handle of muxer
+ *
+ * @return  This function returns zero on success, or negative value with error
+               code.
+ * @see     mx_pause
+ *
+ * @par Example
+ * @code
+if (mx_resume(g_muxer) != MX_ERROR_NONE)
+{
+    MX_E("failed to resume muxer\n");
+}
+ * @endcode
+ */
+int mx_resume(MMHandleType mediamuxer);
+
+/**
+ * This function is to set error call back function
+ *
+ * @param   muxer       [in]    Handle of muxer
+ * @param   callback    [in]    call back function pointer
+ * @param   user_data   [in]    user specific data pointer
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ */
+int mx_set_error_cb(MMHandleType muxer,        mediamuxer_error_cb callback, void* user_data);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_PORT_H__ */
diff --git a/include/mediamuxer_private.h b/include/mediamuxer_private.h
new file mode 100755 (executable)
index 0000000..479d4e6
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_PRIVATE_H__
+#define __TIZEN_MEDIAMUXER_PRIVATE_H__
+#include <mediamuxer.h>
+#include <mediamuxer_port.h>
+#include <mediamuxer_ini.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "TIZEN_N_MEDIAMUXER"
+
+#define MUXER_CHECK_CONDITION(condition,error,msg)     \
+       do \
+       { \
+               if (condition) {} else \
+                       { MX_E("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
+       }while(0)
+
+#define MUXER_INSTANCE_CHECK(muxer)   \
+       MUXER_CHECK_CONDITION(muxer != NULL, \
+                             MEDIAMUXER_ERROR_INVALID_PARAMETER,"MUXER_ERROR_INVALID_PARAMETER")
+
+#define MUXER_STATE_CHECK(muxer,expected_state)       \
+       MUXER_CHECK_CONDITION(muxer->state == expected_state, \
+                             MEDIAMUXER_ERROR_INVALID_STATE,"MUXER_ERROR_INVALID_STATE")
+
+#define MUXER_NULL_ARG_CHECK(arg)      \
+       MUXER_CHECK_CONDITION(arg != NULL,MEDIAMUXER_ERROR_INVALID_PARAMETER, \
+                             "MUXER_ERROR_INVALID_PARAMETER")
+
+/**
+ * @brief Enumerations of media muxer state
+ * @since_tizen 3.0
+ */
+
+int _convert_error_code(int code, char *func_name);
+
+typedef enum {
+       MEDIAMUXER_EVENT_TYPE_PREPARE,
+       MEDIAMUXER_EVENT_TYPE_COMPLETE,
+       MEDIAMUXER_EVENT_TYPE_INTERRUPT,
+       MEDIAMUXER_EVENT_TYPE_ERROR,
+       MEDIAMUXER_EVENT_TYPE_BUFFERING,
+       MEDIAMUXER_EVENT_TYPE_SUBTITLE,
+       MEDIAMUXER_EVENT_TYPE_CLOSED_CAPTION,
+       MEDIAMUXER_EVENT_TYPE_CAPTURE,
+       MEDIAMUXER_EVENT_TYPE_SEEK,
+       MEDIAMUXER_EVENT_TYPE_VIDEO_FRAME,
+       MEDIAMUXER_EVENT_TYPE_AUDIO_FRAME,
+       MEDIAMUXER_EVENT_TYPE_VIDEO_FRAME_RENDER_ERROR,
+       MEDIAMUXER_EVENT_TYPE_PD,
+       MEDIAMUXER_EVENT_TYPE_SUPPORTED_AUDIO_EFFECT,
+       MEDIAMUXER_EVENT_TYPE_SUPPORTED_AUDIO_EFFECT_PRESET,
+       MEDIAMUXER_EVENT_TYPE_MISSED_PLUGIN,
+       MEDIAMUXER_EVENT_TYPE_IMAGE_BUFFER,
+       MEDIAMUXER_EVENT_TYPE_OTHERS,
+       MEDIAMUXER_EVENT_TYPE_NUM
+} mediamuxer_event_e;
+
+typedef struct _mediamuxer_s {
+       MMHandleType mx_handle;
+       const void *user_cb[MEDIAMUXER_EVENT_TYPE_NUM];
+       void *user_data[MEDIAMUXER_EVENT_TYPE_NUM];
+       void *display_handle;
+       int state;
+       bool is_set_pixmap_cb;
+       bool is_stopped;
+       bool is_display_visible;
+       bool is_progressive_download;
+       pthread_t prepare_async_thread;
+       mediamuxer_error_cb error_cb;
+       void* error_cb_userdata;
+       mediamuxer_state_e muxer_state;
+} mediamuxer_s;
+
+typedef struct {
+       /* initialize values */
+       media_port_muxer_ops *muxer_ops;
+       /* initialize values */
+       mx_ini_t ini;
+       /* port specific handle */
+       MMHandleType mxport_handle;
+} mx_handle_t;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_PRIVATE_H__ */
diff --git a/include/mediamuxer_util.h b/include/mediamuxer_util.h
new file mode 100755 (executable)
index 0000000..95c1030
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_UTIL_H__
+#define __TIZEN_MEDIAMUXER_UTIL_H__
+
+#include <glib.h>
+#include <mediamuxer_ini.h>
+#include <mm_types.h>
+#include <mm_error.h>
+#include <mm_message.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define PRINT_ON_CONSOLE
+#ifdef PRINT_ON_CONSOLE
+#include <stdlib.h>
+#include <stdio.h>
+#define PRINT_F          g_print
+#define MX_FENTER();     PRINT_F("function:[%s] ENTER\n",__func__);
+#define MX_FLEAVE();     PRINT_F("function [%s] LEAVE\n",__func__);
+#define MX_C             PRINT_F
+#define MX_E             PRINT_F
+#define MX_W             PRINT_F
+#define MX_I             PRINT_F
+#define MX_L             PRINT_F
+#define MX_V             PRINT_F
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#define MX_FENTER();     LOGI("function:[%s] ENTER\n",__func__);
+#define MX_FLEAVE();     LOGI("function [%s] LEAVE\n",__func__);
+#define MX_C             LOGE  /*MMF_DEBUG_LEVEL_0 */
+#define MX_E             LOGE  /*MMF_DEBUG_LEVEL_1 */
+#define MX_W             LOGW  /*MMF_DEBUG_LEVEL_2 */
+#define MX_I             LOGI  /*MMF_DEBUG_LEVEL_3 */
+#define MX_L             LOGI  /*MMF_DEBUG_LEVEL_4 */
+#define MX_V             LOGV  /*MMF_DEBUG_LEVEL_5 */
+#define MX_F             LOGF  /*MMF_DEBUG_LEVEL_6 */
+#endif
+
+/* general */
+#define MEDIAMUXER_FREEIF(x) \
+       do \
+       { \
+               if ( x ) \
+                       g_free( x ); \
+               x = NULL; \
+       }while(0)
+
+#if 1
+#define MEDIAMUXER_FENTER();              MX_FENTER();
+#define MEDIAMUXER_FLEAVE();              MX_FLEAVE();
+#else
+#define MEDIAMUXER_FENTER();
+#define MEDIAMUXER_FLEAVE();
+#endif
+
+#define MEDIAMUXER_CHECK_NULL( x_var ) \
+       do \
+       { \
+               if ( ! x_var ) \
+               { \
+                       MX_E("[%s] is NULL\n", #x_var ); \
+                       goto ERROR; \
+               } \
+       } while (0)
+#define MEDIAMUXER_CHECK_SET_AND_PRINT( x_var, x_cond, ret, ret_val, err_text )\
+       do \
+       { \
+               if ( x_var != x_cond ) \
+               { \
+                       ret = ret_val; \
+                       MX_E("%s\n", #err_text ); \
+                       goto ERROR; \
+               } \
+       } while (0)
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_UTIL_H__ */
diff --git a/include/port_custom/mediamuxer_port_custom.h b/include/port_custom/mediamuxer_port_custom.h
new file mode 100755 (executable)
index 0000000..7739f91
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_PORT_CUSTOM_H__
+#define __TIZEN_MEDIAMUXER_PORT_CUSTOM_H__
+
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Place holder */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_PORT_CUSTOM_H__ */
diff --git a/include/port_ffmpeg/mediamuxer_port_ffmpeg.h b/include/port_ffmpeg/mediamuxer_port_ffmpeg.h
new file mode 100755 (executable)
index 0000000..2ae9320
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_PORT_FFMPEG_H__
+#define __TIZEN_MEDIAMUXER_PORT_FFMPEG_H__
+
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Place holder */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_PORT_FFMPEG_H__ */
diff --git a/include/port_gst/mediamuxer_port_gst.h b/include/port_gst/mediamuxer_port_gst.h
new file mode 100755 (executable)
index 0000000..189fdb0
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015 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_MEDIAMUXER_PORT_GST_H__
+#define __TIZEN_MEDIAMUXER_PORT_GST_H__
+
+#include <tizen.h>
+#include <gst/gst.h>
+#include <gst/gstelement.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/video/video-format.h>
+
+#define MEDIAMUXER_ELEMENT_SET_STATE( x_element, x_state ) \
+       MX_I("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) ) \
+       { \
+               MX_E("failed to set state %s to %s\n", #x_state, GST_ELEMENT_NAME( x_element )); \
+               goto STATE_CHANGE_FAILED; \
+       }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+       _GST_EVENT_TYPE_COMPLETE,
+       _GST_EVENT_TYPE_ERROR,
+       _GST_EVENT_TYPE_EOS,
+       _GST_EVENT_TYPE_NUM
+} _gst_event_e;
+
+/* GST port Private data */
+typedef struct _mx_gst_track {
+       void *media_format;
+       char *caps;
+       int track_index;
+       int start_feed;
+       int stop_feed;
+} mx_gst_track;
+
+typedef struct _mxgst_handle_t {
+       void *hmux;                     /**< mux handle */
+       int state;                      /**< mx current state */
+       bool is_prepared;
+
+       mx_gst_track video_track;
+       mx_gst_track audio_track;
+
+       mediamuxer_output_format_e muxed_format;
+       char *output_uri;
+       bool eos_flg;
+       guint bus_watch_id;
+       GstElement *pipeline;
+       GstElement *audio_appsrc;               /* Input audio buffers to be muxed */
+       GstElement *video_appsrc;               /* Input video buffers to be muxed */
+       GstElement *audioparse;
+       GstElement *videoparse;
+       GstElement *muxer;
+       GstElement *sink;                       /* sink for the muxed output */
+       char *saveLocation;                     /* Save path for muxed data */
+       void* user_cb[_GST_EVENT_TYPE_NUM];     /* for user cb */
+       void* user_data[_GST_EVENT_TYPE_NUM];
+} mxgst_handle_t;
+
+/**
+ * @brief Called when the error has occured.
+ * @remarks It will be invoked when the error has occured.
+ * @since_tizen 3.0
+ * @param[in] error_code  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 user register this callback using mediamuxer_set_error_cb().
+ * @see mediamuxer_set_error_cb()
+ * @see mediamuxer_unset_error_cb()
+ */
+typedef void (*gst_error_cb)(mediamuxer_error_e error, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIAMUXER_PORT_GST_H__ */
diff --git a/packaging/capi-mediamuxer.spec b/packaging/capi-mediamuxer.spec
new file mode 100755 (executable)
index 0000000..9816fd8
--- /dev/null
@@ -0,0 +1,80 @@
+Name:       capi-mediamuxer
+Summary:    A Media Muxer library in Tizen Native API
+Version:    0.1.1
+Release:    1
+Group:      Multimedia/API
+License:    Apache-2.0
+Source0:    %{name}-%{version}.tar.gz
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(mm-common)
+BuildRequires:  pkgconfig(capi-base-common)
+BuildRequires:  pkgconfig(capi-media-tool)
+BuildRequires:  pkgconfig(libtbm)
+BuildRequires:  pkgconfig(gstreamer-1.0)
+BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
+BuildRequires:  pkgconfig(gstreamer-video-1.0)
+BuildRequires:  pkgconfig(gstreamer-app-1.0)
+BuildRequires:  pkgconfig(iniparser)
+
+Requires(post): /sbin/ldconfig
+Requires(post): libprivilege-control
+Requires(postun): /sbin/ldconfig
+
+%description
+
+%package devel
+Summary:    Multimedia Framework Muxer Library (DEV)
+Group:      Multimedia/API
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+
+%prep
+%setup -q
+
+
+%build
+%if 0%{?sec_build_binary_debug_enable}
+export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
+%endif
+%ifarch %{arm}
+export CFLAGS="$CFLAGS -DENABLE_FFMPEG_CODEC"
+%endif
+
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+%cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}%{_datadir}/license
+mkdir -p %{buildroot}/usr/bin
+cp test/mediamuxer_test %{buildroot}/usr/bin
+cp LICENSE.APLv2 %{buildroot}%{_datadir}/license/%{name}
+
+%make_install
+
+%post
+/sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+
+%files
+%manifest capi-mediamuxer.manifest
+%{_libdir}/libcapi-mediamuxer.so.*
+%{_datadir}/license/%{name}
+%{_bindir}/*
+
+%files devel
+%{_includedir}/media/*.h
+%{_libdir}/pkgconfig/*.pc
+%{_libdir}/libcapi-mediamuxer.so
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..eb5446c
--- /dev/null
@@ -0,0 +1,4 @@
+message(In src folder...)
+add_subdirectory(port_gst)
+add_subdirectory(port_ffmpeg)
+add_subdirectory(port_custom)
diff --git a/src/mediamuxer.c b/src/mediamuxer.c
new file mode 100644 (file)
index 0000000..aa75887
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2015 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>
+#include <string.h>
+#include <mm.h>
+#include <mediamuxer_port.h>
+#include <mm_types.h>
+#include <mediamuxer.h>
+#include <mediamuxer_private.h>
+#include <dlog.h>
+
+#ifndef USE_TASK_QUEUE
+#define USE_TASK_QUEUE
+#endif
+
+/*
+* Public Implementation
+*/
+static gboolean _mediamuxer_error_cb(mediamuxer_error_e error, void *user_data);
+
+int mediamuxer_create(mediamuxer_h *muxer)
+{
+       MX_I("mediamuxer_create\n");
+       mediamuxer_error_e ret = MM_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+
+       mediamuxer_s *handle;
+       handle = (mediamuxer_s *) malloc(sizeof(mediamuxer_s));
+       if (handle != NULL) {
+               memset(handle, 0, sizeof(mediamuxer_s));
+               handle->muxer_state = MEDIAMUXER_STATE_NONE;
+       } else {
+               MX_E("[CoreAPI][%s] MUXER_ERROR_OUT_OF_MEMORY(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_OUT_OF_MEMORY);
+               return MEDIAMUXER_ERROR_OUT_OF_MEMORY;
+       }
+
+       ret = mx_create(&handle->mx_handle);
+       if (ret != MM_ERROR_NONE) {
+               MX_E("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+               free(handle);
+               handle = NULL;
+               return MEDIAMUXER_ERROR_INVALID_OPERATION;
+       } else {
+               *muxer = (mediamuxer_h) handle;
+               handle->is_stopped = false;
+               MX_I("[CoreAPI][%s] new handle : %p", __FUNCTION__, *muxer);
+
+               /* set callback */
+               mx_set_error_cb(handle->mx_handle, (mediamuxer_error_cb)_mediamuxer_error_cb, handle);
+               handle->muxer_state = MEDIAMUXER_STATE_IDLE;
+               return MEDIAMUXER_ERROR_NONE;
+       }
+}
+
+int mediamuxer_set_data_sink(mediamuxer_h muxer, char *path, mediamuxer_output_format_e format)
+{
+       MX_I("mediamuxer_set_data_sink\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       mediamuxer_s *handle;
+       MUXER_INSTANCE_CHECK(muxer);
+       handle = (mediamuxer_s *)(muxer);
+
+       if (path == NULL) {
+               MX_I("Invalid uri");
+               return MEDIAMUXER_ERROR_INVALID_PARAMETER;
+       }
+
+       if (format != MEDIAMUXER_CONTAINER_FORMAT_MP4) {
+               MX_E("\n Unsupported format: %d \n", format);
+               return MEDIAMUXER_ERROR_INVALID_PARAMETER;
+       }
+       if (handle->muxer_state == MEDIAMUXER_STATE_IDLE) {
+               ret = mx_set_data_sink(handle->mx_handle, path, format);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                            __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] set_data_sink successful, handle : %p",
+                            __FUNCTION__, handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                       __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               ret = MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       return ret;
+}
+
+int mediamuxer_add_track(mediamuxer_h muxer, media_format_h media_format, int *track_index)
+{
+       MX_I("mediamuxer_add_track\n");
+       mediamuxer_error_e ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle;
+       handle = (mediamuxer_s *)(muxer);
+       if (handle->muxer_state == MEDIAMUXER_STATE_IDLE){
+               ret = mx_add_track(handle->mx_handle, media_format, track_index);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                            __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] add_track handle : %p", __FUNCTION__,
+                            handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               ret = MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       return ret;
+}
+
+int mediamuxer_start(mediamuxer_h muxer)
+{
+       MX_I("mediamuxer_start\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle = (mediamuxer_s *)(muxer);
+       if (handle->muxer_state == MEDIAMUXER_STATE_IDLE) {
+               ret = mx_start(handle->mx_handle);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                            __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] start successful, handle : %p",
+                            __FUNCTION__, handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               return MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       handle->muxer_state = MEDIAMUXER_STATE_READY;
+       return ret;
+}
+
+int mediamuxer_write_sample(mediamuxer_h muxer, int track_index, media_packet_h inbuf)
+{
+       MX_I("mediamuxer_write_sample\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle = (mediamuxer_s *)(muxer);
+       if (track_index < 0 || inbuf == NULL) {
+               return MEDIAMUXER_ERROR_INVALID_PARAMETER;
+       }
+       if (handle->muxer_state == MEDIAMUXER_STATE_READY
+               || handle->muxer_state == MEDIAMUXER_STATE_MUXING) {
+               ret = mx_write_sample(handle->mx_handle, track_index, inbuf);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E
+                       ("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                        __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] write_sample successful, handle : %p",
+                            __FUNCTION__, handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               return MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       handle->muxer_state = MEDIAMUXER_STATE_MUXING;
+       return ret;
+}
+
+int mediamuxer_close_track(mediamuxer_h muxer, int track_index)
+{
+       MX_I("mediamuxer_close_track\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle = (mediamuxer_s *)(muxer);
+       if (track_index < 0) {
+               return MEDIAMUXER_ERROR_INVALID_PARAMETER;
+       }
+       if (handle->muxer_state == MEDIAMUXER_STATE_MUXING ||
+               handle->muxer_state == MEDIAMUXER_STATE_IDLE ||
+               handle->muxer_state == MEDIAMUXER_STATE_READY) {
+               ret = mx_close_track(handle->mx_handle, track_index);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E
+                       ("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                        __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] close  successful, handle : %p",
+                            __FUNCTION__, handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               ret = MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       return ret;
+}
+
+int mediamuxer_pause(mediamuxer_h muxer)
+{
+       MX_I("mediamuxer_pause\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle = (mediamuxer_s *)(muxer);
+       ret = mx_pause(handle->mx_handle);
+       if (handle->muxer_state == MEDIAMUXER_STATE_READY
+               || handle->muxer_state == MEDIAMUXER_STATE_MUXING) {
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E
+                       ("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                        __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] pause successful, handle : %p",
+                            __FUNCTION__, handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               return MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       handle->muxer_state = MEDIAMUXER_STATE_PAUSED;
+       return ret;
+}
+
+int mediamuxer_resume(mediamuxer_h muxer)
+{
+       MX_I("mediamuxer_resume\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle = (mediamuxer_s *)(muxer);
+       if (handle->muxer_state == MEDIAMUXER_STATE_PAUSED) {
+               ret = mx_resume(handle->mx_handle);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E
+                       ("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                        __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] resume successful, handle : %p",
+                            __FUNCTION__, handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               return MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       handle->muxer_state = MEDIAMUXER_STATE_MUXING;
+       return ret;
+}
+
+int mediamuxer_stop(mediamuxer_h muxer)
+{
+       MX_I("mediamuxer_stop\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle = (mediamuxer_s *)(muxer);
+       if (handle->muxer_state == MEDIAMUXER_STATE_READY
+               || handle->muxer_state == MEDIAMUXER_STATE_MUXING
+               || handle->muxer_state == MEDIAMUXER_STATE_PAUSED) {
+               ret = mx_stop(handle->mx_handle);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E
+                       ("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                        __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] stop successful, handle : %p",
+                            __FUNCTION__, handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               return MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       handle->muxer_state = MEDIAMUXER_STATE_IDLE;
+       return ret;
+}
+
+int mediamuxer_destroy(mediamuxer_h muxer)
+{
+       MX_I("mediamuxer_destroy\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle;
+       handle = (mediamuxer_s *)(muxer);
+       if (handle->muxer_state == MEDIAMUXER_STATE_IDLE) {
+               ret = mx_destroy(handle->mx_handle);
+               if (ret != MEDIAMUXER_ERROR_NONE) {
+                       MX_E("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                            __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+                       ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MX_I("[CoreAPI][%s] destroy handle : %p", __FUNCTION__,
+                            handle);
+               }
+       } else {
+               MX_E("[CoreAPI][%s] MEDIAMUXER_ERROR_INVALID_STATE(0x%08x)",
+                    __FUNCTION__, MEDIAMUXER_ERROR_INVALID_STATE);
+               return MEDIAMUXER_ERROR_INVALID_STATE;
+       }
+       handle->muxer_state = MEDIAMUXER_STATE_NONE;
+       return ret;
+}
+
+int mediamuxer_get_state(mediamuxer_h muxer, mediamuxer_state_e *state)
+{
+       MX_I("mediamuxer_get_state\n");
+       int ret = MEDIAMUXER_ERROR_NONE;
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle = (mediamuxer_s *)(muxer);
+       if (state != NULL) {
+               *state = handle->muxer_state;
+       } else {
+               MX_E("[CoreAPI][%s] MUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                       __FUNCTION__, MEDIAMUXER_ERROR_INVALID_OPERATION);
+               ret = MEDIAMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediamuxer_set_error_cb(mediamuxer_h muxer, mediamuxer_error_cb callback, void* user_data)
+{
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle;
+       handle = (mediamuxer_s *)(muxer);
+
+       handle->error_cb = callback;
+       handle->error_cb_userdata = user_data;
+
+       MX_I("set error_cb(%p)", callback);
+
+       return MEDIAMUXER_ERROR_NONE;
+}
+
+int mediamuxer_unset_error_cb(mediamuxer_h muxer)
+{
+       MUXER_INSTANCE_CHECK(muxer);
+       mediamuxer_s *handle;
+       handle = (mediamuxer_s *)(muxer);
+
+       handle->error_cb = NULL;
+       handle->error_cb_userdata = NULL;
+       MX_I("mediamuxer_unset_error_cb\n");
+       return MEDIAMUXER_ERROR_NONE;
+}
+
+static gboolean _mediamuxer_error_cb(mediamuxer_error_e error, void *user_data)
+{
+       if (user_data == NULL) {
+               MX_I("_mediamuxer_error_cb: ERROR %d to report. But call back is not set\n",error);
+               return 0;
+       }
+       mediamuxer_s * handle = (mediamuxer_s *) user_data;
+
+       if (handle->error_cb ) {
+               ((mediamuxer_error_cb)handle->error_cb)(error, handle->error_cb_userdata);
+       }
+       else {
+               MX_I("_mediamuxer_error_cb: ERROR %d to report. But call back is not set\n",error);
+       }
+       return 0;
+}
diff --git a/src/mediamuxer_ini.c b/src/mediamuxer_ini.c
new file mode 100644 (file)
index 0000000..d829dd5
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015 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 __MEDIAMUXER_INI_C__
+#define __MEDIAMUXER_INI_C__
+
+#include <glib.h>
+#include <stdlib.h>
+#include <glib/gstdio.h>
+#include <mm_debug.h>
+#include <mm_error.h>
+#include "iniparser.h"
+#include <mediamuxer_ini.h>
+#include <mediamuxer_private.h>
+#include <mediamuxer_error.h>
+
+/* macro */
+#define MEDIAMUXER_INI_GET_STRING( x_dict, x_item, x_ini, x_default ) \
+       do \
+       { \
+               gchar* str = iniparser_getstring(x_dict, x_ini, x_default); \
+               \
+               if ( str &&  \
+                    ( strlen( str ) > 0 ) && \
+                    ( strlen( str ) < MEDIAMUXER_INI_MAX_STRLEN ) ) \
+               { \
+                       strcpy ( x_item, str ); \
+               } \
+               else \
+               { \
+                       strcpy ( x_item, x_default ); \
+               } \
+       }while(0)
+
+#define MEDIAMUXER_INI_GET_COLOR( x_dict, x_item, x_ini, x_default ) \
+       do \
+       { \
+               gchar* str = iniparser_getstring(x_dict, x_ini, x_default); \
+               \
+               if ( str &&  \
+                    ( strlen( str ) > 0 ) && \
+                    ( strlen( str ) < MEDIAMUXER_INI_MAX_STRLEN ) ) \
+               { \
+                       x_item = (guint) strtoul(str, NULL, 16); \
+               } \
+               else \
+               { \
+                       x_item = (guint) strtoul(x_default, NULL, 16); \
+               } \
+       }while(0)
+
+/* x_ini is the list of index to set TRUE at x_list[index] */
+#define MEDIAMUXER_INI_GET_BOOLEAN_FROM_LIST( x_dict, x_list, \
+                                              x_list_max, x_ini, x_default ) \
+do \
+{ \
+       int index = 0; \
+       const char *delimiters = " ,"; \
+       char *usr_ptr = NULL; \
+       char *token = NULL; \
+       gchar temp_arr[MEDIAMUXER_INI_MAX_STRLEN] = {0}; \
+       MMMEDIAMUXER_INI_GET_STRING( x_dict, temp_arr, x_ini, x_default); \
+       token = strtok_r( temp_arr, delimiters, &usr_ptr ); \
+       while (token) \
+       { \
+               index = atoi(token); \
+               if (index < 0 || index > x_list_max -1) \
+               { \
+                       MX_W("%d is not valid index\n", index); \
+               } \
+               else \
+               { \
+                       x_list[index] = TRUE; \
+               } \
+               token = strtok_r( NULL, delimiters, &usr_ptr ); \
+       } \
+}while(0)
+
+/* x_ini is the list of value to be set at x_list[index] */
+#define MEDIAMUXER_INI_GET_INT_FROM_LIST( x_dict, x_list, \
+                                          x_list_max, x_ini, x_default ) \
+do \
+{ \
+       int index = 0; \
+       int value = 0; \
+       const char *delimiters = " ,"; \
+       char *usr_ptr = NULL; \
+       char *token = NULL; \
+       gchar temp_arr[MEDIAMUXER_INI_MAX_STRLEN] = {0}; \
+       MMMEDIAMUXER_INI_GET_STRING(x_dict, temp_arr, x_ini, x_default); \
+       token = strtok_r( temp_arr, delimiters, &usr_ptr ); \
+       while (token) \
+       { \
+               if ( index > x_list_max -1) \
+               { \
+                       MX_E("%d is not valid index\n", index); \
+                       break; \
+               } \
+               else \
+               { \
+                       value = atoi(token); \
+                       x_list[index] = value; \
+                       index++; \
+               } \
+               token = strtok_r( NULL, delimiters, &usr_ptr ); \
+       } \
+}while(0)
+
+/* internal functions, macros here */
+#ifdef MEDIAMUXER_DEFAULT_INI
+static gboolean _generate_default_ini(void);
+#endif
+
+static void _mx_ini_check_ini_status(void);
+
+int mx_ini_load(mx_ini_t *ini)
+{
+       dictionary *dict = NULL;
+
+       _mx_ini_check_ini_status();
+
+       /* first, try to load existing ini file */
+       dict = iniparser_load(MEDIAMUXER_INI_DEFAULT_PATH);
+
+       /* if no file exists. create one with set of default values */
+       if (!dict) {
+#ifdef MEDIAMUXER_DEFAULT_INI
+               MX_L("No inifile found. muxer will create default inifile.\n");
+               if (FALSE == _generate_default_ini()) {
+                       MX_W("Creating default inifile failed. \
+                       MediaMuxer will use default values.\n");
+               } else {
+                       /* load default ini */
+                       dict = iniparser_load(MEDIAMUXER_INI_DEFAULT_PATH);
+               }
+#else
+               MX_L("No ini file found. \n");
+               return MM_ERROR_FILE_NOT_FOUND;
+#endif
+       }
+
+       /* get ini values */
+       memset(ini, 0, sizeof(mx_ini_t));
+
+       if (dict) {             /* if dict is available */
+               /* general */
+               MEDIAMUXER_INI_GET_STRING(dict, ini->port_name,
+                                         "port_in_use:mediamuxer_port",
+                                         DEFAULT_PORT);
+       } else {
+               /* if dict is not available just fill
+                  the structure with default value */
+               MX_W("failed to load ini. using hardcoded default\n");
+               strncpy(ini->port_name, DEFAULT_PORT,
+                       MEDIAMUXER_INI_MAX_STRLEN - 1);
+       }
+
+       if (0 == strcmp(ini->port_name, "GST_PORT")) {
+               ini->port_type = GST_PORT;
+       } else if (0 == strcmp(ini->port_name, "FFMPEG_PORT")) {
+               ini->port_type = FFMPEG_PORT;
+       } else if (0 == strcmp(ini->port_name, "CUSTOM_PORT")) {
+               ini->port_type = CUSTOM_PORT;
+       } else {
+               MX_E("Invalid port is set to [%s] [%d]\n", ini->port_name,
+                    ini->port_type);
+               goto ERROR;
+       }
+       MX_L("The port is set to [%s] [%d]\n", ini->port_name, ini->port_type);
+
+       /* free dict as we got our own structure */
+       iniparser_freedict(dict);
+
+       /* dump structure */
+       MX_L("muxer settings -----------------------------------\n");
+
+       /* general */
+       MX_L("port_name: %s\n", ini->port_name);
+       MX_L("port_type : %d\n", ini->port_type);
+
+       return MM_ERROR_NONE;
+ERROR:
+       return MX_COURRPTED_INI;
+}
+
+static void _mx_ini_check_ini_status(void)
+{
+       struct stat ini_buff;
+
+       if (g_stat(MEDIAMUXER_INI_DEFAULT_PATH, &ini_buff) < 0) {
+               MX_W("failed to get muxer ini status\n");
+       } else {
+               if (ini_buff.st_size < 5) {
+                       MX_W("muxer.ini file size=%d, Corrupted! So, Removed\n",
+                            (int)ini_buff.st_size);
+
+                       if (g_remove(MEDIAMUXER_INI_DEFAULT_PATH) == -1)
+                               MX_E("failed to delete corrupted ini");
+               }
+       }
+}
+
+#ifdef MEDIAMUXER_DEFAULT_INI
+static gboolean _generate_default_ini(void)
+{
+       FILE *fp = NULL;
+       gchar *default_ini = MEDIAMUXER_DEFAULT_INI;
+
+       /* create new file */
+       fp = fopen(MEDIAMUXER_INI_DEFAULT_PATH, "wt");
+
+       if (!fp)
+               return FALSE;
+
+       /* writing default ini file */
+       if (strlen(default_ini) !=
+           fwrite(default_ini, 1, strlen(default_ini), fp)) {
+               fclose(fp);
+               return FALSE;
+       }
+
+       fclose(fp);
+       return TRUE;
+}
+#endif
+
+#endif /* #ifdef _MEDIAMUXER_INI_C_ */
diff --git a/src/mediamuxer_port.c b/src/mediamuxer_port.c
new file mode 100644 (file)
index 0000000..81bc5cc
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2015 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 <string.h>
+#include <mm_types.h>
+#include <mm_message.h>
+#include <mm_debug.h>
+#include <mediamuxer.h>
+#include <mediamuxer_ini.h>
+#include <mediamuxer_error.h>
+#include <mediamuxer_private.h>
+#include <mediamuxer_port.h>
+
+/* function type */
+extern int gst_port_register(media_port_muxer_ops *pOps);
+extern int ffmpeg_port_register(media_port_muxer_ops *pOps);
+extern int custom_port_register(media_port_muxer_ops *pOps);
+
+/*
+  * Sequence of functions should be same as the port enumeration "port_mode"
+  * in mx_ini.h file
+  */
+typedef int (*register_port)(media_port_muxer_ops *);
+register_port register_port_func[] = {
+       &gst_port_register,
+       &ffmpeg_port_register,
+       &custom_port_register
+};
+
+int mx_create(MMHandleType *muxer)
+{
+       int result = MX_ERROR_NONE;
+       media_port_muxer_ops *pOps = NULL;
+       mx_handle_t *new_muxer = NULL;
+       MEDIAMUXER_FENTER();
+       new_muxer = (mx_handle_t *) g_malloc(sizeof(mx_handle_t));
+       MEDIAMUXER_CHECK_NULL(new_muxer);
+       memset(new_muxer, 0, sizeof(mx_handle_t));
+
+       /* alloc ops structure */
+       pOps = (media_port_muxer_ops *) g_malloc(sizeof(media_port_muxer_ops));
+       MEDIAMUXER_CHECK_NULL(pOps);
+
+       new_muxer->muxer_ops = pOps;
+       MX_I("mx_create allocating new_demuxer->demuxer_ops %p:\n",
+            new_muxer->muxer_ops);
+       pOps->n_size = sizeof(media_port_muxer_ops);
+       /* load ini files */
+       result = mx_ini_load(&new_muxer->ini);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(result, MX_ERROR_NONE, result,
+                                      MX_COURRPTED_INI, "can't load ini");
+
+       register_port_func[new_muxer->ini.port_type](pOps);
+       result = pOps->init(&new_muxer->mxport_handle);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(result, MX_ERROR_NONE, result,
+                                      MX_NOT_INITIALIZED, "mx_create failed");
+       *muxer = (MMHandleType) new_muxer;
+       MEDIAMUXER_FLEAVE();
+       return result;
+ERROR:
+       *muxer = (MMHandleType) 0;
+       if (pOps)
+               g_free(pOps);
+       if (new_muxer)
+               g_free(new_muxer);
+       MEDIAMUXER_FLEAVE();
+       return result;
+}
+
+int mx_set_data_sink(MMHandleType mediamuxer, char *uri, mediamuxer_output_format_e format)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *) mediamuxer;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->set_data_sink(mx_handle->mxport_handle, uri, format);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_add_track(MMHandleType mediamuxer, media_format_h media_format, int *track_index)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *) mediamuxer;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->add_track(mx_handle->mxport_handle, media_format, track_index);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while adding track");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_start(MMHandleType mediamuxer)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *)(mediamuxer);
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->start(mx_handle->mxport_handle);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while starting");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_write_sample(MMHandleType mediamuxer, int track_index, media_packet_h inbuf)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *) mediamuxer;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->write_sample(mx_handle->mxport_handle, track_index, inbuf);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while writing sample");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_close_track(MMHandleType mediamuxer, int track_index)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *)(mediamuxer);
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->close_track(mx_handle->mxport_handle, track_index);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while closing track");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_pause(MMHandleType mediamuxer)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *)(mediamuxer);
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->pause(mx_handle->mxport_handle);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while pausing");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_resume(MMHandleType mediamuxer)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *)(mediamuxer);
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->resume(mx_handle->mxport_handle);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while resuming");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_stop(MMHandleType mediamuxer)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *)(mediamuxer);
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->stop(mx_handle->mxport_handle);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while destroying");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_destroy(MMHandleType mediamuxer)
+{
+       int ret = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *) mediamuxer;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       ret = pOps->destroy(mx_handle->mxport_handle);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(ret, MX_ERROR_NONE, ret, MX_ERROR,
+                                      "error while destroying");
+
+       /* free mediamuxer structure */
+       if (mx_handle) {
+               if (mx_handle->muxer_ops) {
+                       MX_I("mx_destroy deallocating mx_handle->muxer_ops %p:\n",
+                            mx_handle->muxer_ops);
+                       g_free((void *)(mx_handle->muxer_ops));
+               }
+               MX_I("mx_destroy deallocating mx_handle %p:\n", mx_handle);
+               g_free((void *)mx_handle);
+               mx_handle = NULL;
+       }
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int mx_set_error_cb(MMHandleType muxer,
+                       mediamuxer_error_cb callback, void* user_data)
+{
+       MEDIAMUXER_FENTER();
+       int result = MX_ERROR_NONE;
+       mx_handle_t *mx_handle = (mx_handle_t *) muxer;
+       MEDIAMUXER_CHECK_NULL(mx_handle);
+       media_port_muxer_ops *pOps = mx_handle->muxer_ops;
+       MEDIAMUXER_CHECK_NULL(pOps);
+       result = pOps->set_error_cb(mx_handle->mxport_handle, callback,user_data);
+       MEDIAMUXER_CHECK_SET_AND_PRINT(result, MX_ERROR_NONE, result,
+                       MX_ERROR, "error while setting error call back");
+       MEDIAMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return result;
+}
diff --git a/src/port_custom/mediamuxer_port_custom.c b/src/port_custom/mediamuxer_port_custom.c
new file mode 100644 (file)
index 0000000..83ccafa
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015 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 <mm_debug.h>
+#include <mediamuxer_error.h>
+#include <mediamuxer_private.h>
+#include <mediamuxer_port.h>
+#include <mediamuxer_port_custom.h>
+
+static int custom_muxer_init(MMHandleType *pHandle);
+static int custom_muxer_set_data_sink(MMHandleType pHandle, char *uri,
+                       mediamuxer_output_format_e format);
+
+/*Media Muxer API common*/
+static media_port_muxer_ops def_mux_ops = {
+       .n_size = 0,
+       .init = custom_muxer_init,
+       .set_data_sink = custom_muxer_set_data_sink,
+};
+
+int custom_port_register(media_port_muxer_ops *pOps)
+{
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(pOps);
+
+       def_mux_ops.n_size = sizeof(def_mux_ops);
+
+       memcpy((char *)pOps + sizeof(pOps->n_size),
+              (char *)&def_mux_ops + sizeof(def_mux_ops.n_size),
+              pOps->n_size - sizeof(pOps->n_size));
+
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       return ret;
+}
+
+static int custom_muxer_init(MMHandleType *pHandle)
+{
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_FENTER();
+       MX_E("%s:exit: Not implemented\n", __func__);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int custom_muxer_set_data_sink(MMHandleType pHandle, char *uri,
+    mediamuxer_output_format_e format)
+{
+       MEDIAMUXER_FENTER();
+       MX_E("%s:exit: Not implemented\n", __func__);
+       MEDIAMUXER_FLEAVE();
+       return 0;
+}
diff --git a/src/port_ffmpeg/mediamuxer_port_ffmpeg.c b/src/port_ffmpeg/mediamuxer_port_ffmpeg.c
new file mode 100644 (file)
index 0000000..7857b7c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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 <mm_debug.h>
+#include <mediamuxer_error.h>
+#include <mediamuxer_private.h>
+#include <mediamuxer_port.h>
+#include <mediamuxer_port_ffmpeg.h>
+
+static int ffmpeg_muxer_init(MMHandleType *pHandle);
+static int ffmpeg_muxer_set_data_sink(MMHandleType pHandle, char *uri,
+                       mediamuxer_output_format_e format);
+
+/*Media Muxer API common*/
+static media_port_muxer_ops def_mux_ops = {
+       .n_size = 0,
+       .init = ffmpeg_muxer_init,
+       .set_data_sink = ffmpeg_muxer_set_data_sink,
+};
+
+int ffmpeg_port_register(media_port_muxer_ops *pOps)
+{
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(pOps);
+
+       def_mux_ops.n_size = sizeof(def_mux_ops);
+
+       memcpy((char *)pOps + sizeof(pOps->n_size),
+              (char *)&def_mux_ops + sizeof(def_mux_ops.n_size),
+              pOps->n_size - sizeof(pOps->n_size));
+
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       return ret;
+}
+
+static int ffmpeg_muxer_init(MMHandleType *pHandle)
+{
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_FENTER();
+       MX_E("%s:exit: Not implemented\n", __func__);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int ffmpeg_muxer_set_data_sink(MMHandleType pHandle, char *uri,
+    mediamuxer_output_format_e format)
+{
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_FENTER();
+       MX_E("%s:exit: Not implemented\n", __func__);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
diff --git a/src/port_gst/mediamuxer_port_gst.c b/src/port_gst/mediamuxer_port_gst.c
new file mode 100644 (file)
index 0000000..98b2344
--- /dev/null
@@ -0,0 +1,1185 @@
+/*
+ * Copyright (c) 2015 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 <mm_debug.h>
+#include <mediamuxer_error.h>
+#include <mediamuxer_private.h>
+#include <mediamuxer_port.h>
+#include <mediamuxer_port_gst.h>
+
+#define EOS_POLL_PERIOD 1000
+#define WRITE_POLL_PERIOD 100
+/*#define SEND_FULL_CAPS_VIA_CODEC_DATA *//*For debug purpose*/
+#define ASYCHRONOUS_WRITE  /*write sample is not blocking */
+
+static int gst_muxer_init(MMHandleType *pHandle);
+static int gst_muxer_set_data_sink(MMHandleType pHandle, char *uri,
+                       mediamuxer_output_format_e format);
+static int gst_muxer_add_track(MMHandleType pHandle,
+                       media_format_h media_format, int *track_index);
+static int gst_muxer_start(MMHandleType pHandle);
+static int gst_muxer_write_sample(MMHandleType pHandle, int track_index,
+                       media_packet_h inbuf);
+static int gst_muxer_close_track(MMHandleType pHandle, int track_index);
+static int gst_muxer_pause(MMHandleType pHandle);
+static int gst_muxer_resume(MMHandleType pHandle);
+static int gst_muxer_stop(MMHandleType pHandle);
+static int gst_muxer_destroy(MMHandleType pHandle);
+static int gst_set_error_cb(MMHandleType pHandle,
+                       gst_error_cb callback, void* user_data);
+
+/*Media Muxer API common*/
+static media_port_muxer_ops def_mux_ops = {
+       .n_size = 0,
+       .init = gst_muxer_init,
+       .set_data_sink = gst_muxer_set_data_sink,
+       .add_track = gst_muxer_add_track,
+       .start = gst_muxer_start,
+       .write_sample = gst_muxer_write_sample,
+       .close_track = gst_muxer_close_track,
+       .pause = gst_muxer_pause,
+       .resume = gst_muxer_resume,
+       .stop = gst_muxer_stop,
+       .destroy = gst_muxer_destroy,
+       .set_error_cb = gst_set_error_cb,
+};
+
+int gst_port_register(media_port_muxer_ops *pOps)
+{
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(pOps);
+
+       def_mux_ops.n_size = sizeof(def_mux_ops);
+
+       memcpy((char *)pOps + sizeof(pOps->n_size),
+              (char *)&def_mux_ops + sizeof(def_mux_ops.n_size),
+              pOps->n_size - sizeof(pOps->n_size));
+
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_init(MMHandleType *pHandle)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       mxgst_handle_t *new_mediamuxer = NULL;
+
+       new_mediamuxer = (mxgst_handle_t *) g_malloc(sizeof(mxgst_handle_t));
+       MX_I("GST_Muxer_Init allocating memory for new_mediamuxer: %p\n", new_mediamuxer);
+       if (!new_mediamuxer) {
+               MX_E("Cannot allocate memory for muxer \n");
+               ret = MX_ERROR;
+               goto ERROR;
+       }
+       memset(new_mediamuxer, 0, sizeof(mxgst_handle_t));
+       /* Set desired parameters */
+       new_mediamuxer->output_uri = NULL;
+       new_mediamuxer->muxed_format = -1;
+       new_mediamuxer->video_track.media_format = NULL;
+       new_mediamuxer->audio_track.media_format = NULL;
+       new_mediamuxer->video_track.track_index = -1;
+       new_mediamuxer->audio_track.track_index = -1;
+       new_mediamuxer->video_track.start_feed = 1;
+       new_mediamuxer->audio_track.start_feed = 1;
+       new_mediamuxer->video_track.stop_feed = 0;
+       new_mediamuxer->audio_track.stop_feed = 0;
+
+       MX_I("V.start_feed[%d],V.stop_feed[%d],A.start_feed[%d],A.stop_feed[%d]\n",
+            new_mediamuxer->video_track.start_feed,
+            new_mediamuxer->video_track.stop_feed,
+            new_mediamuxer->audio_track.start_feed,
+            new_mediamuxer->audio_track.stop_feed);
+
+       new_mediamuxer->eos_flg = false;
+       *pHandle = (MMHandleType) new_mediamuxer;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MX_E("%s: Not implemented\n", __func__);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_set_data_sink(MMHandleType pHandle,
+                  char *uri, mediamuxer_output_format_e format)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *mx_handle_gst = (mxgst_handle_t *) pHandle;
+
+       /* Set desired parameters */
+       mx_handle_gst->output_uri = uri;
+       mx_handle_gst->muxed_format = format;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MX_E("muxer handle already NULL, returning \n");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_add_track(MMHandleType pHandle,
+                  media_format_h media_format, int *track_index)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *mx_handle_gst = (mxgst_handle_t *) pHandle;
+
+       media_format_mimetype_e mimetype = 0;
+       if (media_format_get_video_info(media_format, &mimetype, NULL, NULL, NULL, NULL) !=
+                                                                    MEDIA_FORMAT_ERROR_INVALID_OPERATION) {
+               if (mimetype == MEDIA_FORMAT_H264_SP  ||
+                   mimetype == MEDIA_FORMAT_H264_MP ||
+                   mimetype == MEDIA_FORMAT_H264_HP) {
+                       if (mx_handle_gst->video_track.media_format == NULL) {
+                               mx_handle_gst->video_track.media_format = (void *)media_format;
+                               /* ToDo: track_index should be incremented accordingly for multiple tracks */
+                               mx_handle_gst->video_track.track_index = 1;
+                               mx_handle_gst->video_track.caps = NULL;
+                               *track_index = mx_handle_gst->video_track.track_index;
+                               MX_I("Video track added successfully: %p \n", mx_handle_gst->video_track.media_format);
+                       } else {
+                               MX_E("muxer handle already have a video track, \
+                               add failed, as Multiple video tracks are not currently supported");
+                               ret = MX_ERROR_NOT_SUPPORT_API;
+                               goto ERROR;
+                       }
+               }
+       } else if (media_format_get_audio_info(media_format, &mimetype, NULL, NULL, NULL, NULL) !=
+                                                                       MEDIA_FORMAT_ERROR_INVALID_OPERATION) {
+               if (mimetype == MEDIA_FORMAT_AAC ||
+                   mimetype == MEDIA_FORMAT_AAC_LC ||
+                   mimetype == MEDIA_FORMAT_AAC_HE ||
+                   mimetype == MEDIA_FORMAT_AAC_HE_PS)  {
+                       if (mx_handle_gst->audio_track.media_format == NULL) {
+                               mx_handle_gst->audio_track.media_format = (void *)media_format;
+                               /* ToDo: track_index should be incremented accordingly for multiple tracks */
+                               mx_handle_gst->audio_track.track_index = 2;
+                               mx_handle_gst->audio_track.caps = NULL;
+                               *track_index = mx_handle_gst->audio_track.track_index;
+                               MX_I("Audio track added successfully: %p \n", mx_handle_gst->audio_track.media_format);
+                       } else {
+                               MX_E("muxer handle already have a audio track, add failed, \
+                               as Multiple audio tracks are not currently supported");
+                               ret = MX_ERROR_NOT_SUPPORT_API;
+                               goto ERROR;
+                       }
+               } else {
+                       MX_E("Unsupported MIME Type\n");
+               }
+       } else {
+               MX_E("Unsupported A/V MIME Type\n");
+       }
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MX_E(" gst_muxer_add_track failed \n");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static gint __gst_handle_resource_error(mxgst_handle_t* gst_handle, int code)
+{
+       MEDIAMUXER_FENTER();
+       gint trans_err = MEDIAMUXER_ERROR_NONE;
+       g_return_val_if_fail(gst_handle, MX_PARAM_ERROR);
+
+       switch (code) {
+               /* ToDo: Add individual actions as and when needed */
+               case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
+                       trans_err = MX_ERROR_COMMON_NO_FREE_SPACE;
+                       break;
+               case GST_RESOURCE_ERROR_WRITE:
+               case GST_RESOURCE_ERROR_FAILED:
+               case GST_RESOURCE_ERROR_SEEK:
+               case GST_RESOURCE_ERROR_TOO_LAZY:
+               case GST_RESOURCE_ERROR_BUSY:
+               case GST_RESOURCE_ERROR_OPEN_WRITE:
+               case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
+               case GST_RESOURCE_ERROR_CLOSE:
+               case GST_RESOURCE_ERROR_SYNC:
+               case GST_RESOURCE_ERROR_SETTINGS:
+               default:
+                       trans_err = MX_INTERNAL_ERROR;
+                       break;
+       }
+       MEDIAMUXER_FLEAVE();
+       return trans_err;
+}
+
+static gint __gst_handle_core_error(mxgst_handle_t* gst_handle, int code)
+{
+       MEDIAMUXER_FENTER();
+       gint trans_err = MEDIAMUXER_ERROR_NONE;
+
+       /* g_return_val_if_fail(core, MX_PARAM_ERROR); */
+       switch (code) {
+               /* ToDo: Add individual actions as and when needed */
+               case GST_CORE_ERROR_MISSING_PLUGIN:
+               case GST_CORE_ERROR_STATE_CHANGE:
+               case GST_CORE_ERROR_SEEK:
+               case GST_CORE_ERROR_NOT_IMPLEMENTED:
+               case GST_CORE_ERROR_FAILED:
+               case GST_CORE_ERROR_TOO_LAZY:
+               case GST_CORE_ERROR_PAD:
+               case GST_CORE_ERROR_THREAD:
+               case GST_CORE_ERROR_NEGOTIATION:
+               case GST_CORE_ERROR_EVENT:
+               case GST_CORE_ERROR_CAPS:
+               case GST_CORE_ERROR_TAG:
+               case GST_CORE_ERROR_CLOCK:
+               case GST_CORE_ERROR_DISABLED:
+               default:
+                       trans_err =  MX_INTERNAL_ERROR;
+                       break;
+       }
+       MEDIAMUXER_FLEAVE();
+       return trans_err;
+}
+
+static gint __gst_handle_library_error(mxgst_handle_t* gst_handle, int code)
+{
+       MEDIAMUXER_FENTER();
+       gint trans_err = MEDIAMUXER_ERROR_NONE;
+       g_return_val_if_fail(gst_handle, MX_PARAM_ERROR);
+
+       switch (code) {
+               /* ToDo: Add individual actions as and when needed */
+               case GST_LIBRARY_ERROR_FAILED:
+               case GST_LIBRARY_ERROR_TOO_LAZY:
+               case GST_LIBRARY_ERROR_INIT:
+               case GST_LIBRARY_ERROR_SHUTDOWN:
+               case GST_LIBRARY_ERROR_SETTINGS:
+               case GST_LIBRARY_ERROR_ENCODE:
+               default:
+                       trans_err =  MX_INTERNAL_ERROR;
+                       break;
+       }
+       MEDIAMUXER_FLEAVE();
+       return trans_err;
+}
+
+static gboolean _mx_gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
+{
+       MEDIAMUXER_FENTER();
+       int ret  = MX_ERROR_NONE;
+       mxgst_handle_t *gst_handle = (mxgst_handle_t*)data;
+       switch (GST_MESSAGE_TYPE(msg)) {
+               case GST_MESSAGE_EOS:
+                       MX_I("End of stream\n");
+                       break;
+               case GST_MESSAGE_ERROR: {
+                               gchar *debug;
+                               GError *error;
+                               gst_message_parse_error(msg, &error, &debug);
+                               if (!error) {
+                                       MX_E("GST error message parsing failed");
+                                       break;
+                               }
+                               MX_E("Error: %s\n", error->message);
+                               if (error) {
+                                       if (error->domain == GST_RESOURCE_ERROR)
+                                               ret = __gst_handle_resource_error(gst_handle, error->code);
+                                       else if (error->domain == GST_LIBRARY_ERROR)
+                                               ret = __gst_handle_library_error(gst_handle, error->code);
+                                       else if (error->domain == GST_CORE_ERROR)
+                                               ret = __gst_handle_core_error(gst_handle, error->code);
+                                       else
+                                               MX_E("Unexpected error has occured");
+                                       /* ToDo: Update the user callback with ret... */
+                                       return ret;
+                               }
+                               g_free(debug);
+                               MX_E("Error: %s\n", error->message);
+                               g_error_free(error);
+                       }
+                       break;
+               default:
+                       MX_E("unhandled message: 0x%x", GST_MESSAGE_TYPE(msg));
+                       break;
+       }
+       MEDIAMUXER_FLEAVE();
+       return TRUE;
+}
+
+/*
+  * This signal callback triggers when appsrc needs mux_data.
+  * Here, we add an idle handler to the mainloop to start pushing data into the appsrc
+  */
+static void _audio_start_feed(GstElement *source, guint size, mxgst_handle_t *gst_handle)
+{
+       MX_I("\nAudio Start feeding...\n");
+       gst_handle->audio_track.stop_feed = 0;
+       gst_handle->audio_track.start_feed = 1;
+}
+
+static void _video_start_feed(GstElement *source, guint size, mxgst_handle_t *gst_handle)
+{
+       MX_I("\nVideo Start feeding cb...\n");
+       gst_handle->video_track.stop_feed = 0;
+       gst_handle->video_track.start_feed = 1;
+}
+
+/*
+  * This callback triggers when appsrc has enough data and we can stop sending.
+  * We remove the idle handler from the mainloop.
+  */
+static void _audio_stop_feed(GstElement *source, mxgst_handle_t *gst_handle)
+{
+       MX_I("\nAudio Stop feeding cb...\n");
+       gst_handle->audio_track.stop_feed = 1;
+       gst_handle->audio_track.start_feed = 0;
+}
+
+static void _video_stop_feed(GstElement *source, mxgst_handle_t *gst_handle)
+{
+       MX_I("\nVideo Stop feeding...\n");
+       gst_handle->video_track.stop_feed = 1;
+       gst_handle->video_track.start_feed = 0;
+}
+
+mx_ret_e _gst_create_pipeline(mxgst_handle_t *gst_handle)
+{
+       MEDIAMUXER_FENTER();
+       gint ret = MX_ERROR_NONE;
+       GstBus *bus = NULL;
+       /* Note: Use a loop, if needed. GMainLoop *loop; */
+       GstPad *audio_pad, *video_pad, *aud_src, *vid_src;
+
+       /* Initialize GStreamer */
+       /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
+       gst_init(NULL, NULL);
+
+       /* Create the empty pipeline */
+       gst_handle->pipeline = gst_pipeline_new("Muxer Gst pipeline");
+
+       if (gst_handle->muxed_format == MEDIAMUXER_CONTAINER_FORMAT_MP4) {
+               gst_handle->muxer = gst_element_factory_make("qtmux", "media-muxer");
+               /* gst_element_factory_make("mp4mux", "media-muxer"); */
+               if (gst_handle->video_track.track_index == 1) { /* Video track */
+                       gst_handle->video_appsrc = gst_element_factory_make("appsrc", "video appsrc");
+                       gst_handle->videoparse = gst_element_factory_make("h264parse", "h264parse");
+               }
+               if (gst_handle->audio_track.track_index == 2) { /* Audio track */
+                       gst_handle->audio_appsrc = gst_element_factory_make("appsrc", "audio appsrc");
+                       gst_handle->audioparse = gst_element_factory_make("aacparse", "aacparse");
+               }
+       } else {
+               MX_E("Unsupported format. Currently suports only MPEG4");
+               ret = MEDIAMUXER_ERROR_INVALID_PATH;
+               goto ERROR;
+       }
+       gst_handle->sink = gst_element_factory_make("filesink", "muxer filesink");
+
+       if (!gst_handle->pipeline || !gst_handle->muxer || !gst_handle->sink) {
+               MX_E("One element could not be created. Exiting.\n");
+               ret = MEDIAMUXER_ERROR_RESOURCE_LIMIT;
+               goto ERROR;
+       }
+
+       /* Build the pipeline */
+       gst_bin_add_many(GST_BIN(gst_handle->pipeline),
+                                                           gst_handle->muxer,
+                                                           gst_handle->sink,
+                                                           NULL);
+
+       if (gst_handle->video_track.track_index == 1) {
+               /* video track */
+               if (!gst_handle->video_appsrc || !gst_handle->videoparse) {
+                       MX_E("One element (vparse) could not be created. Exiting.\n");
+                       ret = MEDIAMUXER_ERROR_RESOURCE_LIMIT;
+                       goto ERROR;
+               }
+               gst_bin_add_many(GST_BIN(gst_handle->pipeline),
+                                                                    gst_handle->video_appsrc,
+                                                                    gst_handle->videoparse,
+                                                                    NULL);
+               /* Set video caps for corresponding src elements */
+               g_object_set(gst_handle->video_appsrc, "caps",
+                                       gst_caps_from_string(gst_handle->video_track.caps), NULL);
+#ifdef ASYCHRONOUS_WRITE
+               g_signal_connect(gst_handle->video_appsrc, "need-data",
+                                       G_CALLBACK(_video_start_feed), gst_handle);
+               g_signal_connect(gst_handle->video_appsrc, "enough-data",
+                                       G_CALLBACK(_video_stop_feed), gst_handle);
+#else
+               g_object_set(gst_handle->video_appsrc, "block", TRUE, NULL);
+               gst_app_src_set_stream_type((GstAppSrc *)gst_handle->video_appsrc,
+                                       GST_APP_STREAM_TYPE_STREAM);
+#endif
+       }
+
+       if (gst_handle->audio_track.track_index == 2) {
+               /* Audio track */
+               if (!gst_handle->audio_appsrc || !gst_handle->audioparse) {
+                       MX_E("One element (aparse) could not be created. Exiting.\n");
+                       ret = MEDIAMUXER_ERROR_RESOURCE_LIMIT;
+                       goto ERROR;
+               }
+               gst_bin_add_many(GST_BIN(gst_handle->pipeline),
+                                                                    gst_handle->audio_appsrc,
+                                                                    gst_handle->audioparse,
+                                                                    NULL);
+               /* Set audio caps for corresponding src elements */
+               g_object_set(gst_handle->audio_appsrc, "caps",
+                                       gst_caps_from_string(gst_handle->audio_track.caps), NULL);
+#ifdef ASYCHRONOUS_WRITE
+               g_signal_connect(gst_handle->audio_appsrc, "need-data",
+                                       G_CALLBACK(_audio_start_feed), gst_handle);
+               g_signal_connect(gst_handle->audio_appsrc, "enough-data",
+                                       G_CALLBACK(_audio_stop_feed), gst_handle);
+#else
+               g_object_set(gst_handle->audio_appsrc, "block", TRUE, NULL);
+               gst_app_src_set_stream_type((GstAppSrc *)gst_handle->audio_appsrc,
+                                       GST_APP_STREAM_TYPE_STREAM);
+#endif
+       }
+
+       if (!gst_element_link(gst_handle->muxer, gst_handle->sink))
+               MX_E("muxer-sink link failed");
+
+       if (gst_handle->video_track.track_index == 1) {
+               /* video track */
+               gst_element_link(gst_handle->video_appsrc, gst_handle->videoparse);
+               /* Link videoparse to muxer_video_pad.   Request for muxer A/V pads. */
+               video_pad = gst_element_get_request_pad(gst_handle->muxer, "video_00");
+               vid_src = gst_element_get_static_pad(gst_handle->videoparse, "src");
+               if (gst_pad_link(vid_src, video_pad) != GST_PAD_LINK_OK)
+                       MX_E("video parser to muxer link failed");
+       }
+
+       if (gst_handle->audio_track.track_index == 2) {
+               /* audio track */
+               /* we add all elements into the pipeline */
+               gst_element_link(gst_handle->audio_appsrc, gst_handle->audioparse);
+               /* Link audioparse to muxer_audio_pad.   Request for muxer A/V pads. */
+               audio_pad = gst_element_get_request_pad(gst_handle->muxer, "audio_00");
+               aud_src = gst_element_get_static_pad(gst_handle->audioparse, "src");
+               if (gst_pad_link(aud_src, audio_pad) != GST_PAD_LINK_OK)
+                       MX_E("audio parser to muxer link failed");
+       }
+
+       MX_I("Output_uri= %s\n", gst_handle->output_uri);
+       g_object_set(GST_OBJECT(gst_handle->sink), "location",
+                    gst_handle->output_uri, NULL);
+
+       /* connect signals, bus watcher */
+       bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
+       gst_handle->bus_watch_id = gst_bus_add_watch(bus, _mx_gst_bus_call, gst_handle);
+       gst_object_unref(bus);
+
+       /* set pipeline state to PLAYING */
+       MEDIAMUXER_ELEMENT_SET_STATE(GST_ELEMENT_CAST(gst_handle->pipeline),
+                                    GST_STATE_PLAYING);
+       return MX_ERROR_NONE;
+
+STATE_CHANGE_FAILED:
+ERROR:
+
+       if (gst_handle->pipeline)
+               gst_object_unref(GST_OBJECT(gst_handle->pipeline));
+
+       if (gst_handle->video_track.track_index == 1) { /* Video track */
+               if (gst_handle->videoparse)
+                       gst_object_unref(GST_OBJECT(gst_handle->videoparse));
+
+               if (gst_handle->video_appsrc)
+                       gst_object_unref(GST_OBJECT(gst_handle->video_appsrc));
+       }
+
+       if (gst_handle->audio_track.track_index == 2) { /* audio track */
+               if (gst_handle->audio_appsrc)
+                       gst_object_unref(GST_OBJECT(gst_handle->audio_appsrc));
+               if (gst_handle->audioparse)
+                       gst_object_unref(GST_OBJECT(gst_handle->audioparse));
+       }
+
+       if (gst_handle->muxer)
+               gst_object_unref(GST_OBJECT(gst_handle->muxer));
+
+       if (gst_handle->sink)
+               gst_object_unref(GST_OBJECT(gst_handle->sink));
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_start(MMHandleType pHandle)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *new_mediamuxer = (mxgst_handle_t *) pHandle;
+
+       MX_I("__gst_muxer_start adding elements to the pipeline:%p\n", new_mediamuxer);
+       ret = _gst_create_pipeline(new_mediamuxer);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MX_E("muxer handle NULL, returning \n");
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int __gst_codec_specific_caps(GstCaps *new_cap,
+                              media_format_mimetype_e mimetype)
+{
+       MEDIAMUXER_FENTER();
+       GValue val = G_VALUE_INIT;
+       switch (mimetype) {
+                       /*video*/
+               case MEDIA_FORMAT_H261:
+                       break;
+               case MEDIA_FORMAT_H263:
+                       break;
+               case MEDIA_FORMAT_H263P:
+                       break;
+               case MEDIA_FORMAT_H264_SP:
+                       break;
+               case MEDIA_FORMAT_H264_MP:
+                       break;
+               case MEDIA_FORMAT_H264_HP:
+                       break;
+               case MEDIA_FORMAT_MJPEG:
+                       break;
+               case MEDIA_FORMAT_MPEG1:
+                       break;
+               case MEDIA_FORMAT_MPEG2_SP:
+                       break;
+               case MEDIA_FORMAT_MPEG2_MP:
+                       break;
+               case MEDIA_FORMAT_MPEG2_HP:
+                       break;
+               case MEDIA_FORMAT_MPEG4_SP:
+                       break;
+               case MEDIA_FORMAT_MPEG4_ASP:
+                       break;
+               case MEDIA_FORMAT_HEVC:
+                       break;
+               case MEDIA_FORMAT_VP8:
+                       break;
+               case MEDIA_FORMAT_VP9:
+                       break;
+               case MEDIA_FORMAT_VC1:
+                       break;
+               case MEDIA_FORMAT_I420:
+                       break;
+               case MEDIA_FORMAT_NV12:
+                       break;
+               case MEDIA_FORMAT_NV12T:
+                       break;
+               case MEDIA_FORMAT_YV12:
+                       break;
+               case MEDIA_FORMAT_NV21:
+                       break;
+               case MEDIA_FORMAT_NV16:
+                       break;
+               case MEDIA_FORMAT_YUYV:
+                       break;
+               case MEDIA_FORMAT_UYVY:
+                       break;
+               case MEDIA_FORMAT_422P:
+                       break;
+               case MEDIA_FORMAT_RGB565:
+                       break;
+               case MEDIA_FORMAT_RGB888:
+                       break;
+               case MEDIA_FORMAT_RGBA:
+                       break;
+               case MEDIA_FORMAT_ARGB:
+                       break;
+                       /*audio*/
+               case MEDIA_FORMAT_L16:
+                       break;
+               case MEDIA_FORMAT_ALAW:
+                       break;
+               case MEDIA_FORMAT_ULAW:
+                       break;
+               case MEDIA_FORMAT_AMR:
+                       break;
+               case MEDIA_FORMAT_AMR_WB:
+                       break;
+               case MEDIA_FORMAT_G729:
+                       break;
+               case MEDIA_FORMAT_AAC:
+                       g_value_init(&val, G_TYPE_INT);
+                       g_value_set_int(&val, 4);
+                       gst_caps_set_value(new_cap, "mpegversion", &val);
+                       break;
+               case MEDIA_FORMAT_AAC_HE:
+                       g_value_init(&val, G_TYPE_INT);
+                       g_value_set_int(&val, 4);
+                       gst_caps_set_value(new_cap, "mpegversion", &val);
+                       break;
+               case MEDIA_FORMAT_AAC_HE_PS:
+                       g_value_init(&val, G_TYPE_INT);
+                       g_value_set_int(&val, 4);
+                       gst_caps_set_value(new_cap, "mpegversion", &val);
+                       break;
+               case MEDIA_FORMAT_MP3:
+                       break;
+               case MEDIA_FORMAT_VORBIS:
+                       break;
+               case MEDIA_FORMAT_PCM:
+                       break;
+               case MEDIA_FORMAT_PCMA:
+                       break;
+               case MEDIA_FORMAT_PCMU:
+                       break;
+               default:
+                       MX_E("Unknown media mimeype %d. Assuming H264\n", mimetype);
+                       break;
+       }
+       MEDIAMUXER_FLEAVE();
+       return 0;
+}
+
+
+int _gst_set_caps(MMHandleType pHandle, media_packet_h packet)
+{
+       MEDIAMUXER_FENTER();
+       gint ret = MX_ERROR_NONE;
+       GstCaps *new_cap;
+       media_format_mimetype_e mimetype;
+       media_format_h format;
+       GValue val = G_VALUE_INIT;
+       int numerator;
+       int denominator = 1;
+       int channel;
+       int samplerate;
+       int bit;
+       int width;
+       int height;
+       int avg_bps;
+       int max_bps;
+       gchar *caps_string = NULL;
+
+       mxgst_handle_t *gst_handle = (mxgst_handle_t *) pHandle;
+       media_format_type_e formattype;
+       char *codec_data;
+       unsigned int codec_data_size;
+
+       if (media_packet_get_format(packet, &format)) {
+               MX_E("media_format_get_formati call failed \n");
+               goto ERROR;
+       }
+
+       if (media_format_get_type(format, &formattype)) {
+               MX_E("media_format_get_type failed\n");
+               goto ERROR;
+       }
+
+       switch (formattype) {
+               case MEDIA_FORMAT_AUDIO:
+                       if (media_packet_get_codec_data(packet,
+                                                       (void **)&codec_data, &codec_data_size)) {
+                               MX_E("media_packet_get_codec_data call failed\n");
+                               ret = MX_ERROR_UNKNOWN;
+                               break;
+                       }
+                       MX_I("extracted codec data is =%s size is %d\n",
+                            codec_data, codec_data_size);
+                       if (gst_handle->audio_track.caps == NULL ||
+                           g_strcmp0(codec_data, gst_handle->audio_track.caps) != 0) {
+
+#ifndef SEND_FULL_CAPS_VIA_CODEC_DATA
+
+                               if (media_format_get_audio_info(format,
+                                                               &mimetype, &channel, &samplerate,
+                                                               &bit, &avg_bps)) {
+                                       MX_E("media_format_get_audio_info call failed\n");
+                                       ret = MX_ERROR_UNKNOWN;
+                                       break;
+                               }
+                               if (gst_handle->audio_track.caps == NULL) {
+                                       gst_handle->audio_track.caps =
+                                           (char *)g_malloc(codec_data_size);
+                                       if (gst_handle->audio_track.caps == NULL) {
+                                               MX_E("[%s][%d]memory allocation failed\n",
+                                                    __func__, __LINE__);
+                                               ret = MX_ERROR_UNKNOWN;
+                                               break;
+                                       }
+                               }
+                               new_cap = gst_caps_from_string(codec_data);
+                               if (__gst_codec_specific_caps(new_cap, mimetype)) {
+                                       MX_E("Setting Audio caps failed\n");
+                                       gst_caps_unref(new_cap);
+                                       ret = MX_ERROR_UNKNOWN;
+                                       break;
+                               }
+                               caps_string = gst_caps_to_string(new_cap);
+                               MX_I("New cap set by codec data is=%s\n",
+                                    caps_string);
+                               if (caps_string)
+                                       g_free(caps_string);
+                               g_object_set(gst_handle->audio_appsrc,
+                                            "caps", new_cap, NULL);
+                               g_stpcpy(gst_handle->audio_track.caps, codec_data);
+#else
+                               /*Debugging purpose. The whole caps filter can be sent via codec_data*/
+                               new_cap = gst_caps_from_string(codec_data);
+                               MX_I("codec  cap is=%s\n", codec_data);
+                               g_object_set(gst_handle->audio_appsrc,
+                                            "caps", new_cap, NULL);
+                               if (gst_handle->audio_track.caps == NULL) {
+                                       gst_handle->audio_track.caps =
+                                           (char *)g_malloc(codec_data_size);
+                                       if (gst_handle->audio_track.caps == NULL) {
+                                               MX_E("[%s][%d] \
+                                       memory allocation failed\n",
+                                                    __func__, __LINE__);
+                                               gst_caps_unref(new_cap);
+                                               ret = MX_ERROR_UNKNOWN;
+                                               break;
+                                       }
+                               }
+                               g_stpcpy(gst_handle->audio_track.caps, codec_data);
+#endif
+                               gst_caps_unref(new_cap);
+                       }
+                       break;
+               case MEDIA_FORMAT_VIDEO:
+                       if (media_packet_get_codec_data(packet,
+                                                       (void **)&codec_data, &codec_data_size)) {
+                               MX_E("media_packet_get_codec_data call failed\n");
+                               ret = MX_ERROR_UNKNOWN;
+                               break;
+                       }
+                       MX_I("codec data is =%s size is %d\n",
+                            codec_data, codec_data_size);
+                       if (gst_handle->video_track.caps == NULL ||
+                           g_strcmp0(codec_data, gst_handle->video_track.caps) != 0) {
+
+#ifndef SEND_FULL_CAPS_VIA_CODEC_DATA
+
+                               if (media_format_get_video_info(format,
+                                                               &mimetype, &width, &height,
+                                                               &avg_bps, &max_bps)) {
+                                       MX_E("media_format_get_video_info call failed\n");
+                                       ret = MX_ERROR_UNKNOWN;
+                                       break;
+                               }
+                               if (gst_handle->video_track.caps == NULL) {
+                                       gst_handle->video_track.caps =
+                                           (char *)g_malloc(codec_data_size);
+                                       if (gst_handle->video_track.caps == NULL) {
+                                               MX_E("[%s][%d] \
+                                       memory allocation failed\n",
+                                                    __func__, __LINE__);
+                                               ret = MX_ERROR_UNKNOWN;
+                                               break;
+                                       }
+                               }
+                               new_cap = gst_caps_from_string(codec_data);
+                               MX_I("New cap set by codec data is=%s\n",
+                                    codec_data);
+                               if (__gst_codec_specific_caps(new_cap, mimetype)) {
+                                       MX_E("Setting Audio caps failed\n");
+                                       gst_caps_unref(new_cap);
+                                       ret = MX_ERROR_UNKNOWN;
+                                       break;
+                               }
+                               g_stpcpy(gst_handle->video_track.caps, codec_data);
+
+                               if (media_format_get_video_frame_rate(format,
+                                                                     &numerator)) {
+                                       MX_E("media_format_get_video_info call failed\n");
+                               }
+                               g_value_init(&val, GST_TYPE_FRACTION);
+                               gst_value_set_fraction(&val, numerator, denominator);
+                               gst_caps_set_value(new_cap, "framerate", &val);
+                               caps_string = gst_caps_to_string(new_cap);
+                               MX_I("New cap set by codec data is=%s\n",
+                                    caps_string);
+                               if (caps_string)
+                                       g_free(caps_string);
+                               g_object_set(gst_handle->video_appsrc, "caps",
+                                            new_cap, NULL);
+#else
+                               /*Debugging purpose. The whole caps filter can be sent via codec_data*/
+                               media_packet_get_codec_data(packet, &codec_data,
+                                                           &codec_data_size);
+                               MX_I("extracted codec data is =%s\n", codec_data);
+                               new_cap = gst_caps_from_string(codec_data);
+                               MX_I("New cap is=%s\n", codec_data);
+                               g_object_set(gst_handle->video_appsrc, "caps",
+                                            new_cap, NULL);
+                               if (gst_handle->video_track.caps == NULL) {
+                                       gst_handle->video_track.caps =
+                                           (char *)g_malloc(codec_data_size);
+                                       if (gst_handle->video_track.caps == NULL) {
+                                               MX_E("[%s][%d] \
+                                       memory allocation failed\n",
+                                                    __func__, __LINE__);
+                                               gst_caps_unref(new_cap);
+                                               ret = MX_ERROR_UNKNOWN;
+                                               break;
+                                       }
+                               }
+                               g_stpcpy(gst_handle->video_track.caps, codec_data);
+#endif
+                               gst_caps_unref(new_cap);
+                       }
+                       break;
+               case MEDIA_FORMAT_CONTAINER:
+               case MEDIA_FORMAT_TEXT:
+               case MEDIA_FORMAT_UNKNOWN:
+               default:
+                       MX_E("Unknown format type\n");
+       }
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_UNKNOWN;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int _gst_copy_media_packet_to_buf(media_packet_h out_pkt,
+                                         GstBuffer *buffer)
+{
+       MEDIAMUXER_FENTER();
+       void *pkt_data;
+       uint64_t size;
+       unsigned char *data_ptr;
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(out_pkt);
+       /* GstMapInfo map; */
+       int ret = MX_ERROR_NONE;
+       /* copy data*/
+       media_packet_get_buffer_size(out_pkt, &size);
+       MX_I("Media packet Buffer capacity: %llu\n", size);
+       data_ptr = (unsigned char *) g_malloc(size);
+       if (!data_ptr) {
+               MX_E("Memory allocation failed in %s \n", __FUNCTION__);
+               ret = MX_MEMORY_ERROR;
+               goto ERROR;
+       }
+
+       if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
+               MX_E("unable to get the buffer pointer \
+                               from media_packet_get_buffer_data_ptr\n");
+               ret = MX_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       /*if (!gst_buffer_map (buffer, &map, GST_MAP_READ)) {
+               MX_E("gst_buffer_map failed\n");
+               ret = MX_ERROR_UNKNOWN;
+               goto ERROR;
+       }*/
+       uint64_t info;
+       memcpy(data_ptr, (char *)pkt_data, size);
+       gst_buffer_insert_memory(buffer, -1,
+                                gst_memory_new_wrapped(0, data_ptr, size, 0,
+                                                       size, data_ptr, g_free));
+
+       if (media_packet_get_pts(out_pkt, &info)) {
+               MX_E("unable to get the pts\n");
+               ret = MX_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       buffer->pts = info;
+
+       if (media_packet_get_dts(out_pkt, &info)) {
+               MX_E("unable to get the dts\n");
+               ret = MX_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       buffer->dts = info;
+       if (media_packet_get_duration(out_pkt, &info)) {
+               MX_E("unable to get the duration\n");
+               ret = MX_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       buffer->duration = info;
+       /*TBD: set falgs is not available now in media_packet*/
+       media_buffer_flags_e flags;
+       if (media_packet_get_flags(out_pkt, &flags)) {
+               MX_E("unable to get the buffer size\n");
+               ret = MX_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       GST_BUFFER_FLAG_SET(buffer, flags);
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_write_sample(MMHandleType pHandle, int track_index,
+                                         media_packet_h inbuf)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *gst_handle = (mxgst_handle_t *) pHandle;
+
+       _gst_set_caps(pHandle, inbuf);
+       MX_I("\nTrack_index=%d", track_index);
+
+       GstBuffer *gst_inbuf2 = NULL;
+       gst_inbuf2 = gst_buffer_new();
+       /* ToDo: Add functionality to the following function */
+       /* MX_I("\nBefore  buff=%x", gst_inbuf2); */
+       _gst_copy_media_packet_to_buf(inbuf, gst_inbuf2);
+
+       if ((gst_handle->video_track.track_index != -1) &&
+             (track_index == gst_handle->video_track.track_index)) {
+               MX_I("\n pushing video");
+#ifdef ASYCHRONOUS_WRITE
+               /*poll now to make it synchronous*/
+               while (gst_handle->video_track.start_feed == 0) {
+                       g_usleep(WRITE_POLL_PERIOD);
+               }
+               g_signal_emit_by_name(gst_handle->video_appsrc, "push-buffer", gst_inbuf2, &ret);
+#else
+               ret = gst_app_src_push_buffer((GstAppSrc *)gst_handle->video_appsrc, gst_inbuf2);
+#endif
+               MX_I("\n attempted a vid-buf push");
+               if (ret != GST_FLOW_OK) {
+                       /* We got some error, stop sending data */
+                       MX_E("--video appsrc push failed--");
+               }
+       } else if ((gst_handle->audio_track.track_index != -1) &&
+                       (track_index == gst_handle->audio_track.track_index)) {
+               MX_I("\n pushing audio");
+#ifdef ASYCHRONOUS_WRITE
+               while (gst_handle->audio_track.start_feed == 0) {
+                       g_usleep(WRITE_POLL_PERIOD);
+               }
+               g_signal_emit_by_name(gst_handle->audio_appsrc, "push-buffer", gst_inbuf2, &ret);
+#else
+               ret = gst_app_src_push_buffer((GstAppSrc *)gst_handle->audio_appsrc, gst_inbuf2);
+#endif
+               MX_I("\n attempted a aud-buf push");
+               if (ret != GST_FLOW_OK) {
+                       /* We got some error, stop sending data */
+                       MX_E("--audio appsrc push failed--");
+               }
+       } else {
+               MX_E("\nUnsupported track index. Only 1/2 track index is vaild");
+               ret = MX_ERROR_INVALID_ARGUMENT;
+       }
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_close_track(MMHandleType pHandle, int track_index)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *gst_handle = (mxgst_handle_t *) pHandle;
+
+       MX_I("__gst_muxer_stop setting eos to sources:%p\n", gst_handle);
+       if (gst_handle->pipeline!= NULL) {
+               if (gst_handle->audio_track.track_index == track_index) {
+                       MX_I("\n-----EOS for audioappsrc-----\n");
+                       gst_app_src_end_of_stream((GstAppSrc *)(gst_handle->audio_appsrc));
+               } else if (gst_handle->video_track.track_index == track_index) {
+                       MX_I("\n-----EOS for videoappsrc-----\n");
+                       gst_app_src_end_of_stream((GstAppSrc *)(gst_handle->video_appsrc));
+               } else {
+                       MX_E("\nInvalid track Index[%d].\n", track_index);
+                       goto ERROR;
+               }
+       }
+       if (gst_handle->audio_track.track_index == track_index) {
+               gst_handle->audio_track.media_format = NULL;
+               gst_handle->audio_track.track_index  = -1;
+       } else if (gst_handle->video_track.track_index == track_index) {
+               gst_handle->video_track.media_format = NULL;
+               gst_handle->video_track.track_index  = -1;
+       }
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_pause(MMHandleType pHandle)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *gst_handle = (mxgst_handle_t *) pHandle;
+
+       GstState state;
+       MX_I("gst_muxer_pause setting pipeline to pause");
+       gst_element_get_state(gst_handle->pipeline, &state, NULL, GST_CLOCK_TIME_NONE);
+       if (state == GST_STATE_PLAYING) {
+               if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
+                        GST_STATE_CHANGE_FAILURE) {
+                       MX_I("Setting pipeline to pause failed");
+                       ret = MX_ERROR_INVALID_ARGUMENT;
+               }
+       } else {
+               MX_I("pipeline is not in playing, PAUSE is intended to pause a playing pipeline. \
+                       exiting with out state change");
+               ret = MX_ERROR_INVALID_ARGUMENT;
+       }
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_resume(MMHandleType pHandle)
+{
+       MEDIAMUXER_FENTER();
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       int ret = MX_ERROR_NONE;
+       mxgst_handle_t *gst_handle = (mxgst_handle_t *) pHandle;
+
+       MX_I("gst_muxer_resume setting pipeline to playing");
+       if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PLAYING) ==
+                GST_STATE_CHANGE_FAILURE) {
+               MX_I("Setting pipeline to resume failed");
+               ret = MX_ERROR_INVALID_ARGUMENT;
+       }
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+mx_ret_e _gst_destroy_pipeline(mxgst_handle_t *gst_handle)
+{
+       gint ret = MX_ERROR_NONE;
+       MEDIAMUXER_FENTER();
+
+       /* Clean up nicely */
+       gst_element_set_state(gst_handle->pipeline, GST_STATE_NULL);
+
+       /* Free resources & set unused pointers to NULL */
+       if (gst_handle->output_uri != NULL) {
+               gst_handle->output_uri = NULL;
+       }
+
+       if (gst_handle->video_track.track_index == 1) { /* Video track */
+               if (gst_handle->video_track.caps != NULL) {
+                       g_free(gst_handle->video_track.caps);
+               }
+
+               if (gst_handle->video_track.media_format != NULL) {
+                       gst_handle->video_track.media_format = NULL;
+               }
+       }
+
+       if (gst_handle->audio_track.track_index == 2) { /* audio track */
+               if (gst_handle->audio_track.caps != NULL) {
+                       g_free(gst_handle->audio_track.caps);
+               }
+
+               if (gst_handle->audio_track.media_format != NULL) {
+                       gst_handle->audio_track.media_format = NULL;
+               }
+       }
+
+       if (gst_handle->pipeline)
+               gst_object_unref(GST_OBJECT(gst_handle->pipeline));
+
+       g_source_remove(gst_handle->bus_watch_id);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_stop(MMHandleType pHandle)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *gst_handle = (mxgst_handle_t *) pHandle;
+
+       MX_I("__gst_muxer_stop setting eos to sources:%p\n", gst_handle);
+       ret = _gst_destroy_pipeline(gst_handle);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MX_ERROR_INVALID_ARGUMENT;
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_muxer_destroy(MMHandleType pHandle)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *new_mediamuxer = (mxgst_handle_t *) pHandle;
+
+       MX_I("__gst_muxer_destroy deallocating new_mediamuxer:%p\n",  new_mediamuxer);
+       g_free(new_mediamuxer);
+       MEDIAMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MX_E("muxer handle already NULL, returning \n");
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
+
+int gst_set_error_cb(MMHandleType pHandle, gst_error_cb callback, void* user_data)
+{
+       MEDIAMUXER_FENTER();
+       int ret = MX_ERROR_NONE;
+       MEDIAMUXER_CHECK_NULL(pHandle);
+       mxgst_handle_t *gst_handle = (mxgst_handle_t *) pHandle;
+
+       if (!gst_handle) {
+               MX_E("fail invaild param\n");
+               ret = MX_INVALID_ARG;
+               goto ERROR;
+       }
+
+       if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
+               MX_E("Already set mediamuxer_error_cb\n");
+               ret = MX_ERROR_INVALID_ARGUMENT;
+               goto ERROR;
+       }
+       else {
+               if (!callback) {
+                       ret = MX_ERROR_INVALID_ARGUMENT;
+                       goto ERROR;
+               }
+       }
+
+       MX_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
+       gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb) callback;
+       gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
+       MEDIAMUXER_FLEAVE();
+       return MX_ERROR_NONE;
+ERROR:
+       MEDIAMUXER_FLEAVE();
+       return ret;
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f0f24d2
--- /dev/null
@@ -0,0 +1,23 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(fw_test "${fw_name}-test")
+
+INCLUDE_DIRECTORIES(../include)
+INCLUDE_DIRECTORIES(../include/headers)
+link_directories(${CMAKE_SOURCE_DIR}/../)
+
+INCLUDE(FindPkgConfig)
+FOREACH(flag ${${fw_test}_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+aux_source_directory(. sources)
+
+FOREACH(src ${sources})
+    GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+    MESSAGE("${src_name}")
+    ADD_EXECUTABLE(${src_name} ${src})
+    TARGET_LINK_LIBRARIES(${src_name} capi-mediamuxer ${${fw_test}_LDFLAGS})
+ENDFOREACH()
+
diff --git a/test/mediamuxer_test.c b/test/mediamuxer_test.c
new file mode 100644 (file)
index 0000000..f5e57f6
--- /dev/null
@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 2015 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 FILES                                                               |
+|                                                                              |
+==============================================================================*/
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <mm_error.h>
+#include <mm_debug.h>
+#include "../include/mediamuxer_port.h"
+#include <mediamuxer.h>
+#include <mediamuxer_private.h>
+#include <media_packet_internal.h>
+/* Read encoded medial files locally: encoded A/V files along with info & caps */
+#define H264_FILE video_data
+#define H264_INFO video_extra_info
+#define AAC_FILE audio_data
+#define AAC_INFO  audio_extra_info
+
+/*-----------------------------------------------------------------------
+|    GLOBAL VARIABLE DEFINITIONS:                                       |
+-----------------------------------------------------------------------*/
+#define MAX_STRING_LEN 100
+#define PACKAGE "mediamuxer_test"
+
+mediamuxer_h myMuxer = 0;
+media_format_h media_format = NULL;
+media_format_h media_format_a = NULL;
+
+bool aud_eos = 0;
+bool vid_eos = 0;
+char audio_extra_info[1000];
+char audio_data[1000];
+char video_extra_info[1000];
+char video_data[1000];
+
+int test_mediamuxer_create()
+{
+       g_print("test_mediamuxer_create\n");
+       g_print("%p", myMuxer);
+
+       if (mediamuxer_create(&myMuxer)
+           != MEDIAMUXER_ERROR_NONE) {
+               g_print("mediamuxer create is failed\n");
+       }
+       g_print("\n Muxer->mx_handle created successfully with address=%p",
+               (void *)((mediamuxer_s *) myMuxer)->mx_handle);
+       g_print("\n Muxer handle created successfully with address=%p",
+               myMuxer);
+
+       return 0;
+}
+
+int test_mediamuxer_set_data_sink()
+{
+       char *op_uri = "MyTest.mp4";
+
+       /* Set data source after creating */
+       mediamuxer_set_data_sink(myMuxer, op_uri, MEDIAMUXER_CONTAINER_FORMAT_MP4);
+       return 0;
+}
+
+int test_mediamuxer_destroy()
+{
+       int ret = 0;
+       g_print("test_mediamuxer_destroy\n");
+       ret = mediamuxer_destroy(myMuxer);
+       myMuxer = NULL;
+       g_print("\nDestroy operation returned: %d\n", ret);
+       return ret;
+}
+
+int test_mediamuxer_start()
+{
+       g_print("mediamuxer_start completed \n");
+       mediamuxer_start(myMuxer);
+       return 0;
+}
+
+int test_mediamuxer_add_track_video()
+{
+       int track_index_vid = -1;
+       media_format_mimetype_e mimetype;
+       int width;
+       int height;
+       int avg_bps;
+       int max_bps;
+
+       g_print("test_mediamuxer_add_track_video\n");
+       media_format_create(&media_format);
+
+       /* MEDIA_FORMAT_H264_SP  MEDIA_FORMAT_H264_MP  MEDIA_FORMAT_H264_HP */
+       media_format_set_video_mime(media_format, MEDIA_FORMAT_H264_SP);
+
+       media_format_set_video_width(media_format, 640);
+       media_format_set_video_height(media_format, 480);
+       media_format_set_video_avg_bps(media_format, 10);
+       media_format_set_video_max_bps(media_format, 10);
+
+       media_format_get_video_info(media_format, &mimetype, &width, &height, &avg_bps, &max_bps);
+
+       g_print("\n Video Mime trying to set: %x   %x\n", (int)(mimetype), (int)(MEDIA_FORMAT_H264_SP));
+       g_print("\n Video param trying to set: (width, height, avg_bps, max_bps): %d %d %d %d  \n",
+               width, height, avg_bps, max_bps);
+
+       /* To add video track */
+       mediamuxer_add_track(myMuxer, media_format, &track_index_vid);
+       g_print("audio track index returned is: %d", track_index_vid);
+       return 0;
+}
+
+int test_mediamuxer_add_track_audio()
+{
+       int track_index_aud = -1;
+       media_format_mimetype_e mimetype;
+       int channel;
+       int samplerate;
+       int bit;
+       int avg_bps;
+
+       g_print("test_mediamuxer_add_track\n");
+       media_format_create(&media_format_a);
+
+       /* MEDIA_FORMAT_AAC  MEDIA_FORMAT_AAC_LC  MEDIA_FORMAT_AAC_HE  MEDIA_FORMAT_AAC_HE_PS */
+       if (media_format_set_audio_mime(media_format_a, MEDIA_FORMAT_AAC) == MEDIA_FORMAT_ERROR_INVALID_OPERATION)
+               g_print("Problem during media_format_set_audio_mime operation");
+
+       if (media_format_set_audio_channel(media_format_a, 2) == MEDIA_FORMAT_ERROR_INVALID_OPERATION)
+               g_print("Problem during media_format_set_audio_channel operation");
+       media_format_set_audio_samplerate(media_format_a, 44000);
+       media_format_set_audio_bit(media_format_a, 1);
+       media_format_set_audio_avg_bps(media_format_a, 10);
+       media_format_set_audio_aac_type(media_format_a, true);
+
+       media_format_get_audio_info(media_format_a, &mimetype, &channel, &samplerate, &bit, &avg_bps);
+
+       g_print("\n Audio Mime trying to set: %x   %x\n", (int)(mimetype), (int)(MEDIA_FORMAT_AAC));
+       g_print("\n Audio Param trying to set: (ch, samplert, bt, avg_bps) %d %d %d %d \n",
+               channel, samplerate, bit, avg_bps);
+
+       /* To add audio track */
+       mediamuxer_add_track(myMuxer, media_format_a, &track_index_aud);
+       g_print("track index returned is: %d", track_index_aud);
+       return 0;
+}
+
+void app_err_cb(mediamuxer_error_e error, void *user_data)
+{
+       printf("Got Error %d from mediamuxer\n",error);
+}
+
+int test_mediamuxer_set_error_cb()
+{
+       int ret = 0;
+       g_print("test_mediamuxer_set_error_cb\n");
+       ret = mediamuxer_set_error_cb(myMuxer, app_err_cb, myMuxer);
+       return ret;
+}
+
+void *_write_video_data()
+{
+       FILE *pvFile;
+       FILE *pvFileInfo;
+       unsigned int size;
+       unsigned int vsize;
+       unsigned int is_video_readable = 1;
+       unsigned int is_video_pts_readable;
+       unsigned int is_video_dts_readable;
+       unsigned int is_video_duration_readable;
+       unsigned int is_video_flag_readable;
+       unsigned int is_video_key_readable;
+       unsigned long long int pts_vid;
+       unsigned long long int dts_vid;
+       unsigned long long int duration_vid;
+       int flg_vid;
+       int *status = (int *)g_malloc(sizeof(int) * 1);
+       *status = -1;
+       int track_index_vid = 1; /* track_index=2 for video */
+       int vcount = 0;
+       guint8 *ptr_vid;
+       int key_vid;
+       char *vid_caps;
+       int ret_scan;
+       media_packet_h vid_pkt;
+       media_format_h vidfmt;
+       unsigned int vcap_size;
+
+       pvFile = fopen(H264_FILE, "rb");
+       pvFileInfo = fopen(H264_INFO, "rt");
+
+       if (pvFile == NULL || pvFileInfo == NULL) {
+               g_print("\nOne of the files (info/data) cant be loaded...\n");
+               return (void *)status;
+       }
+
+       ret_scan = fscanf(pvFileInfo, "%d\n", &size);
+       vid_caps = (char *)malloc(size + 1);
+       ret_scan = fscanf(pvFileInfo, "%[^\n]s\n", vid_caps);
+       g_print("\nV_Caps = %s\n", vid_caps);
+       vcap_size = size + 1;
+
+       if (!ret_scan) { /* ToDo: repeat the same for every scanf */
+               g_print("\nscan failed");
+               return (void *)status;
+       }
+
+       while (is_video_readable == 1) {
+               /* Read encoded video data */
+               is_video_readable = fscanf(pvFileInfo, "%d\n", &vsize);
+               is_video_pts_readable = fscanf(pvFileInfo, "%llu\n", &pts_vid);
+               is_video_dts_readable = fscanf(pvFileInfo, "%llu\n", &dts_vid);
+               is_video_duration_readable = fscanf(pvFileInfo, "%llu\n", &duration_vid);
+               is_video_flag_readable = fscanf(pvFileInfo, "%u\n", &flg_vid);
+               is_video_key_readable = fscanf(pvFileInfo, "%d\n", &key_vid);
+
+               if (is_video_readable == 1 && is_video_pts_readable == 1 && is_video_dts_readable == 1
+                   && is_video_duration_readable == 1 && is_video_flag_readable == 1
+                   && is_video_key_readable == 1) {
+                       g_print("\nv%d: ", ++vcount);
+                       g_print("\nv_Size: %d, v_pts: %llu, v_dts: %llu v_duration: %llu, v_flag: %d",
+                               vsize, pts_vid, dts_vid, duration_vid, key_vid);
+                       ptr_vid = g_malloc(vsize);
+                       g_assert(ptr_vid);
+                       vsize = fread(ptr_vid, 1, vsize, pvFile);
+
+                       if (media_format_create(&vidfmt)) {
+                               g_print("media_format_create failed\n");
+                               return (void *)status;
+                       }
+                       if (media_format_set_video_mime(vidfmt, MEDIA_FORMAT_H264_SP)) {
+                               g_print("media_format_set_audio_mime failed\n");
+                               return (void *)status;
+                       }
+                       media_format_set_video_width(vidfmt, vsize / 2 + 1);
+                       media_format_set_video_height(vidfmt, vsize / 2 + 1);
+                       /*frame rate is came from the caps filter of demuxer*/
+                       if (media_format_set_video_frame_rate(vidfmt, 30)) {
+                               g_print("media_format_set_video_frame_rate failed\n");
+                               return (void *)status;
+                       }
+
+                       uint64_t ns;
+                       guint8 *dptr;
+
+                       if (media_packet_create(vidfmt, NULL, NULL, &vid_pkt)) {
+                               g_print("\ncreate v media packet failed tc\n");
+                               return (void *)status;
+                       }
+
+                       if (media_packet_alloc(vid_pkt)) {
+                               g_print(" v media packet alloc failed\n");
+                               return (void *)status;
+                       }
+                       media_packet_get_buffer_data_ptr(vid_pkt, (void **)&dptr);
+                       media_packet_get_buffer_size(vid_pkt, &ns);
+                       g_print("set v buf size as %d, data size=%d\n", (int)ns, vsize);
+
+                       memcpy((char *)dptr, ptr_vid, vsize);
+                       if (media_packet_set_buffer_size(vid_pkt, vsize)) {
+                               g_print("set v buf size failed\n");
+                               return (void *)status;
+                       }
+
+
+                       if (media_packet_get_buffer_size(vid_pkt, &ns)) {
+                               g_print("unable to set the v buffer size actual =%d, fixed %d\n", size, (int)ns);
+                               return (void *)status;
+                       }
+                       g_print(" fixed size %d\n", (int)ns);
+
+                       if (media_packet_set_pts(vid_pkt, pts_vid)) {
+                               g_print("unable to set the pts\n");
+                               return (void *)status;
+                       }
+                       if (media_packet_set_dts(vid_pkt, dts_vid)) {
+                               g_print("unable to set the pts\n");
+                               return (void *)status;
+                       }
+                       if (media_packet_set_duration(vid_pkt, duration_vid)) {
+                               g_print("unable to set the pts\n");
+                               return (void *)status;
+                       }
+
+                       if (media_packet_set_flags(vid_pkt, flg_vid)) {
+                               g_print("unable to set the flag size\n");
+                               return (void *)status;
+                       }
+                       if (media_packet_set_codec_data(vid_pkt, vid_caps, vcap_size)) {
+                               g_print("unable to set the flag size\n");
+                               return (void *)status;
+                       }
+
+
+                       g_print("V write sample call. packet add:%x\n", (unsigned int)vid_pkt);
+                       mediamuxer_write_sample(myMuxer, track_index_vid, vid_pkt);
+
+                       media_packet_destroy(vid_pkt);
+               } else {
+                       g_print("\nVideo while done in the test suite");
+                       mediamuxer_close_track(myMuxer, track_index_vid);
+               }
+       }
+       g_print("\n\n\n ******* Out of while loop ****** \n\n\n");
+       fclose(pvFile);
+       fclose(pvFileInfo);
+       *status = 0;
+       return (void *)status;
+}
+
+void *_write_audio_data()
+{
+       FILE *paFile;
+       FILE *paFileInfo;
+       unsigned int size;
+       unsigned int is_audio_readable = 1;
+       unsigned int is_audio_pts_readable;
+       unsigned int is_audio_dts_readable;
+       unsigned int is_audio_duration_readable;
+       unsigned int is_audio_flag_readable;
+       unsigned int is_audio_key_readable;
+       unsigned char *ptr1;
+       unsigned long long int pts;
+       unsigned long long int dts;
+       unsigned long long int duration;
+       int flg;
+
+       int key;
+       int acount = 0;
+       int track_index_aud = 2; /* track_index=2 for audio */
+       char *aud_caps;
+       int ret_scan;
+       media_packet_h aud_pkt;
+       media_format_h audfmt;
+       unsigned int acap_size;
+       int *status = (int *)g_malloc(sizeof(int) * 1);
+       *status = -1;
+
+       paFileInfo = fopen(AAC_INFO, "rt");
+       paFile = fopen(AAC_FILE, "rb");
+
+       if (paFile == NULL || paFileInfo == NULL) {
+               g_print("\nOne of the files (info/data) cant be loaded...\n");
+               return (void *)status;
+       }
+
+       ret_scan = fscanf(paFileInfo, "%d\n", &size);
+       aud_caps = (char *)malloc(1 + size);
+       ret_scan = fscanf(paFileInfo, "%[^\n]s\n", aud_caps);
+       g_print("\nA_Caps = %s\n", aud_caps);
+       acap_size = size + 1;
+
+       if (!ret_scan) { /* ToDo: repeat the same for every scanf */
+               g_print("\nscan failed");
+               return (void *)status;
+       }
+
+       while (is_audio_readable == 1) {
+
+               /* Read encoded audio data */
+               is_audio_readable = fscanf(paFileInfo, "%d\n", &size);
+               is_audio_pts_readable = fscanf(paFileInfo, "%llu\n", &pts);
+               is_audio_dts_readable = fscanf(paFileInfo, "%llu\n", &dts);
+               is_audio_duration_readable = fscanf(paFileInfo, "%llu\n", &duration);
+               is_audio_flag_readable = fscanf(paFileInfo, "%u\n", &flg);
+               is_audio_key_readable = fscanf(paFileInfo, "%d\n", &key);
+
+               if (is_audio_readable == 1 && is_audio_pts_readable == 1
+                   && is_audio_dts_readable == 1 && is_audio_duration_readable == 1
+                   && is_audio_flag_readable == 1 && is_audio_key_readable == 1) {
+                       g_print("\na%d: ", ++acount);
+                       g_print("\nSize: %d, a_pts: %llu, a_dts: %llu, a_duration: %llu, a_flag:%d, a_key:%d",
+                               size, pts, dts, duration, flg, key);
+
+                       if (media_format_create(&audfmt)) {
+                               g_print("media_format_create failed\n");
+                               return (void *)status;
+                       }
+                       if (media_format_set_audio_mime(audfmt, MEDIA_FORMAT_AAC)) {
+                               g_print("media_format_set_audio_mime failed\n");
+                               return (void *)status;
+                       }
+
+                       ptr1 = g_malloc(size);
+                       g_assert(ptr1);
+
+                       size = fread(ptr1, 1, size, paFile);
+
+                       /* To create media_pkt */
+                       uint64_t ns;
+                       guint8 *dptr;
+
+                       if (media_packet_create(audfmt, NULL, NULL, &aud_pkt)) {
+                               g_print("create audio media_packet failed\n");
+                               return (void *)status;
+                       }
+
+                       if (media_packet_alloc(aud_pkt)) {
+                               g_print("audio media_packet alloc failed\n");
+                               return (void *)status;
+                       }
+                       media_packet_get_buffer_data_ptr(aud_pkt, (void **)&dptr);
+                       memcpy((char *)dptr, ptr1, size);
+
+                       if (media_packet_set_buffer_size(aud_pkt, (uint64_t)size)) {
+                               g_print("audio set_buffer_size failed\n");
+                               return (void *)status;
+                       }
+
+                       if (media_packet_get_buffer_size(aud_pkt, &ns)) {
+                               g_print("unable to set the buffer size actual =%d, fixed %d\n", size, (int)&ns);
+                               return (void *)status;
+                       }
+
+                       g_print(" fixed size %d\n", (int)ns);
+
+                       if (media_packet_set_pts(aud_pkt, pts)) {
+                               g_print("unable to set the pts\n");
+                               return (void *)status;
+                       }
+
+                       if (media_packet_set_dts(aud_pkt, dts)) {
+                               g_print("unable to set the pts\n");
+                               return (void *)status;
+                       }
+
+                       if (media_packet_set_duration(aud_pkt, duration)) {
+                               g_print("unable to set the pts\n");
+                               return (void *)status;
+                       }
+
+                       if (media_packet_set_flags(aud_pkt, key)) {
+                               g_print("unable to set the flag size\n");
+                               return (void *)status;
+                       }
+                       if (media_packet_set_codec_data(aud_pkt, aud_caps, acap_size)) {
+                               g_print("unable to set the audio codec data e\n");
+                               return (void *)status;
+                       }
+
+
+                       g_print("A write sample call. packet add:%x\n", (unsigned int)aud_pkt);
+                       mediamuxer_write_sample(myMuxer, track_index_aud, aud_pkt);
+
+                       media_packet_destroy(aud_pkt);
+               } else {
+                       g_print("\nAudio while done in the test suite");
+                       mediamuxer_close_track(myMuxer, track_index_aud);
+               }
+
+       }
+       g_print("\n\n\n ******* Out of while loop ****** \n\n\n");
+
+       fclose(paFile);
+       fclose(paFileInfo);
+       *status = 0;
+       return (void *)status;
+}
+
+
+int test_mediamuxer_write_sample()
+{
+       pthread_t thread[2];
+       pthread_attr_t attr;
+       /* Initialize and set thread detached attribute */
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+       g_print("In main: creating thread  for audio\n");
+       pthread_create(&thread[0], &attr, _write_video_data, NULL);
+       pthread_create(&thread[1], &attr, _write_audio_data, NULL);
+       pthread_attr_destroy(&attr);
+       return 0;
+}
+
+int test_mediamuxer_stop()
+{
+       g_print("test_mediamuxer_stop\n");
+       mediamuxer_stop(myMuxer);
+       media_format_unref(media_format_a);
+       media_format_unref(media_format);
+       return 0;
+}
+
+int test_mediamuxer_pause()
+{
+       g_print("test_mediamuxer_pause\n");
+       mediamuxer_state_e state;
+       if (mediamuxer_get_state(myMuxer, &state) == MEDIAMUXER_ERROR_NONE) {
+               g_print("\nMediamuxer_state=%d",state);
+               if (state == MEDIAMUXER_STATE_MUXING)
+                       mediamuxer_pause(myMuxer);
+       }
+       return 0;
+}
+
+int test_mediamuxer_resume()
+{
+       g_print("test_mediamuxer_resume\n");
+       mediamuxer_resume(myMuxer);
+       return 0;
+}
+
+int test_mediamuxer_add_track()
+{
+       g_print("test_mediamuxer_add_track\n");
+       return 0;
+}
+
+void quit_testApp(void)
+{
+       /* To Do: Replace exit(0) with smooth exit */
+       exit(0);
+}
+
+enum {
+       CURRENT_STATUS_MAINMENU,
+       CURRENT_STATUS_AUDIO_FILENAME,
+       CURRENT_STATUS_AUDIO_INFONAME,
+       CURRENT_STATUS_VIDEO_FILENAME,
+       CURRENT_STATUS_VIDEO_INFONAME,
+};
+
+int g_menu_state = CURRENT_STATUS_MAINMENU;
+static void display_sub_basic();
+
+void reset_menu_state()
+{
+       g_menu_state = CURRENT_STATUS_MAINMENU;
+       return;
+}
+
+static void input_filepath(char *filename)
+{
+       g_print("Opening file %s\n", filename);
+       return;
+}
+
+void _interpret_main_menu(char *cmd)
+{
+       int len = strlen(cmd);
+       if (len == 1) {
+               if (strncmp(cmd, "c", 1) == 0) {
+                       test_mediamuxer_create();
+               } else if (strncmp(cmd, "o", 1) == 0) {
+                       test_mediamuxer_set_data_sink();
+               } else if (strncmp(cmd, "d", 1) == 0) {
+                       test_mediamuxer_destroy();
+               } else if (strncmp(cmd, "s", 1) == 0) {
+                       test_mediamuxer_start();
+               } else if (strncmp(cmd, "a", 1) == 0) {
+                       g_menu_state = CURRENT_STATUS_AUDIO_FILENAME;
+               } else if (strncmp(cmd, "v", 1) == 0) {
+                       g_menu_state = CURRENT_STATUS_VIDEO_FILENAME;
+               } else if (strncmp(cmd, "m", 1) == 0) {
+                       test_mediamuxer_write_sample();
+               } else if (strncmp(cmd, "e", 1) == 0) {
+                       test_mediamuxer_stop();
+               } else if (strncmp(cmd, "p", 1) == 0) {
+                       test_mediamuxer_pause();
+               } else if (strncmp(cmd, "r", 1) == 0) {
+                       test_mediamuxer_resume();
+               } else if (strncmp(cmd, "b", 1) == 0) {
+                       test_mediamuxer_set_error_cb();
+               } else if (strncmp(cmd, "q", 1) == 0) {
+                       quit_testApp();
+               } else {
+                       g_print("unknown menu command. Please try again\n");
+               }
+       } else {
+               g_print("unknown menu command. Please try again\n");
+       }
+
+       return;
+}
+
+static void displaymenu(void)
+{
+       if (g_menu_state == CURRENT_STATUS_MAINMENU) {
+               display_sub_basic();
+       } else if (g_menu_state == CURRENT_STATUS_AUDIO_FILENAME) {
+               g_print("*** input encoded audio_data path:\n");
+               g_print("[This is the raw encoded audio file to be muxed]:");
+       } else if (g_menu_state == CURRENT_STATUS_AUDIO_INFONAME) {
+               g_print("*** input encoded audio info (extra data) path\n");
+               g_print("[This is the extra-information needed to mux.");
+               g_print("This includes gst-caps too]:");
+       } else if (g_menu_state == CURRENT_STATUS_VIDEO_FILENAME) {
+               g_print("*** input encoded video path\n");
+               g_print("[This is the raw encoded video file to be muxed]:");
+       } else if (g_menu_state == CURRENT_STATUS_VIDEO_INFONAME) {
+               g_print("*** input encoded video info (extra data) path\n");
+               g_print("[This is the extra-information needed to mux.");
+               g_print("This includes gst-caps too]:");
+       } else {
+               g_print("*** unknown status.\n");
+               exit(0);
+       }
+       g_print(" >>> ");
+}
+
+gboolean timeout_menu_display(void *data)
+{
+       displaymenu();
+       return FALSE;
+}
+
+static void interpret(char *cmd)
+{
+
+       switch (g_menu_state) {
+               case CURRENT_STATUS_MAINMENU: {
+                               _interpret_main_menu(cmd);
+                               break;
+                       }
+               case CURRENT_STATUS_AUDIO_FILENAME: {
+                               input_filepath(cmd);
+                               strcpy(audio_data, cmd);
+                               g_menu_state = CURRENT_STATUS_AUDIO_INFONAME;
+                               break;
+                       }
+               case CURRENT_STATUS_AUDIO_INFONAME: {
+                               input_filepath(cmd);
+                               strcpy(audio_extra_info, cmd);
+                               test_mediamuxer_add_track_audio();
+                               g_menu_state = CURRENT_STATUS_MAINMENU;
+
+                               break;
+                       }
+               case CURRENT_STATUS_VIDEO_FILENAME: {
+                               input_filepath(cmd);
+                               strcpy(video_data, cmd);
+                               g_menu_state = CURRENT_STATUS_VIDEO_INFONAME;
+                               break;
+                       }
+               case CURRENT_STATUS_VIDEO_INFONAME: {
+                               input_filepath(cmd);
+                               strcpy(video_extra_info, cmd);
+                               test_mediamuxer_add_track_video();
+                               g_menu_state = CURRENT_STATUS_MAINMENU;
+                               break;
+                       }
+               default:
+                       break;
+       }
+       g_timeout_add(100, timeout_menu_display, 0);
+}
+
+static void display_sub_basic()
+{
+       g_print("\n");
+       g_print("==========================================================\n");
+       g_print("                    media muxer test\n");
+       g_print("----------------------------------------------------------\n");
+       g_print("c. Create \t");
+       g_print("o. Set Data Sink \t");
+       g_print("a. AddAudioTrack \t");
+       g_print("v. AddVideoTrack \t");
+       g_print("s. Start \t");
+       g_print("m. StartMuxing \t");
+       g_print("p. PauseMuxing \t");
+       g_print("r. ResumeMuxing \t");
+       g_print("b. set error callback \t");
+       g_print("e. Stop (eos) \n");
+       g_print("d. destroy \t");
+       g_print("q. quit \t");
+       g_print("\n");
+       g_print("==========================================================\n");
+}
+
+/**
+ * This function is to execute command.
+ *
+ * @param      channel [in]    1st parameter
+ *
+ * @return     This function returns TRUE/FALSE
+ * @remark
+ * @see
+ */
+gboolean input(GIOChannel *channel)
+{
+       gchar buf[MAX_STRING_LEN];
+       gsize read;
+       GError *error = NULL;
+       g_io_channel_read_chars(channel, buf, MAX_STRING_LEN, &read, &error);
+       buf[read] = '\0';
+       g_strstrip(buf);
+       interpret(buf);
+       return TRUE;
+}
+
+/**
+ * This function is the example main function for mediamuxer API.
+ *
+ * @param
+ *
+ * @return      This function returns 0.
+ * @remark
+ * @see         other functions
+ */
+int main(int argc, char *argv[])
+{
+       GIOChannel *stdin_channel;
+       GMainLoop *loop = g_main_loop_new(NULL, 0);
+       stdin_channel = g_io_channel_unix_new(0);
+       g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
+       g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc) input, NULL);
+
+       displaymenu();
+       /* g_print("RUN main loop\n"); */
+       g_main_loop_run(loop);
+       g_print("STOP main loop\n");
+
+       g_main_loop_unref(loop);
+       return 0;
+}