--- /dev/null
+Satheesan E N <satheesan.en@samsung.com>\r
+Joungkook Seo <jk7704.seo@samsung.com>\r
--- /dev/null
+
+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)
+
--- /dev/null
+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
--- /dev/null
+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.
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__*/
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+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
+
+
--- /dev/null
+message(In src folder...)
+add_subdirectory(port_gst)
+add_subdirectory(port_ffmpeg)
+add_subdirectory(port_custom)
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+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()
+
--- /dev/null
+/*
+ * 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;
+}