Enable resource manager commonization 51/314551/6
authorYoungHun Kim <yh8004.kim@samsung.com>
Mon, 15 Jul 2024 07:16:36 +0000 (16:16 +0900)
committerYoungHun Kim <yh8004.kim@samsung.com>
Mon, 29 Jul 2024 02:50:36 +0000 (11:50 +0900)
[Version] 0.4.1
[Issue Type] Update

Change-Id: I767316e222bb66d20bb9d577c8315e2c4092570c

configure.ac
packaging/libmm-wfd.spec
src/Makefile.am
src/include/mm_wfd_sink_priv.h
src/include/mm_wfd_sink_rm.h [new file with mode: 0644]
src/include/mm_wfd_sink_util.h
src/mm_wfd_sink_attrs.c
src/mm_wfd_sink_ini.c
src/mm_wfd_sink_priv.c
src/mm_wfd_sink_rm.c [new file with mode: 0644]

index e3d2be6ccf61714ca4d51dfb651c9f7fd831b5fd..31a13356749bf78bf0636b026e03035ff72d62ed 100644 (file)
@@ -103,9 +103,13 @@ PKG_CHECK_MODULES(CAPI_SYSTEM_INFO, capi-system-info)
 AC_SUBST(CAPI_SYSTEM_INFO_CFLAGS)
 AC_SUBST(CAPI_SYSTEM_INFO_LIBS)
 
-PKG_CHECK_MODULES(MM_RESOURCE_MANAGER, mm-resource-manager)
-AC_SUBST(MM_RESOURCE_MANAGER_CFLAGS)
-AC_SUBST(MM_RESOURCE_MANAGER_LIBS)
+PKG_CHECK_MODULES(RM, resource-manager)
+AC_SUBST(RM_CFLAGS)
+AC_SUBST(RM_LIBS)
+
+PKG_CHECK_MODULES(RC, resource-center-api)
+AC_SUBST(RC_CFLAGS)
+AC_SUBST(RC_LIBS)
 
 PKG_CHECK_MODULES(MM_DISPLAY_INTERFACE, mm-display-interface)
 AC_SUBST(MM_DISPLAY_INTERFACE_CFLAGS)
index d13175d8b74b85b5e180a914de3f16ef51c9a681..066211a47f06ae2a2df6d16e27455a010b53d63d 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-wfd
 Summary:    Multimedia Framework Wifi-Display Library
-Version:    0.3.13
+Version:    0.4.1
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
@@ -21,7 +21,8 @@ BuildRequires: pkgconfig(ecore-wl2)
 BuildRequires: pkgconfig(libtbm)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(capi-system-info)
-BuildRequires: pkgconfig(mm-resource-manager)
+BuildRequires: pkgconfig(resource-manager)
+BuildRequires: pkgconfig(resource-center-api)
 BuildRequires: pkgconfig(mm-display-interface)
 %if 0%{?gtests:1}
 BuildRequires:  pkgconfig(gmock)
index 6c83477f9c63a7f5f258ad210e2d1759cd9aae26..90fcaccabbc3f8dc13f54f30b01c8f01b4fbe873 100644 (file)
@@ -18,7 +18,8 @@ libmmfwfdsink_la_SOURCES = mm_wfd_sink_attrs.c \
                                mm_wfd_sink_manager.c \
                                mm_wfd_sink_config.c \
                                mm_wfd_sink_priv.c \
-                               mm_wfd_sink_wayland.c
+                               mm_wfd_sink_wayland.c \
+                               mm_wfd_sink_rm.c
 
 
 libmmfwfdsink_la_CFLAGS = -I$(srcdir)/include \
@@ -31,13 +32,15 @@ libmmfwfdsink_la_CFLAGS = -I$(srcdir)/include \
                        $(GST_VIDEO_CFLAGS) \
                        $(TZPLATFORM_CONFIG_CFLAGS) \
                        $(CAPI_SYSTEM_INFO_CFLAGS) \
-                       $(MM_RESOURCE_MANAGER_CFLAGS) \
+                       $(RM_CFLAGS) \
+                       $(RC_CFLAGS) \
                        $(MM_DISPLAY_INTERFACE_CFLAGS)
 
 libmmfwfdsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = include/mm_wfd_sink_manager.h \
-               include/mm_wfd_sink_wayland.h
+               include/mm_wfd_sink_wayland.h \
+               include/mm_wfd_sink_rm.h
 
 libmmfwfdsink_la_LIBADD = $(GST_LIBS) \
                        $(GST_PLUGINS_BASE_LIBS) \
@@ -49,7 +52,8 @@ libmmfwfdsink_la_LIBADD = $(GST_LIBS) \
                        $(TZPLATFORM_CONFIG_LIBS) \
                        $(CAPI_SYSTEM_INFO_LIBS) \
                        $(GST_VIDEO_LIBS) \
-                       $(MM_RESOURCE_MANAGER_LIBS) \
+                       $(RM_LIBS) \
+                       $(RC_LIBS) \
                        $(MM_DISPLAY_INTERFACE_LIBS)
 
 libmmfwfdsink_la_CFLAGS += $(MMLOG_CFLAGS) -DMMF_LOG_OWNER=0x02000000 -DMMF_DEBUG_PREFIX=\"MMF-WFD-SINK\"
index 1ed4868714d866b0062e073817d8a3d5b125633e..ca2ae68a29b820df3f4e073cae59e0b2925571a6 100644 (file)
@@ -32,7 +32,9 @@
 #include <mm_message.h>
 #include <mm_error.h>
 #include <mm_types.h>
-#include <mm_resource_manager.h>
+#include <rm_api.h>
+#include <rm_type.h>
+#include <resource_center.h>
 #include <mm_display_interface.h>
 #include "mm_wfd_sink_ini.h"
 #include "mm_wfd_sink_attrs.h"
@@ -169,7 +171,6 @@ typedef struct {
        MMWFDSinkVideoStreamInfo video_stream_info;
 } MMWFDSinkStreamInfo;
 
-
 typedef struct {
        gint id;
        GstElement *gst;
@@ -200,6 +201,18 @@ typedef struct {
        int(*unprepare)(MMHandleType wfd_sink);
 } MMWFDSinkPrivateFunc;
 
+/* priv func */
+typedef struct {
+       int handle;
+       rm_device_return_s devices[MM_WFD_SINK_RESOURCE_TYPE_MAX];
+       rm_consumer_info rci;
+       gboolean need_to_acquire[MM_WFD_SINK_RESOURCE_TYPE_MAX];
+       GMutex callback_lock;
+       GMutex control_lock;
+       gboolean interrupted_by_resource;
+} MMWFDSinkResource;
+
+
 #define MMWFDSINK_CAST(x_wfd)          ((mm_wfd_sink_t *)(x_wfd))
 #define MMWFDSINK_GET_ATTRS(x_wfd) ((x_wfd) ? ((mm_wfd_sink_t*)x_wfd)->attrs : (MMHandleType)NULL)
 
@@ -261,10 +274,7 @@ typedef struct {
        gchar *coupled_sink_address;
        gboolean is_coupled_sink_supported;
 
-       /* resource manager for H/W resources */
-       mm_resource_manager_h resource_manager;
-       mm_resource_manager_res_h hw_resource[MM_WFD_SINK_RESOURCE_TYPE_MAX];
-       gboolean interrupted_by_resource;
+       MMWFDSinkResource res;
 
        int display_surface_id;
 } mm_wfd_sink_t;
diff --git a/src/include/mm_wfd_sink_rm.h b/src/include/mm_wfd_sink_rm.h
new file mode 100644 (file)
index 0000000..9af9c3e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: YoungHun Kim <yh8004.kim@samsung.com>
+ *
+ * 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 _MM_WFD_SINK_RM_H_
+#define _MM_WFD_SINK_RM_H_
+
+#include "mm_wfd_sink_priv.h"
+
+int mm_wfd_sink_rm_create(mm_wfd_sink_t *wfd_sink);
+int mm_wfd_sink_rm_allocate(mm_wfd_sink_t *wfd_sink, MMWFDSinkResourceType type);
+int mm_wfd_sink_rm_deallocate(mm_wfd_sink_t *wfd_sink, MMWFDSinkResourceType type);
+int mm_wfd_sink_rm_release(mm_wfd_sink_t *wfd_sink);
+
+#endif
index 3dfaa8f432de023c5e1dfc150fd3c7a63f8cd8a0..3e9138130a2748d883e760750b51c7936add28ce 100644 (file)
 #include <mm_types.h>
 #include "mm_wfd_sink_dlog.h"
 
+#define MMWFDSINK_RET_FAIL(expr) \
+       do { \
+               if (!(expr)) { \
+                       LOGE("failed [%s]", #expr); \
+                       return; \
+               } \
+       } while (0)
+
+#define MMWFDSINK_RET_VAL_FAIL(expr, val) \
+       do { \
+               if (!(expr)) { \
+                       LOGE("failed [%s]", #expr); \
+                       return (val); \
+               } \
+       } while (0)
+
+
 #define MMWFDSINK_FREEIF(x) \
        do      {\
                if ((x)) \
index 62638352152b637d069ea66fb5e0e30897d4b51a..a0984a50cbace1dad80a0c56cb26f735e0824d07 100644 (file)
@@ -488,7 +488,7 @@ _mmwfd_construct_attribute(MMHandleType handle)
                                mm_attrs_set_valid_range(attrs, idx,
                                                                        wfd_attrs[idx].value_min,
                                                                        wfd_attrs[idx].value_max,
-                                                                       (int)wfd_attrs[idx].default_value);
+                                                                       GPOINTER_TO_INT(wfd_attrs[idx].default_value));
                        }
                        break;
 
index 89c3f7efb5a974fb1e5b41997b8d76d4856ac982..bee227ecefb17ae1c98c3d05882c216e9c9dad2a 100644 (file)
@@ -156,7 +156,7 @@ static void __mm_wfd_sink_ini_check_status(const char *path);
 /* macro */
 #define MM_WFD_SINK_INI_GET_STRING(x_dict, x_item, x_ini, x_default) \
        do { \
-               gchar *str = NULL; \
+               const gchar *str = NULL; \
                gint length = 0; \
                \
                str = iniparser_getstring(x_dict, x_ini, (char *)x_default); \
index 442b6ffe29c1d46d3fa4e53ec4e7039dd14d9645..dc39acf3eaec7fe2f636062dd9ab2392fccea4e7 100644 (file)
@@ -33,6 +33,7 @@
 #include "mm_wfd_sink_enum.h"
 #include "mm_wfd_sink_wayland.h"
 #include "mm_wfd_sink_config.h"
+#include "mm_wfd_sink_rm.h"
 
 #define PRINT_WFD_REF_COUNT(wfd_sink)\
        do {\
@@ -47,114 +48,6 @@ static gboolean _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer
 /* util */
 static void __mm_wfd_sink_dump_pipeline_state(mm_wfd_sink_t *wfd_sink);
 
-static int
-__resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
-               void *user_data)
-{
-       mm_wfd_sink_t *wfdsink = NULL;
-       MMWFDSinkResourceType res_idx = MM_WFD_SINK_RESOURCE_TYPE_MAX;
-
-       wfd_sink_debug_fenter();
-
-       if (!user_data) {
-               wfd_sink_error("user_data is null");
-               return FALSE;
-       }
-
-       wfdsink = (mm_wfd_sink_t *)user_data;
-
-       wfdsink->interrupted_by_resource = TRUE;
-
-       wfd_sink_debug("resource is interrupted. resource would be released after destroying");
-
-       MMWFDSINK_CMD_LOCK(wfdsink);
-       if (_mm_wfd_sink_disconnect(wfdsink) != MM_ERROR_NONE)
-               wfd_sink_error("failed to disconnect");
-
-       if (_mm_wfd_sink_unprepare(wfdsink) != MM_ERROR_NONE)
-               wfd_sink_error("failed to unprepare");
-       for (res_idx = MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MM_WFD_SINK_RESOURCE_TYPE_MAX; res_idx++) {
-               wfdsink->hw_resource[res_idx] = NULL;
-       }
-       MMWFDSINK_CMD_UNLOCK(wfdsink);
-
-       wfd_sink_debug_fleave();
-       return TRUE; /* release all the resources */
-}
-
-static int __mm_wfd_sink_acquire_hw_resource (mm_wfd_sink_t* wfd_sink, MMWFDSinkResourceType type)
-{
-       int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
-
-       wfd_sink_debug_fenter();
-
-       mm_resource_manager_res_type_e rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
-
-       switch (type) {
-               case MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER:
-                       rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER;
-                       break;
-               case MM_WFD_SINK_RESOURCE_TYPE_VIDEO_OVERLAY:
-                       rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY;
-                       break;
-               default:
-                       wfd_sink_error("invalid wfd sink resource type %d", type);
-                       return MM_ERROR_WFD_INTERNAL;
-       }
-
-       if (wfd_sink->hw_resource[type] != NULL) {
-               wfd_sink_debug("[%d type] resource was already acquired", type);
-               return MM_ERROR_NONE;
-       }
-
-       wfd_sink_debug("mark for acquire [%d type] resource", type);
-       rm_ret = mm_resource_manager_mark_for_acquire(wfd_sink->resource_manager,
-                       rm_res_type, MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &wfd_sink->hw_resource[type]);
-       if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-               wfd_sink_error("failed to mark resource for acquire, ret(0x%x)", rm_ret);
-               return MM_ERROR_WFD_INTERNAL;
-       }
-
-       rm_ret = mm_resource_manager_commit(wfd_sink->resource_manager);
-       if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-               wfd_sink_error("failed to commit of resource, ret(0x%x)", rm_ret);
-               return MM_ERROR_WFD_INTERNAL;
-       }
-
-       wfd_sink_debug_fleave();
-       return MM_ERROR_NONE;
-}
-
-static int __mm_wfd_sink_release_hw_resource(mm_wfd_sink_t *wfd_sink, MMWFDSinkResourceType type)
-{
-       int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
-
-       wfd_sink_debug_fenter();
-
-       if (wfd_sink->hw_resource[type] == NULL) {
-               wfd_sink_debug("there is no acquired [%d type] resource", type);
-               return MM_ERROR_NONE;
-       }
-
-       wfd_sink_debug("mark for release [%d type] resource", type);
-       rm_ret = mm_resource_manager_mark_for_release(wfd_sink->resource_manager, wfd_sink->hw_resource[type]);
-       if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-               wfd_sink_error("failed to mark resource for release, ret(0x%x)", rm_ret);
-               return MM_ERROR_WFD_INTERNAL;
-       }
-
-       wfd_sink->hw_resource[type] = NULL;
-
-       rm_ret = mm_resource_manager_commit(wfd_sink->resource_manager);
-       if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-               wfd_sink_error("failed to commit of resource, ret(0x%x)", rm_ret);
-               return MM_ERROR_WFD_INTERNAL;
-       }
-
-       wfd_sink_debug_fleave();
-       return MM_ERROR_NONE;
-}
-
 int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink, const char *ini_path)
 {
        int result = MM_ERROR_NONE;
@@ -177,12 +70,11 @@ int _mm_wfd_sink_create(mm_wfd_sink_t **wfd_sink, const char *ini_path)
        }
 
        /* initialize resource manager */
-       if (mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
-               __resource_release_cb, new_wfd_sink, &new_wfd_sink->resource_manager)
-               != MM_RESOURCE_MANAGER_ERROR_NONE) {
-               wfd_sink_error("failed to initialize resource manager");
-               MMWFDSINK_FREEIF(new_wfd_sink);
-               return MM_ERROR_WFD_INTERNAL;
+       result = mm_wfd_sink_rm_create(new_wfd_sink);
+       if (result != MM_ERROR_NONE) {
+               result = MM_ERROR_WFD_INTERNAL;
+               wfd_sink_error("failed to mm_wfd_sink_rm_create %d", result);
+               goto fail_to_attrs;
        }
 
        /* Initialize gstreamer related */
@@ -283,7 +175,7 @@ fail_to_init:
 fail_to_load_ini:
        _mmwfd_deconstruct_attribute(new_wfd_sink->attrs);
 fail_to_attrs:
-       mm_resource_manager_destroy(new_wfd_sink->resource_manager);
+       mm_wfd_sink_rm_release(new_wfd_sink);
        MMWFDSINK_FREEIF(new_wfd_sink);
 
        *wfd_sink = NULL;
@@ -520,12 +412,12 @@ int _mm_wfd_sink_unprepare(mm_wfd_sink_t *wfd_sink)
        /* set state */
        __mm_wfd_sink_set_state(wfd_sink,  MM_WFD_SINK_STATE_NULL);
 
-       if (!wfd_sink->interrupted_by_resource) {
+       if (!wfd_sink->res.interrupted_by_resource) {
                int rm_ret = MM_ERROR_NONE;
                MMWFDSinkResourceType res_idx = MM_WFD_SINK_RESOURCE_TYPE_MAX;
 
                for (res_idx = MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MM_WFD_SINK_RESOURCE_TYPE_MAX; res_idx++) {
-                       rm_ret = __mm_wfd_sink_release_hw_resource(wfd_sink, res_idx);
+                       rm_ret = mm_wfd_sink_rm_deallocate(wfd_sink, res_idx);
                        if (rm_ret != MM_ERROR_NONE)
                                wfd_sink_error("failed to release [%d] resources", res_idx);
                }
@@ -556,7 +448,7 @@ int _mm_wfd_sink_destroy(mm_wfd_sink_t *wfd_sink)
        g_free(wfd_sink->coupled_sink_address);
 
        /* release resource manager */
-       if (MM_ERROR_NONE != mm_resource_manager_destroy(wfd_sink->resource_manager)) {
+       if (MM_ERROR_NONE != mm_wfd_sink_rm_release(wfd_sink)) {
                result = MM_ERROR_WFD_INTERNAL;
                wfd_sink_error("failed to destroy resource manager");
        }
@@ -4408,10 +4300,11 @@ int __mm_wfd_sink_create_video_decodebin(mm_wfd_sink_t *wfd_sink)
                MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_decodebin[WFD_SINK_V_D_H264_PARSE].gst,  "src");
 
                if (!g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "sprddec_h264") ||
-                       !g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "omxdec_h264")) {
+                       !g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "omxdec_h264") ||
+                       !g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "v4l2h264dec")) {
                        /* acquire HW resource */
                        wfd_sink_error("wfd_sink->ini.name_of_video_h264_decoder1 :: %s", wfd_sink->ini.name_of_video_h264_decoder);
-                       if (__mm_wfd_sink_acquire_hw_resource(wfd_sink, MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+                       if (mm_wfd_sink_rm_allocate(wfd_sink, MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
                                wfd_sink_error("failed to acquire video decoder resource");
                                goto CREATE_ERROR;
                        }
@@ -4651,7 +4544,7 @@ int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
        /* create sink */
        mm_attrs_get_int_by_name(wfd_sink->attrs, "display_surface_type", &surface_type);
        if (surface_type == MM_DISPLAY_SURFACE_OVERLAY &&
-               (__mm_wfd_sink_acquire_hw_resource(wfd_sink, MM_WFD_SINK_RESOURCE_TYPE_VIDEO_OVERLAY) == MM_ERROR_NONE)) {
+               (mm_wfd_sink_rm_allocate(wfd_sink, MM_WFD_SINK_RESOURCE_TYPE_VIDEO_OVERLAY) == MM_ERROR_NONE)) {
                MMWFDSINK_CREATE_ELEMENT(v_sinkbin, WFD_SINK_V_S_SINK, wfd_sink->ini.name_of_video_sink, "video_sink", TRUE);
                if(!g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "v4l2h264dec") || !g_strcmp0(wfd_sink->ini.name_of_video_h264_decoder, "sprddec_h264"))
                        if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(v_sinkbin[WFD_SINK_V_S_SINK].gst)), "use-tbm"))
@@ -4663,7 +4556,7 @@ int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
                goto CREATE_ERROR;
        }
 
-       wfd_sink->interrupted_by_resource = FALSE;
+       wfd_sink->res.interrupted_by_resource = FALSE;
 
        MMWFDSINK_PAD_PROBE(wfd_sink, NULL, v_sinkbin[WFD_SINK_V_S_SINK].gst,  "sink");
        if (v_sinkbin[WFD_SINK_V_S_SINK].gst) {
diff --git a/src/mm_wfd_sink_rm.c b/src/mm_wfd_sink_rm.c
new file mode 100644 (file)
index 0000000..1b442a4
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * libmm-wfd
+ *
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: YoungHun Kim <yh8004.kim@samsung.com>
+ *
+ * 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 <unistd.h>
+#include "mm_wfd_sink_rm.h"
+#include "mm_wfd_sink_util.h"
+
+static void
+_mm_wfd_execute_resource_release(mm_wfd_sink_t *wfd_sink)
+{
+       wfd_sink_debug_fenter();
+
+       MMWFDSINK_RET_FAIL(wfd_sink);
+
+       MMWFDSINK_CMD_LOCK(wfd_sink);
+
+       if (_mm_wfd_sink_disconnect(wfd_sink) != MM_ERROR_NONE)
+               wfd_sink_error("failed to disconnect");
+
+       if (_mm_wfd_sink_unprepare(wfd_sink) != MM_ERROR_NONE)
+               wfd_sink_error("failed to unprepare");
+
+       MMWFDSINK_CMD_UNLOCK(wfd_sink);
+
+       wfd_sink_debug_fleave();
+}
+
+static int
+__get_appid_by_pid(int pid, char *name, size_t size)
+{
+       g_autofree gchar *cmdline = NULL;
+       g_autofree gchar *contents = NULL;
+       g_autofree gchar *base = NULL;
+       g_autoptr(GError) error = NULL;
+
+       MMWFDSINK_RET_VAL_FAIL(name, MM_ERROR_WFD_INVALID_ARGUMENT);
+       MMWFDSINK_RET_VAL_FAIL(size, MM_ERROR_WFD_INVALID_ARGUMENT);
+
+       cmdline = g_strdup_printf("/proc/%d/cmdline", pid);
+
+       if (!g_file_get_contents(cmdline, &contents, NULL, &error)) {
+               wfd_sink_error("error : %s", error->message);
+               return MM_ERROR_WFD_INTERNAL;
+       }
+
+       base = g_path_get_basename(contents);
+
+       if (g_strlcpy(name, base, size) >= size)
+               wfd_sink_error("string truncated");
+
+       return MM_ERROR_NONE;
+}
+
+static rm_cb_result
+__resource_release_cb(int handle, rm_callback_type event_src, rm_device_request_s *info, void *cb_data)
+{
+       mm_wfd_sink_t *wfd_sink = NULL;
+       g_autoptr(GMutexLocker) locker = NULL;
+
+       wfd_sink_debug_fenter();
+
+       if (!cb_data) {
+               wfd_sink_error("cb_data is null");
+               return RM_CB_RESULT_ERROR;
+       }
+
+       wfd_sink = (mm_wfd_sink_t *)cb_data;
+
+       wfd_sink_info("rm callback info wfdsink [%p] handle : %d event_src : %d", wfd_sink, handle, event_src);
+
+       locker = g_mutex_locker_new(&wfd_sink->res.callback_lock);
+
+       switch (event_src) {
+       case RM_CALLBACK_TYPE_RESOURCE_CONFLICT:
+       case RM_CALLBACK_TYPE_RESOURCE_CONFLICT_UD:
+               _mm_wfd_execute_resource_release(wfd_sink);
+               break;
+       default:
+               break;
+       }
+
+       wfd_sink_debug_fleave();
+
+       return RM_CB_RESULT_OK;
+}
+
+int mm_wfd_sink_rm_create(mm_wfd_sink_t *wfd_sink)
+{
+       int ret = 0;
+
+       wfd_sink_debug_fenter();
+
+       MMWFDSINK_RET_VAL_FAIL(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+       g_mutex_init(&wfd_sink->res.control_lock);
+       g_mutex_init(&wfd_sink->res.callback_lock);
+
+       wfd_sink->res.rci.app_pid = (int)getpid();
+
+       if (__get_appid_by_pid(wfd_sink->res.rci.app_pid, wfd_sink->res.rci.app_id, sizeof(wfd_sink->res.rci.app_id)) != MM_ERROR_NONE) {
+               wfd_sink_error("__get_appid_by_pid is failed");
+               return MM_ERROR_WFD_INTERNAL;
+       }
+
+       ret = rm_register((rm_resource_cb)__resource_release_cb,
+                                               (void *)wfd_sink,
+                                               &(wfd_sink->res.handle),
+                                               (wfd_sink->res.rci.app_id[0] != '\0') ? &wfd_sink->res.rci : NULL);
+       if (ret != RM_OK) {
+               wfd_sink_error("rm_register fail %d", ret);
+               return MM_ERROR_WFD_INTERNAL;
+       }
+
+       wfd_sink_info("app pid %d app id %s resource h %d", wfd_sink->res.rci.app_pid, wfd_sink->res.rci.app_id, wfd_sink->res.handle);
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
+int mm_wfd_sink_rm_allocate(mm_wfd_sink_t *wfd_sink, MMWFDSinkResourceType type)
+{
+       int ret = RM_OK;
+       int idx = 0;
+       int category_option = 0;
+       rm_rsc_category_e category_id = RM_CATEGORY_NONE;
+       rm_requests_resource_state_e state;
+       rm_category_request_s request_resources;
+       rm_device_return_s *devices;
+       g_autoptr(GMutexLocker) locker = NULL;
+
+       wfd_sink_debug_fenter();
+
+       MMWFDSINK_RET_VAL_FAIL(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+       locker = g_mutex_locker_new(&wfd_sink->res.control_lock);
+
+       wfd_sink_info("app id : %s type %d", wfd_sink->res.rci.app_id, type);
+       memset(&request_resources, 0x0, sizeof(rm_category_request_s));
+
+       devices = &wfd_sink->res.devices[type];
+       memset(devices, 0x0, sizeof(rm_device_return_s));
+
+       switch (type) {
+       case MM_WFD_SINK_RESOURCE_TYPE_VIDEO_DECODER:
+               state = RM_STATE_EXCLUSIVE;
+               category_id = RM_CATEGORY_VIDEO_DECODER;
+               break;
+       case MM_WFD_SINK_RESOURCE_TYPE_VIDEO_OVERLAY:
+               state = RM_STATE_EXCLUSIVE;
+               category_id = RM_CATEGORY_SCALER;
+               break;
+       default:
+               wfd_sink_error("category id can't set");
+               return MM_ERROR_WFD_INTERNAL;
+       }
+
+       category_option = rc_get_capable_category_id(wfd_sink->res.handle, wfd_sink->res.rci.app_id, category_id);
+
+       request_resources.request_num = 1;
+       request_resources.state[0] = state;
+       request_resources.category_id[0] = category_id;
+       request_resources.category_option[0] = category_option;
+       wfd_sink_info("state %d category id 0x%x category option %d", state, category_id, category_option);
+
+       ret = rm_allocate_resources(wfd_sink->res.handle, &request_resources, devices);
+       if (ret != RM_OK) {
+               wfd_sink_warning("Resource allocation request failed ret %d [error type %d]", ret, devices->error_type);
+               return MM_ERROR_WFD_INTERNAL;
+       }
+
+       for (idx = 0; idx < devices->allocated_num; idx++)
+               wfd_sink_info("#%d / %d [%p] device %d %s %s", idx, devices->allocated_num, devices,
+                       devices->device_id[idx], devices->device_node[idx],
+                       devices->device_name[idx]);
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
+int mm_wfd_sink_rm_deallocate(mm_wfd_sink_t *wfd_sink, MMWFDSinkResourceType type)
+{
+       int rm_ret = RM_OK;
+       int idx = 0;
+       rm_device_request_s requested;
+       rm_device_return_s *r_devices;
+       g_autoptr(GMutexLocker) locker = NULL;
+
+       wfd_sink_debug_fenter();
+
+       MMWFDSINK_RET_VAL_FAIL(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+       MMWFDSINK_RET_VAL_FAIL(wfd_sink->res.handle, MM_ERROR_WFD_NOT_INITIALIZED);
+
+       locker = g_mutex_locker_new(&wfd_sink->res.control_lock);
+
+       r_devices = &wfd_sink->res.devices[type];
+
+       wfd_sink_info("[%p] #%d (type %d) alloc num %d", r_devices, idx, type, r_devices->allocated_num);
+
+       if (r_devices->allocated_num > 0) {
+               memset(&requested, 0x0, sizeof(rm_device_request_s));
+               requested.request_num = r_devices->allocated_num;
+               for (idx = 0; idx < requested.request_num; idx++) {
+                       requested.device_id[idx] = r_devices->device_id[idx];
+                       wfd_sink_info("[device id %d] [device name %s]", r_devices->device_id[idx], r_devices->device_name[idx]);
+               }
+
+               rm_ret = rm_deallocate_resources(wfd_sink->res.handle, &requested);
+               if (rm_ret != RM_OK) {
+                       wfd_sink_error("Resource deallocation request failed [%d] [request num %d]", rm_ret, requested.request_num);
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+       }
+
+       for (idx = 0; idx < r_devices->allocated_num; idx++) {
+               if (r_devices->device_node[idx]) {
+                       free(r_devices->device_node[idx]);
+                       r_devices->device_node[idx] = NULL;
+               }
+
+               if (r_devices->omx_comp_name[idx]) {
+                       free(r_devices->omx_comp_name[idx]);
+                       r_devices->omx_comp_name[idx] = NULL;
+               }
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
+int mm_wfd_sink_rm_release(mm_wfd_sink_t *wfd_sink)
+{
+       int ret;
+
+       wfd_sink_debug_fenter();
+
+       MMWFDSINK_RET_VAL_FAIL(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
+
+       if (!wfd_sink->res.handle) {
+               wfd_sink_info("resource manager handle is not registered");
+               return MM_ERROR_NONE;
+       }
+
+       ret = rm_unregister(wfd_sink->res.handle);
+       if (ret != RM_OK) {
+               wfd_sink_error("rm_unregister fail %d", ret);
+               return MM_ERROR_WFD_INTERNAL;
+       }
+
+       g_mutex_clear(&wfd_sink->res.control_lock);
+       g_mutex_clear(&wfd_sink->res.callback_lock);
+
+       wfd_sink_debug("rm_unregister[%d]", ret);
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}