Add new internal API to enable extra video convert element
[platform/core/api/mediacodec.git] / src / media_codec_port_gst.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <dlog.h>
21 #include <media_codec_queue.h>
22 #include <media_codec_port_gst.h>
23 #include <media_packet_internal.h>
24 #include <media_codec_util.h>
25
26 #include <gst/gst.h>
27 #include <gst/gstelement.h>
28 #include <gst/app/gstappsrc.h>
29 #include <gst/pbutils/pbutils.h>
30 #include <gst/tag/tag.h>
31
32 /*
33  * Internal Implementation
34  */
35 static gpointer feed_task(gpointer data);
36 static void _mc_gst_feed_task_new(mc_gst_core_t *core);
37 static void _mc_gst_feed_task_free(mc_gst_core_t *core);
38 static void __mc_gst_stop_feed(GstElement *pipeline, gpointer data);
39 static void __mc_gst_start_feed(GstElement *pipeline, guint size, gpointer data);
40 static media_packet_h _mc_get_input_buffer(mc_gst_core_t *core);
41
42 static gboolean __mc_gst_init_gstreamer();
43 static int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, media_format_mimetype_e out_mime);
44 static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name);
45 static mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core);
46 static void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data);
47 static int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data);
48 static gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format);
49 static GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet_h packet, bool codec_config);
50 static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *mcbuffer);
51 static gchar *__mc_get_gst_input_format(media_format_mimetype_e mimetype, bool is_hw);
52 static GstMCBuffer *__mc_gst_make_media_packet(mc_gst_core_t *core, GstBuffer *buffer);
53 static gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data);
54 static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data);
55 static GstMemory *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, GstMCBuffer *mcbuffer);
56 static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h packet, uint64_t size);
57 static void __mc_input_buffer_finalize_cb(GstMCBuffer *buffer);
58 static int __mc_set_caps_streamheader(mc_gst_core_t *core, GstMCBuffer *mcbuffer, guint streamheader_size);
59 static int __mc_set_caps_codecdata(mc_gst_core_t *core, GstMCBuffer *mcbuffer, guint codecdata_size);
60 static void __mc_push_output_to_queue(mc_gst_core_t *core, GstMCBuffer *mcbuffer);
61 static int __mc_gst_create_eos_packet(media_format_h fmt, GstMCBuffer *mcbuffer);
62 static void _mc_gst_handle_input_buffer_used(mc_gst_core_t *core, media_packet_h packet);
63 static gboolean _mc_gst_video_info_check_and_new(mc_gst_core_t *core, GstMCBuffer *mcbuffer);
64 static void _mc_gst_video_info_free(mc_gst_core_t *core);
65 static void _mc_gst_video_meta_add(mc_gst_core_t *core, GstBuffer *buffer);
66
67 static gint __gst_handle_stream_error(mc_gst_core_t *core, GError *error, GstMessage *message);
68 static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage *message, GError *error);
69 static gint __gst_handle_resource_error(mc_gst_core_t *core, int code);
70 static gint __gst_handle_library_error(mc_gst_core_t *core, int code);
71 static gint __gst_handle_core_error(mc_gst_core_t *core, int code);
72 static const gchar * _mc_error_to_string(mc_ret_e err);
73 static const gchar * _mc_bit_to_string(int bit);
74
75 static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboolean is_encoder, gboolean is_hw);
76 static int _mc_gst_flush_buffers(mc_gst_core_t *core);
77 static void _mc_gst_set_flush_input(mc_gst_core_t *core);
78 static void _mc_gst_set_flush_output(mc_gst_core_t *core);
79
80 #ifdef TIZEN_EXYNOS_SPECIFIC
81 static int __tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos);
82 static void __csc_tiled_to_linear_crop(unsigned char *yuv420_dest,
83                 unsigned char *nv12t_src, int yuv420_width, int yuv420_height,
84                 int left, int top, int right, int buttom);
85 #endif
86
87 static void _mc_send_eos_signal(mc_gst_core_t *core);
88 static void _mc_wait_for_eos(mc_gst_core_t *core);
89 static int _mc_get_mime(mc_gst_core_t *core);
90 static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool codec_config);
91 static gboolean _mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index);
92 static gboolean _mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index);
93
94 static int __mc_fill_input_buffer(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
95 static int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
96
97 static int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
98 static int __mc_fill_input_buffer_with_adec_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
99 static int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer);
100
101 static int __mc_fill_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
102 static int __mc_fill_aenc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
103 static int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
104 static int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer);
105
106 static mc_gst_core_t *mc_gst_core_new();
107 static void mc_gst_core_free(mc_gst_core_t *core);
108
109 static mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core);
110 static void mc_gst_port_free(mc_gst_port_t *port);
111 /* video vtable */
112 __attribute__((unused))
113 static int(*vdec_vtable[])() = {&__mc_fill_input_buffer_with_packet, &__mc_fill_packet_with_output_buffer};
114
115 static int(*venc_vtable[])() = {&__mc_fill_input_buffer_with_packet, &__mc_fill_packet_with_output_buffer};
116
117 static int(*vdec_h264_sw_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* S/W H.264 Decoder Vtable */
118                                                                 &__mc_fill_vdec_packet_with_output_buffer};
119
120 static int(*vdec_mpeg4_sw_vtable[])() = {&__mc_fill_input_buffer_with_packet,                   /* S/W MPEG4 Decoder Vtable */
121                                                                 &__mc_fill_vdec_packet_with_output_buffer};
122
123 static int(*vdec_h263_sw_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* S/W MPEG4 Decoder Vtable */
124                                                                 &__mc_fill_vdec_packet_with_output_buffer};
125
126 static int(*vdec_h264_hw_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* H/W H.264 Decoder Vtable */
127                                                                 &__mc_fill_vdec_packet_with_output_buffer};
128
129 static int(*vdec_mpeg4_hw_vtable[])() = {&__mc_fill_input_buffer_with_packet,                   /* H/W MPEG4 Decoder Vtable */
130                                                                 &__mc_fill_vdec_packet_with_output_buffer};
131
132 static int(*vdec_h263_hw_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* H/W MPEG4 Decoder Vtable */
133                                                                 &__mc_fill_vdec_packet_with_output_buffer};
134
135 static int(*venc_mpeg4_sw_vtable[])() = {&__mc_fill_input_buffer_with_venc_packet,              /* S/W MPEG4 Encoder Vtable */
136                                                                 &__mc_fill_venc_packet_with_output_buffer};
137
138 static int(*venc_h263_sw_vtable[])() = {&__mc_fill_input_buffer_with_venc_packet,               /* S/W MPEG4 Encoder Vtable */
139                                                                 &__mc_fill_venc_packet_with_output_buffer};
140
141 static int(*venc_h264_hw_vtable[])() = {&__mc_fill_input_buffer_with_venc_packet,               /* H/W H.264 Encoder Vtable */
142                                                                 &__mc_fill_venc_packet_with_output_buffer};
143
144 static int(*venc_mpeg4_hw_vtable[])() = {&__mc_fill_input_buffer_with_venc_packet,              /* H/W MPEG4 Encoder Vtable */
145                                                                 &__mc_fill_venc_packet_with_output_buffer};
146
147 static int(*venc_h263_hw_vtable[])() = {&__mc_fill_input_buffer_with_venc_packet,               /* H/W MPEG4 Encoder Vtable */
148                                                                 &__mc_fill_venc_packet_with_output_buffer};
149
150 __attribute__((unused))
151 static int(*aenc_vtable[])() = {&__mc_fill_input_buffer_with_packet, &__mc_fill_packet_with_output_buffer};
152
153 static int(*adec_vtable[])() = {&__mc_fill_input_buffer_with_packet, &__mc_fill_packet_with_output_buffer};
154
155 static int(*aenc_aac_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* AAC LC Encoder vtable */
156                                                         &__mc_fill_aenc_packet_with_output_buffer};
157
158 static int(*adec_aac_vtable[])() = {&__mc_fill_input_buffer_with_adec_packet,               /* AAC LC Decoder Vtable */
159                                                         &__mc_fill_packet_with_output_buffer};
160
161 static int(*adec_aacv12_vtable[])() = {&__mc_fill_input_buffer_with_adec_packet,            /* AAC HE Decoder Vtable */
162                                                         &__mc_fill_packet_with_output_buffer};
163
164 static int(*adec_mp3_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* MP3 Decoder Vtable */
165                                                         &__mc_fill_packet_with_output_buffer};
166
167 static int(*adec_amrnb_vtable[])() = {&__mc_fill_input_buffer_with_packet,                  /* AMR-NB Decoder Vtable */
168                                                         &__mc_fill_packet_with_output_buffer};
169
170 static int(*adec_amrwb_vtable[])() = {&__mc_fill_input_buffer_with_packet,                  /* AMR-WB Decoder Vtable */
171                                                         &__mc_fill_packet_with_output_buffer};
172
173 static int(*aenc_amrnb_vtable[])() = {&__mc_fill_input_buffer_with_packet,                  /* AMR-NB Encoder Vtable */
174                                                         &__mc_fill_packet_with_output_buffer};
175
176 static int(*adec_vorbis_vtable[])() = {&__mc_fill_input_buffer_with_packet,                 /* VORBIS Decoder Vtable */
177                                                         &__mc_fill_packet_with_output_buffer};
178
179 static int(*adec_flac_vtable[])() = {&__mc_fill_input_buffer_with_packet,                   /* FLAC Decoder Vtable */
180                                                         &__mc_fill_packet_with_output_buffer};
181
182 static int(*adec_wma_vtable[])() = {&__mc_fill_input_buffer_with_packet,                    /* WMA Decoder Vtable */
183                                                         &__mc_fill_packet_with_output_buffer};
184
185 static int(*aenc_opus_vtable[])() =  {&__mc_fill_input_buffer_with_packet,                  /* Opus Encoder Vtable */
186                                                         &__mc_fill_aenc_packet_with_output_buffer};
187
188 #define MEDIACODEC_CROP_ARRAY_LENGTH 4
189 #define MEDIACODEC_ELEMENT_SET_STATE(x_element, x_state)                                          \
190         do {                                                                                            \
191                 LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME(x_element)); \
192                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(x_element, x_state)) {                    \
193                         LOGE("failed to set state %s to %s\n", #x_state, GST_ELEMENT_NAME(x_element));        \
194                         goto STATE_CHANGE_FAILED;                                                               \
195                 }                                                                                           \
196         } while (0)
197
198 /*
199  * fill_inbuf virtual functions
200  */
201 int __mc_fill_input_buffer(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
202 {
203         return core->vtable[fill_inbuf](core, packet, mcbuffer);
204 }
205
206 static int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
207 {
208         gint ret = MC_ERROR_NONE;
209         void *buf_data = NULL;
210         uint64_t buf_size = 0;
211
212         ret = media_packet_get_buffer_size(packet, &buf_size);
213         if (ret != MEDIA_PACKET_ERROR_NONE) {
214                 LOGW("buffer size get failed");
215                 return MC_ERROR;
216         }
217
218         ret = media_packet_get_buffer_data_ptr(packet, &buf_data);
219         if (ret != MEDIA_PACKET_ERROR_NONE) {
220                 LOGW("buffer data get failed");
221                 return MC_ERROR;
222         }
223
224         if (buf_data == NULL)
225                 return MC_ERROR;
226
227         gst_buffer_append_memory(mcbuffer->buffer,
228                 gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0,
229                         buf_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb));
230         LOGD("packet data apended");
231
232         return ret;
233 }
234
235 static int __mc_fill_input_buffer_with_adec_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
236 {
237         gint ret = MC_ERROR_NONE;
238         uint64_t buf_size = 0;
239         unsigned int codec_size = 0;
240         bool codec_config = FALSE;
241         void *buf_data = NULL;
242         void *codec_data = NULL;
243
244         ret = media_packet_get_buffer_size(packet, &buf_size);
245         if (ret != MEDIA_PACKET_ERROR_NONE) {
246                 LOGW("buffer size get failed");
247                 return MC_ERROR;
248         }
249
250         ret = media_packet_get_buffer_data_ptr(packet, &buf_data);
251         if (ret != MEDIA_PACKET_ERROR_NONE) {
252                 LOGW("buffer data get failed");
253                 return MC_ERROR;
254         }
255
256         if (media_packet_is_codec_config(packet, &codec_config) != MEDIA_PACKET_ERROR_NONE) {
257                 LOGE("media_packet_is_codec_config failed");
258                 return MC_ERROR;
259         }
260
261         if (buf_data != NULL) {
262                 media_packet_get_codec_data(packet, &codec_data, &codec_size);
263
264                 if (!codec_data && codec_config) {
265                         gst_buffer_append_memory(mcbuffer->buffer,
266                                         gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0,
267                                                 buf_size, NULL, NULL));
268                         LOGD("csd packet data apended");
269                 } else {
270                         gst_buffer_append_memory(mcbuffer->buffer,
271                                         gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0,
272                                                 buf_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb));
273                         LOGD("packet data apended");
274                 }
275
276                 if (codec_data)
277                         free(codec_data);
278         }
279
280         return ret;
281 }
282
283 static int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h packet, GstMCBuffer *mcbuffer)
284 {
285         gint ret = MC_ERROR_NONE;
286         gint i;
287         gint j;
288         gint stride = 0;
289         gint buf_size = 0;
290         gint stride_width;
291         gint stride_height;
292         gint width;
293         gint height;
294         uint32_t plane_num;
295         guint8 *planes[2];
296         GstMemory *mem = NULL;
297
298         mc_gst_port_def_t *port_def = &core->ports[in_port_index]->port_def;
299
300         width = port_def->info.video.width;
301         height = port_def->info.video.height;
302
303         ret = media_packet_get_number_of_video_planes(packet, &plane_num);
304         if (ret != MEDIA_PACKET_ERROR_NONE) {
305                 LOGW("media_packet_get_number_of_video_planes failed");
306                 return MC_ERROR;
307         }
308
309         ret = media_packet_get_video_plane_data_ptr(packet, 0, (void **)&planes[0]);
310         if (ret != MEDIA_PACKET_ERROR_NONE) {
311                 LOGW("media_packet_get_video_plane_data_ptr failed");
312                 return MC_ERROR;
313         }
314
315         ret = media_packet_get_video_stride_width(packet, 0, &stride_width);
316         if (ret != MEDIA_PACKET_ERROR_NONE) {
317                 LOGW("media_packet_get_video_stride_width failed");
318                 return MC_ERROR;
319         }
320
321         ret = media_packet_get_video_stride_height(packet, 0, &stride_height);
322         if (ret != MEDIA_PACKET_ERROR_NONE) {
323                 LOGW("media_packet_get_video_stride_width failed");
324                 return MC_ERROR;
325         }
326
327         if (!core->is_hw) {
328                 if (width == stride_width) {
329                         mcbuffer->buf_size += stride_width * stride_height;
330
331                         for (i = 1; i < plane_num; i++) {
332                                 media_packet_get_video_plane_data_ptr(packet, i, (void **)&planes[1]);
333                                 media_packet_get_video_stride_width(packet, i, &stride_width);
334                                 media_packet_get_video_stride_height(packet, i, &stride_height);
335
336                                 buf_size = stride_width * stride_height;
337
338                                 memcpy(planes[0] + mcbuffer->buf_size, planes[1], buf_size);
339                                 mcbuffer->buf_size += buf_size;
340                                 LOGD("plane : %d, buf_size : %d, total : %d", i, buf_size, mcbuffer->buf_size);
341                         }
342                 } else {
343
344                         for (j = 0; j < height; j++) {
345                                 memcpy(planes[0] + mcbuffer->buf_size, planes[0] + stride, width);
346                                 mcbuffer->buf_size += width;
347                                 stride += stride_width;
348                         }
349
350                         stride = 0;
351
352                         for (i = 1; i < plane_num; i++) {
353                                 media_packet_get_video_plane_data_ptr(packet, i, (void **)&planes[1]);
354                                 media_packet_get_video_stride_width(packet, i, &stride_width);
355                                 media_packet_get_video_stride_height(packet, i, &stride_height);
356
357                                 for (j = 0; j < height>>1; j++) {
358                                         memcpy(planes[0] + mcbuffer->buf_size, planes[1] + stride, width>>1);
359                                         mcbuffer->buf_size += width>>1;
360                                         stride += stride_width;
361                                 }
362
363                                 memcpy(planes[0] + mcbuffer->buf_size, planes[1], buf_size);
364                                 LOGD("plane : %d, buf_size : %d, total : %d", i, buf_size, mcbuffer->buf_size);
365                                 mcbuffer->buf_size += buf_size;
366                         }
367                 }
368
369                 mem = gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY,
370                                 planes[0], mcbuffer->buf_size, 0,
371                                 mcbuffer->buf_size, mcbuffer,
372                                 (GDestroyNotify)__mc_input_buffer_finalize_cb);
373         } else {
374                 mem = __mc_gst_make_tbm_buffer(core, mcbuffer);
375                 LOGD("tizen memory[%p]", mem);
376         }
377
378         if (mem == NULL) {
379                 LOGE("gstmemory failed[is_hw:%d]", core->is_hw);
380                 return MC_ERROR;
381         }
382
383         gst_buffer_append_memory(mcbuffer->buffer, mem);
384
385         _mc_gst_video_meta_add(core, mcbuffer->buffer);
386
387         return ret;
388 }
389
390
391 /*
392  * fill_outbuf virtual functions
393  */
394
395 static int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
396 {
397         return core->vtable[fill_outbuf](core, data, size, mcbuffer);
398 }
399
400 static int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
401 {
402         int i;
403         int stride_width;
404         int stride_height;
405         uint32_t width;
406         uint32_t height;
407         uint32_t buf_size;
408         tbm_surface_info_s tsurf_info;
409         tbm_bo bo[MM_VIDEO_BUFFER_PLANE_MAX];
410         tbm_bo_handle thandle;
411         tbm_surface_h tsurf = NULL;
412         media_packet_h packet = NULL;
413
414         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
415
416         mc_gst_port_def_t *port_def = &core->ports[out_port_index]->port_def;
417
418         if (!core->is_hw) {
419                 width = port_def->info.video.width;
420                 height = port_def->info.video.height;
421                 stride_width = GST_ROUND_UP_4(width);
422                 stride_height = height;
423                 buf_size = stride_width * stride_height * 3 / 2;
424
425                 memset(&tsurf_info, 0x0, sizeof(tbm_surface_info_s));
426
427                 bo[0] = tbm_bo_alloc(core->bufmgr, buf_size, TBM_BO_WC);
428                 if (!bo[0]) {
429                         LOGE("bo allocation failed");
430                         return MC_ERROR;
431                 }
432
433                 tsurf_info.width = port_def->info.video.width;
434                 tsurf_info.height = port_def->info.video.height;
435                 tsurf_info.format = TBM_FORMAT_YVU420;
436                 tsurf_info.bpp = tbm_surface_internal_get_bpp(TBM_FORMAT_YVU420);
437                 tsurf_info.num_planes = tbm_surface_internal_get_num_planes(TBM_FORMAT_YVU420);
438                 tsurf_info.size = 0;
439
440                 for (i = 0; i < tsurf_info.num_planes; i++) {
441                         if (i == 0) {
442                                 tsurf_info.planes[i].stride = stride_width;
443                                 tsurf_info.planes[i].size = stride_width * stride_height;
444                                 tsurf_info.planes[i].offset = 0;
445                                 tsurf_info.size = tsurf_info.planes[i].size;
446                         } else {
447                                 tsurf_info.planes[i].stride = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2);
448                                 tsurf_info.planes[i].size = GST_ROUND_UP_4(GST_ROUND_UP_2(width) / 2) * (height / 2);
449                                 tsurf_info.planes[i].offset = (tsurf_info.planes[i-1].offset + tsurf_info.planes[i - 1].size);
450                                 tsurf_info.size += tsurf_info.planes[i].size;
451                         }
452                 }
453
454                 thandle = tbm_bo_map(bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
455                 memcpy(thandle.ptr, data, tsurf_info.size);
456                 tbm_bo_unmap(bo[0]);
457
458                 tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, bo, 1);
459         } else {
460                 tsurf = (tbm_surface_h)data;
461         }
462
463         if (tsurf) {
464                 media_packet_create_from_tbm_surface(core->output_fmt, tsurf,
465                                 (media_packet_finalize_cb)__mc_output_buffer_finalize_cb, mcbuffer, &packet);
466                 mcbuffer->packet = packet;
467         }
468
469         return MC_ERROR_NONE;
470 }
471
472 static int __mc_fill_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
473 {
474         gint ret = MC_ERROR_NONE;
475         gchar *ext_mem = NULL;
476         gint mem_size = 0;
477         void *packet_data = NULL;
478         media_packet_h packet = NULL;
479
480         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
481
482         if (core->encoder && core->codec_id == MEDIACODEC_AAC)
483                 media_format_set_audio_aac_type(core->output_fmt, FALSE);
484
485         mem_size = GST_ROUND_UP_4(size);
486         ext_mem = g_malloc0(mem_size);
487
488         ret = media_packet_create_from_external_memory(core->output_fmt, ext_mem, mem_size, __mc_output_buffer_finalize_cb, mcbuffer, &packet);
489         if (ret != MEDIA_PACKET_ERROR_NONE) {
490                 LOGW("media_packet_create_alloc failed");
491                 g_free(ext_mem);
492                 return MC_ERROR;
493         }
494         mcbuffer->packet = packet;
495         mcbuffer->ext_mem = ext_mem;
496
497         media_packet_set_buffer_size(packet, size);
498         media_packet_get_buffer_data_ptr(packet, &packet_data);
499         memcpy(packet_data, data, size);
500
501         return MC_ERROR_NONE;
502 }
503
504 static int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
505 {
506         gint ret = MC_ERROR_NONE;
507         bool codec_config = FALSE;
508         bool sync_flag = FALSE;
509         bool slice = FALSE;
510         gint mem_size = 0;
511         gchar *ext_mem = NULL;
512         gint data_size = 0;
513         void *packet_data = NULL;
514         media_packet_h packet = NULL;
515
516         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
517
518         switch (core->ports[out_port_index]->port_def.coding_type) {
519         case MEDIA_FORMAT_H264_SP:
520         case MEDIA_FORMAT_H264_MP:
521         case MEDIA_FORMAT_H264_HP:
522                 data_size = _mc_check_h264_bytestream((unsigned char *)data, size, 1, &codec_config, &sync_flag, &slice);
523
524                 if (data_size < 0) {
525                         LOGE("No valid SPS/PPS ...");
526                         return MC_INVALID_IN_BUF;
527                 }
528                 break;
529         case MEDIA_FORMAT_MPEG4_SP:
530         case MEDIA_FORMAT_MPEG4_ASP:
531                 _mc_check_mpeg4_out_bytestream((unsigned char *)data, size, &codec_config, &sync_flag);
532                 break;
533         case MEDIA_FORMAT_H263:
534         case MEDIA_FORMAT_H263P:
535                 if (!_mc_check_h263_out_bytestream((unsigned char *)data, size, &sync_flag))
536                         return MC_INVALID_IN_BUF;
537                 break;
538         default:
539                 return MC_INVALID_IN_BUF;
540         }
541         LOGD("codec_config : %d, sync_flag : %d, slice : %d", codec_config, sync_flag, slice);
542
543         mem_size = GST_ROUND_UP_4(size);
544         ext_mem = g_malloc0(mem_size);
545
546         ret = media_packet_create_from_external_memory(core->output_fmt, ext_mem, mem_size, __mc_output_buffer_finalize_cb, mcbuffer, &packet);
547         if (ret != MEDIA_PACKET_ERROR_NONE) {
548                 LOGW("media_packet_create_alloc failed");
549                 g_free(ext_mem);
550                 return MC_ERROR;
551         }
552         mcbuffer->packet = packet;
553         mcbuffer->ext_mem = ext_mem;
554
555         media_packet_set_buffer_size(packet, size);
556         media_packet_get_buffer_data_ptr(packet, &packet_data);
557         memcpy(packet_data, data, size);
558
559         core->need_sync_flag = sync_flag ? 1 : 0;
560         core->need_codec_data = codec_config ? 1 : 0;
561
562         return ret;
563 }
564
565 static int __mc_fill_aenc_packet_with_output_buffer(mc_gst_core_t *core, void *data, int size, GstMCBuffer *mcbuffer)
566 {
567         int ret = MC_ERROR_NONE;
568         gint mem_size = 0;
569         GstPad *pad;
570         GstCaps *peercaps;
571         GstMapInfo map;
572         guint8 *ptr;
573         gsize len;
574         gchar *ext_mem = NULL;
575         const GValue *codec_data = NULL;
576         void *packet_data = NULL;
577         media_packet_h packet = NULL;
578
579         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
580
581         if (core->encoder && core->codec_id == MEDIACODEC_AAC)
582                 media_format_set_audio_aac_type(core->output_fmt, FALSE);
583
584         mem_size = GST_ROUND_UP_4(size);
585         ext_mem = g_malloc0(mem_size);
586
587         ret = media_packet_create_from_external_memory(core->output_fmt, ext_mem, mem_size, __mc_output_buffer_finalize_cb, mcbuffer, &packet);
588         if (ret != MEDIA_PACKET_ERROR_NONE) {
589                 LOGW("media_packet_create_alloc failed");
590                 g_free(ext_mem);
591                 return MC_ERROR;
592         }
593         mcbuffer->packet = packet;
594         mcbuffer->ext_mem = ext_mem;
595
596         media_packet_set_buffer_size(packet, size);
597         media_packet_get_buffer_data_ptr(packet, &packet_data);
598         memcpy(packet_data, data, size);
599
600         if (!core->codec_data) {
601                 pad = gst_element_get_static_pad(core->fakesink, "sink");
602                 peercaps = gst_pad_get_current_caps(pad);
603                 if (peercaps) {
604                         GstStructure *s;
605                         if (gst_caps_is_empty(peercaps)) {
606                                 gst_caps_unref(peercaps);
607                                 gst_object_unref(pad);
608                                 LOGW("Empty caps");
609                                 return ret;
610                         }
611
612                         s = gst_caps_get_structure(peercaps, 0);
613                         codec_data = gst_structure_get_value(s, "codec_data");
614                         if (codec_data  == NULL && gst_structure_has_field(s, "streamheader"))
615                                 codec_data = gst_structure_get_value(s, "streamheader");
616
617                         core->codec_data = GST_BUFFER(g_value_dup_boxed(codec_data));
618                         gst_caps_unref(peercaps);
619                 }
620                 gst_object_unref(pad);
621                 LOGD("codec data set");
622         }
623
624         if (core->codec_data) {
625                 gst_buffer_map(core->codec_data, &map, GST_MAP_READ);
626                 ptr = map.data;
627                 len = map.size;
628                 ret = media_packet_set_codec_data(packet, ptr, len);
629                 if (ret != MEDIA_PACKET_ERROR_NONE) {
630                         LOGW("media_packet_set_codec_data failed");
631                         gst_buffer_unmap(core->codec_data, &map);
632                         return MC_ERROR;
633                 }
634                 gst_buffer_unmap(core->codec_data, &map);
635         }
636
637         return ret;
638 }
639
640 static GstCaps *__mc_gst_caps_set_buffer_array(GstCaps * caps, const gchar * name, GstBuffer * buf, ...)
641 {
642         GstStructure *struc = NULL;
643         va_list va;
644         GValue arr_val = { 0 };
645         GValue buf_val = { 0 };
646
647         g_return_val_if_fail(name != NULL, NULL);
648         g_return_val_if_fail(caps != NULL, NULL);
649         g_return_val_if_fail(gst_caps_is_fixed(caps), NULL);
650         caps = gst_caps_make_writable(caps);
651
652         struc = gst_caps_get_structure(caps, 0);
653         if (!struc)
654                 LOGW("cannot get structure from caps.\n");
655
656         g_value_init(&arr_val, GST_TYPE_ARRAY);
657
658         va_start(va, buf);
659         while (buf) {
660                 g_value_init(&buf_val, GST_TYPE_BUFFER);
661                 gst_value_set_buffer(&buf_val, buf);
662                 gst_value_array_append_value(&arr_val, &buf_val);
663                 g_value_unset(&buf_val);
664
665                 buf = va_arg(va, GstBuffer *);
666         }
667         va_end(va);
668
669         gst_structure_take_value(struc, name, &arr_val);
670
671         return caps;
672 }
673
674 int __mc_set_caps_streamheader(mc_gst_core_t *core, GstMCBuffer *mcbuffer, guint streamheader_size)
675 {
676         gint ret = MEDIA_PACKET_ERROR_NONE;
677         uint64_t buf_size = 0;
678         GstBuffer *header1, *header2, *header3;
679         guint hsize1, hsize2, hsize3;
680         GstBuffer *tmp_header;
681         GstMapInfo map;
682         guint8 *buf_data = NULL;
683         guint8 *tmp_buf = NULL;
684
685         ret = media_packet_get_buffer_size(mcbuffer->packet, &buf_size);
686         if (ret != MEDIA_PACKET_ERROR_NONE) {
687                 LOGW("buffer size get failed");
688                 return ret;
689         }
690
691         ret = media_packet_get_buffer_data_ptr(mcbuffer->packet, (void **)&buf_data);
692         if (ret != MEDIA_PACKET_ERROR_NONE) {
693                 LOGW("buffer data get failed");
694                 return ret;
695         }
696
697         LOGD("Set caps for streamheader in mime : %s and codec_id (0x%x)", core->mime, core->codec_id);
698
699         if (core->codec_id == MEDIACODEC_VORBIS) {
700                 /*
701                  * hsize1 : Identification Header (packet type 1) - fixed 30 byte
702                  * hsize2 : Comment Header (packet type 3) - variable byte (need calculate)
703                  * hsize3 : Setup Header (packet type 5) - variable byte (Used remained bytes)
704                  */
705
706                 /* First of all, Need to fins and calculate size of hsize2 */
707                 tmp_header = gst_buffer_new_and_alloc(streamheader_size);
708                 gst_buffer_fill(tmp_header, 0, buf_data, streamheader_size);
709                 gst_buffer_map(tmp_header, &map, GST_MAP_READ);
710                 tmp_buf = map.data;
711                 tmp_buf += (30 + 7);                /* hsize1 + '0x03' + 'vorbis'*/
712                 hsize2 = (7 + 4);
713                 hsize2 += GST_READ_UINT32_LE(tmp_buf);
714                 hsize2 += (4 + 1);
715                 LOGD("Find streamheader hsize2(%d)", hsize2);
716                 gst_buffer_unmap(tmp_header, &map);
717                 gst_buffer_unref(tmp_header);
718
719                 /*  hsize1 : Identification Header (packet type 1) - fixed 30 byte */
720                 hsize1 = 30;
721                 header1 = gst_buffer_new_and_alloc(hsize1);
722                 gst_buffer_fill(header1, 0, buf_data, hsize1);
723                 gst_buffer_map(header1, &map, GST_MAP_READ);
724                 tmp_buf = map.data;
725                 /* '0x01' + 'vorbis' */
726                 if (*tmp_buf != 0x01) {
727                         LOGE("[ERROR] Invalid Caps of Stream header1");
728                         gst_buffer_unmap(header1, &map);
729                         return MEDIA_PACKET_ERROR_INVALID_PARAMETER;
730                 }
731                 gst_buffer_unmap(header1, &map);
732
733                 /* hsize2 : Comment Header (packet type 3) - variable byte */
734                 header2 = gst_buffer_new_and_alloc(hsize2);
735                 gst_buffer_fill(header2, 0,  (buf_data + (hsize1)), hsize2);
736                 gst_buffer_map(header2, &map, GST_MAP_READ);
737                 tmp_buf = map.data;
738                 /* '0x03' + 'vorbis' */
739                 if (*tmp_buf != 0x03) {
740                         LOGE("[ERROR] Invalid Caps of Stream header2");
741                         gst_buffer_unmap(header2, &map);
742                         return MEDIA_PACKET_ERROR_INVALID_PARAMETER;
743                 }
744                 gst_buffer_unmap(header2, &map);
745
746                 /* hsize3 : Setup Header (packet type 5) - variable byte */
747                 hsize3 = streamheader_size - (hsize1 + hsize2);
748                 header3 = gst_buffer_new_and_alloc(hsize3);
749                 gst_buffer_fill(header3, 0,  (buf_data + (hsize1 + hsize2)), hsize3);
750                 gst_buffer_map(header3, &map, GST_MAP_READ);
751                 tmp_buf = map.data;
752                 /* '0x05' + 'vorbis' */
753                 if (*tmp_buf != 0x05) {
754                         LOGE("[ERROR] Invalid Caps of Stream header3");
755                         gst_buffer_unmap(header3, &map);
756                         return MEDIA_PACKET_ERROR_INVALID_PARAMETER;
757                 }
758                 gst_buffer_unmap(header3, &map);
759
760                 LOGD("[vorbis] streamheader hsize1 (%d) + hsize2 (%d) + hsize3 (%d) = Total (%d)",
761                                 hsize1, hsize2, hsize3, (hsize1 + hsize2 + hsize3));
762
763                 __mc_gst_caps_set_buffer_array(core->caps, "streamheader", header1, header2, header3, NULL);
764
765                 gst_buffer_unref(header1);
766                 gst_buffer_unref(header2);
767                 gst_buffer_unref(header3);
768         } else if (core->codec_id == MEDIACODEC_FLAC) {
769                 /*
770                  * hsize1 : Stream Info (type 0) - fixed 51 byte
771                  * hsize2 : Stream Comment (type 4) - variable byte (need calculate)
772                  */
773
774                 /* First of all, Need to fins and calculate size of hsize2 */
775                 tmp_header = gst_buffer_new_and_alloc(streamheader_size);
776                 gst_buffer_fill(tmp_header, 0, buf_data, streamheader_size);
777                 gst_buffer_map(tmp_header, &map, GST_MAP_READ);
778                 tmp_buf = map.data;
779                 hsize2 = 4 + ((tmp_buf[52] << 16) | (tmp_buf[53] << 8) | (tmp_buf[54]));
780                 LOGD("Find streamheader hsize2(%d)", hsize2);
781                 gst_buffer_unmap(tmp_header, &map);
782                 gst_buffer_unref(tmp_header);
783
784                 /*  hsize1 :  Stream Info (type 0) - fixed 51 byte */
785                 hsize1 = 51;
786                 header1 = gst_buffer_new_and_alloc(hsize1);
787                 gst_buffer_fill(header1, 0, buf_data, hsize1);
788                 gst_buffer_map(header1, &map, GST_MAP_READ);
789                 tmp_buf = map.data;
790                 /* '0x7f' + 'FLAC' */
791                 if (*tmp_buf != 0x07f) {
792                         LOGE("[ERROR] Invalid Caps of Stream header1 (Info)");
793                         gst_buffer_unmap(header1, &map);
794                         gst_buffer_unref(header1);
795                         return MEDIA_PACKET_ERROR_INVALID_PARAMETER;
796                 }
797                 gst_buffer_unmap(header1, &map);
798
799                 /* hsize2 : Stream Comment (type 4) - variable byte (need calculate) */
800                 header2 = gst_buffer_new_and_alloc(hsize2);
801                 gst_buffer_fill(header2, 0, (buf_data + (hsize1)), hsize2);
802                 gst_buffer_map(header2, &map, GST_MAP_READ);
803                 tmp_buf = map.data;
804                 /* '0x84' */
805                 if (*tmp_buf != 0x84) {
806                         LOGE("[ERROR] Invalid Caps of Stream header2 (Comment)");
807                         gst_buffer_unmap(header2, &map);
808                         gst_buffer_unref(header1);
809                         gst_buffer_unref(header2);
810                         return MEDIA_PACKET_ERROR_INVALID_PARAMETER;
811                 }
812                 gst_buffer_unmap(header2, &map);
813
814                 LOGD("[flac] streamheader hsize1 (%d) + hsize2 (%d)  = Total (%d)", hsize1, hsize2, (hsize1 + hsize2));
815                 __mc_gst_caps_set_buffer_array(core->caps, "streamheader", header1, header2, NULL);
816                 gst_buffer_unref(header1);
817                 gst_buffer_unref(header2);
818         } else if (core->codec_id == MEDIACODEC_OPUS) {
819                 const GstTagList *tags;
820                 GstTagList *empty_tags = NULL;
821                 GstBuffer *header, *comments;
822                 guint8 *decoding_channel_mapping = NULL;
823                 mc_gst_port_def_t *port_def = &core->ports[in_port_index]->port_def;
824
825                 header = gst_codec_utils_opus_create_header(port_def->info.audio.samplerate,
826                         port_def->info.audio.channel,
827                         0, /* channel mapping family */
828                         1, /* stream count */
829                         0, /* coupled count */
830                         decoding_channel_mapping,
831                         0, /* FIXME: look ahead configured value */
832                         0);
833                 tags = gst_tag_setter_get_tag_list(GST_TAG_SETTER(core->codec));
834                 if (!tags)
835                         tags = empty_tags = gst_tag_list_new_empty();
836                 comments = gst_tag_list_to_vorbiscomment_buffer(tags, (const guint8 *) "OpusTags",
837                         8, "Encoded with GStreamer opusenc");
838                 core->caps = gst_codec_utils_opus_create_caps_from_header(header, comments);
839                 if (empty_tags)
840                         gst_tag_list_unref(empty_tags);
841                 gst_buffer_unref(header);
842                 gst_buffer_unref(comments);
843         } else {
844                 LOGE("Not support case of Stream header Caps");
845         }
846
847         /* Update gstbuffer's data ptr and size for using previous streamheader.*/
848         LOGD("BEFORE : mcbuffer->buffer of size %" G_GSIZE_FORMAT "", gst_buffer_get_size(mcbuffer->buffer));
849         gst_buffer_remove_memory_range(mcbuffer->buffer, streamheader_size, -1);
850         gst_buffer_set_size(mcbuffer->buffer, buf_size - streamheader_size);
851         LOGD("AFTER  : mcbuffer->buffer of size %" G_GSIZE_FORMAT "",  gst_buffer_get_size(mcbuffer->buffer));
852
853         return ret;
854 }
855
856 int __mc_set_caps_codecdata(mc_gst_core_t *core, GstMCBuffer *mcbuffer, guint fixed_size)
857 {
858         gint ret = MC_ERROR_NONE;
859         uint32_t codec_data_size = 0;
860         GstMapInfo map;
861         GstBuffer *codecdata_buffer;
862         guint8 *data = NULL;
863         void *codec_data = NULL;
864
865         media_packet_get_codec_data(mcbuffer->packet, &codec_data, &codec_data_size);
866
867         if (codec_data != NULL) {               /* get the codec data from media_packet_get_codec_data() */
868                 data = g_malloc0(codec_data_size);
869
870                 memcpy(data, codec_data, codec_data_size);
871
872                 free(codec_data);
873                 codec_data = NULL;
874
875                 codecdata_buffer = gst_buffer_new_wrapped(data, codec_data_size);
876                 gst_caps_set_simple(core->caps, "codec_data", GST_TYPE_BUFFER, codecdata_buffer, NULL);
877
878                 LOGD("set codec data : %" G_GSIZE_FORMAT "", gst_buffer_get_size(codecdata_buffer));
879
880                 gst_buffer_unref(codecdata_buffer);
881         } else {                                        /* get the codec data from media_packet_get_buffer_data_ptr() */
882                 uint64_t buffer_size = 0;
883                 void *buff_data = NULL;
884
885                 media_packet_get_buffer_size(mcbuffer->packet, &buffer_size);
886                 media_packet_get_buffer_data_ptr(mcbuffer->packet, &buff_data);
887
888                 /* For audio, it's necessary to change the offset value of buffer after extracting csd */
889                 /* it's not necessary to set csd to caps in case of annex-b */
890                 if (buffer_size > fixed_size) {
891                         data = g_malloc0(fixed_size);
892                         gst_buffer_map(mcbuffer->buffer, &map, GST_MAP_READ);
893                         memcpy(data, map.data, fixed_size);
894                         codecdata_buffer = gst_buffer_new_wrapped(data, fixed_size);
895                         gst_caps_set_simple(core->caps, "codec_data", GST_TYPE_BUFFER, codecdata_buffer, NULL);
896                         gst_buffer_unref(codecdata_buffer);
897
898                         gst_buffer_replace_memory(mcbuffer->buffer, 0,
899                                         gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, map.data + fixed_size , buffer_size - fixed_size, 0,
900                                                 buffer_size - fixed_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb));
901
902                         LOGD("after : set codec data from packet: %" G_GSIZE_FORMAT "",  gst_buffer_get_size(mcbuffer->buffer));
903                         gst_buffer_unmap(mcbuffer->buffer, &map);
904                 }
905         }
906         return ret;
907 }
908
909 int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, media_format_mimetype_e out_mime)
910 {
911         if (media_format_create(&core->output_fmt) != MEDIA_FORMAT_ERROR_NONE) {
912                 LOGE("media format create failed");
913                 return MC_ERROR;
914         }
915         mc_gst_port_def_t *port_def = &core->ports[out_port_index]->port_def;
916
917         if (video) {
918                 media_format_set_video_mime(core->output_fmt, out_mime);
919                 media_format_set_video_width(core->output_fmt, port_def->info.video.width);
920                 media_format_set_video_height(core->output_fmt, port_def->info.video.height);
921
922                 if (encoder)
923                         media_format_set_video_avg_bps(core->output_fmt, port_def->info.video.bitrate);
924         } else {
925                 media_format_set_audio_mime(core->output_fmt, out_mime);
926                 media_format_set_audio_channel(core->output_fmt, port_def->info.audio.channel);
927                 media_format_set_audio_samplerate(core->output_fmt, port_def->info.audio.samplerate);
928                 media_format_set_audio_bit(core->output_fmt, port_def->info.audio.bit_depth);
929
930                 if (encoder)
931                         media_format_set_audio_avg_bps(core->output_fmt, port_def->info.audio.bitrate);
932         }
933
934         return MC_ERROR_NONE;
935 }
936
937 /*
938  * mc_gst_core functions
939  */
940 static mc_gst_core_t *mc_gst_core_new()
941 {
942         mc_gst_core_t *core;
943
944         MEDIACODEC_FENTER();
945
946         core = g_new0(mc_gst_core_t, 1);
947
948         /* 0 : input, 1 : output */
949         core->ports[0] = mc_gst_port_new(core);
950         core->ports[0]->index = 0;
951         core->ports[1] = mc_gst_port_new(core);
952         core->ports[1]->index = 1;
953
954         core->available_queue = g_new0(mc_aqueue_t, 1);
955         core->available_queue->input = mc_async_queue_new();
956
957         g_mutex_init(&core->eos_mutex);
958         g_cond_init(&core->eos_cond);
959         g_cond_init(&core->buffer_cond);
960         g_cond_init(&core->out_buffer_cond);
961         g_mutex_init(&core->prepare_lock);
962         g_mutex_init(&core->drain_lock);
963
964         core->need_drain = false;
965         core->need_feed = false;
966         core->eos = false;
967         core->need_codec_data = false;
968         core->need_sync_flag = false;
969         core->unprepare_flag = false;
970         core->prepare_count = 0;
971         core->etb_count = 0;
972         core->codec_data = NULL;
973         core->allocator = gst_tizen_allocator_new();
974
975         core->bufmgr = NULL;
976         core->drm_fd = -1;
977
978         LOGD("gst_core(%p) is created", core);
979
980         MEDIACODEC_FLEAVE();
981
982         return core;
983 }
984
985 static void mc_gst_core_free(mc_gst_core_t *core)
986 {
987         MEDIACODEC_FENTER();
988
989         g_mutex_clear(&core->eos_mutex);
990         g_mutex_clear(&core->prepare_lock);
991         g_mutex_clear(&core->drain_lock);
992         g_cond_clear(&core->eos_cond);
993         g_cond_clear(&core->buffer_cond);
994         g_cond_clear(&core->out_buffer_cond);
995
996         mc_async_queue_free(core->available_queue->input);
997         g_free(core->available_queue);
998         core->available_queue = NULL;
999
1000         if (core->allocator) {
1001                 gst_object_unref(core->allocator);
1002                 core->allocator = NULL;
1003         }
1004
1005         if (core->codec_data)
1006                 gst_buffer_unref(core->codec_data);
1007
1008         if (core->ports[0] != NULL) {
1009                 mc_gst_port_free(core->ports[0]);
1010                 core->ports[0] = NULL;
1011         }
1012
1013         if (core->ports[1] != NULL) {
1014                 mc_gst_port_free(core->ports[1]);
1015                 core->ports[1] = NULL;
1016         }
1017
1018         LOGD("gst_core(%p) destroyed", core);
1019         g_free(core);
1020
1021         MEDIACODEC_FLEAVE();
1022 }
1023
1024 /*
1025  * mc_gst_port functions
1026  */
1027 static mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core)
1028 {
1029         MEDIACODEC_FENTER();
1030
1031         mc_gst_port_t *port;
1032
1033         port = g_new0(mc_gst_port_t, 1);
1034         port->core = core;
1035         port->num_buffers = -1;
1036         port->buffer_size = 0;
1037         port->is_allocated = 0;
1038
1039         g_mutex_init(&port->mutex);
1040         port->queue = g_queue_new();
1041
1042         LOGD("gst_port(%p) created", port);
1043
1044         MEDIACODEC_FLEAVE();
1045         return port;
1046 }
1047
1048 static void mc_gst_port_free(mc_gst_port_t *port)
1049 {
1050         MEDIACODEC_FENTER();
1051
1052         g_mutex_clear(&port->mutex);
1053         g_queue_free(port->queue);
1054
1055         LOGD("gst_port(%p) freed", port);
1056         g_free(port);
1057
1058         MEDIACODEC_FLEAVE();
1059
1060         return;
1061 }
1062
1063 gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format)
1064 {
1065         int ret = MEDIA_FORMAT_ERROR_NONE;
1066         gint bitrate = 0;
1067         gboolean is_format_change = FALSE;
1068
1069         mc_gst_port_def_t *input_port_def = &core->ports[in_port_index]->port_def;
1070
1071         if (core->video) {
1072                 gint width = 0;
1073                 gint height = 0;
1074                 gint framerate = 0;
1075                 gchar *sformat = NULL;
1076                 media_format_mimetype_e mimetype = 0;
1077
1078                 ret = media_format_get_video_info(format, &mimetype, &width, &height, &bitrate, NULL);
1079                 ret |= media_format_get_video_frame_rate(format, &framerate);
1080                 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1081                         LOGE("get video info/frame_rate failed[0x%x]", ret);
1082                         return FALSE;
1083                 }
1084
1085                 is_format_change |= input_port_def->info.video.width != width;
1086                 is_format_change |= input_port_def->info.video.height != height;
1087                 is_format_change |= ((input_port_def->info.video.framerate != framerate) && (framerate != 0));
1088                 if (is_format_change) {
1089                         LOGD("Format changed : resolution %dx%d -> %dx%d, framerate %d -> %d",
1090                                 input_port_def->info.video.width, input_port_def->info.video.height, width, height,
1091                                 input_port_def->info.video.framerate, framerate);
1092                         input_port_def->info.video.width = width;
1093                         input_port_def->info.video.height = height;
1094                 }
1095
1096                 if (core->encoder) {
1097                         bitrate *= 1000;
1098                         sformat = __mc_get_gst_input_format(mimetype, core->is_hw);
1099                         is_format_change |= ((input_port_def->info.video.bitrate != bitrate) && (bitrate != 0));
1100                         is_format_change |= g_strcmp0(input_port_def->info.video.format, sformat);
1101                         if (is_format_change) {
1102                                 if (bitrate != 0) {
1103                                         LOGD("Bitrate changed : %d -> %d", input_port_def->info.video.bitrate, bitrate);
1104                                         input_port_def->info.video.bitrate = bitrate;
1105                                 }
1106                                 LOGD("Format changed : %s -> %s", input_port_def->info.video.format, sformat);
1107                                 input_port_def->info.video.format = g_strdup(sformat);
1108                         }
1109                 }
1110         } else {
1111                 gint channel;
1112                 gint samplerate;
1113                 gint bit;
1114
1115                 ret = media_format_get_audio_info(format, NULL, &channel, &samplerate, &bit, &bitrate);
1116                 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1117                         LOGE("get audio info failed[0x%x]", ret);
1118                         return FALSE;
1119                 }
1120
1121                 is_format_change |= input_port_def->info.audio.channel != channel;
1122                 is_format_change |= input_port_def->info.audio.samplerate != samplerate;
1123                 is_format_change |= input_port_def->info.audio.bit_depth != bit;
1124                 if (is_format_change) {
1125                         LOGD("Audio info. changed : %d -> %d, %d -> %d, %d -> %d",
1126                                 input_port_def->info.audio.channel, channel,
1127                                 input_port_def->info.audio.samplerate, samplerate,
1128                                 input_port_def->info.audio.bit_depth, bit);
1129                         input_port_def->info.audio.channel = channel;
1130                         input_port_def->info.audio.samplerate = samplerate;
1131                         input_port_def->info.audio.bit_depth = bit;
1132                 }
1133
1134                 if (core->encoder) {
1135                         bitrate *= 1000;
1136                         is_format_change |= ((input_port_def->info.audio.bitrate != bitrate) && (bitrate != 0));
1137                         if (is_format_change) {
1138                                 LOGD("Bitrate changed : %d -> %d", input_port_def->info.audio.bitrate, bitrate);
1139                                 input_port_def->info.audio.bitrate = bitrate;
1140                         }
1141                 }
1142         }
1143
1144         return is_format_change;
1145 }
1146
1147 static gboolean _mc_gst_video_info_check_and_new(mc_gst_core_t *core, GstMCBuffer *mcbuffer)
1148 {
1149         int i = 0;
1150         gchar *caps_str = NULL;
1151         tbm_surface_h surface = NULL;
1152         tbm_surface_info_s sinfo = {0, };
1153
1154         if (!core || !mcbuffer) {
1155                 LOGE("NULL core[%p] or mcbuffer[%p]", core, mcbuffer);
1156                 return FALSE;
1157         }
1158
1159         if (!core->video_info) {
1160                 caps_str = gst_caps_to_string(core->caps);
1161
1162                 LOGI("caps[%s] to video info", caps_str);
1163
1164                 g_free(caps_str);
1165
1166                 core->video_info = gst_video_info_new_from_caps(core->caps);
1167                 if (!core->video_info) {
1168                         LOGE("video info failed");
1169                         return FALSE;
1170                 }
1171
1172                 if (media_packet_get_tbm_surface(mcbuffer->packet, &surface) != MEDIA_PACKET_ERROR_NONE) {
1173                         LOGE("get surface failed");
1174                         return FALSE;
1175                 }
1176
1177                 if (tbm_surface_get_info(surface, &sinfo) != TBM_SURFACE_ERROR_NONE) {
1178                         LOGE("get surface info failed");
1179                         return FALSE;
1180                 }
1181
1182                 for (i = 0 ; i < sinfo.num_planes ; i++) {
1183                         GST_VIDEO_INFO_PLANE_OFFSET(core->video_info, i) = sinfo.planes[i].offset;
1184                         GST_VIDEO_INFO_PLANE_STRIDE(core->video_info, i) = sinfo.planes[i].stride;
1185
1186                         LOGI("[%d] offset[%zu], stride[%d]", i,
1187                                 GST_VIDEO_INFO_PLANE_OFFSET(core->video_info, i),
1188                                 GST_VIDEO_INFO_PLANE_STRIDE(core->video_info, i));
1189                 }
1190
1191                 LOGI("new video info[%p]", core->video_info);
1192         }
1193
1194         return TRUE;
1195 }
1196
1197 static void _mc_gst_video_info_free(mc_gst_core_t *core)
1198 {
1199         if (!core)
1200                 return;
1201
1202         if (core->video_info) {
1203                 LOGI("free video info[%p]", core->video_info);
1204                 gst_video_info_free(core->video_info);
1205                 core->video_info = NULL;
1206         }
1207 }
1208
1209 static void _mc_gst_video_meta_add(mc_gst_core_t *core, GstBuffer *buffer)
1210 {
1211         GstVideoMeta *vmeta = NULL;
1212
1213         if (!core || !core->video_info || !buffer)
1214                 return;
1215
1216         vmeta = gst_buffer_add_video_meta_full(buffer, GST_VIDEO_FRAME_FLAG_NONE,
1217                 GST_VIDEO_INFO_FORMAT(core->video_info),
1218                 GST_VIDEO_INFO_WIDTH(core->video_info),
1219                 GST_VIDEO_INFO_HEIGHT(core->video_info),
1220                 GST_VIDEO_INFO_N_PLANES(core->video_info),
1221                 core->video_info->offset,
1222                 core->video_info->stride);
1223
1224         if (!vmeta) {
1225                 LOGE("No video meta");
1226                 return;
1227         }
1228
1229         if (core->is_hw) {
1230                 vmeta->map = gst_tizen_video_meta_map;
1231                 vmeta->unmap = gst_tizen_video_meta_unmap;
1232         }
1233 }
1234
1235 static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool codec_config)
1236 {
1237         MEDIACODEC_FENTER();
1238
1239         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
1240         g_return_val_if_fail(mcbuffer != NULL, MC_PARAM_ERROR);
1241
1242         int ret = MC_ERROR_NONE;
1243
1244         switch (core->codec_id) {
1245         case MEDIACODEC_AAC:
1246         case MEDIACODEC_AAC_HE:
1247         case MEDIACODEC_AAC_HE_PS:
1248                 if (codec_config) {
1249                         ret = __mc_set_caps_codecdata(core, mcbuffer, AAC_CODECDATA_SIZE);
1250                         if (ret != MC_ERROR_NONE)
1251                                 LOGW("__mc_set_caps_codecdata failed");
1252                 }
1253                 break;
1254         case MEDIACODEC_WMAV1:
1255         case MEDIACODEC_WMAV2:
1256         case MEDIACODEC_WMAPRO:
1257         case MEDIACODEC_WMALSL:
1258                 if (codec_config) {
1259                         ret = __mc_set_caps_codecdata(core, mcbuffer, WMA_CODECDATA_SIZE);
1260                         if (ret != MC_ERROR_NONE)
1261                                 LOGW("__mc_set_caps_codecdata failed");
1262                 }
1263                 break;
1264         case MEDIACODEC_VORBIS:
1265         case MEDIACODEC_FLAC:
1266         case MEDIACODEC_OPUS:
1267                 if (codec_config) {
1268                         ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE);
1269                         if (ret != MC_ERROR_NONE)
1270                                 LOGW("__mc_set_caps_streamheader failed");
1271                 }
1272                 break;
1273         case MEDIACODEC_H264:
1274         case MEDIACODEC_MPEG4:
1275                 ret = __mc_set_caps_codecdata(core, mcbuffer, CODECDATA_NOT_USE);
1276                 if (ret != MC_ERROR_NONE)
1277                         LOGW("__mc_set_caps_codecdata failed");
1278                 break;
1279         default:
1280                 LOGD("doesn't need to set codecdata");
1281                 break;
1282         }
1283
1284         MEDIACODEC_FLEAVE();
1285         return ret;
1286
1287
1288 }
1289
1290 static gpointer feed_task(gpointer data)
1291 {
1292         gint ret = MC_ERROR_NONE;
1293         bool codec_config = FALSE;
1294         bool eos = FALSE;
1295         bool initiative = TRUE;
1296         bool is_format_change = FALSE;
1297         media_format_h format = NULL;
1298         media_packet_h input_buffer = NULL;
1299         GstMCBuffer *mcbuffer = NULL;
1300
1301         MEDIACODEC_FENTER();
1302
1303         mc_gst_core_t *core = (mc_gst_core_t *)data;
1304
1305         while (g_atomic_int_get(&core->available_queue->running)) {
1306                 LOGD("waiting for next input....");
1307                 input_buffer = _mc_get_input_buffer(core);
1308                 if (!input_buffer)
1309                         goto LEAVE;
1310
1311                 media_packet_get_format(input_buffer,  &format);
1312                 if (format) {
1313                         if (_mc_update_packet_info(core, format)) {
1314                                 is_format_change = TRUE;
1315                                 if (!core->mc_caps_new(core, core->codec_id, in_port_index)) {
1316                                         LOGE("caps new failed");
1317                                         goto ERROR;
1318                                 }
1319                         }
1320                         media_format_unref(format);
1321                 }
1322
1323                 if (media_packet_is_codec_config(input_buffer, &codec_config) != MEDIA_PACKET_ERROR_NONE) {
1324                         LOGE("media_packet_is_codec_config failed");
1325                         goto ERROR;
1326                 }
1327
1328                 if (media_packet_is_end_of_stream(input_buffer, &eos) != MEDIA_PACKET_ERROR_NONE) {
1329                         LOGE("media_packet_is_end_of_stream failed");
1330                         goto ERROR;
1331                 }
1332                 /*
1333                  * receive an eos packet. For decoder + encoder case, encoder always get tbm surface plane first from input data,
1334                  * but eos packet only has flag not valid data, so we don't put it to downstream.
1335                  */
1336                 if (eos) {
1337                         LOGD("end of stream");
1338                         gst_app_src_end_of_stream(GST_APP_SRC(core->appsrc));
1339                         _mc_wait_for_eos(core);
1340                         initiative = TRUE;
1341
1342                         _mc_gst_handle_input_buffer_used(core, input_buffer);
1343                         goto LEAVE;
1344                 }
1345
1346                 mcbuffer = _mc_gst_media_packet_to_gstbuffer(core, input_buffer, codec_config);
1347                 if (!mcbuffer) {
1348                         LOGW("gstbuffer can't make");
1349                         goto ERROR;
1350                 }
1351                 /* mcbuffer took the ownership of the input_buffer, so set input_buffer to NULL to aviod double unref */
1352                 input_buffer = NULL;
1353
1354                 if (codec_config || initiative) {
1355                         GstPad *pad = NULL;
1356                         if (!core->encoder) {
1357                                 ret = _mc_set_codec_data(core, mcbuffer, codec_config);
1358                                 if (ret != MC_ERROR_NONE) {
1359                                         LOGE("failed to set codec data");
1360                                         gst_buffer_unref(mcbuffer->buffer);
1361                                         goto ERROR;
1362                                 }
1363                         }
1364                         pad = gst_element_get_static_pad(core->appsrc, "src");
1365                         gst_pad_push_event(pad, gst_event_new_stream_start("start"));
1366                         gst_object_unref(pad);
1367                         is_format_change = TRUE;
1368                         initiative = FALSE;
1369                         core->offset = GST_BUFFER_OFFSET_NONE;
1370                 }
1371
1372                 if (is_format_change) {
1373                         g_object_set(core->appsrc, "caps", core->caps, NULL);
1374
1375                         if (core->encoder) {
1376                                 int bitrate = core->video ? \
1377                                         core->ports[in_port_index]->port_def.info.video.bitrate : \
1378                                         core->ports[in_port_index]->port_def.info.audio.bitrate;
1379
1380                                 g_object_set(core->codec, core->codec_type->property->bitrate_name, bitrate, NULL);
1381
1382                                 LOGI("bitrate[property:%s,v:%d] %d updated",
1383                                         core->codec_type->property->bitrate_name, core->video, bitrate);
1384                         }
1385
1386                         is_format_change = FALSE;
1387                 }
1388
1389
1390                 /* inject buffer */
1391                 ret = _mc_gst_gstbuffer_to_appsrc(core, mcbuffer);
1392                 if (ret != GST_FLOW_OK) {
1393                         LOGE("Failed to push gst buffer");
1394                         goto ERROR;
1395                 }
1396
1397                 continue;
1398 ERROR:
1399                 if (input_buffer)
1400                         _mc_gst_handle_input_buffer_used(core, input_buffer);
1401
1402                 _mc_gst_set_flush_input(core);
1403
1404                 if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) {
1405                         ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR])
1406                                 (MC_INTERNAL_ERROR, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]);
1407                 }
1408
1409                 continue;
1410 LEAVE:
1411                 /*LOGE("status : input_buffer : %p, codec_config : %d, eos : %d, encoder : %d in feed_task", input_buffer, codec_config, eos, core->encoder);*/
1412                 continue;
1413
1414         }
1415
1416         LOGI("status : input_buffer : %p, codec_config : %d, eos : %d, video : %d, encoder : %d in feed_task",
1417                         input_buffer, codec_config, eos, core->video, core->encoder);
1418         LOGD("feed task finished %p v(%d)e(%d)", core, core->video, core->encoder);
1419
1420         MEDIACODEC_FLEAVE();
1421
1422         return NULL;
1423 }
1424
1425 static void _mc_gst_feed_task_new(mc_gst_core_t *core)
1426 {
1427         g_return_if_fail(core && core->available_queue);
1428
1429         g_atomic_int_set(&core->available_queue->running, 1);
1430         core->available_queue->thread = g_thread_new("feed thread", &feed_task, core);
1431
1432         LOGI("new thread for feed[%p]", core->available_queue->thread);
1433 }
1434
1435 static void _mc_gst_feed_task_free(mc_gst_core_t *core)
1436 {
1437         g_return_if_fail(core && core->available_queue);
1438
1439         mc_async_queue_disable(core->available_queue->input);
1440
1441         g_atomic_int_set(&core->available_queue->running, 0);
1442         g_thread_join(core->available_queue->thread);
1443
1444         LOGI("feed thread[%p] is released", core->available_queue->thread);
1445 }
1446
1447 static void __mc_gst_stop_feed(GstElement *pipeline, gpointer data)
1448 {
1449         mc_gst_core_t *core = (mc_gst_core_t *)data;
1450
1451         LOGI("stop_feed called");
1452         if (core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) {
1453                 ((mc_buffer_status_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS])
1454                         (MEDIACODEC_ENOUGH_DATA, core->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]);
1455         }
1456 }
1457
1458 static void __mc_gst_start_feed(GstElement *pipeline, guint size, gpointer data)
1459 {
1460         mc_gst_core_t *core = (mc_gst_core_t *)data;
1461
1462         LOGI("start_feed called");
1463
1464         if (core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) {
1465                 ((mc_buffer_status_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS])
1466                         (MEDIACODEC_NEED_DATA, core->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]);
1467         }
1468 }
1469
1470 static gboolean _mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index)
1471 {
1472         gchar *caps_string = NULL;
1473         g_autoptr(GstCaps) caps = NULL;
1474         mc_gst_port_def_t *port_def = &core->ports[index]->port_def;
1475
1476         caps = gst_caps_new_simple(core->mime,
1477                 "rate", G_TYPE_INT, port_def->info.audio.samplerate,
1478                 "channels", G_TYPE_INT, port_def->info.audio.channel, NULL);
1479
1480         switch (codec_id) {
1481         case MEDIACODEC_AAC:
1482                 if (core->encoder) {
1483                         gst_caps_set_simple(caps,
1484                                 "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth),
1485                                 "layout", G_TYPE_STRING, "interleaved", NULL);
1486                         g_object_set(GST_OBJECT(core->codec), "compliance", -2, NULL);
1487                 } else {
1488                         gst_caps_set_simple(caps,
1489                                 "framed", G_TYPE_BOOLEAN, TRUE,
1490                                 "mpegversion", G_TYPE_INT, 4,
1491                                 "stream-format", G_TYPE_STRING, "adts",
1492                                 NULL);
1493                         LOGD("CAPS for codec_id (MEDIACODEC_AAC_LC - normal ADTS)");
1494                 }
1495                 break;
1496         case MEDIACODEC_AAC_HE:
1497         case MEDIACODEC_AAC_HE_PS:
1498                 if (core->encoder) {
1499                         LOGD("[MC_NOT_SUPPORTED] he-aac-v12 encoder is not supported yet!!!");
1500                         return FALSE;
1501                 } else {
1502                         gst_caps_set_simple(caps,
1503                                 "mpegversion", G_TYPE_INT, 4,
1504                                 "framed", G_TYPE_BOOLEAN, TRUE,
1505                                 "stream-format", G_TYPE_STRING, "raw",
1506                                 NULL);
1507                         LOGD("CAPS for codec_id (MEDIACODEC_AAC_HE)");
1508                 }
1509                 break;
1510         case MEDIACODEC_MP3:
1511                 if (core->encoder) {
1512                         LOGD("[MC_NOT_SUPPORTED] mp3 encoder is not supported yet!!!");
1513                         return FALSE;
1514                 } else {
1515                         gst_caps_set_simple(caps,
1516                                 "framed", G_TYPE_BOOLEAN, TRUE,
1517                                 "mpegversion", G_TYPE_INT, 1,       /* To-Do : plz check */
1518                                 "mpegaudioversion", G_TYPE_INT, 1,  /* To-Do : plz check */
1519                                 "layer", G_TYPE_INT, 3,             /* To-Do : plz check */
1520                                 NULL);
1521                         LOGD("CAPS for codec_id (MEDIACODEC_MP3)");
1522                 }
1523                 break;
1524         case MEDIACODEC_AMR_NB:
1525                 if (core->encoder) {
1526                         gst_caps_set_simple(caps,
1527                                 "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth),
1528                                 "layout", G_TYPE_STRING, "interleaved",
1529                                 NULL);
1530                         LOGD("CAPS for codec_id (MEDIACODEC_AMR_NB)");
1531                 } else {
1532                         gst_caps_set_simple(caps,
1533                                 "rate", G_TYPE_INT, 8000,
1534                                 NULL);
1535                 }
1536                 break;
1537         case MEDIACODEC_AMR_WB:
1538                 if (core->encoder) {
1539                         LOGD("[MC_NOT_SUPPORTED] amr-wb encoder is not supported yet!!!");
1540                         return FALSE;
1541                 } else {
1542                         gst_caps_set_simple(caps,
1543                                 "rate", G_TYPE_INT, 16000,
1544                                 NULL);
1545                 }
1546                 break;
1547         case MEDIACODEC_VORBIS:
1548                 if (core->encoder) {
1549                         LOGD("[MC_NOT_SUPPORTED] vorbis encoder is not supported yet!!!");
1550                         return FALSE;
1551                 } else {
1552                 }
1553                 break;
1554         case MEDIACODEC_FLAC:
1555                 if (core->encoder) {
1556                         LOGD("[MC_NOT_SUPPORTED] flac encoder is not supported yet!!!");
1557                         return FALSE;
1558                 } else {
1559                         gst_caps_set_simple(caps,
1560                                 "framed", G_TYPE_BOOLEAN, TRUE,
1561                                 /* FIXME - Insert More Info */
1562                                 NULL);
1563                 }
1564                 break;
1565         case MEDIACODEC_WMAV1:
1566         case MEDIACODEC_WMAV2:
1567         case MEDIACODEC_WMAPRO:
1568         case MEDIACODEC_WMALSL:
1569                 if (core->encoder) {
1570                         LOGD("[MC_NOT_SUPPORTED] wma encoder is not supported yet!!!");
1571                         return FALSE;
1572                 } else {
1573                         /*
1574                          * Need to extract from Stream Type Specific ... or
1575                          * Need to get Demuxer's Caps from Stream Type Specific
1576                          */
1577                         guint16 format_tag = 0;
1578                         gint wma_version = 0;
1579                         gint block_align = 1024;      /*FIXME : Need checking */
1580                         gint bitrate = 128000;        /*FIXME : Need checking */
1581
1582                         LOGD(" ----- WMA Need Additional Caps -----------");
1583                         if (core->codec_id == MEDIACODEC_WMAV1) {
1584                                 format_tag = 352;       /* 0x160 */
1585                                 wma_version = 1;
1586                         } else if (core->codec_id == MEDIACODEC_WMAV2) {
1587                                 format_tag = 353;       /* 0x161 */
1588                                 wma_version = 2;
1589                         } else if (core->codec_id == MEDIACODEC_WMAPRO) {
1590                                 format_tag = 354;       /* 0x162 */
1591                                 wma_version = 3;
1592                         } else if (core->codec_id == MEDIACODEC_WMALSL) {
1593                                 format_tag = 355;       /* 0x163 */
1594                                 wma_version = 3;
1595                         } else {
1596                                 LOGE("Not support WMA format");
1597                         }
1598
1599                         gst_caps_set_simple(caps,
1600                                 "bitrate", G_TYPE_INT, bitrate,
1601                                 "depth", G_TYPE_INT, port_def->info.audio.bit_depth,
1602                                 /* FIXME - Need More Info */
1603                                 "wmaversion", G_TYPE_INT, wma_version,
1604                                 "format_tag", G_TYPE_INT, format_tag,
1605                                 "block_align", G_TYPE_INT, block_align,
1606                                 NULL);
1607                 }
1608                 break;
1609         case MEDIACODEC_OPUS:
1610                 if (core->encoder) {
1611                         gst_caps_set_simple(caps,
1612                                 "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth),
1613                                 "layout", G_TYPE_STRING, "interleaved", NULL);
1614                 } else {
1615                         LOGD("[MC_NOT_SUPPORTED] opus decoder is not supported yet!!!");
1616                         return FALSE;
1617                 }
1618                 break;
1619         default:
1620                 break;
1621         }
1622
1623         caps_string = gst_caps_to_string(caps);
1624         if (caps_string) {
1625                 LOGI("new caps[%p:%s]", caps, caps_string);
1626                 g_free(caps_string);
1627         }
1628
1629         if (core->caps)
1630                 gst_caps_unref(core->caps);
1631
1632         _mc_gst_video_info_free(core);
1633
1634         core->caps = g_steal_pointer(&caps);
1635
1636         return TRUE;
1637 }
1638
1639 static gboolean _mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index)
1640 {
1641         gchar *caps_string = NULL;
1642         GstCaps *caps = NULL;
1643         mc_gst_port_def_t *port_def = &core->ports[index]->port_def;
1644
1645         caps = gst_caps_new_simple(core->mime,
1646                 "width", G_TYPE_INT, port_def->info.video.width,
1647                 "height", G_TYPE_INT, port_def->info.video.height,
1648                 "framerate", GST_TYPE_FRACTION, port_def->info.video.framerate, 1,
1649                 NULL);
1650
1651         switch (codec_id) {
1652         case MEDIACODEC_H263:
1653                 if (core->encoder) {
1654                         gst_caps_set_simple(caps,
1655                                 "format", G_TYPE_STRING, port_def->info.video.format,
1656                                 NULL);
1657                 } else {
1658                         gst_caps_set_simple(caps,
1659                                 "mpegversion", G_TYPE_INT, 4,
1660                                 "framerate", GST_TYPE_FRACTION, 30, 1,
1661                                 NULL);
1662                 }
1663                 break;
1664         case MEDIACODEC_MPEG4:
1665                 if (core->encoder) {
1666                         gst_caps_set_simple(caps,
1667                                 "format", G_TYPE_STRING, port_def->info.video.format,
1668                                 NULL);
1669                 } else {
1670                         gst_caps_set_simple(caps,
1671                                 "mpegversion", G_TYPE_INT, 4,
1672                                 "systemstream", G_TYPE_BOOLEAN, false,
1673                                 "parsed", G_TYPE_BOOLEAN, TRUE,
1674                                 "framerate", GST_TYPE_FRACTION, 30, 1,
1675                                 NULL);
1676                 }
1677                 break;
1678         case MEDIACODEC_H264:
1679                 if (core->encoder) {
1680                         gst_caps_set_simple(caps,
1681                                 "format", G_TYPE_STRING, port_def->info.video.format,
1682                                 NULL);
1683                         g_object_set(GST_OBJECT(core->codec), "byte-stream", TRUE, NULL);
1684                         LOGE("format : %s", port_def->info.video.format);
1685                 } else {
1686                         gst_caps_set_simple(caps,
1687                                 "parsed", G_TYPE_BOOLEAN, TRUE,  /* FIXME different from sw */
1688                                 "alignment", G_TYPE_STRING, "au",
1689                                 "stream-format", G_TYPE_STRING, "byte-stream",
1690                                 "framerate", GST_TYPE_FRACTION, 30, 1,
1691                                 NULL);
1692                 }
1693                 break;
1694         default:
1695                 break;
1696         }
1697
1698         caps_string = gst_caps_to_string(caps);
1699         if (caps_string) {
1700                 LOGI("new caps[%p:%s]", caps, caps_string);
1701                 g_free(caps_string);
1702         }
1703
1704         if (core->caps)
1705                 gst_caps_unref(core->caps);
1706         _mc_gst_video_info_free(core);
1707
1708         core->caps = caps;
1709
1710         return TRUE;
1711 }
1712
1713 static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboolean encoder, gboolean is_hw)
1714 {
1715         MEDIACODEC_FENTER();
1716
1717         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
1718
1719         switch (id) {
1720         case MEDIACODEC_AAC:
1721                 if (encoder)
1722                         core->vtable = aenc_aac_vtable;
1723                 else
1724                         core->vtable = adec_aac_vtable;
1725                 break;
1726         case MEDIACODEC_AAC_HE:
1727         case MEDIACODEC_AAC_HE_PS:
1728                 if (encoder) {
1729                         LOGD("[MC_NOT_SUPPORTED] he-aac-v12 encoder is not supported yet!!!");
1730                         return MC_NOT_SUPPORTED;
1731                 } else {
1732                         core->vtable = adec_aacv12_vtable;
1733                 }
1734                 break;
1735         case MEDIACODEC_MP3:
1736                 if (encoder) {
1737                         LOGD("[MC_NOT_SUPPORTED] mp3 encoder is not supported yet!!!");
1738                         return MC_NOT_SUPPORTED;
1739                 } else {
1740                         core->vtable = adec_mp3_vtable;
1741                 }
1742                 break;
1743         case MEDIACODEC_AMR_NB:
1744                 LOGD("amrnb vtable");
1745                 if (encoder)
1746                         core->vtable = aenc_amrnb_vtable;
1747                 else
1748                         core->vtable = adec_amrnb_vtable;
1749                 break;
1750         case MEDIACODEC_AMR_WB:
1751                 LOGD("amrwb vtable - Only support decoder");
1752                 if (encoder) {
1753                         LOGD("[MC_NOT_SUPPORTED] amr-wb encoder is not supported yet!!!");
1754                         return MC_NOT_SUPPORTED;
1755                 } else {
1756                         core->vtable = adec_amrwb_vtable;
1757                 }
1758                 break;
1759         case MEDIACODEC_VORBIS:
1760                 LOGD("vorbis vtable");
1761                 if (encoder)
1762                         return MC_NOT_SUPPORTED;
1763                 else
1764                         core->vtable = adec_vorbis_vtable;
1765                 break;
1766         case MEDIACODEC_FLAC:
1767                 LOGD("flac vtable");
1768                 if (encoder) {
1769                         LOGD("[MC_NOT_SUPPORTED] flac encoder is not supported yet!!!");
1770                         return MC_NOT_SUPPORTED;
1771                 } else {
1772                         core->vtable = adec_flac_vtable;
1773                 }
1774                 break;
1775         case MEDIACODEC_OPUS:
1776                 LOGD("opus vtable");
1777                 if (encoder)
1778                         core->vtable = aenc_opus_vtable;
1779                 else
1780                         core->vtable = adec_vtable;
1781                 break;
1782         case MEDIACODEC_WMAV1:
1783         case MEDIACODEC_WMAV2:
1784         case MEDIACODEC_WMAPRO:
1785         case MEDIACODEC_WMALSL:
1786                 LOGD("wma(V1 / V2 / LSL / PRO) vtable");
1787                 if (encoder) {
1788                         LOGD("[MC_NOT_SUPPORTED] wma encoder is not supported yet!!!");
1789                         return MC_NOT_SUPPORTED;
1790                 } else {
1791                         core->vtable = adec_wma_vtable;
1792                 }
1793                 break;
1794         case MEDIACODEC_H263:
1795                 LOGD("h263 vtable");
1796                 if (encoder) {
1797                         core->vtable = is_hw ? venc_h263_hw_vtable : venc_h263_sw_vtable;
1798                 } else {
1799                         if (is_hw)
1800                                 core->vtable = vdec_h263_hw_vtable;
1801                         else
1802                                 core->vtable = vdec_h263_sw_vtable;
1803                 }
1804                 break;
1805         case MEDIACODEC_MPEG4:
1806                 LOGD("mpeg4 vtable");
1807                 if (encoder)
1808                         core->vtable = is_hw ? venc_mpeg4_hw_vtable : venc_mpeg4_sw_vtable;
1809                 else
1810                         core->vtable = is_hw ? vdec_mpeg4_hw_vtable : vdec_mpeg4_sw_vtable;
1811                 break;
1812         case MEDIACODEC_H264:
1813                 LOGD("h264 vtable");
1814                 if (encoder) {
1815                         core->vtable = is_hw ? venc_h264_hw_vtable : venc_vtable;
1816                 } else {
1817                         if (is_hw)
1818                                 core->vtable = vdec_h264_hw_vtable;
1819                         else
1820                                 core->vtable = vdec_h264_sw_vtable;
1821                 }
1822                 break;
1823         default:
1824                 break;
1825         }
1826
1827         MEDIACODEC_FLEAVE();
1828
1829         return MC_ERROR_NONE;
1830 }
1831
1832 static gint _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *mcbuffer)
1833 {
1834         return gst_app_src_push_buffer(GST_APP_SRC(core->appsrc), mcbuffer->buffer);
1835 }
1836
1837 media_packet_h _mc_get_input_buffer(mc_gst_core_t *core)
1838 {
1839         LOGD("waiting for input...");
1840         return mc_async_queue_pop(core->available_queue->input);
1841 }
1842
1843 mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle)
1844 {
1845         int ret = MC_ERROR_NONE;
1846         int num_supported_codec = 0;
1847         int i = 0;
1848         bool video;
1849         bool encoder;
1850         bool hardware;
1851         gchar *factory_name = NULL;
1852         media_format_mimetype_e out_mime;
1853         mediacodec_codec_type_e id;
1854         mc_codec_map_t *codec_map;
1855
1856         MEDIACODEC_FENTER();
1857
1858         if (!mc_handle)
1859                 return MC_PARAM_ERROR;
1860
1861         id = mc_handle->codec_id;
1862         video = mc_handle->is_video;
1863         encoder = mc_handle->is_encoder;
1864         hardware = mc_handle->is_hw;
1865         codec_map = encoder ? mc_handle->encoder_map : mc_handle->decoder_map;
1866         num_supported_codec = encoder ? mc_handle->num_supported_encoder : mc_handle->num_supported_decoder;
1867
1868         for (i = 0; i < num_supported_codec; i++) {
1869                 if ((id == codec_map[i].id) && (hardware == codec_map[i].hardware))
1870                         break;
1871         }
1872
1873         if (i == num_supported_codec)
1874                 return MC_NOT_SUPPORTED;
1875
1876         factory_name = codec_map[i].type.factory_name;
1877         out_mime = codec_map[i].type.out_format;
1878
1879         /* gst_core create */
1880         mc_gst_core_t *new_core = mc_gst_core_new();
1881
1882         new_core->mime = codec_map[i].type.mime;
1883         new_core->is_hw = hardware;
1884         new_core->eos = false;
1885         new_core->encoder = encoder;
1886         new_core->video = video;
1887         memcpy(&new_core->ports[in_port_index]->port_def.info, &mc_handle->info, sizeof(mc_handle->info));
1888         memcpy(&new_core->ports[out_port_index]->port_def.info, &mc_handle->info, sizeof(mc_handle->info));
1889         new_core->ports[out_port_index]->port_def.coding_type = out_mime;
1890         new_core->codec_id = id;
1891         new_core->codec_type = &codec_map[i].type;
1892         new_core->mc_caps_new = video ? &_mc_gst_vid_caps_new : &_mc_gst_aud_caps_new;
1893         new_core->extra_converter = &mc_handle->extra_converter;
1894
1895         new_core->bufmgr = tbm_bufmgr_init(new_core->drm_fd);
1896         if (new_core->bufmgr == NULL) {
1897                 LOGE("TBM initialization failed");
1898                 return MC_ERROR;
1899         }
1900
1901         LOGD("@%p(%p) core is initializing...v(%d)e(%d)", mc_handle, new_core, new_core->video, new_core->encoder);
1902         LOGD("factory name : %s, output_fmt : %x", factory_name, out_mime);
1903
1904         /* create media_packet for output fmt */
1905         ret = _mc_output_media_packet_new(new_core, video, encoder, out_mime);
1906         if (ret != MC_ERROR_NONE) {
1907                 LOGE("Failed to create output pakcet");
1908                 return ret;
1909         }
1910
1911         for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER ; i++) {
1912                 LOGD("copy cb function [%d]", i);
1913                 if (mc_handle->user_cb[i]) {
1914                         new_core->user_cb[i] = mc_handle->user_cb[i];
1915                         new_core->user_data[i] = mc_handle->user_data[i];
1916                         LOGD("user_cb[%d] %p, %p", i, new_core->user_cb[i], mc_handle->user_cb[i]);
1917                 }
1918         }
1919
1920         /* create basic core elements */
1921         ret = _mc_gst_create_pipeline(new_core, factory_name);
1922         if (ret != MC_ERROR_NONE) {
1923                 LOGE("failed to create pipeline");
1924                 return ret;
1925         }
1926
1927         /* link vtable */
1928         ret = _mc_link_vtable(new_core, id, encoder, hardware);
1929         if (ret != MC_ERROR_NONE) {
1930                 LOGE("vtable link failed");
1931                 return ret;
1932         }
1933
1934         /* set caps in capsfilter as default*/
1935         if (!new_core->mc_caps_new(new_core, id, out_port_index)) {
1936                 LOGE("caps new failed");
1937                 return MC_INTERNAL_ERROR;
1938         }
1939
1940         /* FIXME will parse input format from ini. format is needed when linking elements*/
1941         if (new_core->video && new_core->encoder) {
1942                 gst_caps_set_simple(new_core->caps,
1943                         "format", G_TYPE_STRING, (new_core->is_hw ? "SN12" : "I420"),
1944                         NULL);
1945         }
1946
1947         g_object_set(new_core->capsfilter, "caps", new_core->caps, NULL);
1948
1949         _mc_gst_feed_task_new(new_core);
1950
1951         mc_handle->core = new_core;
1952         LOGD("initialized... %d", ret);
1953         MEDIACODEC_FLEAVE();
1954
1955         return ret;
1956 }
1957
1958 mc_ret_e mc_gst_unprepare(mc_handle_t *mc_handle)
1959 {
1960         MEDIACODEC_FENTER();
1961
1962         int i;
1963         int ret = MC_ERROR_NONE;
1964         mc_gst_core_t *core = NULL;
1965
1966         if (!mc_handle)
1967                 return MC_PARAM_ERROR;
1968
1969         core = (mc_gst_core_t *)mc_handle->core;
1970
1971         if (core) {
1972                 LOGD("@%p(%p) core is uninitializing... v(%d)e(%d)", mc_handle, core, core->video, core->encoder);
1973
1974                 g_mutex_lock(&core->drain_lock);
1975                 core->unprepare_flag = TRUE;
1976                 g_mutex_unlock(&core->drain_lock);
1977
1978                 if (core->eos)
1979                         _mc_send_eos_signal(core);
1980
1981                 _mc_gst_feed_task_free(core);
1982
1983                 _mc_gst_set_flush_input(core);
1984
1985                 _mc_gst_video_info_free(core);
1986
1987                 ret = _mc_gst_destroy_pipeline(core);
1988
1989                 /* unset callback */
1990                 for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER; i++) {
1991                         LOGD("unset cb function [%d]", i);
1992                         if (mc_handle->user_cb[i]) {
1993                                 core->user_cb[i] = NULL;
1994                                 core->user_data[i] = NULL;
1995                                 LOGD("user_cb[%d] %p, %p", i, core->user_cb[i], mc_handle->user_cb[i]);
1996                         }
1997                 }
1998
1999                 media_format_unref(core->output_fmt);
2000
2001                 if (core->bufmgr != NULL) {
2002                         tbm_bufmgr_deinit(core->bufmgr);
2003                         core->bufmgr = NULL;
2004                 }
2005
2006                 if (core->drm_fd != -1) {
2007                         close(core->drm_fd);
2008                         LOGD("close drm_fd");
2009                 }
2010
2011                 if (core != NULL) {
2012                         mc_gst_core_free(core);
2013                         mc_handle->core = NULL;
2014                 }
2015         }
2016
2017         MEDIACODEC_FLEAVE();
2018
2019         return ret;
2020 }
2021
2022 mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeout_us)
2023 {
2024         MEDIACODEC_FENTER();
2025
2026         int ret = MC_ERROR_NONE;
2027         mc_gst_core_t *core = NULL;
2028
2029         if (!mc_handle)
2030                 return MC_PARAM_ERROR;
2031
2032         core = (mc_gst_core_t *)mc_handle->core;
2033
2034         g_mutex_lock(&core->drain_lock);
2035
2036         while (g_atomic_int_get(&core->etb_count) == MAXINUM_QNUM) {
2037                 LOGD("Waiting until packets are drained..");
2038                 core->need_drain = true;
2039                 g_cond_wait(&core->buffer_cond, &core->drain_lock);
2040         }
2041         g_mutex_unlock(&core->drain_lock);
2042
2043         if (core->prepare_count == 0)
2044                 return MC_INVALID_STATUS;
2045
2046         g_mutex_lock(&core->drain_lock);
2047
2048         if (!core->eos || !core->unprepare_flag) {
2049                 mc_async_queue_push(core->available_queue->input, inbuf);
2050
2051         } else {
2052                 ret = MC_INVALID_IN_BUF;
2053                 g_mutex_unlock(&core->drain_lock);
2054                 return ret;
2055         }
2056
2057         g_mutex_unlock(&core->drain_lock);
2058         g_atomic_int_inc(&core->etb_count);
2059         LOGI("@v(%d)e(%d)process_input(%d): %p", core->video, core->encoder, core->etb_count, inbuf);
2060
2061         MEDIACODEC_FLEAVE();
2062
2063         return ret;
2064 }
2065
2066 mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeout_us)
2067 {
2068         gint ret = MC_ERROR_NONE;
2069         gint64 end_time = -1;
2070         gboolean signalled;
2071         mc_gst_core_t *core = NULL;
2072         media_packet_h out_packet = NULL;
2073
2074         MEDIACODEC_FENTER();
2075         end_time = g_get_monotonic_time() + timeout_us;
2076
2077         if (!mc_handle)
2078                 return MC_PARAM_ERROR;
2079
2080         core = (mc_gst_core_t *)mc_handle->core;
2081
2082         g_mutex_lock(&core->ports[1]->mutex);
2083
2084         if (!g_queue_is_empty(core->ports[1]->queue))
2085                 signalled = TRUE;
2086         else {
2087                 LOGD("no buffer, wait for signal");
2088                 signalled = g_cond_wait_until(&core->out_buffer_cond, &core->ports[1]->mutex, end_time);
2089         }
2090
2091         if (signalled)
2092                 out_packet = g_queue_pop_head(core->ports[1]->queue);
2093         else {
2094                 LOGW("Failed to get buffer");
2095                 ret = MC_OUTPUT_BUFFER_EMPTY;
2096         }
2097
2098         *outbuf = out_packet;
2099         LOGI("@%p v(%d)e(%d) got buffer :%p", core, core->video, core->encoder, out_packet);
2100
2101         g_mutex_unlock(&core->ports[1]->mutex);
2102
2103         MEDIACODEC_FLEAVE();
2104
2105         return ret;
2106 }
2107
2108 mc_ret_e mc_gst_flush_buffers(mc_handle_t *mc_handle)
2109 {
2110         gint ret = MC_ERROR_NONE;
2111         mc_gst_core_t *core = NULL;
2112
2113         MEDIACODEC_FENTER();
2114
2115         if (!mc_handle)
2116                 return MC_PARAM_ERROR;
2117
2118         core = (mc_gst_core_t *)mc_handle->core;
2119         LOGI("@%p v(%d)e(%d) flush_buffers", core, core->video, core->encoder);
2120
2121         ret = _mc_gst_flush_buffers(core);
2122
2123         MEDIACODEC_FLEAVE();
2124
2125         return ret;
2126 }
2127
2128 static gboolean __mc_gst_init_gstreamer()
2129 {
2130         MEDIACODEC_FENTER();
2131
2132         gint i = 0;
2133         gint arg_count = 0;
2134         static gboolean initialized = FALSE;
2135         static const int max_argc = 50;
2136         gint *argc = NULL;
2137         gchar **argv = NULL;
2138         gchar **argv2 = NULL;
2139         GError *err = NULL;
2140
2141         if (initialized) {
2142                 LOGD("gstreamer already initialized.\n");
2143                 return TRUE;
2144         }
2145
2146         /* alloc */
2147         argc = malloc(sizeof(int));
2148         argv = malloc(sizeof(gchar *) *max_argc);
2149         argv2 = malloc(sizeof(gchar *) *max_argc);
2150
2151         if (!argc || !argv || !argv2)
2152                 goto ERROR;
2153
2154         memset(argv, 0, sizeof(gchar *) *max_argc);
2155         memset(argv2, 0, sizeof(gchar *) *max_argc);
2156
2157         /* add initial */
2158         *argc = 1;
2159         argv[0] = g_strdup("media codec");
2160
2161         /* we would not do fork for scanning plugins */
2162         argv[*argc] = g_strdup("--gst-disable-registry-fork");
2163         (*argc)++;
2164
2165         /* check disable registry scan */
2166         argv[*argc] = g_strdup("--gst-disable-registry-update");
2167         (*argc)++;
2168
2169         /* check disable segtrap */
2170         argv[*argc] = g_strdup("--gst-disable-segtrap");
2171         (*argc)++;
2172
2173         LOGD("initializing gstreamer with following parameter\n");
2174         LOGD("argc : %d\n", *argc);
2175         arg_count = *argc;
2176
2177         for (i = 0; i < arg_count; i++) {
2178                 argv2[i] = argv[i];
2179                 LOGD("argv[%d] : %s\n", i, argv2[i]);
2180         }
2181
2182         /* initializing gstreamer */
2183         if (!gst_init_check(argc, &argv, &err)) {
2184                 LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
2185                 if (err)
2186                         g_error_free(err);
2187
2188                 goto ERROR;
2189         }
2190
2191         /* release */
2192         for (i = 0; i < arg_count; i++)
2193                 MC_FREEIF(argv2[i]);
2194
2195         MC_FREEIF(argv);
2196         MC_FREEIF(argv2);
2197         MC_FREEIF(argc);
2198
2199         /* done */
2200         initialized = TRUE;
2201
2202         MEDIACODEC_FLEAVE();
2203         return TRUE;
2204
2205 ERROR:
2206         /* release */
2207         for (i = 0; i < arg_count; i++) {
2208                 LOGD("free[%d] : %s\n", i, argv2[i]);
2209                 MC_FREEIF(argv2[i]);
2210         }
2211
2212         MC_FREEIF(argv);
2213         MC_FREEIF(argv2);
2214         MC_FREEIF(argc);
2215
2216         return FALSE;
2217 }
2218
2219 static GstElement *__mc_gst_extra_converter_new(mc_extra_converter_t *extra_converter)
2220 {
2221         GstElement *element = NULL;
2222         gint array[MEDIACODEC_CROP_ARRAY_LENGTH] = {0, };
2223
2224         if (!extra_converter) {
2225                 LOGE("NULL extra converter");
2226                 return NULL;
2227         }
2228
2229         LOGI("extra converter[%s]", extra_converter->name);
2230
2231         element = gst_element_factory_make(extra_converter->name, NULL);
2232         if (!element) {
2233                 LOGE("create element[%s] failed", extra_converter->name);
2234                 return NULL;
2235         }
2236
2237         array[0] = extra_converter->crop_x;
2238         array[1] = extra_converter->crop_y;
2239         array[2] = extra_converter->crop_w;
2240         array[3] = extra_converter->crop_h;
2241
2242         if (mc_gst_set_property_array_int(element,
2243                 "crop", array, MEDIACODEC_CROP_ARRAY_LENGTH) != MC_ERROR_NONE) {
2244                 gst_object_unref(element);
2245                 return NULL;
2246         }
2247
2248         LOGI("set crop to extra converter[%d,%d,%dx%d]",
2249                 array[0], array[1], array[2], array[3] );
2250
2251         return element;
2252 }
2253
2254
2255 #ifdef TIZEN_FEATURE_ENABLE_DUMP_SOURCE
2256 static GstPadProbeReturn __dump_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
2257 {
2258         static int count = 0;
2259         int i = 0;
2260         const gchar *dump_path = (const gchar *)u_data;
2261         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
2262         GstMemory *memory = NULL;
2263         FILE *fp = NULL;
2264         tbm_surface_h surface = NULL;
2265         tbm_surface_info_s sinfo = {0, };
2266
2267         if (!dump_path) {
2268                 LOGW("NULL path");
2269                 return GST_PAD_PROBE_OK;
2270         }
2271
2272         if (count++ > 10) {
2273                 LOGW("[%s] SKIP DUMP", dump_path);
2274                 return GST_PAD_PROBE_OK;
2275         }
2276
2277         memory = gst_buffer_peek_memory(buffer, 0);
2278
2279         if (!gst_is_tizen_memory(memory)) {
2280                 LOGW("Not tizen memory");
2281                 return GST_PAD_PROBE_OK;
2282         }
2283
2284         surface = gst_tizen_memory_get_surface(memory);
2285         if (!surface) {
2286                 LOGW("No surface");
2287                 return GST_PAD_PROBE_OK;
2288         }
2289
2290         fp = fopen(dump_path, "a");
2291         if (!fp) {
2292                 LOGW("file open failed[%s]", dump_path);
2293                 return GST_PAD_PROBE_OK;
2294         }
2295
2296         tbm_surface_get_info(surface, &sinfo);
2297
2298         for (i = 0 ; i < sinfo.num_planes ; i++) {
2299                 LOGI("[dump:%s] write plane[%d] size[%u]", dump_path, i, sinfo.planes[i].size);
2300                 fwrite(sinfo.planes[i].ptr, 1, sinfo.planes[i].size, fp);
2301         }
2302
2303         fclose(fp);
2304
2305         return GST_PAD_PROBE_OK;
2306 }
2307 #endif /* TIZEN_FEATURE_ENABLE_DUMP_SOURCE */
2308
2309
2310 mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name)
2311 {
2312         int i = 0;
2313         int bitrate = 0;
2314         GstBus *bus = NULL;
2315
2316         MEDIACODEC_FENTER();
2317
2318         g_mutex_lock(&core->prepare_lock);
2319
2320         if (core->prepare_count == 0) {
2321                 if (!__mc_gst_init_gstreamer()) {
2322                         LOGE("gstreamer initialize fail");
2323                         g_mutex_unlock(&core->prepare_lock);
2324                         return MC_NOT_INITIALIZED;
2325                 }
2326
2327                 core->codec = gst_element_factory_make(factory_name, NULL);
2328                 if (!core->codec) {
2329                         LOGE("codec element create fail");
2330                         goto ERROR;
2331                 }
2332
2333                 LOGD("@%p v(%d)e(%d) create_pipeline", core, core->video, core->encoder);
2334                 MEDIACODEC_ELEMENT_SET_STATE(core->codec, GST_STATE_READY);
2335
2336                 /* create common elements */
2337                 core->pipeline = gst_pipeline_new(NULL);
2338                 if (!core->pipeline) {
2339                         LOGE("pipeline create fail");
2340                         goto ERROR;
2341                 }
2342
2343                 core->appsrc = gst_element_factory_make("appsrc", NULL);
2344                 if (!core->appsrc) {
2345                         LOGE("appsrc can't create");
2346                         goto ERROR;
2347                 }
2348
2349                 if (!core->video && core->encoder) {
2350                         core->audioconvert = gst_element_factory_make("audioconvert", NULL);
2351                         if (!core->audioconvert) {
2352                                 LOGE("audioconvert can't create");
2353                                 goto ERROR;
2354                         }
2355
2356                         core->audioresample = gst_element_factory_make("audioresample", NULL);
2357                         if (!core->audioresample) {
2358                                 LOGE("audioresample can't create");
2359                                 goto ERROR;
2360                         }
2361                 }
2362
2363                 if (core->video && core->encoder && core->extra_converter->enable) {
2364                         core->videoconvert = __mc_gst_extra_converter_new(core->extra_converter);
2365                         if (!core->videoconvert) {
2366                                 LOGE("create[%s] failed", core->extra_converter->name);
2367                                 goto ERROR;
2368                         }
2369                 }
2370
2371                 core->capsfilter = gst_element_factory_make("capsfilter", NULL);
2372                 if (!core->capsfilter) {
2373                         LOGE("capsfilter can't create");
2374                         goto ERROR;
2375                 }
2376
2377                 core->fakesink = gst_element_factory_make("fakesink", NULL);
2378                 if (!core->fakesink) {
2379                         LOGE("fakesink create fail");
2380                         goto ERROR;
2381                 }
2382
2383                 g_object_set(core->fakesink, "enable-last-sample", FALSE, NULL);
2384
2385                 /*__mc_link_elements(core);*/
2386                 if (!core->video && core->encoder) {
2387                         gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->audioresample, core->audioconvert, core->capsfilter, core->codec, core->fakesink, NULL);
2388
2389                         /* link elements */
2390                         if (!(gst_element_link_many(core->appsrc, core->audioresample, core->audioconvert, core->capsfilter, core->codec, core->fakesink, NULL))) {
2391                                 LOGE("gst_element_link_many is failed");
2392                                 goto ERROR;
2393                         }
2394                 } else if (core->video && core->encoder) {
2395                         if (core->extra_converter->enable) {
2396                                 gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->videoconvert, core->codec, core->fakesink, NULL);
2397
2398                                 /* link elements */
2399                                 if (!(gst_element_link_many(core->appsrc, core->videoconvert, core->codec, core->fakesink, NULL))) {
2400                                         LOGE("gst_element_link_many is failed");
2401                                         goto ERROR;
2402                                 }
2403                         } else {
2404                                 gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL);
2405
2406                                 /* link elements */
2407                                 if (!(gst_element_link_many(core->appsrc, core->codec, core->fakesink, NULL))) {
2408                                         LOGE("gst_element_link_many is failed");
2409                                         goto ERROR;
2410                                 }
2411                         }
2412                 } else {
2413                         gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL);
2414
2415                         /* link elements */
2416                         if (!(gst_element_link_many(core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL))) {
2417                                 LOGE("gst_element_link_many is failed");
2418                                 goto ERROR;
2419                         }
2420                 }
2421
2422 #ifdef TIZEN_FEATURE_ENABLE_DUMP_SOURCE
2423                 {
2424                         GstPad *pad = NULL;
2425
2426                         pad = gst_element_get_static_pad(core->videoconvert, "sink");
2427                         if (pad) {
2428                                 gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, __dump_probe, "/tmp/input.dump", NULL);
2429                                 gst_object_unref(pad);
2430                                 pad = NULL;
2431                         }
2432
2433                         pad = gst_element_get_static_pad(core->videoconvert, "src");
2434                         if (pad) {
2435                                 gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, __dump_probe, "/tmp/output.dump", NULL);
2436                                 gst_object_unref(pad);
2437                                 pad = NULL;
2438                         }
2439                 }
2440 #endif /* TIZEN_FEATURE_ENABLE_DUMP_SOURCE */
2441
2442                 /* connect signals, bus watcher */
2443                 bus = gst_pipeline_get_bus(GST_PIPELINE(core->pipeline));
2444                 core->bus_watch_id = gst_bus_add_watch(bus, __mc_gst_bus_callback, core);
2445                 core->thread_default = g_main_context_get_thread_default();
2446
2447                 /* set sync handler to get tag synchronously */
2448                 gst_bus_set_sync_handler(bus, __mc_gst_bus_sync_callback, core, NULL);
2449                 gst_object_unref(GST_OBJECT(bus));
2450
2451                 /* app src */
2452                 g_signal_connect(core->appsrc, "need-data", G_CALLBACK(__mc_gst_start_feed), core);
2453                 g_signal_connect(core->appsrc, "enough-data", G_CALLBACK(__mc_gst_stop_feed), core);
2454
2455                 /* connect handoff */
2456                 g_object_set(GST_OBJECT(core->fakesink), "signal-handoffs", TRUE, NULL);
2457                 core->signal_handoff = g_signal_connect(core->fakesink, "handoff", G_CALLBACK(__mc_gst_buffer_add), core);
2458
2459                 /* set bitrate and properties */
2460                 if (core->encoder) {
2461                         if (core->video)
2462                                 bitrate = core->ports[in_port_index]->port_def.info.video.bitrate;
2463                         else
2464                                 bitrate = core->ports[in_port_index]->port_def.info.audio.bitrate;
2465
2466                         LOGI("set encoder bitrate[property:%s,v:%d] %d",
2467                                 core->codec_type->property->bitrate_name, core->video, bitrate);
2468
2469                         g_object_set(core->codec,
2470                                 core->codec_type->property->bitrate_name, bitrate,
2471                                 NULL);
2472                 }
2473
2474                 for (i = 0 ; i < core->codec_type->property->ext_num ; i++) {
2475                         LOGI("set property [%s] -> [%s]",
2476                                 core->codec_type->property->ext_name[i],
2477                                 core->codec_type->property->ext_value[i]);
2478
2479                         gst_util_set_object_arg((GObject *)core->codec,
2480                                 core->codec_type->property->ext_name[i],
2481                                 core->codec_type->property->ext_value[i]);
2482                 }
2483
2484                 /* set state PLAYING */
2485                 MEDIACODEC_ELEMENT_SET_STATE(GST_ELEMENT_CAST(core->pipeline), GST_STATE_PLAYING);
2486         }
2487
2488         core->prepare_count++;
2489         g_mutex_unlock(&core->prepare_lock);
2490
2491         MEDIACODEC_FLEAVE();
2492
2493         return MC_ERROR_NONE;
2494
2495 STATE_CHANGE_FAILED:
2496 ERROR:
2497
2498         if (core->codec)
2499                 gst_object_unref(GST_OBJECT(core->codec));
2500
2501         if (core->pipeline)
2502                 gst_object_unref(GST_OBJECT(core->pipeline));
2503
2504         if (core->appsrc)
2505                 gst_object_unref(GST_OBJECT(core->appsrc));
2506
2507         if (core->capsfilter)
2508                 gst_object_unref(GST_OBJECT(core->capsfilter));
2509
2510         if (core->audioresample)
2511                 gst_object_unref(GST_OBJECT(core->audioresample));
2512
2513         if (core->videoscale)
2514                 gst_object_unref(GST_OBJECT(core->videoscale));
2515
2516         if (core->videoconvert)
2517                 gst_object_unref(GST_OBJECT(core->videoconvert));
2518
2519         if (core->audioconvert)
2520                 gst_object_unref(GST_OBJECT(core->audioconvert));
2521
2522         if (core->fakesink)
2523                 gst_object_unref(GST_OBJECT(core->fakesink));
2524
2525         g_mutex_unlock(&core->prepare_lock);
2526
2527         return MC_ERROR;
2528 }
2529
2530 mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core)
2531 {
2532         int ret = MC_ERROR_NONE;
2533
2534         MEDIACODEC_FENTER();
2535
2536         g_mutex_lock(&core->prepare_lock);
2537         core->prepare_count--;
2538         if (core->prepare_count == 0) {
2539
2540                 if (core->pipeline) {
2541                         /* disconnect signal */
2542                         if (core->fakesink && GST_IS_ELEMENT(core->fakesink)) {
2543                                 if (g_signal_handler_is_connected(core->fakesink, core->signal_handoff)) {
2544                                         g_signal_handler_disconnect(core->fakesink, core->signal_handoff);
2545                                         LOGD("handoff signal destroy");
2546                                 }
2547                         }
2548
2549                         if (core->bus_watch_id) {
2550                                 GSource *source = NULL;
2551                                 source = g_main_context_find_source_by_id(core->thread_default, core->bus_watch_id);
2552                                 g_source_destroy(source);
2553                                 LOGD("bus_watch_id destroy");
2554                         }
2555
2556                         MEDIACODEC_ELEMENT_SET_STATE(core->pipeline, GST_STATE_NULL);
2557
2558                         gst_object_unref(GST_OBJECT(core->pipeline));
2559
2560                         if (core->caps) {
2561                                 gst_caps_unref(core->caps);
2562                                 core->caps = NULL;
2563                         }
2564                 }
2565         }
2566
2567         LOGD("@%p v(%d)e(%d) destroy_pipeline : %d ", core, core->video, core->encoder, core->prepare_count);
2568         g_mutex_unlock(&core->prepare_lock);
2569
2570         MEDIACODEC_FLEAVE();
2571
2572         return ret;
2573
2574 STATE_CHANGE_FAILED:
2575         if (core->pipeline)
2576                 gst_object_unref(GST_OBJECT(core->pipeline));
2577
2578         LOGD("@%p v(%d)e(%d) destroy_pipeline failed", core, core->video, core->encoder);
2579         g_mutex_unlock(&core->prepare_lock);
2580
2581         return MC_ERROR;
2582 }
2583
2584 void __mc_push_output_to_queue(mc_gst_core_t *core, GstMCBuffer *mcbuffer)
2585 {
2586         g_mutex_lock(&core->ports[1]->mutex);
2587
2588         /* push it to output buffer queue */
2589         g_queue_push_tail(core->ports[1]->queue, mcbuffer->packet);
2590         g_cond_broadcast(&core->out_buffer_cond);
2591
2592         if (mcbuffer->buffer) {
2593                 LOGD("dq : v(%d)e(%d) TIMESTAMP = %"GST_TIME_FORMAT " DURATION = %"GST_TIME_FORMAT, core->video, core->encoder,
2594                         GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(mcbuffer->buffer)), GST_TIME_ARGS(GST_BUFFER_DURATION(mcbuffer->buffer)));
2595         } else {
2596                 LOGD("dq : v(%d)e(%d)", core->video, core->encoder);
2597         }
2598
2599         g_mutex_unlock(&core->ports[1]->mutex);
2600
2601         if (core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) {
2602                 ((mc_fill_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER])
2603                         (mcbuffer->packet, core->user_data[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]);
2604         }
2605 }
2606
2607 void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data)
2608 {
2609         GstMCBuffer *mcbuffer = NULL;
2610
2611         MEDIACODEC_FENTER();
2612
2613         mc_gst_core_t *core = (mc_gst_core_t *)data;
2614
2615         gst_buffer_ref(buffer);
2616
2617         mcbuffer = __mc_gst_make_media_packet(core, buffer);
2618
2619         LOGI("@%p(%d) out_packet : %p", core, core->encoder, mcbuffer->packet);
2620
2621         if (mcbuffer->packet) {
2622                 media_packet_set_pts(mcbuffer->packet, GST_BUFFER_TIMESTAMP(buffer));
2623                 media_packet_set_dts(mcbuffer->packet, GST_BUFFER_DTS(buffer));
2624                 media_packet_set_duration(mcbuffer->packet, GST_BUFFER_DURATION(buffer));
2625
2626                 if (core->need_codec_data) {
2627                         media_packet_set_flags(mcbuffer->packet, MEDIA_PACKET_CODEC_CONFIG);
2628                         core->need_codec_data = false;
2629                 }
2630
2631                 if (core->need_sync_flag) {
2632                         media_packet_set_flags(mcbuffer->packet, MEDIA_PACKET_SYNC_FRAME);
2633                         core->need_sync_flag = false;
2634                 }
2635
2636                 __mc_push_output_to_queue(core, mcbuffer);
2637         } else {
2638                 gst_buffer_unref(buffer);
2639                 LOGE("Failed to dequeue output packet");
2640         }
2641
2642         MEDIACODEC_FLEAVE();
2643
2644         return;
2645 }
2646
2647 int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data)
2648 {
2649         MEDIACODEC_FENTER();
2650
2651         GstMCBuffer *mcbuffer = (GstMCBuffer *)user_data;
2652
2653         gst_buffer_unref((GstBuffer *)mcbuffer->buffer);
2654
2655         if (mcbuffer->ext_mem) {
2656                 g_free(mcbuffer->ext_mem);
2657                 LOGD("freed external memory");
2658                 mcbuffer->ext_mem = NULL;
2659         }
2660
2661         LOGD("output port filled buffer : %p", packet);
2662         g_free(mcbuffer);
2663
2664         MEDIACODEC_FLEAVE();
2665
2666         return MEDIA_PACKET_FINALIZE;
2667 }
2668
2669 gchar *__mc_get_gst_input_format(media_format_mimetype_e mimetype, bool is_hw)
2670 {
2671         gchar *format = NULL;
2672
2673         switch (mimetype) {
2674         case MEDIA_FORMAT_I420:
2675                 format = "I420";
2676                 break;
2677         case MEDIA_FORMAT_NV12:
2678                 if (is_hw)
2679                         format = "SN12";
2680                 else
2681                         format = "NV12";
2682                 break;
2683         case MEDIA_FORMAT_ARGB:
2684                 format = "ARGB";
2685                 break;
2686         default:
2687                 break;
2688         }
2689
2690         LOGD("input packet format : %s", format ? format : "(null)" );
2691
2692         return format;
2693 }
2694
2695 GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet_h packet, bool codec_config)
2696 {
2697         gint ret = MEDIA_PACKET_ERROR_NONE;
2698         uint64_t buf_size = 0;
2699         uint64_t pts = 0;
2700         uint64_t dts = 0;
2701         uint64_t dur = 0;
2702         void *buf_data = NULL;
2703         GstMCBuffer *mcbuffer = NULL;
2704
2705         ret = media_packet_get_buffer_size(packet, &buf_size);
2706         if (ret != MEDIA_PACKET_ERROR_NONE) {
2707                 LOGW("buffer size get fail");
2708                 return NULL;
2709         }
2710
2711         ret = media_packet_get_buffer_data_ptr(packet, &buf_data);
2712         if (ret != MEDIA_PACKET_ERROR_NONE) {
2713                 LOGW("buffer data get fail");
2714                 return NULL;
2715         }
2716
2717         mcbuffer = gst_mediacodec_buffer_new(core, packet, buf_size);
2718         if (mcbuffer == NULL) {
2719                 LOGW("failed to create inbuf");
2720                 return NULL;
2721         }
2722
2723         LOGD("packet :v(%d)e(%d) %p, buf_size : %d", core->video, core->encoder, packet, (int)buf_size);
2724
2725         ret = __mc_fill_input_buffer(core, packet, mcbuffer);
2726         if (ret != MC_ERROR_NONE) {
2727                 LOGW("failed to fill inbuf: %s (ox%08x)", _mc_error_to_string(ret), ret);
2728                 /*
2729                  * if __mc_fill_input_buffer() failed, no memory appended to mcbuffer->buffer, so gst_mediacodec_buffer_finalize()
2730                  * will not be invoked
2731                  */
2732                 gst_buffer_unref(mcbuffer->buffer);
2733                 g_free(mcbuffer);
2734                 return NULL;
2735         }
2736
2737         /* dts */
2738         media_packet_get_pts(packet, &dts);
2739         GST_BUFFER_DTS(mcbuffer->buffer) = dts;
2740
2741         /* pts */
2742         media_packet_get_pts(packet, &pts);
2743         GST_BUFFER_PTS(mcbuffer->buffer) = pts;
2744
2745         /* duration */
2746         media_packet_get_duration(packet, &dur);
2747         GST_BUFFER_DURATION(mcbuffer->buffer) = dur;
2748
2749         GST_BUFFER_OFFSET(mcbuffer->buffer) = core->offset;
2750
2751         core->offset += buf_size;
2752         GST_BUFFER_OFFSET_END(mcbuffer->buffer) = core->offset;
2753
2754         return mcbuffer;
2755 }
2756
2757 GstMCBuffer *__mc_gst_make_media_packet(mc_gst_core_t *core, GstBuffer *buffer)
2758 {
2759         gint ret = MEDIA_PACKET_ERROR_NONE;
2760         GstMemory *mem;
2761         GstMapInfo map = GST_MAP_INFO_INIT;
2762         GstMCBuffer *mcbuffer = NULL;
2763         void *data = NULL;
2764         gint size = 0;
2765
2766         mem = gst_buffer_peek_memory(buffer, 0);
2767
2768         if (gst_is_tizen_memory(mem)) {
2769                 data = (void *)gst_tizen_memory_get_surface(mem);
2770                 size = tbm_surface_internal_get_size((tbm_surface_h)data);
2771         } else {
2772                 if (!gst_memory_map(mem, &map, GST_MAP_READ)) {
2773                         LOGE("gst_memory_map failed for buffer[%p]", buffer);
2774                         return NULL;
2775                 }
2776
2777                 data = map.data;
2778                 size = map.size;
2779         }
2780
2781         mcbuffer = g_new0(GstMCBuffer, 1);
2782
2783         mcbuffer->buffer = buffer;
2784         mcbuffer->core = core;
2785         mcbuffer->buf_size = size;
2786
2787         ret = __mc_fill_output_buffer(core, data, mcbuffer->buf_size,  mcbuffer);
2788
2789         if (!gst_is_tizen_memory(mem))
2790                 gst_memory_unmap(mem, &map);
2791
2792         if (ret != MC_ERROR_NONE) {
2793                 LOGW("failed to fill outbuf: %s (ox%08x)", _mc_error_to_string(ret), ret);
2794                 g_free(mcbuffer);
2795                 return NULL;
2796         }
2797
2798         return mcbuffer;
2799 }
2800
2801 int __mc_gst_create_eos_packet(media_format_h fmt, GstMCBuffer *mcbuffer)
2802 {
2803         gint ret = MC_ERROR_NONE;
2804         media_packet_h packet = NULL;
2805
2806         MEDIACODEC_FENTER();
2807         if (media_packet_create(fmt, __mc_output_buffer_finalize_cb, mcbuffer, &packet)) {
2808                 LOGE("media_packet_create failed\n");
2809                 ret = MC_ERROR;
2810                 goto ERROR;
2811         }
2812
2813         if (media_packet_set_flags(packet, MEDIA_PACKET_END_OF_STREAM)) {
2814                 LOGE("unable to set EOS flag\n");
2815                 ret = MC_ERROR;
2816                 goto ERROR;
2817         }
2818
2819         mcbuffer->buffer = NULL;
2820         mcbuffer->ext_mem = NULL;
2821         mcbuffer->buf_size = 0;
2822         mcbuffer->packet = packet;
2823         MEDIACODEC_FLEAVE();
2824
2825         return ret;
2826 ERROR:
2827         if (packet)
2828                 media_packet_unref(packet);
2829         MEDIACODEC_FLEAVE();
2830         return ret;
2831 }
2832
2833 void _mc_gst_handle_input_buffer_used(mc_gst_core_t *core, media_packet_h packet)
2834 {
2835         if (core) {
2836                 g_atomic_int_dec_and_test(&core->etb_count);
2837                 LOGD("@v(%d)e(%d) input port used(%d)----- ", core->video, core->encoder, core->etb_count);
2838         }
2839
2840         if (core && core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) {
2841                 ((mc_empty_buffer_cb)core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER])
2842                         (packet, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]);
2843
2844                 g_mutex_lock(&core->drain_lock);
2845
2846                 if (core->need_drain) {
2847                         LOGD("@v(%d)e(%d) input port used----- single process_input.....", core->video, core->encoder);
2848                         core->need_drain = false;
2849                         g_cond_signal(&core->buffer_cond);
2850                 }
2851                 g_mutex_unlock(&core->drain_lock);
2852         }
2853 }
2854
2855 gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data)
2856 {
2857         gint ret  = MC_ERROR_NONE;
2858         GstMCBuffer *mcbuffer = NULL;
2859
2860         mc_gst_core_t *core = (mc_gst_core_t *)data;
2861         LOGI("@%p v(%d)e(%d)bus message : %s", core, core->video, core->encoder, gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
2862
2863         switch (GST_MESSAGE_TYPE(msg)) {
2864
2865         case GST_MESSAGE_EOS:
2866                 _mc_send_eos_signal(core);
2867
2868                 mcbuffer = g_new0(GstMCBuffer, 1);
2869                 if (__mc_gst_create_eos_packet(core->output_fmt, mcbuffer) == MC_ERROR_NONE) {
2870                         __mc_push_output_to_queue(core, mcbuffer);
2871                         LOGD("send eos packet.");
2872                 } else {
2873                         LOGE("failed to create eos packet.");
2874                         g_free(mcbuffer);
2875                 }
2876
2877                 if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) {
2878                         LOGD("eos callback invoked");
2879                         ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]);
2880                 }
2881
2882                 LOGD("End of stream\n");
2883                 break;
2884
2885         case GST_MESSAGE_ERROR:
2886         {
2887                 GError *error = NULL;
2888
2889                 gst_message_parse_error(msg, &error, NULL);
2890
2891                 if (!error) {
2892                         LOGW("GST error message parsing failed");
2893                         break;
2894                 }
2895
2896                 if (error) {
2897                         if (error->domain == GST_STREAM_ERROR)
2898                                 ret = __gst_handle_stream_error(core, error, msg);
2899                         else if (error->domain == GST_RESOURCE_ERROR)
2900                                 ret = __gst_handle_resource_error(core, error->code);
2901                         else if (error->domain == GST_LIBRARY_ERROR)
2902                                 ret = __gst_handle_library_error(core, error->code);
2903                         else if (error->domain == GST_CORE_ERROR)
2904                                 ret = __gst_handle_core_error(core, error->code);
2905                         else
2906                                 LOGW("Unexpected error has occured");
2907
2908                 g_mutex_lock(&core->drain_lock);
2909
2910                 if (core->need_drain) {
2911                         LOGD("@v(%d)e(%d) input port used----- single process_input.....", core->video, core->encoder);
2912                         core->need_drain = false;
2913                         g_cond_signal(&core->buffer_cond);
2914                 }
2915
2916                 g_mutex_unlock(&core->drain_lock);
2917
2918                         if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) {
2919                                 ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR])
2920                                         (ret, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]);
2921                                         LOGW("Error : %s (ox%08x)", _mc_error_to_string(ret), ret);
2922                         }
2923                 }
2924                 g_error_free(error);
2925         }
2926                 break;
2927
2928         default:
2929                 break;
2930         }
2931
2932         return TRUE;
2933 }
2934
2935 static gboolean __mc_gst_check_useful_message(mc_gst_core_t *core, GstMessage *msg)
2936 {
2937         gboolean retval = FALSE;
2938
2939         if (!core->pipeline) {
2940                 LOGE("mediacodec pipeline handle is null");
2941                 return TRUE;
2942         }
2943
2944         switch (GST_MESSAGE_TYPE(msg)) {
2945         case GST_MESSAGE_TAG:
2946         case GST_MESSAGE_EOS:
2947         case GST_MESSAGE_ERROR:
2948         case GST_MESSAGE_WARNING:
2949                 retval = TRUE;
2950                 break;
2951         default:
2952                 retval = FALSE;
2953                 break;
2954         }
2955
2956         return retval;
2957 }
2958
2959 static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data)
2960 {
2961         mc_gst_core_t *core = (mc_gst_core_t *)data;
2962         GstBusSyncReply reply = GST_BUS_DROP;
2963
2964         LOGD("__mc_gst_bus_sync_callback is called : %s", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
2965
2966         if (!core->pipeline) {
2967                 LOGE("mediacodec pipeline handle is null");
2968                 return GST_BUS_PASS;
2969         }
2970
2971         if (!__mc_gst_check_useful_message(core, msg)) {
2972                 gst_message_unref(msg);
2973                 return GST_BUS_DROP;
2974         }
2975
2976         switch (GST_MESSAGE_TYPE(msg)) {
2977         case GST_MESSAGE_EOS:
2978         case GST_MESSAGE_ERROR:
2979                 __mc_gst_bus_callback(NULL, msg, core);
2980                 reply = GST_BUS_DROP;
2981                 break;
2982
2983         default:
2984                 reply = GST_BUS_PASS;
2985                 break;
2986         }
2987
2988         if (reply == GST_BUS_DROP)
2989                 gst_message_unref(msg);
2990
2991         return reply;
2992 }
2993
2994 static GstMemory *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, GstMCBuffer *mcbuffer)
2995 {
2996         int ret = MEDIA_PACKET_ERROR_NONE;
2997         tbm_surface_h surface = NULL;
2998         GstMemory *mem = NULL;
2999
3000         if (!mcbuffer->packet) {
3001                 LOGE("output is null");
3002                 return NULL;
3003         }
3004
3005         if (!_mc_gst_video_info_check_and_new(core, mcbuffer)) {
3006                 LOGE("video info failed");
3007                 return NULL;
3008         }
3009
3010         ret = media_packet_get_tbm_surface(mcbuffer->packet, &surface);
3011         if (ret != MEDIA_PACKET_ERROR_NONE) {
3012                 LOGE("Failed to get tbm surface");
3013                 return NULL;
3014         }
3015
3016         mem = gst_tizen_allocator_alloc_surface(core->allocator,
3017                         core->video_info, surface, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb);
3018
3019         return mem;
3020 }
3021
3022 static void __mc_input_buffer_finalize_cb(GstMCBuffer *mcbuffer)
3023 {
3024         MEDIACODEC_FENTER();
3025
3026         if (!mcbuffer)
3027                 return;
3028
3029         LOGD("============>>>>>  _finalize_cb  : %p, %p", mcbuffer, mcbuffer->packet);
3030
3031         _mc_gst_handle_input_buffer_used(mcbuffer->core, mcbuffer->packet);
3032
3033         g_free(mcbuffer);
3034
3035         MEDIACODEC_FLEAVE();
3036 }
3037
3038 static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h packet, uint64_t size)
3039 {
3040         GstMCBuffer *mcbuffer = NULL;
3041
3042         mcbuffer = g_new0(GstMCBuffer, 1);
3043
3044         mcbuffer->buffer = gst_buffer_new();
3045         mcbuffer->buf_size = 0;
3046
3047         LOGD("creating buffer : %p, %p", mcbuffer, mcbuffer->buffer);
3048         mcbuffer->core = core;
3049         mcbuffer->packet = packet;
3050
3051         return mcbuffer;
3052 }
3053
3054 static gint __gst_handle_core_error(mc_gst_core_t *core, int code)
3055 {
3056         gint trans_err = MEDIACODEC_ERROR_NONE;
3057
3058         g_return_val_if_fail(core, MC_PARAM_ERROR);
3059
3060         switch (code) {
3061         case GST_CORE_ERROR_MISSING_PLUGIN:
3062                 return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT;
3063         case GST_CORE_ERROR_STATE_CHANGE:
3064         case GST_CORE_ERROR_SEEK:
3065         case GST_CORE_ERROR_NOT_IMPLEMENTED:
3066         case GST_CORE_ERROR_FAILED:
3067         case GST_CORE_ERROR_TOO_LAZY:
3068         case GST_CORE_ERROR_PAD:
3069         case GST_CORE_ERROR_THREAD:
3070         case GST_CORE_ERROR_NEGOTIATION:
3071         case GST_CORE_ERROR_EVENT:
3072         case GST_CORE_ERROR_CAPS:
3073         case GST_CORE_ERROR_TAG:
3074         case GST_CORE_ERROR_CLOCK:
3075         case GST_CORE_ERROR_DISABLED:
3076         default:
3077                 trans_err =  MEDIACODEC_ERROR_INVALID_STREAM;
3078                 break;
3079         }
3080
3081         return trans_err;
3082 }
3083
3084 static gint __gst_handle_library_error(mc_gst_core_t *core, int code)
3085 {
3086         gint trans_err = MEDIACODEC_ERROR_NONE;
3087
3088         g_return_val_if_fail(core, MC_PARAM_ERROR);
3089
3090         switch (code) {
3091         case GST_LIBRARY_ERROR_FAILED:
3092         case GST_LIBRARY_ERROR_TOO_LAZY:
3093         case GST_LIBRARY_ERROR_INIT:
3094         case GST_LIBRARY_ERROR_SHUTDOWN:
3095         case GST_LIBRARY_ERROR_SETTINGS:
3096         case GST_LIBRARY_ERROR_ENCODE:
3097         default:
3098                 trans_err =  MEDIACODEC_ERROR_INVALID_STREAM;
3099                 break;
3100         }
3101
3102         return trans_err;
3103 }
3104
3105
3106 static gint __gst_handle_resource_error(mc_gst_core_t *core, int code)
3107 {
3108         gint trans_err = MEDIACODEC_ERROR_NONE;
3109
3110         g_return_val_if_fail(core, MC_PARAM_ERROR);
3111
3112         switch (code) {
3113         case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
3114                 trans_err = MEDIACODEC_ERROR_NO_FREE_SPACE;
3115                 break;
3116         case GST_RESOURCE_ERROR_WRITE:
3117         case GST_RESOURCE_ERROR_FAILED:
3118         case GST_RESOURCE_ERROR_SEEK:
3119         case GST_RESOURCE_ERROR_TOO_LAZY:
3120         case GST_RESOURCE_ERROR_BUSY:
3121         case GST_RESOURCE_ERROR_OPEN_WRITE:
3122         case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
3123         case GST_RESOURCE_ERROR_CLOSE:
3124         case GST_RESOURCE_ERROR_SYNC:
3125         case GST_RESOURCE_ERROR_SETTINGS:
3126         default:
3127                 trans_err = MEDIACODEC_ERROR_INTERNAL;
3128                 break;
3129         }
3130
3131         return trans_err;
3132 }
3133
3134 static gint __gst_handle_stream_error(mc_gst_core_t *core, GError *error, GstMessage *message)
3135 {
3136         gint trans_err = MEDIACODEC_ERROR_NONE;
3137
3138         g_return_val_if_fail(core, MC_PARAM_ERROR);
3139         g_return_val_if_fail(error, MC_PARAM_ERROR);
3140         g_return_val_if_fail(message, MC_PARAM_ERROR);
3141
3142         switch (error->code) {
3143         case GST_STREAM_ERROR_FAILED:
3144         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
3145         case GST_STREAM_ERROR_DECODE:
3146         case GST_STREAM_ERROR_WRONG_TYPE:
3147         case GST_STREAM_ERROR_DECRYPT:
3148         case GST_STREAM_ERROR_DECRYPT_NOKEY:
3149         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
3150                 trans_err = __gst_transform_gsterror(core, message, error);
3151                 break;
3152
3153         case GST_STREAM_ERROR_NOT_IMPLEMENTED:
3154         case GST_STREAM_ERROR_TOO_LAZY:
3155         case GST_STREAM_ERROR_ENCODE:
3156         case GST_STREAM_ERROR_DEMUX:
3157         case GST_STREAM_ERROR_MUX:
3158         case GST_STREAM_ERROR_FORMAT:
3159         default:
3160                 trans_err = MEDIACODEC_ERROR_INVALID_STREAM;
3161                 break;
3162         }
3163
3164         return trans_err;
3165 }
3166
3167 static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage *message, GError *error)
3168 {
3169         gchar *src_element_name = NULL;
3170         GstElement *src_element = NULL;
3171         GstElementFactory *factory = NULL;
3172         const gchar *klass = NULL;
3173
3174
3175         src_element = GST_ELEMENT_CAST(message->src);
3176         if (!src_element)
3177                 goto INTERNAL_ERROR;
3178
3179         src_element_name = GST_ELEMENT_NAME(src_element);
3180         if (!src_element_name)
3181                 goto INTERNAL_ERROR;
3182
3183         factory = gst_element_get_factory(src_element);
3184         if (!factory)
3185                 goto INTERNAL_ERROR;
3186
3187         klass = gst_element_factory_get_klass(factory);
3188         if (!klass)
3189                 goto INTERNAL_ERROR;
3190
3191         LOGD("error code=%d, msg=%s, src element=%s, class=%s\n",
3192                         error->code, error->message, src_element_name, klass);
3193
3194         switch (error->code) {
3195         case GST_STREAM_ERROR_DECODE:
3196         case GST_STREAM_ERROR_FAILED:
3197                 return MEDIACODEC_ERROR_INVALID_STREAM;
3198                 break;
3199
3200         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
3201         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
3202         case GST_STREAM_ERROR_WRONG_TYPE:
3203                 return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT;
3204                 break;
3205
3206         default:
3207                 return MEDIACODEC_ERROR_INTERNAL;
3208                 break;
3209         }
3210
3211 INTERNAL_ERROR:
3212         return MEDIACODEC_ERROR_INTERNAL;
3213 }
3214
3215 static gint _mc_gst_flush_buffers(mc_gst_core_t *core)
3216 {
3217         gboolean ret = FALSE;
3218         GstEvent *event = NULL;
3219
3220         MEDIACODEC_FENTER();
3221
3222         _mc_gst_set_flush_input(core);
3223
3224         LOGW("Trying send flush_start .... ");
3225         event = gst_event_new_flush_start();
3226         ret = gst_element_send_event(core->appsrc, event);
3227         if (ret != TRUE) {
3228                 LOGE("failed to send Flush_Start event");
3229                 return MC_ERROR;
3230         }
3231
3232         LOGW("Trying send flush_stop .... ");
3233         event = gst_event_new_flush_stop(TRUE);
3234         ret = gst_element_send_event(core->appsrc, event);
3235         if (ret != TRUE) {
3236                 LOGE("failed to send Flush_Stop event");
3237                 return MC_ERROR;
3238         }
3239
3240         LOGW("Trying send seek .... ");
3241         event = gst_event_new_seek(1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
3242                         GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1);
3243
3244         ret = gst_element_send_event(core->appsrc, event);
3245         if (ret != TRUE) {
3246                 LOGE("failed to send seek event");
3247                 return MC_ERROR;
3248         }
3249
3250         _mc_gst_set_flush_output(core);
3251
3252         MEDIACODEC_FLEAVE();
3253
3254         return MC_ERROR_NONE;
3255 }
3256
3257
3258 static void _mc_gst_set_flush_input(mc_gst_core_t *core)
3259 {
3260         media_packet_h packet = NULL;
3261
3262         MEDIACODEC_FENTER();
3263         LOGI("_mc_gst_set_flush_input called : input_queue_len = %d, etb_count = %d", core->available_queue->input->length, core->etb_count);
3264
3265         while (!mc_async_queue_is_empty(core->available_queue->input)) {
3266                 packet = mc_async_queue_pop_forced(core->available_queue->input);
3267                 LOGD("%p poped(%d)", packet, core->etb_count);
3268
3269                 _mc_gst_handle_input_buffer_used(core, packet);
3270         }
3271
3272         mc_async_queue_flush(core->available_queue->input);
3273         LOGI("_mc_gst_set_flush_input ended : input_queue_len = %d, etb_count = %d", core->available_queue->input->length, core->etb_count);
3274         MEDIACODEC_FLEAVE();
3275 }
3276
3277 static void _mc_gst_set_flush_output(mc_gst_core_t *core)
3278 {
3279         media_packet_h packet = NULL;
3280
3281         MEDIACODEC_FENTER();
3282
3283         g_mutex_lock(&core->ports[1]->mutex);
3284
3285         while ((packet = g_queue_pop_head(core->ports[1]->queue))) {
3286                 LOGD("release packet[%p]", packet);
3287                 media_packet_unref(packet);
3288         }
3289
3290         g_mutex_unlock(&core->ports[1]->mutex);
3291
3292         MEDIACODEC_FLEAVE();
3293 }
3294
3295 #if TIZEN_EXYNOS_SPECIFIC
3296 /*
3297  * Get tiled address of position(x,y)
3298  *
3299  * @param x_size
3300  *   width of tiled[in]
3301  *
3302  * @param y_size
3303  *   height of tiled[in]
3304  *
3305  * @param x_pos
3306  *   x position of tield[in]
3307  *
3308  * @param src_size
3309  *   y position of tield[in]
3310  *
3311  * @return
3312  *   address of tiled data
3313  */
3314 static gint __tile_4x2_read(gint x_size, gint y_size, gint x_pos, gint y_pos)
3315 {
3316         gint pixel_x_m1, pixel_y_m1;
3317         gint roundup_x;
3318         gint linear_addr0, linear_addr1, bank_addr ;
3319         gint x_addr;
3320         gint trans_addr;
3321
3322         pixel_x_m1 = x_size - 1;
3323         pixel_y_m1 = y_size - 1;
3324
3325         roundup_x = ((pixel_x_m1 >> 7) + 1);
3326
3327         x_addr = x_pos >> 2;
3328
3329         if ((y_size <= y_pos+32) && (y_pos < y_size) &&
3330                         (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) {
3331                 linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
3332                 linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f));
3333
3334                 if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
3335                         bank_addr = ((x_addr >> 4) & 0x1);
3336                 else
3337                         bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
3338         } else {
3339                 linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
3340                 linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f));
3341
3342                 if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
3343                         bank_addr = ((x_addr >> 4) & 0x1);
3344                 else
3345                         bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
3346         }
3347
3348         linear_addr0 = linear_addr0 << 2;
3349         trans_addr = (linear_addr1 << 13) | (bank_addr << 11) | linear_addr0;
3350
3351         return trans_addr;
3352 }
3353
3354 /*
3355  * Converts tiled data to linear
3356  * Crops left, top, right, buttom
3357  * 1. Y of NV12T to Y of YUV420P
3358  * 2. Y of NV12T to Y of YUV420S
3359  * 3. UV of NV12T to UV of YUV420S
3360  *
3361  * @param yuv420_dest
3362  *   Y or UV plane address of YUV420[out]
3363  *
3364  * @param nv12t_src
3365  *   Y or UV plane address of NV12T[in]
3366  *
3367  * @param yuv420_width
3368  *   Width of YUV420[in]
3369  *
3370  * @param yuv420_height
3371  *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
3372  *
3373  * @param left
3374  *   Crop size of left
3375  *
3376  * @param top
3377  *   Crop size of top
3378  *
3379  * @param right
3380  *   Crop size of right
3381  *
3382  * @param buttom
3383  *   Crop size of buttom
3384  */
3385 static void __csc_tiled_to_linear_crop(gchar *yuv420_dest, gchar *nv12t_src,
3386                 gint yuv420_width, gint yuv420_height,
3387                 gint left, int top, gint right, gint buttom)
3388 {
3389         gint i, j;
3390         gint tiled_offset = 0, tiled_offset1 = 0;
3391         gint linear_offset = 0;
3392         gint temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0;
3393
3394         temp3 = yuv420_width-right;
3395         temp1 = temp3-left;
3396         /* real width is greater than or equal 256 */
3397         if (temp1 >= 256) {
3398                 for (i = top; i < yuv420_height-buttom; i += 1) {
3399                         j = left;
3400                         temp3 = (j>>8)<<8;
3401                         temp3 = temp3>>6;
3402                         temp4 = i>>5;
3403                         if (temp4 & 0x1) {
3404                                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
3405                                 tiled_offset = temp4-1;
3406                                 temp1 = ((yuv420_width+127)>>7)<<7;
3407                                 tiled_offset = tiled_offset*(temp1>>6);
3408                                 tiled_offset = tiled_offset+temp3;
3409                                 tiled_offset = tiled_offset+2;
3410                                 temp1 = (temp3>>2)<<2;
3411                                 tiled_offset = tiled_offset+temp1;
3412                                 tiled_offset = tiled_offset<<11;
3413                                 tiled_offset1 = tiled_offset+2048*2;
3414                                 temp4 = 8;
3415                         } else {
3416                                 temp2 = ((yuv420_height+31)>>5)<<5;
3417                                 if ((i + 32) < temp2) {
3418                                         /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
3419                                         temp1 = temp3+2;
3420                                         temp1 = (temp1>>2)<<2;
3421                                         tiled_offset = temp3+temp1;
3422                                         temp1 = ((yuv420_width+127)>>7)<<7;
3423                                         tiled_offset = tiled_offset+temp4*(temp1>>6);
3424                                         tiled_offset = tiled_offset<<11;
3425                                         tiled_offset1 = tiled_offset + 2048 * 6;
3426                                         temp4 = 8;
3427                                 } else {
3428                                         /* even2 fomula: x+x_block_num*y */
3429                                         temp1 = ((yuv420_width+127)>>7)<<7;
3430                                         tiled_offset = temp4*(temp1>>6);
3431                                         tiled_offset = tiled_offset+temp3;
3432                                         tiled_offset = tiled_offset<<11;
3433                                         tiled_offset1 = tiled_offset+2048*2;
3434                                         temp4 = 4;
3435                                 }
3436                         }
3437
3438                         temp1 = i&0x1F;
3439                         tiled_offset = tiled_offset+64*(temp1);
3440                         tiled_offset1 = tiled_offset1+64*(temp1);
3441                         temp2 = yuv420_width-left-right;
3442                         linear_offset = temp2*(i-top);
3443                         temp3 = ((j+256)>>8)<<8;
3444                         temp3 = temp3-j;
3445                         temp1 = left&0x3F;
3446
3447                         if (temp3 > 192) {
3448                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+temp1, 64-temp1);
3449                                 temp2 = ((left+63)>>6)<<6;
3450                                 temp3 = ((yuv420_width-right)>>6)<<6;
3451
3452                                 if (temp2 == temp3)
3453                                         temp2 = yuv420_width-right-(64-temp1);
3454
3455                                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset+2048, 64);
3456                                 memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1, 64);
3457                                 memcpy(yuv420_dest+linear_offset+192-temp1, nv12t_src+tiled_offset1+2048, 64);
3458                                 linear_offset = linear_offset+256-temp1;
3459                         } else if (temp3 > 128) {
3460                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+2048+temp1, 64-temp1);
3461                                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1, 64);
3462                                 memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1+2048, 64);
3463                                 linear_offset = linear_offset+192-temp1;
3464                         } else if (temp3 > 64) {
3465                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+temp1, 64-temp1);
3466                                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1+2048, 64);
3467                                 linear_offset = linear_offset+128-temp1;
3468                         } else if (temp3 > 0) {
3469                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+2048+temp1, 64-temp1);
3470                                 linear_offset = linear_offset+64-temp1;
3471                         }
3472
3473                         tiled_offset = tiled_offset+temp4*2048;
3474                         j = (left>>8)<<8;
3475                         j = j + 256;
3476                         temp2 = yuv420_width-right-256;
3477                         for (; j <= temp2; j += 256) {
3478                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3479                                 tiled_offset1 = tiled_offset1+temp4*2048;
3480                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
3481                                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
3482                                 tiled_offset = tiled_offset+temp4*2048;
3483                                 memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, 64);
3484                                 linear_offset = linear_offset+256;
3485                         }
3486
3487                         tiled_offset1 = tiled_offset1+temp4*2048;
3488                         temp2 = yuv420_width-right-j;
3489                         if (temp2 > 192) {
3490                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3491                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
3492                                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
3493                                 memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, temp2-192);
3494                         } else if (temp2 > 128) {
3495                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3496                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
3497                                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, temp2-128);
3498                         } else if (temp2 > 64) {
3499                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3500                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, temp2-64);
3501                         } else {
3502                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
3503                         }
3504                 }
3505         } else if (temp1 >= 64) {
3506                 for (i = top; i < (yuv420_height-buttom); i += 1) {
3507                         j = left;
3508                         tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3509                         temp2 = ((j+64)>>6)<<6;
3510                         temp2 = temp2-j;
3511                         linear_offset = temp1*(i-top);
3512                         temp4 = j&0x3;
3513                         tiled_offset = tiled_offset+temp4;
3514                         memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
3515                         linear_offset = linear_offset+temp2;
3516                         j = j+temp2;
3517                         if ((j+64) <= temp3) {
3518                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3519                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3520                                 linear_offset = linear_offset+64;
3521                                 j = j+64;
3522                         }
3523                         if ((j+64) <= temp3) {
3524                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3525                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3526                                 linear_offset = linear_offset+64;
3527                                 j = j+64;
3528                         }
3529                         if (j < temp3) {
3530                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3531                                 temp2 = temp3-j;
3532                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
3533                         }
3534                 }
3535         } else {
3536                 for (i = top; i < (yuv420_height-buttom); i += 1) {
3537                         linear_offset = temp1*(i-top);
3538                         for (j = left; j < (yuv420_width - right); j += 2) {
3539                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3540                                 temp4 = j&0x3;
3541                                 tiled_offset = tiled_offset+temp4;
3542                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 2);
3543                                 linear_offset = linear_offset+2;
3544                         }
3545                 }
3546         }
3547 }
3548 #endif
3549
3550 void _mc_send_eos_signal(mc_gst_core_t *core)
3551 {
3552         g_mutex_lock(&core->eos_mutex);
3553         core->eos = FALSE;
3554         g_cond_broadcast(&core->eos_cond);
3555         g_mutex_unlock(&core->eos_mutex);
3556         LOGD("send EOS signal");
3557 }
3558
3559 void _mc_wait_for_eos(mc_gst_core_t *core)
3560 {
3561         g_mutex_lock(&core->eos_mutex);
3562         core->eos = TRUE;
3563         LOGD("waiting for EOS");
3564
3565         while (core->eos)
3566                 g_cond_wait(&core->eos_cond, &core->eos_mutex);
3567
3568         LOGD("received EOS");
3569         g_mutex_unlock(&core->eos_mutex);
3570 }
3571
3572 const gchar * _mc_error_to_string(mc_ret_e err)
3573 {
3574         guint err_u = (guint) err;
3575
3576         switch (err_u) {
3577         case MC_ERROR:
3578                 return "Error";
3579         case MC_PARAM_ERROR:
3580                 return "Parameter error";
3581         case MC_INVALID_ARG:
3582                 return "Invailid argument";
3583         case MC_PERMISSION_DENIED:
3584                 return "Permission denied";
3585         case MC_INVALID_STATUS:
3586                 return "Invalid status";
3587         case MC_NOT_SUPPORTED:
3588                 return "Not supported";
3589         case MC_INVALID_IN_BUF:
3590                 return "Invalid inputbuffer";
3591         case MC_INVALID_OUT_BUF:
3592                 return "Invalid outputbuffer";
3593         case MC_INTERNAL_ERROR:
3594                 return "Internal error";
3595         case MC_HW_ERROR:
3596                 return "Hardware error";
3597         case MC_NOT_INITIALIZED:
3598                 return "Not initialized";
3599         case MC_INVALID_STREAM:
3600                 return "Invalid stream";
3601         case MC_CODEC_NOT_FOUND:
3602                 return "Codec not found";
3603         case MC_ERROR_DECODE:
3604                 return "Decode error";
3605         case MC_OUTPUT_BUFFER_EMPTY:
3606                 return "Outputbuffer empty";
3607         case MC_OUTPUT_BUFFER_OVERFLOW:
3608                 return "Outputbuffer overflow";
3609         case MC_MEMORY_ALLOCED:
3610                 return "Memory allocated";
3611         case MC_COURRPTED_INI:
3612                 return "Courrpted ini";
3613         default:
3614                 return "Unknown error";
3615
3616         }
3617 }
3618
3619 const gchar * _mc_bit_to_string(int bit)
3620 {
3621         switch (bit) {
3622         case 16:
3623                 return "S16LE";
3624         case 32:
3625                 return "F32LE";
3626         default:
3627                 return "NULL";
3628
3629         }
3630 }
3631
3632 int _mc_get_mime(mc_gst_core_t *core)
3633 {
3634         media_format_mimetype_e mime = MEDIA_FORMAT_MAX;
3635
3636         switch (core->codec_id) {
3637         case MEDIACODEC_H264:
3638                 if (core->encoder)
3639                         mime = (core->is_hw) ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420;
3640                 else
3641                         mime = MEDIA_FORMAT_H264_SP;
3642                 break;
3643         case MEDIACODEC_MPEG4:
3644                 if (core->encoder)
3645                         mime = (core->is_hw) ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420;
3646                 else
3647                         mime = MEDIA_FORMAT_MPEG4_SP;
3648
3649                 break;
3650         case MEDIACODEC_H263:
3651                 if (core->encoder)
3652                         mime = (core->is_hw) ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420;
3653                 else
3654                         mime = MEDIA_FORMAT_H263P;
3655
3656                 break;
3657         case MEDIACODEC_AAC:
3658                 if (core->encoder)
3659                         mime = MEDIA_FORMAT_PCM_F32LE;  /*FIXME need to change PCM supported by chipset */
3660                 else
3661                         mime = MEDIA_FORMAT_AAC;
3662
3663                 break;
3664         case MEDIACODEC_AAC_HE:
3665                 if (core->encoder)
3666                         mime = MEDIA_FORMAT_PCM_F32LE;  /* FIXME need to change PCM supported by chipset */
3667                 else
3668                         mime = MEDIA_FORMAT_AAC_HE;
3669
3670                 break;
3671         case MEDIACODEC_AAC_HE_PS:
3672                 break;
3673         case MEDIACODEC_MP3:
3674                 mime = MEDIA_FORMAT_MP3;
3675                 break;
3676         case MEDIACODEC_VORBIS:
3677                 break;
3678         case MEDIACODEC_FLAC:
3679                 break;
3680         case MEDIACODEC_WMAV1:
3681                 break;
3682         case MEDIACODEC_WMAV2:
3683                 break;
3684         case MEDIACODEC_WMAPRO:
3685                 break;
3686         case MEDIACODEC_WMALSL:
3687                 break;
3688         case MEDIACODEC_AMR_NB:
3689                 mime = MEDIA_FORMAT_AMR_NB;
3690                 break;
3691         case MEDIACODEC_AMR_WB:
3692                 mime = MEDIA_FORMAT_AMR_WB;
3693                 break;
3694         case MEDIACODEC_OPUS:
3695                 if (core->encoder)
3696                         mime = MEDIA_FORMAT_OPUS;
3697                 else
3698                         mime = MEDIA_FORMAT_PCM_S16LE;
3699                 break;
3700         default:
3701                 LOGE("NOT SUPPORTED!!!! 0x%x ", core->codec_id);
3702                 break;
3703         }
3704         return mime;
3705 }
3706
3707 mc_ret_e mc_gst_get_packet_pool(mc_handle_t *mc_handle, media_packet_pool_h *packet_pool)
3708 {
3709         gint ret = MC_ERROR_NONE;
3710         gint curr_size;
3711         gint max_size, min_size;
3712         media_format_mimetype_e mime_format = MEDIA_FORMAT_MAX;
3713         media_format_h fmt_handle = NULL;
3714         media_packet_pool_h pool = NULL;
3715         mc_gst_core_t *core = NULL;
3716
3717         if (!mc_handle)
3718                 return MC_PARAM_ERROR;
3719
3720         core = (mc_gst_core_t *)mc_handle->core;
3721
3722         ret = media_packet_pool_create(&pool);
3723         if (ret != MEDIA_PACKET_ERROR_NONE) {
3724                 LOGE("media_packet_pool_create failed");
3725                 return MC_ERROR;
3726         }
3727
3728         if (media_format_create(&fmt_handle) != MEDIA_FORMAT_ERROR_NONE) {
3729                 LOGE("media format create failed");
3730                 media_packet_pool_destroy(pool);
3731                 return MC_ERROR;
3732         }
3733
3734         mime_format = _mc_get_mime(core);
3735
3736         if (core->video) {
3737                 media_format_set_video_mime(fmt_handle, mime_format);
3738                 media_format_set_video_width(fmt_handle, mc_handle->info.video.width);
3739                 media_format_set_video_height(fmt_handle, mc_handle->info.video.height);
3740
3741                 if (core->encoder)
3742                         media_format_set_video_avg_bps(fmt_handle, mc_handle->info.video.bitrate);
3743         } else {
3744                         media_format_set_audio_mime(fmt_handle, mime_format);
3745                         media_format_set_audio_channel(fmt_handle, mc_handle->info.audio.channel);
3746                         media_format_set_audio_samplerate(fmt_handle, mc_handle->info.audio.samplerate);
3747                         media_format_set_audio_bit(fmt_handle, mc_handle->info.audio.bit_depth);
3748                 if (core->encoder)
3749                         media_format_set_audio_avg_bps(fmt_handle, mc_handle->info.audio.bitrate);
3750         }
3751
3752         ret = media_packet_pool_set_media_format(pool, fmt_handle);
3753         if (ret != MEDIA_PACKET_ERROR_NONE) {
3754                 media_packet_pool_destroy(pool);
3755                 LOGE("media_packet_pool_set_media_format failed");
3756                 return MC_ERROR;
3757         }
3758
3759         /* will use default size temporarily */
3760         max_size = core->encoder ? DEFAULT_ENC_POOL_SIZE : DEFAULT_DEC_POOL_SIZE;
3761
3762         min_size = max_size;
3763         ret = media_packet_pool_set_size(pool, min_size, max_size);
3764         if (ret != MEDIA_PACKET_ERROR_NONE) {
3765                 media_packet_pool_destroy(pool);
3766                 LOGE("media_packet_pool_set_size failed");
3767                 return MC_ERROR;
3768         }
3769
3770         ret = media_packet_pool_allocate(pool);
3771         if (ret != MEDIA_PACKET_ERROR_NONE) {
3772                 media_packet_pool_destroy(pool);
3773                 LOGE("media_packet_pool_allocate failed");
3774                 return MC_OUT_OF_MEMORY;
3775         }
3776         media_packet_pool_get_size(pool, &min_size, &max_size, &curr_size);
3777         LOGD("curr_size is  %d min_size is %d and max_size is %d \n", curr_size, min_size, max_size);
3778
3779         *packet_pool = pool;
3780         return MC_ERROR_NONE;
3781 }
3782
3783 mc_ret_e mc_gst_set_property_array_int(GstElement *element, const gchar *property_name, gint *array, guint array_length)
3784 {
3785         guint i = 0;
3786         GValue value = G_VALUE_INIT;
3787         GValue tmp = G_VALUE_INIT;
3788
3789         if (!element || !property_name || !array) {
3790                 LOGE("NULL param[%p,%p,%p]", element, property_name, array);
3791                 return MC_PARAM_ERROR;
3792         }
3793
3794         g_value_init(&value, GST_TYPE_ARRAY);
3795         g_value_init(&tmp, G_TYPE_INT);
3796
3797         LOGI("set element[%s], property[%s], array_length[%d]",
3798                 GST_ELEMENT_NAME(element), property_name, array_length);
3799
3800         gst_value_array_init(&value, array_length);
3801
3802         for (i = 0 ; i < array_length ; i++) {
3803                 LOGI("    array[%u] %d", i, array[i]);
3804                 g_value_set_int(&tmp, array[i]);
3805                 gst_value_array_append_value(&value, &tmp);
3806         }
3807
3808         g_object_set_property(G_OBJECT(element), property_name, &value);
3809
3810         g_value_unset(&tmp);
3811         g_value_unset(&value);
3812
3813         return MC_ERROR_NONE;
3814 }