Optimize encoding/decoding image asynchrously 89/107989/3
authorJiyong Min <jiyong.min@samsung.com>
Mon, 2 Jan 2017 08:06:56 +0000 (17:06 +0900)
committerJiyong Min <jiyong.min@samsung.com>
Tue, 3 Jan 2017 06:37:33 +0000 (15:37 +0900)
 - Optimize encoding/decoding thread because of unneccessary waiting
  It make performance slow
 - Encode animated gif refactoring

Change-Id: I140d65231a6501b18b69cf7b5e36c6f7e7e5b054
Signed-off-by: jiyong.min <jiyong.min@samsung.com>
decode-test/image_util_decode_encode_testsuite.c
include/mobile/image_util_private.h
include/wearable/image_util_private.h
packaging/capi-media-image-util.spec
src/image_util.c

index 105853d..e1da546 100755 (executable)
@@ -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;
index a339aa7..eef9732 100755 (executable)
@@ -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;
 
 /**
index a339aa7..068bca9 100755 (executable)
@@ -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;
 
 /**
index f785108..fed7ce4 100755 (executable)
@@ -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
index 940fe02..6fec0aa 100755 (executable)
@@ -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);