heap use after free fix
[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                 /* LCOV_EXCL_START */
254                 ERR("transform_run() Fail(%d)", error);
255                 info->ret = CONTACTS_ERROR_SYSTEM;
256                 /* LCOV_EXCL_STOP */
257         }
258         media_packet_destroy(*dst);
259         g_mutex_lock(&info->mutex);
260         g_cond_signal(&info->cond);
261         g_mutex_unlock(&info->mutex);
262 }
263
264 static int _ctsvc_image_util_transform_run(transformation_h transform,
265                 media_packet_h packet, void **p_buffer, uint64_t *p_size)
266 {
267         int ret;
268         gint64 end_time;
269         struct image_transform *info = NULL;
270
271         RETV_IF(NULL == transform, CONTACTS_ERROR_INVALID_PARAMETER);
272         RETV_IF(NULL == packet, CONTACTS_ERROR_INVALID_PARAMETER);
273
274         info = calloc(1, sizeof(struct image_transform));
275         if (NULL == info) {
276                 /* LCOV_EXCL_START */
277                 ERR("calloc() Fail");
278                 return CONTACTS_ERROR_OUT_OF_MEMORY;
279                 /* LCOV_EXCL_STOP */
280         }
281
282         g_cond_init(&info->cond);
283         g_mutex_init(&info->mutex);
284
285         g_mutex_lock(&info->mutex);
286         ret = image_util_transform_run(transform, packet, _image_transform_completed_cb, info);
287         if (IMAGE_UTIL_ERROR_NONE != ret) {
288                 /* LCOV_EXCL_START */
289                 ERR("image_util_transform_run() Fail(%d)", ret);
290                 g_mutex_unlock(&info->mutex);
291                 g_mutex_clear(&info->mutex);
292                 g_cond_clear(&info->cond);
293                 free(info);
294                 return CONTACTS_ERROR_SYSTEM;
295                 /* LCOV_EXCL_STOP */
296         }
297
298         end_time = g_get_monotonic_time() + 2000 * G_TIME_SPAN_MILLISECOND;
299         if (!g_cond_wait_until(&info->cond, &info->mutex, end_time)) {
300                 /* timeout has passed */
301                 /* LCOV_EXCL_START */
302                 ERR("g_cond_wait_until() return FALSE");
303                 g_mutex_unlock(&info->mutex);
304                 g_mutex_clear(&info->mutex);
305                 g_cond_clear(&info->cond);
306                 free(info);
307                 return CONTACTS_ERROR_SYSTEM;
308                 /* LCOV_EXCL_STOP */
309         }
310         g_mutex_unlock(&info->mutex);
311         g_mutex_clear(&info->mutex);
312         g_cond_clear(&info->cond);
313
314         if (!info && CONTACTS_ERROR_NONE != info->ret) {
315                 /* LCOV_EXCL_START */
316                 ERR("image_util_transform_run() Fail(%d)", info->ret);
317                 free(info->buffer);
318                 free(info);
319                 return CONTACTS_ERROR_SYSTEM;
320                 /* LCOV_EXCL_STOP */
321         }
322
323         *p_size = info->size;
324         *p_buffer = info->buffer;
325         free(info);
326         return CONTACTS_ERROR_NONE;
327 }
328
329
330 int ctsvc_image_util_rotate(media_packet_h packet, image_util_rotation_e rotation,
331                 void **p_buffer, uint64_t *p_size)
332 {
333         int ret;
334         transformation_h transform = NULL;
335
336         ret = image_util_transform_create(&transform);
337         if (IMAGE_UTIL_ERROR_NONE != ret) {
338                 /* LCOV_EXCL_START */
339                 ERR("image_util_transform_create() Fail(%d)", ret);
340                 return CONTACTS_ERROR_SYSTEM;
341                 /* LCOV_EXCL_STOP */
342         }
343
344         ret = image_util_transform_set_rotation(transform, rotation);
345         if (IMAGE_UTIL_ERROR_NONE != ret) {
346                 /* LCOV_EXCL_START */
347                 ERR("image_util_transform_set_rotation() Fail(%d)", ret);
348                 image_util_transform_destroy(transform);
349                 return CONTACTS_ERROR_SYSTEM;
350                 /* LCOV_EXCL_STOP */
351         }
352
353         ret = _ctsvc_image_util_transform_run(transform, packet, p_buffer, p_size);
354
355         image_util_transform_destroy(transform);
356         return ret;
357 }
358
359 int ctsvc_image_util_resize(media_packet_h packet, int width, int height,
360                 void **p_buffer, uint64_t *p_size)
361 {
362         int ret;
363         transformation_h transform = NULL;
364
365         ret = image_util_transform_create(&transform);
366         if (IMAGE_UTIL_ERROR_NONE != ret) {
367                 /* LCOV_EXCL_START */
368                 ERR("image_util_transform_create() Fail(%d)", ret);
369                 return CONTACTS_ERROR_SYSTEM;
370                 /* LCOV_EXCL_STOP */
371         }
372
373         ret = image_util_transform_set_resolution(transform, width, height);
374         if (IMAGE_UTIL_ERROR_NONE != ret) {
375                 /* LCOV_EXCL_START */
376                 ERR("image_util_transform_set_resolution() Fail(%d)", ret);
377                 image_util_transform_destroy(transform);
378                 return CONTACTS_ERROR_SYSTEM;
379                 /* LCOV_EXCL_STOP */
380         }
381
382         ret = _ctsvc_image_util_transform_run(transform, packet, p_buffer, p_size);
383
384         image_util_transform_destroy(transform);
385
386         return ret;
387 }
388