Remove libmm-log build dependency
[platform/core/multimedia/libmm-transcode.git] / transcode / mm_transcode_pipeline.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 int _mm_decode_audio_output_create(handle_s *handle);
25 static int _mm_decode_audio_output_link(handle_s *handle);
26 static int _mm_decode_video_output_create(handle_s *handle);
27 static int _mm_decode_video_output_link(handle_s *handle);
28 static int _mm_decodebin_pipeline_create(handle_s *handle);
29 static int _mm_encodebin_set_audio_property(handle_s *handle);
30 static int _mm_encodebin_set_property(handle_s *handle);
31 static int _mm_encodebin_set_video_property(handle_s *handle);
32 static int _mm_filesrc_pipeline_create(handle_s *handle);
33 static int _mm_filesrc_decodebin_link(handle_s *handle);
34
35 const gchar *_mm_check_media_type(GstCaps *caps)
36 {
37         /* check media type */
38         GstStructure *_str = gst_caps_get_structure(caps, 0);
39         const gchar *mime = gst_structure_get_name(_str);
40
41         return mime;
42 }
43
44 int _mm_cleanup_encodebin(handle_s *handle)
45 {
46         int ret = MM_ERROR_NONE;
47
48         if (!handle) {
49                 LOGE("[ERROR] - handle");
50                 return MM_ERROR_INVALID_ARGUMENT;
51         }
52
53         if (!handle->encodebin) {
54                 LOGE("[ERROR] - handle encodebin");
55                 return MM_ERROR_TRANSCODE_INTERNAL;
56         }
57
58         if (!handle->property) {
59                 LOGE("[ERROR] - handle property");
60                 return MM_ERROR_TRANSCODE_INTERNAL;
61         }
62
63         if (handle->encodebin->encvideopad) {
64                 gst_object_unref(GST_OBJECT(handle->encodebin->encvideopad));
65                 handle->encodebin->encvideopad = NULL;
66                 LOGD("Success - gst_object_unref (encvideopad)");
67         }
68
69         if (handle->encodebin->encaudiopad) {
70                 gst_object_unref(GST_OBJECT(handle->encodebin->encaudiopad));
71                 handle->encodebin->encaudiopad = NULL;
72                 LOGD("Success - gst_object_unref (encaudiopad)");
73         }
74
75         if (handle->property->caps) {
76                 gst_caps_unref(handle->property->caps);
77                 handle->property->caps = NULL;
78                 LOGD("gst_caps_unref");
79         }
80
81         return ret;
82 }
83
84 int _mm_cleanup_signal(handle_s *handle)
85 {
86         int ret = MM_ERROR_NONE;
87
88         if (!handle) {
89                 LOGE("[ERROR] - handle");
90                 return MM_ERROR_INVALID_ARGUMENT;
91         }
92
93         if (!handle->property) {
94                 LOGE("[ERROR] - handle property");
95                 return MM_ERROR_TRANSCODE_INTERNAL;
96         }
97
98         if (handle->property->progress_cb) {
99                 handle->property->progress_cb = NULL;
100                 handle->property->progress_cb_param = NULL;
101         }
102
103         if (handle->property->completed_cb) {
104                 handle->property->completed_cb = NULL;
105                 handle->property->completed_cb_param = NULL;
106         }
107
108         if (handle->property->audio_cb_probe_id) {
109                 g_source_remove(handle->property->audio_cb_probe_id);
110                 handle->property->audio_cb_probe_id = 0;
111                 LOGD("g_source_remove (audio_cb_probe_id)");
112         }
113
114         if (handle->property->video_cb_probe_id) {
115                 g_source_remove(handle->property->video_cb_probe_id);
116                 handle->property->video_cb_probe_id = 0;
117                 LOGD("g_source_remove (video_cb_probe_id)");
118         }
119
120         if (handle->property->progress_event_id) {
121                 g_source_remove(handle->property->progress_event_id);
122                 handle->property->progress_event_id = 0;
123                 LOGD("g_source_remove (progress_event_id)");
124         }
125
126         if (handle->encodebin->audio_event_probe_id) {
127                 g_source_remove(handle->encodebin->audio_event_probe_id);
128                 handle->encodebin->audio_event_probe_id = 0;
129                 LOGD("g_source_remove (audio_event_probe_id)");
130         }
131
132         if (handle->encodebin->video_event_probe_id) {
133                 g_source_remove(handle->encodebin->video_event_probe_id);
134                 handle->encodebin->video_event_probe_id = 0;
135                 LOGD("g_source_remove (video_event_probe_id)");
136         }
137
138         return ret;
139 }
140
141
142 int _mm_cleanup_pipeline(handle_s *handle)
143 {
144         int ret = MM_ERROR_NONE;
145
146         if (!handle) {
147                 LOGE("[ERROR] - handle");
148                 return MM_ERROR_INVALID_ARGUMENT;
149         }
150
151         if (!handle->property) {
152                 LOGE("[ERROR] - handle property");
153                 return MM_ERROR_TRANSCODE_INTERNAL;
154         }
155
156         handle->property->_MMHandle = 0;
157
158         /* g_thread_exit(handle->thread); */
159         LOGD("g_thread_exit");
160         if (handle->property->thread) {
161                 g_thread_join(handle->property->thread);
162                 LOGD("Success - join (thread)");
163         }
164
165         /* disconnecting bus watch */
166         if (handle->property->bus_watcher) {
167                 g_source_remove(handle->property->bus_watcher);
168                 LOGD("g_source_remove");
169                 handle->property->bus_watcher = 0;
170         }
171
172         if (handle->property->queue) {
173                 g_async_queue_unref(handle->property->queue);
174                 handle->property->queue = NULL;
175                 LOGD("Success - g_async_queue_unref(queue)");
176         }
177
178         if (handle->property->thread_mutex) {
179                 g_mutex_clear(handle->property->thread_mutex);
180                 g_free(handle->property->thread_mutex);
181                 handle->property->thread_mutex = NULL;
182                 LOGD("Success - free (thread_mutex)");
183         }
184
185         if (handle->property->thread_cond) {
186                 g_cond_clear(handle->property->thread_cond);
187                 g_free(handle->property->thread_cond);
188                 handle->property->thread_cond = NULL;
189                 LOGD("Success - free (thread_cond)");
190         }
191
192         if (handle->property->thread_exit_mutex) {
193                 g_mutex_clear(handle->property->thread_exit_mutex);
194                 g_free(handle->property->thread_exit_mutex);
195                 handle->property->thread_exit_mutex = NULL;
196                 LOGD("Success - free (thread_exit_mutex)");
197         }
198
199         /* release videopad */
200         if (handle->decoder_vidp) {
201                 if (handle->decoder_vidp->decvideosinkpad) {
202                         gst_object_unref(GST_OBJECT(handle->decoder_vidp->decvideosinkpad));
203                         handle->decoder_vidp->decvideosinkpad = NULL;
204                         LOGD("Success - gt_object_unref (decvideosinkpad)");
205                 }
206
207                 if (handle->decoder_vidp->decvideosrcpad) {
208                         gst_object_unref(GST_OBJECT(handle->decoder_vidp->decvideosrcpad));
209                         handle->decoder_vidp->decvideosrcpad = NULL;
210                         LOGD("Success - gst_object_unref (decvideosrcpad)");
211                 }
212
213                 if (handle->decoder_vidp->srcdecvideopad) {
214                         gst_object_unref(GST_OBJECT(handle->decoder_vidp->srcdecvideopad));
215                         handle->decoder_vidp->srcdecvideopad = NULL;
216                         LOGD("Success - gst_object_unref (srcdecvideopad)");
217                 }
218
219                 if (handle->decoder_vidp->sinkdecvideopad) {
220                         gst_object_unref(GST_OBJECT(handle->decoder_vidp->sinkdecvideopad));
221                         handle->decoder_vidp->sinkdecvideopad = NULL;
222                         LOGD("Success - gst_object_unref (sinkdecvideopad)");
223                 }
224         }
225
226         /* release audiopad */
227         if (handle->decoder_audp) {
228                 if (handle->decoder_audp->decaudiosinkpad) {
229                         gst_object_unref(GST_OBJECT(handle->decoder_audp->decaudiosinkpad));
230                         handle->decoder_audp->decaudiosinkpad = NULL;
231                         LOGD("Success - gst_object_unref (decaudiosinkpad)");
232                 }
233
234                 if (handle->decoder_audp->decaudiosrcpad) {
235                         gst_object_unref(GST_OBJECT(handle->decoder_audp->decaudiosrcpad));
236                         handle->decoder_audp->decaudiosrcpad = NULL;
237                         LOGD("Success - gst_object_unref (decaudiosrcpad)");
238                 }
239
240                 if (handle->decoder_audp->srcdecaudiopad) {
241                         gst_object_unref(GST_OBJECT(handle->decoder_audp->srcdecaudiopad));
242                         handle->decoder_audp->srcdecaudiopad = NULL;
243                         LOGD("Success - gst_object_unref (srcdecaudiopad)");
244                 }
245
246                 if (handle->decoder_audp->sinkdecaudiopad) {
247                         gst_object_unref(GST_OBJECT(handle->decoder_audp->sinkdecaudiopad));
248                         handle->decoder_audp->sinkdecaudiopad = NULL;
249                         LOGD("Success - gst_object_unref (sinkdecaudiopad)");
250                 }
251         }
252
253         if (_mm_cleanup_encodebin(handle) != MM_ERROR_NONE) {
254                 LOGE("ERROR -Play Pipeline");
255                 return FALSE;
256         } else {
257                 LOGD("Success -clean encodebin");
258         }
259
260         if (handle->property->sink_elements) {
261                 g_list_free(handle->property->sink_elements);
262                 handle->property->sink_elements = NULL;
263                 LOGD("Success - g_list_free (sink_elements)");
264         }
265
266         if (handle->pipeline) {
267                 gst_object_unref(handle->pipeline);
268                 handle->pipeline = NULL;
269                 LOGD("Success - gst_object_unref (pipeline)");
270         }
271
272         TRANSCODE_FREE(handle->property->mux);
273         TRANSCODE_FREE(handle->property->venc);
274         TRANSCODE_FREE(handle->property->aenc);
275         TRANSCODE_FREE(handle->decoder_vidp);
276         TRANSCODE_FREE(handle->decoder_audp);
277         TRANSCODE_FREE(handle->encodebin);
278         TRANSCODE_FREE(handle->property);
279         TRANSCODE_FREE(handle);
280
281         return ret;
282 }
283
284 static void _mm_decode_add_sink(handle_s *handle, GstElement *sink_elements)
285 {
286
287         if (!handle) {
288                 LOGE("[ERROR] - handle");
289                 return;
290         }
291
292         if (!handle->property) {
293                 LOGE("[ERROR] - handle property");
294                 return;
295         }
296
297         if (sink_elements) {
298                 handle->property->sink_elements = g_list_append(handle->property->sink_elements, sink_elements);
299                 LOGD("g_list_append");
300         }
301
302 }
303
304 static int _mm_decode_audio_output_create(handle_s *handle)
305 {
306         int ret = MM_ERROR_NONE;
307
308         if (!handle) {
309                 LOGE("[ERROR] - handle");
310                 return MM_ERROR_INVALID_ARGUMENT;
311         }
312
313         if (!handle->decoder_audp) {
314                 LOGE("[ERROR] - handle decoder audio process bin");
315                 return MM_ERROR_TRANSCODE_INTERNAL;
316         }
317
318         if (!handle->property) {
319                 LOGE("[ERROR] - handle property");
320                 return MM_ERROR_TRANSCODE_INTERNAL;
321         }
322
323         handle->decoder_audp->decaudiobin = gst_bin_new("audiobin");
324         if (!handle->decoder_audp->decaudiobin) {
325                 LOGE("decaudiobin could not be created");
326                 return MM_ERROR_TRANSCODE_INTERNAL;
327         }
328
329         handle->decoder_audp->decsinkaudioqueue = gst_element_factory_make("queue", "decsinkaudioqueue");
330         if (!handle->decoder_audp->decsinkaudioqueue) {
331                 LOGE("decsinkaudioqueue could not be created");
332                 return MM_ERROR_TRANSCODE_INTERNAL;
333         }
334
335         _mm_decode_add_sink(handle, handle->decoder_audp->decsinkaudioqueue);
336
337         handle->decoder_audp->decaudiosinkpad = gst_element_get_static_pad(handle->decoder_audp->decsinkaudioqueue, "sink");
338         if (!handle->decoder_audp->decaudiosinkpad) {
339                 LOGE("decaudiosinkpad could not be created");
340                 return MM_ERROR_TRANSCODE_INTERNAL;
341         }
342
343         if (handle->property->audioencoder == MM_AUDIOENCODER_NO_USE) {
344                 LOGD("[MM_AUDIOENCODER_NO_USE] fakesink create");
345
346                 handle->decoder_audp->audiofakesink = gst_element_factory_make("fakesink", "audiofakesink");
347                 if (!handle->decoder_audp->audiofakesink) {
348                         LOGE("fakesink element could not be created");
349                         return MM_ERROR_TRANSCODE_INTERNAL;
350                 }
351         } else {
352                 handle->decoder_audp->aconv = gst_element_factory_make("audioconvert", "aconv");
353                 if (!handle->decoder_audp->aconv) {
354                         LOGE("decaudiobin element could not be created");
355                         return MM_ERROR_TRANSCODE_INTERNAL;
356                 }
357
358                 handle->decoder_audp->valve = gst_element_factory_make("valve", "valve");
359                 if (!handle->decoder_audp->valve) {
360                         LOGE("decaudiobin element could not be created");
361                         return MM_ERROR_TRANSCODE_INTERNAL;
362                 }
363
364                 g_object_set(handle->decoder_audp->valve, "drop", FALSE, NULL);
365
366                 handle->decoder_audp->resample = gst_element_factory_make("audioresample", "audioresample");
367                 if (!handle->decoder_audp->resample) {
368                         LOGE("decaudiobin element could not be created");
369                         return MM_ERROR_TRANSCODE_INTERNAL;
370                 }
371
372                 handle->decoder_audp->audflt = gst_element_factory_make("capsfilter", "afilter");
373                 if (!handle->decoder_audp->audflt) {
374                         LOGE("audflt element could not be created");
375                         return MM_ERROR_TRANSCODE_INTERNAL;
376                 }
377
378                 handle->decoder_audp->decaudiosrcpad = gst_element_get_static_pad(handle->decoder_audp->audflt, "src");
379                 if (!handle->decoder_audp->decaudiosrcpad) {
380                         LOGE("decaudiosrcpad element could not be created");
381                         return MM_ERROR_TRANSCODE_INTERNAL;
382                 }
383         }
384
385         return ret;
386 }
387
388 static int _mm_decode_audio_output_link(handle_s *handle)
389 {
390         int ret = MM_ERROR_NONE;
391
392         if (!handle) {
393                 LOGE("[ERROR] - handle");
394                 return MM_ERROR_INVALID_ARGUMENT;
395         }
396
397         if (!handle->decoder_audp) {
398                 LOGE("[ERROR] - handle decoder audio process bin");
399                 return MM_ERROR_TRANSCODE_INTERNAL;
400         }
401
402         if (!handle->property) {
403                 LOGE("[ERROR] - handle property");
404                 return MM_ERROR_TRANSCODE_INTERNAL;
405         }
406
407         if (handle->property->audioencoder == MM_AUDIOENCODER_NO_USE) {
408                 LOGD("[MM_AUDIOENCODER_NO_USE] fakesink pad create");
409
410                 gst_bin_add_many(GST_BIN(handle->decoder_audp->decaudiobin), handle->decoder_audp->decsinkaudioqueue, handle->decoder_audp->audiofakesink, NULL);
411                 if (!gst_element_link_many(handle->decoder_audp->decsinkaudioqueue, handle->decoder_audp->audiofakesink, NULL)) {
412                         LOGE("[Audio Output Bin] gst_element_link_many failed");
413                         return MM_ERROR_TRANSCODE_INTERNAL;
414                 }
415
416                 gst_element_add_pad(handle->decoder_audp->decaudiobin, gst_ghost_pad_new("decbin_audiosink", handle->decoder_audp->decaudiosinkpad));
417                 /* get sink audiopad of decodebin */
418                 handle->decoder_audp->sinkdecaudiopad = gst_element_get_static_pad(handle->decoder_audp->decaudiobin, "decbin_audiosink");
419         } else {
420                 gst_bin_add_many(GST_BIN(handle->decoder_audp->decaudiobin), handle->decoder_audp->decsinkaudioqueue, handle->decoder_audp->valve, handle->decoder_audp->aconv, handle->decoder_audp->resample, handle->decoder_audp->audflt, NULL);
421                 if (!gst_element_link_many(handle->decoder_audp->decsinkaudioqueue, handle->decoder_audp->valve, handle->decoder_audp->aconv, handle->decoder_audp->resample, handle->decoder_audp->audflt, NULL)) {
422                         LOGE("[Audio Output Bin] gst_element_link_many failed");
423                         return MM_ERROR_TRANSCODE_INTERNAL;
424                 }
425
426                 gst_element_add_pad(handle->decoder_audp->decaudiobin, gst_ghost_pad_new("decbin_audiosink", handle->decoder_audp->decaudiosinkpad));
427                 gst_element_add_pad(handle->decoder_audp->decaudiobin, gst_ghost_pad_new("decbin_audiosrc", handle->decoder_audp->decaudiosrcpad));
428
429                 /* get sink audiopad of decodebin */
430                 handle->decoder_audp->sinkdecaudiopad = gst_element_get_static_pad(handle->decoder_audp->decaudiobin, "decbin_audiosink");
431                 /* get src audiopad of decodebin */
432                 handle->decoder_audp->srcdecaudiopad = gst_element_get_static_pad(handle->decoder_audp->decaudiobin, "decbin_audiosrc");
433
434                 handle->property->audio_cb_probe_id = gst_pad_add_probe(handle->decoder_audp->sinkdecaudiopad, GST_PAD_PROBE_TYPE_BUFFER, _mm_cb_audio_output_stream_probe, handle, NULL);
435                 /* must use sinkpad (sinkpad => srcpad) for normal resized video buffer */
436                 LOGD("audio_cb_probe_id: %lu", handle->property->audio_cb_probe_id);
437         }
438
439         gst_bin_add(GST_BIN(handle->pipeline), handle->decoder_audp->decaudiobin);
440         return ret;
441 }
442
443 static int _mm_decode_video_output_create(handle_s *handle)
444 {
445         int ret = MM_ERROR_NONE;
446
447         if (!handle) {
448                 LOGE("[ERROR] - handle");
449                 return MM_ERROR_INVALID_ARGUMENT;
450         }
451
452         if (!handle->property) {
453                 LOGE("[ERROR] - handle property");
454                 return MM_ERROR_TRANSCODE_INTERNAL;
455         }
456
457         if (!handle->decoder_vidp) {
458                 LOGE("[ERROR] - handle decoder video process bin");
459                 return MM_ERROR_TRANSCODE_INTERNAL;
460         }
461
462         handle->decoder_vidp->decvideobin = gst_bin_new("videobin");
463         if (!handle->decoder_vidp->decvideobin) {
464                 LOGE("decvideobin could not be created. Exiting");
465                 return MM_ERROR_TRANSCODE_INTERNAL;
466         }
467
468         handle->decoder_vidp->decsinkvideoqueue = gst_element_factory_make("queue", "decsinkvideoqueue");
469         if (!handle->decoder_vidp->decsinkvideoqueue) {
470                 LOGE("decsinkvideoqueue element could not be created. Exiting");
471                 return MM_ERROR_TRANSCODE_INTERNAL;
472         }
473
474         _mm_decode_add_sink(handle, handle->decoder_vidp->decsinkvideoqueue);
475
476         handle->decoder_vidp->decvideosinkpad = gst_element_get_static_pad(handle->decoder_vidp->decsinkvideoqueue, "sink");
477         if (!handle->decoder_vidp->decvideosinkpad) {
478                 LOGE("decvideosinkpad element could not be created. Exiting");
479                 return MM_ERROR_TRANSCODE_INTERNAL;
480         }
481
482         handle->decoder_vidp->videorate = gst_element_factory_make("videorate", "videorate");
483         if (!handle->decoder_vidp->videorate) {
484                 LOGE("videorate element could not be created. Exiting");
485                 return MM_ERROR_TRANSCODE_INTERNAL;
486         }
487
488         g_object_set(handle->decoder_vidp->videorate, "average-period", GST_SECOND / 2, NULL);
489         g_object_set(handle->decoder_vidp->videorate, "max-rate", 30, NULL);
490
491         handle->decoder_vidp->videoscale = gst_element_factory_make("videoscale", "scaler");
492         if (!handle->decoder_vidp->videoscale) {
493                 LOGE("videoscale element could not be created. Exiting");
494                 return MM_ERROR_TRANSCODE_INTERNAL;
495         }
496         /* Configure videoscale to use 4-tap scaling for higher quality */
497         g_object_set(handle->decoder_vidp->videoscale, "method", 2, NULL);
498
499         handle->decoder_vidp->vidflt = gst_element_factory_make("capsfilter", "vfilter");
500         if (!handle->decoder_vidp->vidflt) {
501                 LOGE("One element could not be created. Exiting");
502                 return MM_ERROR_TRANSCODE_INTERNAL;
503         }
504
505         handle->decoder_vidp->decvideosrcpad = gst_element_get_static_pad(handle->decoder_vidp->vidflt, "src");
506         if (!handle->decoder_vidp->decvideosrcpad) {
507                 LOGE("decvideosrcpad element could not be created. Exiting");
508                 return MM_ERROR_TRANSCODE_INTERNAL;
509         }
510
511         return ret;
512 }
513
514 static int _mm_decode_video_output_link(handle_s *handle)
515 {
516         int ret = MM_ERROR_NONE;
517
518         if (!handle) {
519                 LOGE("[ERROR] - handle");
520                 return MM_ERROR_INVALID_ARGUMENT;
521         }
522
523         if (!handle->decoder_vidp) {
524                 LOGE("[ERROR] - handle decoder video process bin");
525                 return MM_ERROR_TRANSCODE_INTERNAL;
526         }
527
528         gst_bin_add_many(GST_BIN(handle->decoder_vidp->decvideobin), handle->decoder_vidp->decsinkvideoqueue, handle->decoder_vidp->videoscale, handle->decoder_vidp->videorate, handle->decoder_vidp->vidflt, NULL);
529         if (!gst_element_link_many(handle->decoder_vidp->decsinkvideoqueue, handle->decoder_vidp->videoscale, handle->decoder_vidp->videorate, handle->decoder_vidp->vidflt, NULL)) {
530                 LOGE("[Video Output Bin] gst_element_link_many failed");
531                 return MM_ERROR_TRANSCODE_INTERNAL;
532         }
533
534         gst_element_add_pad(handle->decoder_vidp->decvideobin, gst_ghost_pad_new("decbin_videosink", handle->decoder_vidp->decvideosinkpad));
535         gst_element_add_pad(handle->decoder_vidp->decvideobin, gst_ghost_pad_new("decbin_videosrc", handle->decoder_vidp->decvideosrcpad));
536
537         handle->decoder_vidp->sinkdecvideopad = gst_element_get_static_pad(handle->decoder_vidp->decvideobin, "decbin_videosink");
538         handle->decoder_vidp->srcdecvideopad = gst_element_get_static_pad(handle->decoder_vidp->decvideobin, "decbin_videosrc");
539
540         handle->property->video_cb_probe_id = gst_pad_add_probe(handle->decoder_vidp->sinkdecvideopad, GST_PAD_PROBE_TYPE_BUFFER, _mm_cb_video_output_stream_probe, handle, NULL);
541         /* must use sinkpad (sinkpad => srcpad) */
542         LOGD("video_cb_probe_sink_id: %lu", handle->property->video_cb_probe_id);
543
544         gst_bin_add(GST_BIN(handle->pipeline), handle->decoder_vidp->decvideobin);
545
546         return ret;
547 }
548
549 static int _mm_decodebin_pipeline_create(handle_s *handle)
550 {
551         int ret = MM_ERROR_NONE;
552
553         /* autoplug-select is not worked when decodebin */
554         handle->decodebin = gst_element_factory_make("decodebin", "decoder");
555
556         if (!handle->decodebin) {
557                 LOGE("decbin element could not be created. Exiting");
558                 return MM_ERROR_TRANSCODE_INTERNAL;
559         }
560
561         g_signal_connect(handle->decodebin, "pad-added", G_CALLBACK(_mm_cb_decoder_newpad_encoder), handle);
562         g_signal_connect(handle->decodebin, "autoplug-select", G_CALLBACK(_mm_cb_decode_bin_autoplug_select), handle);
563
564         return ret;
565 }
566
567 int _mm_decodesrcbin_create(handle_s *handle)
568 {
569         int ret = MM_ERROR_NONE;
570
571         if (!handle) {
572                 LOGE("[ERROR] - handle");
573                 return MM_ERROR_INVALID_ARGUMENT;
574         }
575
576         if (!handle->decoder_vidp) {
577                 LOGE("[ERROR] - handle decoder video process bin");
578                 return MM_ERROR_TRANSCODE_INTERNAL;
579         }
580
581         if (!handle->decoder_audp) {
582                 LOGE("[ERROR] - handle decoder audio process bin");
583                 return MM_ERROR_TRANSCODE_INTERNAL;
584         }
585
586         if (!handle->property) {
587                 LOGE("[ERROR] - handle property");
588                 return MM_ERROR_TRANSCODE_INTERNAL;
589         }
590
591         ret = _mm_filesrc_pipeline_create(handle);
592         if (ret == MM_ERROR_NONE) {
593                 LOGD("Success - Create filesrc pipeline");
594         } else {
595                 LOGE("ERROR -Create filesrc pipeline");
596                 return ret;
597         }
598
599         if (handle->property->has_audio_stream) {
600                 ret = _mm_decode_audio_output_create(handle);
601                 if (ret == MM_ERROR_NONE) {
602                         LOGD("Success - Create audiobin pipeline: %p", handle->decoder_audp->decaudiobin);
603                 } else {
604                         LOGE("ERROR - Create audiobin pipeline");
605                         return ret;
606                 }
607         }
608
609         if (handle->property->has_video_stream) {
610                 ret = _mm_decode_video_output_create(handle);
611                 if (ret == MM_ERROR_NONE) {
612                         LOGD("Success - Create videobin pipeline: %p", handle->decoder_vidp->decvideobin);
613                 } else {
614                         LOGE("ERROR -Create videobin pipeline");
615                         return ret;
616                 }
617         }
618
619         ret = _mm_decodebin_pipeline_create(handle);
620         if (ret == MM_ERROR_NONE) {
621                 LOGD("Success - Create decodebin pipeline");
622         } else {
623                 LOGE("ERROR - Create decodebin pipeline");
624                 return ret;
625         }
626
627         return ret;
628 }
629
630 int _mm_decodesrcbin_link(handle_s *handle)
631 {
632         int ret = MM_ERROR_NONE;
633
634         if (!handle) {
635                 LOGE("[ERROR] - handle");
636                 return MM_ERROR_INVALID_ARGUMENT;
637         }
638
639         if (!handle->property) {
640                 LOGE("[ERROR] - handle property");
641                 return MM_ERROR_TRANSCODE_INTERNAL;
642         }
643
644         ret = _mm_filesrc_decodebin_link(handle);
645         if (ret == MM_ERROR_NONE) {
646                 LOGD("Success - _mm_filesrc_decodebin_link");
647         } else {
648                 LOGE("ERROR - _mm_filesrc_decodebin_link");
649                 return ret;
650         }
651
652         if (handle->property->has_audio_stream) {
653                 ret = _mm_decode_audio_output_link(handle);
654                 if (ret == MM_ERROR_NONE) {
655                         LOGD("Success - _mm_decode_audio_output_link");
656                 } else {
657                         LOGE("ERROR - _mm_decode_audio_output_link");
658                         return ret;
659                 }
660         }
661
662         if (handle->property->has_video_stream) {
663                 ret = _mm_decode_video_output_link(handle);
664                 if (ret == MM_ERROR_NONE) {
665                         LOGD("Success - _mm_decode_video_output_link");
666                 } else {
667                         LOGE("ERROR - _mm_decode_video_output_link");
668                         return ret;
669                 }
670         }
671
672         return ret;
673 }
674
675 int _mm_encodebin_create(handle_s *handle)
676 {
677         int ret = MM_ERROR_NONE;
678
679         if (!handle) {
680                 LOGE("[ERROR] - handle");
681                 return MM_ERROR_INVALID_ARGUMENT;
682         }
683
684         if (!handle->encodebin) {
685                 LOGE("[ERROR] - handle encodebin");
686                 return MM_ERROR_TRANSCODE_INTERNAL;
687         }
688
689         if (!handle->property) {
690                 LOGE("[ERROR] - handle property");
691                 return MM_ERROR_TRANSCODE_INTERNAL;
692         }
693
694         handle->encodebin->encbin = gst_element_factory_make("encodebin", "encodebin");
695
696         if (!handle->encodebin->encbin) {
697                 LOGE("encbin element could not be created");
698                 return MM_ERROR_TRANSCODE_INTERNAL;
699         }
700
701         if (handle->property->videoencoder != MM_VIDEOENCODER_NO_USE && handle->property->audioencoder != MM_AUDIOENCODER_NO_USE) {
702                 ret = _mm_encodebin_set_video_property(handle);
703                 if (ret != MM_ERROR_NONE) {
704                         LOGE("ERROR -Setup encodebin video property");
705                         return ret;
706                 }
707
708                 ret = _mm_encodebin_set_audio_property(handle);
709                 if (ret != MM_ERROR_NONE) {
710                         LOGE("ERROR -Setup encodebin audio property");
711                         return ret;
712                 }
713         } else if (handle->property->videoencoder != MM_VIDEOENCODER_NO_USE) {
714                 ret = _mm_encodebin_set_video_property(handle);
715                 if (ret != MM_ERROR_NONE) {
716                         LOGE("ERROR -Setup encodebin video property");
717                         return ret;
718                 }
719         } else if (handle->property->audioencoder != MM_AUDIOENCODER_NO_USE) {
720                 handle->encodebin->encodebin_profile = 1;
721                 LOGD("[AUDIO ONLY ENCODE]");
722                 ret = _mm_encodebin_set_audio_property(handle);
723                 if (ret != MM_ERROR_NONE) {
724                         LOGE("ERROR -Setup encodebin video property");
725                         return ret;
726                 }
727         }
728
729         LOGD("[Encodebin Profile: %d]", handle->encodebin->encodebin_profile);
730         ret = _mm_encodebin_set_property(handle);
731         if (ret != MM_ERROR_NONE) {
732                 LOGE("ERROR -Setup encodebin property");
733                 return ret;
734         }
735
736         return ret;
737 }
738
739 int _mm_encodebin_link(handle_s *handle)
740 {
741         int ret = MM_ERROR_NONE;
742
743         if (!handle) {
744                 LOGE("[ERROR] - handle");
745                 return MM_ERROR_INVALID_ARGUMENT;
746         }
747
748         if (!handle->encodebin) {
749                 LOGE("[ERROR] - handle encodebin");
750                 return MM_ERROR_TRANSCODE_INTERNAL;
751         }
752
753         if (!handle->property) {
754                 LOGE("[ERROR] - handle property");
755                 return MM_ERROR_TRANSCODE_INTERNAL;
756         }
757
758         /* Add encodebin to pipeline */
759         gst_bin_add(GST_BIN(handle->pipeline), handle->encodebin->encbin);
760
761         if (handle->property->has_video_stream) {
762                 if (handle->property->videoencoder != MM_VIDEOENCODER_NO_USE) {
763                         handle->encodebin->encvideopad = gst_element_get_request_pad(handle->encodebin->encbin, "video");
764                         if (handle->encodebin->encvideopad) {
765                                 LOGD("encvideopad: %p", handle->encodebin->encvideopad);
766                                 gst_pad_link(handle->decoder_vidp->srcdecvideopad, handle->encodebin->encvideopad);
767                                 handle->encodebin->audio_event_probe_id = gst_pad_add_probe(handle->encodebin->encvideopad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, _mm_cb_encodebin_sinkpad_event_probe, handle, NULL);
768                         } else {
769                                 LOGE("error encvideopad");
770                                 return MM_ERROR_TRANSCODE_INTERNAL;
771                         }
772                 }
773         }
774
775         if (handle->property->has_audio_stream) {
776                 if (handle->property->audioencoder != MM_AUDIOENCODER_NO_USE) {
777                         handle->encodebin->encaudiopad = gst_element_get_request_pad(handle->encodebin->encbin, "audio");
778                         if (handle->encodebin->encaudiopad) {
779                                 LOGD("encaudiopad: %p", handle->encodebin->encaudiopad);
780                                 gst_pad_link(handle->decoder_audp->srcdecaudiopad, handle->encodebin->encaudiopad);
781                                 handle->encodebin->audio_event_probe_id = gst_pad_add_probe(handle->encodebin->encaudiopad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, _mm_cb_encodebin_sinkpad_event_probe, handle, NULL);
782                         } else {
783                                 LOGE("error encaudiopad");
784                                 return MM_ERROR_TRANSCODE_INTERNAL;
785                         }
786                 }
787         }
788
789         return ret;
790 }
791
792 static int _mm_encodebin_set_audio_property(handle_s *handle)
793 {
794         int ret = MM_ERROR_NONE;
795
796         if (!handle) {
797                 LOGE("[ERROR] - handle");
798                 return MM_ERROR_INVALID_ARGUMENT;
799         }
800
801         if (!handle->encodebin) {
802                 LOGE("[ERROR] - handle encodebin");
803                 return MM_ERROR_TRANSCODE_INTERNAL;
804         }
805
806         if (!handle->property) {
807                 LOGE("[ERROR] - handle property");
808                 return MM_ERROR_TRANSCODE_INTERNAL;
809         }
810
811         if (handle->property->has_audio_stream) {
812                 /* Audio */
813                 if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(handle->encodebin->encbin)), ARS)) {
814                         g_object_set(G_OBJECT(handle->encodebin->encbin), ARS, 0, NULL);
815                         LOGD("[AUDIO RESAMPLE] encbin set auto-audio-resample");
816                 } else {
817                         LOGE("error [AUDIO RESAMPLE] encbin set auto-audio-resample");
818                         return MM_ERROR_TRANSCODE_INTERNAL;
819                 }
820
821                 if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(handle->encodebin->encbin)), ACON)) {
822                         g_object_set(G_OBJECT(handle->encodebin->encbin), ACON, 1, NULL);
823                         LOGD("encbin set auto-audio-convert");
824                 } else {
825                         LOGE("error encbin set auto-audio-convert");
826                         return MM_ERROR_TRANSCODE_INTERNAL;
827                 }
828
829                 if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(handle->encodebin->encbin)), AENC)) {
830                         g_object_set(G_OBJECT(handle->encodebin->encbin), AENC, handle->property->aenc, NULL);
831                         LOGD("[AUDIOENCODER] encbin set [%s: %s]", AENC, handle->property->aenc);
832                 } else {
833                         LOGE("error [AUDIOENCODER] encbin set [%s: %s]", AENC, handle->property->aenc);
834                         return MM_ERROR_TRANSCODE_INTERNAL;
835                 }
836
837                 if (g_strcmp0(handle->property->aenc, AACENC) == 0)
838                         g_object_set(G_OBJECT(gst_bin_get_by_name(GST_BIN(handle->encodebin->encbin), "audio_encode")), AACCOMPLIANCE, AACCOMPLIANCELEVEL, NULL);
839
840                 g_object_get(G_OBJECT(handle->encodebin->encbin), "use-aenc-queue", &(handle->encodebin->aencqueue), NULL);
841                 LOGD("aencqueue : %s", GST_ELEMENT_NAME(handle->encodebin->aencqueue));
842         }
843
844         return ret;
845 }
846
847 static int _mm_encodebin_set_property(handle_s *handle)
848 {
849         int ret = MM_ERROR_NONE;
850
851         if (!handle) {
852                 LOGE("[ERROR] - handle");
853                 return MM_ERROR_INVALID_ARGUMENT;
854         }
855
856         if (!handle->encodebin) {
857                 LOGE("[ERROR] - handle encodebin");
858                 return MM_ERROR_TRANSCODE_INTERNAL;
859         }
860
861         if (!handle->property) {
862                 LOGE("[ERROR] - handle property");
863                 return MM_ERROR_TRANSCODE_INTERNAL;
864         }
865
866         if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(handle->encodebin->encbin)), PROFILE)) {
867                 g_object_set(G_OBJECT(handle->encodebin->encbin), PROFILE, handle->encodebin->encodebin_profile, NULL);
868                 LOGD("encbin set profile");
869         } else {
870                 LOGE("error handle->encbin set profile");
871                 return MM_ERROR_TRANSCODE_INTERNAL;
872         }
873
874         if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(handle->encodebin->encbin)), MUX)) {
875                 g_object_set(G_OBJECT(handle->encodebin->encbin), MUX, handle->property->mux, NULL);
876                 LOGD("[MUX] encbin set [%s: %s]", MUX, handle->property->mux);
877         } else {
878                 LOGE("error [MUX] set [%s: %s]", MUX, handle->property->mux);
879                 return MM_ERROR_TRANSCODE_INTERNAL;
880         }
881
882         return ret;
883 }
884
885 static int _mm_encodebin_set_video_property(handle_s *handle)
886 {
887         int ret = MM_ERROR_NONE;
888
889         if (!handle) {
890                 LOGE("[ERROR] - handle");
891                 return MM_ERROR_INVALID_ARGUMENT;
892         }
893
894         if (!handle->encodebin) {
895                 LOGE("[ERROR] - handle encodebin");
896                 return MM_ERROR_TRANSCODE_INTERNAL;
897         }
898
899         if (!handle->property) {
900                 LOGE("[ERROR] - handle property");
901                 return MM_ERROR_TRANSCODE_INTERNAL;
902         }
903
904         if (handle->property->has_video_stream) {
905                 /* Video */
906                 if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(handle->encodebin->encbin)), ACS)) {
907                         g_object_set(G_OBJECT(handle->encodebin->encbin), ACS, 0, NULL);
908                         LOGD("[AUTO COLORSPACE] encbin set auto-colorspace");
909                 } else {
910                         LOGE("error [AUTO COLORSPACE] encbin set auto-colorspace");
911                         return MM_ERROR_TRANSCODE_INTERNAL;
912                 }
913
914                 if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(handle->encodebin->encbin)), VENC)) {
915                         g_object_set(G_OBJECT(handle->encodebin->encbin), VENC, handle->property->venc, NULL);
916                         LOGD("[VIDEOENCODER] encbin set [%s: %s]", VENC, handle->property->venc);
917                 } else {
918                         LOGE("error [VIDEOENCODER] set [%s: %s]", VENC, handle->property->venc);
919                         return MM_ERROR_TRANSCODE_INTERNAL;
920                 }
921
922                 g_object_get(G_OBJECT(handle->encodebin->encbin), "use-venc-queue", &(handle->encodebin->vencqueue), NULL);
923                 LOGD("vencqueue : %s", GST_ELEMENT_NAME(handle->encodebin->vencqueue));
924         }
925
926         return ret;
927 }
928
929 int _mm_filesink_create(handle_s *handle)
930 {
931         int ret = MM_ERROR_NONE;
932
933         if (!handle) {
934                 LOGE("[ERROR] - handle");
935                 return MM_ERROR_INVALID_ARGUMENT;
936         }
937
938         handle->filesink = gst_element_factory_make("filesink", "filesink");
939
940         if (!handle->filesink) {
941                 LOGE("filesink element could not be created");
942                 return MM_ERROR_TRANSCODE_INTERNAL;
943         }
944
945         LOGD("[sync]");
946         g_object_set(G_OBJECT(handle->filesink), "sync", TRUE, NULL);
947         g_object_set(G_OBJECT(handle->filesink), "async", FALSE, NULL);
948
949         return ret;
950 }
951
952 int _mm_filesink_link(handle_s *handle)
953 {
954         int ret = MM_ERROR_NONE;
955
956         if (!handle) {
957                 LOGE("[ERROR] - handle");
958                 return MM_ERROR_INVALID_ARGUMENT;
959         }
960
961         if (!handle->encodebin) {
962                 LOGE("[ERROR] - handle encodebin");
963                 return MM_ERROR_TRANSCODE_INTERNAL;
964         }
965
966         /* Add encodesinkbin to pipeline */
967         gst_bin_add(GST_BIN(handle->pipeline), handle->filesink);
968
969         /* link encodebin and filesink */
970         if (!gst_element_link(handle->encodebin->encbin, handle->filesink)) {
971                 LOGE("gst_element_link [encbin ! filesink] failed");
972                 return MM_ERROR_TRANSCODE_INTERNAL;
973         } else {
974                 LOGD("gst_element_link [encbin ! filesink]");
975         }
976
977         return ret;
978 }
979
980 static int _mm_filesrc_pipeline_create(handle_s *handle)
981 {
982         int ret = MM_ERROR_NONE;
983
984         handle->filesrc = gst_element_factory_make("filesrc", "source");
985
986         if (!handle->filesrc) {
987                 LOGE("filesrc element could not be created. Exiting");
988                 return MM_ERROR_TRANSCODE_INTERNAL;
989         }
990
991         if (!handle->property) {
992                 LOGE("[ERROR] - handle property");
993                 return MM_ERROR_TRANSCODE_INTERNAL;
994         }
995
996         LOGD("sourcefile: %s", handle->property->sourcefile);
997         g_object_set(G_OBJECT(handle->filesrc), "location", handle->property->sourcefile, NULL);
998
999         return ret;
1000 }
1001
1002 static int _mm_filesrc_decodebin_link(handle_s *handle)
1003 {
1004         int ret = MM_ERROR_NONE;
1005
1006         if (!handle) {
1007                 LOGE("[ERROR] - handle");
1008                 return MM_ERROR_INVALID_ARGUMENT;
1009         }
1010
1011         /* Add element(filesrc, decodebin) */
1012         gst_bin_add_many(GST_BIN(handle->pipeline), handle->filesrc, handle->decodebin, NULL);
1013
1014         if (!gst_element_link_many(handle->filesrc, handle->decodebin, NULL)) {
1015                 LOGE("gst_element_link_many src ! decbin failed");
1016                 return MM_ERROR_TRANSCODE_INTERNAL;
1017         }
1018
1019         return ret;
1020 }
1021
1022 int _mm_transcode_preset_capsfilter(handle_s *handle, unsigned int resolution_width, unsigned int resolution_height)
1023 {
1024         int ret = MM_ERROR_NONE;
1025
1026         if (!handle) {
1027                 LOGE("[ERROR] - handle");
1028                 return MM_ERROR_INVALID_ARGUMENT;
1029         }
1030
1031         if (!handle->decoder_vidp) {
1032                 LOGE("[ERROR] - handle decoder video process bin");
1033                 return MM_ERROR_TRANSCODE_INTERNAL;
1034         }
1035
1036         if (!handle->property) {
1037                 LOGE("[ERROR] - handle property");
1038                 return MM_ERROR_TRANSCODE_INTERNAL;
1039         }
1040
1041         if (handle->decoder_vidp->vidflt) {
1042                 LOGD("[Resolution] Output Width: [%d], Output Height: [%d]", resolution_width, resolution_height);
1043
1044                 if (resolution_width == 0 || resolution_height == 0)
1045                         g_object_set(G_OBJECT(handle->decoder_vidp->vidflt), "caps", gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "I420", NULL), NULL);
1046                 else
1047                         g_object_set(G_OBJECT(handle->decoder_vidp->vidflt), "caps", gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "I420", "width", G_TYPE_INT, resolution_width, "height", G_TYPE_INT, resolution_height, NULL), NULL);
1048         };
1049
1050         return ret;
1051 }
1052
1053 int _mm_setup_pipeline(handle_s *handle)
1054 {
1055         int ret = MM_ERROR_NONE;
1056
1057         if (!handle) {
1058                 LOGE("[ERROR] - handle");
1059                 return MM_ERROR_INVALID_ARGUMENT;
1060         }
1061
1062         handle->pipeline = gst_pipeline_new("TransCode");
1063         LOGD("Success - pipeline");
1064
1065         if (!handle->pipeline) {
1066                 LOGE("pipeline could not be created. Exiting");
1067                 return MM_ERROR_TRANSCODE_INTERNAL;
1068         }
1069
1070         return ret;
1071 }