Added implementation of interruption by resource manager 05/102405/2
authorOleksandr Popov <ol.popov@samsung.com>
Mon, 5 Dec 2016 16:35:48 +0000 (18:35 +0200)
committerOleksandr Popov <ol.popov@samsung.com>
Mon, 5 Dec 2016 16:35:48 +0000 (18:35 +0200)
Signed-off-by: Oleksandr Popov <ol.popov@samsung.com>
Change-Id: I213f1aa51bf6e051baf0a435f268c2798124d558

16 files changed:
CMakeLists.txt
include/media_streamer_gst.h
include/media_streamer_node.h
include/media_streamer_node_resources.h [new file with mode: 0644]
include/media_streamer_priv.h
include/media_streamer_resource.h [new file with mode: 0644]
include/media_streamer_util.h
packaging/capi-media-streamer.spec
src/media_streamer.c
src/media_streamer_gst.c
src/media_streamer_node.c
src/media_streamer_node_resources.c [new file with mode: 0644]
src/media_streamer_priv.c
src/media_streamer_resource.c [new file with mode: 0644]
src/media_streamer_util.c
test/media_streamer_test.c

index 01c07030ff7d4801a282d30459b63bfb71dddd77..0c7e7c52455c89a067216723067da908a34483b6 100644 (file)
@@ -10,8 +10,8 @@ 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 gstreamer-video-1.0 cynara-client capi-system-info ecore elementary")
-SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0 cynara-client capi-system-info ecore evas elementary")
+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 gstreamer-video-1.0 cynara-client capi-system-info ecore elementary murphy-resource murphy-glib")
+SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 gstreamer-video-1.0 cynara-client capi-system-info ecore evas elementary murphy-resource murphy-glib")
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${dependents})
index 37f2b2bc2f67e213d5a4c6387ce52285ae37e85a..11b1da8d0b87151e3dfbc248ff959f0a60118804 100644 (file)
@@ -182,14 +182,14 @@ GstElement *__ms_combine_next_element(GstElement *previous_element, GstPad *prev
  *
  * @since_tizen 3.0
  */
-void __ms_element_lock_state(const GValue *item, gpointer user_data);
+gboolean __ms_element_lock_state(const GValue *item, GValue *ret, gpointer user_data);
 
 /**
  * @brief Unlocks gst_element being contained in GValue data.
  *
  * @since_tizen 3.0
  */
-void __ms_element_unlock_state(const GValue *item, gpointer user_data);
+gboolean __ms_element_unlock_state(const GValue *item, GValue *ret, gpointer user_data);
 
 /**
  * @brief Creates pipeline, bus and src/sink/topology bins.
index eb89d8c6b128681a60ce34f4cb87a2fb7c3cfa6e..f79f9e5b83bad357ea3a5f1ab0c5e948fef204af 100644 (file)
@@ -128,3 +128,6 @@ int __ms_node_set_param_value(media_streamer_node_s *ms_node, param_s *param, co
  * @since_tizen 3.0
  */
 int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt);
+
+gboolean _ms_node_resouces_acquire_iter(const GValue *item, GValue *ret, gpointer user_data);
+gboolean  _ms_node_resouces_release_iter(const GValue *item, GValue *ret, gpointer user_data);
diff --git a/include/media_streamer_node_resources.h b/include/media_streamer_node_resources.h
new file mode 100644 (file)
index 0000000..2f4dd12
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015-2016 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_NODE_RESOURCE_H__
+#define __MEDIA_STREAMER_NODE_RESOURCE_H__
+
+#include <media_streamer_priv.h>
+#include <media_streamer_resource.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __ms_node_resouces_init(media_streamer_node_s *node);
+int __ms_node_resouces_deinit(media_streamer_node_s *node);
+int _ms_node_resource_aquire(media_streamer_node_s *node);
+int _ms_node_resource_release(media_streamer_node_s *node);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEDIA_STREAMER_NODE_RESOURCE_H__ */
index 8ffe1c470d0165eb67d646c5492d30512ff26ee6..14a45f7dad61e5159ea4d1f2181ce7d9d66da8ab 100755 (executable)
@@ -27,6 +27,7 @@ extern "C" {
 
 #include <media_streamer.h>
 #include <media_streamer_util.h>
+#include <media_streamer_resource.h>
 
 struct media_streamer_node_s;
 
@@ -110,6 +111,10 @@ typedef struct {
        media_streamer_callback_s error_cb;
        media_streamer_callback_s state_changed_cb;
        media_streamer_callback_s seek_done_cb;
+       media_streamer_callback_s interrupted_cb;
+
+       gboolean is_interrupted;
+       media_streamer_resource_manager_s resource_manager;
 } media_streamer_s;
 
 /**
@@ -130,6 +135,8 @@ typedef struct {
        GList *sig_list;
 
        void *callbacks_structure;
+
+       media_streamer_resource_manager_s resource_manager;
 } media_streamer_node_s;
 
 typedef struct _media_streamer_wl_info_s {
@@ -185,6 +192,8 @@ int __ms_create(media_streamer_s *ms_streamer);
  */
 int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e state);
 
+int __ms_release_resources(media_streamer_s *ms_streamer);
+
 #ifdef __cplusplus
 }
 
diff --git a/include/media_streamer_resource.h b/include/media_streamer_resource.h
new file mode 100644 (file)
index 0000000..27da5ca
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015-2016 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_RESOURCE_H__
+#define __MEDIA_STREAMER_RESOURCE_H__
+
+#include <murphy/plugins/resource-native/libmurphy-resource/resource-api.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MEDIA_STREAMER_RESOURCE_TIMEOUT 5
+
+#define MEDIA_STREAMER_GET_RESOURCE_LOCK(rm)   (&((media_streamer_resource_manager_s *)rm)->lock)
+#define MEDIA_STREAMER_RESOURCE_LOCK(rm)               (g_mutex_lock(MEDIA_STREAMER_GET_RESOURCE_LOCK(rm)))
+#define MEDIA_STREAMER_RESOURCE_UNLOCK(rm)     (g_mutex_unlock(MEDIA_STREAMER_GET_RESOURCE_LOCK(rm)))
+
+#define MEDIA_STREAMER_GET_RESOURCE_COND(rm)   (&((media_streamer_resource_manager_s *)rm)->cond)
+#define MEDIA_STREAMER_RESOURCE_WAIT(rm)               g_cond_wait(MEDIA_STREAMER_GET_RESOURCE_COND(rm), MEDIA_STREAMER_GET_RESOURCE_LOCK(rm)
+#define MEDIA_STREAMER_RESOURCE_WAIT_UNTIL(rm, end_time) \
+       g_cond_wait_until(MEDIA_STREAMER_GET_RESOURCE_COND(rm), MEDIA_STREAMER_GET_RESOURCE_LOCK(rm), end_time)
+#define MEDIA_STREAMER_RESOURCE_SIGNAL(rm)     g_cond_signal(MEDIA_STREAMER_GET_RESOURCE_COND(rm));
+
+typedef enum {
+       RESOURCE_TYPE_NONE,
+       RESOURCE_TYPE_VIDEO_DECODER,
+       RESOURCE_TYPE_CAMERA,
+       RESOURCE_TYPE_VIDEO_OVERLAY,
+} media_streamer_resource_type_e;
+
+typedef enum {
+       RESOURCE_STATE_ERROR = -1,
+       RESOURCE_STATE_NONE,
+       RESOURCE_STATE_INITIALIZED,
+       RESOURCE_STATE_PREPARED,
+       RESOURCE_STATE_ACQUIRED,
+       RESOURCE_STATE_MAX,
+} media_streamer_resource_state_e;
+
+typedef struct _media_streamer_resource_manager_s media_streamer_resource_manager_s;
+typedef gboolean (*resource_relese_cb) (media_streamer_resource_manager_s *resource_manager, void *user_data);
+
+struct _media_streamer_resource_manager_s {
+       mrp_mainloop_t *mloop;
+       mrp_res_context_t *context;
+       mrp_res_resource_set_t *rset;
+       media_streamer_resource_state_e state;
+       bool is_connected;
+       void *user_data;
+       bool by_rm_cb;
+       GCond cond;
+       GMutex lock;
+
+       /* Release cb */
+       resource_relese_cb release_cb;
+};
+
+int _ms_resource_manager_init(media_streamer_resource_manager_s *resource_manager, resource_relese_cb release_cb, void *user_data);
+int _ms_resource_manager_prepare(media_streamer_resource_manager_s *resource_manager, media_streamer_resource_type_e resource_type);
+int _ms_resource_manager_acquire(media_streamer_resource_manager_s *resource_manager);
+int _ms_resource_manager_release(media_streamer_resource_manager_s  *resource_manager);
+int _ms_resource_manager_unprepare(media_streamer_resource_manager_s *resource_manager);
+int _ms_resource_manager_deinit(media_streamer_resource_manager_s *resource_manager);
+int _ms_resource_manager_get_state(media_streamer_resource_manager_s *resource_manager, media_streamer_resource_state_e *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEDIA_STREAMER_RESOURCE_H__ */
index b4b862575d05095a1bfebdfb498afef480c330de..2b44cdf7d741ee2fdc9655ee530bbf531f85963c 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __MEDIA_STREAMER_UTIL_H__
 #define __MEDIA_STREAMER_UTIL_H__
 
+#include <media_format.h>
+
 #include <stdlib.h>
 #include <glib.h>
 #include <gst/gst.h>
@@ -45,33 +47,33 @@ extern "C" {
 
 #define ms_debug(fmt, arg...)                         \
        do {                                              \
-               LOGD(FONT_COLOR_RESET""fmt"", ##arg);         \
+               LOGD(FONT_COLOR_RESET""fmt""FONT_COLOR_RESET, ##arg);         \
        } while (0)
 
 #define ms_info(fmt, arg...)                          \
        do {                                              \
-               LOGI(FONT_COLOR_GREEN""fmt"", ##arg);         \
+               LOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg);         \
        } while (0)
 
 #define ms_error(fmt, arg...)                         \
        do {                                              \
-               LOGE(FONT_COLOR_RED""fmt"", ##arg);           \
+               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg);           \
        } while (0)
 
 #define ms_debug_fenter()                             \
        do {                                              \
-               LOGD(FONT_COLOR_YELLOW"<Enter>");             \
+               LOGD(FONT_COLOR_YELLOW"<Enter>"FONT_COLOR_RESET);             \
        } while (0)
 
 #define ms_debug_fleave()                             \
        do {                                              \
-               LOGD(FONT_COLOR_PURPLE"<Leave>");             \
+               LOGD(FONT_COLOR_PURPLE"<Leave>"FONT_COLOR_RESET);             \
        } while (0)
 
 #define ms_retm_if(expr, fmt, arg...)                 \
        do {                                              \
                if (expr) {                                   \
-                       LOGE(FONT_COLOR_RED""fmt"", ##arg);       \
+                       LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg);       \
                        return;                                   \
                }                                             \
        } while (0)
@@ -79,7 +81,7 @@ extern "C" {
 #define ms_retvm_if(expr, val, fmt, arg...)           \
        do {                                              \
                if (expr) {                                   \
-                       LOGE(FONT_COLOR_RED""fmt"", ##arg);       \
+                       LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg);       \
                        return(val);                              \
                }                                             \
        } while (0)
@@ -109,8 +111,8 @@ typedef struct __media_streamer_ini {
        gboolean generate_dot;
        gboolean use_decodebin;
        gchar **exclude_elem_names;
+       gchar **resource_required_elem_names;
        gchar **gst_args;
-
 } media_streamer_ini_t;
 
 /**
@@ -215,14 +217,6 @@ typedef struct {
 
 #define MEDIA_STREAMER_DEFAULT_DOT_DIR "/tmp"
 
-#define MS_BIN_FOREACH_ELEMENTS(bin, fn, streamer) \
-       do { \
-               GstIterator *iter = gst_bin_iterate_elements(GST_BIN(bin)); \
-               if (gst_iterator_foreach(iter, fn, streamer) != GST_ITERATOR_DONE) \
-                       ms_error("Error while iterating elements in bin [%s]!", GST_ELEMENT_NAME(bin)); \
-               gst_iterator_free(iter); \
-       } while (0)
-
 #define MS_BIN_UNPREPARE(bin) \
        if (!__ms_bin_remove_elements(ms_streamer, bin)) {\
                ms_debug("Got a few errors during unprepare [%s] bin.", GST_ELEMENT_NAME(bin));\
@@ -340,6 +334,13 @@ void __ms_param_value_destroy(gpointer data);
  */
 int __ms_node_uri_path_check(const char *file_uri);
 
+/**
+ * @brief Iterates func over all elements contained within a bin.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_bin_foreach_elements(GstBin *bin, GstIteratorFoldFunction func, void *user_data);
+
 #ifdef __cplusplus
 }
 #endif
index 716fcb813eee288c804ada3e323b8b20c491bcd7..7443f3b07a49a2767ebf26f1c9d2686f9827bb68 100644 (file)
@@ -29,6 +29,8 @@ BuildRequires:  pkgconfig(ecore)
 BuildRequires:  pkgconfig(evas)
 BuildRequires:  pkgconfig(ecore-wayland)
 BuildRequires:  pkgconfig(appcore-efl)
+BuildRequires:  pkgconfig(murphy-resource)
+BuildRequires:  pkgconfig(murphy-glib)
 
 %description
 A MediaStreamer library in Tizen Native API.
index 8bd592f184dc7fd0367aa1f6f4089d3047cb1d9e..73ba7dcce850eeb1fbb7c6098de875214ea9a339 100644 (file)
@@ -251,6 +251,8 @@ int media_streamer_create(media_streamer_h *streamer)
        /* create streamer lock */
        g_mutex_init(&ms_streamer->mutex_lock);
 
+       g_mutex_lock(&ms_streamer->mutex_lock);
+
        ret = __ms_create(ms_streamer);
        if (ret != MEDIA_STREAMER_ERROR_NONE) {
                ms_error("Error creating Media Streamer");
@@ -263,6 +265,8 @@ int media_streamer_create(media_streamer_h *streamer)
        ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
        *streamer = ms_streamer;
 
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
        ms_info("Media Streamer created successfully");
        return ret;
 }
@@ -712,3 +716,34 @@ int media_streamer_node_get_param(media_streamer_node_h node, const char *param_
 
        return ret;
 }
+
+int media_streamer_set_interrupted_cb(media_streamer_h streamer, media_streamer_interrupted_cb callback, void *user_data)
+{
+       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(callback == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Callback is NULL");
+
+       g_mutex_lock(&ms_streamer->mutex_lock);
+
+       ms_streamer->interrupted_cb.callback = callback;
+       ms_streamer->interrupted_cb.user_data = user_data;
+
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_unset_interrupted_cb(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->interrupted_cb.callback = NULL;
+       ms_streamer->interrupted_cb.user_data = NULL;
+
+       g_mutex_unlock(&ms_streamer->mutex_lock);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
index 39a1a14c4b6c0bad7681096bca3efa5ee5e13f45..f3961d4e567851bea85b69dc5e142e879bddf0b2 100644 (file)
@@ -465,6 +465,28 @@ static gint __decodebin_autoplug_select_cb(GstElement * bin, GstPad * pad, GstCa
 
        }
 
+       if (ms_streamer->ini.resource_required_elem_names) {
+               /* Try to acuire resources before adding element */
+               int index = 0;
+               for ( ; ms_streamer->ini.resource_required_elem_names[index]; ++index) {
+                       if (g_strrstr(factory_name, ms_streamer->ini.resource_required_elem_names[index])) {
+                               ms_debug("Decodebin: trying to acquire resource for [%s] element", factory_name);
+
+                               if (MEDIA_STREAMER_ERROR_NONE !=
+                                       _ms_resource_manager_prepare(&ms_streamer->resource_manager, RESOURCE_TYPE_VIDEO_DECODER)) {
+                                       ms_error("Failed to prepare resources for [%s] element", factory_name);
+                                       return GST_AUTOPLUG_SELECT_SKIP;
+                               }
+
+                               if (MEDIA_STREAMER_ERROR_NONE !=
+                                       _ms_resource_manager_acquire(&ms_streamer->resource_manager)) {
+                                       ms_error("Failed to acquire resources for [%s] element", factory_name);
+                                       return GST_AUTOPLUG_SELECT_SKIP;
+                               }
+                       }
+               }
+       }
+
        return result;
 }
 
@@ -979,6 +1001,7 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node
        GstElement *gst_element = NULL;
 
        const gchar *src_type, *sink_type;
+
        MS_GET_CAPS_TYPE(plug_info->src_caps, src_type);
        MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type);
 
@@ -1474,15 +1497,16 @@ static GstPadProbeReturn __ms_element_event_probe(GstPad * pad, GstPadProbeInfo
        return GST_PAD_PROBE_PASS;
 }
 
-void __ms_element_lock_state(const GValue *item, gpointer user_data)
+gboolean __ms_element_lock_state(const GValue *item, GValue *ret, gpointer user_data)
 {
        GstElement *sink_element = GST_ELEMENT(g_value_get_object(item));
-       ms_retm_if(!sink_element, "Handle is NULL");
+       g_value_set_boolean(ret, FALSE);
+       ms_retvm_if(!sink_element, FALSE, "Handle is NULL");
 
        GstPad *sink_pad = gst_element_get_static_pad(sink_element, "sink");
        if (!sink_pad) {
                ms_info("Failed to get static pad of element [%s]", GST_ELEMENT_NAME(sink_element));
-               return;
+               return FALSE;
        }
        if (!gst_pad_is_blocked(sink_pad)) {
                int probe_id = gst_pad_add_probe(sink_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, __ms_element_event_probe, NULL, NULL);
@@ -1492,19 +1516,24 @@ void __ms_element_lock_state(const GValue *item, gpointer user_data)
                ms_info("Pad [%s] of element [%s] is already locked", GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
        }
        MS_SAFE_UNREF(sink_pad);
+
+       g_value_set_boolean(ret, TRUE);
+
+       return TRUE;
 }
 
-void __ms_element_unlock_state(const GValue *item, gpointer user_data)
+gboolean __ms_element_unlock_state(const GValue *item, GValue *ret, gpointer user_data)
 {
        GstElement *sink_element = GST_ELEMENT(g_value_get_object(item));
-       ms_retm_if(!sink_element, "Handle is NULL");
+       g_value_set_boolean(ret, FALSE);
+       ms_retvm_if(!sink_element, FALSE, "Handle is NULL");
 
        GValue *val = (GValue *) g_object_get_data(G_OBJECT(sink_element), "pad_sink");
        if (val) {
                GstPad *sink_pad = gst_element_get_static_pad(sink_element, "sink");
                if (!sink_pad) {
                        ms_info("Failed to get static pad of element [%s]", GST_ELEMENT_NAME(sink_element));
-                       return;
+                       return FALSE;
                }
                if (gst_pad_is_blocked(sink_pad)) {
                        ms_info("Removing locking probe [%d] ID on [%s] pad of [%s] element", g_value_get_int(val), GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
@@ -1514,6 +1543,10 @@ void __ms_element_unlock_state(const GValue *item, gpointer user_data)
                }
                MS_SAFE_UNREF(sink_pad);
        }
+
+       g_value_set_boolean(ret, TRUE);
+
+       return TRUE;
 }
 
 static gboolean __ms_bus_cb(GstBus *bus, GstMessage *message, gpointer userdata)
index 874afa91f72848fc1cb0402528ff9b1fed35a91a..a87724f5503d88a0fe1bc05ed1cc29799fe9a48e 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <media_streamer_node.h>
+#include <media_streamer_node_resources.h>
 #include <media_streamer_util.h>
 #include <media_streamer_gst.h>
 #include <cynara-client.h>
@@ -240,6 +241,7 @@ int __ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_f
        GstCaps *src_caps = out_fmt ? __ms_create_caps_from_fmt(out_fmt) : NULL;
 
        node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL};
+
        ms_info("Creating node with info: klass_name[%s]; default[%s]",
                        plug_info.info->klass_name, plug_info.info->default_name);
 
@@ -247,13 +249,19 @@ int __ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_f
        if (node->gst_element)
                node->name = gst_element_get_name(node->gst_element);
        else
-               ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
 
        if (src_caps)
-               gst_caps_unref(src_caps);
+                       gst_caps_unref(src_caps);
 
        if (sink_caps)
-               gst_caps_unref(sink_caps);
+                       gst_caps_unref(sink_caps);
+
+       ret = __ms_node_resouces_init(node);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to init resources for node [%s]", node->name);
+               return ret;
+       }
 
        return ret;
 }
@@ -310,7 +318,7 @@ static int __ms_node_check_priveleges(media_streamer_node_s *node)
                        privilege = "http://tizen.org/privilege/camera";
                        break;
                default:
-                       ms_info("For current Src Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
+                       ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
                        break;
                }
        }
@@ -446,7 +454,7 @@ static int __ms_node_check_feature(media_streamer_node_s *node)
                                ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
                        break;
                default:
-                       ms_info("For current Src Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
+                       ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
                        break;
                }
        }
@@ -483,7 +491,7 @@ static int __ms_node_check_feature(media_streamer_node_s *node)
                                ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
                        break;
                default:
-                       ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
+                       ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
                        break;
                }
        }
@@ -560,11 +568,15 @@ int __ms_src_node_create(media_streamer_node_s *node)
 
        MS_SAFE_FREE(plugin_name);
 
-       if (ret == MEDIA_STREAMER_ERROR_NONE) {
-               if (node->gst_element == NULL)
-                       ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
-               else
-                       node->name = gst_element_get_name(node->gst_element);
+       if (node->gst_element == NULL)
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       else
+               node->name = gst_element_get_name(node->gst_element);
+
+       ret = __ms_node_resouces_init(node);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to init resources for node [%s]", node->name);
+               return ret;
        }
 
        return ret;
@@ -670,10 +682,16 @@ int __ms_sink_node_create(media_streamer_node_s *node)
        MS_SAFE_FREE(plugin_name);
 
        if (node->gst_element == NULL)
-               ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
        else
                node->name = gst_element_get_name(node->gst_element);
 
+       ret = __ms_node_resouces_init(node);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to init resources for node [%s]", node->name);
+               return ret;
+       }
+
        return ret;
 }
 
@@ -684,6 +702,10 @@ void __ms_node_destroy(media_streamer_node_s *node)
        /* Disconnects and clean all node signals */
        g_list_free_full(node->sig_list, __ms_signal_destroy);
 
+       /* Deinitialize resource manager */
+       if (MEDIA_STREAMER_ERROR_NONE != __ms_node_resouces_deinit(node))
+               ms_error("Failed to deinitialize resource manager");
+
        MS_SAFE_UNREF(node->gst_element);
        MS_SAFE_FREE(node->name);
        MS_SAFE_FREE(node->callbacks_structure);
@@ -751,24 +773,29 @@ node_info_s * __ms_node_get_klass_by_its_type(media_streamer_node_type_e element
        return &nodes_info[it_klass];
 }
 
-static void _src_node_prepare(const GValue *item, gpointer user_data)
+static gboolean _src_node_prepare(const GValue *item, GValue *ret, gpointer user_data)
 {
        media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
        GstElement *src_element = GST_ELEMENT(g_value_get_object(item));
        g_object_ref(src_element);
+       g_value_set_boolean(ret, FALSE);
 
        media_streamer_node_s *found_node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table, GST_ELEMENT_NAME(src_element));
-       if (!found_node)
-               return;
+       if (!found_node) {
+               /* If we fail to found corresonding node inside streamer
+                       then apprently this element doesn't require resources. */
+               ms_debug("Failed to found corresonding node [%s] inside streamer", GST_ELEMENT_NAME(src_element));
+               g_value_set_boolean(ret, TRUE);
+               return TRUE;
+       }
 
-       ms_retm_if(!ms_streamer || !src_element, "Handle is NULL");
        ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
 
        GstPad *src_pad = gst_element_get_static_pad(src_element, "src");
        GstElement *found_element = NULL;
 
        if (__ms_src_need_typefind(src_pad)) {
-               __ms_find_type(ms_streamer,src_element);
+               __ms_find_type(ms_streamer, src_element);
                MS_SAFE_UNREF(src_element);
        } else {
                /* Check the source element`s pad type */
@@ -777,7 +804,8 @@ static void _src_node_prepare(const GValue *item, gpointer user_data)
                if (gst_pad_is_linked(src_pad)) {
                        MS_SAFE_UNREF(src_pad);
                        MS_SAFE_UNREF(src_element);
-                       return;
+                       g_value_set_boolean(ret, TRUE);
+                       return TRUE;
                }
                /* It is media streamer Server part */
                if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) {
@@ -799,9 +827,19 @@ static void _src_node_prepare(const GValue *item, gpointer user_data)
                MS_SAFE_UNREF(found_element);
        }
        MS_SAFE_UNREF(src_pad);
+
+       g_value_set_boolean(ret, TRUE);
+
+       return TRUE;
 }
 
-static gboolean demux_find(gpointer key, gpointer value, gpointer user_data) {
+static gboolean _sink_node_prepare(const GValue *item, GValue *ret, gpointer user_data)
+{
+       return __ms_element_lock_state(item, ret, user_data);
+}
+
+static gboolean demux_find(gpointer key, gpointer value, gpointer user_data)
+{
        return g_strrstr((char *)key, "demux") != NULL;
 }
 
@@ -816,7 +854,9 @@ int __ms_pipeline_prepare(media_streamer_s *ms_streamer)
        if (rtp_node) {
                ret = __ms_rtp_element_prepare(rtp_node) ? MEDIA_STREAMER_ERROR_NONE : MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
        } else if (demux) {
-               ret = __ms_demux_element_prepare(ms_streamer, demux) ? MEDIA_STREAMER_ERROR_NONE : MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+               ret = __ms_demux_element_prepare(ms_streamer, demux);
+               if (MEDIA_STREAMER_ERROR_NONE != ret)
+                               ms_error("Failed to prepare demux element");
        } else {
                GstBin *nodes_bin = GST_BIN(ms_streamer->src_bin);
                if (nodes_bin->numchildren == 0) {
@@ -831,21 +871,36 @@ int __ms_pipeline_prepare(media_streamer_s *ms_streamer)
        }
 
        if (adaptive_src) {
-               if (GST_BIN(ms_streamer->topology_bin)->numchildren == 0) {
+               if (GST_BIN(ms_streamer->topology_bin)->numchildren == 0)
                        ret = __ms_adaptive_element_prepare(adaptive_src, true);
-               } else {
+               else
                        ret = __ms_adaptive_element_prepare(adaptive_src, false);
-               }
        }
 
-       MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_lock_state, ms_streamer);
-       MS_BIN_FOREACH_ELEMENTS(ms_streamer->src_bin, _src_node_prepare, ms_streamer);
+       if (ret != MEDIA_STREAMER_ERROR_NONE)
+               goto prepare_fail;
+
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->sink_bin), _sink_node_prepare, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to prepare nodes within sink bin");
+               goto prepare_fail;
+       }
+
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->src_bin), _src_node_prepare, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to prepare nodes within src bin");
+               goto prepare_fail;
+       }
 
        ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_READY);
        if (ret != MEDIA_STREAMER_ERROR_NONE)
-               __ms_pipeline_unprepare(ms_streamer);
+               goto prepare_fail;
 
        return ret;
+
+prepare_fail:
+       __ms_pipeline_unprepare(ms_streamer);
+       return ret;
 }
 
 static gboolean __ms_bin_remove_elements(media_streamer_s *ms_streamer, GstElement *bin)
@@ -881,6 +936,7 @@ static gboolean __ms_bin_remove_elements(media_streamer_s *ms_streamer, GstEleme
                        it_res = gst_iterator_next(bin_iterator, &element);
                }
        }
+
        g_value_unset(&element);
        gst_iterator_free(bin_iterator);
 
@@ -898,11 +954,37 @@ int __ms_pipeline_unprepare(media_streamer_s *ms_streamer)
        ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
        int ret = MEDIA_STREAMER_ERROR_NONE;
 
-       __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL);
-       ms_streamer->state = MEDIA_STREAMER_STATE_IDLE;
-       ms_streamer->pend_state = ms_streamer->state;
+       ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
+       if (ret != MEDIA_STREAMER_ERROR_NONE)
+               ms_error("Failed to unprepare pipeline");
+
+       if (!ms_streamer->is_interrupted) {
+               media_streamer_resource_state_e res_state = RESOURCE_STATE_ERROR;
+               ret = _ms_resource_manager_get_state(&ms_streamer->resource_manager,
+                       &res_state);
+               if (ret != MEDIA_STREAMER_ERROR_NONE)
+                       ms_error("Failed to get state of resource manager");
+
+               if (RESOURCE_STATE_ACQUIRED == res_state) {
+                       ret = _ms_resource_manager_release(&ms_streamer->resource_manager);
+                       if (ret != MEDIA_STREAMER_ERROR_NONE)
+                               ms_error("Failed to release resources");
+               }
 
-       MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
+               ret = _ms_resource_manager_get_state(&ms_streamer->resource_manager,
+                       &res_state);
+               if (ret != MEDIA_STREAMER_ERROR_NONE)
+                       ms_error("Failed to get state of resource manager");
+
+               if (RESOURCE_STATE_PREPARED == res_state) {
+                       ret = _ms_resource_manager_unprepare(&ms_streamer->resource_manager);
+                       if (ret != MEDIA_STREAMER_ERROR_NONE)
+                               ms_error("Failed to unprepare resources");
+               }
+
+               /* Unprepare resources in case of failure */
+               __ms_release_resources(ms_streamer);
+       }
 
        /* Disconnects and clean all autoplug signals */
        g_list_free_full(ms_streamer->autoplug_sig_list, __ms_signal_destroy);
@@ -1456,3 +1538,63 @@ int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name,
 
        return ret;
 }
+
+gboolean _ms_node_resouces_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
+{
+       media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
+       media_streamer_node_s *node = NULL;
+       GstElement *element = NULL;
+       g_value_set_boolean(ret, FALSE);
+
+       element = GST_ELEMENT(g_value_get_object(item));
+       g_object_ref(element);
+
+       node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
+               GST_ELEMENT_NAME(element));
+       if (!node) {
+               /* If we fail to found corresonding node inside streamer
+                       then apprently this element doesn't require resources */
+               ms_info("Failed to found corresonding node [%s] inside streamer", GST_ELEMENT_NAME(element));
+               g_value_set_boolean(ret, TRUE);
+               return TRUE;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE != _ms_node_resource_aquire(node)) {
+               ms_error("Failed to acquire resource for node [%s]", node->name);
+               return FALSE;
+       }
+
+       g_value_set_boolean(ret, TRUE);
+
+       return TRUE;
+}
+
+gboolean _ms_node_resouces_release_iter(const GValue *item, GValue *ret, gpointer user_data)
+{
+       media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
+       media_streamer_node_s *node = NULL;
+       GstElement *element = NULL;
+       g_value_set_boolean(ret, FALSE);
+
+       element = GST_ELEMENT(g_value_get_object(item));
+       g_object_ref(element);
+
+       node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
+               GST_ELEMENT_NAME(element));
+       if (!node) {
+               /* If we fail to found corresonding node inside streamer
+                       then apprently this element doesn't require resources. */
+               ms_debug("Failed to found corresonding node [%s] inside streamer", GST_ELEMENT_NAME(element));
+               g_value_set_boolean(ret, TRUE);
+               return TRUE;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE != _ms_node_resource_release(node)) {
+               ms_error("Failed to release resource for node [%s]", node->name);
+               return FALSE;
+       }
+
+       g_value_set_boolean(ret, TRUE);
+
+       return TRUE;
+}
diff --git a/src/media_streamer_node_resources.c b/src/media_streamer_node_resources.c
new file mode 100644 (file)
index 0000000..5dabe15
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * 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_node_resources.h>
+#include <media_streamer.h>
+#include <media_streamer_priv.h>
+#include <media_streamer_node.h>
+#include <media_streamer_resource.h>
+
+static gboolean __ms_resource_relese_cb(
+       media_streamer_resource_manager_s *resource_manager,
+       void *user_data)
+{
+       ms_retvm_if(user_data == NULL, FALSE, "user_data is NULL");
+
+       media_streamer_node_s *node = (media_streamer_node_s *) user_data;
+       media_streamer_s *streamer = (media_streamer_s *) node->parent_streamer;
+       ms_info("Received resource_release_cb from node [%s]", node->name);
+
+       /* Here we perform action to release resources relases that
+          were previoursly acquired. Basically what we need to do is
+          to unprepare media streamer. Whithout calling release function
+          on every acquired resource. */
+       g_mutex_lock(&streamer->mutex_lock);
+       streamer->is_interrupted = TRUE;
+       if (MEDIA_STREAMER_ERROR_NONE !=
+               __ms_pipeline_unprepare(streamer)) {
+               ms_error("Failed to unprepare streamer");
+               streamer->is_interrupted = FALSE;
+               g_mutex_unlock(&streamer->mutex_lock);
+               return FALSE;
+       }
+       streamer->is_interrupted = FALSE;
+
+       /* Call interrupted_cb with appropriate code */
+       media_streamer_interrupted_cb interrupted_cb =
+               (media_streamer_interrupted_cb) streamer->interrupted_cb.callback;
+       if (interrupted_cb) {
+               interrupted_cb(MEDIA_STREAMER_INTERRUPTED_BY_RESOURCE_CONFLICT,
+                       streamer->interrupted_cb.user_data);
+       } else {
+               ms_info("Interuption will not be handled because interrupted_cb is NULL");
+       }
+       g_mutex_unlock(&streamer->mutex_lock);
+
+       return TRUE;
+}
+
+static void __ms_node_get_resources_needed(media_streamer_node_s *node,
+       media_streamer_resource_type_e *resource) {
+       media_streamer_node_type_e type = node->type;
+       int subtype = node->subtype;
+
+       ms_debug("Checking resources for node type %d, subtype %d", type, subtype);
+
+       /* Check for node types */
+       switch (type) {
+       case MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER:
+               break;
+       case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER:
+               *resource = RESOURCE_TYPE_VIDEO_DECODER;
+               break;
+       case MEDIA_STREAMER_NODE_TYPE_SRC:
+               if (MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA == subtype)
+                       *resource = RESOURCE_TYPE_CAMERA;
+               break;
+       case MEDIA_STREAMER_NODE_TYPE_SINK:
+               if (MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY == subtype)
+                       *resource = RESOURCE_TYPE_VIDEO_OVERLAY;
+               break;
+       default:
+               break;
+       }
+}
+
+int __ms_node_resouces_init(media_streamer_node_s *node)
+{
+       media_streamer_resource_type_e resource = RESOURCE_TYPE_NONE;
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+
+       /* Check if node require resource manager */
+       __ms_node_get_resources_needed(node, &resource);
+       if (RESOURCE_TYPE_NONE == resource) {
+               ms_info("No resource is needed for %p node type [%d] subtype [%d]",
+                       node, node->type, node->subtype);
+               return MEDIA_STREAMER_ERROR_NONE;
+       }
+
+       /* Initialize resource manager */
+       ret = _ms_resource_manager_init(&node->resource_manager,
+               __ms_resource_relese_cb, node);
+       if (ret != MEDIA_STREAMER_ERROR_NONE) {
+               ms_error("Failed to initialize resource manager for Node");
+               return ret;
+       }
+
+       return ret;
+}
+
+int __ms_node_resouces_deinit(media_streamer_node_s *node)
+{
+       media_streamer_resource_type_e resource = RESOURCE_TYPE_NONE;
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+
+       /* Check if node require resource manager */
+       __ms_node_get_resources_needed(node, &resource);
+       if (RESOURCE_TYPE_NONE == resource) {
+               ms_info("No resource is needed for %p node type [%d] subtype [%d]",
+                       node, node->type, node->subtype);
+               return MEDIA_STREAMER_ERROR_NONE;
+       }
+
+       /* Deinitialize resource manager */
+       ret = _ms_resource_manager_deinit(&node->resource_manager);
+       if (ret != MEDIA_STREAMER_ERROR_NONE) {
+               ms_error("Failed to deinitialize resource manager for Src Node");
+               return ret;
+       }
+
+       return ret;
+}
+
+int __ms_node_resouces_prepare(media_streamer_node_s *node, media_streamer_resource_type_e resource)
+{
+       media_streamer_resource_state_e resource_state = RESOURCE_STATE_NONE;
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+
+       ret = _ms_resource_manager_get_state(&node->resource_manager, &resource_state);
+       if (ret != MEDIA_STREAMER_ERROR_NONE) {
+               ms_error("Failed to get state from resource menager");
+               return ret;
+       } else {
+               if (RESOURCE_STATE_NONE == resource_state ||
+                       RESOURCE_STATE_ERROR == resource_state) {
+                       ms_error("Wrong resource manager state %d", resource_state);
+                       return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               } else if (RESOURCE_STATE_INITIALIZED == resource_state) {
+                       /* For every node we should call resource manager function to resource */
+                       ret = _ms_resource_manager_prepare(&node->resource_manager, resource);
+               } else {
+                       ms_info("Resource state is %d. No need to prepare", resource_state);
+                       return MEDIA_STREAMER_ERROR_NONE;
+               }
+       }
+
+       return ret;
+}
+
+int __ms_node_resouces_unprepare(media_streamer_node_s *node, media_streamer_resource_type_e resource)
+{
+       media_streamer_resource_state_e resource_state = RESOURCE_STATE_NONE;
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+
+       ret = _ms_resource_manager_get_state(&node->resource_manager, &resource_state);
+       if (ret != MEDIA_STREAMER_ERROR_NONE) {
+               ms_error("Failed to get state from resource menager");
+               return ret;
+       } else {
+               if (RESOURCE_STATE_PREPARED == resource_state) {
+                       /* For every node we should call resource manager function to resource */
+                       ret = _ms_resource_manager_unprepare(&node->resource_manager);
+               } else {
+                       ms_error("Wrong resource manager state %d", resource_state);
+                       return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               }
+       }
+
+       return ret;
+}
+
+int _ms_node_resource_aquire(media_streamer_node_s *node)
+{
+       media_streamer_resource_state_e resource_state = RESOURCE_STATE_NONE;
+       media_streamer_resource_type_e resource = RESOURCE_TYPE_NONE;
+
+       /* Check if node require resource manager */
+       __ms_node_get_resources_needed(node, &resource);
+       if (RESOURCE_TYPE_NONE == resource) {
+               ms_info("No resource is needed for %p node type [%d] subtype [%d]",
+                       node, node->type, node->subtype);
+               return MEDIA_STREAMER_ERROR_NONE;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE != __ms_node_resouces_prepare(node, resource)) {
+               ms_error("Failed to prepare resources for Node [%p]", node);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE !=
+               _ms_resource_manager_get_state(&node->resource_manager, &resource_state)) {
+               ms_error("Failed to get state from resource menager");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       } else {
+               ms_debug("Resource manager state %d", resource_state);
+       }
+
+       ms_debug("Acquire resource for node [%s]", node->name);
+
+       if (RESOURCE_STATE_PREPARED != resource_state) {
+               ms_debug("Resources were not prepared %d. Skipping...", resource_state);
+               return MEDIA_STREAMER_ERROR_NONE;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE !=
+               _ms_resource_manager_acquire(&node->resource_manager)) {
+               ms_error("Failed to acquire resources for node [%s]", node->name);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int _ms_node_resource_release(media_streamer_node_s *node)
+{
+       media_streamer_resource_state_e resource_state = RESOURCE_STATE_NONE;
+       media_streamer_resource_type_e resource = RESOURCE_TYPE_NONE;
+
+  /* Check if node require resource manager */
+       __ms_node_get_resources_needed(node, &resource);
+       if (RESOURCE_TYPE_NONE == resource) {
+               ms_info("No resource is needed for %p node type [%d] subtype [%d]",
+                       node, node->type, node->subtype);
+               return MEDIA_STREAMER_ERROR_NONE;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE !=
+               _ms_resource_manager_get_state(&node->resource_manager, &resource_state)) {
+               ms_error("Failed to get state from resource menager");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       } else {
+               ms_debug("Resource manager state %d", resource_state);
+       }
+
+       ms_debug("Release resources for node [%s]", node->name);
+
+       if (RESOURCE_STATE_ACQUIRED != resource_state) {
+               ms_debug("Resources were not acquired %d. Skipping...", resource_state);
+               return MEDIA_STREAMER_ERROR_NONE;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE !=
+               _ms_resource_manager_release(&node->resource_manager)) {
+               ms_error("Failed to release resources for node [%s]", node->name);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE != __ms_node_resouces_unprepare(node, resource)) {
+               ms_error("Failed to unprepare resources for Node [%p]", node);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
index 47dd4bbfedde9674a99aa4c66dca2619a06df10a..3fe8485bc6adf90a94f573efacea5f6cb1ef617e 100644 (file)
 #include "media_streamer_util.h"
 #include "media_streamer_node.h"
 #include "media_streamer_gst.h"
+#include "media_streamer_resource.h"
 
 #define GST_TIME_TO_MSEC(t) (t == GST_CLOCK_TIME_NONE ? t : (int)(((GstClockTime)(t)) / GST_MSECOND))
 
+int __ms_change_resources_state(media_streamer_s *ms_streamer, media_streamer_state_e state);
+static gboolean media_streamer_resource_relese_cb(media_streamer_resource_manager_s *resource_manager, void *user_data);
+
 int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e state)
 {
        int ret = MEDIA_STREAMER_ERROR_NONE;
@@ -28,6 +32,14 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat
        ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
        ms_retvm_if(ms_streamer->state == state, MEDIA_STREAMER_ERROR_NONE, "Media streamer already in this state");
 
+       if (!ms_streamer->is_interrupted) {
+               ret = __ms_change_resources_state(ms_streamer, state);
+               if (MEDIA_STREAMER_ERROR_NONE != ret) {
+                       ms_error("Failed to change resources state for streamer %p", ms_streamer);
+                       return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               }
+       }
+
        switch (state) {
        case MEDIA_STREAMER_STATE_NONE:
                /*
@@ -43,9 +55,10 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat
                 * Unlink all gst_elements, set pipeline into state NULL
                 */
                ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL);
-               MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
-               ms_streamer->pend_state = MEDIA_STREAMER_STATE_NONE;
+               __ms_bin_foreach_elements(GST_BIN(ms_streamer->sink_bin), __ms_element_unlock_state, ms_streamer);
+               ms_streamer->pend_state = MEDIA_STREAMER_STATE_IDLE;
                ms_streamer->state = state;
+
                break;
        case MEDIA_STREAMER_STATE_READY:
                ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
@@ -53,7 +66,7 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat
                break;
        case MEDIA_STREAMER_STATE_PLAYING:
                ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PLAYING);
-               MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer);
+               __ms_bin_foreach_elements(GST_BIN(ms_streamer->sink_bin), __ms_element_unlock_state, ms_streamer);
                ms_streamer->pend_state = MEDIA_STREAMER_STATE_PLAYING;
                break;
        case MEDIA_STREAMER_STATE_PAUSED:
@@ -77,6 +90,14 @@ int __ms_create(media_streamer_s *ms_streamer)
        ms_streamer->nodes_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __ms_node_remove_from_table);
        ms_retvm_if(ms_streamer->nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating hash table");
 
+       if (MEDIA_STREAMER_ERROR_NONE != _ms_resource_manager_init(
+               &ms_streamer->resource_manager,
+               media_streamer_resource_relese_cb,
+               ms_streamer)) {
+               ms_error("Failed to init resource manager for media streamer");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
        return __ms_pipeline_create(ms_streamer);
 }
 
@@ -155,9 +176,165 @@ int __ms_streamer_destroy(media_streamer_s *ms_streamer)
        if (ms_streamer->ini.exclude_elem_names)
                g_strfreev(ms_streamer->ini.exclude_elem_names);
 
+       /* Clean up resource required elements list */
+       if (ms_streamer->ini.resource_required_elem_names)
+               g_strfreev(ms_streamer->ini.resource_required_elem_names);
+
+       if (MEDIA_STREAMER_ERROR_NONE !=
+               _ms_resource_manager_deinit(&ms_streamer->resource_manager)) {
+               ms_error("Failed to deinit resource manager for media streamer");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
        g_mutex_unlock(&ms_streamer->mutex_lock);
        g_mutex_clear(&ms_streamer->mutex_lock);
        MS_SAFE_FREE(ms_streamer);
 
        return ret;
 }
+
+int __ms_aquire_resources(media_streamer_s *ms_streamer)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+
+       /* Acquire resources for src bin */
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->src_bin),
+               _ms_node_resouces_acquire_iter, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to acquire resources for src bin");
+               return ret;
+       }
+
+       /* Acquire resources for topology bin. If user doesn't
+          add nodes explicitly they will be acquired later.
+                For example when decodebin is used resources are quired
+                when 'autoplug-select' signal is triggered for new GstElement. */
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->topology_bin),
+               _ms_node_resouces_acquire_iter, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to acquire resources for topology bin");
+               return ret;
+       }
+
+       /* Acquire resources for src bin */
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->sink_bin),
+               _ms_node_resouces_acquire_iter, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to acquire resources for sink bin");
+               return ret;
+       }
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_release_resources(media_streamer_s *ms_streamer)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+
+       /* Release resources for src bin */
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->src_bin),
+               _ms_node_resouces_release_iter, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to release resources for src bin");
+               return ret;
+       }
+
+       /* Release resources for topology bin. Here we also consider
+                nodes that were not added by user explicitly (e.g. decodebin
+                was used). */
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->topology_bin),
+               _ms_node_resouces_release_iter, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to release resources for topology bin");
+               return ret;
+       }
+
+       /* Release resources for src bin */
+       ret = __ms_bin_foreach_elements(GST_BIN(ms_streamer->sink_bin),
+               _ms_node_resouces_release_iter, ms_streamer);
+       if (MEDIA_STREAMER_ERROR_NONE != ret) {
+               ms_error("Failed to release resources for sink bin");
+               return ret;
+       }
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_change_resources_state(media_streamer_s *ms_streamer, media_streamer_state_e state)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+
+       /* According to state graph we need to handle only this two states
+        * and different transotions into them */
+       if (state == MEDIA_STREAMER_STATE_IDLE) {
+               switch (ms_streamer->pend_state) {
+               case MEDIA_STREAMER_STATE_READY:
+               case MEDIA_STREAMER_STATE_PAUSED:
+               case MEDIA_STREAMER_STATE_PLAYING:
+                       /* After unprepare function call */
+                       ret = __ms_release_resources(ms_streamer);
+                       break;
+               case MEDIA_STREAMER_STATE_NONE:
+               case MEDIA_STREAMER_STATE_IDLE:
+                       /* We do not considering double unprepare */
+               case MEDIA_STREAMER_STATE_SEEKING:
+               default:
+                       break;
+               }
+       } else if (state == MEDIA_STREAMER_STATE_READY) {
+               switch (ms_streamer->pend_state) {
+               case MEDIA_STREAMER_STATE_IDLE:
+                       /* After prepare function */
+                       ret = __ms_aquire_resources(ms_streamer);
+                       break;
+               case MEDIA_STREAMER_STATE_PAUSED:
+               case MEDIA_STREAMER_STATE_PLAYING:
+               case MEDIA_STREAMER_STATE_NONE:
+               case MEDIA_STREAMER_STATE_SEEKING:
+               default:
+                       break;
+               }
+       } else {
+               ms_debug("Ignoring state for resource managements");
+       }
+
+       return ret;
+}
+
+static gboolean media_streamer_resource_relese_cb(
+       media_streamer_resource_manager_s *resource_manager,
+       void *user_data)
+{
+       ms_retvm_if(user_data == NULL, FALSE, "user_data is NULL");
+
+       media_streamer_s *streamer = (media_streamer_s *) user_data;
+       ms_info("Reseived release_cb for streamer %p", streamer);
+
+       /* Here we perform action to release resources relases that
+                were previoursly acquired (dynamically created case).
+                Basically what we need to do is to unprepare media streamer.
+                Whithout calling release function on every acquired resource. */
+       g_mutex_lock(&streamer->mutex_lock);
+       streamer->is_interrupted = TRUE;
+       if (MEDIA_STREAMER_ERROR_NONE !=
+               __ms_pipeline_unprepare(streamer)) {
+               ms_error("Failed to unprepare streamer");
+               streamer->is_interrupted = FALSE;
+               g_mutex_unlock(&streamer->mutex_lock);
+               return FALSE;
+       }
+       streamer->is_interrupted = FALSE;
+
+       /* Call interrupted_cb with appropriate code */
+       media_streamer_interrupted_cb interrupted_cb =
+               (media_streamer_interrupted_cb) streamer->interrupted_cb.callback;
+       if (interrupted_cb) {
+               interrupted_cb(MEDIA_STREAMER_INTERRUPTED_BY_RESOURCE_CONFLICT,
+                       streamer->interrupted_cb.user_data);
+       } else {
+               ms_info("Interuption will not be handled because interrupted_cb is NULL");
+       }
+       g_mutex_unlock(&streamer->mutex_lock);
+
+       return TRUE;
+}
diff --git a/src/media_streamer_resource.c b/src/media_streamer_resource.c
new file mode 100644 (file)
index 0000000..4d84082
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2016 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_util.h"
+#include "media_streamer_resource.h"
+#include "media_streamer_priv.h"
+#include <murphy/common/glib-glue.h>
+
+#define MRP_APP_CLASS_FOR_MSTREAMER   "media"
+#define MRP_RESOURCE_TYPE_MANDATORY TRUE
+#define MRP_RESOURCE_TYPE_EXCLUSIVE FALSE
+
+enum {
+       MRP_RESOURCE_FOR_VIDEO_OVERLAY,
+       MRP_RESOURCE_FOR_CAMERA,
+       MRP_RESOURCE_FOR_VIDEO_DECODER,
+       MRP_RESOURCE_MAX,
+};
+const char* resource_str[MRP_RESOURCE_MAX] = {
+       "video_overlay",
+       "camera",
+       "video_decoder",
+};
+
+#define MEDIA_STREAMER_WAIT_CONNECTION_TIMEOUT 5
+
+#define MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(x_ms_resource_manager) \
+do { \
+       if (!x_ms_resource_manager) { \
+               ms_error("no resource manager instance");\
+               return MEDIA_STREAMER_ERROR_INVALID_PARAMETER; \
+       } \
+} while (0);
+
+static int __ms_resource_manager_wait_connection(media_streamer_resource_manager_s *resource_manager)
+{
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+
+       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+
+       if (resource_manager->is_connected) {
+               ms_debug("Already connected to resource server");
+       } else {
+               gint64 end_time = g_get_monotonic_time() + MEDIA_STREAMER_RESOURCE_TIMEOUT*G_TIME_SPAN_SECOND;
+
+               ms_debug("Not connected to resource server yet. Waiting...");
+
+               if (!g_cond_wait_until(&resource_manager->cond,
+                       &resource_manager->lock, end_time)) {
+                               ms_error("Could not connect to resource server");
+                               MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+                               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               } else {
+                       if (resource_manager->is_connected)
+                               ms_debug("Successfully connected to resource server!");
+                       else {
+                               ms_error("Failed to connect to resource server");
+                               MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+                               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+                       }
+               }
+       }
+
+       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static char *state_to_str(mrp_res_resource_state_t st)
+{
+       char *state = "unknown";
+       switch (st) {
+       case MRP_RES_RESOURCE_ACQUIRED:
+               state = "acquired";
+               break;
+       case MRP_RES_RESOURCE_LOST:
+               state = "lost";
+               break;
+       case MRP_RES_RESOURCE_AVAILABLE:
+               state = "available";
+               break;
+       case MRP_RES_RESOURCE_PENDING:
+               state = "pending";
+               break;
+       case MRP_RES_RESOURCE_ABOUT_TO_LOOSE:
+               state = "about to loose";
+               break;
+       }
+       return state;
+}
+
+static void mrp_state_callback(mrp_res_context_t *context, mrp_res_error_t err, void *user_data)
+{
+       int i = 0;
+       const mrp_res_resource_set_t *rset;
+       mrp_res_resource_t *resource;
+       media_streamer_resource_manager_s* resource_manager = NULL;
+
+       if (user_data == NULL) {
+               ms_error(" - user data is null");
+               return;
+       }
+       resource_manager = (media_streamer_resource_manager_s *) user_data;
+
+       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+
+       if (err != MRP_RES_ERROR_NONE) {
+               ms_error(" - error message received from Murphy, err(0x%x)", err);
+               g_cond_signal(&resource_manager->cond);
+               MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+               return;
+       }
+
+       switch (context->state) {
+       case MRP_RES_CONNECTED:
+               ms_debug(" - connected to Murphy");
+               if ((rset = mrp_res_list_resources(context)) != NULL) {
+                       mrp_res_string_array_t *resource_names;
+                       resource_names = mrp_res_list_resource_names(rset);
+                       if (!resource_names) {
+                               ms_error(" - no resources available");
+                               return;
+                       }
+                       for (i = 0; i < resource_names->num_strings; i++) {
+                               resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
+                               if (resource)
+                                       ms_debug(" - available resource: %s", resource->name);
+                       }
+                       mrp_res_free_string_array(resource_names);
+               }
+               resource_manager->is_connected = TRUE;
+               g_cond_signal(&resource_manager->cond);
+               break;
+       case MRP_RES_DISCONNECTED:
+               ms_debug(" - disconnected from Murphy");
+               if (resource_manager->rset) {
+                       mrp_res_delete_resource_set(resource_manager->rset);
+                       resource_manager->rset = NULL;
+               }
+               mrp_res_destroy(resource_manager->context);
+               resource_manager->context = NULL;
+               resource_manager->is_connected = FALSE;
+               g_cond_signal(&resource_manager->cond);
+               break;
+       }
+
+       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+
+       return;
+}
+
+static void mrp_rset_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
+{
+       int i = 0;
+       media_streamer_resource_manager_s *resource_manager = (media_streamer_resource_manager_s *)user_data;
+       mrp_res_resource_t *res;
+
+       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+
+       if (!mrp_res_equal_resource_set(rs, resource_manager->rset)) {
+               ms_info("- resource set(%p) is not same as this resource_manager handle's(%p)", rs, resource_manager->rset);
+               MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+               return;
+       }
+
+       ms_debug(" - resource set state of resource_manager(%p) is changed to [%s]", resource_manager, state_to_str(rs->state));
+       for (i = 0; i < MRP_RESOURCE_MAX; i++) {
+               res = mrp_res_get_resource_by_name(rs, resource_str[i]);
+               if (res == NULL)
+                       ms_info(" -- %s not present in resource set", resource_str[i]);
+               else
+                       ms_info(" -- resource name [%s] -> [%s]'", res->name, state_to_str(res->state));
+       }
+
+       mrp_res_delete_resource_set(resource_manager->rset);
+       resource_manager->rset = mrp_res_copy_resource_set(rs);
+
+       if (rs->state == MRP_RES_RESOURCE_ACQUIRED) {
+               ms_debug(" - resource set is acquired");
+               resource_manager->state = RESOURCE_STATE_ACQUIRED;
+               MEDIA_STREAMER_RESOURCE_SIGNAL(resource_manager);
+       } else if ((resource_manager->state >= RESOURCE_STATE_ACQUIRED) &&
+                          (rs->state == MRP_RES_RESOURCE_AVAILABLE)) {
+               ms_debug(" - resource set is released");
+               resource_manager->state = RESOURCE_STATE_PREPARED;
+               MEDIA_STREAMER_RESOURCE_SIGNAL(resource_manager);
+       }
+
+       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+}
+
+
+static void mrp_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
+{
+       int i = 0;
+       media_streamer_resource_manager_s *resource_manager = NULL;
+       mrp_res_resource_t *res;
+
+       if (user_data == NULL) {
+               ms_error("- user_data is null");
+               return;
+       }
+       resource_manager = (media_streamer_resource_manager_s *) user_data;
+
+       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+
+       if (!mrp_res_equal_resource_set(rs, resource_manager->rset)) {
+               ms_info("- resource set(%p) is not same as this resource_manager handle's(%p)",
+                       rs, resource_manager->rset);
+               return;
+       }
+
+       ms_debug(" - resource set state of resource manager (%p) is changed to [%s]",
+               resource_manager, state_to_str(rs->state));
+       for (i = 0; i < MRP_RESOURCE_MAX; i++) {
+               res = mrp_res_get_resource_by_name(rs, resource_str[i]);
+               if (res == NULL)
+                       ms_info(" -- %s not present in resource set", resource_str[i]);
+               else
+                       ms_debug(" -- resource name [%s] -> [%s] %d'", res->name,
+                               state_to_str(res->state), res->state);
+       }
+
+       if (resource_manager->release_cb) {
+               if (!resource_manager->release_cb(resource_manager, resource_manager->user_data)) {
+                       ms_error("release_cb failed");
+               } else {
+                       ms_info("release_cb is fine");
+               }
+       } else {
+               ms_error("release cb is NULL. Something wrong happens...");
+       }
+
+       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+
+       return;
+}
+
+static int create_rset(media_streamer_resource_manager_s *resource_manager)
+{
+       if (resource_manager->rset) {
+               ms_error(" - resource set was already created");
+               return MEDIA_STREAMER_ERROR_INVALID_STATE;
+       }
+
+       resource_manager->rset =
+               mrp_res_create_resource_set(resource_manager->context,
+                                                                                                                               MRP_APP_CLASS_FOR_MSTREAMER,
+                                                                                                                               mrp_rset_state_callback,
+                                                                                                                               (void*)resource_manager);
+       if (resource_manager->rset == NULL) {
+               ms_error(" - could not create resource set");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       if (!mrp_res_set_autorelease(TRUE, resource_manager->rset))
+               ms_info(" - could not set autorelease flag!");
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static int include_resource(media_streamer_resource_manager_s *resource_manager, const char *resource_name)
+{
+       mrp_res_resource_t *resource = NULL;
+       resource = mrp_res_create_resource(resource_manager->rset,
+                               resource_name,
+                               MRP_RESOURCE_TYPE_MANDATORY,
+                               MRP_RESOURCE_TYPE_EXCLUSIVE);
+       if (resource == NULL) {
+               ms_error(" - could not include resource[%s]", resource_name);
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       ms_debug(" - include resource[%s]", resource_name);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static int set_resource_release_cb(media_streamer_resource_manager_s *resource_manager)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+       bool mrp_ret = FALSE;
+
+       if (resource_manager->rset) {
+               if (MRP_RES_RESOURCE_PENDING == resource_manager->rset->state) {
+                       /* FIXME: This workarond is only temporary solution.
+                          When resource set is acquired again after lost the state is 'available'
+                                and no 'pending'. Thus we skip setting reelease callback as it already
+                                was set. */
+                       mrp_ret = mrp_res_set_release_callback(resource_manager->rset, mrp_resource_release_cb, resource_manager);
+                       if (!mrp_ret) {
+                               ms_error(" - could not set release callback");
+                               ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+                       }
+               }
+       } else {
+               ms_error(" - resource set is null");
+               ret = MEDIA_STREAMER_ERROR_INVALID_STATE;
+       }
+
+       return ret;
+}
+
+int _ms_resource_manager_init(media_streamer_resource_manager_s *resource_manager,
+       resource_relese_cb release_cb, void *user_data)
+{
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+       ms_retvm_if(release_cb == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+               "release_cb is NULL");
+
+       g_mutex_init(&resource_manager->lock);
+       g_cond_init(&resource_manager->cond);
+
+       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+
+       GMainContext *mrp_ctx = g_main_context_new();
+       if (!mrp_ctx) {
+               ms_error("- could not create main context for resource manager");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       GMainLoop *mrp_loop = g_main_loop_new(mrp_ctx, TRUE);
+       g_main_context_unref(mrp_ctx);
+       if (!mrp_loop) {
+               ms_error("- could not create glib mainloop for resource manager");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       resource_manager->mloop = mrp_mainloop_glib_get(mrp_loop);
+       g_main_loop_unref(mrp_loop);
+       if (resource_manager->mloop) {
+               resource_manager->context = mrp_res_create(resource_manager->mloop,
+                       mrp_state_callback, resource_manager);
+
+               if (resource_manager->context == NULL) {
+                       ms_error(" - could not get context for resource manager");
+                       mrp_mainloop_destroy(resource_manager->mloop);
+                       resource_manager->mloop = NULL;
+                       return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               }
+               resource_manager->user_data = user_data;
+       } else {
+               ms_error("- could not get mainloop for resource manager");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
+       resource_manager->release_cb = release_cb;
+       resource_manager->state = RESOURCE_STATE_INITIALIZED;
+
+       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int _ms_resource_manager_prepare(media_streamer_resource_manager_s *resource_manager, media_streamer_resource_type_e resource_type)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+       __ms_resource_manager_wait_connection(resource_manager);
+
+       if (!resource_manager->rset)
+               ret = create_rset(resource_manager);
+
+       if (ret == MEDIA_STREAMER_ERROR_NONE) {
+               switch (resource_type) {
+               case RESOURCE_TYPE_VIDEO_OVERLAY:
+                       ret = include_resource(resource_manager, resource_str[MRP_RESOURCE_FOR_VIDEO_OVERLAY]);
+                       break;
+               case RESOURCE_TYPE_VIDEO_DECODER:
+                       ret = include_resource(resource_manager, resource_str[MRP_RESOURCE_FOR_VIDEO_DECODER]);
+                       break;
+               case RESOURCE_TYPE_CAMERA:
+                       ret = include_resource(resource_manager, resource_str[MRP_RESOURCE_FOR_CAMERA]);
+                       break;
+               case RESOURCE_TYPE_NONE:
+               default:
+                       ms_error("Wrong resource type %d", resource_type);
+                       ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+                       break;
+               }
+       }
+
+       if (MEDIA_STREAMER_ERROR_NONE == ret) {
+               resource_manager->state = RESOURCE_STATE_PREPARED;
+       } else {
+               resource_manager->state = RESOURCE_STATE_ERROR;
+       }
+
+       return ret;
+}
+
+int _ms_resource_manager_acquire(media_streamer_resource_manager_s *resource_manager)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+       __ms_resource_manager_wait_connection(resource_manager);
+
+       if (resource_manager->rset == NULL) {
+               ms_error("- could not acquire resource, resource set is null");
+               ret = MEDIA_STREAMER_ERROR_INVALID_STATE;
+       } else {
+               ret = set_resource_release_cb(resource_manager);
+               if (ret) {
+                       ms_error("- could not set resource release cb, ret(%d)", ret);
+                       ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               } else {
+                       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+
+                       ret = mrp_res_acquire_resource_set(resource_manager->rset);
+                       if (ret) {
+                               ms_error("- could not acquire resource, ret(%d)", ret);
+                               ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+                       } else {
+                               gint64 end_time = g_get_monotonic_time() + MEDIA_STREAMER_RESOURCE_TIMEOUT*G_TIME_SPAN_SECOND;
+
+                               ms_debug("- acquire resource waiting..%p till %lld", resource_manager, end_time);
+                               if (!MEDIA_STREAMER_RESOURCE_WAIT_UNTIL(resource_manager, end_time)) {
+                                       ms_error("- could not acquire resource");
+                                       ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+                               } else {
+                                       ms_debug("- resources are acquired");
+                               }
+                       }
+                       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+               }
+       }
+
+       return ret;
+}
+
+int _ms_resource_manager_release(media_streamer_resource_manager_s *resource_manager)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+       __ms_resource_manager_wait_connection(resource_manager);
+
+       if (resource_manager->rset == NULL) {
+               ms_error("- could not release resource, resource set is null");
+               ret = MEDIA_STREAMER_ERROR_INVALID_STATE;
+       } else {
+               if (resource_manager->rset->state != MRP_RES_RESOURCE_ACQUIRED) {
+                       ms_error("- could not release resource, resource set state is [%s]", state_to_str(resource_manager->rset->state));
+                       ret = MEDIA_STREAMER_ERROR_INVALID_STATE;
+               } else {
+                       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+                       ret = mrp_res_release_resource_set(resource_manager->rset);
+                       if (ret) {
+                               ms_error("- could not release resource, ret(%d)", ret);
+                               ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+                       } else {
+                               gint64 end_time = g_get_monotonic_time() + MEDIA_STREAMER_RESOURCE_TIMEOUT*G_TIME_SPAN_SECOND;
+
+                               ms_debug("- release resource waiting..%p till %lld", resource_manager, end_time);
+                               if (!MEDIA_STREAMER_RESOURCE_WAIT_UNTIL(resource_manager, end_time)) {
+                                       ms_info("- could not release resource in time");
+                                       ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+                               } else {
+                                       ms_debug("- resources are released");
+                               }
+                       }
+                       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+               }
+       }
+
+       return ret;
+}
+
+int _ms_resource_manager_unprepare(media_streamer_resource_manager_s *resource_manager)
+{
+       int ret = MEDIA_STREAMER_ERROR_NONE;
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+       __ms_resource_manager_wait_connection(resource_manager);
+
+       if (resource_manager->rset == NULL) {
+               ms_error("- could not unprepare for resource_manager, _ms_resource_manager_prepare() first");
+               ret = MEDIA_STREAMER_ERROR_INVALID_STATE;
+       } else {
+               MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+               mrp_res_delete_resource_set(resource_manager->rset);
+               resource_manager->rset = NULL;
+               MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+       }
+
+       resource_manager->state = RESOURCE_STATE_INITIALIZED;
+
+       return ret;
+}
+
+int _ms_resource_manager_deinit(media_streamer_resource_manager_s *resource_manager)
+{
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+       __ms_resource_manager_wait_connection(resource_manager);
+
+       MEDIA_STREAMER_RESOURCE_LOCK(resource_manager);
+
+       if (resource_manager->rset) {
+               if (resource_manager->rset->state == MRP_RES_RESOURCE_ACQUIRED) {
+                       if (mrp_res_release_resource_set(resource_manager->rset))
+                               ms_error("- could not release resource");
+               }
+               mrp_res_delete_resource_set(resource_manager->rset);
+               resource_manager->rset = NULL;
+       }
+
+       if (resource_manager->context) {
+               mrp_res_destroy(resource_manager->context);
+               resource_manager->context = NULL;
+       }
+
+       if (resource_manager->mloop) {
+               mrp_mainloop_destroy(resource_manager->mloop);
+               resource_manager->mloop = NULL;
+       }
+
+       resource_manager->release_cb = NULL;
+
+       resource_manager->state = RESOURCE_STATE_NONE;
+
+       MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
+
+       g_mutex_clear(&resource_manager->lock);
+       g_cond_clear(&resource_manager->cond);
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int _ms_resource_manager_get_state(media_streamer_resource_manager_s *resource_manager, media_streamer_resource_state_e *state)
+{
+       MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
+       ms_retvm_if(state == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+               "state is NULL");
+
+       ms_debug("resource_state is %d", resource_manager->state);
+
+       *state = resource_manager->state;
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
index 8272f5074258135b4c9e7c929f0bca43a9dd83b7..4ea599f7bd8996d99b5e08aba569fae04bd7d10a 100644 (file)
@@ -17,6 +17,7 @@
 #include <glib/gstdio.h>
 
 #include <media_streamer.h>
+#include <media_streamer_priv.h>
 #include <media_streamer_util.h>
 
 #include <fcntl.h>
@@ -160,6 +161,8 @@ void __ms_load_ini_settings(media_streamer_ini_t *ini)
 
                /* Read exclude elements list */
                __ms_ini_read_list("general:exclude elements", &ini->exclude_elem_names);
+               /* Read resource require elements list */
+               __ms_ini_read_list("general:resource elements", &ini->resource_required_elem_names);
                /* Read gstreamer arguments list */
                __ms_ini_read_list("general:gstreamer arguments", &ini->gst_args);
 
@@ -327,3 +330,43 @@ int __ms_node_uri_path_check(const char *file_uri)
 
        return MEDIA_STREAMER_ERROR_NONE;
 }
+
+int __ms_bin_foreach_elements(GstBin *bin, GstIteratorFoldFunction func, void *user_data)
+{
+       media_streamer_s *streamer = (media_streamer_s *) user_data;
+
+       if (!GST_BIN_NUMCHILDREN(bin)) {
+               ms_debug("No elements were added to bin [%s]. Skipping... ",
+                       GST_ELEMENT_NAME(bin));
+               return MEDIA_STREAMER_STATE_NONE;
+       }
+
+       GstIterator *iter = gst_bin_iterate_recurse(bin);
+       GValue ret = G_VALUE_INIT;
+       GstIteratorResult result = GST_ITERATOR_DONE;
+
+       g_value_init(&ret, G_TYPE_BOOLEAN);
+       result = gst_iterator_fold(iter, func, &ret, streamer);
+       gst_iterator_free(iter);
+
+       switch (result) {
+       case GST_ITERATOR_RESYNC:
+       case GST_ITERATOR_ERROR:
+               ms_error("Error while iterating elements in bin [%s]!",
+                       GST_ELEMENT_NAME(bin));
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               break;
+       case GST_ITERATOR_DONE:
+       case GST_ITERATOR_OK:
+               /* Check for last return value */
+               if (!g_value_get_boolean(&ret)) {
+                       ms_error("Failed to prepare one of nodes");
+                       return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
index 309a1340c6c7c56fb6f6f73d58845a94c6bea3c2..3c8d834e1be487b77b64714e94f39854fb6533c1 100644 (file)
@@ -182,7 +182,12 @@ static void streamer_seek_cb(void *user_data)
 
 static void streamer_changed_cb(media_streamer_h streamer, media_streamer_state_e previous_state, media_streamer_state_e current_state, void *user_data)
 {
-       g_print("Media Streamer State changed [%d] -> [%d]", previous_state, current_state);
+       g_print("Media Streamer State changed [%d] -> [%d]\n", previous_state, current_state);
+}
+
+static void streamer_interrubted_cb(media_streamer_interrupted_code_e code, void *user_data)
+{
+       g_print("Media Streamer was interrupted with code [%d]\n", code);
 }
 
 static void _create(media_streamer_h *streamer)
@@ -215,6 +220,7 @@ static void _prepare(void)
        }
 
        media_streamer_set_state_change_cb(current_media_streamer, streamer_changed_cb, NULL);
+       media_streamer_set_interrupted_cb(current_media_streamer, streamer_interrubted_cb, NULL);
        g_print("== success prepare \n");
 }
 
@@ -290,13 +296,13 @@ static void _destroy(media_streamer_h streamer)
        int ret = MEDIA_STREAMER_ERROR_NONE;
 
        if (streamer == NULL) {
-               g_print("media streamer already destroyed");
+               g_print("media streamer already destroyed\n");
                return;
        }
 
        ret = media_streamer_destroy(streamer);
        if (ret != MEDIA_STREAMER_ERROR_NONE) {
-               g_print("Fail to destroy media streamer");
+               g_print("Fail to destroy media streamer\n");
                return;
        }
 
@@ -313,7 +319,7 @@ static void _destroy(media_streamer_h streamer)
 static void create_formats(void)
 {
        if (!vfmt_raw || !vfmt_encoded || !afmt_raw)
-               g_print("Formats already created!");
+               g_print("Formats already created!\n");
 
        /* Define video raw format */
        media_format_create(&vfmt_raw);
@@ -1551,7 +1557,7 @@ void _interpret_getting_uri_menu(char *cmd)
                return;
        }
 
-       g_print("_interpret_getting_uri_menu %d %d %d", g_menu_state, g_sub_menu_state, g_scenario_mode);
+       g_print("_interpret_getting_uri_menu %d %d %d\n", g_menu_state, g_sub_menu_state, g_scenario_mode);
        if (g_menu_state == MENU_STATE_PLAYING_MENU) {
                if (g_scenario_mode == SCENARIO_MODE_FILE_SUBTITLE_VIDEO_AUDIO) {
                        g_sub_menu_state = SUBMENU_STATE_GETTING_SUBFILE_URI;