8c0ed706d54b194bd37d5af3b27dbcd4a3eb73f9
[platform/core/pim/contacts-service.git] / common / ctsvc_image_util.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include "ctsvc_internal.h"
21 #include "ctsvc_image_util.h"
22
23 struct image_transform {
24         int ret;
25         uint64_t size;
26         void *buffer;
27         GCond cond;
28         GMutex mutex;
29 };
30
31 int ctsvc_image_util_get_mimetype(image_util_colorspace_e colorspace,
32                 int *p_mimetype)
33 {
34         RETV_IF(NULL == p_mimetype, CONTACTS_ERROR_INVALID_PARAMETER);
35
36         media_format_mimetype_e mimetype;
37         switch (colorspace) {
38         case IMAGE_UTIL_COLORSPACE_YUV422:
39                 mimetype = MEDIA_FORMAT_422P;
40                 break;
41         case IMAGE_UTIL_COLORSPACE_NV12:
42                 mimetype = MEDIA_FORMAT_NV12;
43                 break;
44         case IMAGE_UTIL_COLORSPACE_UYVY:
45                 mimetype = MEDIA_FORMAT_UYVY;
46                 break;
47         case IMAGE_UTIL_COLORSPACE_YUYV:
48                 mimetype = MEDIA_FORMAT_YUYV;
49                 break;
50         case IMAGE_UTIL_COLORSPACE_RGB565:
51                 mimetype = MEDIA_FORMAT_RGB565;
52                 break;
53         case IMAGE_UTIL_COLORSPACE_RGB888:
54                 mimetype = MEDIA_FORMAT_RGB888;
55                 break;
56         case IMAGE_UTIL_COLORSPACE_ARGB8888:
57                 mimetype = MEDIA_FORMAT_ARGB;
58                 break;
59         case IMAGE_UTIL_COLORSPACE_RGBA8888:
60                 mimetype = MEDIA_FORMAT_RGBA;
61                 break;
62         case IMAGE_UTIL_COLORSPACE_NV21:
63                 mimetype = MEDIA_FORMAT_NV21;
64                 break;
65         case IMAGE_UTIL_COLORSPACE_NV16:
66                 mimetype = MEDIA_FORMAT_NV16;
67                 break;
68         case IMAGE_UTIL_COLORSPACE_BGRA8888: /* not supported */
69         case IMAGE_UTIL_COLORSPACE_BGRX8888: /* not supported */
70         case IMAGE_UTIL_COLORSPACE_NV61: /* not supported */
71         case IMAGE_UTIL_COLORSPACE_YV12: /* not supported */
72         case IMAGE_UTIL_COLORSPACE_I420: /* not supported */
73         default:
74                 /* LCOV_EXCL_START */
75                 ERR("Not supported %d", colorspace);
76                 return CONTACTS_ERROR_INVALID_PARAMETER;
77                 /* LCOV_EXCL_STOP */
78         }
79         *p_mimetype = mimetype;
80         return CONTACTS_ERROR_NONE;
81 }
82
83 media_format_h ctsvc_image_util_create_media_format(int mimetype, int width,
84                 int height)
85 {
86         int ret;
87         media_format_h fmt = NULL;
88
89         ret = media_format_create(&fmt);
90         if (MEDIA_FORMAT_ERROR_NONE != ret) {
91                 /* LCOV_EXCL_START */
92                 ERR("media_format_create() Fail(%d)", ret);
93                 return NULL;
94                 /* LCOV_EXCL_STOP */
95         }
96
97         ret = media_format_set_video_mime(fmt, mimetype);
98         if (MEDIA_FORMAT_ERROR_NONE != ret) {
99                 /* LCOV_EXCL_START */
100                 ERR("media_format_set_video_mime() Fail(%d)", ret);
101                 media_format_unref(fmt);
102                 return NULL;
103                 /* LCOV_EXCL_STOP */
104         }
105
106         ret = media_format_set_video_width(fmt, width);
107         if (MEDIA_FORMAT_ERROR_NONE != ret) {
108                 /* LCOV_EXCL_START */
109                 ERR("media_format_set_video_width() Fail(%d)", ret);
110                 media_format_unref(fmt);
111                 return NULL;
112                 /* LCOV_EXCL_STOP */
113         }
114
115         ret = media_format_set_video_height(fmt, height);
116         if (MEDIA_FORMAT_ERROR_NONE != ret) {
117                 /* LCOV_EXCL_START */
118                 ERR("media_format_set_video_height() Fail(%d)", ret);
119                 media_format_unref(fmt);
120                 return NULL;
121                 /* LCOV_EXCL_STOP */
122         }
123
124         ret = media_format_set_video_avg_bps(fmt, 2000000); /* image_util guide */
125         if (MEDIA_FORMAT_ERROR_NONE != ret) {
126                 /* LCOV_EXCL_START */
127                 ERR("media_format_set_video_avg_bps() Fail(%d)", ret);
128                 media_format_unref(fmt);
129                 return NULL;
130                 /* LCOV_EXCL_STOP */
131         }
132
133         ret = media_format_set_video_max_bps(fmt, 15000000); /* image_util guide */
134         if (MEDIA_FORMAT_ERROR_NONE != ret) {
135                 /* LCOV_EXCL_START */
136                 ERR("media_format_set_video_max_bps() Fail(%d)", ret);
137                 media_format_unref(fmt);
138                 return NULL;
139                 /* LCOV_EXCL_STOP */
140         }
141
142         return fmt;
143 }
144
145 int _ctsvc_image_packet_create_alloc_finalize_cb(media_packet_h packet,
146                 int error_code, void *user_data)
147 {
148         return MEDIA_PACKET_FINALIZE;
149 }
150
151 media_packet_h ctsvc_image_util_create_media_packet(media_format_h fmt,
152                 void *buffer, unsigned int buffer_size)
153 {
154         int ret;
155         void *mp_buffer = NULL;
156         media_packet_h packet = NULL;
157         uint64_t mp_buffer_size = 0;
158
159         RETV_IF(NULL == fmt, NULL);
160         RETV_IF(NULL == buffer, NULL);
161
162         ret = media_packet_create_alloc(fmt, _ctsvc_image_packet_create_alloc_finalize_cb,
163                         NULL, &packet);
164         if (MEDIA_PACKET_ERROR_NONE != ret) {
165                 /* LCOV_EXCL_START */
166                 ERR("media_packet_create_alloc() Fail(%d)", ret);
167                 return NULL;
168                 /* LCOV_EXCL_STOP */
169         }
170
171         ret = media_packet_get_buffer_size(packet, &mp_buffer_size);
172         if (MEDIA_PACKET_ERROR_NONE != ret) {
173                 /* LCOV_EXCL_START */
174                 ERR("media_packet_get_buffer_size() Fail(%d)", ret);
175                 media_packet_destroy(packet);
176                 return NULL;
177                 /* LCOV_EXCL_STOP */
178         }
179
180         ret = media_packet_get_buffer_data_ptr(packet, &mp_buffer);
181         if (MEDIA_PACKET_ERROR_NONE != ret) {
182                 /* LCOV_EXCL_START */
183                 ERR("media_packet_get_buffer_data_ptr() Fail(%d)", ret);
184                 media_packet_destroy(packet);
185                 return NULL;
186                 /* LCOV_EXCL_STOP */
187         }
188
189         if (mp_buffer)
190                 memcpy(mp_buffer, buffer, (int)((buffer_size < mp_buffer_size) ? buffer_size : mp_buffer_size));
191
192         return packet;
193 }
194
195
196 static void _image_transform_completed_cb(media_packet_h *dst,
197                 image_util_error_e error, void *user_data)
198 {
199         int ret;
200         uint64_t size = 0;
201         void *buffer = 0;
202         struct image_transform *info = user_data;
203
204         if (NULL == info) {
205                 ERR("NULL == info");
206                 media_packet_destroy(*dst);
207                 return;
208         }
209
210         if (IMAGE_UTIL_ERROR_NONE == error) {
211                 ret = media_packet_get_buffer_size(*dst, &size);
212                 if (MEDIA_PACKET_ERROR_NONE != ret) {
213                         /* LCOV_EXCL_START */
214                         ERR("media_packet_get_buffer_size() Fail(%d)", ret);
215                         info->ret = CONTACTS_ERROR_SYSTEM;
216                         media_packet_destroy(*dst);
217                         g_mutex_lock(&info->mutex);
218                         g_cond_signal(&info->cond);
219                         g_mutex_unlock(&info->mutex);
220                         return;
221                         /* LCOV_EXCL_STOP */
222                 }
223
224                 ret = media_packet_get_buffer_data_ptr(*dst, &buffer);
225                 if (MEDIA_PACKET_ERROR_NONE != ret) {
226                         /* LCOV_EXCL_START */
227                         ERR("media_packet_get_buffer_data_ptr() Fail(%d)", ret);
228                         info->ret = CONTACTS_ERROR_SYSTEM;
229                         media_packet_destroy(*dst);
230                         g_mutex_lock(&info->mutex);
231                         g_cond_signal(&info->cond);
232                         g_mutex_unlock(&info->mutex);
233                         return;
234                         /* LCOV_EXCL_STOP */
235                 }
236
237                 info->buffer = calloc(1, (size_t)size);
238                 if (NULL == info->buffer) {
239                         /* LCOV_EXCL_START */
240                         ERR("calloc() Fail");
241                         info->ret = CONTACTS_ERROR_SYSTEM;
242                         media_packet_destroy(*dst);
243                         g_mutex_lock(&info->mutex);
244                         g_cond_signal(&info->cond);
245                         g_mutex_unlock(&info->mutex);
246                         return;
247                         /* LCOV_EXCL_STOP */
248                 }
249                 memcpy(info->buffer, buffer, (size_t)size);
250                 info->size = size;
251                 info->ret = CONTACTS_ERROR_NONE;
252         } else {
253                 ERR("transform_run() Fail(%d)", error);
254                 info->ret = CONTACTS_ERROR_SYSTEM;
255         }
256         media_packet_destroy(*dst);
257         g_mutex_lock(&info->mutex);
258         g_cond_signal(&info->cond);
259         g_mutex_unlock(&info->mutex);
260 }
261
262 static int _ctsvc_image_util_transform_run(transformation_h transform,
263                 media_packet_h packet, void **p_buffer, uint64_t *p_size)
264 {
265         int ret;
266         gint64 end_time;
267         struct image_transform *info = NULL;
268
269         RETV_IF(NULL == transform, CONTACTS_ERROR_INVALID_PARAMETER);
270         RETV_IF(NULL == packet, CONTACTS_ERROR_INVALID_PARAMETER);
271
272         info = calloc(1, sizeof(struct image_transform));
273         if (NULL == info) {
274                 /* LCOV_EXCL_START */
275                 ERR("calloc() Fail");
276                 return CONTACTS_ERROR_OUT_OF_MEMORY;
277                 /* LCOV_EXCL_STOP */
278         }
279
280         g_cond_init(&info->cond);
281         g_mutex_init(&info->mutex);
282
283         g_mutex_lock(&info->mutex);
284         ret = image_util_transform_run(transform, packet, _image_transform_completed_cb, info);
285         if (IMAGE_UTIL_ERROR_NONE != ret) {
286                 /* LCOV_EXCL_START */
287                 ERR("image_util_transform_run() Fail(%d)", ret);
288                 g_mutex_unlock(&info->mutex);
289                 g_mutex_clear(&info->mutex);
290                 g_cond_clear(&info->cond);
291                 return CONTACTS_ERROR_SYSTEM;
292                 /* LCOV_EXCL_STOP */
293         }
294
295         end_time = g_get_monotonic_time() + 4000 * G_TIME_SPAN_MILLISECOND;
296         if (!g_cond_wait_until(&info->cond, &info->mutex, end_time)) {
297                 /* timeout has passed */
298                 ERR("g_cond_wait_until() return FALSE");
299                 info->ret = CONTACTS_ERROR_SYSTEM;
300         }
301         g_mutex_unlock(&info->mutex);
302         g_mutex_clear(&info->mutex);
303         g_cond_clear(&info->cond);
304
305         if (CONTACTS_ERROR_NONE != info->ret) {
306                 /* LCOV_EXCL_START */
307                 ERR("image_util_transform_run() Fail(%d)", info->ret);
308                 free(info->buffer);
309                 free(info);
310                 return CONTACTS_ERROR_SYSTEM;
311                 /* LCOV_EXCL_STOP */
312         }
313
314         *p_size = info->size;
315         *p_buffer = info->buffer;
316         free(info);
317         return CONTACTS_ERROR_NONE;
318 }
319
320
321 int ctsvc_image_util_rotate(media_packet_h packet, image_util_rotation_e rotation,
322                 void **p_buffer, uint64_t *p_size)
323 {
324         int ret;
325         transformation_h transform = NULL;
326
327         ret = image_util_transform_create(&transform);
328         if (IMAGE_UTIL_ERROR_NONE != ret) {
329                 /* LCOV_EXCL_START */
330                 ERR("image_util_transform_create() Fail(%d)", ret);
331                 return CONTACTS_ERROR_SYSTEM;
332                 /* LCOV_EXCL_STOP */
333         }
334
335         ret = image_util_transform_set_rotation(transform, rotation);
336         if (IMAGE_UTIL_ERROR_NONE != ret) {
337                 /* LCOV_EXCL_START */
338                 ERR("image_util_transform_set_rotation() Fail(%d)", ret);
339                 image_util_transform_destroy(transform);
340                 return CONTACTS_ERROR_SYSTEM;
341                 /* LCOV_EXCL_STOP */
342         }
343
344         ret = _ctsvc_image_util_transform_run(transform, packet, p_buffer, p_size);
345
346         image_util_transform_destroy(transform);
347         return ret;
348 }
349
350 int ctsvc_image_util_resize(media_packet_h packet, int width, int height,
351                 void **p_buffer, uint64_t *p_size)
352 {
353         int ret;
354         transformation_h transform = NULL;
355
356         ret = image_util_transform_create(&transform);
357         if (IMAGE_UTIL_ERROR_NONE != ret) {
358                 /* LCOV_EXCL_START */
359                 ERR("image_util_transform_create() Fail(%d)", ret);
360                 return CONTACTS_ERROR_SYSTEM;
361                 /* LCOV_EXCL_STOP */
362         }
363
364         ret = image_util_transform_set_resolution(transform, width, height);
365         if (IMAGE_UTIL_ERROR_NONE != ret) {
366                 /* LCOV_EXCL_START */
367                 ERR("image_util_transform_set_resolution() Fail(%d)", ret);
368                 image_util_transform_destroy(transform);
369                 return CONTACTS_ERROR_SYSTEM;
370                 /* LCOV_EXCL_STOP */
371         }
372
373         ret = _ctsvc_image_util_transform_run(transform, packet, p_buffer, p_size);
374
375         image_util_transform_destroy(transform);
376
377         return ret;
378 }
379