mm-resource-manager integration patch 90/160690/2
authorVadym Sachenko <va.sachenko@partner.samsung.com>
Fri, 17 Nov 2017 13:29:03 +0000 (15:29 +0200)
committerVadym Sachenko <va.sachenko@partner.samsung.com>
Wed, 22 Nov 2017 10:17:06 +0000 (12:17 +0200)
Change-Id: I411252643810ee1e07977d384aadf6b227548cea
Signed-off-by: Vadym Sachenko <va.sachenko@partner.samsung.com>
CMakeLists.txt
include/media_codec_private.h
packaging/capi-media-codec.spec
src/media_codec.c

index 52b72df..dc41164 100755 (executable)
@@ -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 libtbm capi-media-tool iniparser gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 capi-system-info" )
-SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0" )
+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 capi-system-info mm-resource-manager" )
+SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 mm-resource-manager" )
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${dependents})
index 6f50a49..c574563 100644 (file)
@@ -24,6 +24,7 @@
 #include <media_codec.h>
 
 #include <mm_types.h>
+#include <mm_resource_manager.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -101,6 +102,7 @@ typedef struct _mediacodec_s {
        int state;
        bool is_omx;
        char *m_mime;
+       mm_resource_manager_res_h codec_resource;
 
        mediacodec_input_buffer_used_cb empty_buffer_cb;
        void* empty_buffer_cb_userdata;
index 5437140..9f9ee77 100755 (executable)
@@ -4,7 +4,7 @@
 
 Name:       capi-media-codec
 Summary:    A Media Codec library in Tizen Native API
-Version:    0.5.7
+Version:    0.5.8
 Release:    2
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -21,6 +21,7 @@ BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
 BuildRequires:  pkgconfig(gstreamer-app-1.0)
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(iniparser)
+BuildRequires:  pkgconfig(mm-resource-manager)
 #BuildRequires:  pkgconfig(capi-media-camera)
 #BuildRequires:  pkgconfig(capi-mediademuxer)
 #BuildRequires:  pkgconfig(capi-mediamuxer)
index 2d8c848..88784ba 100644 (file)
 
 #include <dlog.h>
 
+#define MC_PREALLOCATED_HANDLE_ARRAY_SIZE 16
+
+static mm_resource_manager_h resource_manager;
+static GPtrArray *mediacodec_handles;
+static GMutex mediacodec_handles_lock;
+
 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_supported_codec_cb(mediacodec_codec_type_e codec_type, void *user_data);
 static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data);
+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);
 
 /*
  * Internal Implementation
@@ -121,6 +131,9 @@ int mediacodec_create(mediacodec_h *mediacodec)
 
        LOGD("mediacodec_create..");
 
+       if (resource_manager == NULL)
+               return MEDIACODEC_ERROR_INTERNAL;
+
        handle = (mediacodec_s *)malloc(sizeof(mediacodec_s));
        if (handle != NULL) {
                memset(handle, 0 , sizeof(mediacodec_s));
@@ -151,6 +164,10 @@ int mediacodec_create(mediacodec_h *mediacodec)
        mc_set_buffer_status_cb(handle->mc_handle, (mediacodec_buffer_status_cb)__mediacodec_buffer_status_cb, handle);
        mc_set_supported_codec_cb(handle->mc_handle, (mediacodec_supported_codec_cb)__mediacodec_supported_codec_cb, handle);
 
+       g_mutex_lock(&mediacodec_handles_lock);
+       g_ptr_array_insert(mediacodec_handles, -1, *mediacodec);
+       g_mutex_unlock(&mediacodec_handles_lock);
+
        return MEDIACODEC_ERROR_NONE;
 
 }
@@ -166,6 +183,10 @@ int mediacodec_destroy(mediacodec_h mediacodec)
                LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
                return MEDIACODEC_ERROR_INVALID_OPERATION;
        } else {
+               g_mutex_lock(&mediacodec_handles_lock);
+               g_ptr_array_remove_fast(mediacodec_handles, mediacodec);
+               g_mutex_unlock(&mediacodec_handles_lock);
+
                handle->state = MEDIACODEC_STATE_NONE;
                free(handle);
                handle = NULL;
@@ -273,8 +294,61 @@ int mediacodec_prepare(mediacodec_h mediacodec)
 {
        MEDIACODEC_INSTANCE_CHECK(mediacodec);
        mediacodec_s *handle = (mediacodec_s *)mediacodec;
+       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;
        MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
 
+       if (mc_handle->is_hw && mc_handle->is_video) {
+
+               if (handle->codec_resource) {
+                       LOGE("Codec resource is tried to be acquired twice\n");
+                       return MC_INTERNAL_ERROR;
+               }
+
+               /*
+                * 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
+                */
+               rm_ret = mm_resource_manager_mark_for_acquire(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)
+                       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;
+                       }
+
+               rm_ret = mm_resource_manager_commit(resource_manager);
+               if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+                       mm_resource_manager_mark_for_release(resource_manager, resource);
+                       switch (rm_ret) {
+                       case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY:
+                               return MEDIACODEC_ERROR_RESOURCE_OVERLOADED;
+                       default:
+                               return MEDIACODEC_ERROR_INTERNAL;
+                       }
+               }
+
+               handle->codec_resource = resource;
+       }
+
        int ret = mc_prepare(handle->mc_handle);
 
        if (ret != MEDIACODEC_ERROR_NONE) {
@@ -295,6 +369,15 @@ int mediacodec_unprepare(mediacodec_h mediacodec)
        if (ret != MEDIACODEC_ERROR_NONE) {
                return __convert_error_code(ret, (char *)__FUNCTION__);
        } else {
+               if (handle->codec_resource != NULL) {
+                       mm_resource_manager_mark_for_release(resource_manager,
+                                       handle->codec_resource);
+                       handle->codec_resource = NULL;
+                       mm_resource_manager_commit(resource_manager);
+               } else {
+                       LOGD("No codec resource to release. Probably resource release cb called\n");
+               }
+
                handle->state = MEDIACODEC_STATE_IDLE;
                return MEDIACODEC_ERROR_NONE;
        }
@@ -597,3 +680,46 @@ static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *
 
        return 1;
 }
+
+
+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(&mediacodec_handles_lock);
+       for (i = 0; i < mediacodec_handles->len; i++) {
+               handle = g_ptr_array_index(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_OVERLOADED, handle);
+                       break;
+               }
+       }
+       g_mutex_unlock(&mediacodec_handles_lock);
+
+       return FALSE;
+}
+
+static void __mediacodec_init_lib()
+{
+       mediacodec_handles = g_ptr_array_sized_new(MC_PREALLOCATED_HANDLE_ARRAY_SIZE);
+       mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
+                       __mediacodec_resource_release_cb, NULL, &resource_manager);
+}
+
+static void __mediacodec_deinit_lib()
+{
+       if (resource_manager != NULL)
+               mm_resource_manager_destroy(resource_manager);
+       g_ptr_array_unref(mediacodec_handles);
+}