Add initial code for mediademuxer 31/43631/6 accepted/tizen/mobile/20150722.062919 accepted/tizen/tv/20150722.062938 accepted/tizen/wearable/20150722.062957 submit/tizen/20150722.060432
authorJoungkook Seo <jk7704.seo@samsung.com>
Mon, 13 Jul 2015 00:22:56 +0000 (09:22 +0900)
committerJoungkook Seo <jk7704.seo@samsung.com>
Tue, 21 Jul 2015 09:40:49 +0000 (18:40 +0900)
[1] Update the code according to the ACR review
[2] Update the code for sync with SPIN 2.4
[3] Fixed review comment of patch set(#3)
[4] Sync with 2.4 and Refine code (2nd)
[5] Fixed review comment of patch set(#5)

Change-Id: I443660bb73e3726f92f6a5e58254fbc951abae9b
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-mediademuxer.manifest [new file with mode: 0755]
capi-mediademuxer.pc.in [new file with mode: 0755]
doc/mediademuxer_doc.h [new file with mode: 0644]
include/mediademuxer.h [new file with mode: 0644]
include/mediademuxer_error.h [new file with mode: 0755]
include/mediademuxer_ini.h [new file with mode: 0755]
include/mediademuxer_port.h [new file with mode: 0755]
include/mediademuxer_private.h [new file with mode: 0755]
include/mediademuxer_util.h [new file with mode: 0755]
include/port_custom/mediademuxer_port_custom.h [new file with mode: 0755]
include/port_ffmpeg/mediademuxer_port_ffmpeg.h [new file with mode: 0755]
include/port_gst/mediademuxer_port_gst.h [new file with mode: 0755]
packaging/capi-mediademuxer.spec [new file with mode: 0755]
src/CMakeLists.txt [new file with mode: 0755]
src/mediademuxer.c [new file with mode: 0755]
src/mediademuxer_ini.c [new file with mode: 0755]
src/mediademuxer_port.c [new file with mode: 0755]
src/port_custom/mediademuxer_port_custom.c [new file with mode: 0755]
src/port_ffmpeg/mediademuxer_port_ffmpeg.c [new file with mode: 0755]
src/port_gst/mediademuxer_port_gst.c [new file with mode: 0755]
test/CMakeLists.txt [new file with mode: 0644]
test/mediademuxer_test.c [new file with mode: 0755]

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..b064642
--- /dev/null
@@ -0,0 +1,112 @@
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(fw_name "capi-mediademuxer")
+
+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 "mediademuxer_*.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_INSTALL_DIR}/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-mediademuxer.manifest b/capi-mediademuxer.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-mediademuxer.pc.in b/capi-mediademuxer.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/mediademuxer_doc.h b/doc/mediademuxer_doc.h
new file mode 100644 (file)
index 0000000..4e3c55f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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_MEDIADEMUXER_DOC_H__
+#define __TIZEN_MEDIADEMUXER_DOC_H__
+
+/**
+ * @file mediademuxer_doc.h
+ * @brief This file contains high level documentation of the CAPI MEDIA DEMUXER API.
+ */
+
+/**
+ * @ingroup CAPI_MEDIA_FRAMEWORK
+ * @defgroup CAPI_MEDIADEMUXER_MODULE Media Demuxer
+ * @brief  The @ref CAPI_MEDIADEMUXER_MODULE  APIs provides functions for demuxing media data
+ *
+ * @section CAPI_MEDIADEMUXER_MODULE_HEADER Required Header
+ *   \#include <mediademuxer.h>
+ *
+ * @section CAPI_MEDIADEMUXER_MODULE_OVERVIEW Overview
+ *
+ * MEDIADEMUXER API allows :<br>
+ * 1) To extract elementary audio, video or text data from a
+ * multiplexed stream<br>
+ * 2) To choose one or multiple desired stream to extract.<br>
+ * 3) To choose the local or remote input source.<br>
+ * 4) To create single or multiple instances of media demuxer. One instance can demux only one<br>
+ * input stream<br>
+ * 5) To demux all the popular media formats such as MP4, AAC-NB, AAC-WB, MP3 etc.<br>
+ * 6) To extract elementarty media sample information, such as timestamp, sample size, key-frame(I-frame) etc.<br>
+ * 7) To identify encripted format<br>
+ * 8) To seek to a different position-forward or backward- while extracting<br>
+ * <br>
+ * Typical Call Flow of mediamuxer APIs is:<br>
+ * mediademuxer_create()<br>
+ * mediademuxer_set_data_source()<br>
+ * mediademuxer_prepare()<br>
+ * mediademuxer_get_track_count()<br>
+ * mediademuxer_select_track()<br>
+ * mediademuxer_start()<br>
+ * mediademuxer_get_track_info()<br>
+ * <pre>
+ * while(EOS) {
+ *     if(track1 is set) {
+ *             mediademuxer_read_sample();
+ *             if(seek_request)
+ *                     mediademuxer_seek();
+ *     }
+ *     else if(track2 is set) {
+ *              mediademuxer_read_sample();
+ *     }
+ *     if(track2_not_needed)
+ *             mediademuxer_unselect_track(track2);
+ *  }
+ * </pre>
+ * mediademuxer_stop()<br>
+ * mediademuxer_unprepare()<br>
+ * mediademuxer_destroy()<br>
+ */
+
+#endif /* __TIZEN_MEDIADEMUXER_DOC_H__ */
diff --git a/include/mediademuxer.h b/include/mediademuxer.h
new file mode 100644 (file)
index 0000000..2c6eb80
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * 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_MEDIADEMUXER_H__
+#define __TIZEN_MEDIADEMUXER_H__
+
+#include <tizen.h>
+#include <stdint.h>
+#include <media_format.h>
+#include <media_packet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef TIZEN_ERROR_MEDIA_DEMUXER
+#define TIZEN_ERROR_MEDIA_DEMUXER -0x04000000
+#endif
+
+/**
+ * @file mediademuxer.h
+ * @brief This file contains the capi media demuxer API.
+ */
+
+/**
+ * @addtogroup CAPI_MEDIADEMUXER_MODULE
+ * @{
+ */
+
+/**
+ * @brief Media Demuxer handle type.
+ * @since_tizen 3.0
+ */
+typedef struct mediademuxer_s *mediademuxer_h;
+
+/**
+ * @brief Enumeration for media demuxer state
+ * @since_tizen 3.0
+ */
+typedef enum {
+       MEDIADEMUXER_NONE,              /**< The mediademuxer is not created */
+       MEDIADEMUXER_IDLE,                      /**< The mediademuxer is created, but not prepared */
+       MEDIADEMUXER_READY,             /**< The mediademuxer is ready to demux media */
+       MEDIADEMUXER_DEMUXING   /**< The mediademuxer is demuxing media */
+} mediademuxer_state;
+
+/**
+ * @brief Enumeration for media demuxer error.
+ * @since_tizen 3.0
+ */
+typedef enum {
+       MEDIADEMUXER_ERROR_NONE = TIZEN_ERROR_NONE,                                                                             /*< Successful */
+       MEDIADEMUXER_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY,                                                   /**< Out of memory */
+       MEDIADEMUXER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER,                   /**< Invalid parameter */
+       MEDIADEMUXER_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION,                   /**< Invalid operation */
+       MEDIADEMUXER_ERROR_NOT_SUPPORTED  = TIZEN_ERROR_NOT_SUPPORTED,                     /**< Not supported */
+       MEDIADEMUXER_ERROR_PERMISSION_DENIED  = TIZEN_ERROR_PERMISSION_DENIED,          /**< Permission denied */
+       MEDIADEMUXER_ERROR_INVALID_STATE = TIZEN_ERROR_MEDIA_DEMUXER | 0x01,                    /**< Invalid state */
+       MEDIADEMUXER_ERROR_INVALID_PATH = TIZEN_ERROR_MEDIA_DEMUXER | 0x02,                     /**< Invalid path */
+       MEDIADEMUXER_ERROR_RESOURCE_LIMIT = TIZEN_ERROR_MEDIA_DEMUXER | 0x03,           /**< Resource limit */
+       MEDIADEMUXER_ERROR_SEEK_FAILED = TIZEN_ERROR_MEDIA_DEMUXER | 0x04,              /**< Seek operation failure */
+       MEDIADEMUXER_ERROR_DRM_NOT_PERMITTED = TIZEN_ERROR_MEDIA_DEMUXER | 0x05         /**< Not permitted format */
+} mediademuxer_error_e;
+
+/**
+ * @brief Called when error occurs in media demuxer.
+ * @details Following error codes can be delivered.
+ *          #MEDIADEMUXER_ERROR_INVALID_OPERATION,
+ *          #MEDIADEMUXER_ERROR_NOT_SUPPORTED,
+ *          #MEDIADEMUXER_ERROR_INVALID_PATH,
+ *          #MEDIADEMUXER_ERROR_RESOURCE_LIMIT,
+ *          #MEDIADEMUXER_ERROR_SEEK_FAILED,
+ *          #MEDIADEMUXER_ERROR_DRM_NOT_PERMITTED
+ * @since_tizen 3.0
+ * @param[in] error  The error that occurred in media demuxer
+ * @param[in] user_data   The user data passed from the code where
+ *                         mediademuxer_set_error_cb() was invoked
+ *                         This data will be accessible from @a mediademuxer_error_cb
+ * @pre Create media demuxer handle by calling mediademuxer_create() function.
+ * @see mediademuxer_set_error_cb()
+ * @see mediademuxer_unset_error_cb()
+ */
+typedef void (*mediademuxer_error_cb)(mediademuxer_error_e error, void *user_data);
+
+/**
+ * @brief Creates a media demuxer handle for demuxing.
+ * @since_tizen 3.0
+ * @remarks You must release @a demuxer using mediademuxer_destroy() function.
+ * @param[out] demuxer    A new handle to media demuxer
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @post The media demuxer state will be #MEDIADEMUXER_STATE_IDLE.
+ * @see mediademuxer_destroy()
+ */
+int mediademuxer_create(mediademuxer_h *demuxer);
+
+/**
+ * @brief Sets the source path of input stream.
+ * @since_tizen 3.0
+ * @remarks The mediastorage privilege(http://tizen.org/privilege/mediastorage) should be added if any video/audio files are used to play located in the internal storage.
+ * @remarks The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are used to play located in the external storage.
+ * @remarks You must release @a demuxer using mediademuxer_destroy() function.
+ * @param[in] demuxer    The media demuxer handle
+ * @param[in] path    The content location, such as the file path
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIADEMUXER_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PATH Invalid path
+ * @pre The media muxer state will be #MEDIADEMUXER_STATE_IDLE by calling mediademuxer_create() function.
+ * */
+int mediademuxer_set_data_source(mediademuxer_h demuxer, const char *path);
+
+/**
+ * @brief Prepares the media demuxer for demuxing.
+ * @since_tizen 3.0
+ * @remark User should call this before mediademuxer_start() function.
+ * @param[in] demuxer    The media demuxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state should be #MEDIADEMUXER_STATE_IDLE.
+ * @post The media demuxer state will be #MEDIADEMUXER_STATE_READY.
+ * @see mediademuxer_set_data_source()
+ * @see mediademuxer_unprepare()
+ * */
+int mediademuxer_prepare(mediademuxer_h demuxer);
+
+/**
+ * @brief Gets the total track count present in the container stream.
+ * @since_tizen 3.0
+ * @param[in] demuxer    The media demuxer handle
+ * @param[out] count     The number of tracks present
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state should be #MEDIADEMUXER_STATE_READY.
+ * @see mediademuxer_prepare()
+ * @see mediademuxer_select_track()
+ * */
+int mediademuxer_get_track_count(mediademuxer_h demuxer, int *count);
+
+/**
+ * @brief Selects the track to be performed.
+ * @since_tizen 3.0
+ * @param[in] demuxer    The media demuxer handle
+ * @param[in] track_index      The track index on which is selected for read
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state should be #MEDIADEMUXER_STATE_READY.
+ * @see mediademuxer_get_track_count()
+ * @see mediademuxer_start()
+ * */
+int mediademuxer_select_track(mediademuxer_h demuxer, int track_index);
+
+/**
+ * @brief Starts the media demuxer.
+ * @since_tizen 3.0
+ * @remark User should call this before mediademuxer_read_sample() function.
+ * @param[in] demuxer    The media demuxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state should be #MEDIADEMUXER_STATE_READY.
+ * @post The media demuxer state will be #MEDIADEMUXER_STATE_DEMUXING.
+ * @see mediademuxer_prepare()
+ * @see mediademuxer_get_track_count()
+ * @see mediademuxer_select_track()
+ * @see mediademuxer_get_track_info()
+ * */
+int mediademuxer_start(mediademuxer_h demuxer);
+
+/**
+ * @brief Retrieves the track format of the read sample.
+ * @since_tizen 3.0
+ * @remarks The @a format should be released using media_format_unref() function.
+ * @param[in] demuxer    The media demuxer handle
+ * @param[in] track_index     The index of the track
+ * @param[out] format    The media format handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state must be set to #MEDIADEMUXER_STATE_DEMUXING by calling
+ *      mediademuxer_start() or set to #MEDIADEMUXER_STATE_READY by calling mediademuxer_prepare().
+ * @see mediademuxer_get_track_count()
+ * @see mediademuxer_select_track()
+ * @see media_format_unref()
+ * @see #media_format_h
+ * */
+int mediademuxer_get_track_info(mediademuxer_h demuxer, int track_index,
+                                media_format_h *format);
+
+/**
+ * @brief Reads a frame(sample) of one single track.
+ * @since_tizen 3.0
+ * @remark The @a outbuf should be released using media_packet_destroy() function.
+ * @remark Once this API is called, user app can call the mediatool APIs to extract
+ *          side information such as pts, size, duration, flags etc.
+ * @param[in] demuxer    The media demuxer handle
+ * @param[in] track_index      The index of track of which data is needed
+ * @param[out] outbuf      The media packet handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state should be #MEDIADEMUXER_STATE_DEMUXING.
+ * @see mediademuxer_start()
+ * @see mediademuxer_get_track_info()
+ * @see mediademuxer_seek() if need to seek to a particular location
+ * @see mediademuxer_unselect_track()
+ * @see mediademuxer_stop()
+ * @see media_packet_destroy()
+ * @see #media_packet_h
+ * */
+int mediademuxer_read_sample(mediademuxer_h demuxer, int track_index,
+                             media_packet_h *outbuf);
+
+/**
+ * @brief Seeks to a particular instance of time (in micro seconds).
+ * @since_tizen 3.0
+ * @param[in] demuxer    The media demuxer handle
+ * @param[in] pos       The value of the new start position
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+* @pre The media demuxer state should be #MEDIADEMUXER_STATE_DEMUXING.
+ * @see mediademuxer_read_sample()
+ * @see mediademuxer_stop()
+ * */
+int mediademuxer_seek(mediademuxer_h demuxer, int64_t pos);
+
+/**
+ * @brief Unselects the selected track.
+ * @since_tizen 3.0
+ * @param[in] demuxer    The media demuxer handle
+ * @param[in] track_index      The track index to be unselected
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state must be set to #MEDIADEMUXER_STATE_DEMUXING by calling
+ *      mediademuxer_read_sample() or set to #MEDIADEMUXER_STATE_READY by calling mediademuxer_select_track().
+ * @see mediademuxer_select_track()
+ * @see mediademuxer_read_sample()
+ * */
+int mediademuxer_unselect_track(mediademuxer_h demuxer, int track_index);
+
+/**
+ * @brief Stops the media demuxer.
+ * @since_tizen 3.0
+ * @remark User can call this if need to stop demuxing if needed.
+ * @param[in] demuxer    The media demuxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state must be set to #MEDIADEMUXER_STATE_DEMUXING.
+ * @post The media demuxer state will be in  #MEDIADEMUXER_READY.
+ * @see mediademuxer_start()
+ * @see mediademuxer_unprepare()
+ * */
+int mediademuxer_stop(mediademuxer_h demuxer);
+
+/**
+ * @brief Resets the media demuxer.
+ * @since_tizen 3.0
+ * @remarks User should call this before mediademuxer_destroy() function.
+ * @param[in] demuxer    The media demuxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre The media demuxer state should be #MEDIADEMUXER_STATE_READY.
+ * @post The media demuxer state will be #MEDIADEMUXER_STATE_IDLE.
+ * @see mediademuxer_prepare()
+ * */
+int mediademuxer_unprepare(mediademuxer_h demuxer);
+
+/**
+ * @brief Removes the instance of media demuxer and clear all its context memory.
+ * @since_tizen 3.0
+ * @param[in] demuxer    The media demuxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
+ * @pre Create a media demuxer handle by calling mediademuxer_create() function.
+ * @post The media demuxer state will be #MEDIADEMUXER_STATE_NONE.
+ * @see mediademuxer_create()
+ * */
+int mediademuxer_destroy(mediademuxer_h demuxer);
+
+/**
+ * @brief Gets media demuxer state.
+ * @since_tizen 3.0
+ * @param[in] demuxer   The media demuxer handle
+ * @param[out] state   The media demuxer sate
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIADEMUXER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media demuxer handle by calling mediademuxer_create() function.
+ * @see #mediademuxer_state
+ * */
+int mediademuxer_get_state(mediademuxer_h demuxer, mediademuxer_state *state);
+
+/**
+ * @brief Registers a error callback function to be invoked when an error occurs.
+ * @details Following error codes can be delivered.
+ *          #MEDIADEMUXER_ERROR_INVALID_OPERATION,
+ *          #MEDIADEMUXER_ERROR_NOT_SUPPORTED,
+ *          #MEDIADEMUXER_ERROR_INVALID_PATH,
+ *          #MEDIADEMUXER_ERROR_RESOURCE_LIMIT,
+ *          #MEDIADEMUXER_ERROR_SEEK_FAILED,
+ *          #MEDIADEMUXER_ERROR_DRM_NOT_PERMITTED
+ * @since_tizen 3.0
+ * @param[in] demuxer   The media demuxer handle
+ * @param[in] callback  Callback function pointer
+ * @param[in] user_data   The user data passed from the code where
+ *                         mediademuxer_set_error_cb() was invoked
+ *                         This data will be accessible from @a mediademuxer_error_cb
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media demuxer handle by calling mediademuxer_create() function.
+ * @post mediademuxer_error_cb() will be invoked.
+ * @see mediademuxer_unset_error_cb()
+ * @see mediademuxer_error_cb()
+ * */
+int mediademuxer_set_error_cb(mediademuxer_h demuxer,
+                       mediademuxer_error_cb callback, void *user_data);
+
+/**
+ * @brief Unregisters the error callback function.
+ * @since_tizen 3.0
+ * @param[in] demuxer   The media demuxer handle
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MEDIADEMUXER_ERROR_NONE Successful
+ * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see mediademuxer_error_cb()
+ * */
+int mediademuxer_unset_error_cb(mediademuxer_h demuxer);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_H__ */
diff --git a/include/mediademuxer_error.h b/include/mediademuxer_error.h
new file mode 100755 (executable)
index 0000000..413f448
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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_MEDIADEMUXER_ERROR_H__
+#define __TIZEN_MEDIADEMUXER_ERROR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+       MD_ERROR_NONE = 0,
+       MD_ERROR = -1,              /**< codec happens error */
+       MD_MEMORY_ERROR = -2,       /**< codec memory is not enough */
+       MD_PARAM_ERROR = -3,        /**< codec parameter is error */
+       MD_INVALID_ARG = -4,        /** < codec has invalid arguments */
+       MD_PERMISSION_DENIED = -5,
+       MD_INVALID_STATUS = -6,     /**< codec works at invalid status */
+       MD_NOT_SUPPORTED = -7,      /**< codec can't support this specific video format */
+       MD_INVALID_IN_BUF = -8,
+       MD_INVALID_OUT_BUF = -9,
+       MD_INTERNAL_ERROR = -10,
+       MD_HW_ERROR = -11,          /**< codec happens hardware error */
+       MD_NOT_INITIALIZED = -12,
+       MD_INVALID_STREAM = -13,
+       MD_OUTPUT_BUFFER_EMPTY = -14,
+       MD_OUTPUT_BUFFER_OVERFLOW = -15,    /**< codec output buffer is overflow */
+       MD_MEMORY_ALLOCED = -16,    /**< codec has got memory and can decode one frame */
+       MD_COURRPTED_INI = -17,     /**< value in the ini file is not valid */
+       MD_ERROR_FILE_NOT_FOUND = -18,
+       MD_EOS,  /** read sample reached end of stream */
+} md_ret_e;
+
+#define MD_ERROR_CLASS              0x80000000     /**< Definition of number describing error group */
+#define MD_ERROR_COMMON_CLASS       0x80000100     /**< Category for describing common error group */
+#define MD_ERROR_GST_PORT_CLASS     0x80000200     /**< Category for describing gst_port error group */
+#define MD_ERROR_FFMPEG_PORT_CLASS  0x80000300     /**< Category for describing ffmpeg port error group */
+#define MD_ERROR_CUSTOM_PORT_CLASS       0x80000400     /**< Category for describing custom error group */
+
+/*
+      MD_ERROR_CLASS
+*/
+#define MD_ERROR_UNKNOWN            (MD_ERROR_CLASS | 0x00)    /**< Unclassified error */
+#define MD_ERROR_INVALID_ARGUMENT       (MD_ERROR_CLASS | 0x01)            /**< Invalid argument */
+#define MD_ERROR_OUT_OF_MEMORY          (MD_ERROR_CLASS | 0x02)            /**< Out of memory */
+#define MD_ERROR_OUT_OF_STORAGE         (MD_ERROR_CLASS | 0x03)            /**< Out of storage */
+#define MD_ERROR_INVALID_HANDLE         (MD_ERROR_CLASS | 0x04)            /**< Invalid handle */
+#define MD_ERROR_FILE_NOT_FOUND         (MD_ERROR_CLASS | 0x05)            /**< Cannot find file */
+#define MD_ERROR_FILE_READ          (MD_ERROR_CLASS | 0x06)    /**< Fail to read data from file */
+#define MD_ERROR_FILE_WRITE         (MD_ERROR_CLASS | 0x07)    /**< Fail to write data to file */
+#define MD_ERROR_END_OF_FILE        (MD_ERROR_CLASS | 0x08)    /**< End of file */
+#define MD_ERROR_NOT_SUPPORT_API        (MD_ERROR_CLASS | 0x09)            /**< Not supported API*/
+#define MD_ERROR_PORT_REG_FAILED        (MD_ERROR_CLASS | 0x0a)            /**< port regitstration failed error */
+
+/*
+       MD_ERROR_COMMON_CLASS
+*/
+#define MD_ERROR_COMMON_INVALID_ARGUMENT    (MD_ERROR_COMMON_CLASS | 1)            /**< Invalid argument */
+#define MD_ERROR_COMMON_NO_FREE_SPACE       (MD_ERROR_COMMON_CLASS | 2)            /**< Out of storage */
+#define MD_ERROR_COMMON_OUT_OF_MEMORY       (MD_ERROR_COMMON_CLASS | 3)            /**< Out of memory */
+#define MD_ERROR_COMMON_UNKNOWN             (MD_ERROR_COMMON_CLASS | 4)            /**< Unknown error */
+#define MD_ERROR_COMMON_INVALID_ATTRTYPE    (MD_ERROR_COMMON_CLASS | 5)            /**< Invalid argument */
+#define MD_ERROR_COMMON_INVALID_PERMISSION  (MD_ERROR_COMMON_CLASS | 6)            /**< Invalid permission */
+#define MD_ERROR_COMMON_OUT_OF_ARRAY        (MD_ERROR_COMMON_CLASS | 7)            /**< Out of array */
+#define MD_ERROR_COMMON_OUT_OF_RANGE        (MD_ERROR_COMMON_CLASS | 8)            /**< Out of value range*/
+#define MD_ERROR_COMMON_ATTR_NOT_EXIST      (MD_ERROR_COMMON_CLASS | 9)            /**< Attribute doesn't exist. */
+
+/*
+ *     MD_ERROR_GST_PORT_CLASS
+ */
+#define MD_ERROR_GST_PORT_NOT_INITIALIZED   (MD_ERROR_GST_PORT_CLASS | 0x01)       /**< GST Port  instance is not initialized */
+
+/*
+    MD_ERROR_FFMPEG_PORT_CLASS
+ */
+#define MD_ERROR_FFMPEG_PORT_NOT_INITIALIZED    (MD_ERROR_FFMPEG_PORT_CLASS | 0x01)    /**< FFMPEG Port instance is not initialized */
+
+/*
+    MD_ERROR_CUSTOM_PORT_CLASS
+*/
+#define MD_ERROR_CUSTOM_PORT_NOT_INITIALIZED    (MD_ERROR_CUSTOM_PORT_CLASS | 0x01)    /**< CUSTOM Port instance is not initialized */
+
+/**
+    @}
+*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_ERROR_H__ */
diff --git a/include/mediademuxer_ini.h b/include/mediademuxer_ini.h
new file mode 100755 (executable)
index 0000000..e563c08
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_ini.h
+ * @brief INI laoding and parsing procedures
+ */
+
+#ifndef __TIZEN_MEDIADEMUXER_INI_H__
+#define __TIZEN_MEDIADEMUXER_INI_H__
+
+#include <glib.h>
+#include <mm_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MEDIADEMUXER_INI_DEFAULT_PATH   "/usr/etc/mmfw_mediademuxer.ini"
+#define MEDIADEMUXER_INI_MAX_STRLEN     100
+#define DEFAULT_PORT "GST_PORT"
+
+typedef enum {
+       GST_PORT = 0,
+       FFMPEG_PORT,
+       CUSTOM_PORT,
+} port_mode;
+
+/* @ mark means the item has tested */
+typedef struct __md_ini {
+       port_mode port_type;
+       /* general */
+       gchar port_name[MEDIADEMUXER_INI_MAX_STRLEN];
+} md_ini_t;
+
+/* 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 MEDIADEMUXER_DEFAULT_INI \
+       "\
+[general] \n\
+\n\
+;Add general config parameters here\n\
+\n\
+\n\
+\n\
+[port_in_use] \n\
+\n\
+;mediademuxer_port = GST_PORT \n\
+;mediademuxer_port = FFMPEG_PORT \n\
+;mediademuxer_port = CUSTOM_PORT \n\
+mediademuxer_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\
+"
+
+int md_ini_load(md_ini_t *ini);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__TIZEN_MEDIADEMUXER_INI_H__*/
diff --git a/include/mediademuxer_port.h b/include/mediademuxer_port.h
new file mode 100755 (executable)
index 0000000..86f1552
--- /dev/null
@@ -0,0 +1,564 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port.h
+ * @brief general port based functions. sets specific function pointers
+ */
+
+#ifndef __TIZEN_MEDIADEMUXER_PORT_H__
+#define __TIZEN_MEDIADEMUXER_PORT_H__
+
+/*===========================================================================================
+|                                                                                           |
+|  INCLUDE FILES                                        |
+|                                                                                           |
+========================================================================================== */
+
+#include <glib.h>
+#include <mm_types.h>
+#include <mm_message.h>
+#include <media_format.h>
+#include <mediademuxer_util.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+    @{
+
+    @par
+    This part describes APIs used for playback of multimedia contents.
+    All multimedia contents are created by a media demuxer through handle of playback.
+    In creating a demuxer, it displays the demuxer'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 mm_demuxer_set_attribute() before create demuxer.
+
+    @par
+    The subtitle for local video playback is supported. Set "subtitle_uri" attribute
+    using mm_demuxer_set_attribute() before the application creates the demuxer.
+    Then the application could receive MMMessageParamType which includes subtitle string and duration.
+
+    @par
+    MediaDemuxer can have 5 states, and each state can be changed by calling
+    described functions on "Figure1. State of MediaDemuxer".
+
+    @par
+    @image html                demuxer_state.jpg       "Figure1. State of MediaDemuxer"        width=12cm
+    @image latex       demuxer_state.jpg       "Figure1. State of MediaDemuxer"        width=12cm
+
+    @par
+    Most of functions which change demuxer state work as synchronous. But, mm_demuxer_start() should be used
+    asynchronously. Both mm_demuxer_pause() and mm_demuxer_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 mm_demuxer_destroy() and mm_demuxer_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>md_create()</td>
+    <td>NONE</td>
+    <td>NULL</td>
+    <td>SYNC</td>
+    </tr>
+    <tr>
+    <td>md_destroy()</td>
+    <td>NULL</td>
+    <td>NONE</td>
+    <td>SYNC</td>
+    </tr>
+    <tr>
+    <td>md_set_data_source()</td>
+    <td>NULL</td>
+    <td>READY</td>
+    <td>SYNC</td>
+    </tr>
+    </table></div>
+
+    @par
+    Following are the attributes supported in demuxer which may be set after initialization. \n
+    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.\n
+    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 demuxer.
+ * @details Following error codes can be delivered.
+ *          #MEDIADEMUXER_ERROR_INVALID_OPERATION,
+ *          #MEDIADEMUXER_ERROR_NOT_SUPPORTED,
+ *          #MEDIADEMUXER_ERROR_INVALID_PATH,
+ *          #MEDIADEMUXER_ERROR_RESOURCE_LIMIT,
+ *          #MEDIADEMUXER_ERROR_SEEK_FAILED,
+ *          #MEDIADEMUXER_ERROR_DRM_NOT_PERMITTED
+ * @since_tizen 3.0
+ * @param[in] error  The error that occurred in media demuxer
+ * @param[in] user_data   The user data passed from the code where
+ *                         mediademuxer_set_error_cb() was invoked
+ *                         This data will be accessible from @a mediademuxer_error_cb
+ * @pre Create media demuxer handle by calling mediademuxer_create() function.
+ * @see mediademuxer_set_error_cb()
+ * @see mediademuxer_unset_error_cb()
+ */
+typedef void (*md_error_cb)(mediademuxer_error_e error, void *user_data);
+/**
+ * Enumerations of demuxer state.
+ */
+/**
+ * Attribute validity structure
+ */
+typedef struct _media_port_demuxer_ops {
+       unsigned int n_size;
+       int (*init)(MMHandleType *pHandle);
+       int (*prepare)(MMHandleType pHandle, char *uri);
+       int (*get_track_count)(MMHandleType pHandle, int *count);
+       int (*set_track)(MMHandleType pHandle, int track);
+       int (*start)(MMHandleType pHandle);
+       int (*get_track_info)(MMHandleType pHandle, media_format_h *format, int track);
+       int (*read_sample)(MMHandleType pHandle, media_packet_h *outbuf, int track_indx);
+       int (*seek)(MMHandleType pHandle, int64_t pos1);
+       int (*unset_track)(MMHandleType pHandle, int track);
+       int (*stop)(MMHandleType pHandle);
+       int (*unprepare)(MMHandleType pHandle);
+       int (*destroy)(MMHandleType pHandle);
+       int (*set_error_cb)(MMHandleType demuxer, md_error_cb callback, void* user_data);
+       int (*get_data)(MMHandleType pHandle, char *buffer);
+} media_port_demuxer_ops;
+
+/*===========================================================================================
+|                                                                                           |
+|  GLOBAL FUNCTION PROTOTYPES                                        |
+|                                                                                           |
+========================================================================================== */
+
+/**
+ * This function creates a demuxer object for parsing multimedia contents. \n
+ * The attributes of demuxer are created to get/set some values with application. \n
+ * And, proper port is selected to do the actual parsing of the mdia.
+ *
+ * @param   demuxer [out]   Handle of demuxer
+ *
+ * @return  This function returns zero on success, or negative value with error code. \n
+ *          Please refer 'mm_demuxer_error.h' to know it in detail.
+ *
+ * @par Example
+ * @code
+  MMHandleType demuxer;
+  md_create(&demuxer);
+  ...
+  md_destroy(&demuxer);
+ * @endcode
+ */
+int md_create(MMHandleType *demuxer);
+
+/**
+ * This function sets the input data source to parse. \n
+ * The source can be a local file or remote server file
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ * @param   uri         [in]    absolute path for the source media
+ *
+ * @return  This function returns zero on success, or negative value with error code. \n
+ *          Please refer 'mm_demuxer_error.h' to know it in detail.
+ *
+ * @par Example
+ * @code
+  MPhandle demuxer;
+  md_create(&demuxer);
+  if (md_set_data_source(demuxer) != MM_ERROR_NONE)
+{
+    MD_E("failed to set the source \n");
+}
+  md_destroy(&demuxer);
+ * @endcode
+ */
+int md_set_data_source(MMHandleType demuxer, const char *uri);
+
+/**
+ * This function releases demuxer object and all resources which were created by md_create(). \n
+ * And, demuxer handle will also be destroyed.
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_create
+ *
+ * @par Example
+ * @code
+if (md_destroy(g_demuxer) != MM_ERROR_NONE)
+{
+    MD_E("failed to destroy demuxer\n");
+}
+ * @endcode
+ */
+int md_destroy(MMHandleType demuxer);
+
+/**
+ * This function set up the internal structure of gstreamer, ffmpeg & custom to handle data set up md_set_data_source
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_set_data_source
+ *
+ * @par Example
+ * @code
+if (md_prepare(g_demuxer) != MM_ERROR_NONE)
+{
+    MD_E("failed to prepare demuxer\n");
+}
+ * @endcode
+ */
+int md_prepare(MMHandleType demuxer);
+
+/**
+ * This function get the total number of tracks present in the stream.
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ * @param   count     [out]    Total track number of streams available in the media
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_set_data_source
+ *
+ * @par Example
+ * @code
+if (md_get_track_count(g_demuxer,count) != MM_ERROR_NONE)
+{
+       MD_E("failed to get count\n");
+}
+ * @endcode
+ */
+int md_get_track_count(MMHandleType demuxer, int *count);
+
+/**
+ * This function get the  format of selected track present in the stream.
+ *
+ * @param   demuxer            [in]    Handle of demuxer
+ * @param   track              [in]    index for the track
+ * @param   format             [out]   pointer to the Handle of media_format
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ *
+ * @par Example
+ * @code
+if (md_get_track_info(g_demuxer, format, track) != MM_ERROR_NONE)
+{
+       MD_E("failed to get track info\n");
+}
+ * @endcode
+ */
+int md_get_track_info(MMHandleType demuxer, int track, media_format_h *format);
+
+/**
+ * This function start the pipeline(in case of gst port it set the pipeline to play state).
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ */
+int md_start(MMHandleType demuxer);
+
+/**
+ * This function read a packet of data from demuxer
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ * @param   track_indx  [in]   selected track number
+ * @param   outbuf      [out]    demuxed packet
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ */
+int md_read_sample(MMHandleType demuxer, int track_indx, media_packet_h *outbuf);
+
+/**
+ * This function stop the pipeline in case of gst_port
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_set_data_source
+ */
+int md_stop(MMHandleType demuxer);
+
+
+/**
+ * This function destroy the pipeline
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_set_data_source
+ */
+int md_unprepare(MMHandleType demuxer);
+
+/**
+ * This function is to select a track on which read need to be performed
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ * @param   index       [in]    index for the track to be selected
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_set_data_source
+ */
+int md_select_track(MMHandleType demuxer, int index);
+
+/**
+ * This function is to unselect a track on which readsample can't be performed
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ * @param   index       [in]    index for the track to be selected
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_set_data_source
+ */
+int md_unselect_track(MMHandleType demuxer, int index);
+
+/**
+ * This function is to seek to a particular position relative to current position
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ * @param   pos         [in]    relative position to seek
+ *
+ * @return  This function returns zero on success, or negative value with error code.
+ * @see     md_set_data_source
+ */
+int md_seek(MMHandleType demuxer, int64_t pos);
+
+/**
+ * This function is to set error call back function
+ *
+ * @param   demuxer     [in]    Handle of demuxer
+ * @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 md_set_error_cb(MMHandleType demuxer, md_error_cb callback, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_PORT_H__ */
diff --git a/include/mediademuxer_private.h b/include/mediademuxer_private.h
new file mode 100755 (executable)
index 0000000..a6beedf
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_private.h
+ * @brief contain information about the pError and return type, enum and structure prototype
+ */
+
+#ifndef __TIZEN_MEDIADEMUXER_PRIVATE_H__
+#define __TIZEN_MEDIADEMUXER_PRIVATE_H__
+
+#include <mediademuxer.h>
+#include <mediademuxer_port.h>
+#include <mediademuxer_ini.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "TIZEN_N_MEDIADEMUXER"
+
+#define DEMUXER_CHECK_CONDITION(condition,error,msg)     \
+       if(condition) {} else \
+               { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
+
+#define DEMUXER_INSTANCE_CHECK(demuxer)   \
+       DEMUXER_CHECK_CONDITION(demuxer != NULL, MEDIADEMUXER_ERROR_INVALID_PARAMETER,"DEMUXER_ERROR_INVALID_PARAMETER")
+
+#define DEMUXER_STATE_CHECK(demuxer,expected_state)       \
+       DEMUXER_CHECK_CONDITION(demuxer->state == expected_state,MEDIADEMUXER_ERROR_INVALID_STATE,"DEMUXER_ERROR_INVALID_STATE")
+
+#define DEMUXER_NULL_ARG_CHECK(arg)      \
+       DEMUXER_CHECK_CONDITION(arg != NULL,MEDIADEMUXER_ERROR_INVALID_PARAMETER,"DEMUXER_ERROR_INVALID_PARAMETER")
+
+/**
+ * @brief Enumeration for media demuxer source type
+ * @since_tizen 3.0
+ */
+typedef enum {
+       MEDIADEMUXER_SRC_NONE = 0,              /**<  Not defined src type */
+       MEDIADEMUXER_SRC_FILE,          /**<  Local file src type */
+       MEDIADEMUXER_SRC_RTP,                   /**<  Rtp src type */
+       MEDIADEMUXER_SRC_WFD,                   /**<  Wfd src type */
+       MEDIADEMUXER_SRC_HTTP,          /**<  Http src type */
+       MEDIADEMUXER_SRC_SS,            /**<  Smooth streaming src type */
+       MEDIADEMUXER_SRC_RTSP,           /**<  Rtsp src type */
+       MEDIADEMUXER_SRC_UNKNOWN,        /**< Unknown src type */
+       MEDIADEMUXER_SRC_INVALID         /**<  Invalid src type */
+} mediademuxer_src_type;
+
+typedef struct _mediademuxer_s {
+       MMHandleType md_handle;
+       int state;
+       bool is_stopped;
+       pthread_t prepare_async_thread;
+       mediademuxer_error_cb error_cb;
+       void* error_cb_userdata;
+       mediademuxer_state demux_state;
+} mediademuxer_s;
+
+typedef struct {
+       /* initialize values */
+       media_port_demuxer_ops *demuxer_ops;
+       /* initialize values */
+       md_ini_t ini;
+       /* port specific handle */
+       /*Source information */
+       char *uri_src;
+       mediademuxer_src_type uri_src_media_type;
+       MMHandleType mdport_handle;
+} md_handle_t;
+
+int __convert_error_code(int code, char *func_name);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_PRIVATE_H__ */
diff --git a/include/mediademuxer_util.h b/include/mediademuxer_util.h
new file mode 100755 (executable)
index 0000000..ed99709
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_util.h
+ * @brief contain information about utility function such as debug, error log and other.
+ */
+
+#ifndef __TIZEN_MEDIADEMUXER_UTIL_H__
+#define __TIZEN_MEDIADEMUXER_UTIL_H__
+
+#include <glib.h>
+#include <mm_types.h>
+#include <mm_error.h>
+#include <mm_message.h>
+
+#include <mediademuxer_ini.h>
+#include <media_format.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 MD_FENTER();     PRINT_F("function:[%s] ENTER\n",__func__);
+#define MD_FLEAVE();     PRINT_F("function [%s] LEAVE\n",__func__);
+#define MD_C             PRINT_F
+#define MD_E             PRINT_F
+#define MD_W             PRINT_F
+#define MD_I             PRINT_F
+#define MD_L             PRINT_F
+#define MD_V             PRINT_F
+#define MD_F             PRINT_F
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#define MD_FENTER();     LOGI("function:[%s] ENTER\n",__func__);
+#define MD_FLEAVE();     LOGI("function [%s] LEAVE\n",__func__);
+#define MD_C             LOGE  /*MMF_DEBUG_LEVEL_0 */
+#define MD_E             LOGE  /*MMF_DEBUG_LEVEL_1 */
+#define MD_W             LOGW  /*MMF_DEBUG_LEVEL_2 */
+#define MD_I             LOGI  /*MMF_DEBUG_LEVEL_3 */
+#define MD_L             LOGI  /*MMF_DEBUG_LEVEL_4 */
+#define MD_V             LOGV  /*MMF_DEBUG_LEVEL_5 */
+#define MD_F             LOGF  /*MMF_DEBUG_LEVEL_6 - indicate that something in the executed code path is not fully implemented or handled yet */
+#endif
+
+/* general */
+#define MEDIADEMUXER_FREEIF(x) \
+       if ( x ) \
+               g_free( x ); \
+       x = NULL;
+
+#if 1
+#define MEDIADEMUXER_FENTER();              MD_FENTER();
+#define MEDIADEMUXER_FLEAVE();              MD_FLEAVE();
+#else
+#define MEDIADEMUXER_FENTER();
+#define MEDIADEMUXER_FLEAVE();
+#endif
+
+#define MEDIADEMUXER_CHECK_NULL( x_var ) \
+       if ( ! x_var ) \
+       { \
+               MD_E("[%s] is NULL\n", #x_var ); \
+               goto ERROR; \
+       }
+
+#define MEDIADEMUXER_CHECK_SET_AND_PRINT( x_var, x_cond, ret, ret_val, err_text ) \
+       if ( x_var != x_cond ) \
+       { \
+               ret = ret_val; \
+               MD_E("%s\n", #err_text ); \
+               goto ERROR; \
+       }
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_UTIL_H__ */
diff --git a/include/port_custom/mediademuxer_port_custom.h b/include/port_custom/mediademuxer_port_custom.h
new file mode 100755 (executable)
index 0000000..38ab5c3
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port_custom.h
+ * @brief Handling for Custom Port
+ */
+
+#ifndef __TIZEN_MEDIADEMUXER_PORT_CUSTOM_H__
+#define __TIZEN_MEDIADEMUXER_PORT_CUSTOM_H__
+
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Place holder*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_PORT_CUSTOM_H__ */
diff --git a/include/port_ffmpeg/mediademuxer_port_ffmpeg.h b/include/port_ffmpeg/mediademuxer_port_ffmpeg.h
new file mode 100755 (executable)
index 0000000..e86ca06
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port_ffmpeg.h
+ * @brief Handling for FFMPEG Port
+ */
+
+#ifndef __TIZEN_MEDIADEMUXER_PORT_FFMPEG_H__
+#define __TIZEN_MEDIADEMUXER_PORT_FFMPEG_H__
+
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Place holder*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_PORT_FFMPEG_H__ */
diff --git a/include/port_gst/mediademuxer_port_gst.h b/include/port_gst/mediademuxer_port_gst.h
new file mode 100755 (executable)
index 0000000..b02cce9
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port_gst.h
+ * @brief Handling for GST Port
+ */
+
+#ifndef __TIZEN_MEDIADEMUXER_PORT_GST_H__
+#define __TIZEN_MEDIADEMUXER_PORT_GST_H__
+
+#include <tizen.h>
+#include <gst/gst.h>
+#include <media_format.h>
+#include <gst/app/gstappsink.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define POLLING_INTERVAL 1000
+#define MAX_APP_BUFFER 100
+
+#define MEDIADEMUXER_SET_STATE( x_element, x_state, error ) \
+       do \
+       { \
+               MD_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) ) \
+               { \
+                       MD_E("failed to set state %s to %s\n", #x_state, GST_ELEMENT_NAME( x_element )); \
+                       goto error; \
+               } \
+       }while(0)
+
+#define MEDIADEMUXER_LINK_PAD( srcpad, sinkpad, error ) \
+       do \
+       { \
+               if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad) ) \
+               { \
+                       MD_E("failed to linkpad\n"); \
+                       goto error; \
+               } \
+       }while(0)
+
+typedef enum {
+       _GST_EVENT_TYPE_COMPLETE,
+       _GST_EVENT_TYPE_ERROR,
+       _GST_EVENT_TYPE_EOS,
+       _GST_EVENT_TYPE_NUM
+} _gst_event_e;
+
+typedef struct track {
+       GstPad *pad;
+       GstCaps *caps;
+       gchar *name;
+       gchar *caps_string;
+       GstElement *appsink;
+       GstElement *fakesink;
+       GstElement *queue;
+       struct track *next;
+} track;
+
+typedef struct track_info {
+       int num_audio_track;
+       int num_video_track;
+       int num_subtitle_track;
+       int num_other_track;
+       track *head;
+} track_info;
+
+/* GST port Private data */
+typedef struct _mdgst_handle_t {
+       void *hdemux;   /*< demux handle */
+       int state;      /*< demux current state */
+       bool is_prepared;
+       GstElement *pipeline;
+       GstElement *filesrc;
+       GstElement *typefind;
+       GstElement *demux;
+       GstElement *fakesink;
+       gulong signal_handoff;
+       gint bus_whatch_id;
+       bool is_valid_container;
+       track_info info;
+       int state_change_timeout;
+       bool *selected_tracks;
+       int total_tracks;
+       GMutex *mutex;
+       /* for user cb */
+       void* user_cb[_GST_EVENT_TYPE_NUM];
+       void* user_data[_GST_EVENT_TYPE_NUM];
+
+} mdgst_handle_t;
+
+/**
+ * @brief Called when the error has occured.
+ * @since_tizen 3.0
+ * @details It will be invoked when the error has occured.
+ * @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 mediademuxer_set_error_cb().
+ * @see mediademuxer_set_error_cb()
+ * @see mediademuxer_unset_error_cb()
+ */
+typedef void (*gst_error_cb)(mediademuxer_error_e error, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_MEDIADEMUXER_PORT_GST_H__ */
diff --git a/packaging/capi-mediademuxer.spec b/packaging/capi-mediademuxer.spec
new file mode 100755 (executable)
index 0000000..d25b022
--- /dev/null
@@ -0,0 +1,80 @@
+Name:       capi-mediademuxer
+Summary:    A Media Demuxer 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 Demuxer 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/mediademuxer_test %{buildroot}/usr/bin
+cp LICENSE.APLv2 %{buildroot}%{_datadir}/license/%{name}
+
+%make_install
+
+%post
+/sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+
+%files
+%manifest capi-mediademuxer.manifest
+%{_libdir}/libcapi-mediademuxer.so.*
+%{_datadir}/license/%{name}
+%{_bindir}/*
+
+%files devel
+%{_includedir}/media/*.h
+%{_libdir}/pkgconfig/*.pc
+%{_libdir}/libcapi-mediademuxer.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/mediademuxer.c b/src/mediademuxer.c
new file mode 100755 (executable)
index 0000000..79e538a
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * 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 <dlog.h>
+#include <mm.h>
+#include <mm_types.h>
+
+#include <mediademuxer.h>
+#include <mediademuxer_private.h>
+#include <mediademuxer_port.h>
+
+#ifndef USE_TASK_QUEUE
+#define USE_TASK_QUEUE
+#endif
+
+/*
+* Public Implementation
+*/
+static gboolean _mediademuxer_error_cb(mediademuxer_error_e error, void *user_data);
+
+int mediademuxer_create(mediademuxer_h *demuxer)
+{
+       MD_I("mediademuxer_create\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+
+       mediademuxer_s *handle;
+       if (*demuxer == NULL) {
+               handle = (mediademuxer_s *) g_malloc(sizeof(mediademuxer_s));
+               if (handle != NULL) {
+                       memset(handle, 0, sizeof(mediademuxer_s));
+                       handle->demux_state = MEDIADEMUXER_NONE;
+               } else {
+                       MD_E("[CoreAPI][%s] DEMUXER_ERROR_OUT_OF_MEMORY(0x%08x)",
+                           __FUNCTION__, MEDIADEMUXER_ERROR_OUT_OF_MEMORY);
+                       return MEDIADEMUXER_ERROR_OUT_OF_MEMORY;
+               }
+       } else {
+               MD_E("Already created the instance\n");
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+
+       ret = md_create(&handle->md_handle);
+
+       if (ret != MEDIADEMUXER_ERROR_NONE) {
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                       __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               free(handle);
+               handle = NULL;
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       } else {
+               *demuxer = (mediademuxer_h) handle;
+               handle->is_stopped = false;
+               MD_I("[CoreAPI][%s] new handle : %p", __FUNCTION__, *demuxer);
+       }
+       /* set callback */
+       md_set_error_cb(handle->md_handle,
+                       (mediademuxer_error_cb) _mediademuxer_error_cb,
+                       handle);
+       handle->demux_state = MEDIADEMUXER_IDLE;
+       return MEDIADEMUXER_ERROR_NONE;
+}
+
+int mediademuxer_set_data_source(mediademuxer_h demuxer, const char *path)
+{
+       MD_I("mediademuxer_set_data_source\n");
+       mediademuxer_error_e ret = MEDIADEMUXER_ERROR_NONE;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && path && handle->demux_state == MEDIADEMUXER_IDLE) {
+               ret = md_set_data_source((MMHandleType) (handle->md_handle), path);
+       } else {
+               if (!path) {
+                       MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                           __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_PATH);
+                       return MEDIADEMUXER_ERROR_INVALID_PATH;
+               } else {
+                       if(handle->demux_state != MEDIADEMUXER_IDLE)
+                               return MEDIADEMUXER_ERROR_INVALID_STATE;
+                       MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                           __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+                       return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+               }
+       }
+       return ret;
+}
+
+int mediademuxer_prepare(mediademuxer_h demuxer)
+{
+       MD_I("mediademuxer_prepare\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_IDLE) {
+               ret = md_prepare((MMHandleType) (handle->md_handle));
+               if (ret == MEDIADEMUXER_ERROR_NONE)
+                       handle->demux_state = MEDIADEMUXER_READY;
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_IDLE)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_get_track_count(mediademuxer_h demuxer, int *count)
+{
+       MD_I("mediademuxer_get_track_count\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_READY) {
+               ret = md_get_track_count((MMHandleType) (handle->md_handle), count);
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_READY)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_select_track(mediademuxer_h demuxer, int track_index)
+{
+       MD_I("mediademuxer_select_track\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_READY) {
+               ret = md_select_track((MMHandleType) (handle->md_handle), track_index);
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_READY)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_start(mediademuxer_h demuxer)
+{
+       MD_I("mediademuxer_start\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_READY) {
+               ret = md_start((MMHandleType) (handle->md_handle));
+               if (ret == MEDIADEMUXER_ERROR_NONE)
+                       handle->demux_state = MEDIADEMUXER_DEMUXING;
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_READY)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_get_track_info(mediademuxer_h demuxer, int track_index,
+                                media_format_h *format)
+{
+       MD_I("mediademuxer_get_track_info\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (track_index < 0 || format == NULL) {
+               MD_E("Invalid input parameters\n");
+               return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
+       }
+       if (handle && (handle->demux_state == MEDIADEMUXER_READY
+               || handle->demux_state == MEDIADEMUXER_DEMUXING)) {
+               ret = md_get_track_info((MMHandleType) (handle->md_handle), track_index, format);
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_READY)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_read_sample(mediademuxer_h demuxer, int track_index,
+                             media_packet_h *outbuf)
+{
+       MD_I("mediademuxer_read_sample\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (outbuf == NULL || track_index < 0) {
+               return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
+       }
+       if (handle && handle->demux_state == MEDIADEMUXER_DEMUXING) {
+               ret = md_read_sample((MMHandleType) (handle->md_handle), track_index, outbuf);
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_DEMUXING)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_seek(mediademuxer_h demuxer, int64_t pos)
+{
+       MD_I("mediademuxer_seek\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_DEMUXING) {
+               ret = md_seek((MMHandleType) (handle->md_handle), pos);
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_DEMUXING)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_unselect_track(mediademuxer_h demuxer, int track_index)
+{
+       MD_I("mediademuxer_unselect_track\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && (handle->demux_state == MEDIADEMUXER_READY
+               || handle->demux_state == MEDIADEMUXER_DEMUXING)) {
+               ret = md_unselect_track((MMHandleType) (handle->md_handle), track_index);
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_READY)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_stop(mediademuxer_h demuxer)
+{
+       MD_I("mediademuxer_stop\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_DEMUXING) {
+               ret = md_stop((MMHandleType) (handle->md_handle));
+               if (ret == MEDIADEMUXER_ERROR_NONE)
+                       handle->demux_state = MEDIADEMUXER_READY;
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_DEMUXING)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                    __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_unprepare(mediademuxer_h demuxer)
+{
+       MD_I("mediademuxer_unprepare\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_READY) {
+               ret = md_unprepare((MMHandleType) (handle->md_handle));
+               if (ret == MEDIADEMUXER_ERROR_NONE)
+                       handle->demux_state = MEDIADEMUXER_IDLE;
+       } else {
+               if(handle->demux_state != MEDIADEMUXER_READY)
+                       return MEDIADEMUXER_ERROR_INVALID_STATE;
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                       __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_destroy(mediademuxer_h demuxer)
+{
+       MD_I("mediademuxer_destroy\n");
+       mediademuxer_error_e ret;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle && handle->demux_state == MEDIADEMUXER_IDLE) {
+               ret = md_destroy(handle->md_handle);
+               if (ret != MEDIADEMUXER_ERROR_NONE) {
+                       MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                           __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+                       return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+               } else {
+                       MD_E("[CoreAPI][%s] destroy handle : %p", __FUNCTION__,
+                            handle);
+               }
+       } else {
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                           __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               return MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       handle->demux_state = MEDIADEMUXER_NONE;
+       return MEDIADEMUXER_ERROR_NONE;
+}
+
+int mediademuxer_get_state(mediademuxer_h demuxer, mediademuxer_state *state)
+{
+       MD_I("mediademuxer_get_state\n");
+       int ret = MEDIADEMUXER_ERROR_NONE;
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle = (mediademuxer_s *)(demuxer);
+       if (state != NULL) {
+               *state = handle->demux_state;
+       } else {
+               MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
+                       __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
+               ret = MEDIADEMUXER_ERROR_INVALID_OPERATION;
+       }
+       return ret;
+}
+
+int mediademuxer_set_error_cb(mediademuxer_h demuxer,
+                       mediademuxer_error_cb callback, void *user_data)
+{
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle->demux_state != MEDIADEMUXER_IDLE)
+               return MEDIADEMUXER_ERROR_INVALID_STATE;
+       handle->error_cb = callback;
+       handle->error_cb_userdata = user_data;
+       MD_I("set error_cb(%p)", callback);
+       return MEDIADEMUXER_ERROR_NONE;
+}
+
+int mediademuxer_unset_error_cb(mediademuxer_h demuxer)
+{
+       DEMUXER_INSTANCE_CHECK(demuxer);
+       mediademuxer_s *handle;
+       handle = (mediademuxer_s *)(demuxer);
+       if (handle->demux_state != MEDIADEMUXER_IDLE)
+               return MEDIADEMUXER_ERROR_INVALID_STATE;
+       handle->error_cb = NULL;
+       handle->error_cb_userdata = NULL;
+       MD_I("mediademuxer_unset_error_cb\n");
+       return MEDIADEMUXER_ERROR_NONE;
+}
+
+static gboolean _mediademuxer_error_cb(mediademuxer_error_e error, void *user_data)
+{
+       if(user_data == NULL){
+               MD_I("_mediademuxer_error_cb: ERROR %d to report. But call back is not set\n",error);
+               return 0;
+       }
+       mediademuxer_s * handle = (mediademuxer_s *) user_data;
+       if(handle->demux_state != MEDIADEMUXER_IDLE)
+               return MEDIADEMUXER_ERROR_INVALID_STATE;
+       if ( handle->error_cb ) {
+               ((mediademuxer_error_cb)handle->error_cb)(error, handle->error_cb_userdata);
+       }
+       else {
+               MD_I("_mediademuxer_error_cb: ERROR %d to report. But call back is not set\n",error);
+       }
+       return 0;
+}
diff --git a/src/mediademuxer_ini.c b/src/mediademuxer_ini.c
new file mode 100755 (executable)
index 0000000..07213d1
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_ini.c
+ * @brief INI laoding and parsing procedures
+ */
+
+#ifndef __MEDIADEMUXER_INI_C__
+#define __MEDIADEMUXER_INI_C__
+
+/* includes here */
+#include <glib.h>
+#include <stdlib.h>
+#include <glib/gstdio.h>
+#include <mediademuxer_error.h>
+#include <mm_debug.h>
+#include <mm_error.h>
+#include "iniparser.h"
+#include <mediademuxer_ini.h>
+#include <mediademuxer_private.h>
+
+/* internal functions, macros here */
+#ifdef MEDIADEMUXER_DEFAULT_INI
+static gboolean _generate_default_ini(void);
+#endif
+
+static void _md_ini_check_ini_status(void);
+
+/* macro */
+#define MEDIADEMUXER_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 ) < MEDIADEMUXER_INI_MAX_STRLEN ) ) \
+               { \
+                       strcpy ( x_item, str ); \
+               } \
+               else \
+               { \
+                       strcpy ( x_item, x_default ); \
+               } \
+       }while(0)
+
+#define MEDIADEMUXER_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 ) < MEDIADEMUXER_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 MEDIADEMUXER_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[MEDIADEMUXER_INI_MAX_STRLEN] = {0}; \
+               MMMEDIADEMUXER_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) \
+                       { \
+                               MD_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 MEDIADEMUXER_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[MEDIADEMUXER_INI_MAX_STRLEN] = {0}; \
+               MMMEDIADEMUXER_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) \
+                       { \
+                               MD_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)
+
+int md_ini_load(md_ini_t *ini)
+{
+       dictionary *dict = NULL;
+       _md_ini_check_ini_status();
+
+       /* first, try to load existing ini file */
+       dict = iniparser_load(MEDIADEMUXER_INI_DEFAULT_PATH);
+
+       /* if no file exists. create one with set of default values */
+       if (!dict) {
+#ifdef MEDIADEMUXER_DEFAULT_INI
+               MD_L("No inifile found. demuxer will create default inifile.\n");
+               if (FALSE == _generate_default_ini()) {
+                       MD_W("Creating default inifile failed. MediaDemuxer will use default values.\n");
+               } else {
+                       /* load default ini */
+                       dict = iniparser_load(MEDIADEMUXER_INI_DEFAULT_PATH);
+               }
+#else
+               MD_L("No ini file found. \n");
+               return MD_ERROR_FILE_NOT_FOUND;
+#endif
+       }
+
+       /* get ini values */
+       memset(ini, 0, sizeof(md_ini_t));
+
+       if (dict) {             /* if dict is available */
+               /* general */
+               MEDIADEMUXER_INI_GET_STRING(dict, ini->port_name,
+                                           "port_in_use:mediademuxer_port",
+                                           DEFAULT_PORT);
+       } else {                /* if dict is not available just fill the structure with default value */
+
+               MD_W("failed to load ini. using hardcoded default\n");
+               strncpy(ini->port_name, DEFAULT_PORT,
+                       MEDIADEMUXER_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 {
+               MD_E("Invalid port is set to [%s] [%d]\n", ini->port_name,
+                    ini->port_type);
+               goto ERROR;
+       }
+       MD_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 */
+       MD_L("demuxer settings -----------------------------------\n");
+
+       /* general */
+       MD_L("port_name: %s\n", ini->port_name);
+       MD_L("port_type : %d\n", ini->port_type);
+
+       return MD_ERROR_NONE;
+ERROR:
+       return MD_COURRPTED_INI;
+
+}
+
+static void _md_ini_check_ini_status(void)
+{
+       struct stat ini_buff;
+
+       if (g_stat(MEDIADEMUXER_INI_DEFAULT_PATH, &ini_buff) < 0) {
+               MD_W("failed to get demuxer ini status\n");
+       } else {
+               if (ini_buff.st_size < 5) {
+                       MD_W("demuxer.ini file size=%d, Corrupted! So, Removed\n", (int)ini_buff.st_size);
+
+                       if (g_remove(MEDIADEMUXER_INI_DEFAULT_PATH) == -1) {
+                               MD_E("failed to delete corrupted ini");
+                       }
+               }
+       }
+}
+
+#ifdef MEDIADEMUXER_DEFAULT_INI
+static gboolean _generate_default_ini(void)
+{
+       FILE *fp = NULL;
+       gchar *default_ini = MEDIADEMUXER_DEFAULT_INI;
+
+       /* create new file */
+       fp = fopen(MEDIADEMUXER_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 _MEDIADEMUXER_INI_C_ */
diff --git a/src/mediademuxer_port.c b/src/mediademuxer_port.c
new file mode 100755 (executable)
index 0000000..346c99e
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port.c
+ * @brief general port based functions. sets specific function pointers
+ */
+
+#include <string.h>
+#include <mm_types.h>
+#include <mm_message.h>
+#include <mm_debug.h>
+#include <mediademuxer.h>
+#include <mediademuxer_ini.h>
+#include <mediademuxer_error.h>
+#include <mediademuxer_private.h>
+#include <mediademuxer_port.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* function type */
+extern int gst_port_register(media_port_demuxer_ops *pOps);
+extern int ffmpeg_port_register(media_port_demuxer_ops *pOps);
+extern int custom_port_register(media_port_demuxer_ops *pOps);
+int __md_util_exist_file_path(const char *file_path);
+bool __md_util_is_sdp_file(const char *path);
+mediademuxer_src_type __md_util_media_type(char **uri);
+int _md_util_parse(MMHandleType demuxer, const char *type);
+
+/*
+  * Sequence of functions should be same as the port enumeration
+  * "port_mode" in mm_demuxer_ini.h file
+  */
+typedef int (*register_port)(media_port_demuxer_ops *);
+register_port register_port_func[] = {
+       &gst_port_register,
+       &ffmpeg_port_register,
+       &custom_port_register
+};
+
+int md_create(MMHandleType *demuxer)
+{
+       int result = MD_ERROR_NONE;
+       media_port_demuxer_ops *pOps = NULL;
+       md_handle_t *new_demuxer = NULL;
+       MEDIADEMUXER_FENTER();
+       new_demuxer = (md_handle_t *) g_malloc(sizeof(md_handle_t));
+       MD_I("md_create allocatiing new_demuxer %p:\n", new_demuxer);
+       MEDIADEMUXER_CHECK_NULL(new_demuxer);
+       memset(new_demuxer, 0, sizeof(md_handle_t));
+
+       /* alloc ops structure */
+       pOps = (media_port_demuxer_ops *) g_malloc(sizeof(media_port_demuxer_ops));
+       MEDIADEMUXER_CHECK_NULL(pOps);
+
+       new_demuxer->demuxer_ops = pOps;
+       MD_I("md_create allocating new_demuxer->demuxer_ops %p:\n",
+            new_demuxer->demuxer_ops);
+       pOps->n_size = sizeof(media_port_demuxer_ops);
+
+       new_demuxer->uri_src = NULL;
+       new_demuxer->uri_src_media_type = MEDIADEMUXER_SRC_INVALID;
+       /* load ini files */
+       result = md_ini_load(&new_demuxer->ini);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_COURRPTED_INI, "can't load ini");
+
+       register_port_func[new_demuxer->ini.port_type](pOps);
+       result = pOps->init(&new_demuxer->mdport_handle);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_NOT_INITIALIZED,
+                                        "md_create failed");
+       *demuxer = (MMHandleType) new_demuxer;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       *demuxer = (MMHandleType) 0;
+       if (pOps)
+               g_free(pOps);
+       if (new_demuxer)
+               g_free(new_demuxer);
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int __md_util_exist_file_path(const char *file_path)
+{
+       int fd = 0;
+       struct stat stat_results = { 0, };
+       MEDIADEMUXER_FENTER();
+
+       if (!file_path || !strlen(file_path))
+               return MD_ERROR_FILE_NOT_FOUND;
+
+       fd = open(file_path, O_RDONLY);
+       if (fd < 0) {
+               MD_E("failed to open file by %s (%d)\n", strerror(errno), errno);
+               if (EACCES == errno) {
+                       MEDIADEMUXER_FLEAVE();
+                       return MD_ERROR_FILE_NOT_FOUND;
+               }
+       }
+
+       if (fstat(fd, &stat_results) < 0) {
+               MD_E("failed to get file status\n");
+               close(fd);
+               MEDIADEMUXER_FLEAVE();
+               return MD_ERROR_FILE_NOT_FOUND;
+       } else if (stat_results.st_size == 0) {
+               MD_E("file size is zero\n");
+               close(fd);
+               MEDIADEMUXER_FLEAVE();
+               return MD_ERROR_FILE_NOT_FOUND;
+       } else {
+               MD_E("file size : %lld bytes\n",
+                    (long long)stat_results.st_size);
+       }
+       close(fd);
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+}
+
+bool __md_util_is_sdp_file(const char *path)
+{
+       gboolean ret = FALSE;
+       gchar *uri = NULL;
+       MEDIADEMUXER_FENTER();
+       return_val_if_fail(path, FALSE);
+       uri = g_ascii_strdown(path, -1);
+       if (uri == NULL) {
+               return FALSE;
+       }
+       /* trimming */
+       g_strstrip(uri);
+       /* strlen(".sdp") == 4 */
+       if (strlen(uri) <= 4) {
+               MD_W("path is too short.\n");
+               return ret;
+       }
+       /* first, check extension name */
+       ret = g_str_has_suffix(uri, "sdp");
+       /* second, if no suffix is there, check it's contents */
+       if (!ret) {
+               /* FIXIT : do it soon */
+       }
+       g_free(uri);
+       uri = NULL;
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+mediademuxer_src_type __md_util_media_type(char **uri)
+{
+       char *path = NULL;
+       char *new_uristr = NULL;
+       char *old_uristr = NULL;
+       MEDIADEMUXER_FENTER();
+       if ((path = strstr((*uri), "file://"))) {
+               int file_stat = MD_ERROR_NONE;
+               file_stat = __md_util_exist_file_path(path + 7);
+               if (file_stat == MD_ERROR_NONE) {
+                       if (__md_util_is_sdp_file(path)) {
+                               MD_L("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
+                               return MEDIADEMUXER_SRC_RTSP;
+                       } else {
+                               return MEDIADEMUXER_SRC_FILE;
+                       }
+                       return MD_ERROR_NONE;
+               } else {
+                       MD_E("could  access %s.\n", path);
+               }
+       } else if ((path = strstr(*uri, "rtsp://"))) {
+               if (strlen(path)) {
+                       if ((path = strstr(*uri, "/wfd1.0/"))) {
+                               return (MEDIADEMUXER_SRC_WFD);
+                       } else {
+                               return (MEDIADEMUXER_SRC_RTSP);
+                       }
+               }
+       } else if ((path = strstr(*uri, "http://"))) {
+               if (strlen(path)) {
+                       if (g_str_has_suffix(g_ascii_strdown(*uri, strlen(*uri)), ".ism/manifest") ||
+                            g_str_has_suffix(g_ascii_strdown(*uri, strlen(*uri)), ".isml/manifest")) {
+                               return (MEDIADEMUXER_SRC_SS);
+                       } else {
+                               return (MEDIADEMUXER_SRC_HTTP);
+                       }
+               }
+       } else {
+               int file_stat = MD_ERROR_NONE;
+               file_stat = __md_util_exist_file_path(*uri);
+               if (file_stat == MD_ERROR_NONE) {
+                       int len_uri = strlen(*uri);
+                       old_uristr = (char *)g_malloc(sizeof(char) * (len_uri + 1));
+                       MEDIADEMUXER_CHECK_NULL(old_uristr);
+                       MD_L("allocating temp old_uristr[%p] \n", old_uristr);
+                       strncpy(old_uristr, *uri, len_uri + 1);
+                       /* need to added 7 char for file:// + 1 for '\0'+ uri len */
+                       new_uristr = (char *)realloc(*uri, (7 + len_uri + 1) * sizeof(char));
+                       MEDIADEMUXER_CHECK_NULL(new_uristr);
+                       MD_L("reallocating uri[%p] to new_uristr[%p] \n", *uri, new_uristr);
+                       *uri = new_uristr;
+                       g_snprintf(*uri, 7 + len_uri + 1, "file://%s", old_uristr);
+                       MD_L("deallocating old_uristr[%p] \n", old_uristr);
+                       free(old_uristr);
+                       old_uristr = NULL;
+                       if (__md_util_is_sdp_file((char *)(*uri))) {
+                               MD_L("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
+                               return (MEDIADEMUXER_SRC_RTSP);
+                       } else {
+                               return (MEDIADEMUXER_SRC_FILE);
+                       }
+               } else {
+                       goto ERROR;
+               }
+       }
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+ERROR:
+       if (new_uristr)
+               free(new_uristr);
+       if (old_uristr)
+               free(old_uristr);
+       MEDIADEMUXER_FLEAVE();
+       return MEDIADEMUXER_SRC_INVALID;
+}
+
+int _md_util_parse(MMHandleType demuxer, const char *type)
+{
+       char *media_type_string = NULL;
+       int lenght_string = 0;
+       int result = MD_ERROR_NONE;
+       md_handle_t *new_demuxer = NULL;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(demuxer);
+       new_demuxer = (md_handle_t *) demuxer;
+       lenght_string = strlen(type);
+       media_type_string = (char *)g_malloc(sizeof(char) * (lenght_string + 1));
+       MEDIADEMUXER_CHECK_NULL(media_type_string);
+       MD_L("media_type_string allocating %p\n", media_type_string);
+       strncpy(media_type_string, type, lenght_string + 1);
+       /*Set media_type depending upon the header of string else consider using file protocol */
+       if (new_demuxer->uri_src) {
+               free(new_demuxer->uri_src);
+               MD_L("new_demuxer->uri_src deallocating %p\n", new_demuxer->uri_src);
+       }
+       new_demuxer->uri_src_media_type = __md_util_media_type(&media_type_string);
+       if (new_demuxer->uri_src_media_type != MEDIADEMUXER_SRC_INVALID) {
+               new_demuxer->uri_src = media_type_string;
+               MD_L("uri:%s\n uri_type:%d\n", new_demuxer->uri_src,
+                    new_demuxer->uri_src_media_type);
+       } else {
+               MD_E("Error while setiing source\n");
+               MD_E("deallocating media_type_string %p\n", media_type_string);
+               free(media_type_string);
+               goto ERROR;
+       }
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_set_data_source(MMHandleType demuxer, const char *uri)
+{
+       int result = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(demuxer);
+       result = _md_util_parse(demuxer, (const char *)uri);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR_INVALID_ARGUMENT,
+                                        "error while parsing the file");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_prepare(MMHandleType demuxer)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->prepare(md_handle->mdport_handle, md_handle->uri_src);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error while doing prepare");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_get_track_count(MMHandleType demuxer, int *count)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->get_track_count(md_handle->mdport_handle, count);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE,
+                                        result, MD_ERROR,
+                                        "error while getting track count");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_select_track(MMHandleType demuxer, int track)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->set_track(md_handle->mdport_handle, track);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error select track");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_start(MMHandleType demuxer)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->start(md_handle->mdport_handle);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error while doing start");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_get_track_info(MMHandleType demuxer, int track, media_format_h *format)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->get_track_info(md_handle->mdport_handle, format, track);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE,
+                                        result, MD_ERROR,
+                                        "error while getting track count");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_read_sample(MMHandleType demuxer, int track_indx, media_packet_h *outbuf)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->read_sample(md_handle->mdport_handle, outbuf, track_indx);
+       if (result == MD_EOS || result == MD_ERROR_NONE) {
+               return result;
+       } else {
+               MD_E("error while reading sample\n");
+               goto ERROR;
+       }
+       MEDIADEMUXER_FLEAVE();
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_seek(MMHandleType demuxer, int64_t pos)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->seek(md_handle->mdport_handle, pos);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error while doing seek");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_unselect_track(MMHandleType demuxer, int track)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->unset_track(md_handle->mdport_handle, track);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error unselect track");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_stop(MMHandleType demuxer)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->stop(md_handle->mdport_handle);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error while doing stop");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_unprepare(MMHandleType demuxer)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->unprepare(md_handle->mdport_handle);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error while doing stop");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
+
+int md_destroy(MMHandleType demuxer)
+{
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       MEDIADEMUXER_FENTER();
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->destroy(md_handle->mdport_handle);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                                        MD_ERROR, "error while doing destroy");
+
+       /* free mediademuxer structure */
+       if (md_handle) {
+               if (md_handle->demuxer_ops) {
+                       MD_I("md_destroy deallocating md_handle->demuxer_ops %p:\n", md_handle->demuxer_ops);
+                       g_free((void *)(md_handle->demuxer_ops));
+               }
+               if (md_handle->uri_src) {
+                       MD_I("md_destroy deallocating md_handle->uri_src %p:\n",
+                            md_handle->uri_src);
+                       g_free((void *)(md_handle->uri_src));
+               }
+               MD_I("md_destroy deallocating md_handle %p:\n", md_handle);
+               g_free((void *)md_handle);
+               md_handle = NULL;
+       }
+       MEDIADEMUXER_FLEAVE();
+       return result;
+
+ERROR:
+       return result;
+}
+
+int md_set_error_cb(MMHandleType demuxer,
+                       mediademuxer_error_cb callback, void *user_data)
+{
+       MEDIADEMUXER_FENTER();
+       int result = MD_ERROR_NONE;
+       md_handle_t *md_handle = (md_handle_t *) demuxer;
+       MEDIADEMUXER_CHECK_NULL(md_handle);
+       media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       result = pOps->set_error_cb(md_handle->mdport_handle, callback,user_data);
+       MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
+                       MD_ERROR, "error while setting error call back");
+       MEDIADEMUXER_FLEAVE();
+       return result;
+ERROR:
+       result = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return result;
+}
diff --git a/src/port_custom/mediademuxer_port_custom.c b/src/port_custom/mediademuxer_port_custom.c
new file mode 100755 (executable)
index 0000000..15c7bfc
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port_custom.c
+ * @brief Handling for Custom Port, defined function and there implementation
+ */
+
+#include <mm_debug.h>
+#include <mediademuxer_error.h>
+#include <mediademuxer_private.h>
+#include <mediademuxer_port.h>
+#include <mediademuxer_port_custom.h>
+
+static int custom_demuxer_init(MMHandleType *pHandle);
+static int custom_demuxer_prepare(MMHandleType pHandle, char *uri);
+static int custom_demuxer_get_data_count(MMHandleType pHandle, int *count);
+static int custom_demuxer_get_track_info(MMHandleType pHandle,
+                                         media_format_h *format, int track);
+static int custom_demuxer_set_track(MMHandleType pHandle, int track);
+static int custom_demuxer_get_data(MMHandleType pHandle, char *buffer);
+
+/*Media Demuxer API common*/
+static media_port_demuxer_ops def_demux_ops = {
+       .n_size = 0,
+       .init = custom_demuxer_init,
+       .prepare = custom_demuxer_prepare,
+       .get_track_count = custom_demuxer_get_data_count,
+       .get_track_info = custom_demuxer_get_track_info,
+       .set_track = custom_demuxer_set_track,
+       .get_data = custom_demuxer_get_data,
+};
+
+int custom_port_register(media_port_demuxer_ops *pOps)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(pOps);
+
+       def_demux_ops.n_size = sizeof(def_demux_ops);
+
+       memcpy((char *)pOps + sizeof(pOps->n_size),
+              (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
+              pOps->n_size - sizeof(pOps->n_size));
+
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MD_ERROR_INVALID_ARGUMENT;
+       return ret;
+}
+
+static int custom_demuxer_init(MMHandleType *pHandle)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int custom_demuxer_prepare(MMHandleType pHandle, char *uri)
+{
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return 0;
+}
+
+
+static int custom_demuxer_get_data_count(MMHandleType pHandle, int *count)
+{
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return 0;
+}
+
+static int custom_demuxer_get_track_info(MMHandleType pHandle,
+                                         media_format_h *format, int track)
+{
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return 0;
+}
+
+static int custom_demuxer_set_track(MMHandleType pHandle, int track)
+{
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return 0;
+}
+
+static int custom_demuxer_get_data(MMHandleType pHandle, char *buffer)
+{
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return 0;
+}
diff --git a/src/port_ffmpeg/mediademuxer_port_ffmpeg.c b/src/port_ffmpeg/mediademuxer_port_ffmpeg.c
new file mode 100755 (executable)
index 0000000..7e55d4e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port_ffmpeg.c
+ * @brief Handling for FFMPEG Port, defined function and there implementation
+ */
+
+#include <mm_debug.h>
+#include <mediademuxer_error.h>
+#include <mediademuxer_private.h>
+#include <mediademuxer_port.h>
+#include <mediademuxer_port_ffmpeg.h>
+
+static int ffmpeg_demuxer_init(MMHandleType *pHandle);
+static int ffmpeg_demuxer_prepare(MMHandleType pHandle, char *uri);
+static int ffmpeg_demuxer_get_data_count(MMHandleType pHandle, int *count);
+static int ffmpeg_demuxer_get_track_info(MMHandleType pHandle,
+                       media_format_h *format, int track);
+static int ffmpeg_demuxer_set_track(MMHandleType pHandle, int track);
+static int ffmpeg_demuxer_get_data(MMHandleType pHandle, char *buffer);
+
+/*Media Demuxer API common*/
+static media_port_demuxer_ops def_demux_ops = {
+       .n_size = 0,
+       .init = ffmpeg_demuxer_init,
+       .prepare = ffmpeg_demuxer_prepare,
+       .get_track_count = ffmpeg_demuxer_get_data_count,
+       .get_track_info = ffmpeg_demuxer_get_track_info,
+       .set_track = ffmpeg_demuxer_set_track,
+       .get_data = ffmpeg_demuxer_get_data,
+};
+
+int ffmpeg_port_register(media_port_demuxer_ops *pOps)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(pOps);
+
+       def_demux_ops.n_size = sizeof(def_demux_ops);
+
+       memcpy((char *)pOps + sizeof(pOps->n_size),
+              (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
+              pOps->n_size - sizeof(pOps->n_size));
+
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MD_ERROR_INVALID_ARGUMENT;
+       return ret;
+}
+
+static int ffmpeg_demuxer_init(MMHandleType *pHandle)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int ffmpeg_demuxer_prepare(MMHandleType pHandle, char *uri)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int ffmpeg_demuxer_get_data_count(MMHandleType pHandle, int *count)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int ffmpeg_demuxer_get_track_info(MMHandleType pHandle,
+                                         media_format_h *format, int track)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int ffmpeg_demuxer_set_track(MMHandleType pHandle, int track)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int ffmpeg_demuxer_get_data(MMHandleType pHandle, char *buffer)
+{
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_FENTER();
+       MD_E("%s:exit: Not implemented\n", __func__);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
diff --git a/src/port_gst/mediademuxer_port_gst.c b/src/port_gst/mediademuxer_port_gst.c
new file mode 100755 (executable)
index 0000000..1ed26b9
--- /dev/null
@@ -0,0 +1,1280 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mediademuxer_port_gst.c
+ * @brief Handling for GStreamer Port, defined function and there implementation
+ */
+
+#include <mm_debug.h>
+#include <unistd.h>
+#include <mediademuxer_error.h>
+#include <mediademuxer_private.h>
+#include <mediademuxer_port.h>
+#include <mediademuxer_port_gst.h>
+
+static int gst_demuxer_init(MMHandleType *pHandle);
+static int gst_demuxer_prepare(MMHandleType pHandle, char *uri);
+static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count);
+static int gst_demuxer_set_track(MMHandleType pHandle, int track);
+static int gst_demuxer_start(MMHandleType pHandle);
+static int gst_demuxer_read_sample(MMHandleType pHandle,
+                       media_packet_h *outbuf, int track_indx);
+static int gst_demuxer_get_track_info(MMHandleType pHandle,
+                       media_format_h *format, int index);
+static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1);
+static int gst_demuxer_unset_track(MMHandleType pHandle, int track);
+static int gst_demuxer_stop(MMHandleType pHandle);
+static int gst_demuxer_unprepare(MMHandleType pHandle);
+static int gst_demuxer_destroy(MMHandleType pHandle);
+static int gst_set_error_cb(MMHandleType pHandle,
+                       gst_error_cb callback, void* user_data);
+
+/*Media Demuxer API common*/
+static media_port_demuxer_ops def_demux_ops = {
+       .n_size = 0,
+       .init = gst_demuxer_init,
+       .prepare = gst_demuxer_prepare,
+       .get_track_count = gst_demuxer_get_data_count,
+       .set_track = gst_demuxer_set_track,
+       .start = gst_demuxer_start,
+       .get_track_info = gst_demuxer_get_track_info,
+       .read_sample = gst_demuxer_read_sample,
+       .seek = gst_demuxer_seek,
+       .unset_track = gst_demuxer_unset_track,
+       .stop = gst_demuxer_stop,
+       .unprepare = gst_demuxer_unprepare,
+       .destroy = gst_demuxer_destroy,
+       .set_error_cb = gst_set_error_cb,
+};
+
+int gst_port_register(media_port_demuxer_ops *pOps)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pOps);
+       def_demux_ops.n_size = sizeof(def_demux_ops);
+
+       memcpy((char *)pOps + sizeof(pOps->n_size),
+              (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
+              pOps->n_size - sizeof(pOps->n_size));
+
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       ret = MD_ERROR_INVALID_ARGUMENT;
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_init(MMHandleType *pHandle)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       mdgst_handle_t *new_mediademuxer = NULL;
+       new_mediademuxer = (mdgst_handle_t *) g_malloc(sizeof(mdgst_handle_t));
+       MD_I("gst_demuxer_init allocating new_mediademuxer:%p\n", new_mediademuxer);
+       if (!new_mediademuxer) {
+               MD_E("Cannot allocate memory for demuxer\n");
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+       memset(new_mediademuxer, 0, sizeof(mdgst_handle_t));
+       new_mediademuxer->is_prepared = false;
+       (new_mediademuxer->info).num_audio_track = 0;
+       (new_mediademuxer->info).num_video_track = 0;
+       (new_mediademuxer->info).num_subtitle_track = 0;
+       (new_mediademuxer->info).num_other_track = 0;
+       (new_mediademuxer->info).head = NULL;
+       *pHandle = (MMHandleType) new_mediademuxer;
+       new_mediademuxer->total_tracks = 0;
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       switch (GST_MESSAGE_TYPE(msg)) {
+               case GST_MESSAGE_EOS: {
+                               MD_I("EOS Reached");
+                       }
+                       break;
+               case GST_MESSAGE_ERROR: {
+                               GError *error = NULL;
+                               gst_message_parse_error(msg, &error, NULL);
+                               if (!error) {
+                                       MD_I("GST error message parsing failed");
+                                       break;
+                               }
+                               MD_E("Error: %s\n", error->message);
+                               g_error_free(error);
+                       }
+                       break;
+               default:
+                       break;
+       }
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static void __gst_no_more_pad(GstElement *element, gpointer data)
+{
+       MEDIADEMUXER_FENTER();
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
+       int loop_track;
+       track_info *head_track = &(gst_handle->info);
+       track *head = head_track->head;
+       gst_handle->selected_tracks =
+           (bool *) g_malloc(sizeof(bool) * (gst_handle->total_tracks));
+       MD_I("Allocating %p to core->selected_tracks \n", gst_handle->selected_tracks);
+       if (!gst_handle->selected_tracks) {
+               MD_E("[%s]Memory allocation failed\n", __FUNCTION__);
+               return;
+       } else {
+               for (loop_track = 0; loop_track < gst_handle->total_tracks;
+                    loop_track++)
+                       gst_handle->selected_tracks[loop_track] = false;
+       }
+       MD_I("Number of video tracks are %d\n", head_track->num_video_track);
+       MD_I("Number of audio tracks are %d\n", head_track->num_audio_track);
+       MD_I("Number of subtitle tracks are %d\n",
+            head_track->num_subtitle_track);
+       MD_I("Number of other tracks are %d\n", head_track->num_other_track);
+       while (head) {
+               MD_I("track caps[%s]\n", head->name);
+               head = head->next;
+       }
+       gst_handle->is_prepared = true;
+       MD_I("core->is_prepared: ");
+       gst_handle->is_prepared ? MD_I("true\n") : MD_I("false\n");
+       MEDIADEMUXER_FLEAVE();
+}
+
+void __gst_free_stuct(track **head)
+{
+       MEDIADEMUXER_FENTER();
+       track *temp = NULL;
+       temp = *head;
+       while (temp) {
+               /*
+               if (temp->pad) {
+               MD_I("deallocate GST_PAD %p\n", temp->pad);
+               gst_object_unref(temp->pad);
+               } */
+               if (temp->name) {
+                       MD_I("deallocate GST_PAD name  %p\n", temp->name);
+                       g_free(temp->name);
+               }
+               if (temp->caps_string) {
+                       MD_I("deallocate GST_PAD caps_string  %p\n",
+                            temp->caps_string);
+                       g_free(temp->caps_string);
+               }
+               if (temp->caps) {
+                       MD_I("deallocate GST_PAD caps_  %p\n", temp->caps);
+                       gst_caps_unref(temp->caps);
+               }
+
+               if (temp->next) {
+                       track *next = temp->next;
+                       MD_I("deallocate memory %p\n", temp);
+                       free(temp);
+                       temp = next;
+               } else {
+                       MD_I("deallocate memory %p\n", temp);
+                       free(temp);
+                       temp = NULL;
+                       *head = NULL;
+               }
+       }
+       MEDIADEMUXER_FLEAVE();
+}
+
+int __gst_add_track_info(GstPad *pad, gchar *name, track **head,
+                         GstElement *pipeline)
+{
+       MEDIADEMUXER_FENTER();
+       GstPad *apppad = NULL;
+       track *temp = NULL;
+       temp = (track *)(g_malloc(sizeof(track)));
+       if (!temp) {
+               MD_E("Not able to allocate memory");
+               return MD_ERROR;
+       } else {
+               MD_I("allocate memory %p", temp);
+       }
+       temp->pad = pad;
+       temp->caps = gst_pad_get_current_caps(pad);
+       temp->name = name;
+       temp->caps_string = gst_caps_to_string(temp->caps);
+       temp->next = NULL;
+       temp->appsink = gst_element_factory_make("appsink", NULL);
+       if (!temp->appsink) {
+               MD_E("factory not able to make appsink");
+               __gst_free_stuct(head);
+               return MD_ERROR;
+       }
+       gst_bin_add_many(GST_BIN(pipeline), temp->appsink, NULL);
+       gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, MAX_APP_BUFFER);
+       MEDIADEMUXER_SET_STATE(temp->appsink, GST_STATE_PAUSED, ERROR);
+       apppad = gst_element_get_static_pad(temp->appsink, "sink");
+       if (!apppad) {
+               MD_E("sink pad of appsink not avaible");
+               __gst_free_stuct(head);
+               return MD_ERROR;
+       }
+       MEDIADEMUXER_LINK_PAD(pad, apppad, ERROR);
+       /*gst_pad_link(pad, fpad) */
+       if (*head == NULL) {
+               *head = temp;
+       } else {
+               track *prev = *head;
+               while (prev->next) {
+                       prev = prev->next;
+               }
+               prev->next = temp;
+       }
+       gst_object_unref(apppad);
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+ERROR:
+       if (apppad)
+               gst_object_unref(apppad);
+       __gst_free_stuct(head);
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
+{
+       MEDIADEMUXER_FENTER();
+       MD_I("Dynamic pad created, linking demuxer/decoder\n");
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
+       track_info *head_track = &(gst_handle->info);
+       gchar *name = gst_pad_get_name(pad);
+       gst_handle->total_tracks++;
+       if (__gst_add_track_info(pad, name, &(head_track->head), gst_handle->pipeline)
+           != MD_ERROR_NONE) {
+               MD_E("unable to added track info");
+               head_track->num_audio_track = 0;
+               head_track->num_video_track = 0;
+               head_track->num_subtitle_track = 0;
+               head_track->num_other_track = 0;
+               __gst_free_stuct(&(head_track->head));
+               return;
+       }
+       if (name[0] == 'v') {
+               MD_I("found Video Pad\n");
+               (head_track->num_video_track)++;
+       } else if (name[0] == 'a') {
+               MD_I("found Audio Pad\n");
+               (head_track->num_audio_track)++;
+       } else if (name[0] == 's') {
+               MD_I("found subtitle Pad\n");
+               (head_track->num_subtitle_track)++;
+       } else {
+               MD_I("found Pad %s\n", name);
+               (head_track->num_other_track)++;
+       }
+       MEDIADEMUXER_FLEAVE();
+}
+
+static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
+{
+       MEDIADEMUXER_FENTER();
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
+       GstPad *pad = NULL;
+       GstPad *aud_pad = NULL;
+       GstPad *aud_srcpad = NULL;
+       GstPad *fake_pad = NULL;
+       GstElement *id3tag = NULL;
+       gchar *name;
+       gchar *type;
+       track_info *head_track = &(gst_handle->info);
+       track *trck;
+       gst_handle->is_valid_container = true;
+       type = gst_caps_to_string(caps);
+       if (strstr(type, "adts")) {
+               gst_handle->demux = gst_element_factory_make("aacparse", NULL);
+       } else if (strstr(type, "audio/mpeg")) {
+               gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
+       } else if (strstr(type, "application/x-id3")) {
+               id3tag = gst_element_factory_make("id3demux", NULL);
+               gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
+       } else if (strstr(type, "audio/x-amr-nb-sh")
+                  || strstr(type, "audio/x-amr-wb-sh")) {
+               gst_handle->demux = gst_element_factory_make("amrparse", NULL);
+       }
+       g_free(type);
+       if (!gst_handle->demux) {
+               gst_handle->is_valid_container = false;
+               MD_E("factory not able to create audio parse element\n");
+               goto ERROR;
+       } else {
+               gst_bin_add_many(GST_BIN(gst_handle->pipeline),
+                                gst_handle->demux, id3tag, NULL);
+               pad = gst_element_get_static_pad(gst_handle->typefind, "src");
+               if (!pad) {
+                       MD_E("fail to get typefind src pad.\n");
+                       goto ERROR;
+               }
+               if (!id3tag) {
+                       aud_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
+               } else {
+                       aud_pad = gst_element_get_static_pad(id3tag, "sink");
+               }
+               if (!aud_pad) {
+                       MD_E("fail to get audio parse sink pad.\n");
+                       goto ERROR;
+               }
+               fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
+               if (!fake_pad) {
+                       MD_E("fail to get fakesink sink pad.\n");
+                       goto ERROR;
+               }
+               gst_pad_unlink(pad, fake_pad);
+               MEDIADEMUXER_LINK_PAD(pad, aud_pad, ERROR);
+               if (!id3tag) {
+                       MEDIADEMUXER_SET_STATE(gst_handle->demux,
+                                              GST_STATE_PAUSED, ERROR);
+               } else {
+                       MEDIADEMUXER_SET_STATE(id3tag, GST_STATE_PAUSED, ERROR);
+                       MEDIADEMUXER_SET_STATE(gst_handle->demux,
+                                              GST_STATE_PAUSED, ERROR);
+                       gst_element_link(id3tag, gst_handle->demux);
+               }
+               if (pad)
+                       gst_object_unref(pad);
+               if (aud_pad)
+                       gst_object_unref(aud_pad);
+               if (fake_pad)
+                       gst_object_unref(fake_pad);
+       }
+
+       /* calling "on_pad_added" function to set the caps*/
+       aud_srcpad = gst_element_get_static_pad(gst_handle->demux, "src");
+       if (!aud_srcpad) {
+               MD_E("fail to get audioparse source pad.\n");
+               goto ERROR;
+       }
+       gst_handle->total_tracks++;
+       name = gst_pad_get_name(aud_srcpad);
+       if (__gst_add_track_info(aud_srcpad, name, &(head_track->head), gst_handle->pipeline)
+           != MD_ERROR_NONE) {
+               MD_E("unable to added track info");
+               head_track->num_audio_track = 0;
+               head_track->num_video_track = 0;
+               head_track->num_subtitle_track = 0;
+               head_track->num_other_track = 0;
+               __gst_free_stuct(&(head_track->head));
+               goto ERROR;
+       }
+       if (aud_srcpad)
+               gst_object_unref(aud_srcpad);
+
+       trck = head_track->head;
+       while (aud_srcpad != trck->pad && trck != NULL) {
+               trck = trck->next;
+       }
+       if (trck != NULL) {
+               trck->caps = caps;
+               trck->caps_string = gst_caps_to_string(trck->caps);
+               MD_I("caps set to %s\n",trck->caps_string);
+               g_strlcpy(name,"audio",strlen(name));
+               trck->name = name;
+       }
+       (head_track->num_audio_track)++;
+       __gst_no_more_pad(gst_handle->demux, data);
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+ERROR:
+       gst_handle->is_valid_container = false;
+       if (gst_handle->demux)
+               gst_object_unref(gst_handle->demux);
+       if (pad)
+               gst_object_unref(pad);
+       if (aud_pad)
+               gst_object_unref(aud_pad);
+       if (fake_pad)
+               gst_object_unref(fake_pad);
+       if (aud_srcpad)
+               gst_object_unref(aud_srcpad);
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+static void __gst_cb_typefind(GstElement *tf, guint probability,
+                  GstCaps *caps, gpointer data)
+{
+       MEDIADEMUXER_FENTER();
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
+       GstPad *pad = NULL;
+       GstPad *qt_pad = NULL;
+       GstPad *fake_pad = NULL;
+       gchar *type;
+       type = gst_caps_to_string(caps);
+       if (type) {
+               MD_I("Media type %s found, probability %d%%\n", type, probability);
+               if (strstr(type, "quicktime")) {
+                       gst_handle->is_valid_container = true;
+                       gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
+                       if (!gst_handle->demux) {
+                               gst_handle->is_valid_container = false;
+                               MD_E("factory not able to create qtdemux\n");
+                               goto ERROR;
+                       } else {
+                               g_signal_connect(gst_handle->demux, "pad-added",
+                                                G_CALLBACK(__gst_on_pad_added), gst_handle);
+                               g_signal_connect(gst_handle->demux, "no-more-pads",
+                                                G_CALLBACK(__gst_no_more_pad), gst_handle);
+                               gst_bin_add_many(GST_BIN(gst_handle->pipeline),
+                                                gst_handle->demux, NULL);
+                               pad = gst_element_get_static_pad(gst_handle->typefind, "src");
+                               if (!pad) {
+                                       MD_E("fail to get typefind src pad.\n");
+                                       goto ERROR;
+                               }
+                               qt_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
+                               if (!qt_pad) {
+                                       MD_E("fail to get qtdemuc sink pad.\n");
+                                       goto ERROR;
+                               }
+                               fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
+                               if (!fake_pad) {
+                                       MD_E("fail to get fakesink sink pad.\n");
+                                       goto ERROR;
+                               }
+                               gst_pad_unlink(pad, fake_pad);
+                               MEDIADEMUXER_LINK_PAD(pad, qt_pad, ERROR);
+                               MEDIADEMUXER_SET_STATE(gst_handle->demux,
+                                                      GST_STATE_PAUSED, ERROR);
+                               if (pad)
+                                       gst_object_unref(pad);
+                               if (qt_pad)
+                                       gst_object_unref(qt_pad);
+                               if (fake_pad)
+                                       gst_object_unref(fake_pad);
+                       }
+               } else if ((strstr(type, "adts"))
+                          || (strstr(type, "audio/mpeg"))
+                          || (strstr(type, "application/x-id3"))
+                          || (strstr(type, "audio/x-amr-nb-sh"))
+                          || (strstr(type, "audio/x-amr-wb-sh"))) {
+                       MD_I("Audio only format is found\n");
+                       __gst_create_audio_only_pipeline(data, caps);
+               } else {
+                       gst_handle->is_valid_container = false;
+                       MD_E("Not supported container %s\n", type);
+               }
+               g_free(type);
+       }
+       MEDIADEMUXER_FLEAVE();
+       return;
+ERROR:
+       gst_handle->is_valid_container = false;
+       if (gst_handle->demux)
+               gst_object_unref(gst_handle->demux);
+       if (type)
+               g_free(type);
+       if (pad)
+               gst_object_unref(pad);
+       if (qt_pad)
+               gst_object_unref(qt_pad);
+       if (fake_pad)
+               gst_object_unref(fake_pad);
+       MEDIADEMUXER_FLEAVE();
+       return;
+}
+
+static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       GstBus *bus = NULL;
+
+       /* 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("Demuxer Gst pipeline");
+       if (!gst_handle->pipeline) {
+               MD_E("pipeline create fail");
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+
+       /* Create the elements */
+       gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
+       if (!gst_handle->filesrc) {
+               MD_E("filesrc creation failed");
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+
+       /* Modify the source's properties */
+       g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
+       gst_handle->typefind = gst_element_factory_make("typefind", NULL);
+       if (!gst_handle->typefind) {
+               MD_E("typefind creation failed");
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+       g_signal_connect(gst_handle->typefind, "have-type",
+                        G_CALLBACK(__gst_cb_typefind), gst_handle);
+       gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
+       if (!gst_handle->fakesink) {
+               MD_E("fakesink creation failed");
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+
+       /* Build the pipeline */
+       gst_bin_add_many(GST_BIN(gst_handle->pipeline),
+                                                            gst_handle->filesrc,
+                                                            gst_handle->typefind,
+                                                            gst_handle->fakesink,
+                                                            NULL);
+       gst_element_link_many(gst_handle->filesrc,
+                                                     gst_handle->typefind,
+                                                     gst_handle->fakesink,
+                                                     NULL);
+
+       /* connect signals, bus watcher */
+       bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
+       gst_handle->bus_whatch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
+       gst_object_unref(bus);
+
+       /* set pipeline state to PAUSED */
+       MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
+
+       int count = 0;
+       while (gst_handle->is_prepared != true) {
+               count++;
+               usleep(POLLING_INTERVAL);
+               MD_I("Inside while loop\n");
+               if (count > POLLING_INTERVAL) {
+                       MD_E("Error occure\n");
+                       ret = MD_ERROR;
+               }
+       }
+
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
+
+       MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
+       ret = _gst_create_pipeline(new_mediademuxer, uri);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
+
+       *count = (new_mediademuxer->info).num_video_track +
+                (new_mediademuxer->info).num_audio_track +
+                (new_mediademuxer->info).num_subtitle_track +
+                (new_mediademuxer->info).num_other_track;
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+int _gst_set_appsink(track *temp, int index, int loop)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       int count = 0;
+       if (index >= loop && index < 0)
+               goto ERROR;
+       while (count != index) {
+               temp = temp->next;
+               count++;
+       }
+       gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
+       gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
+
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+static int gst_demuxer_set_track(MMHandleType pHandle, int track)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_INVALID_ARG;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
+
+       if (track >= new_mediademuxer->total_tracks || track < 0) {
+               goto ERROR;
+       }
+       new_mediademuxer->selected_tracks[track] = true;
+       _gst_set_appsink((((mdgst_handle_t *) pHandle)->info).head, track,
+                        new_mediademuxer->total_tracks);
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_start(MMHandleType pHandle)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
+
+       int indx;
+       for (indx = 0; indx < gst_handle->total_tracks; indx++) {
+               MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
+                    indx, gst_handle->selected_tracks[indx]);
+               /*
+               if (gst_handle->selected_tracks[indx] ==  false)
+                       _gst_demuxer_unset(pHandle, indx);
+               */
+       }
+
+       track_info *head_track = &(gst_handle->info);
+       MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
+            head_track->num_audio_track, head_track->num_video_track,
+            head_track->num_subtitle_track);
+
+       track *temp = head_track->head;
+       indx = 0;
+       while (temp) {
+               MD_I("Got one element %p\n", temp->appsink);
+               if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
+                   GST_STATE_CHANGE_FAILURE) {
+                       MD_E("Failed to set into PLAYING state");
+                       ret = MD_ERROR_UNKNOWN;
+               }
+               MD_I("set the state to playing\n");
+               indx++;
+               if (temp->next) {
+                       track *next = temp->next;
+                       temp = next;
+               } else {
+                       temp = NULL;
+               }
+       }
+
+       MD_I("gst_demuxer_start pipeine %p", gst_handle);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+int _set_mime_video(media_format_h format, track *head)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       GstStructure *struc = NULL;
+       int src_width;
+       int src_height;
+       struc = gst_caps_get_structure(head->caps, 0);
+       if (!struc) {
+               MD_E("cannot get structure from caps.\n");
+               goto ERROR;
+       }
+       if (gst_structure_has_name(struc, "video/x-h264")) {
+               const gchar *version =
+                   gst_structure_get_string(struc, "stream-format");
+               if (strncmp(version, "avc", 3) == 0) {
+                       gst_structure_get_int(struc, "width", &src_width);
+                       gst_structure_get_int(struc, "height", &src_height);
+                       if (media_format_set_video_mime(format, MEDIA_FORMAT_H264_SP))
+                               goto ERROR;
+                       if (media_format_set_video_width(format, src_width))
+                               goto ERROR;
+                       if (media_format_set_video_height(format, src_height))
+                               goto ERROR;
+               }
+       } else {
+               MD_I("Video mime not supported so far\n");
+               goto ERROR;
+       }
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+int _set_mime_audio(media_format_h format, track *head)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       GstStructure *struc = NULL;
+       int rate = 0;
+       int channels = 0;
+       int id3_flag = 0;
+       struc = gst_caps_get_structure(head->caps, 0);
+       if (!struc) {
+               MD_E("cannot get structure from caps.\n");
+               goto ERROR;
+       }
+
+       if (gst_structure_has_name(struc, "application/x-id3")) {
+               id3_flag = 1;
+       }
+       if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
+               gint mpegversion;
+               int layer;
+               gst_structure_get_int(struc, "mpegversion", &mpegversion);
+               if (mpegversion == 4 || mpegversion == 2 ) {
+                       gst_structure_get_int(struc, "channels", &channels);
+                       gst_structure_get_int(struc, "rate", &rate);
+                       if (media_format_set_audio_mime(format, MEDIA_FORMAT_AAC_LC))
+                               goto ERROR;
+                       if(channels == 0)
+                               channels = 2; /* default */
+                       if (media_format_set_audio_channel(format, channels))
+                               goto ERROR;
+                       if(rate == 0)
+                               rate = 44100; /* default */
+                       if (media_format_set_audio_samplerate(format, rate))
+                               goto ERROR;
+                       if (media_format_set_audio_bit(format, 0))
+                               goto ERROR;
+               }
+               if (mpegversion == 1 || id3_flag ) {
+                       gst_structure_get_int(struc, "layer", &layer);
+                       if((layer == 3) || (id3_flag == 1)) {
+                               gst_structure_get_int(struc, "channels", &channels);
+                               gst_structure_get_int(struc, "rate", &rate);
+                               if (media_format_set_audio_mime(format, MEDIA_FORMAT_MP3))
+                                       goto ERROR;
+                               if(channels == 0)
+                                       channels = 2; /* default */
+                               if (media_format_set_audio_channel(format, channels))
+                                       goto ERROR;
+                               if(rate == 0)
+                                       rate = 44100; /* default */
+                               if (media_format_set_audio_samplerate(format, rate))
+                                       goto ERROR;
+                               if (media_format_set_audio_bit(format, 0))
+                                       goto ERROR;
+                       }
+                       else {
+                               MD_I("No Support for MPEG%d Layer %d media\n",mpegversion,layer);
+                               goto ERROR;
+                       }
+               }
+       }else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
+               gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
+               media_format_mimetype_e mime_type;
+               gst_structure_get_int(struc, "channels", &channels);
+               gst_structure_get_int(struc, "rate", &rate);
+               if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
+                       mime_type= MEDIA_FORMAT_AMR_NB;
+                       rate = 8000;
+               }
+               else {
+                       mime_type = MEDIA_FORMAT_AMR_WB;
+                       rate = 16000;
+               }
+               if (media_format_set_audio_mime(format,mime_type))
+                       goto ERROR;
+               if(channels == 0)
+                       channels = 1; /* default */
+               if (media_format_set_audio_channel(format, channels))
+                       goto ERROR;
+               if (media_format_set_audio_samplerate(format, rate))
+                       goto ERROR;
+               if (media_format_set_audio_bit(format, 0))
+                       goto ERROR;
+       }
+       else {
+               MD_I("Audio mime not supported so far\n");
+               goto ERROR;
+       }
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+static int gst_demuxer_get_track_info(MMHandleType pHandle,
+                                      media_format_h *format, int index)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
+
+       track *temp = NULL;
+       int loop;
+       int count = 0;
+       temp = (new_mediademuxer->info).head;
+       loop = (new_mediademuxer->info).num_video_track +
+              (new_mediademuxer->info).num_audio_track +
+              (new_mediademuxer->info).num_subtitle_track +
+              (new_mediademuxer->info).num_other_track;
+       if (index >= loop && index < 0)
+               goto ERROR;
+
+       ret = media_format_create(format);
+       if(ret != MEDIA_FORMAT_ERROR_NONE){
+               MD_E("Mediaformat creation failed. returned %d\n",ret);
+               ret = MD_INTERNAL_ERROR;
+               goto ERROR;
+       }
+       while (count != index) {
+               temp = temp->next;
+               count++;
+       }
+
+       MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
+       MD_I("format ptr[%p]\n", *format);
+       if (temp->name[0] == 'a') {
+               MD_I("Setting for Audio \n");
+               _set_mime_audio(*format, temp);
+       } else if (temp->name[0] == 'v') {
+               MD_I("Setting for Video \n");
+               _set_mime_video(*format, temp);
+       } else {
+               MD_I("Not supported so far (except audio and video)\n");
+       }
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
+                                         GstBuffer *buffer)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(out_pkt);
+       void *pkt_data;
+       uint64_t size;
+       GstMapInfo map;
+
+       if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
+               MD_E("gst_buffer_map failed\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       /* copy data*/
+       media_packet_get_buffer_size(out_pkt, &size);
+       MD_I("Media packet Buffer capacity: %llu GST Buffer size = %d\n", size, map.size);
+       if (size < (uint64_t)map.size) {
+               MD_W("Media packet Buffer capacity[%llu] is \
+                       less than the GST Buffer size[%d]. Resizing...\n", size, map.size);
+               ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
+               media_packet_get_buffer_size(out_pkt, &size);
+               MD_I("Media packet Buffer NEW  capacity: %llu \n", size);
+       }
+       if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
+               MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       memcpy((char *)pkt_data, map.data, map.size);
+       if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
+               MD_E("unable to set the pts\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
+               MD_E("unable to set the dts\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
+               MD_E("unable to set the duration\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       if (media_packet_set_buffer_size(out_pkt,  gst_buffer_get_size(buffer))) {
+               MD_E("unable to set the buffer size\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+       if (media_packet_set_flags(out_pkt,  GST_BUFFER_FLAGS(buffer))) {
+               MD_E("unable to set the buffer size\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+ERROR:
+       gst_buffer_unmap(buffer, &map);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_read_sample(MMHandleType pHandle,
+                                   media_packet_h *outbuf, int track_indx)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *demuxer = (mdgst_handle_t *) pHandle;
+
+       media_packet_h mediabuf = NULL;
+       media_format_h mediafmt = NULL;
+       int indx = 0;
+       track *atrack = demuxer->info.head;
+       if ((demuxer->selected_tracks)[track_indx] == false) {
+               MD_E("Track Not selected\n");
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+       while (atrack) {
+               if (indx == track_indx)  /*Got the requird track details*/
+                       break;
+               if (atrack->next) {
+                       track *next = atrack->next;
+                       atrack = next;
+               } else {
+                       MD_E("Invalid track Index\n");
+                       ret = MD_ERROR_INVALID_ARGUMENT;
+                       goto ERROR;
+               }
+               indx++;
+       }
+       if (atrack->name[0] == 'a') {
+               if (media_format_create(&mediafmt)) {
+                       MD_E("media_format_create failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+               if (media_format_set_audio_mime(mediafmt, MEDIA_FORMAT_AAC)) {
+                       MD_E("media_format_set_audio_mime failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+               if (media_packet_create_alloc(mediafmt, NULL, NULL, &mediabuf)) {
+                       MD_E("media_packet_create_alloc failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+       }
+       else if (atrack->name[0] == 'v'){
+                if (media_format_create(&mediafmt)) {
+                       MD_E("media_format_create failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+               if (media_format_set_video_mime(mediafmt, MEDIA_FORMAT_H264_SP)) {
+                       MD_E("media_format_set_ivideo_mime failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+               if (media_format_set_video_width(mediafmt, 760)) {
+                       MD_E("media_format_set_video_width failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+               if (media_format_set_video_height(mediafmt, 480)) {
+                       MD_E("media_format_set_video_height failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+
+               if (media_packet_create_alloc(mediafmt, NULL, NULL, &mediabuf)) {
+                       MD_E("media_packet_create_alloc failed\n");
+                       ret = MD_ERROR;
+                       goto ERROR;
+               }
+       }
+       else {
+               MD_E("Invalid track format\n");
+               goto ERROR;
+       }
+       if (indx != track_indx) {
+               MD_E("Invalid track Index\n");
+               ret = MD_ERROR_INVALID_ARGUMENT;
+               goto ERROR;
+       }
+       GstElement *sink = atrack->appsink;
+       GstSample *sample = NULL;
+       if (gst_app_sink_is_eos((GstAppSink *) sink)) {
+               MD_W("End of stream reached\n");
+               ret = MD_EOS;
+               goto ERROR;
+       }
+
+       sample = gst_app_sink_pull_sample((GstAppSink *) sink);
+       if (sample == NULL) {
+               MD_E("gst_demuxer_read_sample failed\n");
+               ret = MD_ERROR_UNKNOWN;
+       }
+
+       GstBuffer *buffer = gst_sample_get_buffer(sample);
+       if (buffer == NULL) {
+               MD_E("gst_sample_get_buffer returned NULL pointer\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+
+       /* Fill the media_packet with proper information */
+       ret = _gst_copy_buf_to_media_packet(mediabuf, buffer);
+       gst_sample_unref(sample);
+       *outbuf = mediabuf;
+
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
+{
+       MEDIADEMUXER_FENTER();
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
+
+       gint64 pos, len;
+       gdouble rate = 1;
+       if (gst_element_query_position(gst_handle->pipeline, GST_FORMAT_TIME, &pos) &&
+            gst_element_query_duration(gst_handle->pipeline, GST_FORMAT_TIME, &len)) {
+               MD_I("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
+                    GST_TIME_ARGS(pos),
+                    GST_TIME_ARGS(len));
+       }
+       pos1 = pos + (pos1 * GST_SECOND);
+
+       MD_I("\n\n");
+       MD_I("NEW Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
+            GST_TIME_ARGS(pos1), GST_TIME_ARGS(len));
+
+       track_info *head_track = &(gst_handle->info);
+       track *temp = head_track->head;
+       int indx = 0;
+       while (temp) {
+               MD_I("Got one element %p\n", temp->appsink);
+               if (gst_handle->selected_tracks[indx] == true) {
+                       if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
+                            GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, pos1,
+                            GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
+                               g_print("Seek failed!\n");
+                       } else {
+                               MD_I("Seek success\n");
+                       }
+               }
+               indx++;
+               if (temp->next) {
+                       track *next = temp->next;
+                       temp = next;
+               } else {
+                       temp = NULL;
+               }
+       }
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+int _gst_unset_appsink(track *temp, int index, int loop)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       int count = 0;
+       if (index >= loop && index < 0)
+               goto ERROR;
+       while (count != index) {
+               temp = temp->next;
+               count++;
+       }
+       gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) 0);
+       gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_INVALID_ARG;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
+
+       if (track >= new_mediademuxer->total_tracks || track < 0) {
+               goto ERROR;
+       }
+       new_mediademuxer->selected_tracks[track] = false;
+       _gst_unset_appsink((((mdgst_handle_t *) pHandle)->info).head, track,
+                          new_mediademuxer->total_tracks);
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_stop(MMHandleType pHandle)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
+
+       MD_I("gst_demuxer_stop pipeine %p", gst_handle);
+       if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
+           GST_STATE_CHANGE_FAILURE) {
+               MD_E("Failed to set into PAUSE state");
+               ret = MD_ERROR_UNKNOWN;
+       }
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+void  _gst_clear_struct(mdgst_handle_t *gst_handle)
+{
+       MEDIADEMUXER_FENTER();
+       if (gst_handle->selected_tracks) {
+               MD_I("Deallocating gst_handle->selected_tracks %p\n",
+                    gst_handle->selected_tracks);
+               g_free(gst_handle->selected_tracks);
+               gst_handle->selected_tracks = NULL;
+       }
+       if ((gst_handle->info).head) {
+               __gst_free_stuct(&(gst_handle->info).head);
+       }
+       MEDIADEMUXER_FLEAVE();
+}
+
+int _md_gst_destroy_pipeline(GstElement *pipeline)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       if (pipeline)
+               MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       if (pipeline)
+               gst_object_unref(GST_OBJECT(pipeline));
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR;
+}
+
+static int gst_demuxer_unprepare(MMHandleType pHandle)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
+
+       _gst_clear_struct(gst_handle);
+       MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
+       if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+static int gst_demuxer_destroy(MMHandleType pHandle)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
+
+       MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
+            new_mediademuxer);
+       g_free(new_mediademuxer);
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
+int gst_set_error_cb(MMHandleType pHandle,
+                       gst_error_cb callback, void *user_data)
+{
+       MEDIADEMUXER_FENTER();
+       int ret = MD_ERROR_NONE;
+       MEDIADEMUXER_CHECK_NULL(pHandle);
+       mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
+
+       if (!gst_handle) {
+               MD_E("fail invaild param\n");
+               ret = MD_INVALID_ARG;
+               goto ERROR;
+       }
+
+       if(gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
+               MD_E("Already set mediademuxer_error_cb\n");
+               ret = MD_ERROR_INVALID_ARGUMENT;
+               goto ERROR;
+       }
+       else {
+               if (!callback) {
+                       ret = MD_ERROR_INVALID_ARGUMENT;
+                       goto ERROR;
+               }
+       }
+
+       MD_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;
+       MEDIADEMUXER_FLEAVE();
+       return MD_ERROR_NONE;
+ERROR:
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d5feaa9
--- /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-mediademuxer ${${fw_test}_LDFLAGS})
+ENDFOREACH()
+
diff --git a/test/mediademuxer_test.c b/test/mediademuxer_test.c
new file mode 100755 (executable)
index 0000000..963f369
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ * 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 <glib.h>
+#include <mm_error.h>
+#include <mm_debug.h>
+#include <mediademuxer_error.h>
+#include <mediademuxer.h>
+#include <media_format.h>
+#include <media_packet.h>
+
+/*-----------------------------------------------------------------------
+|    GLOBAL VARIABLE DEFINITIONS:                                       |
+-----------------------------------------------------------------------*/
+#define MAX_STRING_LEN 100
+#define PACKAGE "mediademuxer_test"
+
+/*-----------------------------------------------------------------------
+|    GLOBAL CONSTANT DEFINITIONS:                                       |
+-----------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+|    IMPORTED VARIABLE DECLARATIONS:                                    |
+-----------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+|    IMPORTED FUNCTION DECLARATIONS:                                    |
+-----------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+|    LOCAL #defines:                                                                   |
+-----------------------------------------------------------------------*/
+/*
+ * D E B U G   M E S S A G E
+ */
+#define MMF_DEBUG                       "** (demuxer testsuite) DEBUG: "
+#define MMF_ERR                         "** (demuxer testsuite) ERROR: "
+#define MMF_INFO                        "** (demuxer testsuite) INFO: "
+#define MMF_WARN                        "** (demuxer testsuite) WARNING: "
+
+#define CHECK_MM_ERROR(expr) \
+       do {\
+               int ret = 0; \
+               ret = expr; \
+               if (ret != MD_ERROR_NONE) {\
+                       printf("[%s:%d] error code : %x \n", __func__, __LINE__, ret); \
+                       return; \
+               }\
+       } while(0)
+
+#define debug_msg_t(fmt,arg...)\
+       do { \
+               fprintf(stderr, MMF_DEBUG"[%s:%05d]  " fmt "\n",__func__, __LINE__, ##arg); \
+       } while(0)
+
+#define err_msg_t(fmt,arg...)\
+       do { \
+               fprintf(stderr, MMF_ERR"[%s:%05d]  " fmt "\n",__func__, __LINE__, ##arg); \
+       } while(0)
+
+#define info_msg_t(fmt,arg...)\
+       do { \
+               fprintf(stderr, MMF_INFO"[%s:%05d]  " fmt "\n",__func__, __LINE__, ##arg); \
+       } while(0)
+
+#define warn_msg_t(fmt,arg...)\
+       do { \
+               fprintf(stderr, MMF_WARN"[%s:%05d]  " fmt "\n",__func__, __LINE__, ##arg); \
+       } while(0)
+
+/*-----------------------------------------------------------------------
+|    LOCAL CONSTANT DEFINITIONS:                                        |
+-----------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+|    LOCAL DATA TYPE DEFINITIONS:                                       |
+-----------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+|    LOCAL VARIABLE DEFINITIONS:                                        |
+-----------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------
+|    LOCAL FUNCTION PROTOTYPES:                                        |
+-----------------------------------------------------------------------*/
+#if 0
+int test_mediademuxer_create();
+int test_mediademuxer_destroy();
+int test_mediademuxer_prepare();
+int test_mediademuxer_unprepare();
+int test_mediademuxer_set_data_source();
+int test_mediademuxer_get_track_count();
+int test_mediademuxer_get_track_info();
+int test_mediademuxer_select_track();
+int test_mediademuxer_unselect_track();
+int test_mediademuxer_seek_to();
+int test_mediademuxer_read_sample();
+int test_mediademuxer_get_sample_track_index();
+int test_mediademuxer_get_sample_track_time();
+int test_mediademuxer_advance();
+int test_mediademuxer_is_key_frame();
+int test_mediademuxer_is_encrypted();
+int test_mediademuxe_audio_only();
+int test_mediademuxe_video_only();
+int test_mediademuxe_audio_video_only();
+#endif
+int aud_track=-1;
+int vid_track=-1;
+mediademuxer_h demuxer = NULL;
+int num_tracks = 0;
+media_format_h *g_media_format = NULL;
+
+int test_mediademuxer_get_track_info()
+{
+       int ret = 0;
+       int track = 0;
+       int w;
+       int h;
+       int channel;
+       int samplerate;
+       media_format_mimetype_e mime;
+       g_print("test_mediademuxer_get_track_info\n");
+       g_media_format =
+           (media_format_h *) g_malloc(sizeof(media_format_h) * num_tracks);
+       g_print("allocated %p memory for g_media_format\n", g_media_format);
+       if (g_media_format) {
+               for (; track < num_tracks; track++) {
+                       if (ret == 0) {
+                               g_print
+                               ("g_media_format[%d] is created successfully! \n",
+                                track);
+                               ret =
+                                   mediademuxer_get_track_info(demuxer, track,
+                                                               &g_media_format[track]);
+                               if (ret == 0) {
+                                       if (media_format_get_video_info
+                                           (g_media_format[track], &mime, &w,
+                                            &h, NULL,
+                                            NULL) == MEDIA_FORMAT_ERROR_NONE) {
+                                               g_print
+                                               ("media_format_get_video_info is sucess!\n");
+                                               g_print
+                                               ("\t\t[media_format_get_video]mime:%x, width :%d, height :%d\n",
+                                                mime, w, h);
+                                               vid_track = track;
+                                       } else if (media_format_get_audio_info
+                                                  (g_media_format[track], &mime,
+                                                   &channel, &samplerate, NULL,
+                                                   NULL) ==
+                                                  MEDIA_FORMAT_ERROR_NONE) {
+                                               g_print
+                                               ("media_format_get_audio_info is sucess!\n");
+                                               g_print
+                                               ("\t\t[media_format_get_audio]mime:%x, channel :%d, samplerate :%d\n",
+                                                mime, channel, samplerate);
+                                               aud_track = track;
+                                       } else {
+                                               g_print("Not Supported YET");
+                                       }
+                               } else {
+                                       g_print
+                                       ("Error while getting mediademuxer_get_track_info\n");
+                               }
+                               media_format_unref(g_media_format[track]);
+                               g_media_format[track] = NULL;
+                       } else {
+                               g_print
+                               ("Error while creating media_format_create\n");
+                       }
+               }
+               g_free(g_media_format);
+               g_media_format = NULL;
+       } else {
+               g_print("Error while allocating memory\n");
+       }
+
+       return ret;
+}
+
+int test_mediademuxer_create()
+{
+       int ret = 0;
+       g_print("test_mediademuxer_create\n");
+       ret = mediademuxer_create(&demuxer);
+       return ret;
+}
+
+int test_mediademuxer_destroy()
+{
+       int ret = 0;
+       g_print("test_mediademuxer_destroy\n");
+       ret = mediademuxer_destroy(demuxer);
+       demuxer = NULL;
+       return ret;
+}
+
+int test_mediademuxer_prepare()
+{
+       int ret = 0;
+       g_print("test_mediademuxer_prepare\n");
+       ret = mediademuxer_prepare(demuxer);
+       return ret;
+}
+
+int test_mediademuxer_start()
+{
+       int ret = 0;
+       g_print("test_mediademuxer_start\n");
+       ret = mediademuxer_start(demuxer);
+       return ret;
+}
+
+int test_mediademuxer_get_state()
+{
+       g_print("test_mediademuxer_get_state\n");
+       mediademuxer_state state;
+       if(mediademuxer_get_state(demuxer, &state) == MEDIADEMUXER_ERROR_NONE) {
+               g_print("\nMediademuxer_state=%d",state);
+       }
+       else {
+               g_print("\nMediademuxer_state call failed\n");
+       }
+       return 0;
+}
+
+int test_mediademuxer_stop()
+{
+       int ret = 0;
+       g_print("test_mediademuxer_stop\n");
+       ret = mediademuxer_stop(demuxer);
+       return ret;
+}
+
+int test_mediademuxer_unprepare()
+{
+       int ret = 0;
+       g_print("test_mediademuxer_unprepare\n");
+       ret = mediademuxer_unprepare(demuxer);
+       return ret;
+}
+
+int test_mediademuxer_set_data_source(mediademuxer_h demuxer, const char *path)
+{
+       int ret = 0;
+       g_print("test_mediademuxer_set_data_source\n");
+       ret = mediademuxer_set_data_source(demuxer, path);
+       return ret;
+}
+
+int test_mediademuxer_get_track_count()
+{
+       g_print("test_mediademuxer_get_track_count\n");
+       mediademuxer_get_track_count(demuxer, &num_tracks);
+       g_print("Number of tracks [%d]", num_tracks);
+       return 0;
+}
+
+int test_mediademuxer_select_track()
+{
+       g_print("test_mediademuxer_select_track\n");
+       if (mediademuxer_select_track(demuxer, 0)) {
+               g_print("mediademuxer_select track 0 failed\n");
+               return -1;
+       }
+       if (mediademuxer_select_track(demuxer, 1)) {
+               g_print("mediademuxer_select track 1 failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int test_mediademuxer_unselect_track()
+{
+       g_print("test_mediademuxer_select_track\n");
+       if (mediademuxer_unselect_track(demuxer, 0)) {
+               g_print("mediademuxer_select track 0 failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int test_mediademuxer_seek_to()
+{
+       g_print("test_mediademuxer_seek_to\n");
+       int64_t pos = 1;
+       mediademuxer_seek(demuxer, pos);
+       g_print("Number of tracks [%d]", num_tracks);
+       return 0;
+}
+
+void app_err_cb(mediademuxer_error_e error, void *user_data)
+{
+       printf("Got Error %d from Mediademuxer\n",error);
+}
+
+int test_mediademuxer_set_error_cb()
+{
+       int ret = 0;
+       g_print("test_mediademuxer_set_error_cb\n");
+       ret = mediademuxer_set_error_cb(demuxer,app_err_cb,demuxer);
+       return ret;
+}
+
+void *_fetch_audio_data(void *ptr)
+{
+       int *status = (int *)g_malloc(sizeof(int) * 1);
+       *status = -1;
+       g_print("Audio Data function\n");
+       media_packet_h audbuf;
+       int count = 0;
+
+       while (1) {
+               int EOS = mediademuxer_read_sample(demuxer, aud_track, &audbuf);
+               if (EOS == MD_EOS || EOS != MD_ERROR_NONE)
+                       pthread_exit(NULL);
+               count++;
+               g_print("Read::[%d] audio sample\n", count);
+               media_packet_destroy(audbuf);
+       }
+
+       *status = 0;
+
+       return (void *)status;
+}
+
+void *_fetch_video_data(void *ptr)
+{
+       int *status = (int *)g_malloc(sizeof(int) * 1);
+       media_packet_h vidbuf;
+       *status = -1;
+       g_print("Video Data function\n");
+       int count = 0;
+       while (1) {
+               int EOS = mediademuxer_read_sample(demuxer, vid_track, &vidbuf);
+               if (EOS == MD_EOS || EOS != MD_ERROR_NONE)
+                       pthread_exit(NULL);
+               count++;
+               g_print("Read::[%d] video sample\n", count);
+               media_packet_destroy(vidbuf);
+       }
+       *status = 0;
+       return (void *)status;
+}
+
+int test_mediademuxer_read_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);
+       if(vid_track != -1){
+               g_print("In main: creating thread  for video\n");
+               pthread_create(&thread[0], &attr, _fetch_video_data, NULL);
+       }
+       if(aud_track != -1){
+               g_print("In main: creating thread  for audio\n");
+               pthread_create(&thread[1], &attr, _fetch_audio_data, NULL);
+       }
+       pthread_attr_destroy(&attr);
+       return 0;
+}
+
+int test_mediademuxer_get_sample_track_index()
+{
+       g_print("test_mediademuxer_get_sample_track_index\n");
+       return 0;
+}
+
+int test_mediademuxer_get_sample_track_time()
+{
+       g_print("test_mediademuxer_get_sample_track_time\n");
+       return 0;
+}
+
+int test_mediademuxer_advance()
+{
+       g_print("test_mediademuxer_advance\n");
+       return 0;
+}
+
+int test_mediademuxer_is_key_frame()
+{
+       g_print("test_mediademuxer_is_key_frame\n");
+       return 0;
+}
+
+int test_mediademuxer_is_encrypted()
+{
+       g_print("test_mediademuxer_is_encrypted\n");
+       return 0;
+}
+
+int test_mediademuxer_audio_only()
+{
+       g_print("AUDIO ONLY\n");
+       return 0;
+}
+
+int test_mediademuxer_video_only()
+{
+       g_print("VIDEO ONLY\n");
+       return 0;
+}
+
+int test_mediademuxer_audio_video_only()
+{
+       g_print("AUDIO & VIDEO ONLY\n");
+       return 0;
+}
+
+enum {
+       CURRENT_STATUS_MAINMENU,
+       CURRENT_STATUS_FILENAME,
+       CURRENT_STATUS_SET_DATA
+};
+
+int g_menu_state = CURRENT_STATUS_MAINMENU;
+
+static void display_sub_basic();
+
+void reset_menu_state()
+{
+       g_menu_state = CURRENT_STATUS_MAINMENU;
+       return;
+}
+
+void _interpret_main_menu(char *cmd)
+{
+       int len = strlen(cmd);
+       if (len == 1) {
+               if (strncmp(cmd, "a", 1) == 0) {
+                       test_mediademuxer_create();
+               } else if (strncmp(cmd, "d", 1) == 0) {
+                       test_mediademuxer_unprepare();
+                       test_mediademuxer_destroy();
+               } else if (strncmp(cmd, "s", 1) == 0) {
+                       g_menu_state = CURRENT_STATUS_FILENAME;
+               } else if (strncmp(cmd, "q", 1) == 0) {
+                       exit(0);
+               } else if (strncmp(cmd, "c", 1) == 0) {
+                       test_mediademuxer_set_error_cb();
+               } else {
+                       g_print("unknown menu \n");
+               }
+       }
+
+       return;
+}
+
+static void displaymenu(void)
+{
+       if (g_menu_state == CURRENT_STATUS_MAINMENU) {
+               display_sub_basic();
+       } else if (g_menu_state == CURRENT_STATUS_FILENAME) {
+               g_print("*** input mediapath.\n");
+       } else if (g_menu_state == CURRENT_STATUS_SET_DATA) {
+               g_print("\n");
+               g_print
+               ("=========================================================================================\n");
+               g_print
+               ("                                    media demuxer submenu\n");
+               g_print
+               ("-----------------------------------------------------------------------------------------\n");
+               g_print("1.Get Track\t");
+               g_print("2.Get Info\t");
+               g_print("3.Select Track\t");
+               g_print("4.Uselect Track\n");
+               g_print("5.Seek\t");
+               g_print("6.Read Sample\t");
+               g_print("7.Get Sample Track Index\t");
+               g_print("8.Get Sample Track Time\n");
+               g_print("9.Advance\t");
+               g_print("10.Is Key Frame\t");
+               g_print("11.Is Key encrypted\t");
+               g_print("a. start\n");
+               g_print("b. stop\n");
+               g_print("u. unprepare\n");
+               g_print("s. get state\n");
+               g_print("12.Go Back to main menu\n");
+               g_print
+               ("-----------------------------------------------------------------------------------------\n");
+       } 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_FILENAME: {
+                               int ret = 0;
+                               ret = test_mediademuxer_set_data_source(demuxer, cmd);
+                               if (ret != MD_ERROR_INVALID_ARGUMENT) {
+                                       ret = test_mediademuxer_prepare();
+                                       if (ret != MD_ERROR_INVALID_ARGUMENT) {
+                                               g_menu_state = CURRENT_STATUS_SET_DATA;
+                                       } else {
+                                               g_print
+                                               ("test_mediademuxer_prepare failed \n");
+                                               g_menu_state = CURRENT_STATUS_FILENAME;
+                                       }
+                               } else {
+                                       g_menu_state = CURRENT_STATUS_FILENAME;
+                               }
+                               break;
+                       }
+               case CURRENT_STATUS_SET_DATA: {
+                               int len = strlen(cmd);
+
+                               if (len == 1) {
+                                       if (strncmp(cmd, "1", len) == 0) {
+                                               test_mediademuxer_get_track_count();
+                                       } else if (strncmp(cmd, "2", len) == 0) {
+                                               test_mediademuxer_get_track_info();
+                                       } else if (strncmp(cmd, "3", len) == 0) {
+                                               test_mediademuxer_select_track();
+                                       } else if (strncmp(cmd, "4", len) == 0) {
+                                               test_mediademuxer_unselect_track();
+                                       } else if (strncmp(cmd, "5", len) == 0) {
+                                               test_mediademuxer_seek_to();
+                                       } else if (strncmp(cmd, "6", len) == 0) {
+                                               test_mediademuxer_read_sample();
+                                       } else if (strncmp(cmd, "7", len) == 0) {
+                                               test_mediademuxer_get_sample_track_index
+                                               ();
+                                       } else if (strncmp(cmd, "8", len) == 0) {
+                                               test_mediademuxer_get_sample_track_time
+                                               ();
+                                       } else if (strncmp(cmd, "9", len) == 0) {
+                                               test_mediademuxer_advance();
+                                       } else if (strncmp(cmd, "a", len) == 0) {
+                                               test_mediademuxer_start();
+                                       } else if (strncmp(cmd, "b", len) == 0) {
+                                               test_mediademuxer_stop();
+                                       } else if (strncmp(cmd, "u", len) == 0) {
+                                               test_mediademuxer_unprepare();
+                                       } else if (strncmp(cmd, "s", len) == 0) {
+                                               test_mediademuxer_get_state();
+                                       }
+                               } else if (len == 2) {
+                                       if (strncmp(cmd, "10", len) == 0) {
+                                               test_mediademuxer_is_key_frame();
+                                       } else if (strncmp(cmd, "11", len) == 0) {
+                                               test_mediademuxer_is_encrypted();
+                                       } else if (strncmp(cmd, "12", len) == 0) {
+                                               reset_menu_state();
+                                       } else {
+                                               g_print("UNKNOW COMMAND\n");
+                                       }
+                               } else {
+                                       g_print("UNKNOW COMMAND\n");
+                               }
+                               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 demuxer test\n");
+       g_print
+       ("-----------------------------------------------------------------------------------------\n");
+       g_print("a. Create \t");
+       g_print("c. Set error_call_back\t");
+       g_print("s. Setdata \t\t");
+       g_print("d. Destroy \t\t");
+       g_print("q. exit \t\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 mediademuxer 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;
+}