#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;
+#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_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);
+#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
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));
} else {
- LOGE("MEDIACODEC_ERROR_OUT_OF_MEMORY(0x%08x)", MEDIACODEC_ERROR_OUT_OF_MEMORY);
+ LOGE("MEDIACODEC_ERROR_OUT_OF_MEMORY(0x%08x)", MEDIACODEC_ERROR_OUT_OF_MEMORY); //LCOV_EXCL_LINE
return MEDIACODEC_ERROR_OUT_OF_MEMORY;
}
ret = mc_create(&handle->mc_handle);
if (ret != MEDIACODEC_ERROR_NONE) {
- LOGE("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
+ LOGE("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION); //LCOV_EXCL_LINE
handle->state = MEDIACODEC_STATE_NONE;
g_free(handle->mc_handle);
g_free(handle);
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);
+#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);
+#endif
+
return MEDIACODEC_ERROR_NONE;
}
int ret = mc_destroy(handle->mc_handle);
if (ret != MEDIACODEC_ERROR_NONE) {
- LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
+ LOGD("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;
}
}
+int mediacodec_configure_from_media_format(mediacodec_h mediacodec, media_format_h format, int flags)
+{
+ MEDIACODEC_INSTANCE_CHECK(mediacodec);
+ mediacodec_s *handle = (mediacodec_s *)mediacodec;
+ MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
+
+ int ret = mc_configure(handle->mc_handle, format, flags);
+
+ if (ret != MEDIACODEC_ERROR_NONE) {
+ return __convert_error_code(ret, (char *)__FUNCTION__);
+ } else {
+ handle->state = MEDIACODEC_STATE_IDLE;
+ return MEDIACODEC_ERROR_NONE;
+ }
+}
+
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
MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
+#ifdef USE_MM_RESOURCE_MANAGER
+ if (mc_handle->is_hw && mc_handle->is_video) {
+
+ if (handle->codec_resource) {
+ LOGE("Codec resource is tried to be acquired twice\n"); //LCOV_EXCL_LINE
+ 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
+ */
+//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;
+ }
+ }
+
+ 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);
if (ret != MEDIACODEC_ERROR_NONE) {
{
MEDIACODEC_INSTANCE_CHECK(mediacodec);
mediacodec_s *handle = (mediacodec_s *)mediacodec;
+#ifdef USE_MM_RESOURCE_MANAGER
+ int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
+#endif
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) {
+//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;
+ }
+ }
+//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;
}
return __convert_error_code(ret, (char *)__FUNCTION__);
else
handle->state = MEDIACODEC_STATE_IDLE;
- return MEDIACODEC_ERROR_NONE;
+
+ return MEDIACODEC_ERROR_NONE;
}
int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_input_buffer_used_cb callback, void *user_data)
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
+