74fd6389bd8bf6919a014f231876be535fd2ea95
[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         GstVideoMeta *vmeta = NULL;
1199
1200         if (!core || !core->video_info || !buffer)
1201                 return;
1202
1203         vmeta = gst_buffer_add_video_meta_full(buffer, GST_VIDEO_FRAME_FLAG_NONE,
1204                 GST_VIDEO_INFO_FORMAT(core->video_info),
1205                 GST_VIDEO_INFO_WIDTH(core->video_info),
1206                 GST_VIDEO_INFO_HEIGHT(core->video_info),
1207                 GST_VIDEO_INFO_N_PLANES(core->video_info),
1208                 core->video_info->offset,
1209                 core->video_info->stride);
1210
1211         if (!vmeta) {
1212                 LOGE("No video meta");
1213                 return;
1214         }
1215
1216         if (core->is_hw) {
1217                 vmeta->map = gst_tizen_video_meta_map;
1218                 vmeta->unmap = gst_tizen_video_meta_unmap;
1219         }
1220 }
1221
1222 static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool codec_config)
1223 {
1224         MEDIACODEC_FENTER();
1225
1226         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
1227         g_return_val_if_fail(mcbuffer != NULL, MC_PARAM_ERROR);
1228
1229         int ret = MC_ERROR_NONE;
1230
1231         switch (core->codec_id) {
1232         case MEDIACODEC_AAC:
1233         case MEDIACODEC_AAC_HE:
1234         case MEDIACODEC_AAC_HE_PS:
1235                 if (codec_config) {
1236                         ret = __mc_set_caps_codecdata(core, mcbuffer, AAC_CODECDATA_SIZE);
1237                         if (ret != MC_ERROR_NONE)
1238                                 LOGW("__mc_set_caps_codecdata failed");
1239                 }
1240                 break;
1241         case MEDIACODEC_WMAV1:
1242         case MEDIACODEC_WMAV2:
1243         case MEDIACODEC_WMAPRO:
1244         case MEDIACODEC_WMALSL:
1245                 if (codec_config) {
1246                         ret = __mc_set_caps_codecdata(core, mcbuffer, WMA_CODECDATA_SIZE);
1247                         if (ret != MC_ERROR_NONE)
1248                                 LOGW("__mc_set_caps_codecdata failed");
1249                 }
1250                 break;
1251         case MEDIACODEC_VORBIS:
1252         case MEDIACODEC_FLAC:
1253         case MEDIACODEC_OPUS:
1254                 if (codec_config) {
1255                         ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE);
1256                         if (ret != MC_ERROR_NONE)
1257                                 LOGW("__mc_set_caps_streamheader failed");
1258                 }
1259                 break;
1260         case MEDIACODEC_H264:
1261         case MEDIACODEC_MPEG4:
1262                 ret = __mc_set_caps_codecdata(core, mcbuffer, CODECDATA_NOT_USE);
1263                 if (ret != MC_ERROR_NONE)
1264                         LOGW("__mc_set_caps_codecdata failed");
1265                 break;
1266         default:
1267                 LOGD("doesn't need to set codecdata");
1268                 break;
1269         }
1270
1271         MEDIACODEC_FLEAVE();
1272         return ret;
1273
1274
1275 }
1276
1277 static gpointer feed_task(gpointer data)
1278 {
1279         gint ret = MC_ERROR_NONE;
1280         bool codec_config = FALSE;
1281         bool eos = FALSE;
1282         bool initiative = TRUE;
1283         bool is_format_change = FALSE;
1284         media_format_h format = NULL;
1285         media_packet_h input_buffer = NULL;
1286         GstMCBuffer *mcbuffer = NULL;
1287
1288         MEDIACODEC_FENTER();
1289
1290         mc_gst_core_t *core = (mc_gst_core_t *)data;
1291
1292         while (g_atomic_int_get(&core->available_queue->running)) {
1293                 LOGD("waiting for next input....");
1294                 input_buffer = _mc_get_input_buffer(core);
1295                 if (!input_buffer)
1296                         goto LEAVE;
1297
1298                 media_packet_get_format(input_buffer,  &format);
1299                 if (format) {
1300                         if (_mc_update_packet_info(core, format)) {
1301                                 is_format_change = TRUE;
1302                                 if (!core->mc_caps_new(core, core->codec_id, in_port_index)) {
1303                                         LOGE("caps new failed");
1304                                         goto ERROR;
1305                                 }
1306                         }
1307                         media_format_unref(format);
1308                 }
1309
1310                 if (media_packet_is_codec_config(input_buffer, &codec_config) != MEDIA_PACKET_ERROR_NONE) {
1311                         LOGE("media_packet_is_codec_config failed");
1312                         goto ERROR;
1313                 }
1314
1315                 if (media_packet_is_end_of_stream(input_buffer, &eos) != MEDIA_PACKET_ERROR_NONE) {
1316                         LOGE("media_packet_is_end_of_stream failed");
1317                         goto ERROR;
1318                 }
1319                 /*
1320                  * receive an eos packet. For decoder + encoder case, encoder always get tbm surface plane first from input data,
1321                  * but eos packet only has flag not valid data, so we don't put it to downstream.
1322                  */
1323                 if (eos) {
1324                         LOGD("end of stream");
1325                         gst_app_src_end_of_stream(GST_APP_SRC(core->appsrc));
1326                         _mc_wait_for_eos(core);
1327                         initiative = TRUE;
1328
1329                         _mc_gst_handle_input_buffer_used(core, input_buffer);
1330                         goto LEAVE;
1331                 }
1332
1333                 mcbuffer = _mc_gst_media_packet_to_gstbuffer(core, input_buffer, codec_config);
1334                 if (!mcbuffer) {
1335                         LOGW("gstbuffer can't make");
1336                         goto ERROR;
1337                 }
1338                 /* mcbuffer took the ownership of the input_buffer, so set input_buffer to NULL to aviod double unref */
1339                 input_buffer = NULL;
1340
1341                 if (codec_config || initiative) {
1342                         GstPad *pad = NULL;
1343                         if (!core->encoder) {
1344                                 ret = _mc_set_codec_data(core, mcbuffer, codec_config);
1345                                 if (ret != MC_ERROR_NONE) {
1346                                         LOGE("failed to set codec data");
1347                                         gst_buffer_unref(mcbuffer->buffer);
1348                                         goto ERROR;
1349                                 }
1350                         }
1351                         pad = gst_element_get_static_pad(core->appsrc, "src");
1352                         gst_pad_push_event(pad, gst_event_new_stream_start("start"));
1353                         gst_object_unref(pad);
1354                         is_format_change = TRUE;
1355                         initiative = FALSE;
1356                         core->offset = GST_BUFFER_OFFSET_NONE;
1357                 }
1358
1359                 if (is_format_change) {
1360                         g_object_set(core->appsrc, "caps", core->caps, NULL);
1361
1362                         if (core->encoder) {
1363                                 int bitrate = core->video ? \
1364                                         core->ports[in_port_index]->port_def.info.video.bitrate : \
1365                                         core->ports[in_port_index]->port_def.info.audio.bitrate;
1366
1367                                 g_object_set(core->codec, core->codec_type->property->bitrate_name, bitrate, NULL);
1368
1369                                 LOGI("bitrate[property:%s,v:%d] %d updated",
1370                                         core->codec_type->property->bitrate_name, core->video, bitrate);
1371                         }
1372
1373                         is_format_change = FALSE;
1374                 }
1375
1376
1377                 /* inject buffer */
1378                 ret = _mc_gst_gstbuffer_to_appsrc(core, mcbuffer);
1379                 if (ret != GST_FLOW_OK) {
1380                         LOGE("Failed to push gst buffer");
1381                         goto ERROR;
1382                 }
1383
1384                 continue;
1385 ERROR:
1386                 if (input_buffer)
1387                         _mc_gst_handle_input_buffer_used(core, input_buffer);
1388
1389                 _mc_gst_set_flush_input(core);
1390
1391                 if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) {
1392                         ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR])
1393                                 (MC_INTERNAL_ERROR, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]);
1394                 }
1395
1396                 continue;
1397 LEAVE:
1398                 /*LOGE("status : input_buffer : %p, codec_config : %d, eos : %d, encoder : %d in feed_task", input_buffer, codec_config, eos, core->encoder);*/
1399                 continue;
1400
1401         }
1402
1403         LOGI("status : input_buffer : %p, codec_config : %d, eos : %d, video : %d, encoder : %d in feed_task",
1404                         input_buffer, codec_config, eos, core->video, core->encoder);
1405         LOGD("feed task finished %p v(%d)e(%d)", core, core->video, core->encoder);
1406
1407         MEDIACODEC_FLEAVE();
1408
1409         return NULL;
1410 }
1411
1412 static void _mc_gst_feed_task_new(mc_gst_core_t *core)
1413 {
1414         g_return_if_fail(core && core->available_queue);
1415
1416         g_atomic_int_set(&core->available_queue->running, 1);
1417         core->available_queue->thread = g_thread_new("feed thread", &feed_task, core);
1418
1419         LOGI("new thread for feed[%p]", core->available_queue->thread);
1420 }
1421
1422 static void _mc_gst_feed_task_free(mc_gst_core_t *core)
1423 {
1424         g_return_if_fail(core && core->available_queue);
1425
1426         mc_async_queue_disable(core->available_queue->input);
1427
1428         g_atomic_int_set(&core->available_queue->running, 0);
1429         g_thread_join(core->available_queue->thread);
1430
1431         LOGI("feed thread[%p] is released", core->available_queue->thread);
1432 }
1433
1434 static void __mc_gst_stop_feed(GstElement *pipeline, gpointer data)
1435 {
1436         mc_gst_core_t *core = (mc_gst_core_t *)data;
1437
1438         LOGI("stop_feed called");
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_ENOUGH_DATA, core->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]);
1442         }
1443 }
1444
1445 static void __mc_gst_start_feed(GstElement *pipeline, guint size, gpointer data)
1446 {
1447         mc_gst_core_t *core = (mc_gst_core_t *)data;
1448
1449         LOGI("start_feed called");
1450
1451         if (core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) {
1452                 ((mc_buffer_status_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS])
1453                         (MEDIACODEC_NEED_DATA, core->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]);
1454         }
1455 }
1456
1457 static gboolean _mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index)
1458 {
1459         gchar *caps_string = NULL;
1460         g_autoptr(GstCaps) caps = NULL;
1461         mc_gst_port_def_t *port_def = &core->ports[index]->port_def;
1462
1463         caps = gst_caps_new_simple(core->mime,
1464                 "rate", G_TYPE_INT, port_def->info.audio.samplerate,
1465                 "channels", G_TYPE_INT, port_def->info.audio.channel, NULL);
1466
1467         switch (codec_id) {
1468         case MEDIACODEC_AAC:
1469                 if (core->encoder) {
1470                         gst_caps_set_simple(caps,
1471                                 "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth),
1472                                 "layout", G_TYPE_STRING, "interleaved", NULL);
1473                         g_object_set(GST_OBJECT(core->codec), "compliance", -2, NULL);
1474                 } else {
1475                         gst_caps_set_simple(caps,
1476                                 "framed", G_TYPE_BOOLEAN, TRUE,
1477                                 "mpegversion", G_TYPE_INT, 4,
1478                                 "stream-format", G_TYPE_STRING, "adts",
1479                                 NULL);
1480                         LOGD("CAPS for codec_id (MEDIACODEC_AAC_LC - normal ADTS)");
1481                 }
1482                 break;
1483         case MEDIACODEC_AAC_HE:
1484         case MEDIACODEC_AAC_HE_PS:
1485                 if (core->encoder) {
1486                         LOGD("[MC_NOT_SUPPORTED] he-aac-v12 encoder is not supported yet!!!");
1487                         return FALSE;
1488                 } else {
1489                         gst_caps_set_simple(caps,
1490                                 "mpegversion", G_TYPE_INT, 4,
1491                                 "framed", G_TYPE_BOOLEAN, TRUE,
1492                                 "stream-format", G_TYPE_STRING, "raw",
1493                                 NULL);
1494                         LOGD("CAPS for codec_id (MEDIACODEC_AAC_HE)");
1495                 }
1496                 break;
1497         case MEDIACODEC_MP3:
1498                 if (core->encoder) {
1499                         LOGD("[MC_NOT_SUPPORTED] mp3 encoder is not supported yet!!!");
1500                         return FALSE;
1501                 } else {
1502                         gst_caps_set_simple(caps,
1503                                 "framed", G_TYPE_BOOLEAN, TRUE,
1504                                 "mpegversion", G_TYPE_INT, 1,       /* To-Do : plz check */
1505                                 "mpegaudioversion", G_TYPE_INT, 1,  /* To-Do : plz check */
1506                                 "layer", G_TYPE_INT, 3,             /* To-Do : plz check */
1507                                 NULL);
1508                         LOGD("CAPS for codec_id (MEDIACODEC_MP3)");
1509                 }
1510                 break;
1511         case MEDIACODEC_AMR_NB:
1512                 if (core->encoder) {
1513                         gst_caps_set_simple(caps,
1514                                 "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth),
1515                                 "layout", G_TYPE_STRING, "interleaved",
1516                                 NULL);
1517                         LOGD("CAPS for codec_id (MEDIACODEC_AMR_NB)");
1518                 } else {
1519                         gst_caps_set_simple(caps,
1520                                 "rate", G_TYPE_INT, 8000,
1521                                 NULL);
1522                 }
1523                 break;
1524         case MEDIACODEC_AMR_WB:
1525                 if (core->encoder) {
1526                         LOGD("[MC_NOT_SUPPORTED] amr-wb encoder is not supported yet!!!");
1527                         return FALSE;
1528                 } else {
1529                         gst_caps_set_simple(caps,
1530                                 "rate", G_TYPE_INT, 16000,
1531                                 NULL);
1532                 }
1533                 break;
1534         case MEDIACODEC_VORBIS:
1535                 if (core->encoder) {
1536                         LOGD("[MC_NOT_SUPPORTED] vorbis encoder is not supported yet!!!");
1537                         return FALSE;
1538                 } else {
1539                 }
1540                 break;
1541         case MEDIACODEC_FLAC:
1542                 if (core->encoder) {
1543                         LOGD("[MC_NOT_SUPPORTED] flac encoder is not supported yet!!!");
1544                         return FALSE;
1545                 } else {
1546                         gst_caps_set_simple(caps,
1547                                 "framed", G_TYPE_BOOLEAN, TRUE,
1548                                 /* FIXME - Insert More Info */
1549                                 NULL);
1550                 }
1551                 break;
1552         case MEDIACODEC_WMAV1:
1553         case MEDIACODEC_WMAV2:
1554         case MEDIACODEC_WMAPRO:
1555         case MEDIACODEC_WMALSL:
1556                 if (core->encoder) {
1557                         LOGD("[MC_NOT_SUPPORTED] wma encoder is not supported yet!!!");
1558                         return FALSE;
1559                 } else {
1560                         /*
1561                          * Need to extract from Stream Type Specific ... or
1562                          * Need to get Demuxer's Caps from Stream Type Specific
1563                          */
1564                         guint16 format_tag = 0;
1565                         gint wma_version = 0;
1566                         gint block_align = 1024;      /*FIXME : Need checking */
1567                         gint bitrate = 128000;        /*FIXME : Need checking */
1568
1569                         LOGD(" ----- WMA Need Additional Caps -----------");
1570                         if (core->codec_id == MEDIACODEC_WMAV1) {
1571                                 format_tag = 352;       /* 0x160 */
1572                                 wma_version = 1;
1573                         } else if (core->codec_id == MEDIACODEC_WMAV2) {
1574                                 format_tag = 353;       /* 0x161 */
1575                                 wma_version = 2;
1576                         } else if (core->codec_id == MEDIACODEC_WMAPRO) {
1577                                 format_tag = 354;       /* 0x162 */
1578                                 wma_version = 3;
1579                         } else if (core->codec_id == MEDIACODEC_WMALSL) {
1580                                 format_tag = 355;       /* 0x163 */
1581                                 wma_version = 3;
1582                         } else {
1583                                 LOGE("Not support WMA format");
1584                         }
1585
1586                         gst_caps_set_simple(caps,
1587                                 "bitrate", G_TYPE_INT, bitrate,
1588                                 "depth", G_TYPE_INT, port_def->info.audio.bit_depth,
1589                                 /* FIXME - Need More Info */
1590                                 "wmaversion", G_TYPE_INT, wma_version,
1591                                 "format_tag", G_TYPE_INT, format_tag,
1592                                 "block_align", G_TYPE_INT, block_align,
1593                                 NULL);
1594                 }
1595                 break;
1596         case MEDIACODEC_OPUS:
1597                 if (core->encoder) {
1598                         gst_caps_set_simple(caps,
1599                                 "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth),
1600                                 "layout", G_TYPE_STRING, "interleaved", NULL);
1601                 } else {
1602                         LOGD("[MC_NOT_SUPPORTED] opus decoder is not supported yet!!!");
1603                         return FALSE;
1604                 }
1605                 break;
1606         default:
1607                 break;
1608         }
1609
1610         caps_string = gst_caps_to_string(caps);
1611         if (caps_string) {
1612                 LOGI("new caps[%p:%s]", caps, caps_string);
1613                 g_free(caps_string);
1614         }
1615
1616         if (core->caps)
1617                 gst_caps_unref(core->caps);
1618
1619         _mc_gst_video_info_free(core);
1620
1621         core->caps = g_steal_pointer(&caps);
1622
1623         return TRUE;
1624 }
1625
1626 static gboolean _mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index)
1627 {
1628         gchar *caps_string = NULL;
1629         GstCaps *caps = NULL;
1630         mc_gst_port_def_t *port_def = &core->ports[index]->port_def;
1631
1632         caps = gst_caps_new_simple(core->mime,
1633                 "width", G_TYPE_INT, port_def->info.video.width,
1634                 "height", G_TYPE_INT, port_def->info.video.height,
1635                 "framerate", GST_TYPE_FRACTION, port_def->info.video.framerate, 1,
1636                 NULL);
1637
1638         switch (codec_id) {
1639         case MEDIACODEC_H263:
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                                 "framerate", GST_TYPE_FRACTION, 30, 1,
1648                                 NULL);
1649                 }
1650                 break;
1651         case MEDIACODEC_MPEG4:
1652                 if (core->encoder) {
1653                         gst_caps_set_simple(caps,
1654                                 "format", G_TYPE_STRING, port_def->info.video.format,
1655                                 NULL);
1656                 } else {
1657                         gst_caps_set_simple(caps,
1658                                 "mpegversion", G_TYPE_INT, 4,
1659                                 "systemstream", G_TYPE_BOOLEAN, false,
1660                                 "parsed", G_TYPE_BOOLEAN, TRUE,
1661                                 "framerate", GST_TYPE_FRACTION, 30, 1,
1662                                 NULL);
1663                 }
1664                 break;
1665         case MEDIACODEC_H264:
1666                 if (core->encoder) {
1667                         gst_caps_set_simple(caps,
1668                                 "format", G_TYPE_STRING, port_def->info.video.format,
1669                                 NULL);
1670                         g_object_set(GST_OBJECT(core->codec), "byte-stream", TRUE, NULL);
1671                         LOGE("format : %s", port_def->info.video.format);
1672                 } else {
1673                         gst_caps_set_simple(caps,
1674                                 "parsed", G_TYPE_BOOLEAN, TRUE,  /* FIXME different from sw */
1675                                 "alignment", G_TYPE_STRING, "au",
1676                                 "stream-format", G_TYPE_STRING, "byte-stream",
1677                                 "framerate", GST_TYPE_FRACTION, 30, 1,
1678                                 NULL);
1679                 }
1680                 break;
1681         default:
1682                 break;
1683         }
1684
1685         caps_string = gst_caps_to_string(caps);
1686         if (caps_string) {
1687                 LOGI("new caps[%p:%s]", caps, caps_string);
1688                 g_free(caps_string);
1689         }
1690
1691         if (core->caps)
1692                 gst_caps_unref(core->caps);
1693         _mc_gst_video_info_free(core);
1694
1695         core->caps = caps;
1696
1697         return TRUE;
1698 }
1699
1700 static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboolean encoder, gboolean is_hw)
1701 {
1702         MEDIACODEC_FENTER();
1703
1704         g_return_val_if_fail(core != NULL, MC_PARAM_ERROR);
1705
1706         switch (id) {
1707         case MEDIACODEC_AAC:
1708                 if (encoder)
1709                         core->vtable = aenc_aac_vtable;
1710                 else
1711                         core->vtable = adec_aac_vtable;
1712                 break;
1713         case MEDIACODEC_AAC_HE:
1714         case MEDIACODEC_AAC_HE_PS:
1715                 if (encoder) {
1716                         LOGD("[MC_NOT_SUPPORTED] he-aac-v12 encoder is not supported yet!!!");
1717                         return MC_NOT_SUPPORTED;
1718                 } else {
1719                         core->vtable = adec_aacv12_vtable;
1720                 }
1721                 break;
1722         case MEDIACODEC_MP3:
1723                 if (encoder) {
1724                         LOGD("[MC_NOT_SUPPORTED] mp3 encoder is not supported yet!!!");
1725                         return MC_NOT_SUPPORTED;
1726                 } else {
1727                         core->vtable = adec_mp3_vtable;
1728                 }
1729                 break;
1730         case MEDIACODEC_AMR_NB:
1731                 LOGD("amrnb vtable");
1732                 if (encoder)
1733                         core->vtable = aenc_amrnb_vtable;
1734                 else
1735                         core->vtable = adec_amrnb_vtable;
1736                 break;
1737         case MEDIACODEC_AMR_WB:
1738                 LOGD("amrwb vtable - Only support decoder");
1739                 if (encoder) {
1740                         LOGD("[MC_NOT_SUPPORTED] amr-wb encoder is not supported yet!!!");
1741                         return MC_NOT_SUPPORTED;
1742                 } else {
1743                         core->vtable = adec_amrwb_vtable;
1744                 }
1745                 break;
1746         case MEDIACODEC_VORBIS:
1747                 LOGD("vorbis vtable");
1748                 if (encoder)
1749                         return MC_NOT_SUPPORTED;
1750                 else
1751                         core->vtable = adec_vorbis_vtable;
1752                 break;
1753         case MEDIACODEC_FLAC:
1754                 LOGD("flac vtable");
1755                 if (encoder) {
1756                         LOGD("[MC_NOT_SUPPORTED] flac encoder is not supported yet!!!");
1757                         return MC_NOT_SUPPORTED;
1758                 } else {
1759                         core->vtable = adec_flac_vtable;
1760                 }
1761                 break;
1762         case MEDIACODEC_OPUS:
1763                 LOGD("opus vtable");
1764                 if (encoder)
1765                         core->vtable = aenc_opus_vtable;
1766                 else
1767                         core->vtable = adec_vtable;
1768                 break;
1769         case MEDIACODEC_WMAV1:
1770         case MEDIACODEC_WMAV2:
1771         case MEDIACODEC_WMAPRO:
1772         case MEDIACODEC_WMALSL:
1773                 LOGD("wma(V1 / V2 / LSL / PRO) vtable");
1774                 if (encoder) {
1775                         LOGD("[MC_NOT_SUPPORTED] wma encoder is not supported yet!!!");
1776                         return MC_NOT_SUPPORTED;
1777                 } else {
1778                         core->vtable = adec_wma_vtable;
1779                 }
1780                 break;
1781         case MEDIACODEC_H263:
1782                 LOGD("h263 vtable");
1783                 if (encoder) {
1784                         core->vtable = is_hw ? venc_h263_hw_vtable : venc_h263_sw_vtable;
1785                 } else {
1786                         if (is_hw)
1787                                 core->vtable = vdec_h263_hw_vtable;
1788                         else
1789                                 core->vtable = vdec_h263_sw_vtable;
1790                 }
1791                 break;
1792         case MEDIACODEC_MPEG4:
1793                 LOGD("mpeg4 vtable");
1794                 if (encoder)
1795                         core->vtable = is_hw ? venc_mpeg4_hw_vtable : venc_mpeg4_sw_vtable;
1796                 else
1797                         core->vtable = is_hw ? vdec_mpeg4_hw_vtable : vdec_mpeg4_sw_vtable;
1798                 break;
1799         case MEDIACODEC_H264:
1800                 LOGD("h264 vtable");
1801                 if (encoder) {
1802                         core->vtable = is_hw ? venc_h264_hw_vtable : venc_vtable;
1803                 } else {
1804                         if (is_hw)
1805                                 core->vtable = vdec_h264_hw_vtable;
1806                         else
1807                                 core->vtable = vdec_h264_sw_vtable;
1808                 }
1809                 break;
1810         default:
1811                 break;
1812         }
1813
1814         MEDIACODEC_FLEAVE();
1815
1816         return MC_ERROR_NONE;
1817 }
1818
1819 static gint _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *mcbuffer)
1820 {
1821         return gst_app_src_push_buffer(GST_APP_SRC(core->appsrc), mcbuffer->buffer);
1822 }
1823
1824 media_packet_h _mc_get_input_buffer(mc_gst_core_t *core)
1825 {
1826         LOGD("waiting for input...");
1827         return mc_async_queue_pop(core->available_queue->input);
1828 }
1829
1830 mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle)
1831 {
1832         int ret = MC_ERROR_NONE;
1833         int num_supported_codec = 0;
1834         int i = 0;
1835         bool video;
1836         bool encoder;
1837         bool hardware;
1838         gchar *factory_name = NULL;
1839         media_format_mimetype_e out_mime;
1840         mediacodec_codec_type_e id;
1841         mc_codec_map_t *codec_map;
1842
1843         MEDIACODEC_FENTER();
1844
1845         if (!mc_handle)
1846                 return MC_PARAM_ERROR;
1847
1848         id = mc_handle->codec_id;
1849         video = mc_handle->is_video;
1850         encoder = mc_handle->is_encoder;
1851         hardware = mc_handle->is_hw;
1852         codec_map = encoder ? mc_handle->encoder_map : mc_handle->decoder_map;
1853         num_supported_codec = encoder ? mc_handle->num_supported_encoder : mc_handle->num_supported_decoder;
1854
1855         for (i = 0; i < num_supported_codec; i++) {
1856                 if ((id == codec_map[i].id) && (hardware == codec_map[i].hardware))
1857                         break;
1858         }
1859
1860         if (i == num_supported_codec)
1861                 return MC_NOT_SUPPORTED;
1862
1863         factory_name = codec_map[i].type.factory_name;
1864         out_mime = codec_map[i].type.out_format;
1865
1866         /* gst_core create */
1867         mc_gst_core_t *new_core = mc_gst_core_new();
1868
1869         new_core->mime = codec_map[i].type.mime;
1870         new_core->is_hw = hardware;
1871         new_core->eos = false;
1872         new_core->encoder = encoder;
1873         new_core->video = video;
1874         memcpy(&new_core->ports[in_port_index]->port_def.info, &mc_handle->info, sizeof(mc_handle->info));
1875         memcpy(&new_core->ports[out_port_index]->port_def.info, &mc_handle->info, sizeof(mc_handle->info));
1876         new_core->ports[out_port_index]->port_def.coding_type = out_mime;
1877         new_core->codec_id = id;
1878         new_core->codec_type = &codec_map[i].type;
1879         new_core->mc_caps_new = video ? &_mc_gst_vid_caps_new : &_mc_gst_aud_caps_new;
1880
1881         new_core->bufmgr = tbm_bufmgr_init(new_core->drm_fd);
1882         if (new_core->bufmgr == NULL) {
1883                 LOGE("TBM initialization failed");
1884                 return MC_ERROR;
1885         }
1886
1887         LOGD("@%p(%p) core is initializing...v(%d)e(%d)", mc_handle, new_core, new_core->video, new_core->encoder);
1888         LOGD("factory name : %s, output_fmt : %x", factory_name, out_mime);
1889
1890         /* create media_packet for output fmt */
1891         ret = _mc_output_media_packet_new(new_core, video, encoder, out_mime);
1892         if (ret != MC_ERROR_NONE) {
1893                 LOGE("Failed to create output pakcet");
1894                 return ret;
1895         }
1896
1897         for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER ; i++) {
1898                 LOGD("copy cb function [%d]", i);
1899                 if (mc_handle->user_cb[i]) {
1900                         new_core->user_cb[i] = mc_handle->user_cb[i];
1901                         new_core->user_data[i] = mc_handle->user_data[i];
1902                         LOGD("user_cb[%d] %p, %p", i, new_core->user_cb[i], mc_handle->user_cb[i]);
1903                 }
1904         }
1905
1906         /* create basic core elements */
1907         ret = _mc_gst_create_pipeline(new_core, factory_name);
1908         if (ret != MC_ERROR_NONE) {
1909                 LOGE("failed to create pipeline");
1910                 return ret;
1911         }
1912
1913         /* link vtable */
1914         ret = _mc_link_vtable(new_core, id, encoder, hardware);
1915         if (ret != MC_ERROR_NONE) {
1916                 LOGE("vtable link failed");
1917                 return ret;
1918         }
1919
1920         /* set caps in capsfilter as default*/
1921         if (!new_core->mc_caps_new(new_core, id, out_port_index)) {
1922                 LOGE("caps new failed");
1923                 return MC_INTERNAL_ERROR;
1924         }
1925
1926         /* FIXME will parse input format from ini. format is needed when linking elements*/
1927         if (new_core->video && new_core->encoder) {
1928                 gst_caps_set_simple(new_core->caps,
1929                         "format", G_TYPE_STRING, (new_core->is_hw ? "SN12" : "I420"),
1930                         NULL);
1931         }
1932
1933         g_object_set(new_core->capsfilter, "caps", new_core->caps, NULL);
1934
1935         _mc_gst_feed_task_new(new_core);
1936
1937         mc_handle->core = new_core;
1938         LOGD("initialized... %d", ret);
1939         MEDIACODEC_FLEAVE();
1940
1941         return ret;
1942 }
1943
1944 mc_ret_e mc_gst_unprepare(mc_handle_t *mc_handle)
1945 {
1946         MEDIACODEC_FENTER();
1947
1948         int i;
1949         int ret = MC_ERROR_NONE;
1950         mc_gst_core_t *core = NULL;
1951
1952         if (!mc_handle)
1953                 return MC_PARAM_ERROR;
1954
1955         core = (mc_gst_core_t *)mc_handle->core;
1956
1957         if (core) {
1958                 LOGD("@%p(%p) core is uninitializing... v(%d)e(%d)", mc_handle, core, core->video, core->encoder);
1959
1960                 g_mutex_lock(&core->drain_lock);
1961                 core->unprepare_flag = TRUE;
1962                 g_mutex_unlock(&core->drain_lock);
1963
1964                 if (core->eos)
1965                         _mc_send_eos_signal(core);
1966
1967                 _mc_gst_feed_task_free(core);
1968
1969                 _mc_gst_set_flush_input(core);
1970
1971                 _mc_gst_video_info_free(core);
1972
1973                 ret = _mc_gst_destroy_pipeline(core);
1974
1975                 /* unset callback */
1976                 for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER; i++) {
1977                         LOGD("unset cb function [%d]", i);
1978                         if (mc_handle->user_cb[i]) {
1979                                 core->user_cb[i] = NULL;
1980                                 core->user_data[i] = NULL;
1981                                 LOGD("user_cb[%d] %p, %p", i, core->user_cb[i], mc_handle->user_cb[i]);
1982                         }
1983                 }
1984
1985                 media_format_unref(core->output_fmt);
1986
1987                 if (core->bufmgr != NULL) {
1988                         tbm_bufmgr_deinit(core->bufmgr);
1989                         core->bufmgr = NULL;
1990                 }
1991
1992                 if (core->drm_fd != -1) {
1993                         close(core->drm_fd);
1994                         LOGD("close drm_fd");
1995                 }
1996
1997                 if (core != NULL) {
1998                         mc_gst_core_free(core);
1999                         mc_handle->core = NULL;
2000                 }
2001         }
2002
2003         MEDIACODEC_FLEAVE();
2004
2005         return ret;
2006 }
2007
2008 mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeout_us)
2009 {
2010         MEDIACODEC_FENTER();
2011
2012         int ret = MC_ERROR_NONE;
2013         mc_gst_core_t *core = NULL;
2014
2015         if (!mc_handle)
2016                 return MC_PARAM_ERROR;
2017
2018         core = (mc_gst_core_t *)mc_handle->core;
2019
2020         g_mutex_lock(&core->drain_lock);
2021
2022         while (g_atomic_int_get(&core->etb_count) == MAXINUM_QNUM) {
2023                 LOGD("Waiting until packets are drained..");
2024                 core->need_drain = true;
2025                 g_cond_wait(&core->buffer_cond, &core->drain_lock);
2026         }
2027         g_mutex_unlock(&core->drain_lock);
2028
2029         if (core->prepare_count == 0)
2030                 return MC_INVALID_STATUS;
2031
2032         g_mutex_lock(&core->drain_lock);
2033
2034         if (!core->eos || !core->unprepare_flag) {
2035                 mc_async_queue_push(core->available_queue->input, inbuf);
2036
2037         } else {
2038                 ret = MC_INVALID_IN_BUF;
2039                 g_mutex_unlock(&core->drain_lock);
2040                 return ret;
2041         }
2042
2043         g_mutex_unlock(&core->drain_lock);
2044         g_atomic_int_inc(&core->etb_count);
2045         LOGI("@v(%d)e(%d)process_input(%d): %p", core->video, core->encoder, core->etb_count, inbuf);
2046
2047         MEDIACODEC_FLEAVE();
2048
2049         return ret;
2050 }
2051
2052 mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeout_us)
2053 {
2054         gint ret = MC_ERROR_NONE;
2055         gint64 end_time = -1;
2056         gboolean signalled;
2057         mc_gst_core_t *core = NULL;
2058         media_packet_h out_packet = NULL;
2059
2060         MEDIACODEC_FENTER();
2061         end_time = g_get_monotonic_time() + timeout_us;
2062
2063         if (!mc_handle)
2064                 return MC_PARAM_ERROR;
2065
2066         core = (mc_gst_core_t *)mc_handle->core;
2067
2068         g_mutex_lock(&core->ports[1]->mutex);
2069
2070         if (!g_queue_is_empty(core->ports[1]->queue))
2071                 signalled = TRUE;
2072         else {
2073                 LOGD("no buffer, wait for signal");
2074                 signalled = g_cond_wait_until(&core->out_buffer_cond, &core->ports[1]->mutex, end_time);
2075         }
2076
2077         if (signalled)
2078                 out_packet = g_queue_pop_head(core->ports[1]->queue);
2079         else {
2080                 LOGW("Failed to get buffer");
2081                 ret = MC_OUTPUT_BUFFER_EMPTY;
2082         }
2083
2084         *outbuf = out_packet;
2085         LOGI("@%p v(%d)e(%d) got buffer :%p", core, core->video, core->encoder, out_packet);
2086
2087         g_mutex_unlock(&core->ports[1]->mutex);
2088
2089         MEDIACODEC_FLEAVE();
2090
2091         return ret;
2092 }
2093
2094 mc_ret_e mc_gst_flush_buffers(mc_handle_t *mc_handle)
2095 {
2096         gint ret = MC_ERROR_NONE;
2097         mc_gst_core_t *core = NULL;
2098
2099         MEDIACODEC_FENTER();
2100
2101         if (!mc_handle)
2102                 return MC_PARAM_ERROR;
2103
2104         core = (mc_gst_core_t *)mc_handle->core;
2105         LOGI("@%p v(%d)e(%d) flush_buffers", core, core->video, core->encoder);
2106
2107         ret = _mc_gst_flush_buffers(core);
2108
2109         MEDIACODEC_FLEAVE();
2110
2111         return ret;
2112 }
2113
2114 static gboolean __mc_gst_init_gstreamer()
2115 {
2116         MEDIACODEC_FENTER();
2117
2118         gint i = 0;
2119         gint arg_count = 0;
2120         static gboolean initialized = FALSE;
2121         static const int max_argc = 50;
2122         gint *argc = NULL;
2123         gchar **argv = NULL;
2124         gchar **argv2 = NULL;
2125         GError *err = NULL;
2126
2127         if (initialized) {
2128                 LOGD("gstreamer already initialized.\n");
2129                 return TRUE;
2130         }
2131
2132         /* alloc */
2133         argc = malloc(sizeof(int));
2134         argv = malloc(sizeof(gchar *) *max_argc);
2135         argv2 = malloc(sizeof(gchar *) *max_argc);
2136
2137         if (!argc || !argv || !argv2)
2138                 goto ERROR;
2139
2140         memset(argv, 0, sizeof(gchar *) *max_argc);
2141         memset(argv2, 0, sizeof(gchar *) *max_argc);
2142
2143         /* add initial */
2144         *argc = 1;
2145         argv[0] = g_strdup("media codec");
2146
2147         /* we would not do fork for scanning plugins */
2148         argv[*argc] = g_strdup("--gst-disable-registry-fork");
2149         (*argc)++;
2150
2151         /* check disable registry scan */
2152         argv[*argc] = g_strdup("--gst-disable-registry-update");
2153         (*argc)++;
2154
2155         /* check disable segtrap */
2156         argv[*argc] = g_strdup("--gst-disable-segtrap");
2157         (*argc)++;
2158
2159         LOGD("initializing gstreamer with following parameter\n");
2160         LOGD("argc : %d\n", *argc);
2161         arg_count = *argc;
2162
2163         for (i = 0; i < arg_count; i++) {
2164                 argv2[i] = argv[i];
2165                 LOGD("argv[%d] : %s\n", i, argv2[i]);
2166         }
2167
2168         /* initializing gstreamer */
2169         if (!gst_init_check(argc, &argv, &err)) {
2170                 LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
2171                 if (err)
2172                         g_error_free(err);
2173
2174                 goto ERROR;
2175         }
2176
2177         /* release */
2178         for (i = 0; i < arg_count; i++)
2179                 MC_FREEIF(argv2[i]);
2180
2181         MC_FREEIF(argv);
2182         MC_FREEIF(argv2);
2183         MC_FREEIF(argc);
2184
2185         /* done */
2186         initialized = TRUE;
2187
2188         MEDIACODEC_FLEAVE();
2189         return TRUE;
2190
2191 ERROR:
2192         /* release */
2193         for (i = 0; i < arg_count; i++) {
2194                 LOGD("free[%d] : %s\n", i, argv2[i]);
2195                 MC_FREEIF(argv2[i]);
2196         }
2197
2198         MC_FREEIF(argv);
2199         MC_FREEIF(argv2);
2200         MC_FREEIF(argc);
2201
2202         return FALSE;
2203 }
2204
2205 mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name)
2206 {
2207         int i = 0;
2208         int bitrate = 0;
2209         GstBus *bus = NULL;
2210
2211         MEDIACODEC_FENTER();
2212
2213         g_mutex_lock(&core->prepare_lock);
2214
2215         if (core->prepare_count == 0) {
2216                 if (!__mc_gst_init_gstreamer()) {
2217                         LOGE("gstreamer initialize fail");
2218                         g_mutex_unlock(&core->prepare_lock);
2219                         return MC_NOT_INITIALIZED;
2220                 }
2221
2222                 core->codec = gst_element_factory_make(factory_name, NULL);
2223                 if (!core->codec) {
2224                         LOGE("codec element create fail");
2225                         goto ERROR;
2226                 }
2227
2228                 LOGD("@%p v(%d)e(%d) create_pipeline", core, core->video, core->encoder);
2229                 MEDIACODEC_ELEMENT_SET_STATE(core->codec, GST_STATE_READY);
2230
2231                 /* create common elements */
2232                 core->pipeline = gst_pipeline_new(NULL);
2233                 if (!core->pipeline) {
2234                         LOGE("pipeline create fail");
2235                         goto ERROR;
2236                 }
2237
2238                 core->appsrc = gst_element_factory_make("appsrc", NULL);
2239                 if (!core->appsrc) {
2240                         LOGE("appsrc can't create");
2241                         goto ERROR;
2242                 }
2243
2244                 if (!core->video && core->encoder) {
2245                         core->audioconvert = gst_element_factory_make("audioconvert", NULL);
2246
2247                         if (!core->audioconvert) {
2248                                 LOGE("audioconvert can't create");
2249                                 goto ERROR;
2250                         }
2251
2252                         core->audioresample = gst_element_factory_make("audioresample", NULL);
2253
2254                         if (!core->audioresample) {
2255                                 LOGE("audioresample can't create");
2256                                 goto ERROR;
2257                         }
2258                 }
2259
2260                 if (core->video && core->encoder) {
2261                         core->videoconvert = gst_element_factory_make("videoconvert", NULL);
2262
2263                         if (!core->videoconvert) {
2264                                 LOGE("videoconvert can't create");
2265                                 goto ERROR;
2266                         }
2267
2268                         core->videoscale = gst_element_factory_make("videoscale", NULL);
2269                         if (!core->videoscale) {
2270                                 LOGE("videoscale can't create");
2271                                 goto ERROR;
2272                         }
2273                 }
2274
2275                 core->capsfilter = gst_element_factory_make("capsfilter", NULL);
2276                 if (!core->capsfilter) {
2277                         LOGE("capsfilter can't create");
2278                         goto ERROR;
2279                 }
2280
2281                 core->fakesink = gst_element_factory_make("fakesink", NULL);
2282                 if (!core->fakesink) {
2283                         LOGE("fakesink create fail");
2284                         goto ERROR;
2285                 }
2286
2287                 g_object_set(core->fakesink, "enable-last-sample", FALSE, NULL);
2288
2289                 /*__mc_link_elements(core);*/
2290                 if (!core->video && core->encoder) {
2291                         gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->audioresample, core->audioconvert, core->capsfilter, core->codec, core->fakesink, NULL);
2292
2293                         /* link elements */
2294                         if (!(gst_element_link_many(core->appsrc, core->audioresample, core->audioconvert, core->capsfilter, core->codec, core->fakesink, NULL))) {
2295                                 LOGE("gst_element_link_many is failed");
2296                                 goto ERROR;
2297                         }
2298                 } else if (core->video && core->encoder) {
2299                         gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL);
2300
2301                         /* link elements */
2302                         if (!(gst_element_link_many(core->appsrc, core->codec, core->fakesink, NULL))) {
2303                                 LOGE("gst_element_link_many is failed");
2304                                 goto ERROR;
2305                         }
2306                 } else {
2307                         gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL);
2308
2309                         /* link elements */
2310                         if (!(gst_element_link_many(core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL))) {
2311                                 LOGE("gst_element_link_many is failed");
2312                                 goto ERROR;
2313                         }
2314                 }
2315
2316                 /* connect signals, bus watcher */
2317                 bus = gst_pipeline_get_bus(GST_PIPELINE(core->pipeline));
2318                 core->bus_watch_id = gst_bus_add_watch(bus, __mc_gst_bus_callback, core);
2319                 core->thread_default = g_main_context_get_thread_default();
2320
2321                 /* set sync handler to get tag synchronously */
2322                 gst_bus_set_sync_handler(bus, __mc_gst_bus_sync_callback, core, NULL);
2323                 gst_object_unref(GST_OBJECT(bus));
2324
2325                 /* app src */
2326                 g_signal_connect(core->appsrc, "need-data", G_CALLBACK(__mc_gst_start_feed), core);
2327                 g_signal_connect(core->appsrc, "enough-data", G_CALLBACK(__mc_gst_stop_feed), core);
2328
2329                 /* connect handoff */
2330                 g_object_set(GST_OBJECT(core->fakesink), "signal-handoffs", TRUE, NULL);
2331                 core->signal_handoff = g_signal_connect(core->fakesink, "handoff", G_CALLBACK(__mc_gst_buffer_add), core);
2332
2333                 /* set bitrate and properties */
2334                 if (core->encoder) {
2335                         if (core->video)
2336                                 bitrate = core->ports[in_port_index]->port_def.info.video.bitrate;
2337                         else
2338                                 bitrate = core->ports[in_port_index]->port_def.info.audio.bitrate;
2339
2340                         LOGI("set encoder bitrate[property:%s,v:%d] %d",
2341                                 core->codec_type->property->bitrate_name, core->video, bitrate);
2342
2343                         g_object_set(core->codec,
2344                                 core->codec_type->property->bitrate_name, bitrate,
2345                                 NULL);
2346                 }
2347
2348                 for (i = 0 ; i < core->codec_type->property->ext_num ; i++) {
2349                         LOGI("set property [%s] -> [%s]",
2350                                 core->codec_type->property->ext_name[i],
2351                                 core->codec_type->property->ext_value[i]);
2352
2353                         gst_util_set_object_arg((GObject *)core->codec,
2354                                 core->codec_type->property->ext_name[i],
2355                                 core->codec_type->property->ext_value[i]);
2356                 }
2357
2358                 /* set state PLAYING */
2359                 MEDIACODEC_ELEMENT_SET_STATE(GST_ELEMENT_CAST(core->pipeline), GST_STATE_PLAYING);
2360         }
2361
2362         core->prepare_count++;
2363         g_mutex_unlock(&core->prepare_lock);
2364
2365         MEDIACODEC_FLEAVE();
2366
2367         return MC_ERROR_NONE;
2368
2369 STATE_CHANGE_FAILED:
2370 ERROR:
2371
2372         if (core->codec)
2373                 gst_object_unref(GST_OBJECT(core->codec));
2374
2375         if (core->pipeline)
2376                 gst_object_unref(GST_OBJECT(core->pipeline));
2377
2378         if (core->appsrc)
2379                 gst_object_unref(GST_OBJECT(core->appsrc));
2380
2381         if (core->capsfilter)
2382                 gst_object_unref(GST_OBJECT(core->capsfilter));
2383
2384         if (core->audioresample)
2385                 gst_object_unref(GST_OBJECT(core->audioresample));
2386
2387         if (core->videoscale)
2388                 gst_object_unref(GST_OBJECT(core->videoscale));
2389
2390         if (core->videoconvert)
2391                 gst_object_unref(GST_OBJECT(core->videoconvert));
2392
2393         if (core->audioconvert)
2394                 gst_object_unref(GST_OBJECT(core->audioconvert));
2395
2396         if (core->fakesink)
2397                 gst_object_unref(GST_OBJECT(core->fakesink));
2398
2399         g_mutex_unlock(&core->prepare_lock);
2400
2401         return MC_ERROR;
2402 }
2403
2404 mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core)
2405 {
2406         int ret = MC_ERROR_NONE;
2407
2408         MEDIACODEC_FENTER();
2409
2410         g_mutex_lock(&core->prepare_lock);
2411         core->prepare_count--;
2412         if (core->prepare_count == 0) {
2413
2414                 if (core->pipeline) {
2415                         /* disconnect signal */
2416                         if (core->fakesink && GST_IS_ELEMENT(core->fakesink)) {
2417                                 if (g_signal_handler_is_connected(core->fakesink, core->signal_handoff)) {
2418                                         g_signal_handler_disconnect(core->fakesink, core->signal_handoff);
2419                                         LOGD("handoff signal destroy");
2420                                 }
2421                         }
2422
2423                         if (core->bus_watch_id) {
2424                                 GSource *source = NULL;
2425                                 source = g_main_context_find_source_by_id(core->thread_default, core->bus_watch_id);
2426                                 g_source_destroy(source);
2427                                 LOGD("bus_watch_id destroy");
2428                         }
2429
2430                         MEDIACODEC_ELEMENT_SET_STATE(core->pipeline, GST_STATE_NULL);
2431
2432                         gst_object_unref(GST_OBJECT(core->pipeline));
2433
2434                         if (core->caps) {
2435                                 gst_caps_unref(core->caps);
2436                                 core->caps = NULL;
2437                         }
2438                 }
2439         }
2440
2441         LOGD("@%p v(%d)e(%d) destroy_pipeline : %d ", core, core->video, core->encoder, core->prepare_count);
2442         g_mutex_unlock(&core->prepare_lock);
2443
2444         MEDIACODEC_FLEAVE();
2445
2446         return ret;
2447
2448 STATE_CHANGE_FAILED:
2449         if (core->pipeline)
2450                 gst_object_unref(GST_OBJECT(core->pipeline));
2451
2452         LOGD("@%p v(%d)e(%d) destroy_pipeline failed", core, core->video, core->encoder);
2453         g_mutex_unlock(&core->prepare_lock);
2454
2455         return MC_ERROR;
2456 }
2457
2458 void __mc_push_output_to_queue(mc_gst_core_t *core, GstMCBuffer *mcbuffer)
2459 {
2460         g_mutex_lock(&core->ports[1]->mutex);
2461
2462         /* push it to output buffer queue */
2463         g_queue_push_tail(core->ports[1]->queue, mcbuffer->packet);
2464         g_cond_broadcast(&core->out_buffer_cond);
2465
2466         if (mcbuffer->buffer) {
2467                 LOGD("dq : v(%d)e(%d) TIMESTAMP = %"GST_TIME_FORMAT " DURATION = %"GST_TIME_FORMAT, core->video, core->encoder,
2468                         GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(mcbuffer->buffer)), GST_TIME_ARGS(GST_BUFFER_DURATION(mcbuffer->buffer)));
2469         } else {
2470                 LOGD("dq : v(%d)e(%d)", core->video, core->encoder);
2471         }
2472
2473         g_mutex_unlock(&core->ports[1]->mutex);
2474
2475         if (core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) {
2476                 ((mc_fill_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER])
2477                         (mcbuffer->packet, core->user_data[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]);
2478         }
2479 }
2480
2481 void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data)
2482 {
2483         GstMCBuffer *mcbuffer = NULL;
2484
2485         MEDIACODEC_FENTER();
2486
2487         mc_gst_core_t *core = (mc_gst_core_t *)data;
2488
2489         gst_buffer_ref(buffer);
2490
2491         mcbuffer = __mc_gst_make_media_packet(core, buffer);
2492
2493         LOGI("@%p(%d) out_packet : %p", core, core->encoder, mcbuffer->packet);
2494
2495         if (mcbuffer->packet) {
2496                 media_packet_set_pts(mcbuffer->packet, GST_BUFFER_TIMESTAMP(buffer));
2497                 media_packet_set_dts(mcbuffer->packet, GST_BUFFER_DTS(buffer));
2498                 media_packet_set_duration(mcbuffer->packet, GST_BUFFER_DURATION(buffer));
2499
2500                 if (core->need_codec_data) {
2501                         media_packet_set_flags(mcbuffer->packet, MEDIA_PACKET_CODEC_CONFIG);
2502                         core->need_codec_data = false;
2503                 }
2504
2505                 if (core->need_sync_flag) {
2506                         media_packet_set_flags(mcbuffer->packet, MEDIA_PACKET_SYNC_FRAME);
2507                         core->need_sync_flag = false;
2508                 }
2509
2510                 __mc_push_output_to_queue(core, mcbuffer);
2511         } else {
2512                 gst_buffer_unref(buffer);
2513                 LOGE("Failed to dequeue output packet");
2514         }
2515
2516         MEDIACODEC_FLEAVE();
2517
2518         return;
2519 }
2520
2521 int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data)
2522 {
2523         MEDIACODEC_FENTER();
2524
2525         GstMCBuffer *mcbuffer = (GstMCBuffer *)user_data;
2526
2527         gst_buffer_unref((GstBuffer *)mcbuffer->buffer);
2528
2529         if (mcbuffer->ext_mem) {
2530                 g_free(mcbuffer->ext_mem);
2531                 LOGD("freed external memory");
2532                 mcbuffer->ext_mem = NULL;
2533         }
2534
2535         LOGD("output port filled buffer : %p", packet);
2536         g_free(mcbuffer);
2537
2538         MEDIACODEC_FLEAVE();
2539
2540         return MEDIA_PACKET_FINALIZE;
2541 }
2542
2543 gchar *__mc_get_gst_input_format(media_format_mimetype_e mimetype, bool is_hw)
2544 {
2545         gchar *format = NULL;
2546
2547         switch (mimetype) {
2548         case MEDIA_FORMAT_I420:
2549                 format = "I420";
2550                 break;
2551         case MEDIA_FORMAT_NV12:
2552                 if (is_hw)
2553                         format = "SN12";
2554                 else
2555                         format = "NV12";
2556                 break;
2557         case MEDIA_FORMAT_ARGB:
2558                 format = "ARGB";
2559                 break;
2560         default:
2561                 break;
2562         }
2563
2564         LOGD("input packet format : %s", format ? format : "(null)" );
2565
2566         return format;
2567 }
2568
2569 GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet_h packet, bool codec_config)
2570 {
2571         gint ret = MEDIA_PACKET_ERROR_NONE;
2572         uint64_t buf_size = 0;
2573         uint64_t pts = 0;
2574         uint64_t dts = 0;
2575         uint64_t dur = 0;
2576         void *buf_data = NULL;
2577         GstMCBuffer *mcbuffer = NULL;
2578
2579         ret = media_packet_get_buffer_size(packet, &buf_size);
2580         if (ret != MEDIA_PACKET_ERROR_NONE) {
2581                 LOGW("buffer size get fail");
2582                 return NULL;
2583         }
2584
2585         ret = media_packet_get_buffer_data_ptr(packet, &buf_data);
2586         if (ret != MEDIA_PACKET_ERROR_NONE) {
2587                 LOGW("buffer data get fail");
2588                 return NULL;
2589         }
2590
2591         mcbuffer = gst_mediacodec_buffer_new(core, packet, buf_size);
2592         if (mcbuffer == NULL) {
2593                 LOGW("failed to create inbuf");
2594                 return NULL;
2595         }
2596
2597         LOGD("packet :v(%d)e(%d) %p, buf_size : %d", core->video, core->encoder, packet, (int)buf_size);
2598
2599         ret = __mc_fill_input_buffer(core, packet, mcbuffer);
2600         if (ret != MC_ERROR_NONE) {
2601                 LOGW("failed to fill inbuf: %s (ox%08x)", _mc_error_to_string(ret), ret);
2602                 /*
2603                  * if __mc_fill_input_buffer() failed, no memory appended to mcbuffer->buffer, so gst_mediacodec_buffer_finalize()
2604                  * will not be invoked
2605                  */
2606                 gst_buffer_unref(mcbuffer->buffer);
2607                 g_free(mcbuffer);
2608                 return NULL;
2609         }
2610
2611         /* dts */
2612         media_packet_get_pts(packet, &dts);
2613         GST_BUFFER_DTS(mcbuffer->buffer) = dts;
2614
2615         /* pts */
2616         media_packet_get_pts(packet, &pts);
2617         GST_BUFFER_PTS(mcbuffer->buffer) = pts;
2618
2619         /* duration */
2620         media_packet_get_duration(packet, &dur);
2621         GST_BUFFER_DURATION(mcbuffer->buffer) = dur;
2622
2623         GST_BUFFER_OFFSET(mcbuffer->buffer) = core->offset;
2624
2625         core->offset += buf_size;
2626         GST_BUFFER_OFFSET_END(mcbuffer->buffer) = core->offset;
2627
2628         return mcbuffer;
2629 }
2630
2631 GstMCBuffer *__mc_gst_make_media_packet(mc_gst_core_t *core, GstBuffer *buffer)
2632 {
2633         gint ret = MEDIA_PACKET_ERROR_NONE;
2634         GstMemory *mem;
2635         GstMapInfo map = GST_MAP_INFO_INIT;
2636         GstMCBuffer *mcbuffer = NULL;
2637         void *data = NULL;
2638         gint size = 0;
2639
2640         mem = gst_buffer_peek_memory(buffer, 0);
2641
2642         if (gst_is_tizen_memory(mem)) {
2643                 data = (void *)gst_tizen_memory_get_surface(mem);
2644                 size = tbm_surface_internal_get_size((tbm_surface_h)data);
2645         } else {
2646                 if (!gst_memory_map(mem, &map, GST_MAP_READ)) {
2647                         LOGE("gst_memory_map failed for buffer[%p]", buffer);
2648                         return NULL;
2649                 }
2650
2651                 data = map.data;
2652                 size = map.size;
2653         }
2654
2655         mcbuffer = g_new0(GstMCBuffer, 1);
2656
2657         mcbuffer->buffer = buffer;
2658         mcbuffer->core = core;
2659         mcbuffer->buf_size = size;
2660
2661         ret = __mc_fill_output_buffer(core, data, mcbuffer->buf_size,  mcbuffer);
2662
2663         if (!gst_is_tizen_memory(mem))
2664                 gst_memory_unmap(mem, &map);
2665
2666         if (ret != MC_ERROR_NONE) {
2667                 LOGW("failed to fill outbuf: %s (ox%08x)", _mc_error_to_string(ret), ret);
2668                 g_free(mcbuffer);
2669                 return NULL;
2670         }
2671
2672         return mcbuffer;
2673 }
2674
2675 int __mc_gst_create_eos_packet(media_format_h fmt, GstMCBuffer *mcbuffer)
2676 {
2677         gint ret = MC_ERROR_NONE;
2678         media_packet_h packet = NULL;
2679
2680         MEDIACODEC_FENTER();
2681         if (media_packet_create(fmt, __mc_output_buffer_finalize_cb, mcbuffer, &packet)) {
2682                 LOGE("media_packet_create failed\n");
2683                 ret = MC_ERROR;
2684                 goto ERROR;
2685         }
2686
2687         if (media_packet_set_flags(packet, MEDIA_PACKET_END_OF_STREAM)) {
2688                 LOGE("unable to set EOS flag\n");
2689                 ret = MC_ERROR;
2690                 goto ERROR;
2691         }
2692
2693         mcbuffer->buffer = NULL;
2694         mcbuffer->ext_mem = NULL;
2695         mcbuffer->buf_size = 0;
2696         mcbuffer->packet = packet;
2697         MEDIACODEC_FLEAVE();
2698
2699         return ret;
2700 ERROR:
2701         if (packet)
2702                 media_packet_unref(packet);
2703         MEDIACODEC_FLEAVE();
2704         return ret;
2705 }
2706
2707 void _mc_gst_handle_input_buffer_used(mc_gst_core_t *core, media_packet_h packet)
2708 {
2709         if (core) {
2710                 g_atomic_int_dec_and_test(&core->etb_count);
2711                 LOGD("@v(%d)e(%d) input port used(%d)----- ", core->video, core->encoder, core->etb_count);
2712         }
2713
2714         if (core && core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) {
2715                 ((mc_empty_buffer_cb)core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER])
2716                         (packet, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]);
2717
2718                 g_mutex_lock(&core->drain_lock);
2719
2720                 if (core->need_drain) {
2721                         LOGD("@v(%d)e(%d) input port used----- single process_input.....", core->video, core->encoder);
2722                         core->need_drain = false;
2723                         g_cond_signal(&core->buffer_cond);
2724                 }
2725                 g_mutex_unlock(&core->drain_lock);
2726         }
2727 }
2728
2729 gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data)
2730 {
2731         gint ret  = MC_ERROR_NONE;
2732         GstMCBuffer *mcbuffer = NULL;
2733
2734         mc_gst_core_t *core = (mc_gst_core_t *)data;
2735         LOGI("@%p v(%d)e(%d)bus message : %s", core, core->video, core->encoder, gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
2736
2737         switch (GST_MESSAGE_TYPE(msg)) {
2738
2739         case GST_MESSAGE_EOS:
2740                 _mc_send_eos_signal(core);
2741
2742                 mcbuffer = g_new0(GstMCBuffer, 1);
2743                 if (__mc_gst_create_eos_packet(core->output_fmt, mcbuffer) == MC_ERROR_NONE) {
2744                         __mc_push_output_to_queue(core, mcbuffer);
2745                         LOGD("send eos packet.");
2746                 } else {
2747                         LOGE("failed to create eos packet.");
2748                         g_free(mcbuffer);
2749                 }
2750
2751                 if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) {
2752                         LOGD("eos callback invoked");
2753                         ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]);
2754                 }
2755
2756                 LOGD("End of stream\n");
2757                 break;
2758
2759         case GST_MESSAGE_ERROR:
2760         {
2761                 GError *error = NULL;
2762
2763                 gst_message_parse_error(msg, &error, NULL);
2764
2765                 if (!error) {
2766                         LOGW("GST error message parsing failed");
2767                         break;
2768                 }
2769
2770                 if (error) {
2771                         if (error->domain == GST_STREAM_ERROR)
2772                                 ret = __gst_handle_stream_error(core, error, msg);
2773                         else if (error->domain == GST_RESOURCE_ERROR)
2774                                 ret = __gst_handle_resource_error(core, error->code);
2775                         else if (error->domain == GST_LIBRARY_ERROR)
2776                                 ret = __gst_handle_library_error(core, error->code);
2777                         else if (error->domain == GST_CORE_ERROR)
2778                                 ret = __gst_handle_core_error(core, error->code);
2779                         else
2780                                 LOGW("Unexpected error has occured");
2781
2782                 g_mutex_lock(&core->drain_lock);
2783
2784                 if (core->need_drain) {
2785                         LOGD("@v(%d)e(%d) input port used----- single process_input.....", core->video, core->encoder);
2786                         core->need_drain = false;
2787                         g_cond_signal(&core->buffer_cond);
2788                 }
2789
2790                 g_mutex_unlock(&core->drain_lock);
2791
2792                         if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) {
2793                                 ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR])
2794                                         (ret, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]);
2795                                         LOGW("Error : %s (ox%08x)", _mc_error_to_string(ret), ret);
2796                         }
2797                 }
2798                 g_error_free(error);
2799         }
2800                 break;
2801
2802         default:
2803                 break;
2804         }
2805
2806         return TRUE;
2807 }
2808
2809 static gboolean __mc_gst_check_useful_message(mc_gst_core_t *core, GstMessage *msg)
2810 {
2811         gboolean retval = FALSE;
2812
2813         if (!core->pipeline) {
2814                 LOGE("mediacodec pipeline handle is null");
2815                 return TRUE;
2816         }
2817
2818         switch (GST_MESSAGE_TYPE(msg)) {
2819         case GST_MESSAGE_TAG:
2820         case GST_MESSAGE_EOS:
2821         case GST_MESSAGE_ERROR:
2822         case GST_MESSAGE_WARNING:
2823                 retval = TRUE;
2824                 break;
2825         default:
2826                 retval = FALSE;
2827                 break;
2828         }
2829
2830         return retval;
2831 }
2832
2833 static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data)
2834 {
2835         mc_gst_core_t *core = (mc_gst_core_t *)data;
2836         GstBusSyncReply reply = GST_BUS_DROP;
2837
2838         LOGD("__mc_gst_bus_sync_callback is called : %s", gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
2839
2840         if (!core->pipeline) {
2841                 LOGE("mediacodec pipeline handle is null");
2842                 return GST_BUS_PASS;
2843         }
2844
2845         if (!__mc_gst_check_useful_message(core, msg)) {
2846                 gst_message_unref(msg);
2847                 return GST_BUS_DROP;
2848         }
2849
2850         switch (GST_MESSAGE_TYPE(msg)) {
2851         case GST_MESSAGE_EOS:
2852         case GST_MESSAGE_ERROR:
2853                 __mc_gst_bus_callback(NULL, msg, core);
2854                 reply = GST_BUS_DROP;
2855                 break;
2856
2857         default:
2858                 reply = GST_BUS_PASS;
2859                 break;
2860         }
2861
2862         if (reply == GST_BUS_DROP)
2863                 gst_message_unref(msg);
2864
2865         return reply;
2866 }
2867
2868 static GstMemory *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, GstMCBuffer *mcbuffer)
2869 {
2870         int ret = MEDIA_PACKET_ERROR_NONE;
2871         tbm_surface_h surface = NULL;
2872         GstMemory *mem = NULL;
2873
2874         if (!mcbuffer->packet) {
2875                 LOGE("output is null");
2876                 return NULL;
2877         }
2878
2879         if (!_mc_gst_video_info_check_and_new(core, mcbuffer)) {
2880                 LOGE("video info failed");
2881                 return NULL;
2882         }
2883
2884         ret = media_packet_get_tbm_surface(mcbuffer->packet, &surface);
2885         if (ret != MEDIA_PACKET_ERROR_NONE) {
2886                 LOGE("Failed to get tbm surface");
2887                 return NULL;
2888         }
2889
2890         mem = gst_tizen_allocator_alloc_surface(core->allocator,
2891                         core->video_info, surface, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb);
2892
2893         return mem;
2894 }
2895
2896 static void __mc_input_buffer_finalize_cb(GstMCBuffer *mcbuffer)
2897 {
2898         MEDIACODEC_FENTER();
2899
2900         if (!mcbuffer)
2901                 return;
2902
2903         LOGD("============>>>>>  _finalize_cb  : %p, %p", mcbuffer, mcbuffer->packet);
2904
2905         _mc_gst_handle_input_buffer_used(mcbuffer->core, mcbuffer->packet);
2906
2907         g_free(mcbuffer);
2908
2909         MEDIACODEC_FLEAVE();
2910 }
2911
2912 static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h packet, uint64_t size)
2913 {
2914         GstMCBuffer *mcbuffer = NULL;
2915
2916         mcbuffer = g_new0(GstMCBuffer, 1);
2917
2918         mcbuffer->buffer = gst_buffer_new();
2919         mcbuffer->buf_size = 0;
2920
2921         LOGD("creating buffer : %p, %p", mcbuffer, mcbuffer->buffer);
2922         mcbuffer->core = core;
2923         mcbuffer->packet = packet;
2924
2925         return mcbuffer;
2926 }
2927
2928 static gint __gst_handle_core_error(mc_gst_core_t *core, int code)
2929 {
2930         gint trans_err = MEDIACODEC_ERROR_NONE;
2931
2932         g_return_val_if_fail(core, MC_PARAM_ERROR);
2933
2934         switch (code) {
2935         case GST_CORE_ERROR_MISSING_PLUGIN:
2936                 return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT;
2937         case GST_CORE_ERROR_STATE_CHANGE:
2938         case GST_CORE_ERROR_SEEK:
2939         case GST_CORE_ERROR_NOT_IMPLEMENTED:
2940         case GST_CORE_ERROR_FAILED:
2941         case GST_CORE_ERROR_TOO_LAZY:
2942         case GST_CORE_ERROR_PAD:
2943         case GST_CORE_ERROR_THREAD:
2944         case GST_CORE_ERROR_NEGOTIATION:
2945         case GST_CORE_ERROR_EVENT:
2946         case GST_CORE_ERROR_CAPS:
2947         case GST_CORE_ERROR_TAG:
2948         case GST_CORE_ERROR_CLOCK:
2949         case GST_CORE_ERROR_DISABLED:
2950         default:
2951                 trans_err =  MEDIACODEC_ERROR_INVALID_STREAM;
2952                 break;
2953         }
2954
2955         return trans_err;
2956 }
2957
2958 static gint __gst_handle_library_error(mc_gst_core_t *core, int code)
2959 {
2960         gint trans_err = MEDIACODEC_ERROR_NONE;
2961
2962         g_return_val_if_fail(core, MC_PARAM_ERROR);
2963
2964         switch (code) {
2965         case GST_LIBRARY_ERROR_FAILED:
2966         case GST_LIBRARY_ERROR_TOO_LAZY:
2967         case GST_LIBRARY_ERROR_INIT:
2968         case GST_LIBRARY_ERROR_SHUTDOWN:
2969         case GST_LIBRARY_ERROR_SETTINGS:
2970         case GST_LIBRARY_ERROR_ENCODE:
2971         default:
2972                 trans_err =  MEDIACODEC_ERROR_INVALID_STREAM;
2973                 break;
2974         }
2975
2976         return trans_err;
2977 }
2978
2979
2980 static gint __gst_handle_resource_error(mc_gst_core_t *core, int code)
2981 {
2982         gint trans_err = MEDIACODEC_ERROR_NONE;
2983
2984         g_return_val_if_fail(core, MC_PARAM_ERROR);
2985
2986         switch (code) {
2987         case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
2988                 trans_err = MEDIACODEC_ERROR_NO_FREE_SPACE;
2989                 break;
2990         case GST_RESOURCE_ERROR_WRITE:
2991         case GST_RESOURCE_ERROR_FAILED:
2992         case GST_RESOURCE_ERROR_SEEK:
2993         case GST_RESOURCE_ERROR_TOO_LAZY:
2994         case GST_RESOURCE_ERROR_BUSY:
2995         case GST_RESOURCE_ERROR_OPEN_WRITE:
2996         case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
2997         case GST_RESOURCE_ERROR_CLOSE:
2998         case GST_RESOURCE_ERROR_SYNC:
2999         case GST_RESOURCE_ERROR_SETTINGS:
3000         default:
3001                 trans_err = MEDIACODEC_ERROR_INTERNAL;
3002                 break;
3003         }
3004
3005         return trans_err;
3006 }
3007
3008 static gint __gst_handle_stream_error(mc_gst_core_t *core, GError *error, GstMessage *message)
3009 {
3010         gint trans_err = MEDIACODEC_ERROR_NONE;
3011
3012         g_return_val_if_fail(core, MC_PARAM_ERROR);
3013         g_return_val_if_fail(error, MC_PARAM_ERROR);
3014         g_return_val_if_fail(message, MC_PARAM_ERROR);
3015
3016         switch (error->code) {
3017         case GST_STREAM_ERROR_FAILED:
3018         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
3019         case GST_STREAM_ERROR_DECODE:
3020         case GST_STREAM_ERROR_WRONG_TYPE:
3021         case GST_STREAM_ERROR_DECRYPT:
3022         case GST_STREAM_ERROR_DECRYPT_NOKEY:
3023         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
3024                 trans_err = __gst_transform_gsterror(core, message, error);
3025                 break;
3026
3027         case GST_STREAM_ERROR_NOT_IMPLEMENTED:
3028         case GST_STREAM_ERROR_TOO_LAZY:
3029         case GST_STREAM_ERROR_ENCODE:
3030         case GST_STREAM_ERROR_DEMUX:
3031         case GST_STREAM_ERROR_MUX:
3032         case GST_STREAM_ERROR_FORMAT:
3033         default:
3034                 trans_err = MEDIACODEC_ERROR_INVALID_STREAM;
3035                 break;
3036         }
3037
3038         return trans_err;
3039 }
3040
3041 static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage *message, GError *error)
3042 {
3043         gchar *src_element_name = NULL;
3044         GstElement *src_element = NULL;
3045         GstElementFactory *factory = NULL;
3046         const gchar *klass = NULL;
3047
3048
3049         src_element = GST_ELEMENT_CAST(message->src);
3050         if (!src_element)
3051                 goto INTERNAL_ERROR;
3052
3053         src_element_name = GST_ELEMENT_NAME(src_element);
3054         if (!src_element_name)
3055                 goto INTERNAL_ERROR;
3056
3057         factory = gst_element_get_factory(src_element);
3058         if (!factory)
3059                 goto INTERNAL_ERROR;
3060
3061         klass = gst_element_factory_get_klass(factory);
3062         if (!klass)
3063                 goto INTERNAL_ERROR;
3064
3065         LOGD("error code=%d, msg=%s, src element=%s, class=%s\n",
3066                         error->code, error->message, src_element_name, klass);
3067
3068         switch (error->code) {
3069         case GST_STREAM_ERROR_DECODE:
3070         case GST_STREAM_ERROR_FAILED:
3071                 return MEDIACODEC_ERROR_INVALID_STREAM;
3072                 break;
3073
3074         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
3075         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
3076         case GST_STREAM_ERROR_WRONG_TYPE:
3077                 return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT;
3078                 break;
3079
3080         default:
3081                 return MEDIACODEC_ERROR_INTERNAL;
3082                 break;
3083         }
3084
3085 INTERNAL_ERROR:
3086         return MEDIACODEC_ERROR_INTERNAL;
3087 }
3088
3089 static gint _mc_gst_flush_buffers(mc_gst_core_t *core)
3090 {
3091         gboolean ret = FALSE;
3092         GstEvent *event = NULL;
3093
3094         MEDIACODEC_FENTER();
3095
3096         _mc_gst_set_flush_input(core);
3097
3098         LOGW("Trying send flush_start .... ");
3099         event = gst_event_new_flush_start();
3100         ret = gst_element_send_event(core->appsrc, event);
3101         if (ret != TRUE) {
3102                 LOGE("failed to send Flush_Start event");
3103                 return MC_ERROR;
3104         }
3105
3106         LOGW("Trying send flush_stop .... ");
3107         event = gst_event_new_flush_stop(TRUE);
3108         ret = gst_element_send_event(core->appsrc, event);
3109         if (ret != TRUE) {
3110                 LOGE("failed to send Flush_Stop event");
3111                 return MC_ERROR;
3112         }
3113
3114         LOGW("Trying send seek .... ");
3115         event = gst_event_new_seek(1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
3116                         GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1);
3117
3118         ret = gst_element_send_event(core->appsrc, event);
3119         if (ret != TRUE) {
3120                 LOGE("failed to send seek event");
3121                 return MC_ERROR;
3122         }
3123
3124         _mc_gst_set_flush_output(core);
3125
3126         MEDIACODEC_FLEAVE();
3127
3128         return MC_ERROR_NONE;
3129 }
3130
3131
3132 static void _mc_gst_set_flush_input(mc_gst_core_t *core)
3133 {
3134         media_packet_h packet = NULL;
3135
3136         MEDIACODEC_FENTER();
3137         LOGI("_mc_gst_set_flush_input called : input_queue_len = %d, etb_count = %d", core->available_queue->input->length, core->etb_count);
3138
3139         while (!mc_async_queue_is_empty(core->available_queue->input)) {
3140                 packet = mc_async_queue_pop_forced(core->available_queue->input);
3141                 LOGD("%p poped(%d)", packet, core->etb_count);
3142
3143                 _mc_gst_handle_input_buffer_used(core, packet);
3144         }
3145
3146         mc_async_queue_flush(core->available_queue->input);
3147         LOGI("_mc_gst_set_flush_input ended : input_queue_len = %d, etb_count = %d", core->available_queue->input->length, core->etb_count);
3148         MEDIACODEC_FLEAVE();
3149 }
3150
3151 static void _mc_gst_set_flush_output(mc_gst_core_t *core)
3152 {
3153         media_packet_h packet = NULL;
3154
3155         MEDIACODEC_FENTER();
3156
3157         g_mutex_lock(&core->ports[1]->mutex);
3158
3159         while ((packet = g_queue_pop_head(core->ports[1]->queue))) {
3160                 LOGD("release packet[%p]", packet);
3161                 media_packet_unref(packet);
3162         }
3163
3164         g_mutex_unlock(&core->ports[1]->mutex);
3165
3166         MEDIACODEC_FLEAVE();
3167 }
3168
3169 #if TIZEN_EXYNOS_SPECIFIC
3170 /*
3171  * Get tiled address of position(x,y)
3172  *
3173  * @param x_size
3174  *   width of tiled[in]
3175  *
3176  * @param y_size
3177  *   height of tiled[in]
3178  *
3179  * @param x_pos
3180  *   x position of tield[in]
3181  *
3182  * @param src_size
3183  *   y position of tield[in]
3184  *
3185  * @return
3186  *   address of tiled data
3187  */
3188 static gint __tile_4x2_read(gint x_size, gint y_size, gint x_pos, gint y_pos)
3189 {
3190         gint pixel_x_m1, pixel_y_m1;
3191         gint roundup_x;
3192         gint linear_addr0, linear_addr1, bank_addr ;
3193         gint x_addr;
3194         gint trans_addr;
3195
3196         pixel_x_m1 = x_size - 1;
3197         pixel_y_m1 = y_size - 1;
3198
3199         roundup_x = ((pixel_x_m1 >> 7) + 1);
3200
3201         x_addr = x_pos >> 2;
3202
3203         if ((y_size <= y_pos+32) && (y_pos < y_size) &&
3204                         (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) {
3205                 linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
3206                 linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f));
3207
3208                 if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
3209                         bank_addr = ((x_addr >> 4) & 0x1);
3210                 else
3211                         bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
3212         } else {
3213                 linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
3214                 linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f));
3215
3216                 if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
3217                         bank_addr = ((x_addr >> 4) & 0x1);
3218                 else
3219                         bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
3220         }
3221
3222         linear_addr0 = linear_addr0 << 2;
3223         trans_addr = (linear_addr1 << 13) | (bank_addr << 11) | linear_addr0;
3224
3225         return trans_addr;
3226 }
3227
3228 /*
3229  * Converts tiled data to linear
3230  * Crops left, top, right, buttom
3231  * 1. Y of NV12T to Y of YUV420P
3232  * 2. Y of NV12T to Y of YUV420S
3233  * 3. UV of NV12T to UV of YUV420S
3234  *
3235  * @param yuv420_dest
3236  *   Y or UV plane address of YUV420[out]
3237  *
3238  * @param nv12t_src
3239  *   Y or UV plane address of NV12T[in]
3240  *
3241  * @param yuv420_width
3242  *   Width of YUV420[in]
3243  *
3244  * @param yuv420_height
3245  *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
3246  *
3247  * @param left
3248  *   Crop size of left
3249  *
3250  * @param top
3251  *   Crop size of top
3252  *
3253  * @param right
3254  *   Crop size of right
3255  *
3256  * @param buttom
3257  *   Crop size of buttom
3258  */
3259 static void __csc_tiled_to_linear_crop(gchar *yuv420_dest, gchar *nv12t_src,
3260                 gint yuv420_width, gint yuv420_height,
3261                 gint left, int top, gint right, gint buttom)
3262 {
3263         gint i, j;
3264         gint tiled_offset = 0, tiled_offset1 = 0;
3265         gint linear_offset = 0;
3266         gint temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0;
3267
3268         temp3 = yuv420_width-right;
3269         temp1 = temp3-left;
3270         /* real width is greater than or equal 256 */
3271         if (temp1 >= 256) {
3272                 for (i = top; i < yuv420_height-buttom; i += 1) {
3273                         j = left;
3274                         temp3 = (j>>8)<<8;
3275                         temp3 = temp3>>6;
3276                         temp4 = i>>5;
3277                         if (temp4 & 0x1) {
3278                                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
3279                                 tiled_offset = temp4-1;
3280                                 temp1 = ((yuv420_width+127)>>7)<<7;
3281                                 tiled_offset = tiled_offset*(temp1>>6);
3282                                 tiled_offset = tiled_offset+temp3;
3283                                 tiled_offset = tiled_offset+2;
3284                                 temp1 = (temp3>>2)<<2;
3285                                 tiled_offset = tiled_offset+temp1;
3286                                 tiled_offset = tiled_offset<<11;
3287                                 tiled_offset1 = tiled_offset+2048*2;
3288                                 temp4 = 8;
3289                         } else {
3290                                 temp2 = ((yuv420_height+31)>>5)<<5;
3291                                 if ((i + 32) < temp2) {
3292                                         /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
3293                                         temp1 = temp3+2;
3294                                         temp1 = (temp1>>2)<<2;
3295                                         tiled_offset = temp3+temp1;
3296                                         temp1 = ((yuv420_width+127)>>7)<<7;
3297                                         tiled_offset = tiled_offset+temp4*(temp1>>6);
3298                                         tiled_offset = tiled_offset<<11;
3299                                         tiled_offset1 = tiled_offset + 2048 * 6;
3300                                         temp4 = 8;
3301                                 } else {
3302                                         /* even2 fomula: x+x_block_num*y */
3303                                         temp1 = ((yuv420_width+127)>>7)<<7;
3304                                         tiled_offset = temp4*(temp1>>6);
3305                                         tiled_offset = tiled_offset+temp3;
3306                                         tiled_offset = tiled_offset<<11;
3307                                         tiled_offset1 = tiled_offset+2048*2;
3308                                         temp4 = 4;
3309                                 }
3310                         }
3311
3312                         temp1 = i&0x1F;
3313                         tiled_offset = tiled_offset+64*(temp1);
3314                         tiled_offset1 = tiled_offset1+64*(temp1);
3315                         temp2 = yuv420_width-left-right;
3316                         linear_offset = temp2*(i-top);
3317                         temp3 = ((j+256)>>8)<<8;
3318                         temp3 = temp3-j;
3319                         temp1 = left&0x3F;
3320
3321                         if (temp3 > 192) {
3322                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+temp1, 64-temp1);
3323                                 temp2 = ((left+63)>>6)<<6;
3324                                 temp3 = ((yuv420_width-right)>>6)<<6;
3325
3326                                 if (temp2 == temp3)
3327                                         temp2 = yuv420_width-right-(64-temp1);
3328
3329                                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset+2048, 64);
3330                                 memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1, 64);
3331                                 memcpy(yuv420_dest+linear_offset+192-temp1, nv12t_src+tiled_offset1+2048, 64);
3332                                 linear_offset = linear_offset+256-temp1;
3333                         } else if (temp3 > 128) {
3334                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+2048+temp1, 64-temp1);
3335                                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1, 64);
3336                                 memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1+2048, 64);
3337                                 linear_offset = linear_offset+192-temp1;
3338                         } else if (temp3 > 64) {
3339                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+temp1, 64-temp1);
3340                                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1+2048, 64);
3341                                 linear_offset = linear_offset+128-temp1;
3342                         } else if (temp3 > 0) {
3343                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+2048+temp1, 64-temp1);
3344                                 linear_offset = linear_offset+64-temp1;
3345                         }
3346
3347                         tiled_offset = tiled_offset+temp4*2048;
3348                         j = (left>>8)<<8;
3349                         j = j + 256;
3350                         temp2 = yuv420_width-right-256;
3351                         for (; j <= temp2; j += 256) {
3352                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3353                                 tiled_offset1 = tiled_offset1+temp4*2048;
3354                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
3355                                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
3356                                 tiled_offset = tiled_offset+temp4*2048;
3357                                 memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, 64);
3358                                 linear_offset = linear_offset+256;
3359                         }
3360
3361                         tiled_offset1 = tiled_offset1+temp4*2048;
3362                         temp2 = yuv420_width-right-j;
3363                         if (temp2 > 192) {
3364                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3365                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
3366                                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
3367                                 memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, temp2-192);
3368                         } else if (temp2 > 128) {
3369                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3370                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
3371                                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, temp2-128);
3372                         } else if (temp2 > 64) {
3373                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3374                                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, temp2-64);
3375                         } else {
3376                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
3377                         }
3378                 }
3379         } else if (temp1 >= 64) {
3380                 for (i = top; i < (yuv420_height-buttom); i += 1) {
3381                         j = left;
3382                         tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3383                         temp2 = ((j+64)>>6)<<6;
3384                         temp2 = temp2-j;
3385                         linear_offset = temp1*(i-top);
3386                         temp4 = j&0x3;
3387                         tiled_offset = tiled_offset+temp4;
3388                         memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
3389                         linear_offset = linear_offset+temp2;
3390                         j = j+temp2;
3391                         if ((j+64) <= temp3) {
3392                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3393                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3394                                 linear_offset = linear_offset+64;
3395                                 j = j+64;
3396                         }
3397                         if ((j+64) <= temp3) {
3398                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3399                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
3400                                 linear_offset = linear_offset+64;
3401                                 j = j+64;
3402                         }
3403                         if (j < temp3) {
3404                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3405                                 temp2 = temp3-j;
3406                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
3407                         }
3408                 }
3409         } else {
3410                 for (i = top; i < (yuv420_height-buttom); i += 1) {
3411                         linear_offset = temp1*(i-top);
3412                         for (j = left; j < (yuv420_width - right); j += 2) {
3413                                 tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
3414                                 temp4 = j&0x3;
3415                                 tiled_offset = tiled_offset+temp4;
3416                                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 2);
3417                                 linear_offset = linear_offset+2;
3418                         }
3419                 }
3420         }
3421 }
3422 #endif
3423
3424 void _mc_send_eos_signal(mc_gst_core_t *core)
3425 {
3426         g_mutex_lock(&core->eos_mutex);
3427         core->eos = FALSE;
3428         g_cond_broadcast(&core->eos_cond);
3429         g_mutex_unlock(&core->eos_mutex);
3430         LOGD("send EOS signal");
3431 }
3432
3433 void _mc_wait_for_eos(mc_gst_core_t *core)
3434 {
3435         g_mutex_lock(&core->eos_mutex);
3436         core->eos = TRUE;
3437         LOGD("waiting for EOS");
3438
3439         while (core->eos)
3440                 g_cond_wait(&core->eos_cond, &core->eos_mutex);
3441
3442         LOGD("received EOS");
3443         g_mutex_unlock(&core->eos_mutex);
3444 }
3445
3446 const gchar * _mc_error_to_string(mc_ret_e err)
3447 {
3448         guint err_u = (guint) err;
3449
3450         switch (err_u) {
3451         case MC_ERROR:
3452                 return "Error";
3453         case MC_PARAM_ERROR:
3454                 return "Parameter error";
3455         case MC_INVALID_ARG:
3456                 return "Invailid argument";
3457         case MC_PERMISSION_DENIED:
3458                 return "Permission denied";
3459         case MC_INVALID_STATUS:
3460                 return "Invalid status";
3461         case MC_NOT_SUPPORTED:
3462                 return "Not supported";
3463         case MC_INVALID_IN_BUF:
3464                 return "Invalid inputbuffer";
3465         case MC_INVALID_OUT_BUF:
3466                 return "Invalid outputbuffer";
3467         case MC_INTERNAL_ERROR:
3468                 return "Internal error";
3469         case MC_HW_ERROR:
3470                 return "Hardware error";
3471         case MC_NOT_INITIALIZED:
3472                 return "Not initialized";
3473         case MC_INVALID_STREAM:
3474                 return "Invalid stream";
3475         case MC_CODEC_NOT_FOUND:
3476                 return "Codec not found";
3477         case MC_ERROR_DECODE:
3478                 return "Decode error";
3479         case MC_OUTPUT_BUFFER_EMPTY:
3480                 return "Outputbuffer empty";
3481         case MC_OUTPUT_BUFFER_OVERFLOW:
3482                 return "Outputbuffer overflow";
3483         case MC_MEMORY_ALLOCED:
3484                 return "Memory allocated";
3485         case MC_COURRPTED_INI:
3486                 return "Courrpted ini";
3487         default:
3488                 return "Unknown error";
3489
3490         }
3491 }
3492
3493 const gchar * _mc_bit_to_string(int bit)
3494 {
3495         switch (bit) {
3496         case 16:
3497                 return "S16LE";
3498         case 32:
3499                 return "F32LE";
3500         default:
3501                 return "NULL";
3502
3503         }
3504 }
3505
3506 int _mc_get_mime(mc_gst_core_t *core)
3507 {
3508         media_format_mimetype_e mime = MEDIA_FORMAT_MAX;
3509
3510         switch (core->codec_id) {
3511         case MEDIACODEC_H264:
3512                 if (core->encoder)
3513                         mime = (core->is_hw) ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420;
3514                 else
3515                         mime = MEDIA_FORMAT_H264_SP;
3516                 break;
3517         case MEDIACODEC_MPEG4:
3518                 if (core->encoder)
3519                         mime = (core->is_hw) ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420;
3520                 else
3521                         mime = MEDIA_FORMAT_MPEG4_SP;
3522
3523                 break;
3524         case MEDIACODEC_H263:
3525                 if (core->encoder)
3526                         mime = (core->is_hw) ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420;
3527                 else
3528                         mime = MEDIA_FORMAT_H263P;
3529
3530                 break;
3531         case MEDIACODEC_AAC:
3532                 if (core->encoder)
3533                         mime = MEDIA_FORMAT_PCM_F32LE;  /*FIXME need to change PCM supported by chipset */
3534                 else
3535                         mime = MEDIA_FORMAT_AAC;
3536
3537                 break;
3538         case MEDIACODEC_AAC_HE:
3539                 if (core->encoder)
3540                         mime = MEDIA_FORMAT_PCM_F32LE;  /* FIXME need to change PCM supported by chipset */
3541                 else
3542                         mime = MEDIA_FORMAT_AAC_HE;
3543
3544                 break;
3545         case MEDIACODEC_AAC_HE_PS:
3546                 break;
3547         case MEDIACODEC_MP3:
3548                 mime = MEDIA_FORMAT_MP3;
3549                 break;
3550         case MEDIACODEC_VORBIS:
3551                 break;
3552         case MEDIACODEC_FLAC:
3553                 break;
3554         case MEDIACODEC_WMAV1:
3555                 break;
3556         case MEDIACODEC_WMAV2:
3557                 break;
3558         case MEDIACODEC_WMAPRO:
3559                 break;
3560         case MEDIACODEC_WMALSL:
3561                 break;
3562         case MEDIACODEC_AMR_NB:
3563                 mime = MEDIA_FORMAT_AMR_NB;
3564                 break;
3565         case MEDIACODEC_AMR_WB:
3566                 mime = MEDIA_FORMAT_AMR_WB;
3567                 break;
3568         case MEDIACODEC_OPUS:
3569                 if (core->encoder)
3570                         mime = MEDIA_FORMAT_OPUS;
3571                 else
3572                         mime = MEDIA_FORMAT_PCM_S16LE;
3573                 break;
3574         default:
3575                 LOGE("NOT SUPPORTED!!!! 0x%x ", core->codec_id);
3576                 break;
3577         }
3578         return mime;
3579 }
3580
3581 mc_ret_e mc_gst_get_packet_pool(mc_handle_t *mc_handle, media_packet_pool_h *packet_pool)
3582 {
3583         gint ret = MC_ERROR_NONE;
3584         gint curr_size;
3585         gint max_size, min_size;
3586         media_format_mimetype_e mime_format = MEDIA_FORMAT_MAX;
3587         media_format_h fmt_handle = NULL;
3588         media_packet_pool_h pool = NULL;
3589         mc_gst_core_t *core = NULL;
3590
3591         if (!mc_handle)
3592                 return MC_PARAM_ERROR;
3593
3594         core = (mc_gst_core_t *)mc_handle->core;
3595
3596         ret = media_packet_pool_create(&pool);
3597         if (ret != MEDIA_PACKET_ERROR_NONE) {
3598                 LOGE("media_packet_pool_create failed");
3599                 return MC_ERROR;
3600         }
3601
3602         if (media_format_create(&fmt_handle) != MEDIA_FORMAT_ERROR_NONE) {
3603                 LOGE("media format create failed");
3604                 media_packet_pool_destroy(pool);
3605                 return MC_ERROR;
3606         }
3607
3608         mime_format = _mc_get_mime(core);
3609
3610         if (core->video) {
3611                 media_format_set_video_mime(fmt_handle, mime_format);
3612                 media_format_set_video_width(fmt_handle, mc_handle->info.video.width);
3613                 media_format_set_video_height(fmt_handle, mc_handle->info.video.height);
3614
3615                 if (core->encoder)
3616                         media_format_set_video_avg_bps(fmt_handle, mc_handle->info.video.bitrate);
3617         } else {
3618                         media_format_set_audio_mime(fmt_handle, mime_format);
3619                         media_format_set_audio_channel(fmt_handle, mc_handle->info.audio.channel);
3620                         media_format_set_audio_samplerate(fmt_handle, mc_handle->info.audio.samplerate);
3621                         media_format_set_audio_bit(fmt_handle, mc_handle->info.audio.bit_depth);
3622                 if (core->encoder)
3623                         media_format_set_audio_avg_bps(fmt_handle, mc_handle->info.audio.bitrate);
3624         }
3625
3626         ret = media_packet_pool_set_media_format(pool, fmt_handle);
3627         if (ret != MEDIA_PACKET_ERROR_NONE) {
3628                 media_packet_pool_destroy(pool);
3629                 LOGE("media_packet_pool_set_media_format failed");
3630                 return MC_ERROR;
3631         }
3632
3633         /* will use default size temporarily */
3634         max_size = core->encoder ? DEFAULT_ENC_POOL_SIZE : DEFAULT_DEC_POOL_SIZE;
3635
3636         min_size = max_size;
3637         ret = media_packet_pool_set_size(pool, min_size, max_size);
3638         if (ret != MEDIA_PACKET_ERROR_NONE) {
3639                 media_packet_pool_destroy(pool);
3640                 LOGE("media_packet_pool_set_size failed");
3641                 return MC_ERROR;
3642         }
3643
3644         ret = media_packet_pool_allocate(pool);
3645         if (ret != MEDIA_PACKET_ERROR_NONE) {
3646                 media_packet_pool_destroy(pool);
3647                 LOGE("media_packet_pool_allocate failed");
3648                 return MC_OUT_OF_MEMORY;
3649         }
3650         media_packet_pool_get_size(pool, &min_size, &max_size, &curr_size);
3651         LOGD("curr_size is  %d min_size is %d and max_size is %d \n", curr_size, min_size, max_size);
3652
3653         *packet_pool = pool;
3654         return MC_ERROR_NONE;
3655 }