From e89ab99f6380d1419c2fca0443556b436b92a8ab Mon Sep 17 00:00:00 2001 From: Vadym Sachenko Date: Fri, 17 Nov 2017 15:29:03 +0200 Subject: [PATCH] mm-resource-manager integration patch Change-Id: I411252643810ee1e07977d384aadf6b227548cea Signed-off-by: Vadym Sachenko --- CMakeLists.txt | 4 +- include/media_codec_private.h | 2 + packaging/capi-media-codec.spec | 3 +- src/media_codec.c | 126 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52b72df..dc41164 100755 --- 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 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}) diff --git a/include/media_codec_private.h b/include/media_codec_private.h index 6f50a49..c574563 100644 --- a/include/media_codec_private.h +++ b/include/media_codec_private.h @@ -24,6 +24,7 @@ #include #include +#include #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; diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 5437140..9f9ee77 100755 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -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) diff --git a/src/media_codec.c b/src/media_codec.c index 2d8c848..88784ba 100644 --- a/src/media_codec.c +++ b/src/media_codec.c @@ -24,12 +24,22 @@ #include +#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); +} -- 2.7.4