From: Volodymyr Brynza Date: Thu, 8 Dec 2016 11:48:09 +0000 (+0200) Subject: Implement DPM requests for camera and mic X-Git-Tag: submit/tizen/20161213.083228^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F87%2F103487%2F1;p=platform%2Fcore%2Fapi%2Fmediastreamer.git Implement DPM requests for camera and mic Change-Id: Ic1e57ca37017a0aac694a457e5b62b00ba0cf55b Signed-off-by: Volodymyr Brynza --- 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; +}