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