--- /dev/null
+Eunhae Choi <eunhae1.chohi@samsung.com>
+Oleg Kopysov <o.kopysov@samsung.com>
+Andrey Shelest <a.shelest@samsung.com>
+Vyacheslav Valkovoy <v.valkovoy@samsung.com>
--- /dev/null
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(fw_name "capi-media-streamer")
+
+PROJECT(${fw_name})
+
+SET(CMAKE_INSTALL_PREFIX /usr)
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+
+SET(INC_DIR include)
+INCLUDE_DIRECTORIES(${INC_DIR})
+
+SET(dependents "dlog glib-2.0 mm-common capi-media-tool iniparser bundle libtbm gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0" )
+SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0" )
+
+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} -fPIC -Wall")
+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=/usr/lib")
+
+AUX_SOURCE_DIRECTORY (src MAIN_SRC)
+
+LIST (APPEND SOURCES
+ ${MAIN_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(
+ DIRECTORY ${INC_DIR}/ DESTINATION include/media
+ FILES_MATCHING
+ PATTERN "media_streamer_*.h" EXCLUDE
+ PATTERN "${INC_DIR}/*.h"
+ )
+
+
+SET(PC_NAME ${fw_name})
+SET(PC_REQUIRED ${pc_dependents})
+SET(PC_LDFLAGS -l${fw_name})
+SET(PC_CFLAGS -I\${includedir}/media)
+
+CONFIGURE_FILE(
+ ${fw_name}.pc.in
+ ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc
+ @ONLY
+)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION lib/pkgconfig)
+
+ADD_SUBDIRECTORY(test)
+
+IF(UNIX)
+
+ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution)
+ADD_CUSTOM_COMMAND(
+ DEPENDS clean
+ COMMENT "distribution clean"
+ COMMAND find
+ ARGS .
+ -not -name config.cmake -and \(
+ -name tester.c -or
+ -name Testing -or
+ -name CMakeFiles -or
+ -name cmake.depends -or
+ -name cmake.check_depends -or
+ -name CMakeCache.txt -or
+ -name cmake.check_cache -or
+ -name *.cmake -or
+ -name Makefile -or
+ -name core -or
+ -name core.* -or
+ -name gmon.out -or
+ -name install_manifest.txt -or
+ -name *.pc -or
+ -name *~ \)
+ | grep -v TC | xargs rm -rf
+ TARGET distclean
+ VERBATIM
+)
+
+ENDIF(UNIX)
+
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
--- /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
+prefix = @prefix@
+exec_prefix=@exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+Name : mediastreamer
+Description : Multimedia Framework MediaStreamer Library
+Requires : mm-common
+Version : @VERSION@
+Libs : -L${libdir} -lmmfstreamer
+Cflags : -I${includedir}/mmf
--- /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_MEDIASTREAMER_DOC_H__
+#define __TIZEN_MEDIASTREAMER_DOC_H__
+
+/**
+ * @file mediastreamer_doc.h
+ * @brief This file contains high level documentation of the CAPI MEDIA STREAMER API.
+ */
+
+/**
+ * @ingroup CAPI_MEDIA_FRAMEWORK
+ * @defgroup CAPI_MEDIA_MEDIASTREAMER_MODULE Media Streamer
+ * @brief The @ref CAPI_MEDIA_MEDIASTREAMER_MODULE APIs provides functions for building custom pipeline
+ *
+ * @section CAPI_MEDIA_MEDIASTREAMER_MODULE_HEADER Required Header
+ * \#include <media_streamer.h>
+ *
+ * @section CAPI_MEDIASTREAMER_MODULE_OVERVIEW Overview
+ *
+ * MEDIASTREAMER allows :
+ * Create streamer handle and elements to build custom pipeline.
+ * Application can create, add and link elements manually.
+ *
+ */
+
+#endif /* __TIZEN_MEDIASTREAMER_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_MEDIASTREAMER_H__
+#define __TIZEN_MEDIASTREAMER_H__
+
+#include <tizen.h>
+#include <bundle.h>
+#include <mm_message.h>
+#include <media_format.h>
+#include <media_packet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef TIZEN_ERROR_MEDIA_STREAMER
+#define TIZEN_ERROR_MEDIA_STREAMER -0x03000000
+#endif
+
+/**
+* @file media_streamer.h
+* @brief This file contains the capi media streamer API.
+*/
+
+/**
+* @addtogroup CAPI_MEDIASTREAMER_MODULE
+* @{
+*/
+
+/**
+ * @brief Media Streamer handle type.
+ *
+ * @since_tizen 3.0
+ */
+typedef void *media_streamer_h;
+
+/**
+ * @brief Media Streamer node handle type.
+ *
+ * @since_tizen 3.0
+ */
+typedef void *media_streamer_node_h;
+
+/**
+ * @brief Media streamer time type.
+ *
+ * @since_tizen 3.0
+ */
+typedef long long media_streamer_time_value;
+
+/**
+ * @brief Enumeration for media streamer node type.
+ *
+ * @since_tizen 3.0
+ */
+typedef enum
+{
+ MEDIA_STREAMER_NODE_TYPE_NONE, /**< Not defined type */
+ MEDIA_STREAMER_NODE_TYPE_SRC, /**< Src node type */
+ MEDIA_STREAMER_NODE_TYPE_SINK, /**< Sink node type */
+ MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER, /**< Video encoder node type */
+ MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER, /**< Video decoder node type */
+ MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER, /**< Audio encoder node type */
+ MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER, /**< Audio decoder node type */
+ MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER, /**< Video converter node type */
+ MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER, /**< Audio converter node type */
+ MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE, /**< Audio resample node type */
+ MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY, /**< Rtp video payloader */
+ MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY, /**< Rtp audio payloader */
+ MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY, /**< Rtp video depayloader */
+ MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY, /**< Rtp audio depayloader */
+ MEDIA_STREAMER_NODE_TYPE_PARSER, /**< Parser node type */
+ MEDIA_STREAMER_NODE_TYPE_FILTER, /**< Filter node type, to limit formats of data */
+ MEDIA_STREAMER_NODE_TYPE_TEE, /**< Tee node type, splits data to multiple path */
+ MEDIA_STREAMER_NODE_TYPE_QUEUE, /**< Queue node type */
+ MEDIA_STREAMER_NODE_TYPE_MQUEUE, /**< Multiple data queue node type */
+ MEDIA_STREAMER_NODE_TYPE_MUXER, /**< Muxer node type */
+ MEDIA_STREAMER_NODE_TYPE_DEMUXER, /**< Demuxer node type */
+ MEDIA_STREAMER_NODE_TYPE_RTP, /**< Rtp component to send and receive data */
+ MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR, /**< N-to-1 input stream selector */
+ MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR, /**< 1-to-N output stream selector */
+ MEDIA_STREAMER_NODE_TYPE_INTERLEAVE, /**< Folds many mono channel into one interleaved audio stream */
+ MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE /**< Splits multi channel audio into many mono audio */
+} media_streamer_node_type_e;
+
+/**
+ * @brief Enumeration for media streamer source node type.
+ *
+ * @since_tizen 3.0
+ */
+typedef enum
+{
+ MEDIA_STREAMER_SRC_TYPE_NONE, /**< Not defined src type */
+ MEDIA_STREAMER_SRC_TYPE_FILE, /**< Local file src type */
+ MEDIA_STREAMER_SRC_TYPE_HTTP, /**< Http src type */
+ MEDIA_STREAMER_SRC_TYPE_RTSP, /**< Rtsp src type */
+ MEDIA_STREAMER_SRC_TYPE_CAMERA, /**< Camera src type */
+ MEDIA_STREAMER_SRC_TYPE_AUDIO_CAPTURE, /**< Audio capture src type */
+ MEDIA_STREAMER_SRC_TYPE_VIDEO_CAPTURE, /**< Video capture src type */
+ MEDIA_STREAMER_SRC_TYPE_AUDIO_TEST, /**< Audio test src type */
+ MEDIA_STREAMER_SRC_TYPE_VIDEO_TEST, /**< Video test src type */
+ MEDIA_STREAMER_SRC_TYPE_CUSTOM /**< Custom src type */
+} media_streamer_src_type_e;
+
+/**
+ * @brief Enumeration for media streamer sink node type.
+ *
+ * @since_tizen 3.0
+ */
+typedef enum
+{
+ MEDIA_STREAMER_SINK_TYPE_NONE, /**< Not defined sink type */
+ MEDIA_STREAMER_SINK_TYPE_FILE, /**< Local file sink type */
+ MEDIA_STREAMER_SINK_TYPE_RTSP, /**< Rtsp sink type */
+ MEDIA_STREAMER_SINK_TYPE_HTTP, /**< Http sink type */
+ MEDIA_STREAMER_SINK_TYPE_AUDIO, /**< Audio sink type */
+ MEDIA_STREAMER_SINK_TYPE_SCREEN, /**< Screen sink type */
+ MEDIA_STREAMER_SINK_TYPE_FAKE, /**< Fake sink type */
+ MEDIA_STREAMER_SINK_TYPE_CUSTOM /**< Custom sink type */
+} media_streamer_sink_type_e;
+
+/**
+ * @brief Enumeration for media streamer state.
+ *
+ * @since_tizen 3.0
+ */
+typedef enum
+{
+ MEDIA_STREAMER_STATE_NONE, /**< Streamer is not created */
+ MEDIA_STREAMER_STATE_IDLE, /**< Streamer is created but not prepared */
+ MEDIA_STREAMER_STATE_READY, /**< Streamer is ready to play */
+ MEDIA_STREAMER_STATE_PLAYING, /**< Streamer is playing */
+ MEDIA_STREAMER_STATE_PAUSED, /**< Streamer is paused */
+ MEDIA_STREAMER_STATE_SEEKING /**< Seek is under operation */
+} media_streamer_state_e;
+
+/**
+ * @brief Enumeration for media streamer error.
+ *
+ * @since_tizen 3.0
+ */
+typedef enum
+{
+ MEDIA_STREAMER_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+ MEDIA_STREAMER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid operation */
+ MEDIA_STREAMER_ERROR_FILE_NO_SPACE_ON_DEVICE = TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE, /**< No space left on the device */
+ MEDIA_STREAMER_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */
+ MEDIA_STREAMER_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ MEDIA_STREAMER_ERROR_INVALID_STATE = TIZEN_ERROR_MEDIA_STREAMER|0x01, /**< Invalid state */
+ MEDIA_STREAMER_ERROR_CONNECTION_FAILED = TIZEN_ERROR_MEDIA_STREAMER|0x02, /**< Connection failed */
+ MEDIA_STREAMER_ERROR_RESOURCE_CONFLICT = TIZEN_ERROR_MEDIA_STREAMER|0x03, /**< Resource conflict */
+} media_streamer_error_e;
+
+/**
+ * @brief Enumeration of media streamer buffer status of custom src
+ *
+ * @since_tizen 3.0
+ */
+typedef enum
+{
+ MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, /**< buffer underrun of custom src */
+ MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, /**< buffer overflow of custom src */
+} media_streamer_custom_buffer_status_e;
+
+/**
+ * @brief Called when error occurs in media streamer.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @param [in] error The error that occurred in media steamer
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_set_error_cb() was invoked
+ * This data will be accessible from @a media_streamer_error_cb
+ * @pre Create media streamer handle by calling media_streamer_create() function
+ * @see media_streamer_set_error_cb()
+ * @see media_streamer_unset_error_cb()
+ */
+typedef void (*media_streamer_error_cb)(media_streamer_h streamer,
+ media_streamer_error_e error,
+ void *user_data);
+
+/**
+ * @brief Called when media streamer state was changed.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @param [in] previous_state The previous state of the media steamer
+ * @param [in] current_state The current state of media streamer
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_set_state_changed_cb() was invoked
+ * This data will be accessible from @a media_streamer_state_changed_cb
+ * @pre Create media streamer handle by calling media_streamer_create() function
+ * @see media_streamer_set_state_change_cb()
+ * @see media_streamer_unset_state_change_cb()
+ */
+typedef void (*media_streamer_state_changed_cb)(media_streamer_h streamer,
+ media_streamer_state_e previous_state,
+ media_streamer_state_e current_state,
+ void *user_data);
+
+/**
+ * @brief Called when the custom source needs more data or has enough data.
+ * @details This callback will be invoked when the buffer level drops below the threshold of max size
+ * or no free space in custom source buffer.
+ * @since_tizen 3.0
+ * @remarks Callback can be applied only for MEDIA_STREAMER_SRC_TYPE_CUSTOM source type
+ * @param [in] node Media streamer source node handle
+ * @param [in] user_data The user data passed from the callback registration function
+ * @see media_streamer_src_set_buffer_status_cb()
+ * @see media_streamer_node_get_param_list()
+ * @see media_streamer_node_set_params()
+ */
+typedef void (*media_streamer_custom_buffer_status_cb) (media_streamer_node_h node,
+ media_streamer_custom_buffer_status_e status,
+ void *user_data);
+
+/**
+ * @brief Called when new data is available from custom sink.
+ * @details This callback can be applied only to MEDIA_STREAMER_SINK_TYPE_CUSTOM sink type
+ * @since_tizen 3.0
+ * @param [in] node Media streamer sink node handle
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_sink_set_data_ready_cb() was invoked
+ * This data will be accessible from @a media_streamer_sink_data_ready_cb
+ * @pre media_streamer_sink_set_data_ready_cb()
+ * @see MEDIA_STREAMER_SINK_TYPE_CUSTOM
+ * @see media_streamer_sink_set_data_ready_cb()
+ * @see media_streamer_sink_unset_data_ready_cb()
+ */
+typedef void (*media_streamer_sink_data_ready_cb)(media_streamer_node_h node,
+ void *user_data);
+
+/**
+ * @brief Called when the end-of-stream has been reached.
+ * @details This callback can be applied only to MEDIA_STREAMER_SINK_TYPE_CUSTOM sink type
+ * @since_tizen 3.0
+ * @param [in] node Media streamer sink node handle
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_sink_set_eos_cb() was invoked
+ * This data will be accessible from @a media_streamer_sink_eos_cb
+ * @pre media_streamer_sink_set_eos_cb()
+ * @see MEDIA_STREAMER_SINK_TYPE_CUSTOM
+ * @see media_streamer_sink_set_eos_cb()
+ * @see media_streamer_sink_unset_eos_cb()
+ */
+typedef void (*media_streamer_sink_eos_cb)(media_streamer_node_h node,
+ void *user_data);
+
+/**
+ * @brief Register a error callback function to be invoked when an error occurs.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @param [in] callback Callback function pointer
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_set_error_cb() was invoked
+ * This data will be accessible from @a media_streamer_error_cb
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media streamer handle by calling media_streamer_create() function
+ * @post media_streamer_error_cb() will be invoked.
+ * @see media_streamer_unset_error_cb()
+ * @see media_streamer_error_cb()
+ */
+int media_streamer_set_error_cb(media_streamer_h streamer,
+ media_streamer_error_cb callback,
+ void *user_data);
+
+/**
+ * @brief Unregisters the error callback function.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @see media_streamer_error_cb()
+ */
+int media_streamer_unset_error_cb(media_streamer_h streamer);
+
+/**
+ * @brief Register a callback that will be triggered after media streamer state was changed.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @param [in] callback Callback function pointer
+ * @param [in] user_data The user data passed from the code
+ * where media_streamer_set_state_change_cb() was invoked
+ * This data will be accessible from @a media_streamer_state_changed_cb
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media streamer handle by calling media_streamer_create() function
+ * @post media_streamer_state_changed_cb() will be invoked.
+ * @see media_streamer_unset_state_change_cb()
+ * @see media_streamer_state_change_cb()
+ */
+int media_streamer_set_state_change_cb(media_streamer_h streamer,
+ media_streamer_state_changed_cb callback,
+ void *user_data);
+
+/**
+ * @brief Unregisters the state changed callback function.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @see media_streamer_set_state_change_cb()
+ */
+int media_streamer_unset_state_change_cb(media_streamer_h streamer);
+
+/**
+ * @brief Registers a callback function to be invoked when buffer underrun or overflow is occurred.
+ * @details This function can be called only for MEDIA_STREAMER_SRC_TYPE_CUSTOM source type
+ * @since_tizen 3.0
+ * @remarks This API is used for media stream playback only.
+ * @param [in] source Media streamer source node handle
+ * @param [in] callback The buffer status callback function to register
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_src_set_buffer_status_cb() was invoked
+ * This data will be accessible from @a media_streamer_custom_buffer_status_cb()
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media streamer source node handle by calling media_streamer_src_create() function
+ * @pre Add created media streamer source node to media streamer by calling media_streamer_node_add() function
+ * @post media_streamer_custom_buffer_status_cb() will be invoked.
+ * @see media_streamer_src_unset_buffer_status_cb()
+ * @see media_streamer_custom_buffer_status_cb()
+ */
+int media_streamer_src_set_buffer_status_cb(media_streamer_node_h source,
+ media_streamer_custom_buffer_status_cb callback,
+ void *user_data);
+
+/**
+ * @brief Unregisters the src buffer status callback function.
+ * @since_tizen 3.0
+ * @param [in] source Media streamer source node handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @see media_streamer_src_set_buffer_status_cb()
+ */
+int media_streamer_src_unset_buffer_status_cb(media_streamer_node_h source);
+
+/**
+ * @brief Register a callback function to be called when the custom sink is ready for data processing.
+ * @details This function can be called only for MEDIA_STREAMER_SINK_TYPE_CUSTOM sink type
+ * @since_tizen 3.0
+ * @param [in] sink Media streamer sink handle
+ * @param [in] callback Callback function pointer
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_sink_set_data_ready_cb() was invoked
+ * This data will be accessible from @a media_streamer_sink_data_ready_cb
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media streamer sink handle by calling media_streamer_sink_create() function
+ * @pre Add created media streamer sink node to media streamer by calling media_streamer_node_add() function
+ * @post media_streamer_sink_data_ready_cb() will be invoked.
+ * @see media_streamer_sink_unset_data_ready_cb()
+ * @see media_streamer_sink_data_ready_cb()
+ */
+int media_streamer_sink_set_data_ready_cb(media_streamer_node_h sink,
+ media_streamer_sink_data_ready_cb callback,
+ void *user_data);
+
+/**
+ * @brief Unregisters the sink data ready callback function.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @see media_streamer_sink_set_data_ready_cb()
+ */
+int media_streamer_sink_unset_data_ready_cb(media_streamer_h streamer);
+
+/**
+ * @brief Registers a callback function to be called when custom sink detect the end-of-stream.
+ * @since_tizen 3.0
+ * @param [in] sink Media streamer sink node handle
+ * @param [in] callback Callback function pointer
+ * @param [in] user_data The user data passed from the code where
+ * media_streamer_sink_set_eos_cb() was invoked.
+ * This data will be accessible from @a media_streamer_sink_eos_cb
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media streamer sink handle by calling media_streamer_sink_create() function
+ * @pre Add created media streamer sink node to media streamer by calling media_streamer_node_add() function
+ * @post media_streamer_sink_eos_cb() will be invoked.
+ * @see media_streamer_sink_unset_eos_cb()
+ * @see media_streamer_sink_eos_cb()
+ */
+int media_streamer_sink_set_eos_cb(media_streamer_node_h sink,
+ media_streamer_sink_eos_cb callback,
+ void *user_data);
+
+/**
+ * @brief Unregisters the sink end-of-stream callback function.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @see media_streamer_sink_set_eos_cb()
+ */
+int media_streamer_sink_unset_eos_cb(media_streamer_h streamer);
+
+/**
+ * @brief Creates an instance of media streamer and
+ * passes the handle to the caller.
+ * @since_tizen 3.0
+ * @remarks You must release @a streamer using media_streamer_destroy()
+ * @param [out] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @post The media streamer state will be #MEDIA_STREAMER_STATE_IDLE.
+ * @see media_streamer_destroy()
+ */
+int media_streamer_create(media_streamer_h *streamer);
+
+/**
+ * @brief Sets media streamer state to MEDIA_STREAMER_STATE_READY.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The media streamer state must be set to #MEDIA_STREAMER_STATE_IDLE
+ * by calling media_streamer_create() or media_streamer_unprepare().
+ * @pre At least one src and one sink should be added and linked in the streamer
+ * by calling media_streamer_src_create(), media_streamer_sink_create() and media_streamer_node_link().
+ * @post The media streamer state will be #MEDIA_STREANER_STATE_READY.
+ * @see media_streamer_unprepare()
+ * @see media_streamer_create()
+ */
+int media_streamer_prepare(media_streamer_h streamer);
+
+/**
+ * @brief Sets media streamer state to MEDIA_STREAMER_STATE_IDLE.
+ * @details The most recently used media is reset and no longer associated with the media streamer.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The media streamer state should be higher than #MEDIA_STREAMER_STATE_IDLE.
+ * @post The media streamer state will be #MEDIA_STREAMER_STATE_IDLE.
+ * @see media_streamer_prepare()
+ */
+int media_streamer_unprepare(media_streamer_h streamer);
+
+/**
+ * @brief Sets media streamer state to MEDIA_STREAMER_STATE_PLAYING.
+ * @details start running the current streamer, or resumes it if paused.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The media streamer state must be set to #MEDIA_STREAMER_STATE_READY by calling media_streamer_prepare() or
+ * set to #MEDIA_STREAMER_STATE_PAUSED by calling media_streamer_pause().
+ * @post The media streamer state will be #MEDIA_STREAMER_STATE_PLAYING.
+ * @see media_streamer_create()
+ * @see media_streamer_pause()
+ * @see media_streamer_stop()
+ */
+int media_streamer_play(media_streamer_h streamer);
+
+/**
+ * @brief Pause the media streamer.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The media streamer state must be set to #MEDIA_STREAMER_STATE_PLAYING.
+ * @post The media streamer state will be #MEDIA_STREAMER_STATE_READY.
+ * @see media_streamer_create()
+ * @see media_streamer_play()
+ */
+int media_streamer_pause(media_streamer_h streamer);
+
+/**
+ * @brief Stops the media streamer.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre The media streamer state must be set to #MEDIA_STREAMER_STATE_PLAYING by calling media_streamer_start() or
+ * set to #MEDIA_STREAMER_STATE_PAUSED by calling media_streamer_pause().
+ * @post The media streamer state will be #MEDIA_STREAMER_STATE_READY.
+ * @see media_streamer_create()
+ * @see media_streamer_start()
+ * @see media_streamer_pause()
+ */
+int media_streamer_stop(media_streamer_h streamer);
+
+/**
+ * @brief Destroys media streamer.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media streamer handle by calling media_streamer_create() function
+ * @post The media streamer state will be #MEDIA_STREAMER_STATE_NONE.
+ * @see media_streamer_create()
+ */
+int media_streamer_destroy(media_streamer_h streamer);
+
+/**
+ * @brief Gets media streamer state.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @param [out] state Media streamer state
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a media streamer handle by calling media_streamer_create() function
+ * @see #media_streamer_state_e
+ */
+int media_streamer_get_state(media_streamer_h streamer,
+ media_streamer_state_e *state);
+
+/**
+ * @brief Creates media streamer source node.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege http://tizen.org/privilege/mediastorage
+ * http://tizen.org/privilege/externalstorage
+ * http://tizen.org/privilege/internet
+ * http://tizen.org/privilege/camera
+ * http://tizen.org/privilege/recorder
+ * @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 The internet privilege(http://tizen.org/privilege/internet) should be added if any URIs are used to play from network.
+ * @remarks The camera privilege(http://tizen.org/privilege/camera) should be added if the src node handle the camera device.
+ * @remarks The recorder privilege(http://tizen.org/privilege/recorder) should be added if the src node handle the recorder device.
+ * @remarks You can release @a source node using media_streamer_node_destroy() function
+ * @param [in] type Media streamer source node type
+ * @param [out] src Media streamer source node handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #MEDIA_STREAMER_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MEDIA_STREAMER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE Not support on device
+ * @see #media_streamer_src_type_e
+ * @see media_streamer_node_destroy()
+ */
+int media_streamer_src_create(media_streamer_src_type_e type,
+ media_streamer_node_h *src);
+
+/**
+ * @brief Pushes packet into custom source node.
+ * @details This function can be called only for MEDIA_STREAMER_SRC_TYPE_CUSTOM.
+ * @since_tizen 3.0
+ * @param [in] src Media streamer source node handle
+ * @param [in] packet Media packet handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #MEDIA_STREAMER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a source node handle by calling media_streamer_src_create() function
+ * @pre The media streamer state must be set to #MEDIA_STREAMER_STATE_IDLE at least.
+ * @see #media_packet_h
+ */
+int media_streamer_push_packet(media_streamer_node_h src,
+ media_packet_h packet);
+
+/**
+ * @brief Creates media streamer sink node.
+ * @details This function can be called only for MEDIA_STREAMER_SINK_TYPE_CUSTOM
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege http://tizen.org/privilege/mediastorage
+ * http://tizen.org/privilege/externalstorage
+ * http://tizen.org/privilege/internet
+ * @remarks The mediastorage privilege(http://tizen.org/privilege/mediastorage) should be added if any video/audio files are written in the internal storage devices.
+ * @remarks The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are written in the external storage devices.
+ * @remarks The internet privilege(http://tizen.org/privilege/internet) should be added if any URIs are used to transmit the output data.
+ * @remarks You can release @a sink node using media_streamer_node_destroy()
+ * @param [in] type Type of sink node to be created
+ * @param [out] sink Media streamer sink node handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #MEDIA_STREAMER_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MEDIA_STREAMER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE Not support on device
+ * @see #media_streamer_sink_type_e
+ * @see media_streamer_node_destroy()
+ */
+int media_streamer_sink_create(media_streamer_sink_type_e type,
+ media_streamer_node_h *sink);
+
+/**
+ * @brief Pulls packet from custom sink node.
+ * @details This function can be called only for MEDIA_STREAMER_SINK_TYPE_CUSTOM
+ * @since_tizen 3.0
+ * @param [in] sink Media streamer sink node handle
+ * @param [out] packet Media packet handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a sink node handle by calling media_streamer_sink_create() function
+ * @pre Set media_streamer_data_ready_cb by calling media_streamer_set_data_ready_cb() function.
+ * @see #media_packet_h
+ * @see media_streamer_sink_create()
+ */
+int media_streamer_pull_packet(media_streamer_node_h sink,
+ media_packet_h *packet);
+
+/**
+ * @brief Creates media streamer node except src and sink.
+ * @details Creates node specific @a type with specific format of input
+ * and output data.
+ * @since_tizen 3.0
+ * @remarks You can release @a node using media_streamer_node_destroy() function
+ * @param [in] type Created node type
+ * @param [in] in_fmt Media format handle for input data
+ * @param [in] out_fmt Media format handle for output data
+ * @param [out] node Media streamer node handle to be created
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @see #media_streamer_node_type_e
+ * @see #media_format_h
+ * @see media_streamer_node_destroy()
+ */
+int media_streamer_node_create(media_streamer_node_type_e type,
+ media_format_h in_fmt,
+ media_format_h out_fmt,
+ media_streamer_node_h *node);
+
+/**
+ * @brief Adds node to media streamer.
+ * @since_tizen 3.0
+ * @param [in] streamer Media streamer handle
+ * @param [in] node Media streamer node handle to be added
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create media streamer handle by calling media_streamer_create() function
+ * @pre Create node handle by calling media_streamer_node_create() function
+ * @see media_streamer_create()
+ * @see media_streamer_node_create()
+ * @see media_streamer_src_create()
+ * @see media_streamer_sink_create()
+ */
+int media_streamer_node_add(media_streamer_h streamer,
+ media_streamer_node_h node);
+
+/**
+ * @brief Destroys media streamer node.
+ * @since_tizen 3.0
+ * @param [in] node Media streamer node handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create node handle by calling media_streamer_node_create() function
+ * @pre If the node was added to media streamer, it have to be removed by calling media_streamer_node_remove() function
+ * @see media_streamer_node_create()
+ * @see media_streamer_src_create()
+ * @see media_streamer_sink_create()
+ * @see media_streamer_node_remove()
+ */
+int media_streamer_node_destroy(media_streamer_node_h node);
+
+/**
+ * @brief Remove media streamer node from streamer.
+ * @since_tizen 3.0
+ * @remarks If the node is linked, it will be unlinked before removing.
+ * @param [in] streamer Media streamer handle
+ * @param [in] node Media streamer node handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Add node to streamer by calling media_streamer_node_add() function
+ * @see media_streamer_node_add()
+ */
+int media_streamer_node_remove(media_streamer_h streamer,
+ media_streamer_node_h node);
+
+/**
+ * @brief Sets media format for media streamer node.
+ * @since_tizen 3.0
+ * @param [in] node Media streamer node handle
+ * @param [in] fmt Media format handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create node handle by calling media_streamer_node_create() function
+ * @see #media_format_h
+ */
+int media_streamer_node_set_format(media_streamer_node_h node,
+ media_format_h fmt);
+
+/**
+ * @brief Gets media format for media streamer node.
+ * @since_tizen 3.0
+ * @param [in] node Media streamer node handle
+ * @param [out] fmt Media format handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a source node handle by calling media_streamer_node_create() function
+ * @see #media_format_h
+ */
+int media_streamer_node_get_format(media_streamer_node_h node,
+ media_format_h *fmt);
+
+/**
+ * @brief Links two media streamer nodes.
+ * @since_tizen 3.0
+ * @param [in] src_node Media streamer node handle
+ * @param [in] src_pad The name of the source pad of the source node
+ * @param [in] dest_node The destination media streamer node handle
+ * @param [in] sink_pad The name of the sink pad of the destination node
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a source node and a destination node handles
+ * by calling media_streamer_node_create() function
+ * and add the nodes into streamer by calling media_streamer_node_add() function.
+ * @see media_streamer_node_create()
+ * @see media_streamer_node_add()
+ */
+int media_streamer_node_link(media_streamer_node_h src_node,
+ const char *src_pad,
+ media_streamer_node_h dest_node,
+ const char *sink_pad);
+
+/**
+ * @brief Gets formats of node pads.
+ * @since_tizen 3.0
+ * @remark After using the src_fmt and sink_fmt, it have to be free
+ * @param [in] node Media streamer node handle
+ * @param [out] src_fmt Array of source pad formats
+ * @param [out] sink_fmt Array of sink pad formats
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a node handle by calling media_streamer_node_create() function
+ * @see media_streamer_node_create()
+ * @see media_streamer_src_create()
+ * @see media_streamer_sink_create()
+ */
+int media_streamer_node_get_pad_format(media_streamer_node_h node,
+ char **src_fmt,
+ char **sink_fmt);
+
+/**
+ * @brief Sets parameters of node.
+ * @details Many parameters can be set at one time all together by using bundle.
+ * @since_tizen 3.0
+ * @param [in] node Media streamer node handle
+ * @param [in] param_list Key value array of media streamer node parameters
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a node handle by calling media_streamer_node_create() function.
+ * @pre Get param list to set by calling media_streamer_node_get_param_list() function.
+ * @see media_streamer_node_create()
+ * @see media_streamer_src_create()
+ * @see media_streamer_sink_create()
+ * @see media_streamer_node_get_param_list()
+ * @see media_streamer_node_set_single_param()
+ */
+int media_streamer_node_set_params(media_streamer_node_h node,
+ bundle *param_list);
+
+/**
+ * @brief Sets single parameter of node.
+ * @details Sets parameter one by one without creating param bundle.
+ * @since_tizen 3.0
+ * @param [in] node Media streamer node handle
+ * @param [in] param_name Param name of node
+ * @param [in] param_value Parm value of node
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a node handle by calling media_streamer_node_create() function.
+ * @pre Get param list to set by calling media_streamer_node_get_param_list() function.
+ * @see media_streamer_node_create()
+ * @see media_streamer_src_create()
+ * @see media_streamer_sink_create()
+ * @see media_streamer_node_get_param_list()
+ * @see media_streamer_node_set_params()
+ */
+int media_streamer_node_set_single_param(media_streamer_node_h node,
+ const char *param_name, const char *param_value);
+
+/**
+ * @brief Gets node parameter list.
+ * @since_tizen 3.0
+ * @remark After using param_list, it have to be free by calling bundle_free() in bundle.h
+ * @param [in] node Media streamer node handle
+ * @param [out] param_list Key value array of media streamer node parameters
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_STATE Invalid state
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_OPERATION Invalid operation
+ * @pre Create a node handle by calling media_streamer_node_create() function
+ * @post Set params which are needed to set by calling media_streamer_node_set_params() function.
+ * @see media_streamer_node_create()
+ * @see media_streamer_src_create()
+ * @see media_streamer_sink_create()
+ * @see media_streamer_node_set_params()
+ */
+int media_streamer_node_get_param_list(media_streamer_node_h node,
+ bundle **param_list);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIASTREAMER_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.
+ */
+
+#include <gst/gst.h>
+
+#include <media_streamer_priv.h>
+
+#define DOT_FILE_NAME "streamer"
+
+#define MEDIA_STREAMER_PIPELINE_NAME "media-streamer-pipeline"
+#define MEDIA_STREAMER_SRC_BIN_NAME "streamer_src"
+#define MEDIA_STREAMER_VIDEO_SINK_BIN_NAME "streamer_video_sink"
+#define MEDIA_STREAMER_AUDIO_SINK_BIN_NAME "streamer_audio_sink"
+#define MEDIA_STREAMER_TOPOLOGY_BIN_NAME "streamer_topology"
+
+/**
+ * @brief Generates dot files for GStreamer pipeline.
+ *
+ * @since_tizen 3.0
+ */
+void __ms_generate_dots(GstElement *bin, gchar *name_tag);
+
+/**
+ * @brief Returns the string representation of GST_STATE.
+ *
+ * @since_tizen 3.0
+ */
+const char *_ms_state_to_string(GstState state);
+
+/**
+ * @brief Creates GstElement by plugin name.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_element_create(const char *plugin_name, const char *name);
+
+/**
+ * @brief Creates camera GstElement by camera plugin name.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_camera_element_create(const char *microphone_plugin_name);
+
+/**
+ * @brief Creates encoder GstElement by mime type.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_video_encoder_element_create(dictionary *dict, media_format_mimetype_e mime);
+
+/**
+ * @brief Creates decoder GstElement by mime type.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_video_decoder_element_create(dictionary *dict, media_format_mimetype_e mime);
+
+/**
+ * @brief Creates audio encoder GstElement.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_audio_encoder_element_create(void);
+
+/**
+ * @brief Creates rtp container GstElement.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_rtp_element_create(media_streamer_node_s *ms_node);
+
+/**
+ * @brief Parse param for RTP node type.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_rtp_set_param(
+ media_streamer_node_s *node,
+ const gchar *param_key,
+ const gchar *param_value);
+
+/**
+ * @brief Creates pipeline, bus and src/sink/topology bins.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_pipeline_create(media_streamer_s *ms_streamer);
+
+/**
+ * @brief Adds node to bin
+ *
+ * @since_tizen 3.0
+ */
+int __ms_add_node_into_bin(media_streamer_s *ms_streamer,media_streamer_node_s *ms_node);
+
+/**
+ * @brief Sets GstElement into state.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_element_set_state(GstElement *gst_element, GstState gst_state);
+
+/**
+ * @brief Sets mediaformat into GstElement.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_element_set_fmt(media_streamer_node_s *node, media_format_h fmt);
--- /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 <media_streamer_priv.h>
+
+/**
+ * @brief Creates media streamer node using input and output format.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_node_create(media_streamer_node_s *node,
+ media_format_h in_fmt,
+ media_format_h out_fmt);
+
+/**
+ * @brief Creates media streamer source node.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_src_node_create(media_streamer_node_s *node);
+
+/**
+ * @brief Creates media streamer sink node.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_sink_node_create(media_streamer_node_s *node);
+
+/**
+ * @brief Destroys media streamer node.
+ *
+ * @since_tizen 3.0
+ */
+void __ms_node_destroy(void *data);
+
+/**
+ * @brief Inserts media streamer node into nodes table.
+ *
+ * @since_tizen 3.0
+ */
+void __ms_node_insert_into_table(GHashTable *nodes_table,
+ media_streamer_node_s *ms_node);
+
+/**
+ * @brief Remove media streamer node from nodes table.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_node_remove_from_table(GHashTable *nodes_table,
+ media_streamer_node_s *ms_node);
+
+/**
+ * @brief Reads node parameters from user's bundle object.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_node_read_params_from_bundle (media_streamer_node_s *node,
+ bundle *param_list);
+
+/**
+ * @brief Writes GstElement properties into user's bundle object.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_node_write_params_into_bundle (media_streamer_node_s *node,
+ bundle *param_list);
--- /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_MEDIASTREAMER_PRIVATE_H__
+#define __TIZEN_MEDIASTREAMER_PRIVATE_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <gst/gst.h>
+#include <stdio.h>
+
+#include <media_streamer.h>
+#include <media_streamer_util.h>
+
+/**
+ * @brief Media Streamer callbacks structure.
+ *
+ * @since_tizen 3.0
+ */
+typedef struct
+{
+ void *callback;
+ void *user_data;
+} media_streamer_callback_s;
+
+/**
+ * @brief Media Streamer source callbacks structure.
+ *
+ * @since_tizen 3.0
+ */
+typedef struct
+{
+ media_streamer_callback_s enough_data_cb;
+ media_streamer_callback_s need_data_cb;
+} media_streamer_src_callbacks_s;
+
+/**
+ * @brief Media Streamer sink callbacks structure.
+ *
+ * @since_tizen 3.0
+ */
+typedef struct
+{
+ media_streamer_callback_s data_ready_cb;
+ media_streamer_callback_s eos_cb;
+} media_streamer_sink_callbacks_s;
+
+/**
+ * @brief Media Streamer type handle.
+ *
+ * @since_tizen 3.0
+ */
+typedef struct
+{
+ media_streamer_ini_t ini;
+ GstElement *pipeline;
+
+ GstElement *src_bin;
+ GstElement *sink_video_bin;
+ GstElement *sink_audio_bin;
+ GstElement *topology_bin;
+
+ GHashTable *nodes_table;
+ GMutex mutex_lock;
+
+ GstBus *bus;
+ guint bus_watcher;
+
+ media_streamer_state_e state;
+
+ media_streamer_callback_s error_cb;
+ media_streamer_callback_s state_changed_cb;
+} media_streamer_s;
+
+/**
+ * @brief Media Streamer node type handle.
+ *
+ * @since_tizen 3.0
+ */
+typedef int (*media_streamer_node_set_param)(
+ struct media_streamer_node_s *node,
+ const gchar *param_key,
+ const gchar *param_value);
+
+/**
+ * @brief Media Streamer node type handle.
+ *
+ * @since_tizen 3.0
+ */
+typedef struct
+{
+ GstElement *gst_element;
+ char *name;
+ media_streamer_s *parent_streamer;
+ media_streamer_node_type_e type;
+ int subtype;
+ media_streamer_node_set_param set_param;
+ void *callbacks_structure;
+} media_streamer_node_s;
+
+/* Private functions definition */
+
+/**
+ * @brief Destroys media streamer structure.
+ *
+ * @since_tizen 3.0
+ */
+void __ms_streamer_destroy(media_streamer_s *ms_streamer);
+
+/**
+ * @brief Creates media streamer structure.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_create(media_streamer_s *ms_streamer);
+
+/**
+ * @brief Changes state of media streamer.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e state);
+
+#ifdef __cplusplus
+}
+
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIASTREAMER_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.
+ */
+
+#ifndef __MEDIA_STREAMER_UTIL_H__
+#define __MEDIA_STREAMER_UTIL_H__
+
+#include <stdlib.h>
+#include <glib.h>
+#include <dlog.h>
+#include <iniparser.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DLog Utils*/
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "CAPI_MEDIASTREAMER"
+
+#define FONT_COLOR_RESET "\033[0m"
+#define FONT_COLOR_RED "\033[31m"
+#define FONT_COLOR_GREEN "\033[32m"
+#define FONT_COLOR_YELLOW "\033[33m"
+#define FONT_COLOR_BLUE "\033[34m"
+#define FONT_COLOR_PURPLE "\033[35m"
+#define FONT_COLOR_CYAN "\033[36m"
+#define FONT_COLOR_GRAY "\033[37m"
+
+#define ms_debug(fmt, arg...) do { \
+ LOGD(FONT_COLOR_RESET""fmt"", ##arg); \
+} while(0)
+
+#define ms_info(fmt, arg...) do { \
+ LOGI(FONT_COLOR_GREEN""fmt"", ##arg); \
+} while(0)
+
+#define ms_error(fmt, arg...) do { \
+ LOGE(FONT_COLOR_RED""fmt"", ##arg); \
+} while(0)
+
+#define ms_debug_fenter() do { \
+ LOGD(FONT_COLOR_YELLOW"<Enter>"); \
+} while(0)
+
+#define ms_debug_fleave() do { \
+ LOGD(FONT_COLOR_PURPLE"<Leave>"); \
+} while(0)
+
+#define ms_retm_if(expr, fmt, arg...) do { \
+ if(expr) { \
+ LOGE(FONT_COLOR_RED""fmt"", ##arg); \
+ return; \
+} \
+} while(0)
+
+#define ms_retvm_if(expr, val, fmt, arg...) do { \
+ if(expr) { \
+ LOGE(FONT_COLOR_RED""fmt"", ##arg); \
+ return(val); \
+} \
+} while(0)
+
+
+#define MS_SAFE_FREE(src) {if(src) {free(src); src = NULL;}}
+#define MS_SAFE_GFREE(src) {if(src) {g_free(src); src = NULL;}}
+#define MS_SAFE_UNREF(src) {if(src) {gst_object_unref(GST_OBJECT(src)); src = NULL;}}
+#define MS_TABLE_SAFE_UNREF(src) {if(src) {g_hash_table_unref(src); src = NULL;}}
+
+/* Ini Utils */
+#define MEDIA_STREAMER_INI_DEFAULT_PATH "/usr/etc/media_streamer.ini"
+#define MEDIA_STREAMER_INI_MAX_STRLEN 100
+
+/**
+ * @brief Media Streamer ini settings structure.
+ *
+ * @since_tizen 3.0
+ */
+typedef struct __media_streamer_ini
+{
+ /* general */
+ gboolean generate_dot;
+
+} media_streamer_ini_t;
+
+/*Test elements*/
+#define DEFAULT_VIDEO_TEST_SOURCE "videotestsrc"
+#define DEFAULT_AUDIO_TEST_SOURCE "audiotestsrc"
+#define DEFAULT_FAKE_SINK "fakesink"
+#define DEFAULT_QUEUE "queue"
+
+/* setting default values if each value is not specified in .ini file */
+/* general */
+#define DEFAULT_GENERATE_DOT FALSE
+#define DEFAULT_AUDIO_SOURCE "alsasrc"
+#define DEFAULT_CAMERA_SOURCE "camerasrc"
+#define DEFAULT_VIDEO_SOURCE "ximagesrc"
+#define DEFAULT_AUDIO_SINK "pulsesink"
+#define DEFAULT_VIDEO_SINK "autovideosink"
+
+/* udp streaming */
+#define DEFAULT_UDP_SOURCE "udpsrc"
+#define DEFAULT_UDP_SINK "udpsink"
+#define DEFAULT_RTP_BIN "rtpbin"
+
+/* video format defaults */
+#define DEFAULT_VIDEO_ENCODER "omxh264enc"
+#define DEFAULT_VIDEO_DECODER "omxh264dec"
+#define DEFAULT_VIDEO_PARSER "h264parse"
+#define DEFAULT_VIDEO_RTPPAY "rtph264pay"
+#define DEFAULT_VIDEO_RTPDEPAY "rtph264depay"
+
+/* audio format defaults */
+#define DEFAULT_AUDIO_ENCODER "omxh264enc"
+#define DEFAULT_AUDIO_DECODER "omxh264dec"
+#define DEFAULT_AUDIO_PARSER "h264parse"
+#define DEFAULT_AUDIO_RTPPAY "rtph264pay"
+#define DEFAULT_AUDIO_RTPDEPAY "rtph264depay"
+
+#define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,width=320,height=240"
+#define MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT "audio/x-raw,channels=1,rate=44100,format=S16BE"
+#define MEDIA_STREAMER_DEFAULT_ENCODER_FORMAT "video/x-h264,stream-format=byte-stream,profile=high"
+
+#define MEDIA_STREAMER_DEFAULT_DOT_DIR "/tmp"
+#define MEDIA_STREAMER_DEFAULT_INI \
+"\
+[general] \n\
+; generating dot file representing pipeline state \n\
+generate dot = no \n\
+dot dir = /tmp \n\
+\n\
+\n\
+[sources] \n\
+\n\
+audio_source = pulsesrc \n\
+camera_source = camerasrc \n\
+video_source = ximagesrc \n\
+udp_source = udpsrc \n\
+\n\
+\n\
+[sinks] \n\
+\n\
+audio_sink = pulsesink \n\
+video_sink = autovideosink \n\
+udp_sink = udpsink \n\
+\n\
+\n\
+[h263] \n\
+\n\
+encoder = avenc_h263 \n\
+decoder = avdec_h263 \n\
+rtppay = rtph263pay \n\
+rtpdepay = rtph263depay \n\
+parser = h263parse \n\
+\n\
+\n\
+[h264] \n\
+\n\
+encoder = omxh264enc \n\
+decoder = avdec_h264 \n\
+rtppay = rtph264pay \n\
+rtpdepay = rtph264depay \n\
+parser = h264parse \n\
+\n\
+\n\
+[audio-raw] \n\
+\n\
+encoder = \n\
+decoder = \n\
+rtppay = rtpL16pay \n\
+rtpdepay = rtpL16depay \n\
+\n\
+"
+
+/**
+ * @brief Load media streamer settings from ini file.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_load_ini_settings(media_streamer_ini_t *ini);
+
+/**
+ * @brief Load settings from ini file into dictionary object.
+ *
+ * @since_tizen 3.0
+ */
+gboolean __ms_load_ini_dictionary(dictionary **dict);
+
+/**
+ * @brief Destroys ini dictionary object and frees all resources.
+ *
+ * @since_tizen 3.0
+ */
+gboolean __ms_destroy_ini_dictionary(dictionary *dict);
+
+/**
+ * @brief Read and copy string reading from ini file.
+ *
+ * @since_tizen 3.0
+ */
+gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path,
+ char *default_str);
+
+/**
+ * @brief Converts Media Format mime type into string.
+ *
+ * @since_tizen 3.0
+ */
+const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+ <assign>
+ <filesystem path="/usr/bin/media_streamer_test" label="_" exec_label="none" />
+ </assign>
+</manifest>
--- /dev/null
+Name: capi-media-streamer
+Summary: A Media Streamer library in Tizen Native API
+Version: 0.1.1
+Release: 0
+Group: Multimedia/API
+License: Apache-2.0
+URL: http://source.tizen.org
+Source0: %{name}-%{version}.tar.gz
+Source1001: capi-media-streamer.manifest
+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)
+BuildRequires: pkgconfig(bundle)
+
+%description
+A MediaStreamer library in Tizen Native API.
+
+%package devel
+Summary: Multimedia Streamer Library in Tizen Native API (Development)
+Group: TO_BE/FILLED_IN
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+MediaStreamer Library in Tizen Native API (DEV).
+
+%prep
+%setup -q
+cp %{SOURCE1001} .
+
+%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
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+mkdir -p %{buildroot}/usr/bin
+cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name}
+cp test/media_streamer_test %{buildroot}/usr/bin
+
+%make_install
+
+%post
+/sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+
+%files
+%manifest capi-media-streamer.manifest
+%{_libdir}/libcapi-media-streamer.so.*
+%{_datadir}/license/%{name}
+/usr/bin/*
+
+%files devel
+%{_includedir}/media/*.h
+%{_libdir}/pkgconfig/*.pc
+%{_libdir}/libcapi-media-streamer.so
+
+
--- /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 <stdlib.h>
+#include <string.h>
+
+#include <mm_types.h>
+#include <dlog.h>
+
+#include <media_streamer.h>
+#include <media_streamer_priv.h>
+#include <media_streamer_node.h>
+#include <media_streamer_gst.h>
+
+/*
+* Public Implementation
+*/
+
+int media_streamer_src_create(media_streamer_src_type_e type,
+ media_streamer_node_h *src)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ media_streamer_node_s *ms_src = (media_streamer_node_s*)src;
+ ms_retvm_if(ms_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ms_src = (media_streamer_node_s *)calloc(1, sizeof(media_streamer_node_s));
+ ms_retvm_if(ms_src == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+
+ ms_src->type = MEDIA_STREAMER_NODE_TYPE_SRC;
+ ms_src->subtype = (media_streamer_src_type_e)type;
+ ret = __ms_src_node_create(ms_src);
+ if(ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ MS_SAFE_FREE(ms_src);
+ ms_error( "Error creating Src node [%d]",ret);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ms_info("Source node [%s] created", ms_src->name);
+ *src = (media_streamer_node_h)ms_src;
+
+ return ret;
+}
+
+int media_streamer_sink_create(media_streamer_sink_type_e type,
+ media_streamer_node_h *sink)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ media_streamer_node_s *ms_sink = (media_streamer_node_s*)sink;
+ ms_retvm_if(ms_sink == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ms_sink = (media_streamer_node_s *)calloc(1, sizeof(media_streamer_node_s));
+ ms_retvm_if(ms_sink == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+
+ ms_sink->type = MEDIA_STREAMER_NODE_TYPE_SINK;
+ ms_sink->subtype = (media_streamer_sink_type_e)type;
+ ret = __ms_sink_node_create(ms_sink);
+ if(ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ MS_SAFE_FREE(ms_sink);
+ ms_error( "Error creating Sink node [%d]",ret);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ms_info("Sink node [%s] created", ms_sink->name);
+ *sink = (media_streamer_node_h)ms_sink;
+
+ return ret;
+}
+
+int media_streamer_node_create(media_streamer_node_type_e type,
+ media_format_h in_fmt,
+ media_format_h out_fmt,
+ media_streamer_node_h *node)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ media_streamer_node_s *ms_node = (media_streamer_node_s*)node;
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ms_node = (media_streamer_node_s *)calloc(1, sizeof(media_streamer_node_s));
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+
+ ms_node->type = type;
+ ms_node->subtype = 0;
+
+ ret = __ms_node_create(ms_node, in_fmt, out_fmt);
+ if(ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ MS_SAFE_FREE(ms_node);
+ ms_error( "Error creating Node [%d]",ret);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ms_info("Node [%s] created", ms_node->name);
+ *node = (media_streamer_node_h)ms_node;
+
+ return ret;
+}
+
+int media_streamer_node_destroy(media_streamer_node_h node)
+{
+ media_streamer_node_s *ms_node = (media_streamer_node_s*)node;
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ if (ms_node->parent_streamer == NULL)
+ {
+ // This node was not added into any media streamer
+ __ms_node_destroy(ms_node);
+ }
+ else
+ {
+ int ret = __ms_node_remove_from_table(ms_node->parent_streamer->nodes_table, ms_node);
+ ms_retvm_if(ret != MEDIA_STREAMER_ERROR_NONE, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+ "Current key was not removed from nodes_table");
+ }
+
+ ms_info("Node destroyed successfully");
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_node_add(media_streamer_h streamer,
+ media_streamer_node_h node)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ media_streamer_node_s* ms_node = (media_streamer_node_s*)node;
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ __ms_node_insert_into_table(ms_streamer->nodes_table,ms_node);
+ ms_node->parent_streamer = ms_streamer;
+
+ __ms_add_node_into_bin(ms_streamer, ms_node);
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
+ return ret;
+}
+
+int media_streamer_prepare(media_streamer_h streamer)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_STATE, "Pipeline doesn`t exist");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ if(ms_streamer->state > MEDIA_STREAMER_STATE_IDLE)
+ {
+ ms_error("Error: Media streamer already prepared [%d]!",
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if(__ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_READY) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ __ms_generate_dots(ms_streamer->pipeline, "prepare");
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_unprepare(media_streamer_h streamer)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_STATE, "Pipeline doesn`t exist");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ if(__ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_play(media_streamer_h streamer)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ if(ms_streamer->state < MEDIA_STREAMER_STATE_READY)
+ {
+ ms_error("Error: Media streamer must be prepared first [%d]!",
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if(__ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_PLAYING) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_create(media_streamer_h *streamer)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ media_streamer_s *ms_streamer = NULL;
+ ms_retvm_if(streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ms_streamer = (media_streamer_s *)calloc(1, sizeof(media_streamer_s));
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+
+ /* create streamer lock */
+ g_mutex_init(&ms_streamer->mutex_lock);
+
+ ms_streamer->state = MEDIA_STREAMER_STATE_NONE;
+
+ ret = __ms_create(ms_streamer);
+ if(ret!=MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error creating Media Streamer");
+ __ms_streamer_destroy(ms_streamer);
+
+ g_mutex_clear(&ms_streamer->mutex_lock);
+
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if(__ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ *streamer = ms_streamer;
+ ms_info("Media Streamer created successfully");
+ return ret;
+}
+
+int media_streamer_destroy(media_streamer_h streamer)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ __ms_streamer_destroy(ms_streamer);
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+ g_mutex_clear(&ms_streamer->mutex_lock);
+
+ ms_info("Media Streamer destroyed successfully");
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_set_error_cb(media_streamer_h streamer,
+ media_streamer_error_cb callback,
+ void *data)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_unset_error_cb(media_streamer_h streamer)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_set_state_change_cb(media_streamer_h streamer,
+ media_streamer_state_changed_cb callback,
+ void *data)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_unset_state_change_cb(media_streamer_h streamer)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_src_set_buffer_status_cb(media_streamer_node_h source,
+ media_streamer_custom_buffer_status_cb callback,
+ void *user_data)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_src_unset_buffer_status_cb(media_streamer_node_h source)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_sink_set_data_ready_cb(media_streamer_node_h sink,
+ media_streamer_sink_data_ready_cb callback,
+ void *data)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_sink_unset_data_ready_cb(media_streamer_node_h source)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_sink_set_eos_cb(media_streamer_node_h sink,
+ media_streamer_sink_eos_cb callback,
+ void *data)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_sink_unset_eos_cb(media_streamer_node_h source)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_pause(media_streamer_h streamer)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ if(__ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_PAUSED) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_stop(media_streamer_h streamer)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ if(ms_streamer->state < MEDIA_STREAMER_STATE_READY)
+ {
+ ms_error("Error: Media streamer must be prepared first [%d]!",
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if(__ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_READY) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_get_state(media_streamer_h streamer,
+ media_streamer_state_e *state)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)streamer;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ *state = ms_streamer->state;
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_seek(media_streamer_h streamer,
+ media_streamer_time_value time)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_push_packet(media_streamer_node_h src,
+ media_packet_h packet)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_pull_packet(media_streamer_node_h sink,
+ media_packet_h *packet)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_node_set_format(media_streamer_node_h node,
+ media_format_h fmt)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ media_streamer_node_s *ms_node = (media_streamer_node_s*)node;
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Format is NULL");
+
+ ret = __ms_element_set_fmt(node, fmt);
+ return ret;
+}
+
+int media_streamer_node_get_format(media_streamer_node_h node,
+ media_format_h *fmt)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ media_streamer_node_s *ms_node = (media_streamer_node_s*)node;
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Format is NULL");
+
+
+ return ret;
+}
+
+int media_streamer_node_link(media_streamer_node_h src_node,
+ const char *src_pad,
+ media_streamer_node_h dest_node,
+ const char *sink_pad)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ media_streamer_node_s *ms_src_node = (media_streamer_node_s*)src_node;
+ ms_retvm_if(ms_src_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ media_streamer_node_s *ms_dest_node = (media_streamer_node_s*)dest_node;
+ ms_retvm_if(ms_dest_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ gchar *src_element_name = gst_element_get_name(ms_src_node->gst_element);
+ gchar *sink_element_name = gst_element_get_name(ms_dest_node->gst_element);
+
+ ms_retvm_if(src_pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pad is NULL");
+ ms_retvm_if(sink_pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pad is NULL");
+
+ gboolean link_ret;
+
+ link_ret = gst_element_link_pads (ms_src_node->gst_element, src_pad, ms_dest_node->gst_element, sink_pad);
+ if(!link_ret)
+ {
+ ms_error("Can not link [%s]->%s pad to [%s]->%s pad, ret code [%d] ", src_pad, sink_pad, src_element_name, sink_element_name, link_ret);
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ MS_SAFE_GFREE(src_element_name);
+ MS_SAFE_GFREE(sink_element_name);
+ return ret;
+}
+
+int media_streamer_node_get_pad_format(media_streamer_node_h node,
+ char **in_fmt,
+ char **out_fmt)
+{
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_node_set_params(media_streamer_node_h node,
+ bundle *param_list)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ media_streamer_node_s *ms_node = (media_streamer_node_s*)node;
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(ms_node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Parameters list is NULL");
+
+ ret = __ms_node_read_params_from_bundle(ms_node,param_list);
+ ms_retvm_if(ret != MEDIA_STREAMER_ERROR_NONE, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+ "Parameters list is NULL");
+
+ return ret;
+}
+
+int media_streamer_node_get_param_list(media_streamer_node_h node,
+ bundle **param_list)
+{
+ media_streamer_node_s *ms_node =(media_streamer_node_s*)node;
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Param list pionter is NULL");
+
+ bundle *ms_params = NULL;
+ ms_params = bundle_create();
+ ms_retvm_if(ms_params == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error creating new params object");
+
+ if (__ms_node_write_params_into_bundle(ms_node, ms_params) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_info("Node [%s] do not have any params.", ms_node->name);
+ bundle_free(ms_params);
+ *param_list = NULL;
+
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ *param_list = ms_params;
+ return MEDIA_STREAMER_ERROR_NONE;
+}
--- /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 <bundle.h>
+#include <media_streamer_gst.h>
+
+#define MS_ELEMENT_IS_SINK(el) g_str_has_suffix(el, "sink")
+#define MS_ELEMENT_IS_SOURCE(el) g_str_has_suffix(el, "source")
+#define MS_ELEMENT_IS_AUDIO(el) g_str_has_prefix(el, "audio")
+#define MS_ELEMENT_IS_VIDEO(el) g_str_has_prefix(el, "video")
+
+void __ms_generate_dots(GstElement *bin, gchar *name_tag)
+{
+ gchar *dot_name;
+ ms_retm_if(bin == NULL, "Handle is NULL");
+
+ if (!name_tag)
+ {
+ dot_name = g_strdup(DOT_FILE_NAME);
+ }
+ else
+ {
+ dot_name = g_strconcat (DOT_FILE_NAME, ".", name_tag, NULL);
+ }
+
+ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(bin), GST_DEBUG_GRAPH_SHOW_ALL, dot_name);
+
+ MS_SAFE_GFREE (dot_name);
+}
+
+const char *_ms_state_to_string(GstState state)
+{
+ static const char pending[] = "PENDING\0";
+ static const char null_s[] = "NULL\0";
+ static const char ready[] = "READY\0";
+ static const char paused[] = "PAUSED\0";
+ static const char playing[] = "PLAYING\0";
+ switch(state)
+ {
+ case GST_STATE_VOID_PENDING:
+ return pending;
+ break;
+ case GST_STATE_NULL:
+ return null_s;
+ break;
+ case GST_STATE_READY:
+ return ready;
+ break;
+ case GST_STATE_PAUSED:
+ return paused;
+ break;
+ case GST_STATE_PLAYING:
+ return playing;
+ break;
+ default:
+ return "\0";
+ break;
+ };
+ return 0;
+}
+
+static int __ms_add_ghostpad(GstElement *gst_element,
+ const char *pad_name,
+ GstElement *gst_bin,
+ const char *ghost_pad_name)
+{
+ ms_retvm_if(!ghost_pad_name || !gst_bin, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ GstPad *ghost_pad = NULL;
+ gchar *bin_name = gst_element_get_name(gst_bin);
+
+ if(!gst_element || !pad_name)
+ {
+ ghost_pad = gst_ghost_pad_new_no_target(ghost_pad_name, GST_PAD_SRC);
+ gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad);
+ ms_info("Added %s empty ghostpad into [%s]", bin_name);
+ ret = MEDIA_STREAMER_ERROR_NONE;
+ }
+ else
+ {
+ gchar *element_name = gst_element_get_name(gst_element);
+ GstPad *element_pad = gst_element_get_static_pad(gst_element, pad_name);
+ if(!element_pad)
+ {
+ //maybe it is request pad
+ element_pad = gst_element_get_request_pad(gst_element, pad_name);
+ }
+ if(element_pad != NULL)
+ {
+ ghost_pad = gst_ghost_pad_new(ghost_pad_name, element_pad);
+ gst_pad_set_active(ghost_pad, TRUE);
+
+ gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad);
+ ms_info("Added %s ghostpad from [%s] into [%s]", pad_name, element_name, bin_name);
+ MS_SAFE_UNREF(element_pad);
+ MS_SAFE_GFREE(element_name);
+
+ ret = MEDIA_STREAMER_ERROR_NONE;
+ }
+ else
+ {
+ ms_error("Error: element [%s] does not have valid [%s] pad for adding into [%s] bin",
+ element_name, pad_name, bin_name);
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ }
+
+ MS_SAFE_GFREE(bin_name);
+
+ return ret;
+}
+
+static GObject *__ms_get_property_owner(GstElement *element, const gchar *key, GValue *value)
+{
+ GParamSpec *param;
+ GObject *obj = NULL;
+
+ if (GST_IS_CHILD_PROXY(element))
+ {
+ int i;
+ int childs_count = gst_child_proxy_get_children_count(GST_CHILD_PROXY(element));
+
+ param = NULL;
+ for(i = 0; (i < childs_count) && (param == NULL); ++i)
+ {
+ obj = gst_child_proxy_get_child_by_index(GST_CHILD_PROXY(element),i);
+ param = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), key);
+ }
+ ms_retvm_if(param == NULL || obj == NULL, NULL, "Error: Bin object does not have property [%s].", key);
+ }
+ else
+ {
+ obj = G_OBJECT(element);
+ param = g_object_class_find_property
+ (G_OBJECT_GET_CLASS(obj), key);
+ }
+
+ g_value_init(value, param->value_type);
+
+ if (param->flags & G_PARAM_WRITABLE)
+ {
+ g_object_get_property(G_OBJECT(obj), key, value);
+ }
+ else
+ {
+ // Skip properties which user can not change.
+ ms_error("Error: node param [%s] is not writable!", key);
+ return NULL;
+ }
+ ms_info("%-20s: %s\n", g_param_spec_get_name(param), g_param_spec_get_blurb(param));
+
+ return obj;
+}
+
+static void __ms_element_set_property(GstElement *element, const gchar *key, const gchar *param_value)
+{
+ gchar *element_name = gst_element_get_name(element);
+ GValue value = G_VALUE_INIT;
+ GObject *obj = __ms_get_property_owner(element, key, &value);
+
+ if(obj == NULL)
+ {
+ ms_debug("Element [%s] does not have property [%s].", element_name, key);
+ MS_SAFE_GFREE(element_name);
+ return;
+ }
+
+ switch(G_VALUE_TYPE(&value))
+ {
+ case G_TYPE_STRING:
+ g_value_set_string(&value, param_value);
+ ms_info("Set string value: [%s]", g_value_get_string(&value));
+ break;
+
+ case G_TYPE_BOOLEAN:
+ {
+ gboolean bool_val = !g_strcmp0(param_value, "true") ? TRUE : FALSE;
+ g_value_set_boolean(&value, bool_val);
+ ms_info("Set boolean value: [%d]", g_value_get_boolean(&value));
+ break;
+ }
+
+ case G_TYPE_ULONG:
+ {
+ unsigned long pulong = atol(param_value);
+ g_value_set_ulong(&value, pulong);
+ ms_info("Set ulong value: [%lu]", g_value_get_ulong(&value));
+ break;
+ }
+
+ case G_TYPE_LONG:
+ {
+ long plong = atol(param_value);
+ g_value_set_long(&value, plong);
+ ms_info("Set long value: [%ld]", g_value_get_long(&value));
+ break;
+ }
+
+ case G_TYPE_UINT:
+ {
+ unsigned int puint = atoi(param_value);
+ g_value_set_uint(&value, puint);
+ ms_info("Set uint value: [%u]", g_value_get_uint(&value));
+ break;
+ }
+
+ case G_TYPE_INT:
+ {
+ int pint = atoi(param_value);
+ g_value_set_int(&value, pint);
+ ms_info("Set int value: [%d]", g_value_get_int(&value));
+ break;
+ }
+
+ case G_TYPE_UINT64:
+ {
+ unsigned long long puint64 = strtoull(param_value, NULL, 10);
+ g_value_set_uint64(&value, puint64);
+ ms_info("Set long value: [%llu]", g_value_get_uint64(&value));
+ break;
+ }
+
+ case G_TYPE_INT64:
+ {
+ long long pint64 = strtoll(param_value, NULL, 10);
+ g_value_set_int64(&value, pint64);
+ ms_info("Set long value: [%ll]", g_value_get_int64(&value));
+ break;
+ }
+ case G_TYPE_FLOAT:
+ {
+ float pfloat = strtof(param_value, NULL);
+ g_value_set_float(&value, pfloat);
+ ms_info("Set long value: [%15.7g]", g_value_get_float(&value));
+ break;
+ }
+ case G_TYPE_DOUBLE:
+ {
+ double pdouble = strtod(param_value, NULL);
+ g_value_set_double(&value, pdouble);
+ ms_info("Set long value: [%15.7g]", g_value_get_float(&value));
+ break;
+ }
+ default:
+ if(G_VALUE_TYPE(&value) == GST_TYPE_CAPS)
+ {
+ GstCaps *caps = gst_caps_from_string(param_value);
+
+ if (!caps)
+ {
+ ms_error("Can not create caps from param value.");
+ }
+ else
+ {
+ ms_info("Create Caps from params and set to the object.");
+ g_object_set(obj, key, caps, NULL);
+ gst_caps_unref(caps);
+ }
+ return;
+ }
+ else
+ {
+ ms_info("Got unknown type with param->value_type [%d]", G_VALUE_TYPE(&value));
+ return;
+ }
+ break;
+ }
+ g_object_set_property(obj, key, &value);
+ MS_SAFE_GFREE(element_name);
+}
+
+#if 0
+static void __ms_link_elements_on_pad_added_cb(GstPad *new_pad, GstElement *sink_element)
+{
+ GstPadLinkReturn ret;
+ GstPad *sink_pad;
+ gchar *new_pad_name = NULL;
+ gchar *sink_element_name = NULL;
+ gchar *peer_pad_name = NULL;
+ GstPad *peer_pad = NULL;
+
+ sink_pad = gst_element_get_static_pad(sink_element, "sink");
+ ms_retm_if(sink_pad == NULL, "Sinkpad is NULL");
+
+ sink_element_name = gst_element_get_name(sink_element);
+ new_pad_name = gst_pad_get_name(new_pad);
+
+ if(!gst_pad_is_linked(sink_pad))
+ {
+ ms_info("Pads [rtpbin].[%s] and [%s].[sink] are not linked\n", new_pad_name, sink_element_name);
+
+ ret = gst_pad_link(new_pad, sink_pad);
+ if(GST_PAD_LINK_FAILED (ret))
+ {
+ ms_error("Failed to link [rtpbin].[%s] and [%s].[sink]\n", new_pad_name, sink_element_name);
+ }
+ else
+ {
+ ms_info("Succeeded to link [rtpbin].[%s]->[%s].[sink]\n", new_pad_name, sink_element_name);
+ }
+ }
+ else
+ {
+ peer_pad = gst_pad_get_peer(sink_pad);
+ peer_pad_name = gst_pad_get_name(peer_pad);
+
+ ms_debug("Pads [rtpbin].[%s]->[%s].[sink] are previously linked\n", peer_pad_name, sink_element_name);
+
+ ret = gst_pad_unlink(peer_pad, sink_pad);
+ if(!ret)
+ {
+ ms_error("Filed to unlink pads [rtpbin].[%s] <-and-> [%s].[sink] \n", peer_pad_name, sink_element_name);
+ }
+ else
+ {
+ ms_info("Pads [rtpbin].[%s] <-and-> [%s].[sink] are unlinked successfully\n", peer_pad_name, sink_element_name);
+ }
+
+ ret = gst_pad_link(new_pad, sink_pad);
+ if(GST_PAD_LINK_FAILED(ret))
+ {
+ ms_error("Failed to link [rtpbin].[%s] and [%s].[sink]\n", new_pad_name, sink_element_name);
+ }
+ else
+ {
+ ms_info("Succeeded to link [rtpbin].[%s]->[%s].[sink]\n", new_pad_name, sink_element_name);
+ }
+ }
+
+ MS_SAFE_GFREE(sink_element_name);
+ MS_SAFE_GFREE(new_pad_name);
+ MS_SAFE_GFREE(peer_pad_name);
+}
+
+static void __ms_got_rtpstream_on_pad_added_cb(media_streamer_node_s *ms_node, GstPad *new_pad, const gchar *compared_type)
+{
+ GstPad *src_pad;
+ GstCaps *src_pad_caps = NULL;
+ GstStructure *src_pad_struct = NULL;
+
+ gchar *sink_element_name = NULL;
+ GstElement *sink_element;
+
+ GValue elem=G_VALUE_INIT;
+ const gchar *depay_klass_name = "Codec/Depayloader/Network/RTP";
+ GstIterator *bin_iterator;
+
+ gchar *new_pad_name = gst_pad_get_name(new_pad);
+ gchar *source_pad_name = g_strdup_printf("%s_source", compared_type);
+
+ bin_iterator = gst_bin_iterate_elements(GST_BIN(ms_node->parent_streamer->topology_bin));
+ while(GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &elem))
+ {
+
+ sink_element = (GstElement *)g_value_get_object(&elem);
+ sink_element_name = gst_element_get_name(sink_element);
+
+ const gchar *klass_name = gst_element_factory_get_klass(gst_element_get_factory(sink_element));
+
+ if( g_strrstr(klass_name, depay_klass_name))
+ {
+ src_pad = gst_element_get_static_pad (sink_element, "src");
+ ms_retm_if(src_pad == NULL, "Src pad is NULL");
+
+ src_pad_caps = gst_pad_query_caps(src_pad,NULL);
+ src_pad_struct = gst_caps_get_structure(src_pad_caps, 0);
+ const gchar *src_pad_type = gst_structure_get_name(src_pad_struct);
+
+ if (g_strrstr(src_pad_type, compared_type))
+ {
+ ms_debug("Element to connect [%s] has type [%s] \n", sink_element_name, src_pad_type);
+ GstPad *video_source_pad = gst_element_get_static_pad(ms_node->gst_element, source_pad_name);
+
+ gst_ghost_pad_set_target(GST_GHOST_PAD(video_source_pad), new_pad);
+ gst_pad_set_active(video_source_pad, TRUE);
+ __ms_generate_dots(ms_node->parent_streamer->pipeline);
+ }
+
+ gst_caps_unref(src_pad_caps);
+
+ MS_SAFE_UNREF(src_pad);
+ }
+ g_value_reset(&elem);
+ }
+ g_value_unset(&elem);
+ gst_iterator_free(bin_iterator);
+ MS_SAFE_GFREE(sink_element_name);
+ MS_SAFE_GFREE(source_pad_name);
+ MS_SAFE_FREE(new_pad_name);
+}
+#endif
+
+static void __ms_rtpbin_pad_added_cb(GstElement *src, GstPad *new_pad, gpointer user_data)
+{
+ GstCaps *src_pad_caps = NULL;
+ GstStructure *src_pad_struct = NULL;
+ GstPad *target_pad = NULL;
+
+ gchar *new_pad_name = NULL;
+ gchar *src_element_name = NULL;
+
+ media_streamer_node_s *ms_node = (media_streamer_node_s *)user_data;
+ ms_retm_if(ms_node == NULL, "Handle is NULL");
+
+ new_pad_name = gst_pad_get_name(new_pad);
+ src_element_name = gst_element_get_name(src);
+ ms_debug("Pad [%s] added on [%s]\n", new_pad_name, src_element_name);
+
+ target_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(new_pad));
+ src_pad_caps = gst_pad_query_caps(target_pad,NULL);
+ src_pad_struct = gst_caps_get_structure(src_pad_caps, 0);
+
+ const gchar *src_pad_type = gst_structure_get_string(src_pad_struct, "media");
+ ms_debug("type is [%s]", src_pad_type);
+
+ if(ms_node->parent_streamer == NULL)
+ {
+ ms_error("Node doesn`t have parent streamer:\n");
+ }
+ else
+ {
+ gchar *source_pad_name = NULL;
+ GstElement *sink_bin = NULL;
+ if(g_strrstr(src_pad_type, "video"))
+ {
+ source_pad_name = g_strdup_printf("%s_source", "video");
+ sink_bin = ms_node->parent_streamer->sink_video_bin;
+ }
+ else if(g_strrstr(src_pad_type, "audio"))
+ {
+ source_pad_name = g_strdup_printf("%s_source", "audio");
+ sink_bin = ms_node->parent_streamer->sink_audio_bin;
+ }
+
+ if(source_pad_name != NULL)
+ {
+ if(gst_object_get_parent(GST_OBJECT(sink_bin)) == NULL)
+ {
+ gst_bin_add(GST_BIN(ms_node->parent_streamer->pipeline), sink_bin);
+ }
+ gst_element_sync_state_with_parent(sink_bin);
+
+
+ GstPad *source_pad = gst_element_get_static_pad(ms_node->gst_element, source_pad_name);
+ gst_ghost_pad_set_target(GST_GHOST_PAD(source_pad), new_pad);
+ gst_pad_set_active(source_pad, TRUE);
+
+ GstPad *sink_pad = gst_bin_find_unlinked_pad(GST_BIN(sink_bin), GST_PAD_SINK);
+ if(sink_pad != NULL)
+ {
+ __ms_add_ghostpad(gst_pad_get_parent(sink_pad), "sink", sink_bin, "sink");
+ if (gst_element_link_pads(ms_node->gst_element, source_pad_name, sink_bin, "sink"))
+ {
+ __ms_element_set_state(ms_node->gst_element, GST_STATE_PLAYING);
+ __ms_generate_dots(ms_node->parent_streamer->pipeline, "playing");
+ }
+ else
+ {
+ ms_error("Failed to link [rtp_containeer].[%s] and [sink_bin].[sink]\n", source_pad_name);
+ }
+ MS_SAFE_UNREF(sink_pad);
+ }
+ MS_SAFE_UNREF(source_pad);
+ MS_SAFE_GFREE(source_pad_name);
+ }
+ }
+
+ gst_caps_unref(src_pad_caps);
+ MS_SAFE_UNREF(target_pad);
+ MS_SAFE_GFREE(new_pad_name);
+ MS_SAFE_GFREE(src_element_name);
+}
+
+int __ms_element_set_state(GstElement *gst_element, GstState gst_state)
+{
+ ms_retvm_if(gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ GstStateChangeReturn ret_state;
+ gchar *element_name = gst_element_get_name(gst_element);
+
+ ret_state = gst_element_set_state(gst_element, gst_state);
+ if(ret_state == GST_STATE_CHANGE_FAILURE)
+ {
+ ms_error("Failed to set element [%s] into %s state", element_name, _ms_state_to_string(gst_state));
+ MS_SAFE_GFREE(element_name);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ MS_SAFE_GFREE(element_name);
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+GstElement *__ms_element_create(const char *plugin_name, const char *name)
+{
+ ms_retvm_if(plugin_name == NULL, (GstElement*)NULL, "Error empty plugin name");
+ ms_info("Creating [%s] element", plugin_name);
+ return gst_element_factory_make(plugin_name, name);
+}
+
+GstElement *__ms_camera_element_create(const char *camera_plugin_name)
+{
+ ms_retvm_if(camera_plugin_name == NULL, (GstElement*)NULL, "Error empty camera plugin name");
+
+ gboolean gst_ret = FALSE;
+ GstElement *camera_bin = gst_bin_new("camera_src");
+ GstElement *camera_elem = __ms_element_create(camera_plugin_name, NULL);
+ GstElement *filter = __ms_element_create("capsfilter", NULL);
+ GstElement *scale = __ms_element_create("videoscale", NULL);
+ GstElement *videoconvert = __ms_element_create("videoconvert", NULL);
+ ms_retvm_if(!filter || !camera_elem || !camera_bin || !scale || !videoconvert , (GstElement*)NULL,
+ "Error: creating elements for camera bin");
+
+ GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT);
+ g_object_set (G_OBJECT (filter), "caps", videoCaps, NULL);
+ gst_caps_unref(videoCaps);
+
+ gst_bin_add_many(GST_BIN(camera_bin), camera_elem, filter, scale, videoconvert, NULL);
+ gst_ret = gst_element_link_many(camera_elem, filter, scale, videoconvert, NULL);
+ if (gst_ret != TRUE)
+ {
+ ms_error("Failed to link elements into camerabin");
+ MS_SAFE_UNREF(camera_bin);
+ }
+
+ __ms_add_ghostpad(videoconvert, "src", camera_bin, "src");
+
+ return camera_bin;
+}
+
+GstElement *__ms_video_encoder_element_create(dictionary *dict , media_format_mimetype_e mime)
+{
+ char *plugin_name = NULL;
+ char *format_prefix = NULL;
+
+ format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_DECODER);
+ GstElement *encoder_elem = __ms_element_create(plugin_name,NULL);
+ MS_SAFE_FREE(format_prefix);
+ MS_SAFE_FREE(plugin_name);
+
+ format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_PARSER);
+ GstElement *encoder_parser = __ms_element_create(plugin_name,NULL);
+ MS_SAFE_FREE(format_prefix);
+ MS_SAFE_FREE(plugin_name);
+
+ gboolean gst_ret = FALSE;
+ GstElement *encoder_bin = gst_bin_new("video_encoder");
+ GstElement *filter = __ms_element_create("capsfilter", NULL);
+ ms_retvm_if(!filter || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement*)NULL,
+ "Error: creating elements for video encoder bin");
+
+ format_prefix = g_strdup_printf("video/x-%s,stream-format=byte-stream,profile=high",
+ __ms_convert_mime_to_string(mime));
+ GstCaps *videoCaps = gst_caps_from_string(format_prefix);
+ g_object_set(G_OBJECT(filter), "caps", videoCaps, NULL);
+ MS_SAFE_FREE(format_prefix);
+
+ gst_caps_unref(videoCaps);
+
+ gst_bin_add_many(GST_BIN(encoder_bin), encoder_elem, filter, encoder_parser, NULL);
+ gst_ret = gst_element_link_many(encoder_elem, filter, encoder_parser, NULL);
+ if (gst_ret != TRUE)
+ {
+ ms_error("Failed to link elements into encoder_bin");
+ MS_SAFE_UNREF(encoder_bin);
+ }
+
+ __ms_add_ghostpad(encoder_parser, "src", encoder_bin, "src");
+ __ms_add_ghostpad(encoder_elem, "sink", encoder_bin, "sink");
+
+ return encoder_bin;
+}
+
+GstElement *__ms_video_decoder_element_create(dictionary *dict , media_format_mimetype_e mime)
+{
+ char *plugin_name = NULL;
+ char *format_prefix = NULL;
+ gboolean is_omx = FALSE;
+ GstElement *last_elem = NULL;
+
+ format_prefix = g_strdup_printf("%s:decoder", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_DECODER);
+ GstElement *decoder_elem = __ms_element_create(plugin_name,NULL);
+ MS_SAFE_FREE(format_prefix);
+ MS_SAFE_FREE(plugin_name);
+
+ format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_PARSER);
+ GstElement *decoder_parser = __ms_element_create(plugin_name,NULL);
+
+ if(mime == MEDIA_FORMAT_H264_SP)
+ {
+ g_object_set(G_OBJECT(decoder_parser), "config-interval", 5, NULL);
+ }
+
+ is_omx = g_strrstr(format_prefix, "omx");
+ MS_SAFE_FREE(format_prefix);
+ MS_SAFE_FREE(plugin_name);
+
+ gboolean gst_ret = FALSE;
+ GstElement *decoder_bin = gst_bin_new("video_decoder");
+ GstElement *decoder_queue = __ms_element_create("queue",NULL);
+ ms_retvm_if(!decoder_elem || !decoder_queue || !decoder_bin || !decoder_parser, (GstElement*)NULL,
+ "Error: creating elements for video decoder bin");
+
+ gst_bin_add_many(GST_BIN(decoder_bin), decoder_queue, decoder_elem, decoder_parser, NULL);
+ gst_ret = gst_element_link_many(decoder_queue, decoder_parser, decoder_elem, NULL);
+ if (gst_ret != TRUE)
+ {
+ ms_error("Failed to link elements into decoder_bin");
+ MS_SAFE_UNREF(decoder_bin);
+ return NULL;
+ }
+ last_elem = decoder_elem;
+
+ if(!is_omx)
+ {
+ GstElement *video_conv = __ms_element_create("videoconvert",NULL);
+ GstElement *video_scale = __ms_element_create("videoscale",NULL);
+ ms_retvm_if(!video_conv || !video_scale, (GstElement*)NULL,
+ "Error: creating elements for video decoder bin");
+ gst_bin_add_many(GST_BIN(decoder_bin), video_conv, video_scale, NULL);
+ gst_ret = gst_element_link_many(decoder_elem, video_conv, video_scale, NULL);
+ if (gst_ret != TRUE)
+ {
+ ms_error("Failed to link elements into decoder_bin");
+ MS_SAFE_UNREF(decoder_bin);
+ return NULL;
+ }
+ last_elem = video_scale;
+ }
+
+ __ms_add_ghostpad(last_elem, "src", decoder_bin, "src");
+ __ms_add_ghostpad(decoder_queue, "sink", decoder_bin, "sink");
+
+ return decoder_bin;
+}
+
+GstElement *__ms_audio_encoder_element_create(void)
+{
+ gboolean gst_ret = FALSE;
+ GstElement *audio_convert = __ms_element_create("audioconvert",NULL);
+ GstElement *audio_filter = __ms_element_create("capsfilter",NULL);
+ GstElement *audio_enc_bin = gst_bin_new("audio_encoder");
+ ms_retvm_if(!audio_convert || !audio_filter || !audio_enc_bin, (GstElement*)NULL,
+ "Error: creating elements for encoder bin");
+
+ GstCaps *audioCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
+ g_object_set(G_OBJECT(audio_filter), "caps", audioCaps, NULL);
+ gst_caps_unref(audioCaps);
+
+ gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_filter, NULL);
+ gst_ret = gst_element_link_many(audio_filter, audio_convert, NULL);
+ if (gst_ret != TRUE)
+ {
+ ms_error("Failed to link elements into decoder_bin");
+ MS_SAFE_UNREF(audio_enc_bin);
+ }
+
+ __ms_add_ghostpad(audio_convert, "src", audio_enc_bin, "src");
+ __ms_add_ghostpad(audio_filter, "sink", audio_enc_bin, "sink");
+
+ return audio_enc_bin;
+}
+
+GstElement *__ms_rtp_element_create(media_streamer_node_s *ms_node)
+{
+ ms_retvm_if(ms_node == NULL, (GstElement*)NULL, "Error empty rtp node Handle");
+
+ GstElement *rtp_container = gst_bin_new("rtp_container");
+ GstElement *rtp_elem = __ms_element_create("rtpbin", "rtpbin");
+ ms_retvm_if(!rtp_container || !rtp_elem, (GstElement*)NULL,
+ "Error: creating elements for rtp container");
+
+ gst_bin_add(GST_BIN(rtp_container), rtp_elem);
+ g_signal_connect (rtp_elem, "pad-added", G_CALLBACK (__ms_rtpbin_pad_added_cb), ms_node);
+
+ return rtp_container;
+}
+
+static gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node,
+ GstElement **rtp_elem, GstElement **rtcp_elem, const gchar *elem_name)
+{
+ gboolean ret = FALSE;
+ gchar *rtp_elem_name = NULL;
+ gchar *rtcp_elem_name = NULL;
+ gchar *plugin_name = NULL;
+
+ GstElement *rtpbin = gst_bin_get_by_name(GST_BIN(ms_node->gst_element), "rtpbin");
+
+ ms_retvm_if(!elem_name, FALSE, "Empty rtp element name.");
+
+ if(MS_ELEMENT_IS_SOURCE(elem_name))
+ {
+ plugin_name = g_strdup("udpsrc");
+ }
+ else if(MS_ELEMENT_IS_SINK(elem_name))
+ {
+ plugin_name = g_strdup("udpsink");
+ }
+ else
+ {
+ ms_error("Error: invalid parameter name [%s]", elem_name);
+ return FALSE;
+ }
+
+ rtp_elem_name = g_strdup_printf("%s_rtp", elem_name);
+ rtcp_elem_name = g_strdup_printf("%s_rtcp", elem_name);
+
+ // Find video udp rtp/rtcp element if it present.
+ *rtp_elem = gst_bin_get_by_name(GST_BIN(ms_node->gst_element), rtp_elem_name);
+ *rtcp_elem = gst_bin_get_by_name(GST_BIN(ms_node->gst_element), rtcp_elem_name);
+
+ // Create new udp element if it did not found.
+ if((NULL == *rtp_elem) && (NULL == *rtcp_elem))
+ {
+ *rtp_elem = __ms_element_create(plugin_name, rtp_elem_name);
+ *rtcp_elem = __ms_element_create(plugin_name, rtcp_elem_name);
+ }
+ else
+ {
+ //rtp/rtcp elements already into rtp bin.
+ MS_SAFE_GFREE(rtp_elem_name);
+ MS_SAFE_GFREE(rtcp_elem_name);
+ MS_SAFE_GFREE(plugin_name);
+ return TRUE;
+ }
+
+ gst_bin_add_many(GST_BIN(ms_node->gst_element),
+ *rtp_elem, *rtcp_elem, NULL);
+
+ if(MS_ELEMENT_IS_SINK(elem_name))
+ {
+ g_object_set(GST_OBJECT(*rtcp_elem), "sync", FALSE, NULL);
+ g_object_set(GST_OBJECT(*rtcp_elem), "async", FALSE, NULL);
+
+ if(MS_ELEMENT_IS_VIDEO(elem_name))
+ {
+ __ms_add_ghostpad(rtpbin, "send_rtp_sink_0", ms_node->gst_element, "video_sink");
+ ret = gst_element_link_pads(rtpbin, "send_rtp_src_0", *rtp_elem, "sink") &&
+ gst_element_link_pads(rtpbin, "send_rtcp_src_0",*rtcp_elem, "sink");
+ }
+ else
+ {
+ __ms_add_ghostpad(rtpbin, "send_rtp_sink_1", ms_node->gst_element, "audio_sink");
+ ret = gst_element_link_pads(rtpbin, "send_rtp_src_1", *rtp_elem, "sink") &&
+ gst_element_link_pads(rtpbin, "send_rtcp_src_1",*rtcp_elem, "sink");
+ }
+ }
+ else
+ {
+ if(MS_ELEMENT_IS_VIDEO(elem_name))
+ {
+ ret = gst_element_link_pads(*rtp_elem, "src", rtpbin, "recv_rtp_sink_0") &&
+ gst_element_link_pads (*rtcp_elem, "src", rtpbin, "recv_rtcp_sink_0");
+ __ms_add_ghostpad(NULL, NULL, ms_node->gst_element, "video_source");
+ }
+ else
+ {
+ ret = gst_element_link_pads(*rtp_elem, "src", rtpbin, "recv_rtp_sink_1") &&
+ gst_element_link_pads (*rtcp_elem, "src", rtpbin, "recv_rtcp_sink_1");
+ __ms_add_ghostpad(NULL, NULL, ms_node->gst_element, "audio_source");
+ }
+ }
+
+ if(!ret)
+ {
+ ms_error("Can not link [rtpbin] pad to [%s] pad, ret code [%d] ", rtp_elem, ret);
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ __ms_generate_dots(ms_node->gst_element, "rtp");
+ MS_SAFE_GFREE(rtp_elem_name);
+ MS_SAFE_GFREE(rtcp_elem_name);
+ MS_SAFE_GFREE(plugin_name);
+
+ return ret;
+}
+
+int __ms_rtp_set_param(
+ media_streamer_node_s *ms_node,
+ const gchar *param_key,
+ const gchar *param_value)
+{
+ ms_retvm_if(!ms_node && !ms_node->gst_element, MEDIA_STREAMER_ERROR_NONE, "Error: empty node");
+
+ gchar **tokens = NULL;
+ gchar *elem_name = NULL;
+ guint i = 0;
+ GstElement *rtp_elem = NULL;
+ GstElement *rtcp_elem = NULL;
+
+ tokens = g_strsplit(param_key,",",3);
+ ms_retvm_if(tokens == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Invalid rtp parameter line.");
+ elem_name = tokens[0];
+
+ if(FALSE == __ms_get_rtp_elements(ms_node, &rtp_elem, &rtcp_elem, elem_name))
+ {
+ ms_error("Error: invalid parameter [%s]", param_key);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ for(i = 1; (tokens && tokens[i]); i++)
+ {
+ ms_retvm_if(!rtp_elem || !rtcp_elem,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+ "Error: [%s] did not found or created into streamer", tokens[i]);
+
+ if(!g_strcmp0(tokens[i], "port"))
+ {
+ __ms_element_set_property(rtp_elem, tokens[i], param_value);
+ gchar *next_port = g_strdup(param_value);
+ next_port[strlen(next_port)-1] += 1;
+ __ms_element_set_property(rtcp_elem, tokens[i], next_port);
+ MS_SAFE_GFREE(next_port);
+ }
+ else if(!g_strcmp0(tokens[i], "host") && MS_ELEMENT_IS_SINK(elem_name))
+ {
+ __ms_element_set_property(rtp_elem, tokens[i], param_value);
+ __ms_element_set_property(rtcp_elem, tokens[i], param_value);
+ }
+ else if(!g_strcmp0(tokens[i], "format") && MS_ELEMENT_IS_SOURCE(elem_name))
+ {
+ __ms_element_set_property(rtp_elem, "caps", param_value);
+ }
+
+ }
+ g_strfreev(tokens);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_add_node_into_bin(media_streamer_s *ms_streamer,media_streamer_node_s *ms_node)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
+
+ ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]",
+ ms_node->name, ms_node->type, ms_node->subtype);
+
+ gchar *bin_name = NULL;
+ gboolean gst_ret = FALSE;
+
+ switch(ms_node->type)
+ {
+ case MEDIA_STREAMER_NODE_TYPE_SRC:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->src_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_SRC_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_SINK:
+ switch(ms_node->subtype)
+ {
+ case MEDIA_STREAMER_SINK_TYPE_SCREEN:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_SINK_TYPE_AUDIO:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_audio_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_AUDIO_SINK_BIN_NAME);
+ break;
+ default:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
+ break;
+ }
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->topology_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_TOPOLOGY_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_audio_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_AUDIO_SINK_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_audio_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_AUDIO_SINK_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER:
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_audio_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_AUDIO_SINK_BIN_NAME);
+ break;
+ default:
+ // Another elements will be add into topology bin
+ gst_ret = gst_bin_add(GST_BIN(ms_streamer->topology_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_TOPOLOGY_BIN_NAME);
+ break;
+ }
+
+ if(!gst_ret)
+ {
+ ms_error("Failed to add Element [%s] into [%s] bin.", ms_node->name, bin_name);
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ else
+ {
+ ms_info("Success added Element [%s] into [%s] bin.", ms_node->name, bin_name);
+ ret = MEDIA_STREAMER_ERROR_NONE;
+ }
+
+ MS_SAFE_GFREE(bin_name);
+
+ return ret;
+}
+
+
+static gboolean __ms_bus_cb(GstBus *bus, GstMessage *message, gpointer userdata)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ media_streamer_s *ms_streamer = (media_streamer_s*)userdata;
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_STATE, "Pipeline doesn`t exist");
+
+ /* Parse message */
+ if (message != NULL)
+ {
+ switch (GST_MESSAGE_TYPE(message))
+ {
+ case GST_MESSAGE_ERROR:
+ {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error (message, &err, &debug);
+
+ ms_error("[Source: %s] Error: %s", GST_OBJECT_NAME(GST_OBJECT_CAST(GST_ELEMENT(GST_MESSAGE_SRC (message)))), err->message);
+
+ MS_SAFE_FREE(err);
+ MS_SAFE_FREE(debug);
+ break;
+ }
+
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+ if (GST_MESSAGE_SRC (message) == GST_OBJECT (ms_streamer->pipeline))
+ {
+ GstState state_old, state_new, state_pending;
+ gchar *state_transition_name;
+
+ gst_message_parse_state_changed (message, &state_old, &state_new, &state_pending);
+ ms_info ("GST_MESSAGE_STATE_CHANGED: [%s] %s -> %s\n",
+ gst_object_get_name(GST_MESSAGE_SRC(message)),
+ _ms_state_to_string(state_old),
+ _ms_state_to_string(state_new));
+
+ state_transition_name = g_strdup_printf ("%s_%s",
+ gst_element_state_get_name (state_old),
+ gst_element_state_get_name (state_new));
+
+ __ms_generate_dots(ms_streamer->pipeline, state_transition_name);
+
+ MS_SAFE_GFREE (state_transition_name);
+
+ if (state_old == GST_STATE_NULL && state_new == GST_STATE_READY)
+ {
+ ms_info("[Success] GST_STATE_NULL => GST_STATE_READY");
+
+ /* Pause Media_Streamer */
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
+ if(ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("ERROR - Pause pipeline");
+ return FALSE;
+ }
+ }
+
+ if (state_old == GST_STATE_READY && state_new == GST_STATE_PAUSED)
+ {
+ ms_info("[Success] GST_STATE_READY => GST_STATE_PAUSED");
+
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PLAYING);
+ if(ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("ERROR - Play Pipeline");
+ return FALSE;
+ }
+ }
+ }
+ break;
+ }
+
+ case GST_MESSAGE_EOS:
+ {
+ ms_info("GST_MESSAGE_EOS end-of-stream");
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
+ if(ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("ERROR - Pause Pipeline");
+ return FALSE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return TRUE;
+}
+
+int __ms_pipeline_create(media_streamer_s *ms_streamer)
+{
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ gst_init(NULL, NULL);
+
+ ms_streamer->pipeline = gst_pipeline_new(MEDIA_STREAMER_PIPELINE_NAME);
+ ms_retvm_if(ms_streamer->pipeline == NULL,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error creating pipeline");
+
+ ms_streamer->bus = gst_pipeline_get_bus(GST_PIPELINE(ms_streamer->pipeline));
+ ms_retvm_if(ms_streamer->bus == NULL,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error getting the bus of the pipeline");
+
+ ms_streamer->bus_watcher = gst_bus_add_watch (ms_streamer->bus, (GstBusFunc)__ms_bus_cb, ms_streamer);
+
+ ms_streamer->src_bin = gst_bin_new(MEDIA_STREAMER_SRC_BIN_NAME);
+ ms_retvm_if(ms_streamer->src_bin == NULL,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error creating Src bin");
+
+// g_signal_connect(ms_streamer->src_bin, "element-added", G_CALLBACK(__src_bin_element_added_cb), ms_streamer);
+
+ ms_streamer->sink_video_bin = gst_bin_new(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
+ ms_retvm_if(ms_streamer->sink_video_bin == NULL,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error creating Sink bin");
+// g_signal_connect(ms_streamer->sink_bin, "element-added", G_CALLBACK(__sink_bin_element_added_cb), ms_streamer);
+
+ ms_streamer->sink_audio_bin = gst_bin_new(MEDIA_STREAMER_AUDIO_SINK_BIN_NAME);
+ ms_retvm_if(ms_streamer->sink_audio_bin == NULL,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error creating Audio Sink bin");
+
+ ms_streamer->topology_bin = gst_bin_new(MEDIA_STREAMER_TOPOLOGY_BIN_NAME);
+ ms_retvm_if(ms_streamer->topology_bin == NULL,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error creating Topology bin");
+// g_signal_connect(ms_streamer->topology_bin, "element-added", G_CALLBACK(__bin_element_added_cb), ms_streamer);
+
+ gst_bin_add_many(GST_BIN(ms_streamer->pipeline), ms_streamer->src_bin,
+ ms_streamer->topology_bin, NULL);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static GstCaps *__ms_create_caps_from_fmt(media_format_h fmt)
+{
+ GstCaps *caps = NULL;
+ media_format_mimetype_e mime;
+ gchar *format_name = NULL;
+ int width;
+ int height;
+ int avg_bps;
+ int max_bps;
+ int channel;
+ int samplerate;
+ int bit;
+
+ if (media_format_get_video_info(fmt, &mime, &width, &height, &avg_bps, &max_bps) == MEDIA_PACKET_ERROR_NONE)
+ {
+
+ ms_info("Creating video Caps from media format [width=%d, height=%d, bps=%d, mime=%d]",
+ width, height, avg_bps, mime);
+
+ if (mime & MEDIA_FORMAT_RAW)
+ {
+ format_name = g_strdup(__ms_convert_mime_to_string(mime));
+ caps = gst_caps_new_simple("video/x-raw",
+// "framerate", GST_TYPE_FRACTION, max_bps, avg_bps,
+ "format", G_TYPE_STRING, format_name,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height, NULL);
+ }
+ else
+ {
+ //mime & MEDIA_FORMAT_ENCODED
+ format_name = g_strdup_printf("video/x-%s", __ms_convert_mime_to_string(mime));
+ caps = gst_caps_new_simple(format_name,
+ "framerate", GST_TYPE_FRACTION, max_bps, avg_bps,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height, NULL);
+ }
+
+ }
+ else if (media_format_get_audio_info(fmt, &mime, &channel, &samplerate, &bit, &avg_bps) == MEDIA_PACKET_ERROR_NONE)
+ {
+ ms_info("Creating audio Caps from media format [channel=%d, samplerate=%d, bit=%d, avg_bps=%d, mime=%d]",
+ channel, samplerate, bit, avg_bps, mime);
+
+ if (mime & MEDIA_FORMAT_RAW)
+ {
+ format_name = g_strdup(__ms_convert_mime_to_string(mime));
+ caps = gst_caps_new_simple("audio/x-raw",
+ "channels", G_TYPE_INT, channel,
+ "format", G_TYPE_STRING, format_name,
+ "rate", G_TYPE_INT, samplerate, NULL);
+ }
+ else
+ {
+ ms_error("Encoded audio formats does not supported yet.");
+ }
+ }
+ else
+ {
+ ms_error("Failed getting media info from fmt.");
+ }
+ MS_SAFE_GFREE(format_name);
+
+ return caps;
+}
+
+int __ms_element_set_fmt(media_streamer_node_s *node, media_format_h fmt)
+{
+ GstCaps *caps = NULL;
+ GObject *obj = NULL;
+ GValue value = G_VALUE_INIT;
+ caps = __ms_create_caps_from_fmt(fmt);
+ ms_retvm_if(caps == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Fail creating caps from fmt.");
+
+ obj = __ms_get_property_owner(node->gst_element, "caps", &value);
+ gst_value_set_caps(&value, caps);
+ g_object_set_property(obj, "caps", &value);
+ gst_caps_unref(caps);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
--- /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 <media_streamer_node.h>
+#include <media_streamer_util.h>
+#include <media_streamer_gst.h>
+
+int __ms_node_create(media_streamer_node_s *node,
+ media_format_h in_fmt,
+ media_format_h out_fmt)
+{
+ ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ dictionary *dict = NULL;
+ char *plugin_name = NULL;
+ media_format_mimetype_e mime;
+
+ if (MEDIA_FORMAT_ERROR_NONE != media_format_get_video_info(out_fmt, &mime, NULL, NULL, NULL, NULL))
+ {
+ media_format_get_audio_info(out_fmt, &mime, NULL, NULL, NULL, NULL);
+ }
+ char* format_prefix = NULL;
+
+ __ms_load_ini_dictionary(&dict);
+
+ switch(node->type)
+ {
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER:
+ format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict,
+ format_prefix, DEFAULT_VIDEO_ENCODER);
+ node->gst_element = __ms_video_encoder_element_create(dict, mime);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER:
+ format_prefix = g_strdup_printf("%s:decoder", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict,
+ format_prefix, DEFAULT_VIDEO_DECODER);
+ node->gst_element = __ms_video_decoder_element_create(dict, mime);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_PARSER:
+ format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict,
+ format_prefix, DEFAULT_VIDEO_PARSER);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_FILTER:
+ node->gst_element = __ms_element_create("capsfilter", NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY:
+ format_prefix = g_strdup_printf("%s:rtppay", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict,
+ format_prefix, DEFAULT_VIDEO_RTPPAY);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY:
+ plugin_name = __ms_ini_get_string(dict,
+ "audio-raw:rtppay", DEFAULT_AUDIO_RTPPAY);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY:
+ format_prefix = g_strdup_printf("%s:rtpdepay", __ms_convert_mime_to_string(mime));
+ plugin_name = __ms_ini_get_string(dict,
+ format_prefix, DEFAULT_VIDEO_RTPDEPAY);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY:
+ plugin_name = __ms_ini_get_string(dict,
+ "audio-raw:rtpdepay", DEFAULT_AUDIO_RTPPAY);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_RTP:
+ node->gst_element = __ms_rtp_element_create(node);
+ node->set_param = (media_streamer_node_set_param)__ms_rtp_set_param;
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_QUEUE:
+ node->gst_element = __ms_element_create(DEFAULT_QUEUE, NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER:
+ node->gst_element = __ms_audio_encoder_element_create();
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER:
+ node->gst_element = __ms_element_create("videoconvert", NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER:
+ node->gst_element = __ms_element_create("audioconvert", NULL);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE:
+ node->gst_element = __ms_element_create("audioresample", NULL);
+ break;
+ default:
+ ms_error( "Error: invalid node Type [%d]",node->type);
+ break;
+ }
+
+ ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating GstElement");
+
+ node->name = gst_element_get_name(node->gst_element);
+
+ MS_SAFE_FREE(plugin_name);
+ MS_SAFE_FREE(format_prefix);
+ __ms_destroy_ini_dictionary(dict);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+
+int __ms_src_node_create(media_streamer_node_s *node)
+{
+ ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ dictionary *dict = NULL;
+ char *plugin_name = NULL;
+
+ __ms_load_ini_dictionary(&dict);
+
+ switch(node->subtype)
+ {
+ case MEDIA_STREAMER_SRC_TYPE_FILE:
+ ms_error("Error: not implemented yet");
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_RTSP:
+ node->gst_element = __ms_element_create(DEFAULT_UDP_SOURCE, NULL);
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_HTTP:
+ ms_error("Error: not implemented yet");
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_CAMERA:
+ plugin_name = __ms_ini_get_string(dict,
+ "sources:camera_source",DEFAULT_CAMERA_SOURCE);
+ node->gst_element = __ms_camera_element_create(plugin_name);
+
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_AUDIO_CAPTURE:
+ plugin_name = __ms_ini_get_string(dict,
+ "sources:audio_source",DEFAULT_AUDIO_SOURCE);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_VIDEO_CAPTURE:
+ plugin_name = __ms_ini_get_string(dict,
+ "sources:video_source",DEFAULT_VIDEO_SOURCE);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_VIDEO_TEST:
+ node->gst_element = __ms_element_create(DEFAULT_VIDEO_TEST_SOURCE, NULL);
+ g_object_set (G_OBJECT (node->gst_element), "is-live", true, NULL);
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_AUDIO_TEST:
+ node->gst_element = __ms_element_create(DEFAULT_AUDIO_TEST_SOURCE, NULL);
+ break;
+ case MEDIA_STREAMER_SRC_TYPE_CUSTOM:
+ ms_error("Error: not implemented yet");
+ break;
+ default:
+ ms_error( "Error: invalid Src node Type [%d]",node->subtype);
+ break;
+ }
+
+ ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating GstElement");
+ node->name = gst_element_get_name(node->gst_element);
+
+ MS_SAFE_FREE(plugin_name);
+ __ms_destroy_ini_dictionary(dict);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_sink_node_create(media_streamer_node_s *node)
+{
+ ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ dictionary *dict = NULL;
+ char *plugin_name = NULL;
+
+ __ms_load_ini_dictionary(&dict);
+
+ switch(node->subtype)
+ {
+ case MEDIA_STREAMER_SINK_TYPE_FILE:
+ ms_error("Error: not implemented yet");
+ break;
+ case MEDIA_STREAMER_SINK_TYPE_RTSP:
+ node->gst_element = __ms_element_create(DEFAULT_UDP_SINK, NULL);
+ break;
+ case MEDIA_STREAMER_SINK_TYPE_HTTP:
+ ms_error("Error: not implemented yet");
+ break;
+ case MEDIA_STREAMER_SINK_TYPE_AUDIO:
+ plugin_name = __ms_ini_get_string(dict,
+ "sinks:audio_sink",DEFAULT_AUDIO_SINK);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_SINK_TYPE_SCREEN:
+ plugin_name = __ms_ini_get_string(dict,
+ "sinks:video_sink",DEFAULT_VIDEO_SINK);
+ node->gst_element = __ms_element_create(plugin_name, NULL);
+ break;
+ case MEDIA_STREAMER_SINK_TYPE_FAKE:
+ node->gst_element = __ms_element_create(DEFAULT_FAKE_SINK, NULL);
+ break;
+ case MEDIA_STREAMER_SINK_TYPE_CUSTOM:
+
+ break;
+ default:
+ ms_error( "Error: invalid Sink node Type [%d]",node->subtype);
+ break;
+ }
+
+ ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating GstElement");
+ node->name = gst_element_get_name(node->gst_element);
+
+ MS_SAFE_FREE(plugin_name);
+ __ms_destroy_ini_dictionary(dict);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+void __ms_node_destroy(void *data)
+{
+ char *node_name = NULL;
+ media_streamer_node_s *node = (media_streamer_node_s*)data;
+ ms_retm_if(node == NULL, "Empty value while deleting element from table");
+
+ node_name = g_strdup(node->name);
+ MS_SAFE_UNREF(node->gst_element);
+ MS_SAFE_FREE(node->name);
+
+ ms_info("Node [%s] destroyed", node_name);
+ MS_SAFE_FREE(node_name);
+}
+
+void __ms_node_insert_into_table(GHashTable *nodes_table,
+ media_streamer_node_s *ms_node)
+{
+ if(g_hash_table_contains(nodes_table,ms_node->name))
+ {
+ ms_debug( "Current Node [%s] already added", ms_node->name);
+ return;
+ }
+ g_hash_table_insert(nodes_table,(gpointer)ms_node->name,(gpointer)ms_node);
+ ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]",
+ ms_node->name, ms_node->type, ms_node->subtype);
+}
+
+int __ms_node_remove_from_table(GHashTable *nodes_table,
+ media_streamer_node_s *ms_node)
+{
+ ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
+
+ gboolean g_ret = g_hash_table_remove(nodes_table, ms_node->name);
+ ms_retvm_if(g_ret != TRUE, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
+ "Error while removing element from table");
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static void __params_foreach_cb(const char *key,
+ const int type,
+ const bundle_keyval_t *kv,
+ void *user_data)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ media_streamer_node_s *ms_node = (media_streamer_node_s*)user_data;
+ ms_retm_if(ms_node == NULL, "Handle is NULL");
+
+ void *basic_val = NULL;
+ size_t basic_size = 0;
+
+ ms_info("Try to add parameter [%s] with type [%d] to the node [%s].", key, type, ms_node->name);
+
+ if(!bundle_keyval_type_is_array((bundle_keyval_t *)kv))
+ {
+ bundle_keyval_get_basic_val((bundle_keyval_t *)kv, &basic_val, &basic_size);
+ ms_info("Read param value[%s] with size [%d].", (gchar*)basic_val, basic_size);
+
+ if(ms_node->set_param != NULL)
+ {
+ ret = ms_node->set_param(ms_node, (gchar*)key, (gchar*)basic_val);
+ }
+ else
+ {
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ }
+ else
+ {
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ms_retm_if(ret != MEDIA_STREAMER_ERROR_NONE,
+ "Error while adding param [%s,%s] to the node [%s]",
+ key, type, ms_node->name);
+}
+
+int __ms_node_read_params_from_bundle (media_streamer_node_s *node,
+ bundle *param_list)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ bundle_foreach(param_list, __params_foreach_cb, (void*)node);
+ return ret;
+}
+
+int __ms_node_write_params_into_bundle (media_streamer_node_s *node,
+ bundle *param_list)
+{
+ GParamSpec **property_specs;
+ guint num_properties, i;
+ char *string_val = NULL;
+
+ property_specs = g_object_class_list_properties
+ (G_OBJECT_GET_CLASS(node->gst_element), &num_properties);
+
+ if (num_properties <= 0)
+ {
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ms_info("Getting parameter of the Node [%s]", node->name );
+
+ for (i = 0; i < num_properties; i++)
+ {
+ GValue value = { 0, };
+ GParamSpec *param = property_specs[i];
+
+ g_value_init(&value, param->value_type);
+ if (param->flags & G_PARAM_READWRITE)
+ {
+ g_object_get_property(G_OBJECT(node->gst_element), param->name, &value);
+ }
+ else
+ {
+ // Skip properties which user can not change.
+ continue;
+ }
+
+ ms_info("%-20s: %s\n", g_param_spec_get_name(param), g_param_spec_get_blurb(param));
+
+ switch(G_VALUE_TYPE(&value))
+ {
+ case G_TYPE_STRING:
+ bundle_add_str(param_list, g_param_spec_get_name(param), g_value_get_string(&value));
+ ms_info("Got string value: [%s]", g_value_get_string(&value));
+ break;
+
+ case G_TYPE_BOOLEAN:
+ string_val = g_strdup_printf("%s", g_value_get_boolean(&value) ? "true" : "false");
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got boolean value: [%s]", string_val);
+ break;
+
+ case G_TYPE_ULONG:
+ {
+ GParamSpecULong *pulong = G_PARAM_SPEC_ULONG(param);
+ string_val = g_strdup_printf("%lu", g_value_get_ulong(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got ulong value: [%s], range: %lu - %lu (default %s)",
+ string_val, pulong->minimum, pulong->maximum);
+ break;
+ }
+
+ case G_TYPE_LONG:
+ {
+ GParamSpecLong *plong = G_PARAM_SPEC_LONG(param);
+ string_val = g_strdup_printf("%ld", g_value_get_long(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got long value: [%s], range: %ld - %ld (default %s)",
+ string_val, plong->minimum, plong->maximum);
+ break;
+ }
+
+ case G_TYPE_UINT:
+ {
+ GParamSpecUInt *puint = G_PARAM_SPEC_UINT(param);
+ string_val = g_strdup_printf("%u", g_value_get_uint(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got uint value: [%s], range: %u - %u",
+ string_val, puint->minimum, puint->maximum);
+ break;
+ }
+
+ case G_TYPE_INT:
+ {
+ GParamSpecInt *pint = G_PARAM_SPEC_INT(param);
+ string_val = g_strdup_printf("%d", g_value_get_int(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got int value: [%s], range: %d - %d",
+ string_val, pint->minimum, pint->maximum);
+ break;
+ }
+
+ case G_TYPE_UINT64:
+ {
+ GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64(param);
+ string_val = g_strdup_printf("%" G_GUINT64_FORMAT, g_value_get_uint64(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got uint64 value: [%s], range: %" G_GUINT64_FORMAT "- %" G_GUINT64_FORMAT,
+ string_val, puint64->minimum, puint64->maximum);
+ break;
+ }
+
+ case G_TYPE_INT64:
+ {
+ GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64(param);
+ string_val = g_strdup_printf("%" G_GINT64_FORMAT, g_value_get_int64(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got uint64 value: [%s], range: %" G_GINT64_FORMAT "- %" G_GINT64_FORMAT,
+ string_val, pint64->minimum, pint64->maximum);
+ break;
+ }
+
+ case G_TYPE_FLOAT:
+ {
+ GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT(param);
+ string_val = g_strdup_printf("%15.7g", g_value_get_float(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got float value: [%s], range:%15.7g -%15.7g",
+ string_val, pfloat->minimum, pfloat->maximum);
+ break;
+ }
+
+ case G_TYPE_DOUBLE:
+ {
+ GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE(param);
+ string_val = g_strdup_printf("%15.7g", g_value_get_double(&value));
+ bundle_add_str(param_list, g_param_spec_get_name(param), string_val);
+ ms_info("Got double value: [%s], range:%15.7g -%15.7g",
+ string_val, pdouble->minimum, pdouble->maximum);
+ break;
+ }
+
+ default:
+ ms_info("Got unknown type with param->value_type [%d]", param->value_type);
+ break;
+
+ MS_SAFE_FREE(string_val);
+ }
+ }
+ return MEDIA_STREAMER_ERROR_NONE;
+}
--- /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 "media_streamer_priv.h"
+#include "media_streamer_util.h"
+#include "media_streamer_node.h"
+#include "media_streamer_gst.h"
+
+int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e state)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ media_streamer_state_e previous_state= ms_streamer->state;
+ ms_retvm_if(previous_state == state, MEDIA_STREAMER_ERROR_NONE, "Media streamer already in this state");
+
+ switch(state)
+ {
+ case MEDIA_STREAMER_STATE_NONE:
+ /*
+ * Media streamer must be in IDLE state
+ * Unlink and destroy all bins and elements.
+ */
+ if (previous_state != MEDIA_STREAMER_STATE_IDLE)
+ {
+ __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
+ }
+ break;
+ case MEDIA_STREAMER_STATE_IDLE:
+ /*
+ * Unlink all gst_elements, set pipeline into state NULL
+ */
+ if (previous_state != MEDIA_STREAMER_STATE_NONE)
+ {
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL);
+ }
+ break;
+ case MEDIA_STREAMER_STATE_READY:
+ break;
+ case MEDIA_STREAMER_STATE_PLAYING:
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PLAYING);
+ break;
+ case MEDIA_STREAMER_STATE_PAUSED:
+ ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
+ break;
+ case MEDIA_STREAMER_STATE_SEEKING:
+ default:
+ {
+ ms_info("Error: invalid state [%s]", state);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ }
+
+ if(ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Failed change state");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ms_streamer->state = state;
+ ms_info("Media streamer state changed to [%d]", state);
+ return ret;
+}
+
+int __ms_create(media_streamer_s *ms_streamer)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ ret = __ms_load_ini_settings(&ms_streamer->ini);
+ ms_retvm_if(ret!=MEDIA_STREAMER_ERROR_NONE,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error load ini file");
+
+ ms_streamer->nodes_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __ms_node_destroy);
+ ms_retvm_if(ms_streamer->nodes_table == NULL,
+ MEDIA_STREAMER_ERROR_INVALID_OPERATION,"Error creating hash table");
+
+ ret = __ms_pipeline_create(ms_streamer);
+ if (ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error while creating media streamer pipeline.");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ms_info("Media streamer pipeline created successfully.");
+
+ return ret;
+}
+
+static void __node_remove_cb(gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s*)user_data;
+ ms_retm_if(ms_streamer == NULL, "Handle is NULL");
+
+ media_streamer_node_s *ms_node = (media_streamer_node_s*)value;
+ ms_retm_if(ms_node == NULL, "Handle is NULL");
+
+ ms_info("Try to delete [%s] node from streamer, node type/subtype [%d/%d]",
+ ms_node->name, ms_node->type, ms_node->subtype);
+
+ gchar *bin_name = NULL;
+ gboolean gst_ret = FALSE;
+
+ __ms_element_set_state(ms_node->gst_element, GST_STATE_NULL);
+ gst_object_ref(ms_node->gst_element);
+
+ switch(ms_node->type)
+ {
+ case MEDIA_STREAMER_NODE_TYPE_SRC:
+ gst_ret = gst_bin_remove(GST_BIN(ms_streamer->src_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_SRC_BIN_NAME);
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_SINK:
+ gst_ret = gst_bin_remove(GST_BIN(ms_streamer->sink_video_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME);
+ break;
+ default:
+ gst_ret = gst_bin_remove(GST_BIN(ms_streamer->topology_bin),ms_node->gst_element);
+ bin_name = g_strdup(MEDIA_STREAMER_TOPOLOGY_BIN_NAME);
+ break;
+ }
+
+ if(!gst_ret)
+ {
+ ms_error("Failed to remove Element [%s] from bin [%s]", ms_node->name, bin_name);
+ }
+ else
+ {
+ ms_info("Success removed Element [%s] from bin [%s]", ms_node->name, bin_name);
+ }
+
+ MS_SAFE_GFREE(bin_name);
+
+}
+
+
+void __ms_streamer_destroy(media_streamer_s *ms_streamer)
+{
+ if(__ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_NONE) != MEDIA_STREAMER_ERROR_NONE)
+ {
+ ms_error("Error: can not set state [%d]", MEDIA_STREAMER_ERROR_INVALID_OPERATION);
+ }
+
+ gst_element_unlink_many(ms_streamer->src_bin,
+ ms_streamer->topology_bin,
+ ms_streamer->sink_video_bin, NULL);
+
+ g_hash_table_foreach(ms_streamer->nodes_table, __node_remove_cb,(gpointer)ms_streamer);
+
+ if(ms_streamer->src_bin && !gst_bin_remove(GST_BIN(ms_streamer->pipeline),ms_streamer->src_bin))
+ {
+ ms_error("Failed to remove src_bin from pipeline");
+ }
+ else
+ {
+ ms_info("src_bin removed from pipeline");
+ }
+
+ if(ms_streamer->sink_video_bin && !gst_bin_remove(GST_BIN(ms_streamer->pipeline),ms_streamer->sink_video_bin))
+ {
+ ms_error("Failed to remove sink_bin from pipeline");
+ }
+ else
+ {
+ ms_info("sink_bin removed from pipeline");
+ }
+
+
+ if(ms_streamer->topology_bin && !gst_bin_remove(GST_BIN(ms_streamer->pipeline),ms_streamer->topology_bin))
+ {
+ ms_error("Failed to remove topology_bin from pipeline");
+ }
+ else
+ {
+ ms_info("topology_bin removed from pipeline");
+ }
+
+
+ ms_streamer->state = MEDIA_STREAMER_STATE_NONE;
+
+ MS_TABLE_SAFE_UNREF(ms_streamer->nodes_table);
+ MS_SAFE_UNREF(ms_streamer->bus);
+ MS_SAFE_UNREF(ms_streamer->pipeline);
+
+ MS_SAFE_FREE(ms_streamer);
+
+// gst_deinit();
+}
--- /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 __MEDIA_STREAMER_UTIL_C__
+#define __MEDIA_STREAMER_UTIL_C__
+
+#include <glib/gstdio.h>
+
+#include <media_streamer.h>
+#include <media_streamer_util.h>
+
+#ifdef MEDIA_STREAMER_DEFAULT_INI
+ static gboolean __ms_generate_default_ini(void);
+#endif
+
+static void __ms_check_ini_status(void);
+
+gchar* __ms_ini_get_string(dictionary *dict,
+ const char *ini_path, char *default_str)
+{
+ gchar *result_str = NULL;
+
+ ms_retvm_if(ini_path == NULL, NULL, "Invalid ini path");
+
+ if (dict == NULL)
+ {
+ result_str = g_strdup(default_str);
+ }
+ else
+ {
+ gchar *str = NULL;
+ str = iniparser_getstring(dict, ini_path, default_str);
+ if (str &&
+ (strlen(str) > 0) &&
+ (strlen(str) < MEDIA_STREAMER_INI_MAX_STRLEN))
+ {
+ result_str = g_strdup(str);
+ }
+ else
+ {
+ result_str = g_strdup(default_str);
+ }
+ }
+ return result_str;
+}
+
+gboolean __ms_load_ini_dictionary(dictionary **dict)
+{
+ ms_retvm_if(dict == NULL, FALSE, "Handle is NULL");
+
+ __ms_check_ini_status();
+
+ dictionary *ms_dict = NULL;
+
+ /* loading existing ini file */
+ ms_dict = iniparser_load(MEDIA_STREAMER_INI_DEFAULT_PATH);
+
+ /* if no file exists. create one with set of default values */
+ if (!ms_dict)
+ {
+#ifdef MEDIA_STREAMER_DEFAULT_INI
+ ms_debug("No inifile found. Media streamer will create default inifile.");
+ if (FALSE == __ms_generate_default_ini())
+ {
+ ms_debug("Creating default .ini file failed. Media-streamer will use default values.");
+ }
+ else
+ {
+ /* load default ini */
+ ms_dict = iniparser_load(MEDIA_STREAMER_INI_DEFAULT_PATH);
+ }
+#else
+ ms_debug("No ini file found.");
+ return FALSE;
+#endif
+ }
+
+ *dict = ms_dict;
+ return TRUE;
+}
+
+gboolean __ms_destroy_ini_dictionary(dictionary *dict)
+{
+ ms_retvm_if(dict == NULL, FALSE, "Handle is null");
+
+ /* free dict as we got our own structure */
+ iniparser_freedict(dict);
+
+ return TRUE;
+}
+
+int __ms_load_ini_settings(media_streamer_ini_t *ini)
+{
+ dictionary *dict = NULL;
+
+ /* get ini values */
+ memset(ini, 0, sizeof(media_streamer_ini_t));
+
+ if (__ms_load_ini_dictionary(&dict))
+ {
+ /* general */
+ ini->generate_dot = iniparser_getboolean(dict, "general:generate dot", DEFAULT_GENERATE_DOT);
+ if (ini->generate_dot == TRUE)
+ {
+ gchar *dot_path = iniparser_getstring(dict, "general:dot dir" , MEDIA_STREAMER_DEFAULT_DOT_DIR);
+ ms_debug("generate_dot is TRUE, dot file will be stored into %s",dot_path);
+ g_setenv ("GST_DEBUG_DUMP_DOT_DIR", dot_path, FALSE);
+ }
+
+ }
+ else /* if dict is not available just fill the structure with default value */
+ {
+ ms_debug("failed to load ini. using hardcoded default");
+
+ /* general settings*/
+ ini->generate_dot = DEFAULT_GENERATE_DOT;
+ }
+
+ __ms_destroy_ini_dictionary(dict);
+
+ /* general */
+ ms_debug("generate_dot : %d\n", ini->generate_dot);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static void __ms_check_ini_status(void)
+{
+ FILE *fp = fopen(MEDIA_STREAMER_INI_DEFAULT_PATH, "r");
+ int file_size = 0;
+ int status = 0;
+
+ if(fp == NULL)
+ {
+ ms_debug("Failed to get media streamer ini file.");
+ }
+ else
+ {
+ fseek(fp, 0, SEEK_END);
+ file_size = ftell(fp);
+ fclose(fp);
+ if (file_size < 5)
+ {
+ ms_debug("media_streamer.ini file size=%d, Corrupted! Removed", file_size);
+ status = g_remove(MEDIA_STREAMER_INI_DEFAULT_PATH);
+ if (status == -1)
+ {
+ ms_error("failed to delete corrupted ini");
+ }
+ }
+ }
+}
+
+#ifdef MEDIA_STREAMER_DEFAULT_INI
+static gboolean __ms_generate_default_ini(void)
+{
+ FILE *fp = NULL;
+ gchar *default_ini = MEDIA_STREAMER_DEFAULT_INI;
+
+
+ /* create new file */
+ fp = fopen(MEDIA_STREAMER_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
+
+const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime)
+{
+ switch(mime)
+ {
+ case MEDIA_FORMAT_I420:
+ return "I420";
+ case MEDIA_FORMAT_YV12:
+ return "YV12";
+ case MEDIA_FORMAT_H263:
+ return "h263";
+ case MEDIA_FORMAT_H264_HP:
+ case MEDIA_FORMAT_H264_MP:
+ case MEDIA_FORMAT_H264_SP:
+ return "h264";
+ case MEDIA_FORMAT_PCM:
+ return "S16BE";
+ default:
+ ms_error("Invalid or Unsupported media format [%d].", mime);
+ return NULL;
+ break;
+ }
+
+}
+#endif
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(fw_test "${fw_name}-test")
+
+INCLUDE_DIRECTORIES(../include)
+
+link_directories(${CMAKE_SOURCE_DIR}/../)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_test} REQUIRED glib-2.0)
+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-media-streamer ${${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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include <media_streamer.h>
+
+typedef enum
+{
+ MENU_STATE_UNKNOWN = 0,
+ MENU_STATE_MAIN_MENU,
+ MENU_STATE_BROADCAST_MENU,
+ MENU_STATE_VOIP_MENU,
+ MENU_STATE_PRESET_MENU
+} menu_state_e;
+
+typedef enum
+{
+ SUBMENU_STATE_UNKNOWN = 0,
+ SUBMENU_STATE_GETTING_IP,
+ SUBMENU_STATE_AUTOPLUG = 3,
+ SUBMENU_STATE_FORMAT
+} submenu_state_e;
+
+#define SECOND_VOIP_MASK 0x8
+#define DOUBLE_STREAMER_MASK 0x10
+
+typedef enum
+{
+ PRESET_UNKNOWN = 0,
+ PRESET_RTP_STREAMER = 0x01,
+ PRESET_RTP_CLIENT = 0x02,
+ PRESET_VOIP = PRESET_RTP_STREAMER | PRESET_RTP_CLIENT,
+ PRESET_VOIP_2 = PRESET_VOIP | SECOND_VOIP_MASK,
+ PRESET_DOUBLE_VOIP_SERVER = PRESET_RTP_STREAMER | DOUBLE_STREAMER_MASK,
+ PRESET_DOUBLE_VOIP_SERVER_2 = PRESET_RTP_STREAMER | DOUBLE_STREAMER_MASK | SECOND_VOIP_MASK,
+ PRESET_DOUBLE_VOIP_CLIENT = PRESET_RTP_CLIENT | DOUBLE_STREAMER_MASK,
+ PRESET_DOUBLE_VOIP_CLIENT_2 = PRESET_RTP_CLIENT | DOUBLE_STREAMER_MASK | SECOND_VOIP_MASK
+} preset_type_e;
+
+#define PACKAGE "media_streamer_test"
+/*---------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS: |
+---------------------------------------------------------------------------*/
+
+static media_streamer_h g_media_streamer;
+static media_streamer_h g_media_streamer_2;
+static media_streamer_h current_media_streamer = &g_media_streamer;
+
+//#define ONE_DEVICE_TEST
+#define MAX_STRING_LEN 2048
+#define DEFAULT_IP_ADDR "127.0.0.1"
+
+#define VIDEO_PORT 5000
+#define AUDIO_PORT 6000
+
+//#define DISABLE_AUDIO
+//#define DISABLE_VIDEO
+
+/*---------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS: |
+---------------------------------------------------------------------------*/
+GMainLoop *g_loop;
+
+gchar *g_broadcast_address = NULL;
+menu_state_e g_menu_state = MENU_STATE_MAIN_MENU;
+submenu_state_e g_sub_menu_state = SUBMENU_STATE_UNKNOWN;
+preset_type_e g_menu_preset = PRESET_UNKNOWN;
+
+gboolean g_autoplug_mode = FALSE;
+
+media_format_h vfmt_raw = NULL;
+media_format_h vfmt_encoded = NULL;
+media_format_h afmt_raw = NULL;
+
+/*---------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------*/
+
+static gboolean _create(media_streamer_h *streamer)
+{
+ g_print("== create \n");
+
+ if(*streamer != NULL)
+ {
+ return TRUE;
+ }
+
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ ret = media_streamer_create(streamer);
+
+ if( ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ g_print("Fail to create media streamer");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean _prepare(void)
+{
+ g_print("== prepare \n");
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ ret = media_streamer_prepare(current_media_streamer);
+ if( ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ g_print("Fail to prepare media streamer");
+ return FALSE;
+ }
+ g_print("== success prepare \n");
+
+ return TRUE;
+}
+
+static gboolean _unprepare(void)
+{
+ g_print("== unprepare \n");
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ ret = media_streamer_unprepare(current_media_streamer);
+ if( ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ g_print("Fail to unprepare media streamer");
+ return FALSE;
+ }
+ g_print("== success unprepare \n");
+
+ return TRUE;
+}
+
+static gboolean _play()
+{
+ g_print("== play \n");
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ ret = media_streamer_play(current_media_streamer);
+ if( ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ g_print("Fail to play media streamer");
+ return FALSE;
+ }
+ g_print("== success play \n");
+
+ return TRUE;
+}
+
+static gboolean _destroy(media_streamer_h streamer)
+{
+ g_print("== destroy \n");
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ if(streamer == NULL)
+ {
+ g_print("media streamer already destroyed");
+ return TRUE;
+ }
+
+ ret = media_streamer_destroy(streamer);
+ if( ret != MEDIA_STREAMER_ERROR_NONE)
+ {
+ g_print("Fail to destroy media streamer");
+ return FALSE;
+ }
+
+ g_menu_preset = PRESET_UNKNOWN;
+ g_print("== success destroy \n");
+ return TRUE;
+}
+
+static void create_formats(void)
+{
+ if(!vfmt_raw || !vfmt_encoded || afmt_raw)
+ {
+ g_print("Formats already created!");
+ }
+
+ /* Define video raw format */
+ media_format_create(&vfmt_raw);
+ if (media_format_set_video_mime(vfmt_raw, MEDIA_FORMAT_YV12) != MEDIA_FORMAT_ERROR_NONE)
+ {
+ g_print("media_format_set_video_mime failed!");
+ }
+ media_format_set_video_width(vfmt_raw, 800);
+ media_format_set_video_height(vfmt_raw, 600);
+ media_format_set_video_avg_bps(vfmt_raw, 10000);
+ media_format_set_video_max_bps(vfmt_raw, 30000);
+
+ /* Define encoded video format */
+ media_format_create(&vfmt_encoded);
+ if (media_format_set_video_mime(vfmt_encoded, MEDIA_FORMAT_H264_SP) != MEDIA_FORMAT_ERROR_NONE)
+ {
+ g_print("media_format_set_video_mime failed!");
+ }
+ media_format_set_video_width(vfmt_encoded, 800);
+ media_format_set_video_height(vfmt_encoded, 600);
+ media_format_set_video_avg_bps(vfmt_encoded, 10000);
+ media_format_set_video_max_bps(vfmt_encoded, 30000);
+
+ /* Define audio raw format */
+ media_format_create(&afmt_raw);
+ if (media_format_set_audio_mime(afmt_raw, MEDIA_FORMAT_PCM) != MEDIA_FORMAT_ERROR_NONE)
+ {
+ g_print("media_format_set_audio_mime failed!");
+ }
+ media_format_set_audio_channel(afmt_raw, 1);
+ media_format_set_audio_samplerate(afmt_raw, 44100);
+ media_format_set_audio_bit(afmt_raw, 16);
+}
+
+static void set_rtp_params (media_streamer_node_h rtp_node,
+ const gchar *ip,
+ int video_port,
+ int audio_port,
+ gboolean port_reverse)
+{
+ bundle *params = bundle_create();
+
+#ifndef DISABLE_AUDIO
+ gchar *audio_src_port = g_strdup_printf("%d", port_reverse ? (audio_port + 5) : audio_port);
+ gchar *audio_sink_port = g_strdup_printf("%d", port_reverse ? audio_port : (audio_port + 5));
+
+ if(g_menu_preset & PRESET_RTP_STREAMER)
+ {
+ bundle_add_str(params, "audio_sink,port", audio_sink_port);
+ bundle_add_str(params, "audio_sink,host", ip);
+ }
+ if(g_menu_preset & PRESET_RTP_CLIENT)
+ {
+ bundle_add_str(params, "audio_source,port", audio_src_port);
+ bundle_add_str(params, "audio_source,format",
+ "application/x-rtp,media=audio,clock-rate=44100,encoding-name=L16,"
+ "encoding-params=1,channels=1,payload=96");
+ }
+
+ g_free(audio_src_port);
+ g_free(audio_sink_port);
+#endif
+
+#ifndef DISABLE_VIDEO
+ gchar *video_src_port = g_strdup_printf("%d", port_reverse ? (video_port + 5) : video_port);
+ gchar *video_sink_port = g_strdup_printf("%d", port_reverse ? video_port : (video_port + 5));
+
+ if(g_menu_preset & PRESET_RTP_STREAMER)
+ {
+ bundle_add_str(params, "video_sink,port", video_sink_port);
+ bundle_add_str(params, "video_sink,host", ip);
+ }
+ if(g_menu_preset & PRESET_RTP_CLIENT)
+ {
+ bundle_add_str(params, "video_source,port", video_src_port);
+ bundle_add_str(params, "video_source,format",
+ "application/x-rtp,media=video,clock-rate=90000,encoding-name=H264");
+ }
+
+ g_free(video_src_port);
+ g_free(video_sink_port);
+#endif
+
+ media_streamer_node_set_params(rtp_node, params);
+ bundle_free(params);
+ params = NULL;
+}
+
+static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin)
+{
+ g_print("== _create_rtp_streamer \n");
+
+#ifndef DISABLE_VIDEO
+ //********************** video source ***********************************
+ media_streamer_node_h video_src = NULL;
+#ifdef ONE_DEVICE_TEST
+ if(g_menu_preset & SECOND_VOIP_MASK)
+ {
+ media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_VIDEO_TEST, &video_src);
+ }
+ else
+ {
+ media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_CAMERA, &video_src);
+ }
+#else
+ media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_CAMERA, &video_src);
+#endif
+// media_streamer_node_set_fmt(video_src, vfmt_raw);
+ media_streamer_node_add(current_media_streamer, video_src);
+
+ //********************** encoder ****************************************
+ media_streamer_node_h video_enc = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER, NULL, vfmt_encoded, &video_enc);
+ media_streamer_node_add(current_media_streamer, video_enc);
+
+
+ //********************** videopay ***************************************
+ media_streamer_node_h video_pay = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY, NULL, vfmt_encoded, &video_pay);
+ media_streamer_node_add(current_media_streamer, video_pay);
+
+ //====================Linking Video Streamer===========================//
+ media_streamer_node_link(video_src, "src", video_enc, "sink");
+ media_streamer_node_link(video_enc, "src", video_pay, "sink");
+ media_streamer_node_link(video_pay, "src", rtp_bin, "video_sink");
+ //======================================================================//
+
+ g_print("== success streamer video part \n");
+#endif
+
+#ifndef DISABLE_AUDIO
+ //********************** audiosrc ***********************************
+ media_streamer_node_h audio_src = NULL;
+ media_streamer_src_create(MEDIA_STREAMER_SRC_TYPE_AUDIO_CAPTURE, &audio_src);
+ media_streamer_node_add(current_media_streamer, audio_src);
+
+ //********************** audioencoder ***********************************
+ media_streamer_node_h audio_enc = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER, NULL, NULL, &audio_enc);
+ media_streamer_node_add(current_media_streamer, audio_enc);
+
+
+ //********************** rtpL16pay ***********************************
+ media_streamer_node_h audio_pay = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY, NULL, NULL, &audio_pay);
+ media_streamer_node_add(current_media_streamer, audio_pay);
+
+ //====================Linking Audio Streamer===========================//
+ media_streamer_node_link(audio_src, "src", audio_enc, "sink");
+ media_streamer_node_link(audio_enc, "src", audio_pay, "sink");
+ media_streamer_node_link(audio_pay, "src", rtp_bin, "audio_sink");
+ //======================================================================//
+
+ g_print("== success streamer audio part \n");
+#endif
+
+ return TRUE;
+}
+
+static gboolean _create_rtp_client(media_streamer_node_h rtp_bin)
+{
+ g_print("== _create_rtp_client \n");
+
+#ifndef DISABLE_VIDEO
+ //********************** video_depay***********************************
+ media_streamer_node_h video_depay = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY, NULL, vfmt_encoded, &video_depay);
+ media_streamer_node_add(current_media_streamer, video_depay);
+
+ //********************** videodec ***********************************
+ media_streamer_node_h video_dec = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER, NULL, vfmt_encoded, &video_dec);
+ media_streamer_node_add(current_media_streamer, video_dec);
+
+ //********************** videosink ***********************************
+ media_streamer_node_h video_sink = NULL;
+ media_streamer_sink_create(MEDIA_STREAMER_SINK_TYPE_SCREEN, &video_sink);
+ media_streamer_node_add(current_media_streamer, video_sink);
+
+ //====================Linking Video Client===========================//
+ media_streamer_node_link(video_depay, "src", video_dec, "sink");
+ media_streamer_node_link(video_dec, "src", video_sink,"sink");
+// media_streamer_node_link(rtp_bin, "video_source", video_depay,"sink");
+
+ g_print("== success client video part \n");
+#endif
+
+#ifndef DISABLE_AUDIO
+ //********************** audiodepay ***********************************
+ media_streamer_node_h audio_depay = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY, NULL, NULL, &audio_depay);
+ media_streamer_node_add(current_media_streamer, audio_depay);
+
+ //********************** audioconvert ***********************************
+ media_streamer_node_h audio_converter = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER, NULL, NULL, &audio_converter);
+ media_streamer_node_add(current_media_streamer, audio_converter);
+
+ //********************** audioresample ***********************************
+ media_streamer_node_h audio_res = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE, NULL, NULL, &audio_res);
+ media_streamer_node_add(current_media_streamer, audio_res);
+
+ //********************** audiosink ***********************************
+ media_streamer_node_h audio_sink = NULL;
+ media_streamer_sink_create(MEDIA_STREAMER_SINK_TYPE_AUDIO, &audio_sink);
+ media_streamer_node_add(current_media_streamer, audio_sink);
+
+ //====================Linking Audio Client===========================//
+ media_streamer_node_link(audio_depay, "src", audio_converter, "sink");
+ media_streamer_node_link(audio_converter, "src", audio_res, "sink");
+ media_streamer_node_link(audio_res, "src", audio_sink,"sink");
+// media_streamer_node_link(rtp_bin, "audio_source", audio_depay,"sink");
+ //======================================================================//
+
+ g_print("== success client audio part \n");
+#endif
+
+ return TRUE;
+}
+
+static media_streamer_node_h _create_rtp(
+ int video_port,
+ int audio_port,
+ gboolean second_client)
+{
+ g_print("== create rtp node for current preset \n");
+
+ //********************** rtpbin ***********************************
+ media_streamer_node_h rtp_bin = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_RTP, vfmt_encoded, vfmt_encoded, &rtp_bin);
+ set_rtp_params(rtp_bin, g_broadcast_address, video_port, audio_port, second_client);
+ media_streamer_node_add(current_media_streamer, rtp_bin);
+ return rtp_bin;
+}
+
+/***************************************************************/
+/** Testsuite */
+/***************************************************************/
+
+void quit()
+{
+ reset_current_menu_state();
+ g_main_loop_quit(g_loop);
+}
+
+/*
+ * Function resets menu state to the main menu state
+ * and cleans media streamer handle.
+ */
+void reset_current_menu_state(void)
+{
+ g_menu_state = MENU_STATE_MAIN_MENU;
+ g_autoplug_mode = FALSE;
+ current_media_streamer = NULL;
+
+ if (g_media_streamer)
+ {
+ _destroy(g_media_streamer);
+ g_media_streamer = NULL;
+ }
+
+ if (g_media_streamer_2)
+ {
+ _destroy(g_media_streamer_2);
+ g_media_streamer_2 = NULL;
+ }
+
+ if(g_broadcast_address != NULL)
+ {
+ g_free(g_broadcast_address);
+ g_broadcast_address = NULL;
+ }
+}
+
+static void display_getting_ip_menu(void)
+{
+ g_print("\n");
+ g_print("Please input IP address for broadcasting\n");
+ g_print("By default will be used [%s]\n", DEFAULT_IP_ADDR);
+}
+
+static void display_autoplug_select_menu(void)
+{
+ g_print("\n");
+ g_print("Please select Media Streamer pluging mode\n");
+ g_print("By default will be used [%s] mode\n",
+ g_autoplug_mode == TRUE ? "autoplug" : "manual");
+ g_print("1. Manual mode \n");
+ g_print("2. Autoplug mode \n");
+}
+
+static void display_preset_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media streamer test: Preset menu v0.3\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. create media streamer \n");
+ g_print("2. set up current preset \n");
+ g_print("4. prepare \n");
+ g_print("5. unprepare \n");
+ g_print("6. play \n");
+ g_print("7. destroy media streamer \n\n");
+ g_print("b. back \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+}
+
+static void display_voip_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media streamer test: VoIP menu v0.3\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. one streamer VoIP 1 \n");
+ g_print("2. one streamer VoIP 2 \n");
+ g_print("3. two streamers VoIP server 1 \n");
+ g_print("4. two streamers VoIP server 2 \n");
+ g_print("5. two streamers VoIP client 1 \n");
+ g_print("6. two streamers VoIP client 2 \n");
+ g_print("b. back \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+}
+
+static void display_broadcast_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media streamer test: Broadcast menu v0.3\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. Broadcast client \n");
+ g_print("2. Broadcast streamer \n");
+ g_print("b. back \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+}
+
+static void display_main_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media streamer test: Main menu v0.3\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. Broadcast \n");
+ g_print("2. VOIP \n");
+ g_print("q. quit \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+}
+
+static void display_menu(void)
+{
+ if (g_sub_menu_state == SUBMENU_STATE_UNKNOWN)
+ {
+ switch (g_menu_state)
+ {
+ case MENU_STATE_MAIN_MENU:
+ display_main_menu();
+ break;
+ case MENU_STATE_BROADCAST_MENU:
+ display_broadcast_menu();
+ break;
+ case MENU_STATE_VOIP_MENU:
+ display_voip_menu();
+ break;
+ case MENU_STATE_PRESET_MENU:
+ display_preset_menu();
+ break;
+ default:
+ g_print("*** Unknown status.\n");
+ break;
+ }
+ }
+ else
+ {
+ switch (g_sub_menu_state)
+ {
+ case SUBMENU_STATE_GETTING_IP:
+ display_getting_ip_menu();
+ break;
+ case SUBMENU_STATE_AUTOPLUG:
+ display_autoplug_select_menu();
+ break;
+ case SUBMENU_STATE_FORMAT:
+// display_format_menu();
+ break;
+ default:
+ g_print("*** Unknown Submenu state.\n");
+ break;
+ }
+ }
+
+}
+
+static void run_preset(void)
+{
+ media_streamer_node_h rtp_bin = NULL;
+ create_formats();
+
+ switch(g_menu_preset)
+ {
+ case PRESET_RTP_STREAMER:
+ rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, FALSE);
+ _create_rtp_streamer(rtp_bin);
+ break;
+ case PRESET_RTP_CLIENT:
+ rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, TRUE);
+ _create_rtp_client(rtp_bin);
+ break;
+ case PRESET_VOIP:
+ rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, FALSE);
+ _create_rtp_streamer(rtp_bin);
+ _create_rtp_client(rtp_bin);
+ break;
+ case PRESET_VOIP_2:
+ rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, TRUE);
+ _create_rtp_streamer(rtp_bin);
+ _create_rtp_client(rtp_bin);
+ break;
+ case PRESET_DOUBLE_VOIP_SERVER:
+ rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, FALSE);
+ _create_rtp_streamer(rtp_bin);
+ break;
+ case PRESET_DOUBLE_VOIP_SERVER_2:
+ rtp_bin = _create_rtp(VIDEO_PORT+10, AUDIO_PORT+10, TRUE);
+ _create_rtp_streamer(rtp_bin);
+ break;
+ case PRESET_DOUBLE_VOIP_CLIENT:
+ rtp_bin = _create_rtp(VIDEO_PORT+10, AUDIO_PORT+10, FALSE);
+ _create_rtp_client(rtp_bin);
+ break;
+ case PRESET_DOUBLE_VOIP_CLIENT_2:
+ rtp_bin = _create_rtp(VIDEO_PORT, AUDIO_PORT, TRUE);
+ _create_rtp_client(rtp_bin);
+ break;
+ default:
+ g_print("Invalid menu preset was selected!");
+ break;
+ }
+}
+
+void _interpret_main_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if(len == 1)
+ {
+ if ( !strncmp(cmd, "1", len))
+ {
+ g_menu_state = MENU_STATE_BROADCAST_MENU;
+ }
+ else if ( !strncmp(cmd, "2", len))
+ {
+ g_menu_state = MENU_STATE_VOIP_MENU;
+ }
+ else if ( !strncmp(cmd, "q", len))
+ {
+ quit();
+ }
+ }
+ else
+ {
+ g_print("wrong command\n");
+ }
+}
+
+//=====================Broadcast Menu============================//
+void _interpret_broadcast_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if(len == 1)
+ {
+ if( !strncmp(cmd, "1", len))
+ {
+ g_menu_preset = PRESET_RTP_CLIENT;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "2", len))
+ {
+ g_menu_preset = PRESET_RTP_STREAMER;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "b", len))
+ {
+ reset_current_menu_state();
+ display_menu();
+ }
+ }
+ else
+ {
+ g_print("wrong command\n");
+ }
+}
+
+void _interpret_voip_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if(len == 1)
+ {
+ if( !strncmp(cmd, "1", len))
+ {
+ g_menu_preset = PRESET_VOIP;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "2", len))
+ {
+ g_menu_preset = PRESET_VOIP_2;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "3", len))
+ {
+ //double Server 1
+ g_menu_preset = PRESET_DOUBLE_VOIP_SERVER;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "4", len))
+ {
+ //double Server 2
+ g_menu_preset = PRESET_DOUBLE_VOIP_SERVER_2;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "5", len))
+ {
+ //double Client 1
+ g_menu_preset = PRESET_DOUBLE_VOIP_CLIENT;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "6", len))
+ {
+ //double Client 2
+ g_menu_preset = PRESET_DOUBLE_VOIP_CLIENT_2;
+ g_menu_state = MENU_STATE_PRESET_MENU;
+ }
+ else if( !strncmp(cmd, "b", len))
+ {
+ reset_current_menu_state();
+ //display_menu();
+ }
+
+ }
+ else
+ {
+ g_print("wrong command\n");
+ }
+}
+
+void _interpret_getting_ip_menu(char *cmd)
+{
+ int min_len = strlen("0.0.0.0");
+ int cmd_len = strlen(cmd);
+ if(g_broadcast_address != NULL)
+ {
+ g_free(g_broadcast_address);
+ }
+
+ if(cmd_len > min_len)
+ {
+ g_broadcast_address = g_strdup(cmd);
+ g_print("== IP address setted to [%s]\n", g_broadcast_address);
+ }
+ else
+ {
+ g_broadcast_address = g_strdup(DEFAULT_IP_ADDR);
+ g_print("Invalid IP. Default address will be used [%s]\n", DEFAULT_IP_ADDR);
+ }
+
+ run_preset();
+ g_sub_menu_state = SUBMENU_STATE_UNKNOWN;
+}
+
+void _interpret_autoplug_menu(char *cmd)
+{
+
+ int cmd_number = atoi(cmd)-1;
+
+
+ if(cmd_number == 1 || cmd_number == 0)
+ {
+ g_autoplug_mode = cmd_number;
+ }
+ else
+ {
+ g_print("Invalid input. Default autoplug mode will be used\n");
+ }
+ g_print("Selected pluging mode is [%s]\n",
+ g_autoplug_mode == TRUE ? "autoplug" : "manual");
+
+ if(g_menu_preset & PRESET_RTP_STREAMER)
+ {
+ g_sub_menu_state = SUBMENU_STATE_GETTING_IP;
+ }
+ else
+ {
+ run_preset();
+ g_sub_menu_state = SUBMENU_STATE_UNKNOWN;
+ }
+}
+
+void _interpret_preset_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if(len == 1 || len == 2)
+ {
+ if( !strncmp(cmd, "1", len))
+ {
+ if((g_menu_preset & DOUBLE_STREAMER_MASK) &&
+ (g_menu_preset & PRESET_RTP_CLIENT))
+ {
+ _create(&g_media_streamer_2);
+ current_media_streamer = g_media_streamer_2;
+ g_print("== success create media streamer 2\n");
+ }
+ else
+ {
+ _create(&g_media_streamer);
+ current_media_streamer = g_media_streamer;
+ g_print("== success create media streamer\n");
+ }
+
+ }
+ else if( !strncmp(cmd, "2", len))
+ {
+ // call the run_preset function after autoplug mode was selected;
+ g_sub_menu_state = SUBMENU_STATE_AUTOPLUG;
+ }
+ else if( !strncmp(cmd, "4", len))
+ {
+ _prepare();
+ }
+ else if( !strncmp(cmd, "5", len))
+ {
+ _unprepare();
+ }
+ else if( !strncmp(cmd, "6", len))
+ {
+ _play(g_media_streamer);
+ }
+ else if( !strncmp(cmd, "7", len))
+ {
+ _destroy(current_media_streamer);
+ current_media_streamer = NULL;
+ }
+ else if( !strncmp(cmd, "b", len))
+ {
+ if(g_menu_preset & DOUBLE_STREAMER_MASK)
+ {
+ g_menu_state = MENU_STATE_VOIP_MENU;
+ g_autoplug_mode = FALSE;
+ current_media_streamer = NULL;
+ }
+ else
+ {
+ reset_current_menu_state();
+ }
+ display_menu();
+ }
+
+ }
+ else
+ {
+ g_print("wrong command\n");
+ }
+}
+
+static void interpret_cmd(char *cmd)
+{
+ if(g_sub_menu_state == SUBMENU_STATE_UNKNOWN)
+ {
+ switch(g_menu_state)
+ {
+ case MENU_STATE_MAIN_MENU:
+ _interpret_main_menu(cmd);
+ break;
+ case MENU_STATE_BROADCAST_MENU:
+ _interpret_broadcast_menu(cmd);
+ break;
+ case MENU_STATE_VOIP_MENU:
+ _interpret_voip_menu(cmd);
+ break;
+ case MENU_STATE_PRESET_MENU:
+ _interpret_preset_menu(cmd);
+ break;
+ default:
+ g_print("Invalid command\n");
+ return;
+ break;
+ }
+ }
+ else
+ {
+ switch (g_sub_menu_state)
+ {
+ case SUBMENU_STATE_GETTING_IP:
+ _interpret_getting_ip_menu(cmd);
+ break;
+ case SUBMENU_STATE_AUTOPLUG:
+ _interpret_autoplug_menu(cmd);
+ break;
+ case SUBMENU_STATE_FORMAT:
+ //display_format_menu();
+ break;
+ default:
+ g_print("*** Unknown Submenu state.\n");
+ break;
+ }
+ }
+
+ display_menu();
+}
+
+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_cmd(buf);
+
+ return TRUE;
+
+}
+
+int main(int argc, char **argv)
+{
+ GIOChannel *stdin_channel;
+ 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);
+
+ display_menu();
+
+ g_loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(g_loop);
+ return 0;
+}