Remove unused macro
[platform/core/multimedia/libmm-imgp-gstcs.git] / gstcs / mm_util_gstcs.c
1 /*
2  * libmm-imgp-gstcs
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 #include <stdbool.h>
22 #include "mm_util_gstcs_internal.h"
23 #include <gst/check/gstcheck.h>
24 #include <gst/video/video-format.h>
25
26 #define MM_UTIL_ROUND_UP_2(num) (((num)+1)&~1)
27 #define MM_UTIL_ROUND_UP_4(num) (((num)+3)&~3)
28 #define MM_UTIL_ROUND_UP_8(num) (((num)+7)&~7)
29
30
31
32 static GstFlowReturn
33 _mm_sink_sample(GstElement * appsink, gpointer user_data)
34 {
35         GstBuffer *_buf = NULL;
36         GstSample *_sample = NULL;
37         gstreamer_s * pGstreamer_s = (gstreamer_s*) user_data;
38         _sample = gst_app_sink_pull_sample((GstAppSink*)appsink);
39         if (_sample) {
40                 _buf = gst_sample_get_buffer(_sample);
41
42                 pGstreamer_s->output_buffer = _buf;
43
44                 if (pGstreamer_s->output_buffer != NULL) {
45                         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
46                         gst_buffer_map(pGstreamer_s->output_buffer, &mapinfo, GST_MAP_READ);
47                         gstcs_debug("Create Output Buffer: GST_BUFFER_DATA: %p\t GST_BUFFER_SIZE: %zu", mapinfo.data, mapinfo.size);
48                         gst_buffer_unmap(pGstreamer_s->output_buffer, &mapinfo);
49                 } else {
50                         gstcs_error("ERROR -Input Prepare Buffer! Check createoutput buffer function");
51                 }
52         }
53
54         gst_buffer_ref(pGstreamer_s->output_buffer); /* when you want to avoid flushing */
55         gst_sample_unref(_sample);
56
57         return GST_FLOW_OK;
58 }
59
60 static gboolean
61 _mm_on_src_message(GstBus * bus, GstMessage * message, gpointer user_data)
62 {
63         gstreamer_s * pGstreamer_s = (gstreamer_s*) user_data;
64         switch (GST_MESSAGE_TYPE(message)) {
65         case GST_MESSAGE_EOS: {
66                 gstcs_debug("The source got dry");
67                 gst_app_src_end_of_stream(GST_APP_SRC(pGstreamer_s->appsrc));
68                 g_main_context_pop_thread_default(pGstreamer_s->context);
69                 g_main_loop_quit(pGstreamer_s->loop);
70                 break;
71                 }
72         case GST_MESSAGE_ERROR: {
73                 GError *err = NULL;
74                 gchar *dbg_info = NULL;
75
76                 gst_message_parse_error(message, &err, &dbg_info);
77                 gstcs_error("ERROR from element %s: %s\n", GST_OBJECT_NAME(message->src), err->message);
78                 gstcs_error("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
79                 g_error_free(err);
80                 g_free(dbg_info);
81                 g_main_context_pop_thread_default(pGstreamer_s->context);
82                 g_main_loop_quit(pGstreamer_s->loop);
83                 gstcs_debug("Quit GST_CS\n");
84                 break;
85                 }
86         default:
87                 break;
88         }
89         return TRUE;
90 }
91
92 static int _mm_get_byte_per_pixcel(mm_util_color_format_e color_format)
93 {
94         int byte_per_pixcel = 1;
95
96         switch (color_format) {
97         case MM_UTIL_COLOR_YUV420:
98         case MM_UTIL_COLOR_YUV422:
99         case MM_UTIL_COLOR_I420:
100         case MM_UTIL_COLOR_NV12:
101         case MM_UTIL_COLOR_UYVY:
102         case MM_UTIL_COLOR_YUYV:
103                 byte_per_pixcel = 1;
104                 break;
105         case MM_UTIL_COLOR_RGB16:
106                 byte_per_pixcel = 2;
107                 break;
108         case MM_UTIL_COLOR_RGB24:
109                 byte_per_pixcel = 3;
110                 break;
111         case MM_UTIL_COLOR_ARGB:
112         case MM_UTIL_COLOR_BGRA:
113         case MM_UTIL_COLOR_RGBA:
114         case MM_UTIL_COLOR_BGRX:
115                 byte_per_pixcel = 4;
116                 break;
117         default:
118                 gstcs_error("Not supported format");
119                 break;
120         }
121
122         gstcs_debug("color_format [%d] byte per pixcel [%d]", color_format, byte_per_pixcel);
123
124         return byte_per_pixcel;
125 }
126
127 static int _mm_create_pipeline(gstreamer_s* pGstreamer_s)
128 {
129         int ret = GSTCS_ERROR_NONE;
130         pGstreamer_s->pipeline = gst_pipeline_new("pipeline");
131         if (!pGstreamer_s->pipeline) {
132                 gstcs_error("pipeline could not be created. Exiting.\n");
133                 ret = GSTCS_ERROR_INVALID_PARAMETER;
134         }
135         pGstreamer_s->appsrc = gst_element_factory_make("appsrc" , "appsrc");
136         if (!pGstreamer_s->appsrc) {
137                 gstcs_error("appsrc could not be created. Exiting.\n");
138                 ret = GSTCS_ERROR_INVALID_PARAMETER;
139         }
140         pGstreamer_s->colorspace = gst_element_factory_make("videoconvert" , "convert");
141         if (!pGstreamer_s->colorspace) {
142                 gstcs_error("colorspace could not be created. Exiting.\n");
143                 ret = GSTCS_ERROR_INVALID_PARAMETER;
144         }
145         pGstreamer_s->videoscale = gst_element_factory_make("videoscale", "scale");
146         if (!pGstreamer_s->videoscale) {
147                 gstcs_error("videoscale could not be created. Exiting.\n");
148                 ret = GSTCS_ERROR_INVALID_PARAMETER;
149         }
150         pGstreamer_s->videoflip = gst_element_factory_make("videoflip", "flip");
151         if (!pGstreamer_s->videoflip) {
152                 gstcs_error("videoflip could not be created. Exiting.\n");
153                 ret = GSTCS_ERROR_INVALID_PARAMETER;
154         }
155         pGstreamer_s->appsink = gst_element_factory_make("appsink" , "appsink");
156         if (!pGstreamer_s->appsink) {
157                 gstcs_error("appsink could not be created. Exiting.\n");
158                 ret = GSTCS_ERROR_INVALID_PARAMETER;
159         }
160         return ret;
161 }
162
163 static void _mm_destroy_notify(gpointer data)
164 {
165         unsigned char *_data = (unsigned char *)data;
166         if (_data != NULL) {
167                 free(_data);
168                 _data = NULL;
169         }
170 }
171
172 static void
173 _mm_check_caps_format(GstCaps* caps)
174 {
175         GstStructure *caps_structure = gst_caps_get_structure(caps, 0);
176         const gchar* formatInfo = gst_structure_get_string(caps_structure, "format");
177         gstcs_debug("[%d] caps: %s", GST_IS_CAPS(caps), formatInfo);
178 }
179
180 static void
181 _mm_link_pipeline(gstreamer_s* pGstreamer_s, int value)
182 {
183         gstcs_fenter();
184
185         /* set property */
186         gst_bin_add_many(GST_BIN(pGstreamer_s->pipeline), pGstreamer_s->appsrc, pGstreamer_s->colorspace, pGstreamer_s->videoscale, pGstreamer_s->videoflip, pGstreamer_s->appsink, NULL);
187         if (!gst_element_link_many(pGstreamer_s->appsrc, pGstreamer_s->colorspace, pGstreamer_s->videoscale, pGstreamer_s->videoflip, pGstreamer_s->appsink, NULL))
188                 gstcs_error("Fail to link pipeline");
189         else
190                 gstcs_debug("Success to link pipeline");
191
192         g_object_set(G_OBJECT(pGstreamer_s->appsrc), "stream-type", 0, "format", GST_FORMAT_TIME, NULL);
193         g_object_set(pGstreamer_s->appsrc, "num-buffers", 1, NULL);
194         g_object_set(pGstreamer_s->appsrc, "is-live", TRUE, NULL); /* add because of gstreamer_s time issue */
195
196         g_object_set(pGstreamer_s->videoflip, "method", value, NULL); /* GST_VIDEO_FLIP_METHOD_IDENTITY (0): none- Identity (no rotation) (1): clockwise - Rotate clockwise 90 degrees (2): rotate-180 - Rotate 180 degrees (3): counterclockwise - Rotate counter-clockwise 90 degrees (4): horizontal-flip - Flip horizontally (5): vertical-flip - Flip vertically (6): upper-left-diagonal - Flip across upper left/lower right diagonal (7): upper-right-diagonal - Flip across upper right/lower left diagonal */
197
198         /*g_object_set(pGstreamer_s->appsink, "drop", TRUE, NULL);*/
199         g_object_set(pGstreamer_s->appsink, "emit-signals", TRUE, "sync", FALSE, NULL);
200
201         gstcs_fleave();
202 }
203
204 static GstVideoFormat _mm_get_video_format(mm_util_color_format_e color_format)
205 {
206         GstVideoFormat videoFormat = GST_VIDEO_FORMAT_UNKNOWN;
207         int _bpp = 0;
208         int _depth = 0;
209         int _red_mask = 0;
210         int _green_mask = 0;
211         int _blue_mask = 0;
212         int _alpha_mask = 0;
213         int _endianness = 0;
214
215         switch (color_format) {
216         case MM_UTIL_COLOR_YUV420:
217                 videoFormat = GST_VIDEO_FORMAT_YV12;
218                 break;
219         case MM_UTIL_COLOR_YUV422:
220                 videoFormat = GST_VIDEO_FORMAT_Y42B;
221                 break;
222         case MM_UTIL_COLOR_I420:
223                 videoFormat = GST_VIDEO_FORMAT_I420;
224                 break;
225         case MM_UTIL_COLOR_NV12:
226                 videoFormat = GST_VIDEO_FORMAT_NV12;
227                 break;
228         case MM_UTIL_COLOR_UYVY:
229                 videoFormat = GST_VIDEO_FORMAT_UYVY;
230                 break;
231         case MM_UTIL_COLOR_YUYV:
232                 videoFormat = GST_VIDEO_FORMAT_YVYU;
233                 break;
234         case MM_UTIL_COLOR_RGB16:
235                 _bpp = 16; _depth = 16; _red_mask = 63488; _green_mask = 2016; _blue_mask = 31; _endianness = 1234; _alpha_mask = 0;
236                 videoFormat = gst_video_format_from_masks(_depth, _bpp, _endianness, _red_mask, _green_mask, _blue_mask, _alpha_mask);
237                 break;
238         case MM_UTIL_COLOR_RGB24:
239                 _bpp = 24; _depth = 24; _red_mask = 16711680; _green_mask = 65280; _blue_mask = 255; _endianness = 4321; _alpha_mask = 0;
240                 videoFormat = gst_video_format_from_masks(_depth, _bpp, _endianness, _red_mask, _green_mask, _blue_mask, _alpha_mask);
241                 break;
242         case MM_UTIL_COLOR_ARGB:
243                 _bpp = 32; _depth = 32; _red_mask = 16711680; _green_mask = 65280; _blue_mask = 255; _alpha_mask = -16777216; _endianness = 4321;
244                 videoFormat = gst_video_format_from_masks(_depth, _bpp, _endianness, _red_mask, _green_mask, _blue_mask, _alpha_mask);
245                 break;
246         case MM_UTIL_COLOR_BGRA:
247                 _bpp = 32; _depth = 32; _red_mask = 65280; _green_mask = 16711680; _blue_mask = -16777216; _alpha_mask = 255; _endianness = 4321;
248                 videoFormat = gst_video_format_from_masks(_depth, _bpp, _endianness, _red_mask, _green_mask, _blue_mask, _alpha_mask);
249                 break;
250         case MM_UTIL_COLOR_RGBA:
251                 _bpp = 32; _depth = 32; _red_mask = -16777216; _green_mask = 16711680; _blue_mask = 65280; _alpha_mask = 255; _endianness = 4321;
252                 videoFormat = gst_video_format_from_masks(_depth, _bpp, _endianness, _red_mask, _green_mask, _blue_mask, _alpha_mask);
253                 break;
254         case MM_UTIL_COLOR_BGRX:
255                 _bpp = 32; _depth = 24; _red_mask = 65280; _green_mask = 16711680; _blue_mask = -16777216; _endianness = 4321; _alpha_mask = 0;
256                 videoFormat = gst_video_format_from_masks(_depth, _bpp, _endianness, _red_mask, _green_mask, _blue_mask, _alpha_mask);
257                 break;
258         default:
259                 gstcs_error("Not supported format");
260                 break;
261         }
262
263         gstcs_debug("color_format [%d], Chosen video format [%s]", color_format, gst_video_format_to_string(videoFormat));
264
265         return videoFormat;
266
267 }
268
269 static GstCaps* _mm_get_capabilities(mm_util_color_format_e color_format, unsigned int width, unsigned int height)
270 {
271         GstCaps *caps = NULL;
272         GstVideoFormat videoFormat = GST_VIDEO_FORMAT_UNKNOWN;
273
274         videoFormat = _mm_get_video_format(color_format);
275
276         caps = gst_caps_new_simple("video/x-raw",
277                         "format", G_TYPE_STRING, gst_video_format_to_string(videoFormat),
278                         "framerate", GST_TYPE_FRACTION, 25, 1,
279                         "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
280                         "width", G_TYPE_INT, width,
281                         "height", G_TYPE_INT, height,
282                         "framerate", GST_TYPE_FRACTION, 1, 1,
283                         NULL);
284
285         if (caps)
286                 _mm_check_caps_format(caps);
287         else
288                 gstcs_error("caps is NULL");
289
290         return caps;
291 }
292
293 static void _mm_get_round_up_width_height(mm_util_color_format_e color_format, unsigned int width, unsigned int height, unsigned int *stride, unsigned int *elevation)
294 {
295         switch (color_format) {
296         case MM_UTIL_COLOR_YUV420:
297         case MM_UTIL_COLOR_YUV422:
298         case MM_UTIL_COLOR_I420:
299         case MM_UTIL_COLOR_NV12:
300         case MM_UTIL_COLOR_UYVY:
301         case MM_UTIL_COLOR_YUYV:
302                 *stride = width;
303                 *elevation = height;
304                 break;
305         case MM_UTIL_COLOR_RGB16:
306         case MM_UTIL_COLOR_RGB24:
307                 *stride = MM_UTIL_ROUND_UP_4(width);
308                 *elevation = MM_UTIL_ROUND_UP_2(height);
309                 break;
310         case MM_UTIL_COLOR_ARGB:
311         case MM_UTIL_COLOR_BGRA:
312         case MM_UTIL_COLOR_RGBA:
313         case MM_UTIL_COLOR_BGRX:
314                 *stride = width;
315                 *elevation = MM_UTIL_ROUND_UP_2(height);
316                 break;
317         default:
318                 gstcs_error("Not supported format");
319                 break;
320         }
321
322         gstcs_debug("color_format[%d] width[%u] height[%u] stride[%u], elevation[%u]", color_format, width, height, *stride, *elevation);
323 }
324
325 static size_t _mm_setup_image_size(mm_util_color_format_e color_format, unsigned int width, unsigned int height)
326 {
327         size_t size = 0;
328
329         gstcs_debug("color_format [%d] width [%u] height [%u]", color_format, width, height);
330
331         switch (color_format) {
332         case MM_UTIL_COLOR_YUV420:
333                 size = (MM_UTIL_ROUND_UP_4(width) * MM_UTIL_ROUND_UP_2(height) + MM_UTIL_ROUND_UP_8(width) * MM_UTIL_ROUND_UP_2(height) / 2); /* width * height *1; */
334                 break;
335         case MM_UTIL_COLOR_YUV422:
336                 size = (MM_UTIL_ROUND_UP_4(width) * height + MM_UTIL_ROUND_UP_8(width) * height); /*width * height *2; */
337                 break;
338         case MM_UTIL_COLOR_I420:
339                 size = (MM_UTIL_ROUND_UP_4(width) * MM_UTIL_ROUND_UP_2(height) + MM_UTIL_ROUND_UP_8(width) * MM_UTIL_ROUND_UP_2(height) /2); /*width * height *1.5; */
340                 break;
341         case MM_UTIL_COLOR_NV12:
342                 size = (MM_UTIL_ROUND_UP_4(width) * MM_UTIL_ROUND_UP_2(height) * 1.5); /* width * height *1.5; */
343                 break;
344         case MM_UTIL_COLOR_UYVY:
345                 size = (MM_UTIL_ROUND_UP_2(width) * 2 * height); /* width * height *2; */
346                 break;
347         case MM_UTIL_COLOR_YUYV:
348                 size = (MM_UTIL_ROUND_UP_2(width) * 2 * height); /* width * height *2; */
349                 break;
350         case MM_UTIL_COLOR_RGB16:
351                 size = (MM_UTIL_ROUND_UP_4(width) * 2 * height); /* width * height *2; */
352                 break;
353         case MM_UTIL_COLOR_RGB24:
354                 size = (MM_UTIL_ROUND_UP_4(width) * 3 * height); /* width * height *3; */
355                 break;
356         case MM_UTIL_COLOR_ARGB:
357         case MM_UTIL_COLOR_BGRA:
358         case MM_UTIL_COLOR_RGBA:
359         case MM_UTIL_COLOR_BGRX:
360                 size = width * height *4;
361                 break;
362         default:
363                 gstcs_error("Not supported format");
364                 break;
365         }
366
367
368         gstcs_debug("Image size [%zu]", size);
369
370         return size;
371 }
372
373 static int _mm_push_buffer_into_pipeline(imgp_info_s* pImgp_info, unsigned char *src, gstreamer_s * pGstreamer_s)
374 {
375         int ret = GSTCS_ERROR_NONE;
376         size_t data_size = 0;
377         GstBuffer* gst_buf = NULL;
378
379         gstcs_fenter();
380
381         gstcs_retvm_if(pGstreamer_s->pipeline == NULL, GSTCS_ERROR_INVALID_PARAMETER, "Invalid pipeline");
382
383         data_size = _mm_setup_image_size(pImgp_info->src_format, pImgp_info->src_width, pImgp_info->src_height);
384         gst_buf = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, src, data_size, 0, data_size, NULL, NULL);
385
386         gstcs_retvm_if(gst_buf == NULL, GSTCS_ERROR_INVALID_OPERATION, "buffer is NULL");
387
388         gst_app_src_push_buffer(GST_APP_SRC(pGstreamer_s->appsrc), gst_buf); /* push buffer to pipeline */
389
390         gstcs_fleave();
391
392         return ret;
393 }
394
395 static int _mm_push_buffer_into_pipeline_new(unsigned char *src, gstreamer_s * pGstreamer_s, mm_util_color_format_e color_format, unsigned int width, unsigned int height, unsigned int stride, unsigned int elevation)
396 {
397         int ret = GSTCS_ERROR_NONE;
398         GstBuffer *gst_buf = NULL;
399         size_t src_size = 0;
400         unsigned char *data = NULL;
401
402         gstcs_fenter();
403
404         gstcs_retvm_if(pGstreamer_s->pipeline == NULL, GSTCS_ERROR_INVALID_PARAMETER, "Invalid pipeline");
405         gstcs_retvm_if((width == 0 || height == 0), GSTCS_ERROR_INVALID_PARAMETER, "Invalid width(%u) and height(%u)", width, height);
406
407         src_size = _mm_setup_image_size(color_format, stride, elevation);
408
409         int byte_per_pixcel = _mm_get_byte_per_pixcel(color_format);
410         unsigned int src_row = width * byte_per_pixcel;
411         unsigned int stride_row = stride * byte_per_pixcel;
412         unsigned int i = 0, y = 0;
413
414         data = (unsigned char *) malloc(src_size);
415         gstcs_retvm_if(data == NULL, GSTCS_ERROR_OUT_OF_MEMORY, "data is NULL");
416
417         for (y = 0; y < height; y++) {
418                 guint8 *pLine = (guint8 *) &(src[src_row * y]);
419                 for (i = 0; i < src_row; i++)
420                         data[y * stride_row + i] = pLine[i];
421                 guint8 stride_row_color = pLine[i - 1];
422                 for (i = src_row; i < stride_row; i++)
423                         data[y * stride_row + i] = stride_row_color;
424         }
425         for (y = height; y < elevation; y++) {
426                 for (i = 0; i < stride_row; i++)
427                         data[y * stride_row + i] = data[(y - 1) * stride_row + i];
428         }
429         gst_buf = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, data, src_size, 0, src_size, data, _mm_destroy_notify);
430
431         if (gst_buf == NULL) {
432                 gstcs_error("buffer is NULL\n");
433                 GSTCS_FREE(data);
434                 return GSTCS_ERROR_INVALID_PARAMETER;
435         }
436
437         gst_app_src_push_buffer(GST_APP_SRC(pGstreamer_s->appsrc), gst_buf); /* push buffer to pipeline */
438
439         gstcs_fleave();
440
441         return ret;
442 }
443
444 static int _mm_imgp_gstcs_processing(gstreamer_s* pGstreamer_s, unsigned char *src, unsigned char **dst, imgp_info_s* pImgp_info)
445 {
446         GstBus *bus = NULL;
447         GstStateChangeReturn ret_state;
448         int ret = GSTCS_ERROR_NONE;
449         GstCaps *src_caps = NULL;
450         GstCaps *dst_caps = NULL;
451         unsigned int src_stride = 0;
452         unsigned int src_elevation = 0;
453
454         gstcs_fenter();
455
456         /*create pipeline*/
457         ret = _mm_create_pipeline(pGstreamer_s);
458         if (ret != GSTCS_ERROR_NONE)
459                 gstcs_error("ERROR - mm_create_pipeline ");
460
461         /* Make appsink emit the "new-preroll" and "new-sample" signals. This option is by default disabled because signal emission is expensive and unneeded when the application prefers to operate in pull mode. */
462         gst_app_sink_set_emit_signals((GstAppSink*)pGstreamer_s->appsink, TRUE);
463
464         bus = gst_pipeline_get_bus(GST_PIPELINE(pGstreamer_s->pipeline));
465         gst_bus_add_watch(bus, (GstBusFunc) _mm_on_src_message, pGstreamer_s);
466         gst_object_unref(bus);
467
468         _mm_get_round_up_width_height(pImgp_info->src_format, pImgp_info->src_width, pImgp_info->src_height, &src_stride, &src_elevation);
469         _mm_get_round_up_width_height(pImgp_info->dst_format, pImgp_info->dst_width, pImgp_info->dst_height, &pImgp_info->output_stride, &pImgp_info->output_elevation);
470
471         src_caps = _mm_get_capabilities(pImgp_info->src_format, src_stride, src_elevation);
472         dst_caps = _mm_get_capabilities(pImgp_info->dst_format, pImgp_info->output_stride, pImgp_info->output_elevation);
473
474         gst_app_src_set_caps(GST_APP_SRC(pGstreamer_s->appsrc), src_caps);
475         gst_app_sink_set_caps(GST_APP_SINK(pGstreamer_s->appsink), dst_caps);
476
477         if ((pImgp_info->src_width != src_stride) || (pImgp_info->src_height != src_elevation)) {
478                 ret = _mm_push_buffer_into_pipeline_new(src, pGstreamer_s, pImgp_info->src_format, pImgp_info->src_width, pImgp_info->src_height, src_stride, src_elevation);
479         } else {
480                 ret = _mm_push_buffer_into_pipeline(pImgp_info, src, pGstreamer_s);
481         }
482
483         if (ret != GSTCS_ERROR_NONE) {
484                 gstcs_error("ERROR - mm_push_buffer_into_pipeline ");
485                 if (src_caps)
486                         gst_caps_unref(src_caps);
487                 if (dst_caps)
488                         gst_caps_unref(dst_caps);
489                 gst_object_unref(pGstreamer_s->pipeline);
490                 return ret;
491         }
492
493         /*link pipeline*/
494         _mm_link_pipeline(pGstreamer_s, pImgp_info->angle);
495
496         /* Conecting to the new-sample signal emited by the appsink*/
497         gstcs_debug("Start G_CALLBACK(_mm_sink_sample)");
498         g_signal_connect(pGstreamer_s->appsink, "new-sample", G_CALLBACK(_mm_sink_sample), pGstreamer_s);
499         gstcs_debug("End G_CALLBACK(_mm_sink_sample)");
500
501         /* GST_STATE_PLAYING*/
502         gstcs_debug("Start GST_STATE_PLAYING");
503         ret_state = gst_element_set_state(pGstreamer_s->pipeline, GST_STATE_PLAYING);
504         gstcs_debug("End GST_STATE_PLAYING ret_state: %d", ret_state);
505
506         /*g_main_loop_run*/
507         gstcs_debug("g_main_loop_run");
508         g_main_loop_run(pGstreamer_s->loop);
509
510         gstcs_debug("Sucess GST_STATE_CHANGE");
511
512         /*GST_STATE_NULL*/
513         gst_element_set_state(pGstreamer_s->pipeline, GST_STATE_NULL);
514         gstcs_debug("End GST_STATE_NULL");
515
516         gstcs_debug("###pGstreamer_s->output_buffer### : %p", pGstreamer_s->output_buffer);
517
518         ret_state = gst_element_get_state(pGstreamer_s->pipeline, NULL, NULL, 1*GST_SECOND);
519
520         if (ret_state == GST_STATE_CHANGE_SUCCESS)
521                 gstcs_debug("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_SUCCESS)\n", ret_state);
522         else if (ret_state == GST_STATE_CHANGE_ASYNC)
523                 gstcs_debug("GST_STATE_NULL ret_state = %d (GST_STATE_CHANGE_ASYNC)\n", ret_state);
524
525         gstcs_debug("Success gst_element_get_state\n");
526
527         if (src_caps)
528                 gst_caps_unref(src_caps);
529         if (dst_caps)
530                 gst_caps_unref(dst_caps);
531
532         if (ret_state == GST_STATE_CHANGE_FAILURE) {
533                 gstcs_error("GST_STATE_CHANGE_FAILURE");
534         } else {
535                 if (pGstreamer_s->output_buffer != NULL) {
536                         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
537                         gst_buffer_map(pGstreamer_s->output_buffer, &mapinfo, GST_MAP_READ);
538                         size_t buffer_size = mapinfo.size;
539                         size_t calc_buffer_size = 0;
540
541                         calc_buffer_size = _mm_setup_image_size(pImgp_info->dst_format, pImgp_info->output_stride, pImgp_info->output_elevation);
542
543                         gstcs_debug("buffer size[%zu], calc[%zu]", buffer_size, calc_buffer_size);
544                         if (buffer_size != calc_buffer_size) {
545                                 gstcs_debug("Buffer size is different \n");
546                                 gstcs_debug("unref output buffer");
547                                 gst_buffer_unref(pGstreamer_s->output_buffer);
548                                 gst_object_unref(pGstreamer_s->pipeline);
549                                 pGstreamer_s->output_buffer = NULL;
550                                 return GSTCS_ERROR_INVALID_OPERATION;
551                         }
552                         gstcs_debug("pGstreamer_s->output_buffer: %p\n", pGstreamer_s->output_buffer);
553                         *dst = calloc(1, buffer_size);
554                         if (*dst == NULL) {
555                                 gstcs_error("ERROR - calloc ");
556                                 gst_buffer_unref(pGstreamer_s->output_buffer);
557                                 gst_object_unref(pGstreamer_s->pipeline);
558                                 pGstreamer_s->output_buffer = NULL;
559                                 return GSTCS_ERROR_INVALID_OPERATION;
560                         }
561
562                         memcpy(*dst, mapinfo.data, buffer_size);
563                         pImgp_info->buffer_size = buffer_size;
564                         gst_buffer_unmap(pGstreamer_s->output_buffer, &mapinfo);
565                 } else {
566                         gstcs_debug("pGstreamer_s->output_buffer is NULL");
567                 }
568         }
569         gstcs_debug("unref output buffer");
570         gst_buffer_unref(pGstreamer_s->output_buffer);
571         gst_object_unref(pGstreamer_s->pipeline);
572         pGstreamer_s->output_buffer = NULL;
573
574         gstcs_debug("dst: %p", *dst);
575         gstcs_fleave();
576
577         return ret;
578 }
579
580 static int _gstcs_create_default_thread(gstreamer_s *gstreamer)
581 {
582         gstcs_retvm_if(gstreamer == NULL, GSTCS_ERROR_INVALID_PARAMETER, "Invalid gstreamer");
583
584         gstreamer->context = g_main_context_new();
585         gstcs_retvm_if(gstreamer->context == NULL, GSTCS_ERROR_INVALID_OPERATION, "ERROR - g_main_context_new");
586
587         gstreamer->loop = g_main_loop_new(gstreamer->context, FALSE);
588         if (gstreamer->loop == NULL) {
589                 gstcs_error("ERROR - g_main_loop_new ");
590                 g_main_context_unref(gstreamer->context);
591                 return GSTCS_ERROR_INVALID_OPERATION;
592         }
593
594         g_main_context_push_thread_default(gstreamer->context);
595
596         return GSTCS_ERROR_NONE;
597 }
598
599 static int _gstcs_destroy_default_thread(gstreamer_s *gstreamer)
600 {
601         gstcs_retvm_if(gstreamer == NULL, GSTCS_ERROR_INVALID_PARAMETER, "Invalid gstreamer");
602
603         if (gstreamer->loop != NULL)
604                 g_main_loop_unref(gstreamer->loop);
605
606         if (gstreamer->context != NULL)
607                 g_main_context_unref(gstreamer->context);
608
609         return GSTCS_ERROR_NONE;
610 }
611
612 static int _gstcs_init(gstreamer_s** gstreamer)
613 {
614         static const int max_argc = 50;
615         gint argc = 0;
616         gchar** argv = NULL;
617         int i = 0;
618         int ret = GSTCS_ERROR_NONE;
619
620         argv = malloc(sizeof(gchar*) * max_argc);
621
622         gstcs_retvm_if(argv == NULL, GSTCS_ERROR_OUT_OF_MEMORY, "argv is not allocated");
623
624         memset(argv, 0, sizeof(gchar*) * max_argc);
625
626         argv[argc] = g_strdup("mmutil_gstcs");
627         if (argv[argc] == NULL) {
628                 gstcs_error("argv[%d] is not allocated", argc);
629                 ret = GSTCS_ERROR_OUT_OF_MEMORY;
630         }
631         argc++;
632         /* check disable registry scan */
633         argv[argc] = g_strdup("--gst-disable-registry-update");
634         if (argv[argc] == NULL) {
635                 gstcs_error("argv[%d] is not allocated", argc);
636                 ret = GSTCS_ERROR_OUT_OF_MEMORY;
637         }
638         argc++;
639         if (ret != GSTCS_ERROR_NONE) {
640                 for (i = 0; i < argc; i++)
641                         GSTCS_FREE(argv[i]);
642
643                 GSTCS_FREE(argv);
644                 return ret;
645         }
646
647         gst_init(&argc, &argv);
648
649         *gstreamer = g_new0(gstreamer_s, 1);
650         if (*gstreamer == NULL) {
651                 gstcs_error("gstreamer structure is not allocated");
652                 ret = GSTCS_ERROR_OUT_OF_MEMORY;
653         }
654
655         for (i = 0; i < argc; i++)
656                 GSTCS_FREE(argv[i]);
657
658         GSTCS_FREE(argv);
659         return ret;
660 }
661
662 static int _mm_imgp_gstcs(imgp_info_s* pImgp_info, unsigned char *src, unsigned char **dst)
663 {
664         gstreamer_s* pGstreamer_s;
665         int ret = GSTCS_ERROR_NONE;
666
667         /* Print debug message for inout structure */
668         gstcs_debug("src_width [%d] src_height [%d] src_format [%d] dst_width [%d] dst_height [%d] dst_format [%d] rotation [%d]",
669         pImgp_info->src_width, pImgp_info->src_height, pImgp_info->src_format, pImgp_info->dst_width, pImgp_info->dst_height, pImgp_info->dst_format, pImgp_info->angle);
670
671         /* Initialize gstreamer */
672         ret = _gstcs_init(&pGstreamer_s);
673         if (ret != GSTCS_ERROR_NONE) {
674                 gstcs_error("Error: _gstcs_new is failed");
675                 return ret;
676         }
677
678         /* Create default thread for async behavior */
679         ret = _gstcs_create_default_thread(pGstreamer_s);
680         if (ret != GSTCS_ERROR_NONE) {
681                 gstcs_error("Error: _gstcs_create_default_thread is failed");
682                 GSTCS_FREE(pGstreamer_s);
683                 return ret;
684         }
685
686         /* Do gstreamer processing */
687         ret = _mm_imgp_gstcs_processing(pGstreamer_s, src, dst, pImgp_info); /* input: buffer pointer for input image , input image format, input image width, input image height, output: buffer porinter for output image */
688
689         if (ret == GSTCS_ERROR_NONE)
690                 gstcs_debug("End _mm_imgp_gstcs_processing [dst: %p]", *dst);
691         else if (ret != GSTCS_ERROR_NONE)
692                 gstcs_error("ERROR - _mm_imgp_gstcs_processing");
693
694         /* Free resouces */
695         ret = _gstcs_destroy_default_thread(pGstreamer_s);
696         if (ret != GSTCS_ERROR_NONE)
697                 gstcs_error("Error: _gstcs_create_default_thread is failed");
698
699         GSTCS_FREE(pGstreamer_s);
700
701         return ret;
702 }
703
704 static bool _mm_imgp_check_format(mm_util_color_format_e color_format)
705 {
706         if ((color_format >= MM_UTIL_COLOR_YUV420) && (color_format <= MM_UTIL_COLOR_BGRX))
707                 return TRUE;
708
709         return FALSE;
710 }
711
712 int mm_imgp(imgp_info_s* pImgp_info, unsigned char *src, unsigned char **dst, imgp_type_e _imgp_type)
713 {
714         gstcs_retvm_if(pImgp_info == NULL, GSTCS_ERROR_INVALID_PARAMETER, "Invalid info");
715         gstcs_retvm_if(src == NULL, GSTCS_ERROR_INVALID_PARAMETER, "Invalid src");
716         gstcs_retvm_if(dst == NULL, GSTCS_ERROR_INVALID_PARAMETER, "Invalid dst");
717         gstcs_retvm_if((_imgp_type < 0 || _imgp_type > IMGP_MAX), GSTCS_ERROR_INVALID_PARAMETER, "Invalid _imgp_type[%d]", _imgp_type);
718         gstcs_retvm_if((_mm_imgp_check_format(pImgp_info->src_format) == FALSE), GSTCS_ERROR_NOT_SUPPORTED_FORMAT, "not supported src_format [%d]", pImgp_info->src_format);
719         gstcs_retvm_if((_mm_imgp_check_format(pImgp_info->dst_format) == FALSE), GSTCS_ERROR_NOT_SUPPORTED_FORMAT, "not supported dst_format [%d]", pImgp_info->dst_format);
720
721         gstcs_debug("[src %p] [dst %p]", src, dst);
722
723         return _mm_imgp_gstcs(pImgp_info, src, dst);
724 }