From e80f13f7e477027275dc4671b987dbc08e390640 Mon Sep 17 00:00:00 2001
From: Oleksandr Popov
Date: Mon, 5 Dec 2016 18:35:48 +0200
Subject: [PATCH 01/16] Added implementation of interruption by resource
manager
Signed-off-by: Oleksandr Popov
Change-Id: I213f1aa51bf6e051baf0a435f268c2798124d558
(cherry picked from commit c252c62a3ea4e82a304a8b32c53d8ab9a1fd5afa)
---
CMakeLists.txt | 4 +-
include/media_streamer_gst.h | 4 +-
include/media_streamer_node.h | 3 +
include/media_streamer_node_resources.h | 36 +++
include/media_streamer_priv.h | 9 +
include/media_streamer_resource.h | 84 +++++
include/media_streamer_util.h | 33 +-
packaging/capi-media-streamer.spec | 2 +
src/media_streamer.c | 35 ++
src/media_streamer_gst.c | 45 ++-
src/media_streamer_node.c | 202 ++++++++++--
src/media_streamer_node_resources.c | 268 ++++++++++++++++
src/media_streamer_priv.c | 183 ++++++++++-
src/media_streamer_resource.c | 550 ++++++++++++++++++++++++++++++++
src/media_streamer_util.c | 43 +++
test/media_streamer_test.c | 16 +-
16 files changed, 1453 insertions(+), 64 deletions(-)
create mode 100644 include/media_streamer_node_resources.h
create mode 100644 include/media_streamer_resource.h
create mode 100644 src/media_streamer_node_resources.c
create mode 100644 src/media_streamer_resource.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 01c0703..0c7e7c5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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})
diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h
index 37f2b2b..11b1da8 100644
--- a/include/media_streamer_gst.h
+++ b/include/media_streamer_gst.h
@@ -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.
diff --git a/include/media_streamer_node.h b/include/media_streamer_node.h
index eb89d8c..f79f9e5 100644
--- a/include/media_streamer_node.h
+++ b/include/media_streamer_node.h
@@ -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
index 0000000..2f4dd12
--- /dev/null
+++ b/include/media_streamer_node_resources.h
@@ -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
+#include
+
+#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__ */
diff --git a/include/media_streamer_priv.h b/include/media_streamer_priv.h
index 8ffe1c4..14a45f7 100755
--- a/include/media_streamer_priv.h
+++ b/include/media_streamer_priv.h
@@ -27,6 +27,7 @@ extern "C" {
#include
#include
+#include
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
index 0000000..27da5ca
--- /dev/null
+++ b/include/media_streamer_resource.h
@@ -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
+
+#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__ */
diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h
index b4b8625..2b44cdf 100644
--- a/include/media_streamer_util.h
+++ b/include/media_streamer_util.h
@@ -17,6 +17,8 @@
#ifndef __MEDIA_STREAMER_UTIL_H__
#define __MEDIA_STREAMER_UTIL_H__
+#include
+
#include
#include
#include
@@ -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""); \
+ LOGD(FONT_COLOR_YELLOW""FONT_COLOR_RESET); \
} while (0)
#define ms_debug_fleave() \
do { \
- LOGD(FONT_COLOR_PURPLE""); \
+ LOGD(FONT_COLOR_PURPLE""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
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index 716fcb8..7443f3b 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -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.
diff --git a/src/media_streamer.c b/src/media_streamer.c
index 8bd592f..73ba7dc 100644
--- a/src/media_streamer.c
+++ b/src/media_streamer.c
@@ -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;
+}
diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c
index 39a1a14..f3961d4 100644
--- a/src/media_streamer_gst.c
+++ b/src/media_streamer_gst.c
@@ -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)
diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c
index 874afa9..a87724f 100644
--- a/src/media_streamer_node.c
+++ b/src/media_streamer_node.c
@@ -15,6 +15,7 @@
*/
#include
+#include
#include
#include
#include
@@ -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
index 0000000..5dabe15
--- /dev/null
+++ b/src/media_streamer_node_resources.c
@@ -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
+
+#include
+#include
+#include
+#include
+#include
+
+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;
+}
diff --git a/src/media_streamer_priv.c b/src/media_streamer_priv.c
index 47dd4bb..3fe8485 100644
--- a/src/media_streamer_priv.c
+++ b/src/media_streamer_priv.c
@@ -18,9 +18,13 @@
#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
index 0000000..4d84082
--- /dev/null
+++ b/src/media_streamer_resource.c
@@ -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
+
+#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;
+}
diff --git a/src/media_streamer_util.c b/src/media_streamer_util.c
index 8272f50..4ea599f 100644
--- a/src/media_streamer_util.c
+++ b/src/media_streamer_util.c
@@ -17,6 +17,7 @@
#include
#include
+#include
#include
#include
@@ -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;
+}
diff --git a/test/media_streamer_test.c b/test/media_streamer_test.c
index 309a134..3c8d834 100644
--- a/test/media_streamer_test.c
+++ b/test/media_streamer_test.c
@@ -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;
--
2.7.4
From b79012ad96b65afc7f54debd6e5fb6ce1788b43a Mon Sep 17 00:00:00 2001
From: Volodymyr Brynza
Date: Thu, 8 Dec 2016 13:48:09 +0200
Subject: [PATCH 02/16] Implement DPM requests for camera and mic
Change-Id: Ic1e57ca37017a0aac694a457e5b62b00ba0cf55b
Signed-off-by: Volodymyr Brynza
---
CMakeLists.txt | 4 +-
include/media_streamer_node.h | 1 +
include/media_streamer_node_policy.h | 40 +++++++
include/media_streamer_priv.h | 3 +
packaging/capi-media-streamer.spec | 1 +
src/media_streamer_node.c | 41 +++++++
src/media_streamer_node_policy.c | 204 +++++++++++++++++++++++++++++++++++
src/media_streamer_node_resources.c | 2 +-
src/media_streamer_priv.c | 47 ++++++++
9 files changed, 340 insertions(+), 3 deletions(-)
create mode 100644 include/media_streamer_node_policy.h
create mode 100644 src/media_streamer_node_policy.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c7e7c5..04a307d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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 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")
+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 dpm")
+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 dpm")
INCLUDE(FindPkgConfig)
pkg_check_modules(${fw_name} REQUIRED ${dependents})
diff --git a/include/media_streamer_node.h b/include/media_streamer_node.h
index f79f9e5..add8a37 100644
--- a/include/media_streamer_node.h
+++ b/include/media_streamer_node.h
@@ -131,3 +131,4 @@ int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name,
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);
+gboolean _ms_node_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data);
diff --git a/include/media_streamer_node_policy.h b/include/media_streamer_node_policy.h
new file mode 100644
index 0000000..5f9adef
--- /dev/null
+++ b/include/media_streamer_node_policy.h
@@ -0,0 +1,40 @@
+/*
+ * 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_POLICY_H__
+#define __MEDIA_STREAMER_NODE_POLICY_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ POLICY_TYPE_NONE,
+ POLICY_TYPE_CAMERA,
+ POLICY_TYPE_MIC,
+} media_streamer_policy_type_e;
+
+int __ms_node_policy_init(media_streamer_node_s *node);
+int __ms_node_policy_deinit(media_streamer_node_s *node);
+int _ms_node_policy_check(media_streamer_node_s *node);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEDIA_STREAMER_NODE_POLICY_H__ */
diff --git a/include/media_streamer_priv.h b/include/media_streamer_priv.h
index 14a45f7..bbfd37b 100755
--- a/include/media_streamer_priv.h
+++ b/include/media_streamer_priv.h
@@ -24,6 +24,7 @@ extern "C" {
#include
#include
+#include
#include
#include
@@ -137,6 +138,8 @@ typedef struct {
void *callbacks_structure;
media_streamer_resource_manager_s resource_manager;
+ device_policy_manager_h dpm_handle;
+ int policy_changed_cb_id;
} media_streamer_node_s;
typedef struct _media_streamer_wl_info_s {
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index 7443f3b..317b737 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -31,6 +31,7 @@ BuildRequires: pkgconfig(ecore-wayland)
BuildRequires: pkgconfig(appcore-efl)
BuildRequires: pkgconfig(murphy-resource)
BuildRequires: pkgconfig(murphy-glib)
+BuildRequires: pkgconfig(dpm)
%description
A MediaStreamer library in Tizen Native API.
diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c
index a87724f..ced5323 100644
--- a/src/media_streamer_node.c
+++ b/src/media_streamer_node.c
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
#include
@@ -579,6 +580,12 @@ int __ms_src_node_create(media_streamer_node_s *node)
return ret;
}
+ ret = __ms_node_policy_init(node);
+ if (MEDIA_STREAMER_ERROR_NONE != ret) {
+ ms_error("Failed to init policy for node [%s]", node->name);
+ return ret;
+ }
+
return ret;
}
@@ -702,6 +709,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 policy manager */
+ if (MEDIA_STREAMER_ERROR_NONE != __ms_node_policy_deinit(node))
+ ms_error("Failed to deinitialize policy manager");
+
/* Deinitialize resource manager */
if (MEDIA_STREAMER_ERROR_NONE != __ms_node_resouces_deinit(node))
ms_error("Failed to deinitialize resource manager");
@@ -1598,3 +1609,33 @@ gboolean _ms_node_resouces_release_iter(const GValue *item, GValue *ret, gpointe
return TRUE;
}
+
+gboolean _ms_node_policy_check_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_policy_check(node)) {
+ ms_error("Failed to check policy for node [%s]", node->name);
+ return FALSE;
+ }
+
+ g_value_set_boolean(ret, TRUE);
+
+ return TRUE;
+}
diff --git a/src/media_streamer_node_policy.c b/src/media_streamer_node_policy.c
new file mode 100644
index 0000000..90628b9
--- /dev/null
+++ b/src/media_streamer_node_policy.c
@@ -0,0 +1,204 @@
+/*
+ * 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
+#include
+
+#include
+#include
+#include
+#include
+
+#define DPM_ALLOWED 1
+#define DPM_DISALLOWED 0
+
+enum {
+ DPM_POLICY_FOR_CAMERA,
+ DPM_POLICY_FOR_MIC,
+ DPM_POLICY_MAX,
+};
+const char* policy_str[DPM_POLICY_MAX] = {
+ "camera",
+ "microphone",
+};
+
+static void __ms_node_get_dpm_check_needed(media_streamer_node_s *node,
+ media_streamer_policy_type_e *policy) {
+ int subtype = node->subtype;
+
+ ms_debug("Checking policy for node type %d, subtype %d", node->type, subtype);
+
+ /* Check for node types */
+ switch (subtype) {
+ case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
+ case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
+ *policy = POLICY_TYPE_CAMERA;
+ break;
+ case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
+ *policy = POLICY_TYPE_MIC;
+ break;
+ default:
+ break;
+ }
+}
+
+static void __ms_node_policy_changed_cb(const char *name, const char *value, void *user_data)
+{
+ if (user_data == NULL)
+ return;
+
+ media_streamer_node_s *node = (media_streamer_node_s *) user_data;
+ media_streamer_s *streamer = (media_streamer_s *) node->parent_streamer;
+ ms_info("Received policy_changed_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.*/
+ 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;
+ }
+ 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_SECURITY,
+ streamer->interrupted_cb.user_data);
+ } else {
+ ms_info("Interuption will not be handled because interrupted_cb is NULL");
+ }
+ g_mutex_unlock(&streamer->mutex_lock);
+}
+
+int __ms_node_policy_init(media_streamer_node_s *node)
+{
+ media_streamer_policy_type_e policy = POLICY_TYPE_NONE;
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ const char *policy_name = NULL;
+
+ /* Check if node require policy manager */
+ __ms_node_get_dpm_check_needed(node, &policy);
+ if (POLICY_TYPE_NONE == policy) {
+ ms_info("No policy is needed for %p node type [%d] subtype [%d]",
+ node, node->type, node->subtype);
+ return MEDIA_STREAMER_ERROR_NONE;
+ }
+
+ switch (policy) {
+ case POLICY_TYPE_CAMERA:
+ policy_name = policy_str[DPM_POLICY_FOR_CAMERA];
+ break;
+ case POLICY_TYPE_MIC:
+ policy_name = policy_str[DPM_POLICY_FOR_MIC];
+ break;
+ default:
+ break;
+ }
+ /* Initialize policy manager */
+ node->dpm_handle = dpm_manager_create();
+ if (node->dpm_handle) {
+ int dpm_ret = DPM_ERROR_NONE;
+ dpm_ret = dpm_add_policy_changed_cb(node->dpm_handle, policy_name,
+ __ms_node_policy_changed_cb, (void *)node, &node->policy_changed_cb_id);
+
+ if (dpm_ret != DPM_ERROR_NONE) {
+ ms_error("add DPM changed cb failed, keep going");
+ node->policy_changed_cb_id = 0;
+ }
+ ms_debug("DPM initialized");
+ }
+
+ return ret;
+}
+
+int __ms_node_policy_deinit(media_streamer_node_s *node)
+{
+ media_streamer_policy_type_e policy = POLICY_TYPE_NONE;
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ /* Check if node require policy manager */
+ __ms_node_get_dpm_check_needed(node, &policy);
+ if (POLICY_TYPE_NONE == policy) {
+ ms_info("No policy is needed for %p node type [%d] subtype [%d]",
+ node, node->type, node->subtype);
+ return MEDIA_STREAMER_ERROR_NONE;
+ }
+
+ if (node->dpm_handle) {
+ if (node->policy_changed_cb_id > 0) {
+ dpm_remove_policy_changed_cb(node->dpm_handle, node->policy_changed_cb_id);
+ } else {
+ ms_info("invalid dpm cb id");
+ }
+ ms_debug("DPM released");
+ }
+
+ dpm_manager_destroy(node->dpm_handle);
+ node->dpm_handle = NULL;
+
+ return ret;
+}
+
+int _ms_node_policy_check(media_streamer_node_s *node)
+{
+ media_streamer_policy_type_e policy = POLICY_TYPE_NONE;
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ int dpm_state = DPM_ALLOWED;
+ int dpm_ret = DPM_ERROR_NONE;
+
+ /* Check if node require policy manager */
+ __ms_node_get_dpm_check_needed(node, &policy);
+ if (POLICY_TYPE_NONE == policy) {
+ ms_info("No policy is needed for %p node type [%d] subtype [%d]",
+ node, node->type, node->subtype);
+ return MEDIA_STREAMER_ERROR_NONE;
+ }
+
+ if (node->dpm_handle == NULL) {
+ ms_error("DPM manager handle is NULL");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ switch (policy) {
+ case POLICY_TYPE_CAMERA:
+ dpm_ret = dpm_restriction_get_camera_state(node->dpm_handle, &dpm_state);
+ break;
+ case POLICY_TYPE_MIC:
+ dpm_ret = dpm_restriction_get_microphone_state(node->dpm_handle, &dpm_state);
+ break;
+ default:
+ break;
+ }
+
+ if (dpm_ret == DPM_ERROR_NONE) {
+ ms_info("DPM state - %d", dpm_state);
+ if (dpm_state == DPM_DISALLOWED) {
+ ms_error("Policy disallowed by DPM");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ ms_info("get DPM state failed, continue too work");
+ }
+
+ return ret;
+}
diff --git a/src/media_streamer_node_resources.c b/src/media_streamer_node_resources.c
index 5dabe15..3c1545a 100644
--- a/src/media_streamer_node_resources.c
+++ b/src/media_streamer_node_resources.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * 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.
diff --git a/src/media_streamer_priv.c b/src/media_streamer_priv.c
index 3fe8485..a6b995d 100644
--- a/src/media_streamer_priv.c
+++ b/src/media_streamer_priv.c
@@ -23,6 +23,7 @@
#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);
+int __ms_change_policy_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)
@@ -33,6 +34,11 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat
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_policy_state(ms_streamer, state);
+ if (MEDIA_STREAMER_ERROR_NONE != ret) {
+ ms_error("Failed to change policy state for streamer %p", ms_streamer);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
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);
@@ -338,3 +344,44 @@ static gboolean media_streamer_resource_relese_cb(
return TRUE;
}
+
+int __ms_check_policy(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_policy_check_iter, ms_streamer);
+ if (MEDIA_STREAMER_ERROR_NONE != ret) {
+ ms_error("Failed to check policies for src bin");
+ return ret;
+ }
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_change_policy_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 state
+ * and different transotions into them */
+ if (state == MEDIA_STREAMER_STATE_READY) {
+ switch (ms_streamer->pend_state) {
+ case MEDIA_STREAMER_STATE_IDLE:
+ /* After prepare function */
+ ret = __ms_check_policy(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 policy managements");
+ }
+
+ return ret;
+}
--
2.7.4
From 73a6be599b809791ca3f094cc2902a789c168751 Mon Sep 17 00:00:00 2001
From: Volodymyr Brynza
Date: Thu, 8 Dec 2016 13:48:09 +0200
Subject: [PATCH 03/16] Implement DPM requests for camera and mic
Change-Id: Ic1e57ca37017a0aac694a457e5b62b00ba0cf55b
Signed-off-by: Volodymyr Brynza
(cherry picked from commit b79012ad96b65afc7f54debd6e5fb6ce1788b43a)
---
CMakeLists.txt | 4 +-
include/media_streamer_node.h | 1 +
include/media_streamer_node_policy.h | 40 +++++++
include/media_streamer_priv.h | 3 +
packaging/capi-media-streamer.spec | 1 +
src/media_streamer_node.c | 41 +++++++
src/media_streamer_node_policy.c | 204 +++++++++++++++++++++++++++++++++++
src/media_streamer_node_resources.c | 2 +-
src/media_streamer_priv.c | 47 ++++++++
9 files changed, 340 insertions(+), 3 deletions(-)
create mode 100644 include/media_streamer_node_policy.h
create mode 100644 src/media_streamer_node_policy.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c7e7c5..04a307d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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 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")
+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 dpm")
+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 dpm")
INCLUDE(FindPkgConfig)
pkg_check_modules(${fw_name} REQUIRED ${dependents})
diff --git a/include/media_streamer_node.h b/include/media_streamer_node.h
index f79f9e5..add8a37 100644
--- a/include/media_streamer_node.h
+++ b/include/media_streamer_node.h
@@ -131,3 +131,4 @@ int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name,
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);
+gboolean _ms_node_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data);
diff --git a/include/media_streamer_node_policy.h b/include/media_streamer_node_policy.h
new file mode 100644
index 0000000..5f9adef
--- /dev/null
+++ b/include/media_streamer_node_policy.h
@@ -0,0 +1,40 @@
+/*
+ * 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_POLICY_H__
+#define __MEDIA_STREAMER_NODE_POLICY_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ POLICY_TYPE_NONE,
+ POLICY_TYPE_CAMERA,
+ POLICY_TYPE_MIC,
+} media_streamer_policy_type_e;
+
+int __ms_node_policy_init(media_streamer_node_s *node);
+int __ms_node_policy_deinit(media_streamer_node_s *node);
+int _ms_node_policy_check(media_streamer_node_s *node);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEDIA_STREAMER_NODE_POLICY_H__ */
diff --git a/include/media_streamer_priv.h b/include/media_streamer_priv.h
index 14a45f7..bbfd37b 100755
--- a/include/media_streamer_priv.h
+++ b/include/media_streamer_priv.h
@@ -24,6 +24,7 @@ extern "C" {
#include
#include
+#include
#include
#include
@@ -137,6 +138,8 @@ typedef struct {
void *callbacks_structure;
media_streamer_resource_manager_s resource_manager;
+ device_policy_manager_h dpm_handle;
+ int policy_changed_cb_id;
} media_streamer_node_s;
typedef struct _media_streamer_wl_info_s {
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index 7443f3b..317b737 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -31,6 +31,7 @@ BuildRequires: pkgconfig(ecore-wayland)
BuildRequires: pkgconfig(appcore-efl)
BuildRequires: pkgconfig(murphy-resource)
BuildRequires: pkgconfig(murphy-glib)
+BuildRequires: pkgconfig(dpm)
%description
A MediaStreamer library in Tizen Native API.
diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c
index a87724f..ced5323 100644
--- a/src/media_streamer_node.c
+++ b/src/media_streamer_node.c
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
#include
@@ -579,6 +580,12 @@ int __ms_src_node_create(media_streamer_node_s *node)
return ret;
}
+ ret = __ms_node_policy_init(node);
+ if (MEDIA_STREAMER_ERROR_NONE != ret) {
+ ms_error("Failed to init policy for node [%s]", node->name);
+ return ret;
+ }
+
return ret;
}
@@ -702,6 +709,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 policy manager */
+ if (MEDIA_STREAMER_ERROR_NONE != __ms_node_policy_deinit(node))
+ ms_error("Failed to deinitialize policy manager");
+
/* Deinitialize resource manager */
if (MEDIA_STREAMER_ERROR_NONE != __ms_node_resouces_deinit(node))
ms_error("Failed to deinitialize resource manager");
@@ -1598,3 +1609,33 @@ gboolean _ms_node_resouces_release_iter(const GValue *item, GValue *ret, gpointe
return TRUE;
}
+
+gboolean _ms_node_policy_check_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_policy_check(node)) {
+ ms_error("Failed to check policy for node [%s]", node->name);
+ return FALSE;
+ }
+
+ g_value_set_boolean(ret, TRUE);
+
+ return TRUE;
+}
diff --git a/src/media_streamer_node_policy.c b/src/media_streamer_node_policy.c
new file mode 100644
index 0000000..90628b9
--- /dev/null
+++ b/src/media_streamer_node_policy.c
@@ -0,0 +1,204 @@
+/*
+ * 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
+#include
+
+#include
+#include
+#include
+#include
+
+#define DPM_ALLOWED 1
+#define DPM_DISALLOWED 0
+
+enum {
+ DPM_POLICY_FOR_CAMERA,
+ DPM_POLICY_FOR_MIC,
+ DPM_POLICY_MAX,
+};
+const char* policy_str[DPM_POLICY_MAX] = {
+ "camera",
+ "microphone",
+};
+
+static void __ms_node_get_dpm_check_needed(media_streamer_node_s *node,
+ media_streamer_policy_type_e *policy) {
+ int subtype = node->subtype;
+
+ ms_debug("Checking policy for node type %d, subtype %d", node->type, subtype);
+
+ /* Check for node types */
+ switch (subtype) {
+ case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
+ case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
+ *policy = POLICY_TYPE_CAMERA;
+ break;
+ case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
+ *policy = POLICY_TYPE_MIC;
+ break;
+ default:
+ break;
+ }
+}
+
+static void __ms_node_policy_changed_cb(const char *name, const char *value, void *user_data)
+{
+ if (user_data == NULL)
+ return;
+
+ media_streamer_node_s *node = (media_streamer_node_s *) user_data;
+ media_streamer_s *streamer = (media_streamer_s *) node->parent_streamer;
+ ms_info("Received policy_changed_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.*/
+ 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;
+ }
+ 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_SECURITY,
+ streamer->interrupted_cb.user_data);
+ } else {
+ ms_info("Interuption will not be handled because interrupted_cb is NULL");
+ }
+ g_mutex_unlock(&streamer->mutex_lock);
+}
+
+int __ms_node_policy_init(media_streamer_node_s *node)
+{
+ media_streamer_policy_type_e policy = POLICY_TYPE_NONE;
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ const char *policy_name = NULL;
+
+ /* Check if node require policy manager */
+ __ms_node_get_dpm_check_needed(node, &policy);
+ if (POLICY_TYPE_NONE == policy) {
+ ms_info("No policy is needed for %p node type [%d] subtype [%d]",
+ node, node->type, node->subtype);
+ return MEDIA_STREAMER_ERROR_NONE;
+ }
+
+ switch (policy) {
+ case POLICY_TYPE_CAMERA:
+ policy_name = policy_str[DPM_POLICY_FOR_CAMERA];
+ break;
+ case POLICY_TYPE_MIC:
+ policy_name = policy_str[DPM_POLICY_FOR_MIC];
+ break;
+ default:
+ break;
+ }
+ /* Initialize policy manager */
+ node->dpm_handle = dpm_manager_create();
+ if (node->dpm_handle) {
+ int dpm_ret = DPM_ERROR_NONE;
+ dpm_ret = dpm_add_policy_changed_cb(node->dpm_handle, policy_name,
+ __ms_node_policy_changed_cb, (void *)node, &node->policy_changed_cb_id);
+
+ if (dpm_ret != DPM_ERROR_NONE) {
+ ms_error("add DPM changed cb failed, keep going");
+ node->policy_changed_cb_id = 0;
+ }
+ ms_debug("DPM initialized");
+ }
+
+ return ret;
+}
+
+int __ms_node_policy_deinit(media_streamer_node_s *node)
+{
+ media_streamer_policy_type_e policy = POLICY_TYPE_NONE;
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ /* Check if node require policy manager */
+ __ms_node_get_dpm_check_needed(node, &policy);
+ if (POLICY_TYPE_NONE == policy) {
+ ms_info("No policy is needed for %p node type [%d] subtype [%d]",
+ node, node->type, node->subtype);
+ return MEDIA_STREAMER_ERROR_NONE;
+ }
+
+ if (node->dpm_handle) {
+ if (node->policy_changed_cb_id > 0) {
+ dpm_remove_policy_changed_cb(node->dpm_handle, node->policy_changed_cb_id);
+ } else {
+ ms_info("invalid dpm cb id");
+ }
+ ms_debug("DPM released");
+ }
+
+ dpm_manager_destroy(node->dpm_handle);
+ node->dpm_handle = NULL;
+
+ return ret;
+}
+
+int _ms_node_policy_check(media_streamer_node_s *node)
+{
+ media_streamer_policy_type_e policy = POLICY_TYPE_NONE;
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ int dpm_state = DPM_ALLOWED;
+ int dpm_ret = DPM_ERROR_NONE;
+
+ /* Check if node require policy manager */
+ __ms_node_get_dpm_check_needed(node, &policy);
+ if (POLICY_TYPE_NONE == policy) {
+ ms_info("No policy is needed for %p node type [%d] subtype [%d]",
+ node, node->type, node->subtype);
+ return MEDIA_STREAMER_ERROR_NONE;
+ }
+
+ if (node->dpm_handle == NULL) {
+ ms_error("DPM manager handle is NULL");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ switch (policy) {
+ case POLICY_TYPE_CAMERA:
+ dpm_ret = dpm_restriction_get_camera_state(node->dpm_handle, &dpm_state);
+ break;
+ case POLICY_TYPE_MIC:
+ dpm_ret = dpm_restriction_get_microphone_state(node->dpm_handle, &dpm_state);
+ break;
+ default:
+ break;
+ }
+
+ if (dpm_ret == DPM_ERROR_NONE) {
+ ms_info("DPM state - %d", dpm_state);
+ if (dpm_state == DPM_DISALLOWED) {
+ ms_error("Policy disallowed by DPM");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ ms_info("get DPM state failed, continue too work");
+ }
+
+ return ret;
+}
diff --git a/src/media_streamer_node_resources.c b/src/media_streamer_node_resources.c
index 5dabe15..3c1545a 100644
--- a/src/media_streamer_node_resources.c
+++ b/src/media_streamer_node_resources.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * 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.
diff --git a/src/media_streamer_priv.c b/src/media_streamer_priv.c
index 3fe8485..a6b995d 100644
--- a/src/media_streamer_priv.c
+++ b/src/media_streamer_priv.c
@@ -23,6 +23,7 @@
#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);
+int __ms_change_policy_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)
@@ -33,6 +34,11 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat
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_policy_state(ms_streamer, state);
+ if (MEDIA_STREAMER_ERROR_NONE != ret) {
+ ms_error("Failed to change policy state for streamer %p", ms_streamer);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
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);
@@ -338,3 +344,44 @@ static gboolean media_streamer_resource_relese_cb(
return TRUE;
}
+
+int __ms_check_policy(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_policy_check_iter, ms_streamer);
+ if (MEDIA_STREAMER_ERROR_NONE != ret) {
+ ms_error("Failed to check policies for src bin");
+ return ret;
+ }
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_change_policy_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 state
+ * and different transotions into them */
+ if (state == MEDIA_STREAMER_STATE_READY) {
+ switch (ms_streamer->pend_state) {
+ case MEDIA_STREAMER_STATE_IDLE:
+ /* After prepare function */
+ ret = __ms_check_policy(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 policy managements");
+ }
+
+ return ret;
+}
--
2.7.4
From 7c16b0bd37214f99f2bb3dd1a46d67bd87961484 Mon Sep 17 00:00:00 2001
From: Volodymyr Brynza
Date: Mon, 19 Dec 2016 22:31:44 +0200
Subject: [PATCH 04/16] Add Murphy loop quit to prevent polling after destroy
Change-Id: I789b032fced4b95a767b4efcda92c54fb5c2cd12
Signed-off-by: Volodymyr Brynza
---
src/media_streamer_resource.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/media_streamer_resource.c b/src/media_streamer_resource.c
index 4d84082..6f99048 100644
--- a/src/media_streamer_resource.c
+++ b/src/media_streamer_resource.c
@@ -520,6 +520,7 @@ int _ms_resource_manager_deinit(media_streamer_resource_manager_s *resource_mana
}
if (resource_manager->mloop) {
+ mrp_mainloop_quit(resource_manager->mloop, 0);
mrp_mainloop_destroy(resource_manager->mloop);
resource_manager->mloop = NULL;
}
--
2.7.4
From 526c4fde1380d5fcdfa70a0a8c320c10af3094c8 Mon Sep 17 00:00:00 2001
From: Volodymyr Brynza
Date: Mon, 19 Dec 2016 22:31:44 +0200
Subject: [PATCH 05/16] Add Murphy loop quit to prevent polling after destroy
Change-Id: I789b032fced4b95a767b4efcda92c54fb5c2cd12
Signed-off-by: Volodymyr Brynza
(cherry picked from commit 7c16b0bd37214f99f2bb3dd1a46d67bd87961484)
---
src/media_streamer_resource.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/media_streamer_resource.c b/src/media_streamer_resource.c
index 4d84082..6f99048 100644
--- a/src/media_streamer_resource.c
+++ b/src/media_streamer_resource.c
@@ -520,6 +520,7 @@ int _ms_resource_manager_deinit(media_streamer_resource_manager_s *resource_mana
}
if (resource_manager->mloop) {
+ mrp_mainloop_quit(resource_manager->mloop, 0);
mrp_mainloop_destroy(resource_manager->mloop);
resource_manager->mloop = NULL;
}
--
2.7.4
From 6fceb7b1aa3d798c22ffc7b1cb13403976b1c034 Mon Sep 17 00:00:00 2001
From: Oleksandr Popov
Date: Tue, 27 Dec 2016 19:00:21 +0200
Subject: [PATCH 06/16] Add platform check before resource manager
initialization
Change-Id: I001fbd14fe4589db030a69e6fd985a32460ac6da
Signed-off-by: Oleksandr Popov
---
include/media_streamer_resource.h | 2 +-
src/media_streamer_node_resources.c | 58 +++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/include/media_streamer_resource.h b/include/media_streamer_resource.h
index 27da5ca..2cefdc8 100644
--- a/include/media_streamer_resource.h
+++ b/include/media_streamer_resource.h
@@ -52,7 +52,7 @@ typedef enum {
} 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);
+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;
diff --git a/src/media_streamer_node_resources.c b/src/media_streamer_node_resources.c
index 3c1545a..5e96813 100644
--- a/src/media_streamer_node_resources.c
+++ b/src/media_streamer_node_resources.c
@@ -16,6 +16,8 @@
#include
+#include
+
#include
#include
#include
@@ -61,6 +63,41 @@ static gboolean __ms_resource_relese_cb(
return TRUE;
}
+static gboolean __ms_node_resources_is_needed_by_platform(media_streamer_node_s *node)
+{
+ media_streamer_node_type_e type = node->type;
+ int subtype = node->subtype;
+ char *model_name, *platform_processor;
+ gboolean ret = FALSE;
+
+ /* Checking for model_name and processor because some resources
+ are platform dependent */
+ system_info_get_platform_string("http://tizen.org/system/model_name", &model_name);
+ system_info_get_platform_string("http://tizen.org/system/platform.processor", &platform_processor);
+ ms_info("Check for resources for model_name %s, platform.processor %s", model_name, platform_processor);
+
+ switch (type) {
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER:
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER:
+ if (!g_strcmp0(model_name, "Emulator") ||
+ !g_strcmp0(platform_processor, "Emulator"))
+ ret = FALSE;
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_SRC:
+ if (MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA == subtype)
+ ret = TRUE;
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_SINK:
+ if (MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY == subtype)
+ ret = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
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;
@@ -101,6 +138,13 @@ int __ms_node_resouces_init(media_streamer_node_s *node)
return MEDIA_STREAMER_ERROR_NONE;
}
+ /* Check if platform requires resource (e.g. Emulator) */
+ if (!__ms_node_resources_is_needed_by_platform(node)) {
+ ms_info("Platform doesn't require resource 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);
@@ -125,6 +169,13 @@ int __ms_node_resouces_deinit(media_streamer_node_s *node)
return MEDIA_STREAMER_ERROR_NONE;
}
+ /* Check if platform requires resource (e.g. Emulator) */
+ if (!__ms_node_resources_is_needed_by_platform(node)) {
+ ms_info("Platform doesn't require resource 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) {
@@ -196,6 +247,13 @@ int _ms_node_resource_aquire(media_streamer_node_s *node)
return MEDIA_STREAMER_ERROR_NONE;
}
+ /* Check if platform requires resource (e.g. Emulator) */
+ if (!__ms_node_resources_is_needed_by_platform(node)) {
+ ms_info("Platform doesn't require resource 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;
--
2.7.4
From 81d4e447b82db4346069405ecfcfaeaf1fc0b388 Mon Sep 17 00:00:00 2001
From: Oleksandr Popov
Date: Tue, 27 Dec 2016 19:00:21 +0200
Subject: [PATCH 07/16] Add platform check before resource manager
initialization
Change-Id: I001fbd14fe4589db030a69e6fd985a32460ac6da
Signed-off-by: Oleksandr Popov
---
include/media_streamer_resource.h | 2 +-
src/media_streamer_node_resources.c | 58 +++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/include/media_streamer_resource.h b/include/media_streamer_resource.h
index 27da5ca..2cefdc8 100644
--- a/include/media_streamer_resource.h
+++ b/include/media_streamer_resource.h
@@ -52,7 +52,7 @@ typedef enum {
} 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);
+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;
diff --git a/src/media_streamer_node_resources.c b/src/media_streamer_node_resources.c
index 3c1545a..5e96813 100644
--- a/src/media_streamer_node_resources.c
+++ b/src/media_streamer_node_resources.c
@@ -16,6 +16,8 @@
#include
+#include
+
#include
#include
#include
@@ -61,6 +63,41 @@ static gboolean __ms_resource_relese_cb(
return TRUE;
}
+static gboolean __ms_node_resources_is_needed_by_platform(media_streamer_node_s *node)
+{
+ media_streamer_node_type_e type = node->type;
+ int subtype = node->subtype;
+ char *model_name, *platform_processor;
+ gboolean ret = FALSE;
+
+ /* Checking for model_name and processor because some resources
+ are platform dependent */
+ system_info_get_platform_string("http://tizen.org/system/model_name", &model_name);
+ system_info_get_platform_string("http://tizen.org/system/platform.processor", &platform_processor);
+ ms_info("Check for resources for model_name %s, platform.processor %s", model_name, platform_processor);
+
+ switch (type) {
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER:
+ case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER:
+ if (!g_strcmp0(model_name, "Emulator") ||
+ !g_strcmp0(platform_processor, "Emulator"))
+ ret = FALSE;
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_SRC:
+ if (MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA == subtype)
+ ret = TRUE;
+ break;
+ case MEDIA_STREAMER_NODE_TYPE_SINK:
+ if (MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY == subtype)
+ ret = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
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;
@@ -101,6 +138,13 @@ int __ms_node_resouces_init(media_streamer_node_s *node)
return MEDIA_STREAMER_ERROR_NONE;
}
+ /* Check if platform requires resource (e.g. Emulator) */
+ if (!__ms_node_resources_is_needed_by_platform(node)) {
+ ms_info("Platform doesn't require resource 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);
@@ -125,6 +169,13 @@ int __ms_node_resouces_deinit(media_streamer_node_s *node)
return MEDIA_STREAMER_ERROR_NONE;
}
+ /* Check if platform requires resource (e.g. Emulator) */
+ if (!__ms_node_resources_is_needed_by_platform(node)) {
+ ms_info("Platform doesn't require resource 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) {
@@ -196,6 +247,13 @@ int _ms_node_resource_aquire(media_streamer_node_s *node)
return MEDIA_STREAMER_ERROR_NONE;
}
+ /* Check if platform requires resource (e.g. Emulator) */
+ if (!__ms_node_resources_is_needed_by_platform(node)) {
+ ms_info("Platform doesn't require resource 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;
--
2.7.4
From 0a187c0051812dbe8e6c2f12c189cac7c2b239ae Mon Sep 17 00:00:00 2001
From: Oleksandr Popov
Date: Tue, 27 Dec 2016 19:39:48 +0200
Subject: [PATCH 08/16] Added missing condition for resource management check
Signed-off-by: Oleksandr Popov
Change-Id: I700bad3752224583d04762081689b48188a5ec74
---
src/media_streamer_node_resources.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/media_streamer_node_resources.c b/src/media_streamer_node_resources.c
index 5e96813..2f69001 100644
--- a/src/media_streamer_node_resources.c
+++ b/src/media_streamer_node_resources.c
@@ -82,6 +82,8 @@ static gboolean __ms_node_resources_is_needed_by_platform(media_streamer_node_s
if (!g_strcmp0(model_name, "Emulator") ||
!g_strcmp0(platform_processor, "Emulator"))
ret = FALSE;
+ else
+ ret = TRUE;
break;
case MEDIA_STREAMER_NODE_TYPE_SRC:
if (MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA == subtype)
--
2.7.4
From 4b988c903016df04335ca09a98ed9ddf9cf544a1 Mon Sep 17 00:00:00 2001
From: Eunhae Choi
Date: Mon, 9 Jan 2017 21:52:24 +0900
Subject: [PATCH 09/16] [v0.1.12] init mrp after create pipeline and add missed
unlock
Change-Id: Icd662f3ce720ed2863a05dc0045b52459ff90717
(cherry picked from commit 1603f61104ec15d3adb42edfc4a694c21e1788d7)
---
packaging/capi-media-streamer.spec | 2 +-
src/media_streamer.c | 1 +
src/media_streamer_gst.c | 10 +++++-----
src/media_streamer_node_policy.c | 16 ++++++++--------
src/media_streamer_priv.c | 6 +++++-
src/media_streamer_resource.c | 34 ++++++++++++++++++++--------------
6 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index 317b737..89c0c35 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -1,6 +1,6 @@
Name: capi-media-streamer
Summary: A Media Streamer API
-Version: 0.1.11
+Version: 0.1.12
Release: 0
Group: Multimedia/API
License: Apache-2.0
diff --git a/src/media_streamer.c b/src/media_streamer.c
index 73ba7dc..a17c699 100644
--- a/src/media_streamer.c
+++ b/src/media_streamer.c
@@ -256,6 +256,7 @@ int media_streamer_create(media_streamer_h *streamer)
ret = __ms_create(ms_streamer);
if (ret != MEDIA_STREAMER_ERROR_NONE) {
ms_error("Error creating Media Streamer");
+ g_mutex_unlock(&ms_streamer->mutex_lock);
__ms_streamer_destroy(ms_streamer);
return ret;
diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c
index f3961d4..c592087 100644
--- a/src/media_streamer_gst.c
+++ b/src/media_streamer_gst.c
@@ -2068,15 +2068,15 @@ static void __demux_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_st
{
GstElement *found_element = gst_pad_get_parent_element(src_pad);
const gchar *new_pad_type = __ms_get_pad_type(src_pad);
- if (MS_ELEMENT_IS_VIDEO(new_pad_type)) {
+ if (MS_ELEMENT_IS_VIDEO(new_pad_type))
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
- } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
+ else if (MS_ELEMENT_IS_AUDIO(new_pad_type))
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
- } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) {
+ else if (MS_ELEMENT_IS_TEXT(new_pad_type))
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
- } else {
+ else
ms_error("Unsupported pad type [%s]!", new_pad_type);
- }
+
__ms_generate_dots(ms_streamer->pipeline, "after_demux_linked");
gst_object_unref(found_element);
}
diff --git a/src/media_streamer_node_policy.c b/src/media_streamer_node_policy.c
index 90628b9..3c4f6ec 100644
--- a/src/media_streamer_node_policy.c
+++ b/src/media_streamer_node_policy.c
@@ -145,11 +145,11 @@ int __ms_node_policy_deinit(media_streamer_node_s *node)
}
if (node->dpm_handle) {
- if (node->policy_changed_cb_id > 0) {
+ if (node->policy_changed_cb_id > 0)
dpm_remove_policy_changed_cb(node->dpm_handle, node->policy_changed_cb_id);
- } else {
+ else
ms_info("invalid dpm cb id");
- }
+
ms_debug("DPM released");
}
@@ -191,11 +191,11 @@ int _ms_node_policy_check(media_streamer_node_s *node)
}
if (dpm_ret == DPM_ERROR_NONE) {
- ms_info("DPM state - %d", dpm_state);
- if (dpm_state == DPM_DISALLOWED) {
- ms_error("Policy disallowed by DPM");
- return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
- }
+ ms_info("DPM state - %d", dpm_state);
+ if (dpm_state == DPM_DISALLOWED) {
+ ms_error("Policy disallowed by DPM");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
} else {
ms_info("get DPM state failed, continue too work");
}
diff --git a/src/media_streamer_priv.c b/src/media_streamer_priv.c
index a6b995d..c3825dc 100644
--- a/src/media_streamer_priv.c
+++ b/src/media_streamer_priv.c
@@ -91,11 +91,14 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat
int __ms_create(media_streamer_s *ms_streamer)
{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
__ms_load_ini_settings(&ms_streamer->ini);
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");
+ ret = __ms_pipeline_create(ms_streamer);
+
if (MEDIA_STREAMER_ERROR_NONE != _ms_resource_manager_init(
&ms_streamer->resource_manager,
media_streamer_resource_relese_cb,
@@ -104,7 +107,7 @@ int __ms_create(media_streamer_s *ms_streamer)
return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
}
- return __ms_pipeline_create(ms_streamer);
+ return ret;
}
int __ms_get_position(media_streamer_s *ms_streamer, int *time)
@@ -189,6 +192,7 @@ int __ms_streamer_destroy(media_streamer_s *ms_streamer)
if (MEDIA_STREAMER_ERROR_NONE !=
_ms_resource_manager_deinit(&ms_streamer->resource_manager)) {
ms_error("Failed to deinit resource manager for media streamer");
+ g_mutex_unlock(&ms_streamer->mutex_lock);
return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
}
diff --git a/src/media_streamer_resource.c b/src/media_streamer_resource.c
index 6f99048..bce054d 100644
--- a/src/media_streamer_resource.c
+++ b/src/media_streamer_resource.c
@@ -64,9 +64,9 @@ static int __ms_resource_manager_wait_connection(media_streamer_resource_manager
MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
} else {
- if (resource_manager->is_connected)
+ if (resource_manager->is_connected) {
ms_debug("Successfully connected to resource server!");
- else {
+ } else {
ms_error("Failed to connect to resource server");
MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
@@ -119,7 +119,7 @@ static void mrp_state_callback(mrp_res_context_t *context, mrp_res_error_t err,
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);
+ MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
return;
}
@@ -131,6 +131,7 @@ static void mrp_state_callback(mrp_res_context_t *context, mrp_res_error_t err,
resource_names = mrp_res_list_resource_names(rset);
if (!resource_names) {
ms_error(" - no resources available");
+ MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
return;
}
for (i = 0; i < resource_names->num_strings; i++) {
@@ -219,6 +220,7 @@ static void mrp_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resourc
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;
}
@@ -234,11 +236,10 @@ static void mrp_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resourc
}
if (resource_manager->release_cb) {
- if (!resource_manager->release_cb(resource_manager, resource_manager->user_data)) {
+ if (!resource_manager->release_cb(resource_manager, resource_manager->user_data))
ms_error("release_cb failed");
- } else {
+ else
ms_info("release_cb is fine");
- }
} else {
ms_error("release cb is NULL. Something wrong happens...");
}
@@ -316,6 +317,7 @@ static int set_resource_release_cb(media_streamer_resource_manager_s *resource_m
int _ms_resource_manager_init(media_streamer_resource_manager_s *resource_manager,
resource_relese_cb release_cb, void *user_data)
{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
MEDIA_STREAMER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
ms_retvm_if(release_cb == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
"release_cb is NULL");
@@ -328,14 +330,16 @@ int _ms_resource_manager_init(media_streamer_resource_manager_s *resource_manage
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;
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ goto EXIT;
}
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;
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ goto EXIT;
}
resource_manager->mloop = mrp_mainloop_glib_get(mrp_loop);
@@ -348,20 +352,23 @@ int _ms_resource_manager_init(media_streamer_resource_manager_s *resource_manage
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;
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ goto EXIT;
}
resource_manager->user_data = user_data;
} else {
ms_error("- could not get mainloop for resource manager");
- return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ goto EXIT;
}
resource_manager->release_cb = release_cb;
resource_manager->state = RESOURCE_STATE_INITIALIZED;
+EXIT:
MEDIA_STREAMER_RESOURCE_UNLOCK(resource_manager);
- return MEDIA_STREAMER_ERROR_NONE;
+ return ret;
}
int _ms_resource_manager_prepare(media_streamer_resource_manager_s *resource_manager, media_streamer_resource_type_e resource_type)
@@ -392,11 +399,10 @@ int _ms_resource_manager_prepare(media_streamer_resource_manager_s *resource_man
}
}
- if (MEDIA_STREAMER_ERROR_NONE == ret) {
+ if (MEDIA_STREAMER_ERROR_NONE == ret)
resource_manager->state = RESOURCE_STATE_PREPARED;
- } else {
+ else
resource_manager->state = RESOURCE_STATE_ERROR;
- }
return ret;
}
--
2.7.4
From f0f288ba44517a92a4a27603e708ff01203d8b96 Mon Sep 17 00:00:00 2001
From: Volodymyr Brynza
Date: Thu, 2 Feb 2017 13:26:20 +0200
Subject: [PATCH 10/16] fix memory leak
Change-Id: I4687b9f4949ecaac16e44bdd210a5ed4d1964b6a
Signed-off-by: Volodymyr Brynza
---
packaging/capi-media-streamer.spec | 2 +-
src/media_streamer_gst.c | 5 ++++-
src/media_streamer_node.c | 13 +++++++++++++
src/media_streamer_node_resources.c | 9 +++++++++
4 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index 89c0c35..646ff93 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -1,6 +1,6 @@
Name: capi-media-streamer
Summary: A Media Streamer API
-Version: 0.1.12
+Version: 0.1.13
Release: 0
Group: Multimedia/API
License: Apache-2.0
diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c
index c592087..3ac83fc 100644
--- a/src/media_streamer_gst.c
+++ b/src/media_streamer_gst.c
@@ -1172,6 +1172,7 @@ GstElement *__ms_video_decoder_element_create(node_plug_s *plug_info, media_stre
GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type)
{
GstCaps *enc_caps = plug_info->src_caps;
+ gchar *encoder_name = NULL;
if (!enc_caps) {
enc_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
ms_debug("No Audio encoding format is set! Deafault will be: [%s]", MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
@@ -1192,8 +1193,10 @@ GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info, media_stre
if (!audio_encoder)
audio_encoder = __ms_element_create_by_registry(&plug_info_encoder, type);
- if (g_strrstr(gst_element_get_name(audio_encoder), "aac"))
+ encoder_name = gst_element_get_name(audio_encoder);
+ if (encoder_name && g_strrstr(encoder_name, "aac"))
g_object_set(audio_encoder, "compliance", -2, NULL);
+ MS_SAFE_GFREE(encoder_name);
/* Creating bin - Audio Encoder */
GstElement *audio_enc_bin = gst_bin_new("audio_encoder");
diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c
index ced5323..0f69deb 100644
--- a/src/media_streamer_node.c
+++ b/src/media_streamer_node.c
@@ -657,6 +657,7 @@ int __ms_sink_node_create(media_streamer_node_s *node)
case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY:
plugin_name = __ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK);
node->gst_element = __ms_element_create(plugin_name, NULL);
+ g_object_set(node->gst_element, "use-tbm", FALSE, NULL);
break;
case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
plugin_name = __ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK);
@@ -1567,16 +1568,20 @@ gboolean _ms_node_resouces_acquire_iter(const GValue *item, GValue *ret, gpointe
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);
+ g_object_unref(element);
return TRUE;
}
if (MEDIA_STREAMER_ERROR_NONE != _ms_node_resource_aquire(node)) {
ms_error("Failed to acquire resource for node [%s]", node->name);
+ g_object_unref(element);
return FALSE;
}
g_value_set_boolean(ret, TRUE);
+ g_object_unref(element);
+
return TRUE;
}
@@ -1597,16 +1602,20 @@ gboolean _ms_node_resouces_release_iter(const GValue *item, GValue *ret, gpointe
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);
+ g_object_unref(element);
return TRUE;
}
if (MEDIA_STREAMER_ERROR_NONE != _ms_node_resource_release(node)) {
ms_error("Failed to release resource for node [%s]", node->name);
+ g_object_unref(element);
return FALSE;
}
g_value_set_boolean(ret, TRUE);
+ g_object_unref(element);
+
return TRUE;
}
@@ -1627,15 +1636,19 @@ gboolean _ms_node_policy_check_iter(const GValue *item, GValue *ret, gpointer us
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);
+ g_object_unref(element);
return TRUE;
}
if (MEDIA_STREAMER_ERROR_NONE != _ms_node_policy_check(node)) {
ms_error("Failed to check policy for node [%s]", node->name);
+ g_object_unref(element);
return FALSE;
}
g_value_set_boolean(ret, TRUE);
+ g_object_unref(element);
+
return TRUE;
}
diff --git a/src/media_streamer_node_resources.c b/src/media_streamer_node_resources.c
index 2f69001..dbf8c54 100644
--- a/src/media_streamer_node_resources.c
+++ b/src/media_streamer_node_resources.c
@@ -74,6 +74,12 @@ static gboolean __ms_node_resources_is_needed_by_platform(media_streamer_node_s
are platform dependent */
system_info_get_platform_string("http://tizen.org/system/model_name", &model_name);
system_info_get_platform_string("http://tizen.org/system/platform.processor", &platform_processor);
+ if (!model_name || ! platform_processor) {
+ ms_error("Failed to get information about platform check resources");
+ MS_SAFE_FREE(model_name);
+ MS_SAFE_FREE(platform_processor);
+ return TRUE;
+ }
ms_info("Check for resources for model_name %s, platform.processor %s", model_name, platform_processor);
switch (type) {
@@ -97,6 +103,9 @@ static gboolean __ms_node_resources_is_needed_by_platform(media_streamer_node_s
break;
}
+ MS_SAFE_FREE(model_name);
+ MS_SAFE_FREE(platform_processor);
+
return ret;
}
--
2.7.4
From 9094f0c3465c389223ddc8f930ea296fb46e3a9a Mon Sep 17 00:00:00 2001
From: Eunhae Choi
Date: Thu, 16 Feb 2017 19:45:43 +0900
Subject: [PATCH 11/16] [0.1.14] fix svace issue
Change-Id: I7e05d5b5cb6dab7fb21bda14b2988ef0f9b7db9d
(cherry picked from commit 74dc3e6ba4dade3c52216587d31c3e984dac3f7a)
---
packaging/capi-media-streamer.spec | 2 +-
src/media_streamer_gst.c | 22 +++++++++++++++++-----
src/media_streamer_node.c | 2 +-
3 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index 646ff93..cab5a44 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -1,6 +1,6 @@
Name: capi-media-streamer
Summary: A Media Streamer API
-Version: 0.1.13
+Version: 0.1.14
Release: 0
Group: Multimedia/API
License: Apache-2.0
diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c
index 3ac83fc..d10c954 100644
--- a/src/media_streamer_gst.c
+++ b/src/media_streamer_gst.c
@@ -817,11 +817,22 @@ static GstElement *__ms_manifest_src_create(media_streamer_node_s *ms_node)
}
}
g_free(protocol);
- ms_retvm_if(manifest_src_name == NULL, NULL,
- "Error empty manifest source name for adaprive source");
+
+ if (manifest_src_name == NULL) {
+ LOGE("Error empty manifest source name for adaptive source");
+ g_free(location);
+ return NULL;
+ }
+
manifest_src = gst_element_factory_make(manifest_src_name, NULL);
- ms_retvm_if(manifest_src == NULL, NULL,
- "Error creating manifest source for adaptive source");
+ g_free(manifest_src_name);
+
+ if (manifest_src == NULL) {
+ LOGE("Error creating manifest source for adaptive source");
+ g_free(location);
+ return NULL;
+ }
+
g_object_set(manifest_src, "location", location, NULL);
g_free(location);
@@ -843,8 +854,9 @@ int __ms_adaptive_element_prepare(media_streamer_node_s *ms_node, bool auto_plug
ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaprive source");
ms_info("Creating [%s] element", plugin_name);
plugin_elem = gst_element_factory_make(plugin_name, NULL);
+ g_free(plugin_name);
ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
- "Error creating element [%s] for adaptive source", plugin_name);
+ "Error creating element for adaptive source");
res = gst_bin_add(GST_BIN(ms_node->gst_element), plugin_elem);
ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c
index 0f69deb..ddc60e5 100644
--- a/src/media_streamer_node.c
+++ b/src/media_streamer_node.c
@@ -343,7 +343,7 @@ static int __ms_node_check_priveleges(media_streamer_node_s *node)
char smackLabel[SMACK_LABEL_LEN + 1];
char uid[10];
- cynara *cynara_h;
+ cynara *cynara_h = NULL;
if (CYNARA_API_SUCCESS != cynara_initialize(&cynara_h, NULL)) {
ms_error("Failed to initialize cynara structure\n");
--
2.7.4
From 340e505a7c067e5c68ecc5324856e874348ea0a9 Mon Sep 17 00:00:00 2001
From: Oleksandr Popov
Date: Mon, 20 Feb 2017 18:08:39 +0000
Subject: [PATCH 12/16] Added http server feature
Change-Id: I286acf360eae667868d1ee17372e4930f82e719f
Signed-off-by: Oleksandr Popov
---
CMakeLists.txt | 4 +-
include/media_streamer_http_server.h | 42 ++++++
include/media_streamer_net_util.h | 31 +++++
include/media_streamer_priv.h | 3 +
include/media_streamer_util.h | 2 +-
packaging/capi-media-streamer.spec | 7 +-
src/media_streamer.c | 4 +
src/media_streamer_gst.c | 4 +-
src/media_streamer_http_server.c | 262 +++++++++++++++++++++++++++++++++++
src/media_streamer_net_util.c | 49 +++++++
src/media_streamer_node.c | 40 +++++-
src/media_streamer_util.c | 4 +-
test/media_streamer_test.c | 2 +-
13 files changed, 443 insertions(+), 11 deletions(-)
create mode 100644 include/media_streamer_http_server.h
create mode 100644 include/media_streamer_net_util.h
mode change 100755 => 100644 include/media_streamer_priv.h
create mode 100644 src/media_streamer_http_server.c
create mode 100644 src/media_streamer_net_util.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 04a307d..2a05d39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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 murphy-resource murphy-glib dpm")
-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 dpm")
+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 dpm capi-network-connection capi-content-mime-type libsoup-2.4")
+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 dpm capi-system-info capi-network-connection capi-content-mime-type libsoup-2.4")
INCLUDE(FindPkgConfig)
pkg_check_modules(${fw_name} REQUIRED ${dependents})
diff --git a/include/media_streamer_http_server.h b/include/media_streamer_http_server.h
new file mode 100644
index 0000000..29c565c
--- /dev/null
+++ b/include/media_streamer_http_server.h
@@ -0,0 +1,42 @@
+
+/*
+ * 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_HTTP_H__
+#define __MEDIA_STREAMER_HTTP_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *media_streamer_http_server_h;
+
+int __ms_http_server_create(media_streamer_http_server_h *server, char *ip_address, char *port);
+int __ms_http_server_destroy(media_streamer_http_server_h server);
+
+int __ms_http_server_start(media_streamer_http_server_h server);
+int __ms_http_server_stop(media_streamer_http_server_h server);
+
+int __ms_http_server_register_uri(media_streamer_http_server_h server, char *uri, char *file_path);
+int __ms_http_server_unregister_uri(media_streamer_http_server_h server, char *uri);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEDIA_STREAMER_HTTP_H__ */
diff --git a/include/media_streamer_net_util.h b/include/media_streamer_net_util.h
new file mode 100644
index 0000000..76f72e9
--- /dev/null
+++ b/include/media_streamer_net_util.h
@@ -0,0 +1,31 @@
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MEDIA_STREAMER_NET_UTIL_H__
+#define __MEDIA_STREAMER_NET_UTIL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __ms_get_local_network_address(char **ip_address);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEDIA_STREAMER_NET_UTIL_H__ */
diff --git a/include/media_streamer_priv.h b/include/media_streamer_priv.h
old mode 100755
new mode 100644
index bbfd37b..9ba66a0
--- a/include/media_streamer_priv.h
+++ b/include/media_streamer_priv.h
@@ -29,6 +29,7 @@ extern "C" {
#include
#include
#include
+#include
struct media_streamer_node_s;
@@ -116,6 +117,8 @@ typedef struct {
gboolean is_interrupted;
media_streamer_resource_manager_s resource_manager;
+
+ media_streamer_http_server_h http_server;
} media_streamer_s;
/**
diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h
index 2b44cdf..5c85853 100644
--- a/include/media_streamer_util.h
+++ b/include/media_streamer_util.h
@@ -332,7 +332,7 @@ void __ms_param_value_destroy(gpointer data);
*
* @since_tizen 3.0
*/
-int __ms_node_uri_path_check(const char *file_uri);
+int __ms_util_uri_path_check(const char *file_uri);
/**
* @brief Iterates func over all elements contained within a bin.
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index cab5a44..d413ffb 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -1,6 +1,6 @@
Name: capi-media-streamer
Summary: A Media Streamer API
-Version: 0.1.14
+Version: 0.1.15
Release: 0
Group: Multimedia/API
License: Apache-2.0
@@ -32,6 +32,9 @@ BuildRequires: pkgconfig(appcore-efl)
BuildRequires: pkgconfig(murphy-resource)
BuildRequires: pkgconfig(murphy-glib)
BuildRequires: pkgconfig(dpm)
+BuildRequires: pkgconfig(capi-network-connection)
+BuildRequires: pkgconfig(libsoup-2.4)
+BuildRequires: pkgconfig(capi-content-mime-type)
%description
A MediaStreamer library in Tizen Native API.
@@ -51,7 +54,7 @@ cp %{SOURCE1001} .
%define ini_path %{_sysconfdir}/multimedia/mmfw_media_streamer.ini
%build
-flags="-DMEDIA_STREAMER_INI_PATH=\\\"%{ini_path}\\\""
+flags="-DMEDIA_STREAMER_INI_PATH=\\\"%{ini_path}\\\" -D_FILE_OFFSET_BITS=64"
%if 0%{?sec_build_binary_debug_enable}
flags="$flags -DTIZEN_DEBUG_ENABLE"
diff --git a/src/media_streamer.c b/src/media_streamer.c
index a17c699..a2eb3ff 100644
--- a/src/media_streamer.c
+++ b/src/media_streamer.c
@@ -213,6 +213,8 @@ int media_streamer_unprepare(media_streamer_h streamer)
ret = __ms_pipeline_unprepare(ms_streamer);
+ __ms_http_server_destroy(ms_streamer->http_server);
+
__ms_generate_dots(ms_streamer->pipeline, "after_unprepare");
g_mutex_unlock(&ms_streamer->mutex_lock);
@@ -477,6 +479,8 @@ int media_streamer_stop(media_streamer_h streamer)
else
ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_PAUSED);
+ __ms_http_server_stop(ms_streamer->http_server);
+
g_mutex_unlock(&ms_streamer->mutex_lock);
__ms_get_state(ms_streamer);
diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c
index d10c954..5171d3d 100644
--- a/src/media_streamer_gst.c
+++ b/src/media_streamer_gst.c
@@ -752,7 +752,7 @@ static int __ms_adaptive_sink_prepare(media_streamer_s * ms_streamer)
{"Codec/Muxer", "mpegtsmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */
};
- GstCaps *video_enc_src_caps = gst_caps_new_empty_simple("video/mpeg");
+ GstCaps *video_enc_src_caps = gst_caps_new_simple("video/mpeg", "mpegversion", G_TYPE_INT, 4, NULL);
GstCaps *video_enc_sink_caps = gst_caps_new_empty_simple("video/x-raw");
node_plug_s video_enc_plug_info = {&(nodes_info[0]), video_enc_src_caps, video_enc_sink_caps, NULL};
GstElement *video_enc = __ms_node_element_create(&video_enc_plug_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
@@ -807,7 +807,7 @@ static GstElement *__ms_manifest_src_create(media_streamer_node_s *ms_node)
location = gst_uri_get_location(uri);
} else {
ms_error("Unsupported URI protocol... Check URI is file path");
- if (__ms_node_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
+ if (__ms_util_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
manifest_src_name = __ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
location = g_strdup(uri);
} else {
diff --git a/src/media_streamer_http_server.c b/src/media_streamer_http_server.c
new file mode 100644
index 0000000..0179559
--- /dev/null
+++ b/src/media_streamer_http_server.c
@@ -0,0 +1,262 @@
+/*
+ * 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
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#define HTTP_SERVER_LOG_LEVEL AD_LOG_DEBUG
+
+typedef struct {
+ SoupServer *server; /* Soup HTTP server */
+
+ GHashTable *uri_table;
+} _ms_http_server_s;
+
+static int __ms_http_server_file_read_contents(const char *file_path, char **content, gsize *size);
+static void __ms_http_server_connection_handle_cb(SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query, SoupClientContext *client, gpointer user_data);
+
+int __ms_http_server_create(media_streamer_http_server_h *server, char *ip_address, char *port)
+{
+ ms_retvm_if(server == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ //ms_retvm_if(ip_address == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "IP address is NULL");
+ ms_retvm_if(port == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Port is NULL");
+
+ _ms_http_server_s *ms_server = (_ms_http_server_s *) calloc(1, sizeof(_ms_http_server_s));
+ ms_retvm_if(ms_server == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error allocation memory");
+
+ const int iport = atoi(port);
+ ms_server->server = soup_server_new(SOUP_SERVER_PORT, iport, NULL);
+
+ if (!ms_server->server) {
+ ms_error("Failed to create http server");
+ __ms_http_server_destroy(ms_server);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ /* Create hash table for URIs */
+ ms_server->uri_table = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!ms_server->uri_table) {
+ ms_error("Failed to URIs hash table");
+ __ms_http_server_destroy(ms_server);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ *server = ms_server;
+
+ ms_info("http server created successfully");
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_http_server_destroy(media_streamer_http_server_h server)
+{
+ ms_retvm_if(server == NULL, MEDIA_STREAMER_ERROR_NONE, "Handle is NULL");
+ _ms_http_server_s *hserver = (_ms_http_server_s *) server;
+
+ /* Stop server first */
+ __ms_http_server_stop(server);
+
+ /* Destroy URIs hash table */
+ g_hash_table_destroy(hserver->uri_table);
+
+ if (hserver->server)
+ g_object_unref(hserver->server);
+
+ MS_SAFE_GFREE(hserver);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_http_server_start(media_streamer_http_server_h server)
+{
+ ms_retvm_if(server == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ _ms_http_server_s *hserver = (_ms_http_server_s *) server;
+
+ soup_server_add_handler(hserver->server, NULL,
+ __ms_http_server_connection_handle_cb, hserver, NULL);
+
+ soup_server_run_async(hserver->server);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_http_server_stop(media_streamer_http_server_h server)
+{
+ ms_retvm_if(server == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ _ms_http_server_s *hserver = (_ms_http_server_s *) server;
+
+ soup_server_disconnect(hserver->server);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_http_server_register_uri(media_streamer_http_server_h server, char *uri, char *file_path)
+{
+ ms_retvm_if(server == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(uri == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "URI address is NULL");
+ ms_retvm_if(file_path == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "File path is NULL");
+
+ _ms_http_server_s *hserver = (_ms_http_server_s *) server;
+
+ if (!hserver->uri_table) {
+ ms_error("Failed to register URI. Table is NULL");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ g_hash_table_insert(hserver->uri_table, uri, file_path);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int __ms_http_server_unregister_uri(media_streamer_http_server_h server, char *uri)
+{
+ ms_retvm_if(server == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(uri == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "URI address is NULL");
+
+ _ms_http_server_s *hserver = (_ms_http_server_s *) server;
+
+ if (!hserver->uri_table) {
+ ms_error("Failed to unregister URI. Table is NULL");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ /* Return if URI is not registered */
+ if (!g_hash_table_contains(hserver->uri_table, uri))
+ return MEDIA_STREAMER_ERROR_NONE;
+
+ if (!g_hash_table_remove(hserver->uri_table, uri)) {
+ ms_error("Failed to remove URI %s from table", uri);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static const char *get_filename_ext(const char *file_path)
+{
+ const char *dot = strrchr(file_path, '.');
+
+ if (!dot || dot == file_path) return "";
+ return dot + 1;
+}
+
+static int __ms_http_server_file_read_contents(const char *file_path, char **content, gsize *size)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ struct stat stat_results = {0, };
+ int file_open = 0;
+
+ if (!file_path || !strlen(file_path))
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+
+ ret = __ms_util_uri_path_check(file_path);
+ if (MEDIA_STREAMER_ERROR_NONE != ret)
+ return ret;
+
+ file_open = open(file_path, O_RDONLY);
+ if (file_open < 0) {
+ char mes_error[256];
+ strerror_r(errno, mes_error, sizeof(mes_error));
+ ms_error("Couldn`t open file [%s] according to [%s]. Error N [%d]", file_path, mes_error, errno);
+
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ }
+
+ if (fstat(file_open, &stat_results) < 0) {
+ ms_error("Couldn`t get status of the file [%s]", file_path);
+ } else if (stat_results.st_size == 0) {
+ ms_error("The size of file is 0");
+ close(file_open);
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ } else {
+ ms_debug("Size of file [%lld] bytes", (long long)stat_results.st_size);
+ }
+
+ *content = malloc((size_t)stat_results.st_size);
+ if (read(file_open, *content, (size_t)stat_results.st_size) < (size_t)stat_results.st_size)
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ *size = (gsize)stat_results.st_size;
+
+ close(file_open);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
+static void __ms_http_server_connection_handle_cb(SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query, SoupClientContext *client, gpointer user_data)
+{
+ _ms_http_server_s *hserver = (_ms_http_server_s *) user_data;
+
+ /* Close connetion if handle is NULL */
+ ms_retm_if(hserver == NULL, "Handle is NULL");
+
+ SoupMessageHeadersIter iter;
+ const char *name, *value;
+
+ ms_debug("%s %s HTTP/1.%d", msg->method, path,
+ soup_message_get_http_version(msg));
+ soup_message_headers_iter_init(&iter, msg->request_headers);
+ while (soup_message_headers_iter_next(&iter, &name, &value))
+ ms_debug("%s: %s", name, value);
+ if (msg->request_body->length)
+ ms_debug("%s", msg->request_body->data);
+
+ if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD) {
+ ms_info("Received read event");
+
+ /* Extract file path with URI. First symbol is '/' */
+ char *fs_dir = (char *)g_hash_table_lookup(hserver->uri_table, "adaptive_path");
+ char *file_path = g_strjoin(NULL, fs_dir, path+1, NULL);
+ const char *extension = get_filename_ext(path+1);
+ char *content = NULL;
+ gsize size = 0;
+ char *mime_type = NULL;
+
+ mime_type_get_mime_type(extension, &mime_type);
+
+ ms_info("Recieved URI %s", path + 1);
+ ms_info("mime-type: %s", mime_type);
+
+ if (MEDIA_STREAMER_ERROR_NONE !=
+ __ms_http_server_file_read_contents(file_path, &content, &size)) {
+
+ soup_message_set_status(msg, SOUP_STATUS_BAD_REQUEST);
+ } else {
+ ms_info("Sending response");
+ soup_message_set_response(msg, mime_type, SOUP_MEMORY_TAKE, content, size);
+ soup_message_set_status(msg, SOUP_STATUS_OK);
+ }
+
+ g_free(file_path);
+ g_free(mime_type);
+ } else {
+ soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ soup_message_set_status(msg, SOUP_STATUS_OK);
+ }
+}
diff --git a/src/media_streamer_net_util.c b/src/media_streamer_net_util.c
new file mode 100644
index 0000000..71a92e0
--- /dev/null
+++ b/src/media_streamer_net_util.c
@@ -0,0 +1,49 @@
+/*
+ * 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
+#include
+#include
+
+#include
+
+int __ms_get_local_network_address(char **ip_address)
+{
+ connection_h conn = NULL;
+ connection_type_e conn_type = CONNECTION_TYPE_DISCONNECTED;
+
+ if (CONNECTION_ERROR_NONE != connection_create(&conn)) {
+ ms_error("Failed to create connection");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (CONNECTION_ERROR_NONE != connection_get_type(conn, &conn_type)) {
+ ms_error("Failed to acquire connection type");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (conn_type != CONNECTION_TYPE_WIFI) {
+ ms_error("Wrong connection type");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (CONNECTION_ERROR_NONE != connection_get_ip_address(conn, CONNECTION_ADDRESS_FAMILY_IPV4, ip_address)) {
+ ms_error("Failed to acquire connection ip address");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c
index ddc60e5..5bd70c1 100644
--- a/src/media_streamer_node.c
+++ b/src/media_streamer_node.c
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -29,6 +30,7 @@
#define SMACK_LABEL_LEN 255
#define DEFAULT_URI_SCHEME_LENGTH 10
+#define DEFAULT_HTTP_PORT "8888"
param_s param_table[] = {
{MEDIA_STREAMER_PARAM_CAMERA_ID, "camera-id"},
@@ -855,6 +857,38 @@ static gboolean demux_find(gpointer key, gpointer value, gpointer user_data)
return g_strrstr((char *)key, "demux") != NULL;
}
+static int __ms_adaptive_sink_http_server_prepare(media_streamer_s * ms_streamer, media_streamer_node_s *node)
+{
+ int err_code = MEDIA_STREAMER_ERROR_NONE;
+ char *playlist_location = NULL;
+ char *playlist_dir = NULL;
+ char *split = NULL;
+
+ /* Create and start http server */
+ err_code = __ms_http_server_create(&ms_streamer->http_server, NULL, DEFAULT_HTTP_PORT);
+ if (MEDIA_STREAMER_ERROR_NONE != err_code) {
+ ms_error("Failed to create http server during prepare");
+ } else {
+ ms_info("Starting http server");
+ /* FIXME: find out how to set default port */
+ err_code = __ms_http_server_start(ms_streamer->http_server);
+ if (MEDIA_STREAMER_ERROR_NONE != err_code) {
+ ms_error("Failed to start http server during prepare. Destroying http server");
+ __ms_http_server_destroy(ms_streamer->http_server);
+ }
+ }
+
+ g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
+ split = strrchr(playlist_location, '/');
+ playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
+
+ __ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
+
+ MS_SAFE_GFREE(playlist_location);
+
+ return err_code;
+}
+
int __ms_pipeline_prepare(media_streamer_s *ms_streamer)
{
ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
@@ -863,6 +897,7 @@ int __ms_pipeline_prepare(media_streamer_s *ms_streamer)
media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
media_streamer_node_s *demux = (media_streamer_node_s *)g_hash_table_find(ms_streamer->nodes_table, (GHRFunc)demux_find, NULL);
media_streamer_node_s *adaptive_src = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_src");
+ media_streamer_node_s *adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
if (rtp_node) {
ret = __ms_rtp_element_prepare(rtp_node) ? MEDIA_STREAMER_ERROR_NONE : MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
} else if (demux) {
@@ -889,6 +924,9 @@ int __ms_pipeline_prepare(media_streamer_s *ms_streamer)
ret = __ms_adaptive_element_prepare(adaptive_src, false);
}
+ if (adaptive_sink)
+ __ms_adaptive_sink_http_server_prepare(ms_streamer, adaptive_sink);
+
if (ret != MEDIA_STREAMER_ERROR_NONE)
goto prepare_fail;
@@ -1477,7 +1515,7 @@ int __ms_node_set_param_value(media_streamer_node_s *ms_node, param_s *param, co
else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM))
g_object_set(ms_node->gst_element, param->origin_name, !g_ascii_strcasecmp(param_value, "true"), NULL);
else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
- ret = __ms_node_uri_path_check(param_value);
+ ret = __ms_util_uri_path_check(param_value);
if (ret == MEDIA_STREAMER_ERROR_NONE)
g_object_set(ms_node->gst_element, param->origin_name, param_value, NULL);
} else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT))
diff --git a/src/media_streamer_util.c b/src/media_streamer_util.c
index 4ea599f..7f55672 100644
--- a/src/media_streamer_util.c
+++ b/src/media_streamer_util.c
@@ -296,7 +296,7 @@ void __ms_param_value_destroy(gpointer data)
MS_SAFE_GFREE(val);
}
-int __ms_node_uri_path_check(const char *file_uri)
+int __ms_util_uri_path_check(const char *file_uri)
{
struct stat stat_results = {0, };
int file_open = 0;
@@ -308,7 +308,7 @@ int __ms_node_uri_path_check(const char *file_uri)
if (file_open < 0) {
char mes_error[256];
strerror_r(errno, mes_error, sizeof(mes_error));
- ms_error("Couldn`t open file according to [%s]. Error N [%d]", mes_error, errno);
+ ms_error("Couldn`t open file [%s] according to [%s]. Error N [%d]", file_uri, mes_error, errno);
if (EACCES == errno)
return MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
diff --git a/test/media_streamer_test.c b/test/media_streamer_test.c
index 3c8d834..11eafcc 100644
--- a/test/media_streamer_test.c
+++ b/test/media_streamer_test.c
@@ -1557,7 +1557,7 @@ void _interpret_getting_uri_menu(char *cmd)
return;
}
- g_print("_interpret_getting_uri_menu %d %d %d\n", g_menu_state, g_sub_menu_state, g_scenario_mode);
+ g_print("_interpret_getting_uri_menu %d %d %d", 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;
--
2.7.4
From 7fcbd1e606a124ae6ee1c24e4f88a52b5bc1bb49 Mon Sep 17 00:00:00 2001
From: Eunhae Choi
Date: Wed, 22 Mar 2017 19:21:06 +0900
Subject: [PATCH 13/16] [0.1.15] Use %license macro to copy license
Change-Id: I292746121fab2da101ba4a2f9c226565c368ecc7
---
packaging/capi-media-streamer.spec | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index d413ffb..e30cddc 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -71,10 +71,8 @@ make %{?jobs:-j%jobs}
%install
rm -rf %{buildroot}
-mkdir -p %{buildroot}%{_datadir}/license
-mkdir -p %{buildroot}/usr/bin
-cp LICENSE.APLv2 %{buildroot}%{_datadir}/license/%{name}
-cp test/media_streamer_test %{buildroot}/usr/bin
+mkdir -p %{buildroot}%{_bindir}
+cp test/media_streamer_test %{buildroot}%{_bindir}
mkdir -p %{buildroot}/usr/etc
@@ -90,7 +88,7 @@ mkdir -p %{buildroot}/usr/etc
%manifest %{name}.manifest
%license LICENSE.APLv2
%{_libdir}/lib%{name}.so.*
-%{_datadir}/license/%{name}
+%license LICENSE.APLv2
%{_bindir}/*
%files devel
--
2.7.4
From a8fe84c312f9607a87ec2fb38593465b2d38d2e4 Mon Sep 17 00:00:00 2001
From: Eunhae Choi
Date: Wed, 5 Apr 2017 16:41:03 +0900
Subject: [PATCH 14/16] doc: update featuring doc path
Change-Id: Icb0a69d20fe0f71b9dc8dc9b8da62d889b48a1e1
(cherry picked from commit 5431cd6d88366f21e0b44c8748f4edf923bc5930)
---
doc/mediastreamer_doc.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/mediastreamer_doc.h b/doc/mediastreamer_doc.h
index 117e05b..289d684 100755
--- a/doc/mediastreamer_doc.h
+++ b/doc/mediastreamer_doc.h
@@ -53,7 +53,7 @@
* It is recommended to design feature related codes in your application for reliability.\n
* You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n
* To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n
- * More details on featuring your application can be found from Feature Element.
+ * More details on featuring your application can be found from Feature List.
*
*/
--
2.7.4
From 56c3360271da3de3478d3968b4aca3112c75e847 Mon Sep 17 00:00:00 2001
From: Eunhae Choi
Date: Mon, 17 Apr 2017 16:46:40 +0900
Subject: [PATCH 15/16] [0.1.16] fix svace issue
Change-Id: I71289af8dae084733fd99b98429adc75da1bc211
---
LICENSE.APLv2 => LICENSE.Apache-2.0 | 0
packaging/capi-media-streamer.spec | 5 ++---
src/media_streamer_http_server.c | 4 +++-
src/media_streamer_node.c | 27 +++++++++++++++++++--------
4 files changed, 24 insertions(+), 12 deletions(-)
rename LICENSE.APLv2 => LICENSE.Apache-2.0 (100%)
mode change 100755 => 100644
diff --git a/LICENSE.APLv2 b/LICENSE.Apache-2.0
old mode 100755
new mode 100644
similarity index 100%
rename from LICENSE.APLv2
rename to LICENSE.Apache-2.0
diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec
index e30cddc..9e8832c 100644
--- a/packaging/capi-media-streamer.spec
+++ b/packaging/capi-media-streamer.spec
@@ -1,6 +1,6 @@
Name: capi-media-streamer
Summary: A Media Streamer API
-Version: 0.1.15
+Version: 0.1.16
Release: 0
Group: Multimedia/API
License: Apache-2.0
@@ -86,9 +86,8 @@ mkdir -p %{buildroot}/usr/etc
%files
%manifest %{name}.manifest
-%license LICENSE.APLv2
+%license LICENSE.Apache-2.0
%{_libdir}/lib%{name}.so.*
-%license LICENSE.APLv2
%{_bindir}/*
%files devel
diff --git a/src/media_streamer_http_server.c b/src/media_streamer_http_server.c
index 0179559..5d35bc2 100644
--- a/src/media_streamer_http_server.c
+++ b/src/media_streamer_http_server.c
@@ -199,8 +199,10 @@ static int __ms_http_server_file_read_contents(const char *file_path, char **con
}
*content = malloc((size_t)stat_results.st_size);
- if (read(file_open, *content, (size_t)stat_results.st_size) < (size_t)stat_results.st_size)
+ if (read(file_open, *content, (size_t)stat_results.st_size) < (size_t)stat_results.st_size) {
+ close(file_open);
return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
*size = (gsize)stat_results.st_size;
close(file_open);
diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c
index 5bd70c1..33afa5b 100644
--- a/src/media_streamer_node.c
+++ b/src/media_streamer_node.c
@@ -868,17 +868,26 @@ static int __ms_adaptive_sink_http_server_prepare(media_streamer_s * ms_streamer
err_code = __ms_http_server_create(&ms_streamer->http_server, NULL, DEFAULT_HTTP_PORT);
if (MEDIA_STREAMER_ERROR_NONE != err_code) {
ms_error("Failed to create http server during prepare");
- } else {
- ms_info("Starting http server");
- /* FIXME: find out how to set default port */
- err_code = __ms_http_server_start(ms_streamer->http_server);
- if (MEDIA_STREAMER_ERROR_NONE != err_code) {
- ms_error("Failed to start http server during prepare. Destroying http server");
- __ms_http_server_destroy(ms_streamer->http_server);
- }
+ goto _DONE;
+ }
+
+ ms_info("Starting http server");
+ /* FIXME: find out how to set default port */
+ err_code = __ms_http_server_start(ms_streamer->http_server);
+ if (MEDIA_STREAMER_ERROR_NONE != err_code) {
+ ms_error("Failed to start http server during prepare. Destroying http server");
+ __ms_http_server_destroy(ms_streamer->http_server);
+ goto _DONE;
}
g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
+ if (!playlist_location) {
+ err_code = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ ms_error("Failed to get playlist location");
+ __ms_http_server_destroy(ms_streamer->http_server);
+ goto _DONE;
+ }
+
split = strrchr(playlist_location, '/');
playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
@@ -886,6 +895,8 @@ static int __ms_adaptive_sink_http_server_prepare(media_streamer_s * ms_streamer
MS_SAFE_GFREE(playlist_location);
+_DONE:
+
return err_code;
}
--
2.7.4
From c41e5f861f18cd4c844e7a73fef331764b70649b Mon Sep 17 00:00:00 2001
From: Eunhae Choi
Date: Mon, 22 May 2017 20:01:53 +0900
Subject: [PATCH 16/16] [0.1.16] modify doc
Change-Id: I53bd6ea1e8714432ff1f721444a3b31a8d4231ef
---
doc/mediastreamer_doc.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/mediastreamer_doc.h b/doc/mediastreamer_doc.h
index 289d684..e97184c 100755
--- a/doc/mediastreamer_doc.h
+++ b/doc/mediastreamer_doc.h
@@ -53,7 +53,7 @@
* It is recommended to design feature related codes in your application for reliability.\n
* You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n
* To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n
- * More details on featuring your application can be found from Feature List.
+ * More details on featuring your application can be found from Feature Element.
*
*/
--
2.7.4