Unused nxvideo codec(artik H/W codec)
[platform/core/multimedia/libmm-transcode.git] / transcode / mm_transcode_seek.c
1 /*
2  * libmm-transcode
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 #include "mm_transcode.h"
22 #include "mm_transcode_internal.h"
23
24 static void _mm_transcode_audio_capsfilter(GstCaps *caps, handle_s *handle);
25 static void _mm_transcode_video_capsfilter(GstCaps *caps, handle_s *handle);
26 static void _mm_transcode_video_capsfilter_call(handle_s *handle);
27 static void _mm_transcode_video_capsfilter_set_parameter(GstCaps *caps, handle_s *handle);
28 static int _mm_transcode_exec(handle_s *handle, handle_param_s *param);
29 static int _mm_transcode_play(handle_s *handle);
30 static int _mm_transcode_seek(handle_s *handle);
31 static gpointer _mm_transcode_thread_repeate(gpointer data);
32
33 GstPadProbeReturn _mm_cb_audio_output_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
34 {
35         handle_s *handle = (handle_s *)user_data;
36
37         if (!handle) {
38                 LOGE("[ERROR] - handle");
39                 return GST_PAD_PROBE_REMOVE;
40         }
41
42         if (!handle->property) {
43                 LOGE("[ERROR] - handle property");
44                 return GST_PAD_PROBE_REMOVE;
45         }
46
47         gint64 start_pos_ts = handle->param->start_pos * G_GINT64_CONSTANT(1000000);
48
49         if (GST_BUFFER_PTS_IS_VALID(GST_PAD_PROBE_INFO_BUFFER(info))) {
50                 if (0 == handle->property->AUDFLAG++) {
51                         GstCaps *current_caps = gst_pad_get_current_caps(pad);
52                         /* Need to audio caps converting when amrnbenc */
53                         /* Not drop buffer with 'return FALSE' */
54                         _mm_transcode_audio_capsfilter(current_caps, handle);
55
56                         if (current_caps)
57                                 gst_caps_unref(current_caps);
58                 }
59
60                 if (handle->param->seeking) {
61                         /* Shifting the decoded out buffer time as the start time */
62                         if (GST_BUFFER_PTS(GST_PAD_PROBE_INFO_BUFFER(info)) >= start_pos_ts) {
63                                 GST_BUFFER_PTS(GST_PAD_PROBE_INFO_BUFFER(info)) -= start_pos_ts;
64                         } else {
65                                 /* If input buffer time is less than start position,
66                                  * input buffer will be dropped.
67                                  */
68                                 return GST_PAD_PROBE_DROP;
69                         }
70
71                 }
72         }
73         return GST_PAD_PROBE_OK;
74 }
75
76 GstPadProbeReturn _mm_cb_video_output_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
77 {
78         handle_s *handle = (handle_s *)user_data;
79
80         if (!handle) {
81                 LOGE("[ERROR] - handle");
82                 return GST_PAD_PROBE_REMOVE;
83         }
84
85         if (!handle->property) {
86                 LOGE("[ERROR] - handle property");
87                 return GST_PAD_PROBE_REMOVE;
88         }
89
90         gint64 start_pos_ts = handle->param->start_pos * G_GINT64_CONSTANT(1000000);
91
92         if (GST_BUFFER_PTS_IS_VALID(GST_PAD_PROBE_INFO_BUFFER(info))) {
93                 if (0 == handle->property->VIDFLAG++) {
94                         GstCaps *current_caps = gst_pad_get_current_caps(pad);
95                         /* Not drop buffer with 'return FALSE' */
96                         _mm_transcode_video_capsfilter(current_caps, handle);
97
98                         if (current_caps)
99                                 gst_caps_unref(current_caps);
100                 }
101
102                 if (handle->param->seeking) {
103                         /* Shifting the decoded out buffer time as the start time */
104                         if (GST_BUFFER_PTS(GST_PAD_PROBE_INFO_BUFFER(info)) >= start_pos_ts) {
105                                 GST_BUFFER_PTS(GST_PAD_PROBE_INFO_BUFFER(info)) -= start_pos_ts;
106                         } else {
107                                 /* If input buffer time is less than start position,
108                                  * input buffer will be dropped.
109                                  */
110                                 return GST_PAD_PROBE_DROP;
111                         }
112
113                 }
114         }
115         return GST_PAD_PROBE_OK;
116 }
117
118 GstPadProbeReturn _mm_cb_encodebin_sinkpad_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
119 {
120         handle_s *handle = (handle_s *)user_data;
121         GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info);
122
123         if (!handle) {
124                 LOGE("[ERROR] - handle");
125                 return GST_PAD_PROBE_REMOVE;
126         }
127
128         if (!handle->property) {
129                 LOGE("[ERROR] - handle property");
130                 return GST_PAD_PROBE_REMOVE;
131         }
132
133         if (!event) {
134                 LOGE("[ERROR] - event");
135                 return GST_PAD_PROBE_REMOVE;
136         }
137
138         switch (GST_EVENT_TYPE(event)) {
139         case GST_EVENT_SEGMENT:
140                 {
141                         if (!handle->param->seeking)
142                                 break;
143
144                         const GstSegment *segment = NULL;
145                         GstSegment *new_segment = NULL;
146                         gst_event_parse_segment(event, &segment);
147                         if (segment->format != GST_FORMAT_TIME)
148                                 break;
149
150                         new_segment = gst_segment_copy(segment);
151                         gst_event_unref(event);
152
153                         if (!new_segment) {
154                                 LOGE("[ERROR] segment copy error");
155                                 return GST_PAD_PROBE_REMOVE;
156                         }
157
158                         new_segment->start = 0;
159                         new_segment->stop = handle->param->duration * G_GINT64_CONSTANT(1000000);
160
161                         /* replace the new segment (change start/stop position) */
162                         GstEvent *new_event = gst_event_new_segment(new_segment);
163
164                         GST_PAD_PROBE_INFO_DATA(info) = new_event;
165                 }
166
167                 break;
168         default:
169                 break;
170         }
171
172         return GST_PAD_PROBE_OK;
173 }
174
175 GstAutoplugSelectResult _mm_cb_decode_bin_autoplug_select(GstElement *element, GstPad *pad, GstCaps *caps, GstElementFactory *factory, handle_s *handle)
176 {
177         const gchar *feature_name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
178         const gchar *caps_str = NULL;
179
180         if (!handle) {
181                 LOGE("[ERROR] - handle");
182                 return MM_ERROR_INVALID_ARGUMENT;
183         }
184
185         if (!handle->property) {
186                 LOGE("[ERROR] - handle property");
187                 return MM_ERROR_TRANSCODE_INTERNAL;
188         }
189
190         caps_str = _mm_check_media_type(caps);
191         if (g_strrstr(caps_str, "audio")) {
192                 handle->property->audiodecodename = (char *)malloc(sizeof(char) * ENC_BUFFER_SIZE);
193                 if (handle->property->audiodecodename == NULL) {
194                         LOGE("audiodecodename is NULL");
195                         return GST_AUTOPLUG_SELECT_TRY;
196                 }
197                 memset(handle->property->audiodecodename, 0, ENC_BUFFER_SIZE);
198                 g_strlcpy(handle->property->audiodecodename, feature_name, ENC_BUFFER_SIZE);
199                 LOGD("[audio decode name %s : %s]", caps_str, handle->property->audiodecodename);
200         }
201
202         if (g_strrstr(caps_str, "video")) {
203                 if (g_strrstr(feature_name, "omx") || g_strrstr(feature_name, "sprd")
204                         || g_strrstr(feature_name, "v4l2") || g_strrstr(feature_name, "nxvideo")) {
205                         /* emit autoplug-select to see what we should do with it. */
206                         LOGD("SKIP %s Codec", feature_name);
207                         return GST_AUTOPLUG_SELECT_SKIP;
208                 }
209                 handle->property->videodecodename = (char *)malloc(sizeof(char) * ENC_BUFFER_SIZE);
210                 if (handle->property->videodecodename == NULL) {
211                         LOGE("videodecodename is NULL");
212                         return GST_AUTOPLUG_SELECT_TRY;
213                 }
214                 memset(handle->property->videodecodename, 0, ENC_BUFFER_SIZE);
215                 g_strlcpy(handle->property->videodecodename, feature_name, ENC_BUFFER_SIZE);
216                 LOGD("[video decode name %s : %s]", caps_str, handle->property->videodecodename);
217         }
218
219         /* Try factory. */
220         return GST_AUTOPLUG_SELECT_TRY;
221 }
222
223 void _mm_cb_decoder_newpad_encoder(GstElement *decodebin, GstPad *pad, handle_s *handle)
224 {
225         if (!handle) {
226                 LOGE("[ERROR] - handle");
227                 return;
228         }
229
230         if (!handle->decoder_vidp) {
231                 LOGE("[ERROR] - handle decoder_vidp");
232                 return;
233         }
234
235         if (!handle->decoder_audp) {
236                 LOGE("[ERROR] - handle decoder_audp");
237                 return;
238         }
239
240         if (!handle->encodebin) {
241                 LOGE("[ERROR] - handle encodebin");
242                 return;
243         }
244
245         if (!handle->property) {
246                 LOGE("[ERROR] - handle property");
247                 return;
248         }
249
250         LOGD("[============ new-decoded-pad ============]");
251         handle->property->caps = gst_pad_query_caps(pad, NULL);
252         const gchar *mime = _mm_check_media_type(handle->property->caps);
253
254         if (!mime) {
255                 LOGE("[ERROR] - mime");
256                 return;
257         }
258
259         if (g_strrstr(mime, "video")) {
260                 handle->property->linked_vidoutbin = TRUE;
261
262                 /* link videopad */
263                 if (gst_pad_is_linked(pad)) {
264                         LOGD("pad liked");
265                 } else {
266                         if (gst_pad_link(pad, (GstPad *) handle->decoder_vidp->sinkdecvideopad) != GST_PAD_LINK_OK)
267                                 LOGE("Error [pad - sinkdecvideopad]");
268                         else
269                                 LOGD("Success [pad - sinkdecvideopad]");
270                 }
271
272         } else if (g_strrstr(mime, "audio")) {
273                 handle->property->linked_audoutbin = TRUE;
274
275                 /* link audiopad */
276                 if (gst_pad_is_linked(pad)) {
277                         LOGD("pad liked");
278                 } else {
279                         if (gst_pad_link(pad, (GstPad *) handle->decoder_audp->sinkdecaudiopad) != GST_PAD_LINK_OK)
280                                 LOGE("Error [pad - sinkdecaudiopad]");
281                         else
282                                 LOGD("Success [pad - sinkdecaudiopad]");
283                 }
284
285         } else {
286                 LOGD("gst structure error");
287         }
288 }
289
290 gboolean _mm_cb_print_position(handle_s *handle)
291 {
292         GstFormat fmt = GST_FORMAT_TIME;
293         gint64 pos;
294
295         if (!handle) {
296                 LOGE("[ERROR] - handle");
297                 return FALSE;
298         }
299
300         if (!handle->property) {
301                 LOGE("[ERROR] - handle property");
302                 return FALSE;
303         }
304
305         /* To avoid gst_element_query_position bs */
306         if (!handle->property->repeat_thread_exit) {
307                 if (gst_element_query_position(handle->pipeline, fmt, &pos)) {
308                         unsigned long current_pos = (unsigned long)(GST_TIME_AS_MSECONDS(pos));
309                         if (handle->param->seeking == FALSE) {
310                                 handle->property->current_pos = current_pos;
311                                 handle->property->real_duration = handle->property->total_length;
312                         } else if (handle->param->seeking == TRUE) {
313                                 handle->property->current_pos = current_pos - handle->param->start_pos;
314                                 if (handle->param->duration != 0) {
315                                         if (handle->param->start_pos + handle->param->duration > handle->property->total_length)
316                                                 handle->property->real_duration = handle->property->total_length - handle->param->start_pos;
317                                         else
318                                                 handle->property->real_duration = handle->param->duration;
319                                 /* seek to origin file length */
320                                 } else if (handle->param->duration == 0) {
321                                         handle->property->real_duration = handle->property->total_length - handle->param->start_pos;
322                                 }
323                         }
324
325                         if (handle->property->current_pos <= handle->property->real_duration) {
326                                 /* 2 = 1000 / 500 minimum printed cnt for last buffer */
327                                 if (handle->property->current_pos == 0 && handle->param->printed > 2)
328                                         handle->property->current_pos = handle->property->real_duration;
329
330                                 if (handle->property->progress_cb) {
331                                         /* for first buffer */
332                                         if (0 == handle->param->printed)
333                                                 handle->property->current_pos = 0;
334                                         handle->property->progress_cb(handle->property->current_pos, handle->property->real_duration, handle->property->progress_cb_param);
335                                         handle->param->printed++;
336                                 }
337                         }
338                 }
339         }
340
341         return TRUE;
342 }
343
344 gboolean _mm_cb_transcode_bus(GstBus *bus, GstMessage *message, gpointer userdata)
345 {
346         handle_s *handle = (handle_s *)userdata;
347         int ret = MM_ERROR_NONE;
348
349         if (!handle) {
350                 LOGE("[ERROR] - handle");
351                 return FALSE;
352         }
353
354         if (!handle->property) {
355                 LOGE("[ERROR] - handle property");
356                 return FALSE;
357         }
358
359         gint64 total_length;
360         GstFormat fmt = GST_FORMAT_TIME;
361         MMHandleType MMHandle = (MMHandleType)handle;
362
363         switch (GST_MESSAGE_TYPE(message)) {
364         case GST_MESSAGE_ERROR:
365                 {
366                         GError *err;
367                         gchar *debug;
368                         gst_message_parse_error(message, &err, &debug);
369
370                         if (!err) {
371                                 LOGW("Fail to parse error message");
372                                 break;
373                         }
374
375                         LOGE("[Source: %s] Error: %s", GST_OBJECT_NAME(GST_OBJECT_CAST(GST_ELEMENT(GST_MESSAGE_SRC(message)))), err->message);
376
377                         ret = mm_transcode_cancel(MMHandle);
378                         if (ret == MM_ERROR_NONE) {
379                                 LOGD("Success - Cancel Transcode");
380                         } else {
381                                 LOGE("ERROR - Cancel Transcode");
382                                 return FALSE;
383                         }
384
385                         g_error_free(err);
386                         err = NULL;
387
388                         TRANSCODE_FREE(debug);
389                         TRANSCODE_FREE(handle->param);
390                         /* g_main_loop_quit (handle->loop); */
391                         break;
392                 }
393
394         case GST_MESSAGE_STATE_CHANGED:
395                 {
396                         if (GST_ELEMENT(GST_MESSAGE_SRC(message)) != handle->pipeline)
397                                 break;
398
399                         GstState State_Old, State_New, State_Pending;
400                         gst_message_parse_state_changed(message, &State_Old, &State_New, &State_Pending);
401
402                         LOGD("[Source: %s] [State: %d -> %d]", GST_OBJECT_NAME(GST_OBJECT_CAST(GST_ELEMENT(GST_MESSAGE_SRC(message)))), State_Old, State_New);
403
404                         if (State_Old == GST_STATE_NULL && State_New == GST_STATE_READY) {
405                                 LOGD("[Set State: Pause]");
406                                 /* Pause Transcode */
407                                 ret = _mm_transcode_state_change(handle, GST_STATE_PAUSED);
408                                 if (ret == MM_ERROR_NONE) {
409                                         LOGD("Success - Pause pipeline");
410                                 } else {
411                                         LOGE("ERROR - Pause pipeline");
412                                         return FALSE;
413                                 }
414                         }
415
416                         if (State_Old == GST_STATE_READY && State_New == GST_STATE_PAUSED) {
417                                 /* Seek */
418                                 LOGD("[%s] Start New Segment pipeline", handle->param->outputfile);
419                                 ret = _mm_transcode_seek(handle);
420
421                                 if (ret == MM_ERROR_NONE) {
422                                         LOGD("Success - Set New Segment pipeline");
423                                 } else {
424                                         LOGD("[Null Trancode]");
425                                         if (_mm_transcode_state_change(handle, GST_STATE_NULL) != MM_ERROR_NONE) {
426                                                 LOGE("ERROR -Null Pipeline");
427                                                 return FALSE;
428                                         }
429                                         g_mutex_lock(handle->property->thread_mutex);
430                                         LOGD("[g_mutex_lock]");
431                                         TRANSCODE_FREE(handle->param);
432                                         LOGD("g_free(param)");
433                                         g_cond_signal(handle->property->thread_cond);
434                                         LOGD("[g_cond_signal]");
435                                         g_mutex_unlock(handle->property->thread_mutex);
436                                         LOGD("[g_mutex_unlock]");
437                                 }
438                         }
439
440                         break;
441                 }
442
443         case GST_MESSAGE_ASYNC_DONE:
444                 {
445                         if (GST_ELEMENT(GST_MESSAGE_SRC(message)) != handle->pipeline)
446                                 break;
447
448                         if (gst_element_query_duration(handle->pipeline, fmt, &total_length) && handle->property->total_length == 0) {
449                                 LOGD("[GST_MESSAGE_ASYNC_DONE] Total Duration: %" G_GUINT64_FORMAT " ", total_length);
450                                 handle->property->total_length = (unsigned long)(GST_TIME_AS_MSECONDS(total_length));
451                         }
452
453                         handle->param->async_done = TRUE;
454                         LOGD("GST_MESSAGE_ASYNC_DONE");
455
456                         /* Play Transcode */
457                         LOGD("[Play Trancode] [%lu ~ %lu]", handle->param->start_pos, handle->property->end_pos);
458
459                         if (_mm_transcode_play(handle) != MM_ERROR_NONE) {
460                                 LOGE("ERROR - Play Pipeline");
461                                 return FALSE;
462                         }
463                         break;
464                 }
465
466         case GST_MESSAGE_SEGMENT_DONE:
467                 {
468                         if (GST_ELEMENT(GST_MESSAGE_SRC(message)) != handle->pipeline)
469                                 break;
470
471                         handle->param->segment_done = TRUE;
472                         LOGD("GST_MESSAGE_SEGMENT_DONE");
473                         break;
474                 }
475
476         case GST_MESSAGE_EOS:
477                 {
478                         /* end-of-stream */
479                         LOGD("[GST_MESSAGE_EOS] end-of-stream");
480
481                         LOGD("[completed] %s (Transcode ID: %d)", handle->param->outputfile, handle->property->seek_idx++);
482                         handle->property->AUDFLAG = 0;
483                         handle->property->VIDFLAG = 0;
484
485                         /* Null Transcode *//* Need to fresh filesink's property */
486                         LOGD("[Null Trancode]");
487                         if (_mm_transcode_state_change(handle, GST_STATE_NULL) != MM_ERROR_NONE) {
488                                 LOGE("ERROR -Null Pipeline");
489                                 return FALSE;
490                         }
491                         /* checkpoint once more here (eos) and not unlink when Audio only */
492                         if ((handle->param->start_pos > handle->property->total_length && handle->property->total_length != 0) && (handle->property->videoencoder != MM_VIDEOENCODER_NO_USE)) {
493                                 unlink(handle->param->outputfile);
494                                 LOGD("[unlink] %s %lu > %lu", handle->param->outputfile, handle->param->start_pos, handle->property->total_length);
495                         }
496                         g_mutex_lock(handle->property->thread_mutex);
497                         handle->param->completed = TRUE;
498                         handle->property->is_busy = FALSE;
499                         g_cond_signal(handle->property->thread_cond);
500                         LOGD("===> send completed signal");
501                         g_mutex_unlock(handle->property->thread_mutex);
502
503                         LOGD("[MMHandle] %p [msg_cb] %p [msg_cb_param] %p", MMHandle, handle->property->completed_cb, handle->property->completed_cb_param);
504
505                         if (handle->property->progress_cb)
506                                 handle->property->progress_cb(handle->property->real_duration, handle->property->real_duration, handle->property->progress_cb_param);
507
508                         if (handle->property->completed_cb)
509                                 handle->property->completed_cb(MM_ERROR_NONE, handle->property->completed_cb_param);
510
511                         break;
512                 }
513         default:
514                 /* unhandle meage */
515                 /*LOGD("unhandle message"); */
516                 break;
517         }
518         return TRUE;
519 }
520
521 static void _mm_transcode_audio_capsfilter(GstCaps *caps, handle_s *handle)
522 {
523         gchar *str = NULL;
524
525         if (!handle) {
526                 LOGE("[ERROR] - handle");
527                 return;
528         }
529
530         if (!handle->encodebin) {
531                 LOGE("[ERROR] - handle encodebin");
532                 return;
533         }
534
535         if (!handle->property) {
536                 LOGE("[ERROR] - handle property");
537                 return;
538         }
539
540         if (!caps) {
541                 LOGE("[ERROR] - caps");
542                 return;
543         }
544
545         if (!strcmp(handle->property->aenc, AMRENC))
546                 caps = gst_caps_new_simple("audio/x-raw", "rate", G_TYPE_INT, 8000, "channels", G_TYPE_INT, 1, NULL);
547         else if (!strcmp(handle->property->aenc, AACENC))
548                 caps = gst_caps_new_simple("audio/x-raw", "rate", G_TYPE_INT, 44100, "channels", G_TYPE_INT, 1, NULL);
549
550         TRANSCODE_FREE(handle->property->audiodecodename);
551         g_object_set(G_OBJECT(handle->decoder_audp->audflt), "caps", caps, NULL);
552
553         str = gst_caps_to_string(caps);
554
555         if (str) {
556                 LOGD("audio decoder capsfilter audiocaps: %s", str);
557                 g_free(str);
558         }
559
560         return;
561
562 }
563
564 int _mm_transcode_create(handle_s *handle)
565 {
566         int ret = MM_ERROR_NONE;
567
568         if (!handle) {
569                 LOGE("[ERROR] - handle");
570                 return MM_ERROR_INVALID_ARGUMENT;
571         }
572
573         ret = _mm_decodesrcbin_create(handle);
574         if (ret == MM_ERROR_NONE) {
575                 LOGD("Success - Create decodesrcbin");
576         } else {
577                 LOGE("ERROR - Create decodesrcbin");
578                 return ret;
579         }
580
581         ret = _mm_encodebin_set_venc_aenc(handle);
582         if (ret == MM_ERROR_NONE) {
583                 LOGD("Success - Setup video and audio encoder of encodebin");
584         } else {
585                 LOGE("ERROR -Setup video and audio encoder of encodebin ");
586                 return ret;
587         }
588
589         ret = _mm_encodebin_create(handle);
590         if (ret == MM_ERROR_NONE) {
591                 LOGD("Success - Create encodebin");
592         } else {
593                 LOGE("ERROR - Create encodebin");
594                 return ret;
595         }
596
597         /*create filesink */
598         ret = _mm_filesink_create(handle);
599         if (ret == MM_ERROR_NONE) {
600                 LOGD("Success - Create Filesink");
601         } else {
602                 LOGE("ERROR - Create Filesink");
603                 return ret;
604         }
605
606         return ret;
607 }
608
609 static int _mm_transcode_exec(handle_s *handle, handle_param_s *param)
610 {
611         int ret = MM_ERROR_NONE;
612
613         if (!handle) {
614                 LOGE("[ERROR] - handle");
615                 return MM_ERROR_INVALID_ARGUMENT;
616         }
617
618         if (!handle->property) {
619                 LOGE("[ERROR] - handle property");
620                 return MM_ERROR_TRANSCODE_INTERNAL;
621         }
622
623         if (!param || !param->outputfile) {
624                 LOGE("[ERROR] - param");
625                 return MM_ERROR_TRANSCODE_INVALID_VALUE;
626         }
627
628         g_mutex_lock(handle->property->thread_mutex);
629
630         if (handle->property->repeat_thread_exit) {
631                 g_mutex_unlock(handle->property->thread_mutex);
632                 LOGD("unlock destory");
633         } else {
634                 LOGD("start_pos: %lu, duration: %lu, seek_mode: %d output file name: %s\n", param->start_pos, param->duration, param->seek_mode, param->outputfile);
635                 handle->param = g_new0(handle_param_s, 1);
636                 /*g_value_init (handle->param, G_TYPE_INT); */
637
638                 if (!handle->param) {
639                         LOGE("[ERROR] - handle param");
640                         return MM_ERROR_TRANSCODE_INTERNAL;
641                 }
642
643                 handle->param->resolution_width = param->resolution_width;
644                 handle->param->resolution_height = param->resolution_height;
645                 handle->param->fps_value = param->fps_value;
646                 handle->param->start_pos = param->start_pos;
647                 handle->param->duration = param->duration;
648                 handle->param->seek_mode = param->seek_mode;
649                 handle->param->outputfile = malloc(sizeof(gchar) * BUFFER_SIZE);
650                 if (!handle->param->outputfile) {
651                         TRANSCODE_FREE(handle->param);
652                         return MM_ERROR_TRANSCODE_NO_FREE_SPACE;
653                 }
654
655                 memset(handle->param->outputfile, 0, BUFFER_SIZE);
656                 g_strlcpy(handle->param->outputfile, param->outputfile, BUFFER_SIZE);
657
658                 handle->param->seeking = param->seeking;
659                 handle->param->async_done = FALSE;
660                 handle->param->segment_done = FALSE;
661                 handle->param->completed = FALSE;
662                 handle->param->printed = 0;
663                 LOGD("[SEEK: %d] width: %d height: %d fps_value: %d start_pos: %lu duration: %lu seek_mode: %d outputfile: %s",
664                         handle->param->seeking, handle->param->resolution_width, handle->param->resolution_height,
665                         handle->param->fps_value, handle->param->start_pos, handle->param->duration,
666                         handle->param->seek_mode, handle->param->outputfile);
667
668                 if (handle->property->total_length != 0 && handle->param->start_pos > handle->property->total_length) {
669                         LOGD("[SKIP] [%s] because out of duration [%lu < %lu ~ %lu] ", handle->param->outputfile, handle->property->total_length, handle->param->start_pos, handle->param->duration);
670                         g_mutex_unlock(handle->property->thread_mutex);
671                         LOGD("[thread_mutex unlock]");
672                 } else {
673                         g_object_set(G_OBJECT(handle->filesink), "location", handle->param->outputfile, NULL);
674                         LOGD("[%s] set filesink location", handle->param->outputfile);
675
676                         /* Ready Transcode */
677                         if (strlen(handle->param->outputfile) != 0) {
678                                 LOGD("[Set State: Ready]");
679                                 ret = _mm_transcode_state_change(handle, GST_STATE_READY);
680                                 if (ret == MM_ERROR_NONE) {
681                                         LOGD("Success - Ready pipeline");
682                                 } else {
683                                         LOGE("ERROR - Reay pipeline");
684                                         g_mutex_unlock(handle->property->thread_mutex);
685                                         return ret;
686                                 }
687                         }
688
689                         if (0 == handle->property->seek_idx) {
690                                 LOGD("Link Filesink");
691                                 /* link filesink */
692                                 ret = _mm_filesink_link(handle);
693                                 if (ret == MM_ERROR_NONE) {
694                                         LOGD("Success - Link Filesink");
695                                 } else {
696                                         LOGE("ERROR - Link Filesink");
697                                         g_mutex_unlock(handle->property->thread_mutex);
698                                         return ret;
699                                 }
700                         }
701
702                         g_cond_wait(handle->property->thread_cond, handle->property->thread_mutex);
703                         LOGD("<=== get completed signal");
704                         g_mutex_unlock(handle->property->thread_mutex);
705                 }
706         }
707
708         return ret;
709 }
710
711 int _mm_transcode_get_stream_info(handle_s *handle)
712 {
713         int ret = MM_ERROR_NONE;
714
715         if (!handle) {
716                 LOGE("[ERROR] - handle");
717                 return MM_ERROR_INVALID_ARGUMENT;
718         }
719
720         if (!handle->property) {
721                 LOGE("[ERROR] - handle property");
722                 return MM_ERROR_TRANSCODE_INTERNAL;
723         }
724
725         if (strlen(handle->property->sourcefile) == 0) {
726                 LOGE("Invalid arguments [sourcefile size 0]\n");
727                 return MM_ERROR_INVALID_ARGUMENT;
728         }
729
730         int audio_track_num = 0;
731         int video_track_num = 0;
732
733         ret = mm_file_get_stream_info(handle->property->sourcefile, &audio_track_num, &video_track_num);
734         if (ret == MM_ERROR_NONE) {
735                 LOGD("Success - mm_file_get_stream_info");
736         } else {
737                 LOGE("ERROR - mm_file_get_stream_info");
738                 return MM_ERROR_TRANSCODE_INTERNAL;
739         }
740
741         if (audio_track_num)
742                 handle->property->has_audio_stream = TRUE;
743         else
744                 handle->property->has_audio_stream = FALSE;
745
746         LOGD("has_audio_stream: %d", handle->property->has_audio_stream);
747
748         if (video_track_num)
749                 handle->property->has_video_stream = TRUE;
750         else
751                 handle->property->has_video_stream = FALSE;
752
753         LOGD("has_video_stream: %d", handle->property->has_video_stream);
754
755         if ((handle->property->videoencoder != MM_VIDEOENCODER_NO_USE && !handle->property->has_video_stream) || (handle->property->audioencoder != MM_AUDIOENCODER_NO_USE && !handle->property->has_audio_stream)) {
756                 LOGE("No video || audio stream");
757                 return MM_ERROR_INVALID_ARGUMENT;
758         }
759
760         return ret;
761 }
762
763 int _mm_transcode_link(handle_s *handle)
764 {
765         int ret = MM_ERROR_NONE;
766
767         if (!handle) {
768                 LOGE("[ERROR] - handle");
769                 return MM_ERROR_INVALID_ARGUMENT;
770         }
771
772         ret = _mm_decodesrcbin_link(handle);
773         if (ret == MM_ERROR_NONE) {
774                 LOGD("Success - decodesrcbin link");
775         } else {
776                 LOGE("ERROR - decodesrcbin link");
777                 return ret;
778         }
779
780         ret = _mm_encodebin_link(handle);
781         if (ret == MM_ERROR_NONE) {
782                 LOGD("Success - encodebin link");
783         } else {
784                 LOGE("ERROR - encodebin link");
785                 return ret;
786         }
787
788         return ret;
789 }
790
791 static void _mm_transcode_video_capsfilter(GstCaps *caps, handle_s *handle)
792 {
793         if (!handle) {
794                 LOGE("[ERROR] - handle");
795                 return;
796         }
797
798         if (!handle->property) {
799                 LOGE("[ERROR] - handle property");
800                 return;
801         }
802
803         if (!caps) {
804                 LOGE("[ERROR] - caps");
805                 TRANSCODE_FREE(handle->property->videodecodename);
806                 return;
807         }
808
809         LOGD("[First Video Buffer] Set CapsFilter Parameter");
810         _mm_transcode_video_capsfilter_set_parameter(caps, handle);
811
812         /* Not support enlarge video resolution */
813         LOGD("Execute Resize");
814 #if 0
815         /* Not irrelevant to the ratio */
816         handle->param->resolution_height = handle->param->resolution_width * handle->in_height / handle->in_width;
817 #endif
818
819         LOGD("[Resize] resolution_width: %d, resolution_height: %d", handle->param->resolution_width, handle->param->resolution_height);
820         if (0 == handle->param->resolution_width || 0 == handle->param->resolution_height) {
821                 LOGD("[Origin Resolution] Two resolutoin value = 0");
822                 handle->param->resolution_width = handle->property->in_width;
823                 handle->param->resolution_height = handle->property->in_height;
824         }
825
826         if (handle->param->resolution_width < VIDEO_RESOLUTION_WIDTH_SQCIF || handle->param->resolution_height < VIDEO_RESOLUTION_HEIGHT_SQCIF) {
827                 LOGD("The Minimun resolution is SQCIF");
828                 handle->param->resolution_width = VIDEO_RESOLUTION_WIDTH_SQCIF;
829                 handle->param->resolution_height = VIDEO_RESOLUTION_HEIGHT_SQCIF;
830         }
831
832         if (handle->property->in_width < handle->param->resolution_width || handle->property->in_height < handle->param->resolution_height) {
833                 LOGD("[Origin Resolution] resolutoin value > origin resolution");
834                 handle->param->resolution_width = handle->property->in_width;
835                 handle->param->resolution_height = handle->property->in_height;
836         }
837
838         LOGD("[Call CapsFilter] resolution_width: %d, resolution_height: %d", handle->param->resolution_width, handle->param->resolution_height);
839         _mm_transcode_video_capsfilter_call(handle);
840         TRANSCODE_FREE(handle->property->videodecodename);
841 }
842
843 static void _mm_transcode_video_capsfilter_call(handle_s *handle)
844 {
845         if (!handle) {
846                 LOGE("[ERROR] - handle");
847                 return;
848         }
849
850         if (!handle->decoder_vidp) {
851                 LOGE("[ERROR] - handle decoder video process bin");
852                 return;
853         }
854
855         if (!handle->property) {
856                 LOGE("[ERROR] - handle property");
857                 return;
858         }
859
860         /* Configure videoscale to use 4-tap scaling for higher quality */
861         LOGD("Input Width: [%d] Input Hieght: [%d] Output Width: [%d], Output Height: [%d]", handle->property->in_width, handle->property->in_height, handle->param->resolution_width, handle->param->resolution_height);
862
863         g_object_set(G_OBJECT(handle->decoder_vidp->vidflt), "caps", gst_caps_new_simple(handle->property->mime, "format", G_TYPE_STRING, handle->property->format, "width", G_TYPE_INT, handle->param->resolution_width, "height", G_TYPE_INT, handle->param->resolution_height, "framerate", GST_TYPE_FRACTION, handle->property->fps_n, handle->property->fps_d, "pixel-aspect-ratio", GST_TYPE_FRACTION, handle->property->aspect_x, handle->property->aspect_y, NULL), NULL);
864 }
865
866 static void _mm_transcode_video_capsfilter_set_parameter(GstCaps *caps, handle_s *handle)
867 {
868         const GValue *par, *fps;
869
870         if (!handle) {
871                 LOGE("[ERROR] - handle");
872                 return;
873         }
874
875         if (!handle->property) {
876                 LOGE("[ERROR] - handle property");
877                 return;
878         }
879
880         if (!caps) {
881                 LOGE("[ERROR] - caps");
882                 return;
883         }
884
885         GstStructure *_str = gst_caps_get_structure(caps, 0);
886         handle->property->mime = _mm_check_media_type(caps);
887         LOGD("mime: %s", handle->property->mime);
888
889         const gchar *format = gst_structure_get_string(_str, "format");
890         g_strlcpy(handle->property->format, format, sizeof(handle->property->format));
891
892         switch (gst_video_format_from_string(handle->property->format)) {
893         case GST_VIDEO_FORMAT_I420:
894         case GST_VIDEO_FORMAT_RGB:
895         case GST_VIDEO_FORMAT_NV12:
896                 LOGD("format: %s", handle->property->format);
897                 break;
898
899         case GST_VIDEO_FORMAT_UNKNOWN:
900                 if (strcmp(handle->property->format, "SN12") == 0 || strcmp(handle->property->format, "ST12") == 0)
901                         LOGD("format: %s", handle->property->format);
902
903                 break;
904
905         default:
906                 break;
907         }
908
909         if (!gst_structure_get_int(_str, "width", &handle->property->in_width) || !gst_structure_get_int(_str, "height", &handle->property->in_height))
910                 LOGE("error gst_structure_get_int [width] [height]");
911         else
912                 LOGD("Origin File's Width: [%u] Origin File's Hieght: [%u]", handle->property->in_width, handle->property->in_height);
913
914         fps = gst_structure_get_value(_str, "framerate");
915
916         if (fps) {
917                 handle->property->fps_n = gst_value_get_fraction_numerator(fps);
918                 handle->property->fps_d = gst_value_get_fraction_denominator(fps);
919                 LOGD("[Origin framerate] gst_value_get_fraction_numerator: %d, gst_value_get_fraction_denominator: %d", handle->property->fps_n, handle->property->fps_d);
920         }
921
922         if (handle->param->fps_value >= 5 && handle->param->fps_value <= 30 && handle->param->fps_value <= handle->property->fps_n) {
923                 handle->property->fps_n = (gint) handle->param->fps_value;
924                 handle->property->fps_d = 1;
925         }
926         LOGD("[framerate] gst_value_get_fraction_numerator: %d, gst_value_get_fraction_denominator: %d", handle->property->fps_n, handle->property->fps_d);
927
928         par = gst_structure_get_value(_str, "pixel-aspect-ratio");
929         if (par) {
930                 handle->property->aspect_x = gst_value_get_fraction_numerator(par);
931                 handle->property->aspect_y = gst_value_get_fraction_denominator(par);
932         } else {
933                 handle->property->aspect_x = handle->property->aspect_y = 1;
934         }
935         LOGD("[pixel-aspect-ratio] gst_value_get_fraction_numerator: %d, gst_value_get_fraction_denominator: %d", handle->property->aspect_x, handle->property->aspect_y);
936
937 }
938
939 int _mm_transcode_set_handle_element(handle_s *handle, const char *in_Filename, mm_containerformat_e containerformat, mm_videoencoder_e videoencoder, mm_audioencoder_e audioencoder)
940 {
941         int ret = MM_ERROR_NONE;
942
943         if (!handle) {
944                 LOGE("[ERROR] - handle");
945                 return MM_ERROR_INVALID_ARGUMENT;
946         }
947
948         if (!handle->property) {
949                 LOGE("[ERROR] - handle property");
950                 return MM_ERROR_TRANSCODE_INTERNAL;
951         }
952
953         if (in_Filename == NULL) {
954                 LOGE("Invalid arguments [filename null]\n");
955                 return MM_ERROR_INVALID_ARGUMENT;
956         }
957
958         if (strlen(in_Filename) == 0 || strlen(in_Filename) > BUFFER_SIZE) {
959                 LOGE("Invalid arguments [filename size: %d]\n", strlen(in_Filename));
960                 return MM_ERROR_INVALID_ARGUMENT;
961         }
962
963         handle->property->sourcefile = malloc(sizeof(char) * BUFFER_SIZE);
964         if (handle->property->sourcefile) {
965                 memset(handle->property->sourcefile, 0, BUFFER_SIZE);
966                 g_strlcpy(handle->property->sourcefile, in_Filename, BUFFER_SIZE);
967                 LOGD("%s", handle->property->sourcefile);
968         } else {
969                 LOGE("[ERROR] malloc fail of sourcefile");
970                 return MM_ERROR_TRANSCODE_INTERNAL;
971         }
972
973         handle->property->containerformat = containerformat;
974         handle->property->videoencoder = videoencoder;
975         handle->property->audioencoder = audioencoder;
976
977         LOGD("container format: %d videoencoder:%d, audioencoder: %d", handle->property->containerformat, handle->property->videoencoder, handle->property->audioencoder);
978
979         return ret;
980 }
981
982 int _mm_transcode_set_handle_parameter(handle_param_s *param, unsigned int resolution_width, unsigned int resolution_height, unsigned int fps_value, unsigned long start_pos, unsigned long duration, mm_seek_mode_e seek_mode, const char *out_Filename)
983 {
984         int ret = MM_ERROR_NONE;
985
986         if (!param) {
987                 LOGE("param error");
988                 return MM_ERROR_TRANSCODE_INTERNAL;
989         }
990
991         param->resolution_width = resolution_width;
992         param->resolution_height = resolution_height;
993         param->fps_value = fps_value;
994
995         param->start_pos = start_pos;
996         param->duration = duration;
997         param->seek_mode = seek_mode;
998         LOGD("resolution_width: %d, resolution_height: %d, fps_value: %d, start_pos: %lu, duration: %lu, seek_mode: %d \n",
999                 param->resolution_width, param->resolution_height, fps_value, param->start_pos, param->duration, param->seek_mode);
1000
1001         if (start_pos == 0 && duration == 0)
1002                 param->seeking = FALSE;
1003         else
1004                 param->seeking = TRUE;
1005
1006         if (out_Filename) {
1007                 param->outputfile = malloc(sizeof(gchar) * BUFFER_SIZE);
1008                 if (!param->outputfile) {
1009                         LOGE("[ERROR] outputfile");
1010                         return MM_ERROR_TRANSCODE_NO_FREE_SPACE;
1011                 }
1012                 memset(param->outputfile, 0, BUFFER_SIZE);
1013                 g_strlcpy(param->outputfile, out_Filename, BUFFER_SIZE);
1014                 LOGD("%s(%d)", param->outputfile, strlen(out_Filename));
1015         } else {
1016                 LOGE("out_Filename error");
1017                 return MM_ERROR_INVALID_ARGUMENT;
1018         }
1019
1020         return ret;
1021 }
1022
1023 int _mm_transcode_state_change(handle_s *handle, GstState gst_state)
1024 {
1025         int ret = MM_ERROR_NONE;
1026         GstStateChangeReturn ret_state;
1027
1028         if (gst_state == GST_STATE_NULL)
1029                 LOGD("Before - GST_STATE_NULL");
1030         else if (gst_state == GST_STATE_READY)
1031                 LOGD("Before - GST_STATE_READY");
1032         else if (gst_state == GST_STATE_PAUSED)
1033                 LOGD("Before - GST_STATE_PAUSED");
1034         else if (gst_state == GST_STATE_PLAYING)
1035                 LOGD("Before - GST_STATE_PLAYING");
1036
1037         ret_state = gst_element_set_state(handle->pipeline, gst_state);
1038         if (ret_state == GST_STATE_CHANGE_FAILURE) {
1039                 if (gst_state == GST_STATE_NULL)
1040                         LOGE("ERROR - SET GST_STATE_NULL");
1041                 else if (gst_state == GST_STATE_READY)
1042                         LOGE("ERROR - SET GST_STATE_READY");
1043                 else if (gst_state == GST_STATE_PAUSED)
1044                         LOGE("ERROR - SET GST_STATE_PAUSED");
1045                 else if (gst_state == GST_STATE_PLAYING)
1046                         LOGE("ERROR - SET GST_STATE_PLAYING");
1047
1048                 return MM_ERROR_TRANSCODE_INTERNAL;
1049         } else {
1050                 if (gst_state == GST_STATE_NULL)
1051                         LOGD("Success - SET GST_STATE_NULL");
1052                 else if (gst_state == GST_STATE_READY)
1053                         LOGD("Success - SET GST_STATE_READY");
1054                 else if (gst_state == GST_STATE_PAUSED)
1055                         LOGD("Success - SET GST_STATE_PAUSED");
1056                 else if (gst_state == GST_STATE_PLAYING)
1057                         LOGD("Success - SET GST_STATE_PLAYING");
1058         }
1059
1060         ret_state = gst_element_get_state(handle->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
1061         if (ret_state == GST_STATE_CHANGE_FAILURE) {
1062                 if (gst_state == GST_STATE_NULL)
1063                         LOGE("ERROR - GET GST_STATE_NULL");
1064                 else if (gst_state == GST_STATE_READY)
1065                         LOGE("ERROR - GET GST_STATE_READY");
1066                 else if (gst_state == GST_STATE_PAUSED)
1067                         LOGE("ERROR - GET GST_STATE_PAUSED");
1068                 else if (gst_state == GST_STATE_PLAYING)
1069                         LOGE("ERROR - GET GST_STATE_PLAYING");
1070
1071                 return MM_ERROR_TRANSCODE_INTERNAL;
1072         } else {
1073                 if (gst_state == GST_STATE_NULL)
1074                         LOGD("Success - GET GST_STATE_NULL");
1075                 else if (gst_state == GST_STATE_READY)
1076                         LOGD("Success - GET GST_STATE_READY");
1077                 else if (gst_state == GST_STATE_PAUSED)
1078                         LOGD("Success - GET GST_STATE_PAUSED");
1079                 else if (gst_state == GST_STATE_PLAYING)
1080                         LOGD("Success - GET GST_STATE_PLAYING");
1081         }
1082
1083         return ret;
1084 }
1085
1086 int _mm_transcode_param_flush(handle_s *handle)
1087 {
1088         int ret = MM_ERROR_NONE;
1089
1090         if (!handle) {
1091                 LOGE("[ERROR] - handle");
1092                 return MM_ERROR_INVALID_ARGUMENT;
1093         }
1094
1095         if (!handle->encodebin) {
1096                 LOGE("[ERROR] - handle encodebin");
1097                 return MM_ERROR_TRANSCODE_INTERNAL;
1098         }
1099
1100         if (!handle->property) {
1101                 LOGE("[ERROR] - handle property");
1102                 return MM_ERROR_TRANSCODE_INTERNAL;
1103         }
1104
1105         handle->property->linked_vidoutbin = FALSE;
1106         handle->property->linked_audoutbin = FALSE;
1107         handle->encodebin->encodebin_profile = 0;
1108         handle->property->AUDFLAG = 0;
1109         handle->property->VIDFLAG = 0;
1110         handle->encodebin->audio_event_probe_id = 0;
1111         handle->encodebin->video_event_probe_id = 0;
1112
1113         handle->property->total_length = 0;
1114         handle->property->repeat_thread_exit = FALSE;
1115         handle->property->is_busy = FALSE;
1116         handle->property->audio_cb_probe_id = 0;
1117         handle->property->video_cb_probe_id = 0;
1118         handle->property->progress_event_id = 0;
1119         handle->property->seek_idx = 0;
1120
1121         return ret;
1122 }
1123
1124 static int _mm_transcode_play(handle_s *handle)
1125 {
1126         int ret = MM_ERROR_NONE;
1127
1128         if (!handle) {
1129                 LOGE("[ERROR] - handle");
1130                 return MM_ERROR_INVALID_ARGUMENT;
1131         }
1132
1133         if (!handle->property) {
1134                 LOGE("[ERROR] - handle property");
1135                 return MM_ERROR_TRANSCODE_INTERNAL;
1136         }
1137
1138         ret = _mm_transcode_state_change(handle, GST_STATE_PLAYING);
1139         if (ret != MM_ERROR_NONE) {
1140                 LOGE("ERROR -Playing Pipeline");
1141                 return ret;
1142         }
1143
1144         LOGD("[SEEK: %d] width: %d height: %d start_pos: %lu duration: %lu (%lu) seek_mode: %d outputfile: %s",
1145                 handle->param->seeking, handle->param->resolution_width, handle->param->resolution_height,
1146                 handle->param->start_pos, handle->param->duration, handle->property->end_pos,
1147                 handle->param->seek_mode, handle->param->outputfile);
1148
1149         if (!handle->property->progress_event_id) {
1150                 handle->property->progress_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc) _mm_cb_print_position, handle);
1151                 LOGD("Timer (id=[%d], timeout=[%d ms])\n", handle->property->progress_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
1152         }
1153
1154         return ret;
1155 }
1156
1157 static int _mm_transcode_seek(handle_s *handle)
1158 {
1159         int ret = MM_ERROR_NONE;
1160
1161         if (!handle) {
1162                 LOGE("[ERROR] - handle");
1163                 return MM_ERROR_INVALID_ARGUMENT;
1164         }
1165
1166         if (!handle->property) {
1167                 LOGE("[ERROR] - handle property");
1168                 return MM_ERROR_TRANSCODE_INTERNAL;
1169         }
1170
1171         GList *walk_element = handle->property->sink_elements;
1172         gint64 start_pos, end_pos;
1173         gdouble rate = 1.0;
1174         GstSeekFlags _Flags = GST_SEEK_FLAG_NONE;
1175
1176         start_pos = handle->param->start_pos * G_GINT64_CONSTANT(1000000);
1177         handle->property->end_pos = handle->param->start_pos + handle->param->duration;
1178
1179         if (handle->param->start_pos > handle->property->total_length && handle->property->seek_idx) {
1180                 LOGE("[%lu ~ %lu] out of %lu",
1181                         handle->param->start_pos, handle->property->end_pos, handle->property->total_length);
1182                 return MM_ERROR_TRANSCODE_SEEK_FAILED;
1183         } else {
1184                 if (handle->param->duration != 0) {
1185                         end_pos = start_pos + handle->param->duration * G_GINT64_CONSTANT(1000000);
1186                 } else if (handle->param->duration == 0) {
1187                         /* seek to origin file length */
1188                         end_pos = handle->property->total_length * G_GINT64_CONSTANT(1000000);
1189                 }
1190
1191                 LOGD("seek time : [ (%lu msec) : (%lu msec) ]\n",
1192                         handle->param->start_pos, handle->property->end_pos);
1193
1194                 while (walk_element) {
1195                         GstElement *seekable_element = GST_ELEMENT(walk_element->data);
1196
1197                         if (!seekable_element) {
1198                                 LOGE("ERROR - seekable");
1199                                 return MM_ERROR_TRANSCODE_INTERNAL;
1200                         }
1201
1202                         if (handle->param->seek_mode == MM_SEEK_ACCURATE)
1203                                 _Flags = GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH;
1204                         else if (handle->param->seek_mode == MM_SEEK_INACCURATE)
1205                                 _Flags = GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH;
1206
1207                         if (!gst_element_seek(seekable_element, rate, GST_FORMAT_TIME, _Flags, GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_SET, end_pos)) {
1208                                 LOGE("ERROR - gst_element_seek (on) event : %s", GST_OBJECT_NAME(GST_OBJECT_CAST(seekable_element)));
1209                                 return MM_ERROR_TRANSCODE_SEEK_FAILED;
1210                         }
1211
1212                         if (walk_element)
1213                                 walk_element = g_list_next(walk_element);
1214                 }
1215         }
1216
1217         return ret;
1218 }
1219
1220 int _mm_transcode_thread(handle_s *handle)
1221 {
1222         int ret = MM_ERROR_NONE;
1223
1224         if (!handle) {
1225                 LOGE("[ERROR] - handle");
1226                 return MM_ERROR_INVALID_ARGUMENT;
1227         }
1228
1229         if (!handle->property) {
1230                 LOGE("[ERROR] - handle property");
1231                 return MM_ERROR_TRANSCODE_INTERNAL;
1232         }
1233
1234         if (!handle->property->thread_mutex) {
1235                 handle->property->thread_mutex = g_new(GMutex, 1);
1236                 g_mutex_init(handle->property->thread_mutex);
1237                 LOGD("create thread_mutex: %p", handle->property->thread_mutex);
1238         } else {
1239                 LOGE("ERROR - thread_mutex is already created");
1240         }
1241
1242         if (!handle->property->thread_exit_mutex) {
1243                 handle->property->thread_exit_mutex = g_new(GMutex, 1);
1244                 g_mutex_init(handle->property->thread_exit_mutex);
1245                 LOGD("create exit mutex: %p", handle->property->thread_exit_mutex);
1246         } else {
1247                 LOGE("ERROR - thread_exit_mutex is already created");
1248         }
1249
1250         /* These are a communicator for thread */
1251         if (!handle->property->queue) {
1252                 handle->property->queue = g_async_queue_new();
1253                 LOGD("create async queue: %p", handle->property->queue);
1254         } else {
1255                 LOGE("ERROR - async queue is already created");
1256         }
1257
1258         if (!handle->property->thread_cond) {
1259                 handle->property->thread_cond = g_new(GCond, 1);
1260                 g_cond_init(handle->property->thread_cond);
1261                 LOGD("create thread cond: %p", handle->property->thread_cond);
1262         } else {
1263                 LOGE("thread cond is already created");
1264         }
1265
1266         /* create threads */
1267         LOGD("create thread");
1268         handle->property->thread = g_thread_new(NULL, (GThreadFunc)_mm_transcode_thread_repeate, (gpointer)handle);
1269         if (!handle->property->thread) {
1270                 LOGE("ERROR - create thread");
1271                 return MM_ERROR_TRANSCODE_INTERNAL;
1272         } else {
1273                 LOGD("create thread: %p", handle->property->thread);
1274         }
1275
1276         return ret;
1277 }
1278
1279 static gpointer _mm_transcode_thread_repeate(gpointer data)
1280 {
1281         handle_s *handle = (handle_s *) data;
1282         int ret = MM_ERROR_NONE;
1283
1284         if (!handle) {
1285                 LOGE("[ERROR] - handle");
1286                 return NULL;
1287         }
1288
1289         if (!handle->property) {
1290                 LOGE("[ERROR] - handle property");
1291                 return NULL;
1292         }
1293
1294         /* thread while */
1295         while (1) {
1296                 int length = g_async_queue_length(handle->property->queue);
1297                 if (length) {
1298                         LOGD("[QUEUE #] %d", length);
1299                         handle->property->is_busy = TRUE;
1300                 }
1301
1302                 handle_param_s *pop_data = (handle_param_s *) g_async_queue_pop(handle->property->queue);
1303
1304                 if (handle->property->repeat_thread_exit || !handle->property->is_busy) {
1305                         LOGD("[Receive Last Queue]");
1306                         LOGD("[Destroy]");
1307                         break;
1308                 } else {
1309                         LOGD("[pop queue] resolution_width: %d, resolution_height: %d, start_pos: %lu, duration: %lu, seek_mode: %d outputfile: %s\n",
1310                                 pop_data->resolution_width, pop_data->resolution_height, pop_data->start_pos,
1311                                 pop_data->duration, pop_data->seek_mode, pop_data->outputfile);
1312
1313                         /* Need to block */
1314                         ret = _mm_transcode_exec(handle, pop_data);
1315                         if (ret == MM_ERROR_NONE) {
1316                                 LOGD("Success - transcode_exec");
1317                         } else {
1318                                 LOGD("Destroy - transcode_exec");
1319                                 LOGD("<=== get exit (%d) signal", handle->property->repeat_thread_exit);
1320                                 break;
1321                         }
1322                 }
1323         }
1324         LOGD("exit thread");
1325         return NULL;
1326 }