From 80b780056e12ca1f808de69c0931832bca96d126 Mon Sep 17 00:00:00 2001 From: Jiyong Min Date: Mon, 2 Jan 2017 17:06:56 +0900 Subject: [PATCH] Optimize encoding/decoding image asynchrously - Optimize encoding/decoding thread because of unneccessary waiting It make performance slow - Encode animated gif refactoring Change-Id: I140d65231a6501b18b69cf7b5e36c6f7e7e5b054 Signed-off-by: jiyong.min --- decode-test/image_util_decode_encode_testsuite.c | 69 ++++++++++---- include/mobile/image_util_private.h | 7 +- include/wearable/image_util_private.h | 6 +- packaging/capi-media-image-util.spec | 2 +- src/image_util.c | 115 +++++++---------------- 5 files changed, 89 insertions(+), 110 deletions(-) diff --git a/decode-test/image_util_decode_encode_testsuite.c b/decode-test/image_util_decode_encode_testsuite.c index 105853d..e1da546 100755 --- a/decode-test/image_util_decode_encode_testsuite.c +++ b/decode-test/image_util_decode_encode_testsuite.c @@ -166,7 +166,6 @@ int main(int argc, char *argv[]) image_util_encode_h encoded = NULL; void *src = NULL; unsigned char *data = NULL; - unsigned char *animated_data = NULL; unsigned char *dst = NULL; unsigned long long src_size = 0; int encode_image_type = -1; @@ -179,9 +178,6 @@ int main(int argc, char *argv[]) return 0; } - if (argv[3]) - encode_image_type = atoi(argv[3]); - if (!strcmp("encode-gif", argv[1]) || !strcmp("encode-gif-mem", argv[1])) { struct dirent *dp; DIR *fd; @@ -190,6 +186,7 @@ int main(int argc, char *argv[]) 0,}, temp[BUFFER_SIZE] = {0,}, file_format[BUFFER_SIZE] = {0,}; unsigned long gif_image_width[1000] = { 0, }, gif_image_height[1000] = { 0,}; + unsigned char *animated_data[1000] = {NULL, }; memset(gif_filename, 0, BUFFER_SIZE); { snprintf(gif_filename, BUFFER_SIZE, "%s%s", DECODE_RESULT_PATH, "gif"); @@ -240,38 +237,72 @@ int main(int argc, char *argv[]) snprintf(temp, BUFFER_SIZE, "%s%s-%d%s", argv[2], temp_filename, i, file_format); ret = image_util_decode_set_input_path(decoded, temp); - if (ret != IMAGE_UTIL_ERROR_NONE) + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } return 0; + } - ret = image_util_decode_set_output_buffer(decoded, &animated_data); - if (ret != IMAGE_UTIL_ERROR_NONE) + ret = image_util_decode_set_output_buffer(decoded, &animated_data[i]); + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } return 0; + } ret = image_util_decode_run(decoded, &gif_image_width[i], &gif_image_height[i], NULL); - if (ret != IMAGE_UTIL_ERROR_NONE) + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } return 0; + } ret = image_util_decode_destroy(decoded); - if (ret != IMAGE_UTIL_ERROR_NONE) + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } return 0; + } - ret = image_util_encode_set_input_buffer(encoded, animated_data); - if (ret != IMAGE_UTIL_ERROR_NONE) + ret = image_util_encode_set_input_buffer(encoded, animated_data[i]); + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } return 0; + } ret = image_util_encode_set_resolution(encoded, gif_image_width[i], gif_image_height[i]); - if (ret != IMAGE_UTIL_ERROR_NONE) + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } return 0; + } ret = image_util_encode_set_gif_frame_delay_time(encoded, 10); - if (ret != IMAGE_UTIL_ERROR_NONE) + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } return 0; + } + } - ret = image_util_encode_run(encoded, &image_size); - if (ret != IMAGE_UTIL_ERROR_NONE) - return 0; + ret = image_util_encode_run(encoded, &image_size); + if (ret != IMAGE_UTIL_ERROR_NONE) { + for (i = 0; i < number_files; i++) { + free(animated_data[i]); + } + return 0; + } - free(animated_data); + for (i = 0; i < number_files; i++) { + free(animated_data[i]); } ret = image_util_encode_destroy(encoded); @@ -290,6 +321,10 @@ int main(int argc, char *argv[]) fprintf(stderr, "\t\t1. decode/encode : capi-media-image-util-decode-test decode/decode-mem/decode-async filepath encode_image_type\n"); return 0; } + + if (argv[3]) + encode_image_type = atoi(argv[3]); + ret = image_util_decode_create(&decoded); if (ret != IMAGE_UTIL_ERROR_NONE) return 0; diff --git a/include/mobile/image_util_private.h b/include/mobile/image_util_private.h index a339aa7..eef9732 100755 --- a/include/mobile/image_util_private.h +++ b/include/mobile/image_util_private.h @@ -129,12 +129,9 @@ typedef struct { decode_cb_s *_decode_cb; encode_cb_s *_encode_cb; - /* for multi instance */ - GCond thread_cond; - GMutex thread_mutex; + /* for async */ GThread *thread; - - bool is_finish; + GAsyncQueue *async_queue; } decode_encode_s; /** diff --git a/include/wearable/image_util_private.h b/include/wearable/image_util_private.h index a339aa7..068bca9 100755 --- a/include/wearable/image_util_private.h +++ b/include/wearable/image_util_private.h @@ -129,12 +129,8 @@ typedef struct { decode_cb_s *_decode_cb; encode_cb_s *_encode_cb; - /* for multi instance */ - GCond thread_cond; - GMutex thread_mutex; + /* for async */ GThread *thread; - - bool is_finish; } decode_encode_s; /** diff --git a/packaging/capi-media-image-util.spec b/packaging/capi-media-image-util.spec index f785108..fed7ce4 100755 --- a/packaging/capi-media-image-util.spec +++ b/packaging/capi-media-image-util.spec @@ -1,6 +1,6 @@ Name: capi-media-image-util Summary: A Image Utility library in Tizen Native API -Version: 0.1.14 +Version: 0.1.15 Release: 2 Group: Multimedia/API License: Apache-2.0 diff --git a/src/image_util.c b/src/image_util.c index 940fe02..6fec0aa 100755 --- a/src/image_util.c +++ b/src/image_util.c @@ -1353,37 +1353,21 @@ gpointer _image_util_decode_thread(gpointer data) { decode_encode_s *_handle = (decode_encode_s *) data; int err = MM_UTIL_ERROR_NONE; - gint64 end_time = 0; if (!_handle) { image_util_error("[ERROR] - handle"); return NULL; } - while (!_handle->is_finish) { - end_time = g_get_monotonic_time() + 1 * G_TIME_SPAN_SECOND; - image_util_debug("waiting..."); - g_mutex_lock(&(_handle->thread_mutex)); - g_cond_wait_until(&(_handle->thread_cond), &(_handle->thread_mutex), end_time); - image_util_debug("<=== get run decode thread signal"); - g_mutex_unlock(&(_handle->thread_mutex)); - - if (_handle->is_finish) { - image_util_debug("exit loop"); - break; - } - - err = _image_util_decode_internal(_handle); - if (err == MM_UTIL_ERROR_NONE) - image_util_debug("Success - decode_internal"); - else - image_util_error("Error - decode_internal"); + err = _image_util_decode_internal(_handle); + if (err == MM_UTIL_ERROR_NONE) + image_util_debug("Success - decode_internal"); + else + image_util_error("Error - decode_internal"); - if (_handle->_decode_cb) { - image_util_debug("completed_cb"); - _handle->is_finish = TRUE; - _handle->_decode_cb->image_decode_completed_cb(_convert_image_util_error_code(__func__, err), _handle->_decode_cb->user_data, _handle->width, _handle->height, _handle->dst_size); - } + if (_handle->_decode_cb) { + image_util_debug("completed_cb"); + _handle->_decode_cb->image_decode_completed_cb(_convert_image_util_error_code(__func__, err), _handle->_decode_cb->user_data, _handle->width, _handle->height, _handle->dst_size); } image_util_debug("exit thread"); @@ -1396,18 +1380,12 @@ static int _image_util_decode_create_thread(decode_encode_s * handle) int err = MM_UTIL_ERROR_NONE; image_util_retvm_if((handle == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle"); - - g_mutex_init(&(handle->thread_mutex)); - - g_cond_init(&(handle->thread_cond)); + image_util_retvm_if((handle->thread != NULL), MM_UTIL_ERROR_INVALID_OPERATION, "A thread is alread running"); /*create threads */ handle->thread = g_thread_new("decode_thread", (GThreadFunc) _image_util_decode_thread, (gpointer) handle); if (!handle->thread) { image_util_error("ERROR - create thread"); - g_mutex_clear(&(handle->thread_mutex)); - - g_cond_clear(&(handle->thread_cond)); return MM_UTIL_ERROR_INVALID_OPERATION; } @@ -1428,11 +1406,13 @@ int image_util_decode_run_async(image_util_decode_h handle, image_util_decode_co return IMAGE_UTIL_ERROR_INVALID_PARAMETER; } image_util_retvm_if((completed_cb == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid callback"); + image_util_retvm_if((_handle->thread != NULL), MM_UTIL_ERROR_INVALID_OPERATION, "A thread is alread running"); if (_handle->_decode_cb != NULL) { IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb); _handle->_decode_cb = NULL; } + _handle->_decode_cb = (decode_cb_s *) calloc(1, sizeof(decode_cb_s)); image_util_retvm_if((_handle->_decode_cb == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "Out of memory"); @@ -1440,6 +1420,10 @@ int image_util_decode_run_async(image_util_decode_h handle, image_util_decode_co _handle->_decode_cb->image_decode_completed_cb = completed_cb; err = _image_util_decode_create_thread(_handle); + if (err != MM_UTIL_ERROR_NONE) { + IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb); + _handle->_decode_cb = NULL; + } return _convert_image_util_error_code(__func__, err); } @@ -1511,17 +1495,8 @@ int image_util_decode_destroy(image_util_decode_h handle) /* g_thread_exit(handle->thread); */ if (_handle->thread) { - _handle->is_finish = TRUE; - g_mutex_lock(&(_handle->thread_mutex)); - g_cond_signal(&(_handle->thread_cond)); - image_util_debug("===> send signal(finish) to decode_thread"); - g_mutex_unlock(&(_handle->thread_mutex)); - g_thread_join(_handle->thread); - - g_mutex_clear(&(_handle->thread_mutex)); - - g_cond_clear(&(_handle->thread_cond)); + IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb); } IMAGE_UTIL_SAFE_FREE(_handle->src_buffer); IMAGE_UTIL_SAFE_FREE(_handle); @@ -2130,39 +2105,25 @@ gpointer _image_util_encode_thread(gpointer data) { decode_encode_s *_handle = (decode_encode_s *) data; int err = MM_UTIL_ERROR_NONE; - gint64 end_time = 0; if (!_handle) { image_util_error("[ERROR] - handle"); return NULL; } - while (!_handle->is_finish) { - end_time = g_get_monotonic_time() + 1 * G_TIME_SPAN_SECOND; - image_util_debug("waiting..."); - g_mutex_lock(&(_handle->thread_mutex)); - g_cond_wait_until(&(_handle->thread_cond), &(_handle->thread_mutex), end_time); - image_util_debug("<=== get run encode thread signal"); - g_mutex_unlock(&(_handle->thread_mutex)); - - if (_handle->is_finish) { - image_util_debug("exit loop"); - break; - } - - err = _image_util_encode_internal(_handle); - if (err == MM_UTIL_ERROR_NONE) - image_util_debug("Success - encode_internal"); - else - image_util_error("Error - encode_internal"); + err = _image_util_encode_internal(_handle); + if (err == MM_UTIL_ERROR_NONE) + image_util_debug("Success - encode_internal"); + else + image_util_error("Error - encode_internal"); - if (_handle->_encode_cb) { - image_util_debug("completed_cb"); - _handle->is_finish = TRUE; - _handle->_encode_cb->image_encode_completed_cb(_convert_image_util_error_code(__func__, err), _handle->_encode_cb->user_data, _handle->dst_size); - } + if (_handle->_encode_cb) { + image_util_debug("completed_cb"); + _handle->_encode_cb->image_encode_completed_cb(_convert_image_util_error_code(__func__, err), _handle->_encode_cb->user_data, _handle->dst_size); } + IMAGE_UTIL_SAFE_FREE(_handle->_encode_cb); + _handle->thread = NULL; image_util_debug("exit thread"); return NULL; @@ -2173,18 +2134,13 @@ static int _image_util_encode_create_thread(decode_encode_s * handle) int ret = MM_UTIL_ERROR_NONE; image_util_retvm_if((handle == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle"); - - g_mutex_init(&(handle->thread_mutex)); - - g_cond_init(&(handle->thread_cond)); + image_util_retvm_if((handle->thread != NULL), MM_UTIL_ERROR_INVALID_OPERATION, "The thread is alread running"); /*create threads */ handle->thread = g_thread_new("encode_thread", (GThreadFunc) _image_util_encode_thread, (gpointer) handle); if (!handle->thread) { image_util_error("ERROR - create thread"); - g_mutex_clear(&(handle->thread_mutex)); - g_cond_clear(&(handle->thread_cond)); return MM_UTIL_ERROR_INVALID_OPERATION; } @@ -2205,8 +2161,8 @@ int image_util_encode_run_async(image_util_encode_h handle, image_util_encode_co return IMAGE_UTIL_ERROR_INVALID_PARAMETER; } image_util_retvm_if((_image_util_check_resolution(_handle->width, _handle->height) == false), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid resolution"); - image_util_retvm_if((completed_cb == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid callback"); + image_util_retvm_if((_handle->thread != NULL), MM_UTIL_ERROR_INVALID_OPERATION, "The thread is alread running"); if (_handle->_encode_cb != NULL) { IMAGE_UTIL_SAFE_FREE(_handle->_encode_cb); @@ -2219,6 +2175,10 @@ int image_util_encode_run_async(image_util_encode_h handle, image_util_encode_co _handle->_encode_cb->image_encode_completed_cb = completed_cb; err = _image_util_encode_create_thread(_handle); + if (err != MM_UTIL_ERROR_NONE) { + IMAGE_UTIL_SAFE_FREE(_handle->_encode_cb); + _handle->_encode_cb = NULL; + } return _convert_image_util_error_code(__func__, err); } @@ -2297,17 +2257,8 @@ int image_util_encode_destroy(image_util_encode_h handle) /* g_thread_exit(handle->thread); */ if (_handle->thread) { - _handle->is_finish = TRUE; - g_mutex_lock(&(_handle->thread_mutex)); - g_cond_signal(&(_handle->thread_cond)); - image_util_debug("===> send signal(finish) to decode_thread"); - g_mutex_unlock(&(_handle->thread_mutex)); - g_thread_join(_handle->thread); - - g_mutex_clear(&(_handle->thread_mutex)); - - g_cond_clear(&(_handle->thread_cond)); + IMAGE_UTIL_SAFE_FREE(_handle->_encode_cb); } IMAGE_UTIL_SAFE_FREE(_handle->src_buffer); -- 2.7.4