Enable resource manager commonization 18/314618/17 accepted/tizen/unified/20240816.171352 accepted/tizen/unified/dev/20240819.095525 accepted/tizen/unified/x/20240819.023433
authorYoungHun Kim <yh8004.kim@samsung.com>
Tue, 16 Jul 2024 08:23:00 +0000 (17:23 +0900)
committerYoungHun Kim <yh8004.kim@samsung.com>
Fri, 2 Aug 2024 03:11:34 +0000 (12:11 +0900)
[Version] 1.1.0
[Issue Type] Update

Change-Id: Iafc1f27db618838b47138ae9f36ffd5cde5f7e68

CMakeLists.txt
include/media_codec_private.h
include/media_codec_rm.h [new file with mode: 0644]
packaging/capi-media-codec.spec
src/media_codec.c
src/media_codec_rm.c [new file with mode: 0644]

index fb87c89e2ceba9bed557f7382a7a3eefae093060..9f3c7efd6198fa99c148e90641ceb74af1d4d864 100644 (file)
@@ -12,9 +12,9 @@ INCLUDE_DIRECTORIES(${INC_DIR})
 
 SET(dependents "dlog glib-2.0 mm-common libtbm capi-media-tool iniparser gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 gstreamer-pbutils-1.0 gstreamer-tag-1.0 capi-system-info gstreamer-allocators-1.0")
 SET(pc_dependents "capi-base-common capi-media-tool")
-IF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
-SET(dependents "${dependents} mm-resource-manager")
-ENDIF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
+IF(RMC)
+SET(dependents "${dependents} resource-manager resource-center-api")
+ENDIF(RMC)
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${dependents})
@@ -31,9 +31,9 @@ ENDIF("${ARCH}" STREQUAL "arm")
 
 ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
 ADD_DEFINITIONS("-DTIZEN_DEBUG")
-IF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
-ADD_DEFINITIONS("-DUSE_MM_RESOURCE_MANAGER")
-ENDIF(TIZEN_FEATURE_MM_RESOURCE_MANAGER)
+IF(RMC)
+ADD_DEFINITIONS("-DRM_COMMON")
+ENDIF(RMC)
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}")
 
index 08cfecc124b1b7490e70e545c54c80a3ac301c79..12915a00f3e738b01b01c5dfc978485bf40c9fd6 100644 (file)
@@ -24,8 +24,8 @@
 #include <media_codec.h>
 
 #include <mm_types.h>
-#ifdef USE_MM_RESOURCE_MANAGER
-#include <mm_resource_manager.h>
+#ifdef RM_COMMON
+#include <rm_api.h>
 #endif
 
 #ifdef __cplusplus
@@ -75,6 +75,22 @@ typedef enum {
        MEDIACODEC_PORT_TYPE_MAX,
 } mediacodec_port_type_e;
 
+#ifdef RM_COMMON
+typedef enum {
+       RES_TYPE_VIDEO_DECODER,     /**< ID of video decoder resource type */
+       RES_TYPE_VIDEO_ENCODER,     /**< ID of video encoder resource type */
+       RES_TYPE_MAX,               /**< Used to iterate on resource types only */
+} mediacodec_res_type_e;
+
+typedef struct _mediacodec_res_s {
+       int handle;
+       rm_device_return_s devices[RES_TYPE_MAX];
+       rm_consumer_info rci;
+       GMutex callback_lock;
+       GMutex control_lock;
+} mediacodec_res_s;
+#endif
+
 /**
  * @brief Media Codec's format for configuring codec.
  */
@@ -103,8 +119,9 @@ typedef struct _mediacodec_s {
        int state;
        bool is_omx;
        char *m_mime;
-#ifdef USE_MM_RESOURCE_MANAGER
-       mm_resource_manager_res_h codec_resource;
+
+#ifdef RM_COMMON
+       mediacodec_res_s resource;
 #endif
 
        mediacodec_input_buffer_used_cb empty_buffer_cb;
@@ -120,6 +137,7 @@ typedef struct _mediacodec_s {
 } mediacodec_s;
 
 bool __mediacodec_state_validate(mediacodec_h mediacodec, mediacodec_state_e threshold);
+gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data);
 
 #ifdef __cplusplus
 }
diff --git a/include/media_codec_rm.h b/include/media_codec_rm.h
new file mode 100644 (file)
index 0000000..2265e79
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __TIZEN_MEDIA_CODEC_RM_H__
+#define __TIZEN_MEDIA_CODEC_RM_H__
+
+#include <media_codec_private.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mediacodec_resource_create(mediacodec_s *mediacodec );
+int mediacodec_resource_allocate(mediacodec_s *mediacodec, mediacodec_res_type_e type);
+int mediacodec_resource_deallocate(mediacodec_s *mediacodec, mediacodec_res_type_e type);
+int mediacodec_resource_release(mediacodec_s *mediacodec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_MEDIA_CODEC_RM_H__ */
index deae11cef6432c23b49e90667ae88349d59e694c..187de3d179075aaf3b20f3e9345934ee3f86010e 100644 (file)
@@ -4,7 +4,7 @@
 
 Name:       capi-media-codec
 Summary:    A Media Codec library in Tizen Native API
-Version:    1.0.2
+Version:    1.1.0
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -25,7 +25,8 @@ BuildRequires:  pkgconfig(gstreamer-allocators-1.0)
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(iniparser)
 %if "%{tizen_profile_name}" != "tv"
-BuildRequires:  pkgconfig(mm-resource-manager)
+BuildRequires:  pkgconfig(resource-center-api)
+BuildRequires:  pkgconfig(resource-manager)
 %endif
 #BuildRequires:  pkgconfig(capi-media-camera)
 #BuildRequires:  pkgconfig(capi-mediademuxer)
@@ -73,9 +74,9 @@ SO_FULLVER=0.7.0
 SO_MAJORVER=`echo ${SO_FULLVER} | awk 'BEGIN {FS="."}{print $1}'`
 %cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER} -DSO_FULLVER=${SO_FULLVER} -DSO_MAJORVER=${SO_MAJORVER} \
 %if "%{tizen_profile_name}" == "tv"
-  -DTIZEN_FEATURE_MM_RESOURCE_MANAGER=NO
+  -DRMC=NO
 %else
-  -DTIZEN_FEATURE_MM_RESOURCE_MANAGER=YES
+  -DRMC=YES
 %endif
 
 make %{?jobs:-j%jobs}
index 0e094fd88c0759fe04a6b5b6a6348644cdd9e309..649c12613287349d1c7fc0f9425f7ae1a6783479 100644 (file)
 
 #include <dlog.h>
 
-#define MC_PREALLOCATED_HANDLE_ARRAY_SIZE 16
-
-#ifdef USE_MM_RESOURCE_MANAGER
-static mm_resource_manager_h g_mc_resource_manager;
-static GPtrArray *g_mediacodec_handles;
-static GMutex g_mediacodec_lock;
+#ifdef RM_COMMON
+#include <media_codec_rm.h>
 #endif
 
 static gboolean  __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data);
 static gboolean __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data);
-static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data);
 static gboolean __mediacodec_eos_cb(void *user_data);
 static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data);
-#ifdef USE_MM_RESOURCE_MANAGER
-static void __mediacodec_init_lib() __attribute__((constructor));
-static void __mediacodec_deinit_lib() __attribute__((destructor));
-static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
-               mm_resource_manager_res_h resource_h, void *user_data);
-#endif
 
 /*
  * Internal Implementation
@@ -134,22 +123,6 @@ int mediacodec_create(mediacodec_h *mediacodec)
 
        LOGD("mediacodec_create..");
 
-#ifdef USE_MM_RESOURCE_MANAGER
-       g_mutex_lock(&g_mediacodec_lock);
-
-       if (!g_mc_resource_manager) {
-               int mm_ret = mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
-                       __mediacodec_resource_release_cb, NULL, &g_mc_resource_manager);
-               if (mm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-                       g_mutex_unlock(&g_mediacodec_lock);
-                       LOGE("mm_resource_manager_create failed 0x%x", mm_ret);
-                       return MEDIACODEC_ERROR_INTERNAL;
-               }
-       }
-
-       g_mutex_unlock(&g_mediacodec_lock);
-#endif
-
        handle = (mediacodec_s *)malloc(sizeof(mediacodec_s));
        if (handle != NULL) {
                memset(handle, 0 , sizeof(mediacodec_s));
@@ -179,10 +152,17 @@ int mediacodec_create(mediacodec_h *mediacodec)
        mc_set_eos_cb(handle->mc_handle, (mediacodec_eos_cb)__mediacodec_eos_cb, handle);
        mc_set_buffer_status_cb(handle->mc_handle, (mediacodec_buffer_status_cb)__mediacodec_buffer_status_cb, handle);
 
-#ifdef USE_MM_RESOURCE_MANAGER
-       g_mutex_lock(&g_mediacodec_lock);
-       g_ptr_array_insert(g_mediacodec_handles, -1, *mediacodec);
-       g_mutex_unlock(&g_mediacodec_lock);
+#ifdef RM_COMMON
+       ret = mediacodec_resource_create(handle);
+       if (ret != MEDIACODEC_ERROR_NONE) {
+               handle->state = MEDIACODEC_STATE_NONE;
+               if (mc_destroy(handle->mc_handle) != MEDIACODEC_ERROR_NONE) {
+                       LOGE("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
+                       return MEDIACODEC_ERROR_INVALID_OPERATION;
+               }
+               g_free(handle);
+               return __convert_error_code(ret, (char *)__FUNCTION__);
+       }
 #endif
 
        return MEDIACODEC_ERROR_NONE;
@@ -197,20 +177,22 @@ int mediacodec_destroy(mediacodec_h mediacodec)
 
        int ret = mc_destroy(handle->mc_handle);
        if (ret != MEDIACODEC_ERROR_NONE) {
-               LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION); //LCOV_EXCL_LINE
+               LOGE("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION); //LCOV_EXCL_LINE
                return MEDIACODEC_ERROR_INVALID_OPERATION;
-       } else {
-#ifdef USE_MM_RESOURCE_MANAGER
-               g_mutex_lock(&g_mediacodec_lock);
-               g_ptr_array_remove_fast(g_mediacodec_handles, mediacodec);
-               g_mutex_unlock(&g_mediacodec_lock);
-#endif
+       }
 
-               handle->state = MEDIACODEC_STATE_NONE;
-               free(handle);
-               handle = NULL;
-               return MEDIACODEC_ERROR_NONE;
+#ifdef RM_COMMON
+       ret = mediacodec_resource_release(handle);
+       if (ret != MEDIACODEC_ERROR_NONE) {
+               return __convert_error_code(ret, (char *)__FUNCTION__);
        }
+#endif
+
+       handle->state = MEDIACODEC_STATE_NONE;
+       free(handle);
+       handle = NULL;
+       return MEDIACODEC_ERROR_NONE;
+
 }
 
 int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_id, int flags)
@@ -313,65 +295,29 @@ int mediacodec_prepare(mediacodec_h mediacodec)
 {
        MEDIACODEC_INSTANCE_CHECK(mediacodec);
        mediacodec_s *handle = (mediacodec_s *)mediacodec;
-#ifdef USE_MM_RESOURCE_MANAGER
-       mc_handle_t *mc_handle = (mc_handle_t *) handle->mc_handle;
-       int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
-       mm_resource_manager_res_h resource;
-#endif
+       int ret;
+       mc_handle_t *mc_handle = NULL;
+
        MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
 
-#ifdef USE_MM_RESOURCE_MANAGER
+#ifdef RM_COMMON
+//LCOV_EXCL_START
+       mc_handle = handle->mc_handle;
+       MEDIACODEC_INSTANCE_CHECK(mc_handle);
+
        if (mc_handle->is_hw && mc_handle->is_video) {
+               mc_handle = (mc_handle_t *) handle->mc_handle;
 
-               if (handle->codec_resource) {
-                       LOGE("Codec resource is tried to be acquired twice\n"); //LCOV_EXCL_LINE
-                       return MC_INTERNAL_ERROR;
-               }
+               ret = mediacodec_resource_allocate(handle, mc_handle->is_encoder ? RES_TYPE_VIDEO_ENCODER : RES_TYPE_VIDEO_DECODER);
 
-               /*
-                * TODO
-                * Currently volume of requested resource is set to 1. Default
-                * capacity for video encoder/decoder is 1 too. The actual capacity
-                * should be set in mmfw-sysconf > mmfw_resource_manager.ini.
-                * If different encode/decode operation needs different volume of
-                * video encoder/decoder, '1' in the following
-                * mm_resource_manager_mark_for_acquire function should be set to
-                * corresponding value.
-                * If that value depends on platform where it's executed,
-                * MM_RESOURCE_MANAGER_RES_TYPE_COND_* and
-                * mm_resource_manager_get_res_type_volume() can be used.
-                * Additional info can be found in doxygen comments of mm_resource_manager.h
-                */
-//LCOV_EXCL_START
-               rm_ret = mm_resource_manager_mark_for_acquire(g_mc_resource_manager,
-                               mc_handle->is_encoder ?
-                               MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_ENCODER :
-                               MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
-                               1, &resource);
-               if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-                       LOGE("Failed to acquire resource manager %x", rm_ret);
-                       switch (rm_ret) {
-                       case MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED:
-                               return MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE;
-                       case MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH:
-                               return MEDIACODEC_ERROR_RESOURCE_OVERLOADED;
-                       default:
-                               return MEDIACODEC_ERROR_INTERNAL;
-                       }
+               if (ret != MEDIACODEC_ERROR_NONE) {
+                       return __convert_error_code(ret, (char *)__FUNCTION__);
                }
-
-               rm_ret = mm_resource_manager_commit(g_mc_resource_manager);
-               if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-                       mm_resource_manager_mark_for_release(g_mc_resource_manager, resource);
-                       LOGE("Failed to commit resource manager : %x", rm_ret);
-                       return MEDIACODEC_ERROR_INTERNAL;
-               }
-               handle->codec_resource = resource;
 //LCOV_EXCL_STOP
        }
 #endif
 
-       int ret = mc_prepare(handle->mc_handle);
+       ret = mc_prepare(handle->mc_handle);
 
        if (ret != MEDIACODEC_ERROR_NONE) {
                return __convert_error_code(ret, (char *)__FUNCTION__);
@@ -385,40 +331,28 @@ int mediacodec_unprepare(mediacodec_h mediacodec)
 {
        MEDIACODEC_INSTANCE_CHECK(mediacodec);
        mediacodec_s *handle = (mediacodec_s *)mediacodec;
-#ifdef USE_MM_RESOURCE_MANAGER
-       int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
-#endif
+       mc_handle_t *mc_handle = handle->mc_handle;
+
+       MEDIACODEC_INSTANCE_CHECK(mc_handle);
 
        int ret = mc_unprepare(handle->mc_handle);
 
        if (ret != MEDIACODEC_ERROR_NONE) {
                return __convert_error_code(ret, (char *)__FUNCTION__);
-       } else {
-#ifdef USE_MM_RESOURCE_MANAGER
-               if (handle->codec_resource != NULL) {
+       }
+
+#ifdef RM_COMMON
 //LCOV_EXCL_START
-                       mm_resource_manager_mark_for_release(g_mc_resource_manager,
-                                       handle->codec_resource);
-                       handle->codec_resource = NULL;
-                       rm_ret = mm_resource_manager_commit(g_mc_resource_manager);
-                       if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
-                               mm_resource_manager_mark_for_release(g_mc_resource_manager, handle->codec_resource);
-                               switch (rm_ret) {
-                               case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY:
-                                       return MEDIACODEC_ERROR_RESOURCE_OVERLOADED;
-                               default:
-                                       return MEDIACODEC_ERROR_INTERNAL;
-                               }
-                       }
+       ret = mediacodec_resource_deallocate(handle, mc_handle->is_encoder ? RES_TYPE_VIDEO_ENCODER : RES_TYPE_VIDEO_DECODER);
+
+       if (ret != MEDIACODEC_ERROR_NONE) {
+               return __convert_error_code(ret, (char *)__FUNCTION__);
+       }
 //LCOV_EXCL_STOP
-               } else {
-                       LOGD("No codec resource to release. Probably resource release cb called\n");
-               }
 #endif
 
-               handle->state = MEDIACODEC_STATE_IDLE;
-               return MEDIACODEC_ERROR_NONE;
-       }
+       handle->state = MEDIACODEC_STATE_IDLE;
+       return MEDIACODEC_ERROR_NONE;
 }
 
 int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint64_t timeOutUs)
@@ -661,7 +595,7 @@ static gboolean  __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data
        return 1;
 }
 
-static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data)
+gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data)
 {
        if (user_data == NULL)
                return 0;
@@ -699,60 +633,3 @@ static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *
 
        return 1;
 }
-
-#ifdef USE_MM_RESOURCE_MANAGER
-//LCOV_EXCL_START
-static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
-               mm_resource_manager_res_h resource_h, void *user_data)
-{
-       int i;
-       mediacodec_s *handle;
-
-       g_mutex_lock(&g_mediacodec_lock);
-       for (i = 0; i < g_mediacodec_handles->len; i++) {
-               handle = g_ptr_array_index(g_mediacodec_handles, i);
-               if (handle->codec_resource == resource_h) {
-                       /*
-                        * TODO
-                        * The resource release cb is asynchronous, so mediacodec_unprepare might be
-                        * called in this thread and in the main thread at the same time.
-                        * Mutex lock/unlock should be added in the body of mediacodec_unprepare() to
-                        * avoid the race condition.
-                        */
-                       handle->codec_resource = NULL;
-                       mediacodec_unprepare((mediacodec_h)handle);
-                       __mediacodec_error_cb(MEDIACODEC_ERROR_RESOURCE_CONFLICT, handle);
-                       break;
-               }
-       }
-       g_mutex_unlock(&g_mediacodec_lock);
-
-       return FALSE;
-}
-//LCOV_EXCL_STOP
-
-
-static void __mediacodec_init_lib()
-{
-       LOGD("START");
-
-       g_mutex_init(&g_mediacodec_lock);
-       g_mediacodec_handles = g_ptr_array_sized_new(MC_PREALLOCATED_HANDLE_ARRAY_SIZE);
-
-       LOGD("DONE");
-}
-
-static void __mediacodec_deinit_lib()
-{
-       LOGD("START");
-
-       if (g_mc_resource_manager != NULL)
-               mm_resource_manager_destroy(g_mc_resource_manager);
-
-       g_ptr_array_unref(g_mediacodec_handles);
-       g_mutex_clear(&g_mediacodec_lock);
-
-       LOGD("DONE");
-}
-#endif
-
diff --git a/src/media_codec_rm.c b/src/media_codec_rm.c
new file mode 100644 (file)
index 0000000..f7c8739
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2024 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.
+ */
+
+#ifdef RM_COMMON
+
+#include "media_codec_rm.h"
+#include <dlog.h>
+
+#include <rm_api.h>
+#include <rm_type.h>
+#include <resource_center.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+//LCOV_EXCL_START
+static rm_cb_result
+__mediacodec_resource_release_cb(int handle, rm_callback_type event_src, rm_device_request_s *info, void *cb_data)
+{
+       mediacodec_s *mediacodec = (mediacodec_s *)cb_data;
+       MEDIACODEC_INSTANCE_CHECK(mediacodec);
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&mediacodec->resource.callback_lock);
+
+       LOGI("rm callback info mediacodec_s [%p] handle : %d event_src : %d", mediacodec, handle, event_src);
+
+       switch (event_src) {
+       case RM_CALLBACK_TYPE_RESOURCE_CONFLICT:
+       case RM_CALLBACK_TYPE_RESOURCE_CONFLICT_UD:
+               mediacodec_unprepare((mediacodec_h)mediacodec);
+               __mediacodec_error_cb(MEDIACODEC_ERROR_RESOURCE_CONFLICT, mediacodec);
+               break;
+       default:
+               break;
+       }
+
+       LOGI("RM_CB_RESULT_OK");
+
+       return RM_CB_RESULT_OK;
+}
+//LCOV_EXCL_STOP
+
+static int
+__mediacodec_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;
+
+       MEDIACODEC_NULL_ARG_CHECK(name);
+
+       cmdline = g_strdup_printf("/proc/%d/cmdline", (int)pid);
+
+       if (!g_file_get_contents(cmdline, &contents, NULL, &error)) {
+               LOGE("error : %s", error->message);
+               return MEDIACODEC_ERROR_INVALID_OPERATION;
+       }
+
+       base = g_path_get_basename(contents);
+
+       if (g_strlcpy(name, base, size) >= size) {
+               LOGE("string truncated");
+               return MEDIACODEC_ERROR_INVALID_OPERATION;
+       }
+
+       return MEDIACODEC_ERROR_NONE;
+}
+
+int mediacodec_resource_create(mediacodec_s *mediacodec)
+{
+       MEDIACODEC_INSTANCE_CHECK(mediacodec);
+       int ret = 0;
+
+       g_mutex_init(&mediacodec->resource.control_lock);
+       g_mutex_init(&mediacodec->resource.callback_lock);
+
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&mediacodec->resource.control_lock);
+
+       memset(&mediacodec->resource.rci, 0x00, sizeof(rm_consumer_info));
+
+       mediacodec->resource.rci.app_pid = (int)getpid();
+
+       if (__mediacodec_get_appid_by_pid(mediacodec->resource.rci.app_pid,
+               mediacodec->resource.rci.app_id,
+               sizeof(mediacodec->resource.rci.app_id)) != MEDIACODEC_ERROR_NONE) {
+               LOGE("__mediacodec_get_appid_by_pid is failed");
+               return MEDIACODEC_ERROR_INTERNAL;
+       }
+
+       LOGI("app pid %d app id %s", mediacodec->resource.rci.app_pid, mediacodec->resource.rci.app_id);
+
+       ret = rm_register((rm_resource_cb)__mediacodec_resource_release_cb,
+                                                                                       (void *)mediacodec,
+                                                                                       &(mediacodec->resource.handle),
+                                                                                       (mediacodec->resource.rci.app_id[0] != '\0') ? &mediacodec->resource.rci : NULL);
+       if (ret != RM_OK) {
+               LOGE("rm_register fail %d", ret);
+               return MEDIACODEC_ERROR_INTERNAL;
+       }
+
+       return MEDIACODEC_ERROR_NONE;
+}
+
+int mediacodec_resource_allocate(mediacodec_s *mediacodec, mediacodec_res_type_e type)
+{
+       MEDIACODEC_INSTANCE_CHECK(mediacodec);
+
+       int ret = 0;
+       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 *device;
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&mediacodec->resource.control_lock);
+
+       memset(&request_resources, 0x0, sizeof(rm_category_request_s));
+
+       device = &mediacodec->resource.devices[type];
+       memset(device, 0x0, sizeof(rm_device_return_s));
+
+       switch (type) {
+       case RES_TYPE_VIDEO_DECODER:
+               state = RM_STATE_EXCLUSIVE;
+               category_id = RM_CATEGORY_VIDEO_DECODER;
+               break;
+       case RES_TYPE_VIDEO_ENCODER:
+               state = RM_STATE_EXCLUSIVE;
+               category_id = RM_CATEGORY_VIDEO_ENCODER;
+               break;
+       default:
+               LOGE("category id can't set");
+               return MEDIACODEC_ERROR_INTERNAL;
+       }
+
+       category_option = rc_get_capable_category_id(mediacodec->resource.handle, mediacodec->resource.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;
+       LOGI("state %d category id 0x%x category option %d", state, category_id, category_option);
+
+       ret = rm_allocate_resources(mediacodec->resource.handle, &request_resources, device);
+       if (ret != RM_OK) {
+               LOGW("Resource allocation request failed ret %d [error type %d]", ret, device->error_type);
+               return MEDIACODEC_ERROR_INTERNAL;
+       }
+
+       for (idx = 0; idx < device->allocated_num; idx++) {
+               LOGI("#%d / %d [%p] device %d %s %s", idx, device->allocated_num, device,
+                       device->device_id[idx], device->device_node[idx],
+                       device->device_name[idx]);
+       }
+
+       return MEDIACODEC_ERROR_NONE;
+}
+
+int mediacodec_resource_deallocate(mediacodec_s *mediacodec, mediacodec_res_type_e type)
+{
+       MEDIACODEC_INSTANCE_CHECK(mediacodec);
+
+       int rm_ret = RM_OK;
+       int idx = 0;
+       rm_device_request_s requested;
+       rm_device_return_s *r_devices;
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&mediacodec->resource.control_lock);
+
+       LOGI("app id : %s type %d", mediacodec->resource.rci.app_id, type);
+
+       if (mediacodec->resource.handle == 0) {
+               LOGE("Resource handle is not initialized");
+               return MEDIACODEC_ERROR_INVALID_OPERATION;
+       }
+
+       r_devices = &mediacodec->resource.devices[type];
+
+       LOGI("[%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];
+                       LOGI("[device id %d] [device name %s]", r_devices->device_id[idx], r_devices->device_name[idx]);
+               }
+
+               rm_ret = rm_deallocate_resources(mediacodec->resource.handle, &requested);
+               if (rm_ret != RM_OK) {
+                       LOGE("Resource deallocation request failed [%d] [request num %d]", rm_ret, requested.request_num);
+                       return MEDIACODEC_ERROR_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;
+               }
+       }
+
+       return MEDIACODEC_ERROR_NONE;
+}
+
+
+int mediacodec_resource_release(mediacodec_s *mediacodec)
+{
+       MEDIACODEC_INSTANCE_CHECK(mediacodec);
+       int ret = 0;
+       g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&mediacodec->resource.control_lock);
+
+       ret = rm_unregister(mediacodec->resource.handle);
+       if (ret != RM_OK) {
+               LOGE("rm_unregister fail %d", ret);
+               return MEDIACODEC_ERROR_INTERNAL;
+       }
+
+       g_clear_pointer (&locker, g_mutex_locker_free);
+
+       g_mutex_clear(&mediacodec->resource.control_lock);
+       g_mutex_clear(&mediacodec->resource.callback_lock);
+
+       return MEDIACODEC_ERROR_NONE;
+}
+#endif