Add internal function - ms_find_element_in_bin_by_type()
[platform/core/api/mediastreamer.git] / src / media_streamer_gst.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <bundle.h>
18 #include "media_streamer_gst.h"
19 #include "media_streamer_node.h"
20
21 #define MS_PADS_UNLINK(pad, peer) GST_PAD_IS_SRC(pad) ? \
22                 gst_pad_unlink(pad, peer) : \
23                 gst_pad_unlink(peer, pad)
24 #define H264_PARSER_CONFIG_INTERVAL 5
25 #define H264_ENCODER_ZEROLATENCY 0x00000004
26
27 #define MEDIASTREAMER_DECODEBIN_TYPE_DECODER "video_decoder"
28
29 typedef enum {
30         MEDIA_STREAMER_SINK_BIN_NORMAL,
31         MEDIA_STREAMER_SINK_BIN_RTP_SERVER,
32         MEDIA_STREAMER_SINK_BIN_ADAPTIVE,
33 } media_streamer_sink_bin_type_e;
34
35 static int __ms_adaptive_sink_prepare(media_streamer_s *ms_streamer);
36
37 void ms_generate_dots(GstElement *bin, gchar *name_tag)
38 {
39         gchar *dot_name;
40         ms_retm_if(bin == NULL, "bin is NULL");
41
42         if (!name_tag)
43                 dot_name = g_strdup(DOT_FILE_NAME);
44         else
45                 dot_name = g_strconcat(DOT_FILE_NAME, ".", name_tag, NULL);
46
47         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(bin), GST_DEBUG_GRAPH_SHOW_ALL, dot_name);
48
49         MS_SAFE_GFREE(dot_name);
50 }
51
52 static int __ms_add_no_target_ghostpad(GstElement *gst_bin, const char *ghost_pad_name, GstPadDirection pad_direction)
53 {
54         int ret = MEDIA_STREAMER_ERROR_NONE;
55         gchar *bin_name = NULL;
56         GstPad *ghost_pad = NULL;
57
58         ms_debug_fenter();
59
60         ms_retvm_if(gst_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_bin is NULL");
61
62         bin_name = gst_element_get_name(gst_bin);
63         ghost_pad = gst_ghost_pad_new_no_target(ghost_pad_name, pad_direction);
64         if (gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad)) {
65                 gst_pad_set_active(ghost_pad, TRUE);
66                 ms_info("Added [%s] empty ghostpad into [%s]", ghost_pad_name, bin_name);
67         } else {
68                 ms_info("Error: Failed to add empty [%s] ghostpad into [%s]", ghost_pad_name, bin_name);
69                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
70         }
71
72         MS_SAFE_GFREE(bin_name);
73
74         ms_debug_fleave();
75
76         return ret;
77 }
78
79 static gboolean __ms_add_ghostpad(GstElement *gst_element, const char *pad_name, GstElement *gst_bin, const char *ghost_pad_name)
80 {
81         gboolean ret = FALSE;
82         GstPad *ghost_pad = NULL;
83         GstPad *element_pad = NULL;
84
85         ms_debug_fenter();
86
87         ms_retvm_if(!gst_element, FALSE, "gst_element is NULL");
88         ms_retvm_if(!pad_name, FALSE, "pad_name is NULL");
89         ms_retvm_if(!gst_bin, FALSE, "gst_bin is NULL");
90
91         element_pad = gst_element_get_static_pad(gst_element, pad_name);
92
93         /* Check, if pad is not static, get it by request */
94         if (element_pad == NULL)
95                 element_pad = gst_element_get_request_pad(gst_element, pad_name);
96
97         ghost_pad = gst_ghost_pad_new(ghost_pad_name, element_pad);
98         ms_retvm_if(!ghost_pad, FALSE, "ghost_pad is NULL");
99
100         gst_pad_set_active(ghost_pad, TRUE);
101
102         ret = gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad);
103
104         if (ret)
105                 ms_info("Added %s ghostpad from [%s] into [%s]", pad_name, GST_ELEMENT_NAME(gst_element), GST_ELEMENT_NAME(gst_bin));
106         else
107                 ms_error("Error: element [%s] does not have valid [%s] pad for adding into [%s] bin", GST_ELEMENT_NAME(gst_element), pad_name, GST_ELEMENT_NAME(gst_bin));
108
109         MS_SAFE_UNREF(element_pad);
110
111         ms_debug_fleave();
112
113         return ret;
114 }
115
116 /* This unlinks from its peer and ghostpads on its way */
117 static gboolean __ms_pad_peer_unlink(GstPad *pad)
118 {
119         gboolean ret = TRUE;
120         GstPad *peer_pad = NULL;
121
122         ms_debug_fenter();
123
124         ms_retvm_if(!pad, FALSE, "pad is NULL");
125
126         if (!gst_pad_is_linked(pad))
127                 return TRUE;
128
129         peer_pad = gst_pad_get_peer(pad);
130         ms_retvm_if(!peer_pad, FALSE, "Fail to get peer pad");
131
132         if (GST_IS_PROXY_PAD(peer_pad)) {
133
134                 GstObject *ghost_object = gst_pad_get_parent(peer_pad);
135                 if (GST_IS_GHOST_PAD(ghost_object)) {
136                         GstPad *ghost_pad = GST_PAD(ghost_object);
137                         GstPad *target_pad = gst_pad_get_peer(ghost_pad);
138
139                         if (target_pad && GST_IS_GHOST_PAD(target_pad))
140                                 ret = ret && gst_element_remove_pad(GST_ELEMENT(GST_PAD_PARENT(target_pad)), target_pad);
141                         else {
142                                 /* This is a usual static pad */
143                                 if (target_pad)
144                                         ret = ret && MS_PADS_UNLINK(ghost_pad, target_pad);
145                                 else
146                                         ms_info("Ghost Pad [%s] does not have target.", GST_PAD_NAME(ghost_pad));
147                         }
148                         ret = ret && gst_element_remove_pad(GST_ELEMENT(GST_PAD_PARENT(ghost_pad)), ghost_pad);
149
150                         MS_SAFE_UNREF(target_pad);
151                         MS_SAFE_UNREF(ghost_pad);
152                 } else {
153                         MS_SAFE_UNREF(ghost_object);
154                 }
155         } else if (GST_IS_GHOST_PAD(peer_pad)) {
156                 ret = ret && gst_element_remove_pad(GST_ELEMENT(GST_PAD_PARENT(peer_pad)), peer_pad);
157         } else {
158                 /* This is a usual static pad */
159                 ret = ret && MS_PADS_UNLINK(pad, peer_pad);
160         }
161
162         MS_SAFE_UNREF(peer_pad);
163
164         ms_debug_fleave();
165
166         return ret;
167 }
168
169 static GstElement *__ms_pad_get_peer_element(GstPad *pad)
170 {
171         GstPad *peer_pad = NULL;
172         GstElement *ret = NULL;
173
174         ms_debug_fenter();
175
176         ms_retvm_if(!pad, NULL, "pad is NULL");
177
178         if (!gst_pad_is_linked(pad)) {
179                 ms_info("Pad [%s:%s] is not linked yet", GST_DEBUG_PAD_NAME(pad));
180                 return NULL;
181         }
182
183         peer_pad = gst_pad_get_peer(pad);
184         ms_retvm_if(!peer_pad, NULL, "Fail to get peer pad");
185
186         ret = gst_pad_get_parent_element(peer_pad);
187         if (!ret) {
188                 if (GST_IS_PROXY_PAD(peer_pad)) {
189                         GstPad *ghost_pad = GST_PAD(gst_pad_get_parent(peer_pad));
190                         GstPad *target_pad = gst_pad_get_peer(ghost_pad);
191                         if (GST_GHOST_PAD(target_pad)) {
192                                 GstPad *element_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(target_pad));
193                                 ret = gst_pad_get_parent_element(element_pad);
194                                 MS_SAFE_UNREF(element_pad);
195                         } else {
196                                 /* This is a usual static pad */
197                                 ret = gst_pad_get_parent_element(target_pad);
198                         }
199
200                         MS_SAFE_UNREF(target_pad);
201                         MS_SAFE_UNREF(ghost_pad);
202                 } else if (GST_IS_GHOST_PAD(peer_pad)) {
203                         GstPad *element_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(peer_pad));
204                         ret = gst_pad_get_parent_element(element_pad);
205                         MS_SAFE_UNREF(element_pad);
206                 } else {
207                         /* This is a usual static pad */
208                         ret = gst_pad_get_parent_element(peer_pad);
209                 }
210         }
211         MS_SAFE_UNREF(peer_pad);
212
213         ms_debug_fleave();
214
215         return ret;
216 }
217
218 gboolean ms_element_unlink(GstElement *element)
219 {
220         gboolean ret = TRUE;
221         GstPad *pad = NULL;
222         GValue elem = G_VALUE_INIT;
223         GstIterator *pad_iterator = NULL;
224
225         ms_debug_fenter();
226
227         ms_retvm_if(!element, FALSE, "element is NULL");
228
229         pad_iterator = gst_element_iterate_pads(element);
230         while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &elem)) {
231                 pad = (GstPad *) g_value_get_object(&elem);
232                 ret = ret && __ms_pad_peer_unlink(pad);
233                 g_value_reset(&elem);
234         }
235         g_value_unset(&elem);
236         gst_iterator_free(pad_iterator);
237
238         ms_debug_fleave();
239
240         return ret;
241 }
242
243 gboolean ms_bin_remove_element(GstElement *element)
244 {
245         GstElement *parent = NULL;
246         gboolean ret = FALSE;
247
248         ms_debug_fenter();
249
250         ms_retvm_if(!element, FALSE, "element is NULL");
251
252         parent = (GstElement *) gst_element_get_parent(element);
253
254         /* Remove node's element from bin that decreases ref count */
255         if (parent != NULL) {
256                 ret = gst_bin_remove(GST_BIN(parent), element);
257                 if (ret)
258                         ms_debug("Element [%s] removed from [%s] bin", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(parent));
259         }
260
261         MS_SAFE_UNREF(parent);
262
263         ms_debug_fleave();
264
265         return ret;
266 }
267
268 gboolean ms_bin_add_element(GstElement *bin, GstElement *element, gboolean do_ref)
269 {
270         GstElement *parent = NULL;
271         gboolean ret = FALSE;
272
273         ms_debug_fenter();
274
275         ms_retvm_if(!bin, FALSE, "bin is NULL");
276         ms_retvm_if(!element, FALSE, "element is NULL");
277
278         parent = (GstElement *) gst_element_get_parent(element);
279
280         /* Add node's element into bin and increases ref count if needed */
281         if (parent == NULL) {
282                 ret = gst_bin_add(GST_BIN(bin), element);
283                 if (ret && do_ref) {
284                         ms_debug("Element [%s] added into [%s] bin", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(bin));
285                         gst_object_ref(element);
286                 }
287         }
288
289         MS_SAFE_UNREF(parent);
290
291         ms_debug_fleave();
292
293         return ret;
294 }
295
296 const gchar *ms_get_pad_type(GstPad *element_pad)
297 {
298         const gchar *pad_type = NULL;
299         GstCaps *pad_caps = NULL;
300
301         ms_debug_fenter();
302
303         ms_retvm_if(!element_pad, NULL, "element_pad is NULL");
304
305         pad_caps = gst_pad_query_caps(element_pad, 0);
306         MS_GET_CAPS_TYPE(pad_caps, pad_type);
307         gst_caps_unref(pad_caps);
308
309         ms_debug_fleave();
310
311         return pad_type;
312 }
313
314 static GstElement *__ms_find_peer_element_by_type(GstElement *previous_element, GstPad *prev_elem_src_pad, node_info_s *node_klass_type)
315 {
316         GstElement *peer_element = NULL;
317         GstIterator *src_pad_iterator = NULL;
318         GValue src_pad_value = G_VALUE_INIT;
319         const gchar *found_klass = NULL;
320
321         ms_debug_fenter();
322
323         ms_retvm_if(!previous_element, NULL, "previous_element is NULL");
324         ms_retvm_if(!node_klass_type, NULL, "node_klass_type is NULL");
325         ms_retvm_if(!node_klass_type->klass_name, NULL, "node_klass_type->klass_name is NULL");
326         ms_retvm_if(!node_klass_type->default_name, NULL, "node_klass_type->default_name is NULL");
327
328         if (prev_elem_src_pad) {
329
330                 /* Check if previous element`s source pad is connected with element */
331                 peer_element = __ms_pad_get_peer_element(prev_elem_src_pad);
332                 if (peer_element) {
333                         found_klass = gst_element_factory_get_klass(gst_element_get_factory(peer_element));
334                         if (g_strrstr(found_klass, node_klass_type->klass_name) || g_strrstr(GST_ELEMENT_NAME(peer_element), node_klass_type->default_name))
335                                 ms_info(" Found peer element [%s] ", GST_ELEMENT_NAME(peer_element));
336                         else
337                                 MS_SAFE_UNREF(peer_element);
338                 }
339         } else {
340
341                 /* Check if any of previous element`s source pads is connected with element */
342                 src_pad_iterator = gst_element_iterate_src_pads(previous_element);
343                 while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) {
344                         GstPad *src_pad = (GstPad *) g_value_get_object(&src_pad_value);
345                         peer_element = __ms_pad_get_peer_element(src_pad);
346                         if (peer_element) {
347                                 found_klass = gst_element_factory_get_klass(gst_element_get_factory(peer_element));
348                                 if (g_strrstr(found_klass, node_klass_type->klass_name) || g_strrstr(GST_ELEMENT_NAME(peer_element), node_klass_type->default_name)) {
349                                         ms_info(" Found peer element [%s] ", GST_ELEMENT_NAME(peer_element));
350                                         g_value_reset(&src_pad_value);
351                                         break;
352                                 } else
353                                         MS_SAFE_UNREF(peer_element);
354                         }
355                         g_value_reset(&src_pad_value);
356                 }
357                 g_value_unset(&src_pad_value);
358                 gst_iterator_free(src_pad_iterator);
359         }
360
361         if (!peer_element)
362                 ms_info(" Element [%s] is not connected", GST_ELEMENT_NAME(previous_element));
363
364         ms_debug_fleave();
365
366         return peer_element;
367 }
368
369 static gboolean __ms_link_two_elements(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *found_element)
370 {
371         GValue src_pad_value = G_VALUE_INIT;
372         gboolean elements_linked = FALSE;
373         GstPad * found_sink_pad = NULL;
374         GstElement *peer_element = NULL;
375         GstIterator *src_pad_iterator = NULL;
376         GstPad *src_pad = NULL;
377
378         ms_debug_fenter();
379
380         ms_retvm_if(!previous_element, FALSE, "previous_element is NULL");
381         ms_retvm_if(!found_element, FALSE, "found_element is NULL");
382
383         if (prev_elem_src_pad) {
384                 peer_element = __ms_pad_get_peer_element(prev_elem_src_pad);
385                 if (!gst_pad_is_linked(prev_elem_src_pad)) {
386
387                         /* Check compatibility of previous element and unlinked found element */
388                         found_sink_pad = gst_element_get_compatible_pad(found_element, prev_elem_src_pad, NULL);
389                         if (found_sink_pad)
390                                 elements_linked = gst_element_link_pads(previous_element, GST_PAD_NAME(prev_elem_src_pad), found_element, GST_PAD_NAME(found_sink_pad));
391                 } else if (peer_element == found_element) {
392                         elements_linked = TRUE;
393                 }
394                 MS_SAFE_UNREF(peer_element);
395         } else {
396
397                 /* Check if previous element has any unlinked src pad */
398                 src_pad_iterator = gst_element_iterate_src_pads(previous_element);
399                 while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) {
400                         src_pad = (GstPad *) g_value_get_object(&src_pad_value);
401                         GstElement *peer_element = __ms_pad_get_peer_element(src_pad);
402                         if (!gst_pad_is_linked(src_pad)) {
403
404                                 /* Check compatibility of previous element and unlinked found element */
405                                 found_sink_pad = gst_element_get_compatible_pad(found_element, src_pad, NULL);
406                                 if (found_sink_pad) {
407                                         elements_linked = gst_element_link_pads(previous_element, GST_PAD_NAME(src_pad), found_element, GST_PAD_NAME(found_sink_pad));
408                                         if (elements_linked) {
409                                                 g_value_reset(&src_pad_value);
410                                                 MS_SAFE_UNREF(peer_element);
411                                                 break;
412                                         }
413                                 }
414                         } else if (peer_element == found_element) {
415                                 elements_linked = TRUE;
416                         }
417                         MS_SAFE_UNREF(peer_element);
418                         g_value_reset(&src_pad_value);
419                 }
420                 g_value_unset(&src_pad_value);
421                 gst_iterator_free(src_pad_iterator);
422         }
423
424         if (found_sink_pad) {
425                 if (elements_linked)
426                         ms_info("Succeeded to link [%s] -> [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(found_element));
427                 else
428                         ms_debug("Failed to link [%s] and [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(found_element));
429         } else
430                 ms_info("Element [%s] has no free compatible pad to be connected with [%s] or linked", GST_ELEMENT_NAME(found_element), GST_ELEMENT_NAME(previous_element));
431
432         MS_SAFE_UNREF(found_sink_pad);
433
434         ms_debug_fleave();
435
436         return elements_linked;
437 }
438
439 static GstElement *__ms_bin_find_element_and_link_by_type(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *search_bin, node_info_s *node_klass_type)
440 {
441         GValue element_value = G_VALUE_INIT;
442         GstElement *found_element = NULL;
443         gboolean elements_linked = FALSE;
444         const gchar *found_klass = NULL;
445         GstIterator *bin_iterator = NULL;
446
447         ms_debug_fenter();
448
449         ms_retvm_if(!previous_element, NULL, "previous_element is NULL");
450         ms_retvm_if(!search_bin, NULL, "search_bin is NULL");
451         ms_retvm_if(!node_klass_type, NULL, "node_klass_type is NULL");
452         ms_retvm_if(!node_klass_type->default_name, NULL, "node_klass_type->default_name is NULL");
453
454         bin_iterator = gst_bin_iterate_sorted(GST_BIN(search_bin));
455
456         while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &element_value)) {
457                 found_element = (GstElement *) g_value_get_object(&element_value);
458                 found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element));
459
460                 /* Check if found element is of appropriate needed plugin class */
461                 if (g_strrstr(found_klass, node_klass_type->klass_name) ||
462                         g_strrstr(GST_ELEMENT_NAME(found_element), node_klass_type->default_name)) {
463                         ms_info("Found element by type [%s]", GST_ELEMENT_NAME(found_element));
464                         if (__ms_link_two_elements(previous_element, prev_elem_src_pad, found_element)) {
465                                 elements_linked = TRUE;
466                                 g_value_reset(&element_value);
467                                 g_object_ref(found_element);
468                                 break;
469                         }
470                 }
471                 g_value_reset(&element_value);
472         }
473
474         g_value_unset(&element_value);
475         gst_iterator_free(bin_iterator);
476
477         ms_debug_fleave();
478
479         return elements_linked ? found_element : NULL;
480 }
481
482 GstElement *ms_find_element_in_bin_by_type(GstElement *bin, node_info_s *node_klass_type)
483 {
484         GValue element_value = G_VALUE_INIT;
485         GstElement *found_element = NULL;
486         GstElement *next_element = NULL;
487         const gchar *found_klass = NULL;
488         GstIterator *bin_iterator = NULL;
489
490         ms_debug_fenter();
491
492         ms_retvm_if(!bin, NULL, "bin is NULL");
493         ms_retvm_if(!node_klass_type, NULL, "node_klass_type is NULL");
494         ms_retvm_if(!node_klass_type->default_name, NULL, "node_klass_type->default_name is NULL");
495
496         bin_iterator = gst_bin_iterate_sorted(GST_BIN(bin));
497
498         while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &element_value)) {
499                 next_element = (GstElement *) g_value_get_object(&element_value);
500                 found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element));
501
502                 /* Check if found element is of appropriate needed plugin class */
503                 if (g_strrstr(found_klass, node_klass_type->klass_name) ||
504                         g_strrstr(GST_ELEMENT_NAME(next_element), node_klass_type->default_name)) {
505                         ms_info("Found element by type [%s]", GST_ELEMENT_NAME(next_element));
506                         found_element = next_element;
507                         break;
508                 }
509
510                 g_value_reset(&element_value);
511         }
512
513         gst_iterator_free(bin_iterator);
514
515         ms_debug_fleave();
516
517         return found_element;
518 }
519
520 static int __ms_factory_rank_compare(GstPluginFeature *first_feature, GstPluginFeature *second_feature)
521 {
522         ms_debug_fenter();
523         guint first_rank = 0, second_rank = 0;
524
525         first_rank = gst_plugin_feature_get_rank(first_feature);
526         second_rank = gst_plugin_feature_get_rank(second_feature);
527         ms_debug("second[%s]_rank(%d) - first[%s]_rank(%d) = (%d)",
528                 GST_OBJECT_NAME(GST_ELEMENT_FACTORY(second_feature)), second_rank,
529                 GST_OBJECT_NAME(GST_ELEMENT_FACTORY(first_feature)), first_rank, second_rank - first_rank);
530
531         ms_debug_fleave();
532         return second_rank - first_rank;
533 }
534
535 GstElement *ms_combine_next_element(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *bin_to_find_in, media_streamer_node_type_e node_type)
536 {
537         GstCaps *prev_caps = NULL;
538         GstElement *found_element = NULL;
539         node_info_s *node_klass_type = NULL;
540
541         ms_retvm_if(!previous_element, NULL, "previous_element is NULL");
542         ms_retvm_if(!bin_to_find_in, NULL, "bin_to_find_in is NULL");
543
544         ms_debug_fenter();
545
546         node_klass_type = ms_node_get_klass_by_its_type(node_type);
547
548         /* - 1 - If previous element is linked  - check for peer element */
549         found_element = __ms_find_peer_element_by_type(GST_ELEMENT(previous_element), prev_elem_src_pad, node_klass_type);
550
551         /* - 2 - If previous element is not linked  - find in bin by type */
552         if (!found_element)
553                 found_element = __ms_bin_find_element_and_link_by_type(previous_element, prev_elem_src_pad, bin_to_find_in, node_klass_type);
554
555         /* - 3 - If element by type is not found in bin - create element by type */
556         if (!found_element) {
557
558                 /* Create Node type information for a New element */
559                 if (prev_elem_src_pad)
560                         prev_caps = gst_pad_query_caps(prev_elem_src_pad, 0);
561                 else {
562                         GstPad *src_pad = gst_element_get_static_pad(previous_element, "src");
563                         if (src_pad)
564                                 prev_caps = gst_pad_query_caps(src_pad, 0);
565                         MS_SAFE_UNREF(src_pad);
566                 }
567                 node_plug_s plug_info = {node_klass_type, NULL, prev_caps, NULL};
568
569                 /* Create Node by ini or registry */
570                 found_element = ms_node_element_create(&plug_info, node_type);
571                 if (found_element) {
572                         ms_info("New Element [%s] is created ", GST_ELEMENT_NAME(found_element));
573
574                         /* Add created element */
575                         if (ms_bin_add_element(bin_to_find_in, found_element, TRUE)) {
576                                 gst_element_sync_state_with_parent(found_element);
577                                 __ms_link_two_elements(previous_element, prev_elem_src_pad, found_element);
578                                 ms_generate_dots(bin_to_find_in, GST_ELEMENT_NAME(found_element));
579                         } else {
580                                 ms_error("Element [%s] was not added into [%s] bin", GST_ELEMENT_NAME(found_element), GST_ELEMENT_NAME(bin_to_find_in));
581                                 MS_SAFE_UNREF(found_element);
582                         }
583                 } else
584                         ms_info("New Element is not created ");
585         } else
586                 ms_info("Next element is not combined");
587
588         MS_SAFE_UNREF(previous_element);
589
590         ms_debug_fleave();
591
592         return found_element;
593 }
594
595 static gint __decodebin_autoplug_select_cb(GstElement *bin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, gpointer data)
596 {
597         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed */
598         typedef enum {
599                 GST_AUTOPLUG_SELECT_TRY,
600                 GST_AUTOPLUG_SELECT_EXPOSE,
601                 GST_AUTOPLUG_SELECT_SKIP
602         } GstAutoplugSelectResult;
603
604         int index = 0;
605         gchar *factory_name = NULL;
606         const gchar *klass = NULL;
607         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
608         media_streamer_s *ms_streamer = (media_streamer_s *) data;
609
610         ms_debug_fenter();
611
612         ms_retvm_if(!factory, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "factory is NULL");
613         ms_retvm_if(!ms_streamer, GST_AUTOPLUG_SELECT_TRY, "data is NULL");
614
615         factory_name = GST_OBJECT_NAME(factory);
616         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
617
618         ms_debug("Decodebin: found new element [%s] to link [%s]", factory_name, klass);
619
620         if (ms_streamer->ini.exclude_elem_names) {
621                 /* Search if such plugin must be excluded */
622                 for (index = 0; ms_streamer->ini.exclude_elem_names[index]; ++index) {
623                         if (g_strrstr(factory_name, ms_streamer->ini.exclude_elem_names[index])) {
624                                 ms_debug("Decodebin: skipping [%s] as excluded", factory_name);
625                                 ms_debug_fleave();
626
627                                 return GST_AUTOPLUG_SELECT_SKIP;
628                         }
629                 }
630
631         }
632
633         if (ms_streamer->ini.resource_required_elem_names) {
634                 /* Try to acquire resources before adding element */
635                 for (index = 0; ms_streamer->ini.resource_required_elem_names[index]; ++index) {
636                         if (g_strrstr(factory_name, ms_streamer->ini.resource_required_elem_names[index])) {
637                                 ms_debug("Decodebin: trying to acquire resource for [%s] element", factory_name);
638
639                                 if (MM_RESOURCE_MANAGER_ERROR_NONE !=
640                                         mm_resource_manager_mark_for_acquire(ms_streamer->resource_manager,
641                                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
642                                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
643                                                         &ms_streamer->video_decoder_resource)) {
644                                         ms_error("Failed to mark resources for acquire in [%s] element", factory_name);
645                                         return GST_AUTOPLUG_SELECT_SKIP;
646                                 }
647
648                                 if (MM_RESOURCE_MANAGER_ERROR_NONE !=
649                                         mm_resource_manager_commit(ms_streamer->resource_manager)) {
650                                         ms_error("Failed to acquire resources for [%s] element", factory_name);
651
652                                         if (MM_RESOURCE_MANAGER_ERROR_NONE !=
653                                                         mm_resource_manager_mark_for_release(
654                                                         ms_streamer->resource_manager,
655                                                         ms_streamer->video_decoder_resource))
656                                                 ms_error("Failed to mark resources for release in [%s] element", factory_name);
657
658                                         return GST_AUTOPLUG_SELECT_SKIP;
659                                 }
660                         }
661                 }
662         }
663
664         ms_debug_fleave();
665
666         return result;
667 }
668
669 static gint __pad_type_compare(gconstpointer a, gconstpointer b)
670 {
671         GstPad *a_pad = NULL;
672         GstPad *b_pad = NULL;
673         const gchar *a_pad_type = NULL;
674         const gchar *b_pad_type = NULL;
675
676         ms_debug_fenter();
677
678         ms_retvm_if(!a, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "a is NULL");
679         ms_retvm_if(!b, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "b is NULL");
680
681         a_pad = GST_PAD(a);
682         b_pad = GST_PAD(b);
683
684         a_pad_type = ms_get_pad_type(a_pad);
685         b_pad_type = ms_get_pad_type(b_pad);
686
687         ms_debug_fleave();
688
689         if (MS_ELEMENT_IS_TEXT(a_pad_type))
690                 return -1;
691         else if (MS_ELEMENT_IS_TEXT(b_pad_type))
692                 return 1;
693         else
694                 return 0;
695 }
696
697 static void __decodebin_pad_added_cb(GstElement *element, GstPad *new_pad, gpointer user_data)
698 {
699         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
700
701         ms_debug_fenter();
702
703         ms_retm_if(new_pad == NULL, "new_pad is NULL");
704         ms_retm_if(ms_streamer == NULL, "user_data is NULL");
705
706         g_mutex_lock(&ms_streamer->mutex_lock);
707
708         g_object_ref(new_pad);
709
710         ms_streamer->pads_types_list = g_list_insert_sorted(ms_streamer->pads_types_list, new_pad, __pad_type_compare);
711
712         g_mutex_unlock(&ms_streamer->mutex_lock);
713
714         ms_debug_fleave();
715 }
716
717 static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer, media_streamer_sink_bin_type_e sink_bin_type)
718 {
719         GstElement *found_element = NULL;
720         const gchar *new_pad_type = NULL;
721         GstCaps *caps = NULL;
722         gchar *caps_str = NULL;
723
724         ms_debug_fenter();
725
726         ms_retm_if(src_pad == NULL, "src_pad is NULL");
727         ms_retm_if(ms_streamer == NULL, "ms_streamer is NULL");
728
729         found_element = gst_pad_get_parent_element(src_pad);
730         new_pad_type = ms_get_pad_type(src_pad);
731
732         if (MS_ELEMENT_IS_VIDEO(new_pad_type)) {
733                 if (__ms_bin_find_element_and_link_by_type(found_element, src_pad, ms_streamer->transform_bin,
734                                                         ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY))) {
735                         found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
736                         src_pad = NULL;
737                 }
738                 if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_RTP_SERVER) {
739                         found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
740                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
741                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
742                 } else if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_ADAPTIVE) {
743                         found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
744                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_MUXER);
745                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
746                 } else {
747                         caps = gst_pad_query_caps(src_pad, NULL);
748                         caps_str = gst_caps_to_string(caps);
749                         if (caps_str && (g_strrstr(caps_str, "ST12") || g_strrstr(caps_str, "SN12") ||
750                                 g_strrstr(caps_str, "SN21") || g_strrstr(caps_str, "S420") || g_strrstr(caps_str, "SR32"))) {
751                                 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
752                         } else {
753                                 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER);
754                                 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
755                         }
756                         MS_SAFE_GFREE(caps_str);
757                         gst_caps_unref(caps);
758                 }
759         } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
760                 if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_RTP_SERVER) {
761                         found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
762                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
763                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
764                 } else if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_ADAPTIVE) {
765                         found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
766                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_MUXER);
767                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
768                 } else {
769                         found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER);
770                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
771                 }
772         } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) {
773                 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
774         } else {
775                 ms_error("Unsupported pad type [%s]!", new_pad_type);
776         }
777
778         ms_generate_dots(ms_streamer->pipeline, "after_sink_linked");
779         gst_object_unref(found_element);
780
781         ms_debug_fleave();
782 }
783
784 static void __decodebin_nomore_pads_cb(GstElement *decodebin, gpointer user_data)
785 {
786         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
787         media_streamer_sink_bin_type_e sink_bin_type = MEDIA_STREAMER_SINK_BIN_NORMAL;
788         media_streamer_node_s *rtp_node = NULL;
789         media_streamer_node_s *adaptive_sink = NULL;
790         char *decodebin_name = NULL;
791         char *param_value = NULL;
792         GList *iterator = NULL;
793         GList *list = NULL;
794         GstPad *src_pad = NULL;
795
796         ms_debug_fenter();
797
798         ms_retm_if(decodebin == NULL, "decodebin is NULL");
799         ms_retm_if(ms_streamer == NULL, "user_data is NULL");
800
801         g_mutex_lock(&ms_streamer->mutex_lock);
802
803         rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
804         adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
805
806         if (rtp_node) {
807                 g_object_get(G_OBJECT(decodebin), "name", &decodebin_name, NULL);
808
809                 /* FIXME: This case may be not general */
810                 if (g_strrstr(decodebin_name, MEDIASTREAMER_DECODEBIN_TYPE_DECODER)) {
811                         sink_bin_type = MEDIA_STREAMER_SINK_BIN_NORMAL;
812                         MS_SAFE_FREE(decodebin_name);
813                 } else {
814                         /* It`s server part of Streaming Scenario*/
815                         media_streamer_node_get_param(rtp_node, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, &param_value);
816                         if (param_value && (strtol(param_value, NULL, 10) > 0))
817                                 sink_bin_type = MEDIA_STREAMER_SINK_BIN_RTP_SERVER;
818
819                         MS_SAFE_FREE(param_value);
820                 }
821         } else if (adaptive_sink) {
822                 __ms_adaptive_sink_prepare(ms_streamer);
823                 sink_bin_type = MEDIA_STREAMER_SINK_BIN_ADAPTIVE;
824         }
825
826         iterator = NULL;
827         list = ms_streamer->pads_types_list;
828         for (iterator = list; iterator; iterator = iterator->next) {
829                 src_pad = GST_PAD(iterator->data);
830                 __decodebin_nomore_pads_combine(src_pad, ms_streamer, sink_bin_type);
831         }
832
833         g_mutex_unlock(&ms_streamer->mutex_lock);
834
835         ms_debug_fleave();
836 }
837
838 static GstElement *__ms_decodebin_create(media_streamer_s *ms_streamer, char *name)
839 {
840         GstElement *decodebin = NULL;
841
842         ms_debug_fenter();
843
844         ms_retvm_if(!ms_streamer, NULL, "ms_streamer is NULL");
845
846         decodebin = ms_element_create(DEFAULT_DECODEBIN, name);
847         ms_bin_add_element(ms_streamer->transform_bin, decodebin, TRUE);
848         gst_element_sync_state_with_parent(decodebin);
849
850         ms_signal_create(&ms_streamer->autoplug_sig_list, decodebin, "pad-added", G_CALLBACK(__decodebin_pad_added_cb), ms_streamer);
851         ms_signal_create(&ms_streamer->autoplug_sig_list, decodebin, "autoplug-select", G_CALLBACK(__decodebin_autoplug_select_cb), ms_streamer);
852         ms_signal_create(&ms_streamer->autoplug_sig_list, decodebin, "no-more-pads", G_CALLBACK(__decodebin_nomore_pads_cb), ms_streamer);
853
854         ms_debug_fleave();
855
856         return decodebin;
857 }
858
859 //LCOV_EXCL_START
860 static gboolean __ms_sink_bin_prepare(media_streamer_s *ms_streamer, GstPad *src_pad, const gchar *src_pad_type)
861 {
862         GstElement *decoder_element = NULL;
863         GstElement *found_element = NULL;
864         GstElement *parent_rtp_element = NULL;
865
866         ms_debug_fenter();
867
868         ms_retvm_if(!ms_streamer, FALSE, "ms_streamer is NULL");
869         ms_retvm_if(!src_pad, FALSE, "src_pad is NULL");
870
871         /* Getting Depayloader */
872         parent_rtp_element = gst_pad_get_parent_element(src_pad);
873
874         if (MS_ELEMENT_IS_VIDEO(src_pad_type)) {
875                 gst_object_ref(parent_rtp_element);
876                 found_element = ms_combine_next_element(parent_rtp_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY);
877                 decoder_element = __ms_bin_find_element_and_link_by_type(found_element, NULL, ms_streamer->transform_bin,
878                                                                         ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER));
879
880                 if (!decoder_element) {
881                         if (ms_streamer->ini.use_decodebin) {
882                                 decoder_element = __ms_decodebin_create(ms_streamer, MEDIASTREAMER_DECODEBIN_TYPE_DECODER);
883                                 gst_object_ref(found_element);
884                                 __ms_link_two_elements(found_element, NULL, decoder_element);
885                                 MS_SAFE_UNREF(decoder_element);
886
887                                 ms_debug_fleave();
888
889                                 return TRUE;
890                         } else {
891                                 gst_object_ref(found_element);
892                                 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
893                                 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
894                         }
895                 } else {
896                         __ms_link_two_elements(found_element, NULL, decoder_element);
897                         found_element = ms_combine_next_element(decoder_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
898                 }
899         } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) {
900                 gst_object_ref(parent_rtp_element);
901                 found_element = ms_combine_next_element(parent_rtp_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY);
902                 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
903                 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
904         } else {
905                 ms_info("Unknown media type received from rtp element!");
906         }
907         MS_SAFE_UNREF(found_element);
908         MS_SAFE_UNREF(parent_rtp_element);
909
910         ms_debug_fleave();
911
912         return TRUE;
913 }
914
915 void ms_rtpbin_pad_added_cb(GstElement *src, GstPad *new_pad, gpointer user_data)
916 {
917         media_streamer_s *ms_streamer = NULL;
918         GstPad *target_pad = NULL;
919         GstCaps *src_pad_caps = NULL;
920         gchar *src_pad_name = NULL;
921         GstStructure *src_pad_struct = NULL;
922         const gchar *src_pad_type = NULL;
923         GstPad *src_pad = NULL;
924         media_streamer_node_s *ms_node = (media_streamer_node_s *) user_data;
925
926         ms_debug_fenter();
927
928         ms_retm_if(new_pad == NULL, "new_pad is NULL");
929         ms_retm_if(ms_node == NULL, "ms_node is NULL");
930         ms_debug("Pad [%s] added on [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(src));
931
932         if (g_str_has_prefix(GST_PAD_NAME(new_pad), "recv_rtp_src")) {
933                 ms_streamer = ms_node->parent_streamer;
934                 ms_retm_if(ms_streamer == NULL, "Node's parent streamer handle is NULL");
935                 g_mutex_lock(&ms_streamer->mutex_lock);
936
937                 target_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(new_pad));
938                 src_pad_caps = gst_pad_query_caps(target_pad, NULL);
939                 src_pad_struct = gst_caps_get_structure(src_pad_caps, 0);
940                 src_pad_type = gst_structure_get_string(src_pad_struct, "media");
941                 ms_debug("type is [%s]", src_pad_type);
942
943                 if (MS_ELEMENT_IS_VIDEO(src_pad_type))
944                         src_pad_name = g_strdup_printf("%s_out", "video");
945                 else if (MS_ELEMENT_IS_AUDIO(src_pad_type))
946                         src_pad_name = g_strdup_printf("%s_out", "audio");
947
948                 if (src_pad_name != NULL) {
949
950                         src_pad = gst_element_get_static_pad(ms_node->gst_element, src_pad_name);
951
952                         if (src_pad)
953                                 gst_ghost_pad_set_target(GST_GHOST_PAD(src_pad), new_pad);
954
955                         if (src_pad && __ms_sink_bin_prepare(ms_streamer, src_pad, src_pad_type)) {
956                                 ms_element_set_state(ms_node->gst_element, GST_STATE_PLAYING);
957                                 ms_generate_dots(ms_streamer->pipeline, "rtpbin_playing");
958                         } else {
959                                 ms_error("Failed to prepare sink_bin for pad type [%s]", src_pad_type);
960                         }
961
962                         MS_SAFE_GFREE(src_pad_name);
963                 }
964                 g_mutex_unlock(&ms_node->parent_streamer->mutex_lock);
965
966                 gst_caps_unref(src_pad_caps);
967                 MS_SAFE_UNREF(target_pad);
968         }
969
970         ms_debug_fleave();
971 }
972 //LCOV_EXCL_STOP
973
974 void ms_demux_pad_added_cb(GstElement *element, GstPad *new_pad, gpointer user_data)
975 {
976         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
977
978         ms_debug_fenter();
979
980         ms_retm_if(ms_streamer == NULL, "user_data is NULL");
981         ms_retm_if(new_pad == NULL, "new_pad is NULL");
982
983         g_mutex_lock(&ms_streamer->mutex_lock);
984
985         g_object_ref(new_pad);
986
987         ms_streamer->pads_types_list = g_list_insert_sorted(ms_streamer->pads_types_list, new_pad, __pad_type_compare);
988
989         g_mutex_unlock(&ms_streamer->mutex_lock);
990
991         ms_debug_fleave();
992 }
993
994 void ms_hlsdemux_pad_added_cb(GstElement *element, GstPad *new_pad, gpointer user_data)
995 {
996         GstPad *gp = NULL;
997
998         ms_debug_fenter();
999
1000         gp = GST_PAD(user_data);
1001         gst_ghost_pad_set_target(GST_GHOST_PAD(gp), new_pad);
1002
1003         ms_debug_fleave();
1004 }
1005
1006 static void __demux_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer)
1007 {
1008         GstElement *found_element = NULL;
1009         const gchar *new_pad_type = NULL;
1010
1011         ms_debug_fenter();
1012
1013         found_element = gst_pad_get_parent_element(src_pad);
1014         new_pad_type = ms_get_pad_type(src_pad);
1015
1016         if (MS_ELEMENT_IS_VIDEO(new_pad_type))
1017                 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1018         else if (MS_ELEMENT_IS_AUDIO(new_pad_type))
1019                 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1020         else if (MS_ELEMENT_IS_TEXT(new_pad_type))
1021                 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
1022         else
1023                 ms_error("Unsupported pad type [%s]!", new_pad_type);
1024
1025         ms_generate_dots(ms_streamer->pipeline, "after_demux_linked");
1026         gst_object_unref(found_element);
1027
1028         ms_debug_fleave();
1029 }
1030
1031 void ms_demux_nomore_pads_cb(GstElement *element, gpointer user_data)
1032 {
1033         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1034         GList *iterator = NULL;
1035         GList *list = NULL;
1036
1037         ms_debug_fenter();
1038
1039         ms_retm_if(ms_streamer == NULL, "Handle is NULL");
1040
1041         g_mutex_lock(&ms_streamer->mutex_lock);
1042
1043         list = ms_streamer->pads_types_list;
1044         for (iterator = list; iterator; iterator = iterator->next) {
1045                 GstPad *src_pad = GST_PAD(iterator->data);
1046                 __demux_nomore_pads_combine(src_pad, ms_streamer);
1047         }
1048
1049         g_mutex_unlock(&ms_streamer->mutex_lock);
1050
1051         ms_debug_fleave();
1052 }
1053
1054 int ms_element_set_state(GstElement *element, GstState state)
1055 {
1056         GstStateChangeReturn ret_state;
1057
1058         ms_debug_fenter();
1059
1060         ms_retvm_if(element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "element is NULL");
1061
1062         ret_state = gst_element_set_state(element, state);
1063
1064         if (ret_state == GST_STATE_CHANGE_FAILURE) {
1065                 ms_error("Failed to set element [%s] into %s state", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
1066                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1067         }
1068
1069         ms_debug_fleave();
1070
1071         return MEDIA_STREAMER_ERROR_NONE;
1072 }
1073
1074 GstElement *ms_element_create(const char *plugin_name, const char *name)
1075 {
1076         GstElement *plugin_elem = NULL;
1077
1078         ms_debug_fenter();
1079
1080         ms_retvm_if(plugin_name == NULL, (GstElement *) NULL, "Error empty plugin name");
1081
1082         ms_info("Creating [%s] element", plugin_name);
1083
1084         plugin_elem = gst_element_factory_make(plugin_name, name);
1085         ms_retvm_if(plugin_elem == NULL, (GstElement *) NULL, "Error creating element [%s]", plugin_name);
1086
1087         ms_debug_fleave();
1088
1089         return plugin_elem;
1090 }
1091
1092 static int __ms_adaptive_sink_prepare(media_streamer_s *ms_streamer)
1093 {
1094         static node_info_s nodes_info[] = {
1095                 {"Codec/Encoder/Video", "video_encoder"},          /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
1096                 {"Codec/Encoder/Audio", "audio_encoder"},          /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
1097                 {"Codec/Muxer", "mpegtsmux"},                          /* MEDIA_STREAMER_NODE_TYPE_MUXER */
1098         };
1099
1100         GstCaps *video_enc_src_caps = NULL;
1101         GstCaps *video_enc_sink_caps = NULL;
1102         GstCaps *audio_enc_src_caps = NULL;
1103         GstCaps *audio_enc_sink_caps = NULL;
1104         GstElement *audio_enc = NULL;
1105         GstElement *video_enc = NULL;
1106         GstCaps *muxer_src_caps = NULL;
1107         GstElement *muxer = NULL;
1108         node_plug_s video_enc_plug_info = {0, };
1109         node_plug_s audio_enc_plug_info = {0, };
1110         node_plug_s mux_plug_info = {0, };
1111
1112         ms_debug_fenter();
1113
1114         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1115
1116         video_enc_src_caps = gst_caps_new_simple("video/mpeg", "mpegversion", G_TYPE_INT, 4, NULL);
1117         video_enc_sink_caps = gst_caps_new_empty_simple("video/x-raw");
1118         video_enc_plug_info.info = &(nodes_info[0]);
1119         video_enc_plug_info.src_caps = video_enc_src_caps;
1120         video_enc_plug_info.sink_caps = video_enc_sink_caps;
1121         video_enc = ms_node_element_create(&video_enc_plug_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1122
1123         audio_enc_src_caps = gst_caps_new_simple("audio/mpeg", "mpegversion", G_TYPE_INT, 4, NULL);
1124         audio_enc_sink_caps = gst_caps_new_empty_simple("audio/x-raw");
1125         audio_enc_plug_info.info = &(nodes_info[1]);
1126         audio_enc_plug_info.src_caps = audio_enc_src_caps;
1127         audio_enc_plug_info.sink_caps = audio_enc_sink_caps;
1128         audio_enc = ms_node_element_create(&audio_enc_plug_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1129
1130         muxer_src_caps = gst_caps_new_empty_simple("video/mpegts");
1131         mux_plug_info.info = &(nodes_info[2]);
1132         mux_plug_info.src_caps = muxer_src_caps;
1133         muxer = ms_node_element_create(&mux_plug_info, MEDIA_STREAMER_NODE_TYPE_MUXER);
1134
1135         ms_bin_add_element(ms_streamer->transform_bin, muxer, FALSE);
1136         gst_element_sync_state_with_parent(muxer);
1137         ms_bin_add_element(ms_streamer->transform_bin, video_enc, FALSE);
1138         gst_element_sync_state_with_parent(video_enc);
1139         ms_bin_add_element(ms_streamer->transform_bin, audio_enc, FALSE);
1140         gst_element_sync_state_with_parent(audio_enc);
1141
1142         ms_debug_fleave();
1143
1144         return MEDIA_STREAMER_ERROR_NONE;
1145 }
1146
1147 GstElement *ms_adaptive_element_create(void)
1148 {
1149         GstElement *adaptive_bin = NULL;
1150
1151         ms_debug_fenter();
1152
1153         adaptive_bin = gst_bin_new("adaptive_src");
1154         ms_retvm_if(!adaptive_bin, (GstElement *) NULL, "Error: creating elements for adaptive source");
1155
1156         __ms_add_no_target_ghostpad(adaptive_bin, "src", GST_PAD_SRC);
1157
1158         /* Add adaptive node parameters as GObject data with destroy function */
1159         MS_SET_INT_STATIC_STRING_PARAM(adaptive_bin, MEDIA_STREAMER_PARAM_URI, "http://localhost");
1160
1161         ms_debug_fleave();
1162
1163         return adaptive_bin;
1164 }
1165
1166
1167 static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer data)
1168 {
1169         node_plug_s *plug_info = (node_plug_s*)data;
1170         gboolean can_accept = FALSE;
1171         gboolean src_can_accept = FALSE;
1172         gboolean sink_can_accept = FALSE;
1173         GstElementFactory *factory = NULL;
1174         const gchar *factory_klass = NULL;
1175
1176         if (!GST_IS_ELEMENT_FACTORY(feature))
1177                 return FALSE;
1178
1179         factory = GST_ELEMENT_FACTORY(feature);
1180         factory_klass = gst_element_factory_get_klass(factory);
1181
1182         if (plug_info && g_strrstr(factory_klass, plug_info->info->klass_name)) {
1183                 if (GST_IS_CAPS(plug_info->src_caps))
1184                         src_can_accept = gst_element_factory_can_src_any_caps(factory, plug_info->src_caps);
1185
1186                 if (GST_IS_CAPS(plug_info->sink_caps))
1187                         sink_can_accept = gst_element_factory_can_sink_any_caps(factory, plug_info->sink_caps);
1188
1189                 if (GST_IS_CAPS(plug_info->src_caps) && GST_IS_CAPS(plug_info->sink_caps)) {
1190                         if (src_can_accept && sink_can_accept)
1191                                 can_accept = TRUE;
1192                 } else if (src_can_accept || sink_can_accept)
1193                         can_accept = TRUE;
1194
1195                 if (can_accept) {
1196                         int index = 0;
1197                         for ( ; plug_info->exclude_names && plug_info->exclude_names[index]; ++index) {
1198                                 if (g_strrstr(GST_OBJECT_NAME(factory), plug_info->exclude_names[index])) {
1199                                         ms_debug("Skipping compatible factory [%s] as excluded.", GST_OBJECT_NAME(factory));
1200                                         return FALSE;
1201                                 }
1202                         }
1203
1204                         ms_info("[INFO] Found compatible factory [%s] for klass [%s]",
1205                                 GST_OBJECT_NAME(factory), factory_klass);
1206                         return TRUE;
1207                 }
1208
1209         }
1210
1211         return FALSE;
1212 }
1213
1214 static GstElement *ms_element_create_from_ini(node_plug_s *plug_info, media_streamer_node_type_e type)
1215 {
1216         const gchar *src_type, *sink_type;
1217         const gchar *format_type;
1218         GstElement *gst_element = NULL;
1219         gchar conf_key[INI_MAX_STRLEN] = {0,};
1220         gchar *plugin_name = NULL;
1221
1222         ms_debug_fenter();
1223
1224         ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1225
1226         MS_GET_CAPS_TYPE(plug_info->src_caps, src_type);
1227         MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type);
1228
1229         ms_info("Specified node formats types: in[%s] - out[%s]", sink_type, src_type);
1230
1231         if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER) {
1232                 format_type = src_type;
1233                 if (!format_type)
1234                         MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT), format_type);
1235         } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) {
1236                 format_type = src_type;
1237                 if (!format_type)
1238                         MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT), format_type);
1239         } else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER) {
1240                 format_type = sink_type;
1241                 if (!format_type)
1242                         MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT), format_type);
1243         } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER) {
1244                 format_type = sink_type;
1245                 if (!format_type)
1246                         MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT), format_type);
1247         } else
1248                 format_type = sink_type ? sink_type : src_type;
1249
1250         if (snprintf(conf_key, INI_MAX_STRLEN, "node type %d:%s", type, format_type) >= INI_MAX_STRLEN) {
1251                 ms_error("Failed to generate config field name, size >= %d", INI_MAX_STRLEN);
1252                 return NULL;
1253         }
1254
1255         plugin_name = ms_ini_get_string(conf_key, NULL);
1256
1257         if (plugin_name) {
1258                 gst_element = ms_element_create(plugin_name, NULL);
1259                 MS_SAFE_GFREE(plugin_name);
1260         }
1261
1262         ms_debug_fleave();
1263
1264         return gst_element;
1265 }
1266
1267 static GstElement *ms_element_create_by_registry(node_plug_s *plug_info, media_streamer_node_type_e type)
1268 {
1269         GstElement *gst_element = NULL;
1270         const gchar *src_type = NULL;
1271         const gchar *sink_type = NULL;
1272         GList *factories = NULL;
1273         GstElementFactory *factory = NULL;
1274
1275         ms_debug_fenter();
1276
1277         ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1278
1279         MS_GET_CAPS_TYPE(plug_info->src_caps, src_type);
1280         MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type);
1281
1282         ms_ini_read_list("general:exclude elements", &plug_info->exclude_names);
1283
1284         factories = gst_registry_feature_filter(gst_registry_get(),
1285                                 __ms_feature_node_filter, FALSE, plug_info);
1286         factories = g_list_sort(factories, (GCompareFunc) __ms_factory_rank_compare);
1287
1288         if (factories) {
1289                 factory = GST_ELEMENT_FACTORY(factories->data);
1290                 ms_info("Sorted result element is [%s]", GST_OBJECT_NAME(factory));
1291                 gst_element = ms_element_create(GST_OBJECT_NAME(factory), NULL);
1292         } else {
1293                 ms_debug("Could not find any compatible element for node [%d]: in[%s] - out[%s]",
1294                                 type, sink_type, src_type);
1295         }
1296
1297         g_strfreev(plug_info->exclude_names);
1298         gst_plugin_list_free(factories);
1299
1300         ms_debug_fleave();
1301
1302         return gst_element;
1303 }
1304
1305 static GstElement *__ms_video_encoder_element_create(node_plug_s *plug_info)
1306 {
1307         GstElement *video_scale = NULL;
1308         GstElement *video_convert = NULL;
1309         GstElement *encoder_elem = NULL;
1310         GstElement *encoder_parser = NULL;
1311         GstElement *encoder_bin = NULL;
1312         gboolean gst_ret = FALSE;
1313         const gchar *src_type = NULL;
1314         node_plug_s encoder_info = {0,};
1315         node_plug_s parser_info = {0,};
1316         node_info_s node_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER};
1317         media_format_mimetype_e encoder_type = MEDIA_FORMAT_MAX;
1318         GstCaps *enc_caps = NULL;
1319
1320         ms_debug_fenter();
1321
1322         ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1323
1324         enc_caps = plug_info->src_caps;
1325         if (!enc_caps) {
1326                 enc_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1327                 ms_debug("No Video encoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1328         }
1329
1330         /* Creating Scaler, Converter */
1331         video_scale = ms_element_create(DEFAULT_VIDEO_SCALE, NULL);
1332         video_convert = ms_element_create(DEFAULT_VIDEO_CONVERT, NULL);
1333
1334         /* Creating Video Encoder */
1335         encoder_info.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1336         encoder_info.src_caps = enc_caps;
1337         encoder_info.sink_caps = plug_info->sink_caps;
1338         encoder_info.exclude_names = NULL;
1339
1340         encoder_elem = ms_element_create_from_ini(&encoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1341         if (!encoder_elem)
1342                 encoder_elem = ms_element_create_by_registry(&encoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1343
1344         /* Creating bin - Video Encoder */
1345         encoder_bin = gst_bin_new("video_encoder");
1346
1347         if (!video_convert || !video_scale || !encoder_elem || !encoder_bin) {
1348                 goto ERROR;
1349         }
1350
1351         MS_GET_CAPS_TYPE(enc_caps, src_type);
1352         encoder_type = ms_convert_string_format_to_media_format(src_type);
1353
1354         if (encoder_type == MEDIA_FORMAT_VP8) {
1355                 /* VP8 does not have parser */
1356                 g_object_set(G_OBJECT(encoder_elem), "deadline", 1, NULL);
1357
1358                 /* Adding elements to bin Video Encoder */
1359                 gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, encoder_elem, NULL);
1360                 gst_ret = gst_element_link_many(video_convert, video_scale, encoder_elem, NULL);
1361                 if (gst_ret != TRUE) {
1362                         ms_error("Failed to link elements into encoder_bin");
1363                         MS_SAFE_UNREF(encoder_bin);
1364                         return NULL;
1365                 }
1366                 __ms_add_ghostpad(encoder_elem, "src", encoder_bin, "src");
1367         } else {
1368                 /* Creating Video Parser */
1369                 parser_info.info = &node_info;
1370                 parser_info.src_caps = enc_caps;
1371                 parser_info.sink_caps = enc_caps;
1372                 parser_info.exclude_names = NULL;
1373
1374                 encoder_parser = ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1375                 if (!encoder_parser)
1376                         encoder_parser = ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1377                 if (!encoder_parser)
1378                         goto ERROR;
1379
1380                 /* Settings if H264 format is set*/
1381                 if (encoder_type == MEDIA_FORMAT_H264_SP) {
1382                         g_object_set(GST_OBJECT(encoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL);
1383                         g_object_set(G_OBJECT(encoder_elem), "tune",  H264_ENCODER_ZEROLATENCY, NULL);
1384                         g_object_set(G_OBJECT(encoder_elem), "byte-stream", TRUE, NULL);
1385                         g_object_set(G_OBJECT(encoder_elem), "bitrate", 3000, NULL);
1386                         g_object_set(G_OBJECT(encoder_elem), "threads", 2, NULL);
1387                 }
1388
1389                 /* Adding elements to bin Video Encoder */
1390                 gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, encoder_elem, encoder_parser, NULL);
1391                 gst_ret = gst_element_link_many(video_convert, video_scale, encoder_elem, encoder_parser, NULL);
1392                 if (gst_ret != TRUE) {
1393                         ms_error("Failed to link elements into encoder_bin");
1394                         MS_SAFE_UNREF(encoder_bin);
1395                         return NULL;
1396                 }
1397                 __ms_add_ghostpad(encoder_parser, "src", encoder_bin, "src");
1398         }
1399         __ms_add_ghostpad(video_convert, "sink", encoder_bin, "sink");
1400
1401         ms_debug_fleave();
1402
1403         return encoder_bin;
1404
1405 ERROR:
1406         ms_error("Error: creating elements for video encoder bin");
1407         MS_SAFE_UNREF(video_convert);
1408         MS_SAFE_UNREF(video_scale);
1409         MS_SAFE_UNREF(encoder_elem);
1410         MS_SAFE_UNREF(encoder_parser);
1411         MS_SAFE_UNREF(encoder_bin);
1412
1413         ms_debug_fleave();
1414
1415         return NULL;
1416 }
1417
1418 static GstElement *__ms_video_decoder_element_create(node_plug_s *plug_info)
1419 {
1420         gboolean is_hw_codec = FALSE;
1421         GstElement *last_elem = NULL;
1422         GstElement *decoder_elem = NULL;
1423         GstElement *decoder_parser = NULL;
1424         GstElement *decoder_queue = NULL;
1425         GstElement *video_conv = NULL;
1426         GstElement *video_scale = NULL;
1427         GstElement *decoder_bin = NULL;
1428         node_plug_s decoder_info = {0,};
1429         node_plug_s parser_info = {0,};
1430         node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER};
1431         media_format_mimetype_e decoder_type = MEDIA_FORMAT_MAX;
1432         gboolean gst_ret = FALSE;
1433         const gchar *sink_type = NULL;
1434         GstCaps *dec_caps = NULL;
1435         gchar *codec_name = NULL;
1436
1437         ms_debug_fenter();
1438
1439         ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1440
1441         dec_caps = plug_info->sink_caps;
1442         if (!dec_caps) {
1443                 dec_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1444                 ms_debug("No Video decoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1445         }
1446
1447         /* Creating Video Decoder */
1448         decoder_info.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1449         decoder_info.src_caps = plug_info->src_caps;
1450         decoder_info.sink_caps = dec_caps;
1451         decoder_info.exclude_names = NULL;
1452
1453         decoder_elem = ms_element_create_from_ini(&decoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1454         if (!decoder_elem)
1455                 decoder_elem = ms_element_create_by_registry(&decoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1456
1457         /* Creating Video Parser */
1458         parser_info.info = &nodes_info;
1459         parser_info.src_caps = dec_caps;
1460         parser_info.sink_caps = dec_caps;
1461         parser_info.exclude_names = NULL;
1462
1463         decoder_parser = ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1464         if (!decoder_parser)
1465                 decoder_parser = ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1466
1467         /* Settings if H264 format is set*/
1468         MS_GET_CAPS_TYPE(dec_caps, sink_type);
1469         decoder_type = ms_convert_string_format_to_media_format(sink_type);
1470         if (decoder_type == MEDIA_FORMAT_H264_SP)
1471                 g_object_set(G_OBJECT(decoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL);
1472
1473         /* Creating bin - Video Decoder */
1474         decoder_queue = ms_element_create("queue", NULL);
1475         decoder_bin = gst_bin_new("video_decoder");
1476
1477         if (!decoder_elem || !decoder_queue || !decoder_parser || !decoder_bin) {
1478                 ms_error("Error: creating elements for video decoder bin");
1479                 goto ERROR;
1480         }
1481
1482         codec_name = GST_OBJECT_NAME(decoder_elem);
1483         if (g_strrstr(codec_name, "omx") || g_strrstr(codec_name, "sprd"))
1484                 is_hw_codec = TRUE;
1485
1486         /* Adding elements to bin Audio Encoder */
1487         gst_bin_add_many(GST_BIN(decoder_bin), decoder_queue, decoder_elem, decoder_parser, NULL);
1488         gst_ret = gst_element_link_many(decoder_queue, decoder_parser, decoder_elem, NULL);
1489         if (gst_ret != TRUE) {
1490                 ms_error("Failed to link elements into decoder_bin");
1491                 MS_SAFE_UNREF(decoder_bin);
1492                 return NULL;
1493         }
1494
1495         last_elem = decoder_elem;
1496
1497         if (!is_hw_codec) {
1498                 video_conv = ms_element_create("videoconvert", NULL);
1499                 video_scale = ms_element_create("videoscale", NULL);
1500                 if (!video_conv || !video_scale) {
1501                         ms_error("Error: creating elements for video decoder bin");
1502                         goto ERROR;
1503                 }
1504
1505                 gst_bin_add_many(GST_BIN(decoder_bin), video_conv, video_scale, NULL);
1506                 gst_ret = gst_element_link_many(decoder_elem, video_conv, video_scale, NULL);
1507                 if (gst_ret != TRUE) {
1508                         ms_error("Failed to link elements into decoder_bin");
1509                         MS_SAFE_UNREF(decoder_bin);
1510                         return NULL;
1511                 }
1512                 last_elem = video_scale;
1513         }
1514
1515         __ms_add_ghostpad(last_elem, "src", decoder_bin, "src");
1516         __ms_add_ghostpad(decoder_queue, "sink", decoder_bin, "sink");
1517
1518         ms_debug_fleave();
1519
1520         return decoder_bin;
1521
1522 ERROR:
1523
1524         MS_SAFE_UNREF(decoder_elem);
1525         MS_SAFE_UNREF(decoder_queue);
1526         MS_SAFE_UNREF(decoder_parser);
1527         MS_SAFE_UNREF(video_conv);
1528         MS_SAFE_UNREF(video_scale);
1529         MS_SAFE_UNREF(decoder_bin);
1530
1531         ms_debug_fleave();
1532
1533         return NULL;
1534 }
1535
1536 static GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info)
1537 {
1538         gboolean gst_ret = FALSE;
1539         GstElement *audio_convert = NULL;
1540         GstElement *audio_resample = NULL;
1541         GstElement *audio_filter = NULL;
1542         GstElement *audio_postenc_convert = NULL;
1543         GstElement *audio_encoder = NULL;
1544         GstElement *audio_enc_bin = NULL;
1545         node_plug_s plug_info_encoder = {0,};
1546         gchar *encoder_name = NULL;
1547         GstCaps *audioCaps = NULL;
1548         GstCaps *enc_caps = NULL;
1549
1550         ms_debug_fenter();
1551
1552         ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1553
1554         enc_caps = plug_info->src_caps;
1555         if (!enc_caps) {
1556                 enc_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1557                 ms_debug("No Audio encoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1558         }
1559
1560         /* Creating Converter, Resampler, Filter */
1561         audio_convert = ms_element_create(DEFAULT_AUDIO_CONVERT, NULL);
1562         audio_resample = ms_element_create(DEFAULT_AUDIO_RESAMPLE, NULL);
1563         audio_filter = ms_element_create(DEFAULT_FILTER, NULL);
1564         audio_postenc_convert = ms_element_create(DEFAULT_AUDIO_CONVERT, NULL);
1565
1566         /* Creating Audio Encoder */
1567         plug_info_encoder.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1568         plug_info_encoder.src_caps = enc_caps;
1569         plug_info_encoder.sink_caps = plug_info->sink_caps;
1570         plug_info_encoder.exclude_names = NULL;
1571
1572         audio_encoder = ms_element_create_from_ini(&plug_info_encoder, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1573         if (!audio_encoder)
1574                 audio_encoder = ms_element_create_by_registry(&plug_info_encoder, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1575
1576         encoder_name = gst_element_get_name(audio_encoder);
1577         if (encoder_name && g_strrstr(encoder_name, "aac"))
1578                 g_object_set(audio_encoder, "compliance", -2, NULL);
1579         MS_SAFE_GFREE(encoder_name);
1580
1581         /* Creating bin - Audio Encoder */
1582         audio_enc_bin = gst_bin_new("audio_encoder");
1583         if (!audio_convert || !audio_postenc_convert || !audio_filter || !audio_resample || !audio_encoder || !audio_enc_bin) {
1584                 ms_error("Error: creating elements for audio encoder bin");
1585                 goto ERROR;
1586         }
1587
1588         audioCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RAW_FORMAT);
1589         g_object_set(G_OBJECT(audio_filter), "caps", audioCaps, NULL);
1590         gst_caps_unref(audioCaps);
1591
1592         /* Adding elements to bin Audio Encoder */
1593         gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_postenc_convert, audio_filter, audio_resample, audio_encoder, NULL);
1594         gst_ret = gst_element_link_many(audio_convert, audio_resample, audio_filter, audio_postenc_convert, audio_encoder, NULL);
1595         if (gst_ret != TRUE) {
1596                 ms_error("Failed to link elements into decoder_bin");
1597                 MS_SAFE_UNREF(audio_enc_bin);
1598         }
1599
1600         __ms_add_ghostpad(audio_encoder, "src", audio_enc_bin, "src");
1601         __ms_add_ghostpad(audio_convert, "sink", audio_enc_bin, "sink");
1602
1603         ms_debug_fleave();
1604
1605         return audio_enc_bin;
1606
1607 ERROR:
1608
1609         MS_SAFE_UNREF(audio_convert);
1610         MS_SAFE_UNREF(audio_resample);
1611         MS_SAFE_UNREF(audio_postenc_convert);
1612         MS_SAFE_UNREF(audio_filter);
1613         MS_SAFE_UNREF(audio_encoder);
1614         MS_SAFE_UNREF(audio_enc_bin);
1615
1616         ms_debug_fleave();
1617
1618         return NULL;
1619
1620 }
1621
1622 static GstElement *__ms_audio_decoder_element_create(node_plug_s *plug_info)
1623 {
1624         gboolean gst_ret = FALSE;
1625         GstElement *decoder_bin = NULL;
1626         GstElement *decoder_elem = NULL;
1627         GstElement *decoder_parser = NULL;
1628         GstElement *decoder_queue = NULL;
1629         GstElement *audio_conv = NULL;
1630         GstElement *audio_resample = NULL;
1631         node_plug_s decoder_info = {0,};
1632         node_plug_s parser_info = {0,};
1633         node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_AUDIO_PARSER};
1634         GstCaps *dec_caps = NULL;
1635
1636         ms_debug_fenter();
1637
1638         dec_caps = plug_info->sink_caps;
1639         if (!dec_caps) {
1640                 dec_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1641                 ms_debug("No Audio decoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1642         }
1643
1644         /* Creating Audio Decoder */
1645         decoder_info.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1646         decoder_info.src_caps = plug_info->src_caps;
1647         decoder_info.sink_caps = dec_caps;
1648         decoder_info.exclude_names = NULL;
1649
1650         decoder_elem = ms_element_create_from_ini(&decoder_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1651         if (!decoder_elem)
1652                 decoder_elem = ms_element_create_by_registry(&decoder_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1653
1654         /* Creating Audio Parser */
1655         parser_info.info = &nodes_info;
1656         parser_info.src_caps = dec_caps;
1657         parser_info.sink_caps = dec_caps;
1658         parser_info.exclude_names = NULL;
1659
1660         decoder_parser = ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1661         if (!decoder_parser)
1662                 decoder_parser = ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1663
1664         /* Creating bin - Audio Decoder */
1665         decoder_bin = gst_bin_new("audio_decoder");
1666         decoder_queue = ms_element_create("queue", NULL);
1667         if (!decoder_elem || !decoder_queue || !decoder_parser || !decoder_bin) {
1668                 ms_error("Error: creating elements for audio decoder bin");
1669                 goto ERROR;
1670         }
1671
1672         /* Adding elements to bin Audio Encoder */
1673         gst_bin_add_many(GST_BIN(decoder_bin), decoder_queue, decoder_elem, decoder_parser, NULL);
1674         gst_ret = gst_element_link_many(decoder_queue, decoder_parser, decoder_elem, NULL);
1675         if (gst_ret != TRUE) {
1676                 ms_error("Failed to link elements into decoder_bin");
1677                 MS_SAFE_UNREF(decoder_bin);
1678                 return NULL;
1679         }
1680
1681         audio_conv = ms_element_create("audioconvert", NULL);
1682         audio_resample = ms_element_create("audioresample", NULL);
1683         if (!audio_conv || !audio_resample) {
1684                 ms_error("Error: creating elements for audio decoder bin");
1685                 goto ERROR;
1686         }
1687
1688         gst_bin_add_many(GST_BIN(decoder_bin), audio_conv, audio_resample, NULL);
1689         gst_ret = gst_element_link_many(decoder_elem, audio_conv, audio_resample, NULL);
1690         if (gst_ret != TRUE) {
1691                 ms_error("Failed to link elements into decoder_bin");
1692                 MS_SAFE_UNREF(decoder_bin);
1693                 return NULL;
1694         }
1695
1696         __ms_add_ghostpad(audio_resample, "src", decoder_bin, "src");
1697         __ms_add_ghostpad(decoder_queue, "sink", decoder_bin, "sink");
1698
1699         ms_debug_fleave();
1700
1701         return decoder_bin;
1702
1703 ERROR:
1704
1705         MS_SAFE_UNREF(decoder_elem);
1706         MS_SAFE_UNREF(decoder_queue);
1707         MS_SAFE_UNREF(decoder_parser);
1708         MS_SAFE_UNREF(audio_conv);
1709         MS_SAFE_UNREF(audio_resample);
1710         MS_SAFE_UNREF(decoder_bin);
1711
1712         ms_debug_fleave();
1713
1714         return NULL;
1715 }
1716
1717 GstElement *ms_node_element_create(node_plug_s *plug_info, media_streamer_node_type_e type)
1718 {
1719         GstElement *gst_element = NULL;
1720         const gchar *src_type = NULL;
1721         const gchar *sink_type = NULL;
1722
1723         ms_debug_fenter();
1724
1725         ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1726
1727         MS_GET_CAPS_TYPE(plug_info->src_caps, src_type);
1728         MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type);
1729
1730         /* 1. Main priority:
1731          * If Node klass defined as MEDIA_STREAMER_STRICT or ENCODER/DECODER or CONVERTER types,
1732          * element will be created immediately by format or name */
1733         if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER)
1734                 gst_element = __ms_audio_encoder_element_create(plug_info);
1735         else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER)
1736                 gst_element = __ms_audio_decoder_element_create(plug_info);
1737         else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER)
1738                 gst_element = __ms_video_encoder_element_create(plug_info);
1739         else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER)
1740                 gst_element = __ms_video_decoder_element_create(plug_info);
1741         else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER || type == MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER)
1742                 gst_element = ms_element_create(plug_info->info->default_name, NULL);
1743         else if (g_strrstr(MEDIA_STREAMER_STRICT, plug_info->info->klass_name) || (!src_type && !sink_type)) {
1744                 if (type == MEDIA_STREAMER_NODE_TYPE_RTP)
1745                         gst_element = ms_rtp_element_create();
1746                 else
1747                         gst_element = ms_element_create(plug_info->info->default_name, NULL);
1748         } else {
1749
1750                 /* 2. Second priority:
1751                  * Try to get plugin name that defined in ini file
1752                  * according with node type and specified format. */
1753                 gst_element = ms_element_create_from_ini(plug_info, type);
1754         }
1755
1756         /* 3. Third priority:
1757          * If previous cases did not create a valid gst_element,
1758          * try to find compatible plugin in gstreamer registry.
1759          * Elements that are compatible but defined as excluded will be skipped*/
1760         if (!gst_element) {
1761                 /* Read exclude elements list */
1762                 gst_element = ms_element_create_by_registry(plug_info, type);
1763         }
1764
1765         if (type == MEDIA_STREAMER_NODE_TYPE_FILTER) {
1766                 if (plug_info->src_caps)
1767                         g_object_set(G_OBJECT(gst_element), "caps", plug_info->src_caps, NULL);
1768         }
1769
1770         ms_debug_fleave();
1771
1772         return gst_element;
1773 }
1774
1775 GstElement *ms_rtp_element_create(void)
1776 {
1777         GstElement *rtp_container = NULL;
1778
1779         ms_debug_fenter();
1780
1781         rtp_container = gst_bin_new("rtp_container");
1782         ms_retvm_if(!rtp_container, (GstElement *) NULL, "Error: creating elements for rtp container");
1783
1784         __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_VIDEO_OUT, GST_PAD_SRC);
1785         __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_AUDIO_OUT, GST_PAD_SRC);
1786         __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_VIDEO_IN, GST_PAD_SINK);
1787         __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_AUDIO_IN, GST_PAD_SINK);
1788
1789         __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_VIDEO_IN"_rtp", GST_PAD_SINK);
1790         __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_AUDIO_IN"_rtp", GST_PAD_SINK);
1791
1792         /* Add RTP node parameters as GObject data with destroy function */
1793         MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT, RTP_STREAM_DISABLED);
1794         MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT, RTP_STREAM_DISABLED);
1795         MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, RTP_STREAM_DISABLED);
1796         MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT, RTP_STREAM_DISABLED);
1797         MS_SET_INT_STATIC_STRING_PARAM(rtp_container, MEDIA_STREAMER_PARAM_HOST, "localhost");
1798         MS_SET_INT_CAPS_PARAM(rtp_container, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT, gst_caps_new_any());
1799         MS_SET_INT_CAPS_PARAM(rtp_container, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT, gst_caps_new_any());
1800
1801         ms_debug_fleave();
1802
1803         return rtp_container;
1804 }
1805
1806 //LCOV_EXCL_START
1807 static gboolean __ms_parse_gst_error(media_streamer_s *ms_streamer, GstMessage *message, GError *error)
1808 {
1809         media_streamer_error_e ret_error = MEDIA_STREAMER_ERROR_NONE;
1810
1811         ms_debug_fenter();
1812
1813         ms_retvm_if(!ms_streamer, FALSE, "Error: invalid Media Streamer handle.");
1814         ms_retvm_if(!message, FALSE, "Error: invalid bus message handle.");
1815         ms_retvm_if(!error, FALSE, "Error: invalid error handle.");
1816
1817         if (error->domain == GST_CORE_ERROR)
1818                 ret_error = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1819         else if (error->domain == GST_LIBRARY_ERROR)
1820                 ret_error = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1821         else if (error->domain == GST_RESOURCE_ERROR)
1822                 ret_error = MEDIA_STREAMER_ERROR_RESOURCE_CONFLICT;
1823         else if (error->domain == GST_STREAM_ERROR)
1824                 ret_error = MEDIA_STREAMER_ERROR_CONNECTION_FAILED;
1825         else
1826                 ret_error = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1827
1828         /* post error to application */
1829         if (ms_streamer->error_cb.callback) {
1830                 media_streamer_error_cb error_cb = (media_streamer_error_cb) ms_streamer->error_cb.callback;
1831                 error_cb((media_streamer_h) ms_streamer, ret_error, ms_streamer->error_cb.user_data);
1832         }
1833
1834         ms_debug_fleave();
1835
1836         return TRUE;
1837 }
1838 //LCOV_EXCL_STOP
1839
1840 static GstPadProbeReturn __ms_element_event_probe(GstPad * pad, GstPadProbeInfo *info, gpointer user_data)
1841 {
1842         GstElement *parent_element = NULL;
1843         GstEvent *event = NULL;
1844
1845         parent_element = gst_pad_get_parent_element(pad);
1846         if (!parent_element) {
1847                 ms_error("filed to get parent_elem");
1848                 return GST_PAD_PROBE_PASS;
1849         }
1850
1851         event = GST_PAD_PROBE_INFO_EVENT(info);
1852
1853         if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM) {
1854                 if (GST_EVENT_TYPE(event) == GST_EVENT_BUFFERSIZE) {
1855                         GValue *val_ = (GValue *) g_object_get_data(G_OBJECT(parent_element), "pad_sink");
1856                         ms_info("Set locking probe [%d] on [%s] pad of [%s] element", g_value_get_int(val_), GST_PAD_NAME(pad), GST_ELEMENT_NAME(parent_element));
1857                         MS_SAFE_UNREF(parent_element);
1858                         return GST_PAD_PROBE_OK;
1859                 }
1860         }
1861
1862         MS_SAFE_UNREF(parent_element);
1863
1864         return GST_PAD_PROBE_PASS;
1865 }
1866
1867 gboolean ms_element_lock_state(const GValue *item, GValue *ret, gpointer user_data)
1868 {
1869         GstElement *sink_element = NULL;
1870         GstPad *sink_pad = NULL;
1871         int probe_id = 0;
1872
1873         ms_debug_fenter();
1874
1875         sink_element = GST_ELEMENT(g_value_get_object(item));
1876         ms_retvm_if(!sink_element, FALSE, "Handle is NULL");
1877
1878         g_value_set_boolean(ret, FALSE);
1879
1880         sink_pad = gst_element_get_static_pad(sink_element, "sink");
1881         if (!sink_pad) {
1882                 ms_info("Failed to get static pad of element [%s]", GST_ELEMENT_NAME(sink_element));
1883                 return FALSE;
1884         }
1885         if (!gst_pad_is_blocked(sink_pad)) {
1886                 probe_id = gst_pad_add_probe(sink_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, __ms_element_event_probe, NULL, NULL);
1887                 MS_SET_INT_PARAM(sink_element, "pad_sink", probe_id);
1888                 ms_info("Added locking probe [%d] on pad [%s] of element [%s]", probe_id, GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1889         } else {
1890                 ms_info("Pad [%s] of element [%s] is already locked", GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1891         }
1892         MS_SAFE_UNREF(sink_pad);
1893
1894         g_value_set_boolean(ret, TRUE);
1895
1896         ms_debug_fleave();
1897
1898         return TRUE;
1899 }
1900
1901 gboolean ms_element_unlock_state(const GValue *item, GValue *ret, gpointer user_data)
1902 {
1903         GstElement *sink_element = NULL;
1904         GValue *val = NULL;
1905         GstPad *sink_pad = NULL;
1906
1907         ms_debug_fenter();
1908
1909         g_value_set_boolean(ret, FALSE);
1910         sink_element = GST_ELEMENT(g_value_get_object(item));
1911         ms_retvm_if(!sink_element, FALSE, "Handle is NULL");
1912
1913         val = (GValue *) g_object_get_data(G_OBJECT(sink_element), "pad_sink");
1914         if (val) {
1915                 sink_pad = gst_element_get_static_pad(sink_element, "sink");
1916                 if (!sink_pad) {
1917                         ms_info("Failed to get static pad of element [%s]", GST_ELEMENT_NAME(sink_element));
1918                         return FALSE;
1919                 }
1920                 if (gst_pad_is_blocked(sink_pad)) {
1921                         ms_info("Removing locking probe [%d] ID on [%s] pad of [%s] element", g_value_get_int(val), GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1922                         gst_pad_remove_probe(sink_pad, g_value_get_int(val));
1923                 } else {
1924                         ms_info("No locking Probe on pad [%s] of element [%s]", GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1925                 }
1926                 MS_SAFE_UNREF(sink_pad);
1927         }
1928
1929         g_value_set_boolean(ret, TRUE);
1930
1931         ms_debug_fleave();
1932
1933         return TRUE;
1934 }
1935
1936 static gboolean __ms_bus_cb(GstBus *bus, GstMessage *message, gpointer userdata)
1937 {
1938         int ret = MEDIA_STREAMER_ERROR_NONE;
1939         media_streamer_s *ms_streamer = NULL;
1940         GError *err = NULL;
1941         gchar *debug = NULL;
1942         gchar *state_transition_name = NULL;
1943         GstState state_old = 0, state_new = 0, state_pending = 0;
1944
1945         ms_streamer = (media_streamer_s *) userdata;
1946         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
1947         ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_STATE, "Pipeline doesn`t exist");
1948
1949         /* Parse message */
1950         if (message != NULL) {
1951                 switch (GST_MESSAGE_TYPE(message)) {
1952                 case GST_MESSAGE_ERROR:{
1953                                 gst_message_parse_error(message, &err, &debug);
1954
1955                                 /* Transform gst error code to media streamer error code.
1956                                  * then post it to application if needed */
1957                                 __ms_parse_gst_error(ms_streamer, message, err);
1958
1959                                 ms_error("[Source: %s] Error: %s", GST_OBJECT_NAME(GST_OBJECT_CAST(GST_ELEMENT(GST_MESSAGE_SRC(message)))), err->message);
1960
1961                                 g_error_free(err);
1962                                 MS_SAFE_GFREE(debug);
1963                                 break;
1964                         }
1965
1966                 case GST_MESSAGE_STATE_CHANGED:{
1967                                 if (GST_MESSAGE_SRC(message) == GST_OBJECT(ms_streamer->pipeline)) {
1968                                         gst_message_parse_state_changed(message, &state_old, &state_new, &state_pending);
1969                                         state_transition_name = g_strdup_printf("Old_[%s]_New_[%s]_Pending_[%s]", gst_element_state_get_name(state_old),
1970                                                                                         gst_element_state_get_name(state_new), gst_element_state_get_name(state_pending));
1971                                         ms_info("GST_MESSAGE_STATE_CHANGED: [%s] %s. ", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), state_transition_name);
1972                                         ms_generate_dots(ms_streamer->pipeline, state_transition_name);
1973                                         MS_SAFE_GFREE(state_transition_name);
1974
1975                                         media_streamer_state_e old_state = ms_streamer->state;
1976                                         if (state_new >= GST_STATE_PAUSED) {
1977                                                 if ((old_state == MEDIA_STREAMER_STATE_PLAYING) && (state_new <= GST_STATE_PAUSED))
1978                                                         ms_streamer->pend_state = MEDIA_STREAMER_STATE_PAUSED;
1979
1980                                                 if (ms_streamer->pend_state != ms_streamer->state) {
1981
1982                                                         g_mutex_lock(&ms_streamer->mutex_lock);
1983                                                         ms_streamer->state = ms_streamer->pend_state;
1984                                                         g_mutex_unlock(&ms_streamer->mutex_lock);
1985
1986                                                         ms_info("Media streamer state changed to [%d] [%d]", old_state, ms_streamer->state);
1987                                                         if (ms_streamer->state_changed_cb.callback) {
1988                                                                 media_streamer_state_changed_cb cb = (media_streamer_state_changed_cb) ms_streamer->state_changed_cb.callback;
1989                                                                 cb((media_streamer_h) ms_streamer, old_state, ms_streamer->state, ms_streamer->state_changed_cb.user_data);
1990                                                         }
1991                                                 }
1992                                         }
1993                                 }
1994                                 break;
1995                         }
1996
1997                 case GST_MESSAGE_ASYNC_DONE:{
1998                                 ms_debug("GST_MESSAGE_ASYNC_DONE");
1999                                 if (GST_MESSAGE_SRC(message) == GST_OBJECT(ms_streamer->pipeline)
2000                                         && ms_streamer->is_seeking) {
2001
2002                                         g_mutex_lock(&ms_streamer->mutex_lock);
2003                                         ms_streamer->pend_state = MEDIA_STREAMER_STATE_SEEKING;
2004                                         g_mutex_unlock(&ms_streamer->mutex_lock);
2005
2006                                         if (ms_streamer->seek_done_cb.callback) {
2007                                                 media_streamer_position_changed_cb cb = (media_streamer_position_changed_cb) ms_streamer->seek_done_cb.callback;
2008                                                 cb(ms_streamer->seek_done_cb.user_data);
2009                                         }
2010
2011                                         g_mutex_lock(&ms_streamer->mutex_lock);
2012                                         ms_streamer->is_seeking = FALSE;
2013                                         ms_streamer->pend_state = MEDIA_STREAMER_STATE_PLAYING;
2014                                         ms_streamer->seek_done_cb.callback = NULL;
2015                                         ms_streamer->seek_done_cb.user_data = NULL;
2016                                         g_mutex_unlock(&ms_streamer->mutex_lock);
2017                                 }
2018                                 break;
2019                         }
2020                 case GST_MESSAGE_EOS:{
2021                                 ms_info("GST_MESSAGE_EOS end-of-stream");
2022                                 ret = ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
2023                                 if (ret != MEDIA_STREAMER_ERROR_NONE) {
2024                                         ms_error("ERROR - Pause Pipeline");
2025                                         return FALSE;
2026                                 }
2027                                 break;
2028                         }
2029                 default:
2030                         break;
2031                 }
2032         }
2033
2034         return TRUE;
2035 }
2036
2037 static int __ms_gstreamer_init(media_streamer_s *ms_streamer)
2038 {
2039         int ret = MEDIA_STREAMER_ERROR_NONE;
2040         int *argc = NULL;
2041         char **argv = NULL;
2042         GError *err = NULL;
2043         gboolean gst_ret = 0;
2044         int i = 0;
2045
2046         ms_debug_fenter();
2047
2048         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2049
2050         argc = (int *)malloc(sizeof(int));
2051         if (!argc) {
2052                 ms_error("Error allocation memory");
2053                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2054         }
2055
2056         /* get argc(number of command line option), argc is always one without option */
2057         *argc = 1;
2058         if (ms_streamer->ini.gst_args)
2059                 (*argc) += g_strv_length(ms_streamer->ini.gst_args); /* default is "--gst-debug = 2 */
2060
2061         argv = (char **)calloc(*argc, sizeof(char*));
2062         if (!argv) {
2063                 MS_SAFE_FREE(argc);
2064                 ms_error("Error allocation memory");
2065                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2066         }
2067
2068         argv[0] = g_strdup("MediaStreamer");
2069
2070         if (ms_streamer->ini.gst_args) {
2071                 for ( ; ms_streamer->ini.gst_args[i]; ++i) {
2072                         if (*argc <= i+1) {
2073                                 ms_error("need to check, prevent overrun");
2074                                 break;
2075                         }
2076                         argv[i+1] = ms_streamer->ini.gst_args[i];
2077                         ms_debug("Add [%s] gstreamer parameter.", argv[i+1]);
2078                 }
2079         }
2080
2081         gst_ret = gst_init_check(argc, &argv, &err);
2082
2083         /* Clean memory of gstreamer arguments*/
2084         g_strfreev(ms_streamer->ini.gst_args);
2085         ms_streamer->ini.gst_args = NULL;
2086
2087         for (i = 1; i < *argc; i++)
2088                 argv[i] = NULL;
2089
2090         MS_SAFE_FREE(argv[0]);
2091         MS_SAFE_FREE(argv);
2092         MS_SAFE_FREE(argc);
2093
2094         if (!gst_ret) {
2095                 ms_error("Error: Failed to initialize GStreamer [%s].", err->message);
2096                 g_clear_error(&err);
2097                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2098         }
2099
2100         ms_debug_fleave();
2101
2102         return ret;
2103 }
2104
2105 int ms_pipeline_create(media_streamer_s *ms_streamer)
2106 {
2107         int ret = MEDIA_STREAMER_ERROR_NONE;
2108
2109         ms_debug_fenter();
2110
2111         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2112
2113         /* initialize gstreamer with configured parameter */
2114         ret = __ms_gstreamer_init(ms_streamer);
2115         if (ret != MEDIA_STREAMER_ERROR_NONE)
2116                 return ret;
2117
2118         ms_streamer->pipeline = gst_pipeline_new(MEDIA_STREAMER_PIPELINE_NAME);
2119         ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating pipeline");
2120
2121         ms_streamer->bus = gst_pipeline_get_bus(GST_PIPELINE(ms_streamer->pipeline));
2122         ms_retvm_if(ms_streamer->bus == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error getting the bus of the pipeline");
2123
2124         ms_streamer->bus_watcher = gst_bus_add_watch(ms_streamer->bus, (GstBusFunc) __ms_bus_cb, ms_streamer);
2125
2126         ms_streamer->src_bin = gst_bin_new(MEDIA_STREAMER_SRC_BIN_NAME);
2127         ms_retvm_if(ms_streamer->src_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating Src bin");
2128
2129         ms_streamer->sink_bin = gst_bin_new(MEDIA_STREAMER_SINK_BIN_NAME);
2130         ms_retvm_if(ms_streamer->sink_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating Sink bin");
2131
2132         ms_streamer->transform_bin = gst_bin_new(MEDIA_STREAMER_TRANSFORM_BIN_NAME);
2133         ms_retvm_if(ms_streamer->transform_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating Transform bin");
2134
2135         gst_bin_add_many(GST_BIN(ms_streamer->pipeline), ms_streamer->src_bin, ms_streamer->sink_bin, ms_streamer->transform_bin, NULL);
2136         ms_info("Media streamer pipeline created successfully.");
2137
2138         ms_debug_fleave();
2139
2140         return ret;
2141 }
2142
2143 static gboolean __find_node(gpointer key, gpointer value, gpointer user_data)
2144 {
2145         gchar *node_name = (gchar *)user_data;
2146
2147         return g_strrstr((char *)key, node_name) != NULL;
2148 }
2149
2150 static void __ms_pending_pads_remove(void *data)
2151 {
2152         GstPad *pad = NULL;
2153
2154         ms_debug_fenter();
2155
2156         ms_retm_if(data == NULL, "data is NULL");
2157
2158         pad = GST_PAD(data);
2159         MS_SAFE_UNREF(pad);
2160
2161         ms_debug_fleave();
2162 }
2163
2164 static gboolean __ms_bin_unprepare(media_streamer_s *ms_streamer, GstElement *bin)
2165 {
2166         GValue element = G_VALUE_INIT;
2167         GstIterator *bin_iterator = NULL;
2168         gboolean ret = TRUE; /* If the bin doesn't have any elements, it returns TRUE */
2169         GstElement *found_element = NULL;
2170         GstIteratorResult it_res = GST_ITERATOR_ERROR;
2171         media_streamer_node_s *found_node = NULL;
2172
2173         ms_debug_fenter();
2174
2175         ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2176         ms_retvm_if(bin == NULL, FALSE, "bin is NULL");
2177         ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
2178
2179         bin_iterator = gst_bin_iterate_elements(GST_BIN(bin));
2180         it_res = gst_iterator_next(bin_iterator, &element);
2181
2182         while (GST_ITERATOR_OK == it_res) {
2183                 found_element = (GstElement *) g_value_get_object(&element);
2184
2185                 /* Get node of this element if it appears as node */
2186                 found_node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table, GST_ELEMENT_NAME(found_element));
2187                 if (found_node) {
2188                         if (!found_node->linked_by_user)
2189                                 ret = ret && ms_element_unlink(found_element);
2190                         else
2191                                 ms_info("Unprepare skipped user-linked node [%s]", found_node->name);
2192                         ms_generate_dots(ms_streamer->pipeline, GST_ELEMENT_NAME(found_element));
2193                 } else {
2194                         ret = ret && ms_bin_remove_element(found_element);
2195                 }
2196
2197                 g_value_reset(&element);
2198
2199                 it_res = gst_iterator_next(bin_iterator, &element);
2200                 if (GST_ITERATOR_RESYNC == it_res) {
2201                         gst_iterator_resync(bin_iterator);
2202                         it_res = gst_iterator_next(bin_iterator, &element);
2203                 }
2204         }
2205
2206         g_value_unset(&element);
2207         gst_iterator_free(bin_iterator);
2208
2209         ms_debug_fleave();
2210
2211         return ret;
2212 }
2213
2214 int ms_pipeline_prepare(media_streamer_s *ms_streamer)
2215 {
2216         int ret = MEDIA_STREAMER_ERROR_NONE;
2217         media_streamer_node_s *rtp = NULL;
2218         media_streamer_node_s *demux = NULL;
2219         media_streamer_node_s *adaptive_src = NULL;
2220         media_streamer_node_s *adaptive_sink = NULL;
2221         gchar *find_node_name = "demux";
2222
2223         ms_debug_fenter();
2224
2225         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2226         ms_retvm_if(ms_streamer->nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->nodes_table is NULL");
2227         ms_retvm_if(ms_streamer->src_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->src_bin is NULL");
2228         ms_retvm_if(ms_streamer->transform_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->transform_bin is NULL");
2229
2230         rtp = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
2231         demux = (media_streamer_node_s *)g_hash_table_find(ms_streamer->nodes_table, (GHRFunc)__find_node, find_node_name);
2232         adaptive_src = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_src");
2233         adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
2234
2235         if (rtp) {
2236                 ret = ms_rtp_node_prepare(rtp);
2237         } else if (demux) {
2238                 ret = ms_demux_node_prepare(ms_streamer, demux);
2239                 if (MEDIA_STREAMER_ERROR_NONE != ret)
2240                                 ms_error("Failed to prepare demux element");
2241         } else {
2242                 GstBin *nodes_bin = GST_BIN(ms_streamer->src_bin);
2243                 if (nodes_bin->numchildren == 0) {
2244                         ms_debug(" No any node is added to [%s]", GST_ELEMENT_NAME(ms_streamer->src_bin));
2245                         return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2246                 }
2247                 nodes_bin = GST_BIN(ms_streamer->sink_bin);
2248                 if (nodes_bin->numchildren == 0) {
2249                         ms_debug(" No any node is added to [%s]", GST_ELEMENT_NAME(ms_streamer->sink_bin));
2250                         return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2251                 }
2252         }
2253
2254         if (adaptive_src) {
2255                 if (GST_BIN(ms_streamer->transform_bin)->numchildren == 0)
2256                         ret = ms_adaptive_src_node_prepare(adaptive_src, true);
2257                 else
2258                         ret = ms_adaptive_src_node_prepare(adaptive_src, false);
2259         }
2260
2261         if (adaptive_sink)
2262                 ret = ms_adaptive_sink_node_prepare(ms_streamer, adaptive_sink);
2263
2264         if (ret != MEDIA_STREAMER_ERROR_NONE)
2265                 goto prepare_fail;
2266
2267         ret = ms_bin_foreach_elements(GST_BIN(ms_streamer->sink_bin), ms_sink_node_prepare_iter, ms_streamer);
2268         if (MEDIA_STREAMER_ERROR_NONE != ret) {
2269                 ms_error("Failed to prepare nodes within sink bin");
2270                 goto prepare_fail;
2271         }
2272
2273         ret = ms_bin_foreach_elements(GST_BIN(ms_streamer->src_bin), ms_src_node_prepare_iter, ms_streamer);
2274         if (MEDIA_STREAMER_ERROR_NONE != ret) {
2275                 ms_error("Failed to prepare nodes within src bin");
2276                 goto prepare_fail;
2277         }
2278
2279         ret = ms_set_state(ms_streamer, MEDIA_STREAMER_STATE_READY);
2280         if (ret != MEDIA_STREAMER_ERROR_NONE)
2281                 goto prepare_fail;
2282
2283         ms_debug_fleave();
2284
2285         return ret;
2286
2287 prepare_fail:
2288         ms_pipeline_unprepare(ms_streamer);
2289         return ret;
2290 }
2291
2292 int ms_pipeline_unprepare(media_streamer_s *ms_streamer)
2293 {
2294         int ret = MEDIA_STREAMER_ERROR_NONE;
2295
2296         ms_debug_fenter();
2297
2298         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2299         ms_retvm_if(ms_streamer->nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->nodes_table is NULL");
2300
2301         ret = ms_set_state(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
2302         if (ret != MEDIA_STREAMER_ERROR_NONE)
2303                 ms_error("Failed to unprepare pipeline");
2304
2305         if (!ms_streamer->is_interrupted) {
2306                 /* FIXME: it seems possible to move codes below to ms_set_state(), need to check the history. */
2307                 /* Unprepare resources in case of failure */
2308                 if (ms_streamer->video_decoder_resource != NULL) {
2309                         ret = mm_resource_manager_mark_for_release(ms_streamer->resource_manager,
2310                                         ms_streamer->video_decoder_resource);
2311                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
2312                                 ms_error("Failed to mark resources for release");
2313
2314                         ret = mm_resource_manager_commit(ms_streamer->resource_manager);
2315                         if (ret != MEDIA_STREAMER_ERROR_NONE)
2316                                 ms_error("Failed to release resources");
2317                         else
2318                                 ms_streamer->video_decoder_resource = NULL;
2319                 }
2320         }
2321
2322         /* Disconnects and clean all autoplug signals */
2323         g_list_free_full(ms_streamer->autoplug_sig_list, ms_signal_destroy);
2324         ms_streamer->autoplug_sig_list = NULL;
2325
2326         /* Removes all pending pads according to list */
2327         g_list_free_full(ms_streamer->pads_types_list, __ms_pending_pads_remove);
2328         ms_streamer->pads_types_list = NULL;
2329
2330         media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
2331         if (rtp_node) {
2332                 g_list_free_full(rtp_node->sig_list, ms_signal_destroy);
2333                 rtp_node->sig_list = NULL;
2334                 __ms_bin_unprepare(ms_streamer, rtp_node->gst_element);
2335         }
2336
2337         __ms_bin_unprepare(ms_streamer, ms_streamer->src_bin);
2338         __ms_bin_unprepare(ms_streamer, ms_streamer->transform_bin);
2339         __ms_bin_unprepare(ms_streamer, ms_streamer->sink_bin);
2340
2341         ms_debug_fleave();
2342
2343         return ret;
2344 }
2345
2346 void ms_pipeline_get_state(media_streamer_s *ms_streamer)
2347 {
2348         GstState state_old = GST_STATE_NULL, state_new = GST_STATE_NULL;
2349         GstStateChangeReturn ret_state = -1;
2350
2351         ms_debug_fenter();
2352
2353         ms_retm_if(ms_streamer == NULL, "ms_streamer is NULL");
2354         ms_retm_if(ms_streamer->pipeline == NULL, "ms_streamer->pipeline is NULL");
2355
2356         ret_state = gst_element_get_state(ms_streamer->pipeline, &state_old, &state_new, GST_CLOCK_TIME_NONE);
2357         if (ret_state == GST_STATE_CHANGE_SUCCESS)
2358                 ms_info("Got state for [%s]: old [%s], new [%s]", GST_ELEMENT_NAME(ms_streamer->pipeline), gst_element_state_get_name(state_old), gst_element_state_get_name(state_new));
2359         else
2360                 ms_error("Couldn`t get state for [%s]", GST_ELEMENT_NAME(ms_streamer->pipeline));
2361
2362         ms_debug_fleave();
2363 }
2364
2365 GstCaps *ms_create_caps_from_fmt(media_format_h fmt)
2366 {
2367         GstCaps *caps = NULL;
2368         gchar *caps_name = NULL;
2369         media_format_mimetype_e mime;
2370         int width, height, avg_bps, max_bps, channel, samplerate, bit;
2371
2372         ms_debug_fenter();
2373
2374         if (!media_format_get_audio_info(fmt, &mime, &channel, &samplerate, &bit, &avg_bps)) {
2375                 if (MEDIA_FORMAT_RAW == (mime & MEDIA_FORMAT_RAW)) {
2376                         caps = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING, ms_convert_mime_to_string_format(mime), NULL);
2377                 } else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED)) {
2378                         if (mime == MEDIA_FORMAT_AAC)
2379                                 caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "mpegversion", G_TYPE_INT, 4, NULL);
2380                         else if (mime == MEDIA_FORMAT_MP3)
2381                                 caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "mpegversion", G_TYPE_INT, 1, NULL);
2382                         else
2383                                 caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "channels", G_TYPE_INT, channel, "rate", G_TYPE_INT, samplerate, NULL);
2384                 }
2385                 caps_name = gst_caps_to_string(caps);
2386                 ms_info("Creating Audio Caps from media format [%s]", caps_name);
2387
2388         } else if (!media_format_get_video_info(fmt, &mime, &width, &height, &avg_bps, &max_bps)) {
2389                 if (MEDIA_FORMAT_RAW == (mime & MEDIA_FORMAT_RAW))
2390                         caps = gst_caps_new_simple("video/x-raw", "framerate", GST_TYPE_FRACTION, max_bps,
2391                                         avg_bps, "format", G_TYPE_STRING, ms_convert_mime_to_string_format(mime), "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
2392                 else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED))
2393                         caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "framerate", GST_TYPE_FRACTION, max_bps,
2394                                                         avg_bps, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
2395                 caps_name = gst_caps_to_string(caps);
2396                 ms_info("Creating Video Caps from media format [%s]", caps_name);
2397
2398         } else if (!media_format_get_container_mime(fmt, &mime)) {
2399                         caps = gst_caps_new_empty_simple(ms_convert_mime_to_string_format(mime));
2400                         caps_name = gst_caps_to_string(caps);
2401                         ms_info("Creating Video Caps from media format [%s]", caps_name);
2402
2403         } else
2404                 ms_error("Error getting media format information");
2405
2406         MS_SAFE_GFREE(caps_name);
2407
2408         ms_debug_fleave();
2409
2410         return caps;
2411 }
2412
2413 static media_format_h __ms_create_fmt_from_caps(GstCaps *caps)
2414 {
2415         media_format_h fmt;
2416         GstStructure *pad_struct;
2417         int fmt_ret = MEDIA_FORMAT_ERROR_NONE;
2418         const gchar *pad_type = NULL;
2419         const gchar *pad_format = NULL;
2420         int channels = 0, bps = 0;
2421         int width = 0, height = 0, avg_bps = 0, max_bps = 0;
2422
2423         ms_debug_fenter();
2424
2425         ms_retvm_if(caps == NULL, NULL, "Error: empty caps!");
2426
2427         if (gst_caps_is_any(caps)) {
2428                 ms_debug("Can not get format info from any caps!");
2429                 return NULL;
2430         }
2431
2432         fmt_ret = media_format_create(&fmt);
2433         ms_retvm_if(fmt_ret != MEDIA_FORMAT_ERROR_NONE, NULL, "Error: while creating media format object, err[%d]!", fmt_ret);
2434
2435         pad_struct = gst_caps_get_structure(caps, 0);
2436         pad_type = gst_structure_get_name(pad_struct);
2437         pad_format = pad_type;
2438
2439         /* Got raw format type if needed */
2440         if (g_strrstr(pad_type, "/x-raw"))
2441                 pad_format = gst_structure_get_string(pad_struct, "format");
2442
2443         ms_debug("Pad type is [%s], format: [%s]", pad_type, pad_format);
2444
2445         if (MS_ELEMENT_IS_VIDEO(pad_type)) {
2446                 gst_structure_get_int(pad_struct, "width", &width);
2447                 gst_structure_get_fraction(pad_struct, "framerate", &max_bps, &avg_bps);
2448                 gst_structure_get_int(pad_struct, "height", &height);
2449
2450                 media_format_set_video_mime(fmt, ms_convert_string_format_to_media_format(pad_format));
2451                 media_format_set_video_width(fmt, width);
2452                 media_format_set_video_height(fmt, height);
2453                 media_format_set_video_avg_bps(fmt, avg_bps);
2454                 media_format_set_video_max_bps(fmt, max_bps);
2455         } else if (MS_ELEMENT_IS_AUDIO(pad_type)) {
2456                 media_format_set_audio_mime(fmt, ms_convert_string_format_to_media_format(pad_format));
2457                 gst_structure_get_int(pad_struct, "channels", &channels);
2458                 media_format_set_audio_channel(fmt, channels);
2459                 gst_structure_get_int(pad_struct, "rate", &bps);
2460                 media_format_set_audio_avg_bps(fmt, bps);
2461         }
2462
2463         ms_debug_fleave();
2464
2465         return fmt;
2466 }
2467
2468 int ms_element_pad_names(GstElement *gst_element, GstPadDirection pad_type, char ***pad_name_array, int *pads_count)
2469 {
2470         int ret = MEDIA_STREAMER_ERROR_NONE;
2471         int pad_number = 0;
2472         GValue elem = G_VALUE_INIT;
2473         GstPad *pad = NULL;
2474         char **pad_names = NULL;
2475         GstIterator *pad_iterator = NULL;
2476         gchar *pad_name = NULL;
2477
2478         ms_debug_fenter();
2479
2480         ms_retvm_if(gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
2481         ms_retvm_if(pad_name_array == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name_array is NULL");
2482         ms_retvm_if(pads_count == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pads_count is NULL");
2483
2484         if (pad_type == GST_PAD_SRC) {
2485                 pad_iterator = gst_element_iterate_src_pads(gst_element);
2486         } else if (pad_type == GST_PAD_SINK) {
2487                 pad_iterator = gst_element_iterate_sink_pads(gst_element);
2488         } else {
2489                 pad_iterator = gst_element_iterate_pads(gst_element);
2490                 ms_info("Iterating all pads of the Gst element");
2491         }
2492
2493         while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &elem)) {
2494                 pad = (GstPad *) g_value_get_object(&elem);
2495
2496                 pad_names = (char **)realloc(pad_names, sizeof(char *) * (pad_number + 1));
2497                 if (!pad_names) {
2498                         ms_error("Error allocation memory");
2499                         ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2500                         pad_number = 0;
2501                         MS_SAFE_FREE(pad_names);
2502                         break;
2503                 }
2504
2505                 pad_name = gst_pad_get_name(pad);
2506                 pad_names[pad_number] = pad_name;
2507                 g_free(pad_name);
2508                 ++pad_number;
2509
2510                 g_value_reset(&elem);
2511         }
2512
2513         g_value_unset(&elem);
2514         gst_iterator_free(pad_iterator);
2515
2516         *pad_name_array = pad_names;
2517         *pads_count = pad_number;
2518
2519         MS_SAFE_FREE(pad_names);
2520
2521         ms_debug_fleave();
2522
2523         return ret;
2524 }
2525
2526 int ms_element_get_pad_fmt(GstElement *gst_element, const char *pad_name, media_format_h *fmt)
2527 {
2528         int ret = MEDIA_STREAMER_ERROR_NONE;
2529         GstCaps *allowed_caps = NULL;
2530         GstCaps *format_caps = NULL;
2531         GstPad *pad = NULL;
2532         GValue *value = NULL;
2533
2534         ms_debug_fenter();
2535
2536         ms_retvm_if(gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
2537         ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2538         ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2539
2540
2541         pad = gst_element_get_static_pad(gst_element, pad_name);
2542         ms_retvm_if(pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Fail to get pad [%s] from element [%s].", pad_name, GST_ELEMENT_NAME(gst_element));
2543
2544         value = (GValue *) g_object_get_data(G_OBJECT(gst_element), pad_name);
2545         if (value)
2546                 format_caps = GST_CAPS(gst_value_get_caps(value));
2547         else
2548                 ms_info(" No any format is set for pad [%s]", pad_name);
2549
2550         allowed_caps = gst_pad_get_allowed_caps(pad);
2551         if (allowed_caps) {
2552                 if (gst_caps_is_empty(allowed_caps) || gst_caps_is_any(allowed_caps)) {
2553                         if (format_caps)
2554                                 *fmt = __ms_create_fmt_from_caps(format_caps);
2555                         else
2556                                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2557                 } else {
2558                         *fmt = __ms_create_fmt_from_caps(allowed_caps);
2559                 }
2560         } else {
2561                 if (format_caps)
2562                         *fmt = __ms_create_fmt_from_caps(format_caps);
2563                 else
2564                         ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2565         }
2566
2567         if (allowed_caps)
2568                 gst_caps_unref(allowed_caps);
2569
2570         MS_SAFE_UNREF(pad);
2571
2572         ms_debug_fleave();
2573
2574         return ret;
2575 }
2576
2577 int ms_element_set_fmt(GstElement *element, const char *pad_name, media_format_h fmt)
2578 {
2579         gboolean can_accept = FALSE;
2580         GstCaps *fmt_caps = NULL;
2581         GstElementFactory *factory = NULL;
2582         GstPad *node_pad = NULL;
2583
2584         ms_debug_fenter();
2585
2586         ms_retvm_if(!element || !pad_name || !fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2587
2588         fmt_caps = ms_create_caps_from_fmt(fmt);
2589         ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps");
2590
2591         factory = gst_element_get_factory(element);
2592         node_pad = gst_element_get_static_pad(element, pad_name);
2593
2594         if (node_pad && GST_PAD_IS_SRC(node_pad))
2595                 can_accept  = gst_element_factory_can_src_any_caps(factory, fmt_caps);
2596         else if (node_pad && GST_PAD_IS_SINK(node_pad))
2597                 can_accept  = gst_element_factory_can_sink_any_caps(factory, fmt_caps);
2598         else
2599                 ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name);
2600
2601         if (!can_accept) {
2602                 if (fmt_caps)
2603                         gst_caps_unref(fmt_caps);
2604                 ms_error("[%s]'s pad [%s] can`t be set with the given format", GST_ELEMENT_NAME(element), pad_name);
2605                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2606         } else {
2607                 MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps);
2608                 ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name);
2609         }
2610
2611         MS_SAFE_UNREF(node_pad);
2612
2613         ms_debug_fleave();
2614
2615         return MEDIA_STREAMER_ERROR_NONE;
2616 }
2617
2618 gboolean ms_gst_seek(GstElement *element, gint64 g_time, GstSeekFlags seek_flag)
2619 {
2620         gboolean result = FALSE;
2621         GstEvent *event = NULL;
2622
2623         ms_debug_fenter();
2624
2625         ms_retvm_if(element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Element is NULL");
2626
2627         event = gst_event_new_seek(1.0, GST_FORMAT_TIME, seek_flag,
2628                                                                          GST_SEEK_TYPE_SET, g_time,
2629                                                                          GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
2630         if (event)
2631                 result = gst_element_send_event(element, event);
2632
2633         ms_debug_fleave();
2634
2635         return result;
2636 }
2637
2638 int ms_element_push_packet(GstElement *src_element, media_packet_h packet)
2639 {
2640         GstBuffer *buffer = NULL;
2641         GstFlowReturn gst_ret = GST_FLOW_OK;
2642         guchar *buffer_data = NULL;
2643
2644         ms_debug_fenter();
2645
2646         ms_retvm_if(src_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2647
2648         if (packet == NULL) {
2649                 g_signal_emit_by_name(G_OBJECT(src_element), "end-of-stream", &gst_ret, NULL);
2650                 return MEDIA_STREAMER_ERROR_NONE;
2651         }
2652
2653         media_packet_get_buffer_data_ptr(packet, (void **)&buffer_data);
2654
2655         if (buffer_data != NULL) {
2656                 GstMapInfo buff_info = GST_MAP_INFO_INIT;
2657                 guint64 pts = 0;
2658                 guint64 duration = 0;
2659                 guint64 size = 0;
2660
2661                 media_packet_get_buffer_size(packet, &size);
2662
2663                 buffer = gst_buffer_new_and_alloc(size);
2664                 if (!buffer) {
2665                         ms_error("Failed to allocate memory for push buffer");
2666                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2667                 }
2668
2669                 if (gst_buffer_map(buffer, &buff_info, GST_MAP_READWRITE)) {
2670                         memcpy(buff_info.data, buffer_data, size);
2671                         buff_info.size = size;
2672                         gst_buffer_unmap(buffer, &buff_info);
2673                 }
2674
2675                 media_packet_get_pts(packet, &pts);
2676                 GST_BUFFER_PTS(buffer) = pts;
2677
2678                 media_packet_get_duration(packet, &duration);
2679                 GST_BUFFER_DURATION(buffer) = duration;
2680
2681                 g_signal_emit_by_name(G_OBJECT(src_element), "push-buffer", buffer, &gst_ret, NULL);
2682                 gst_buffer_unref(buffer);
2683
2684         } else {
2685                 g_signal_emit_by_name(G_OBJECT(src_element), "end-of-stream", &gst_ret, NULL);
2686         }
2687
2688         if (gst_ret != GST_FLOW_OK)
2689                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2690
2691         ms_debug_fleave();
2692
2693         return MEDIA_STREAMER_ERROR_NONE;
2694 }
2695
2696 int ms_element_pull_packet(GstElement *sink_element, media_packet_h *packet)
2697 {
2698         int ret = MEDIA_STREAMER_ERROR_NONE;
2699         GstSample *sample = NULL;
2700         media_format_h fmt = NULL;
2701         guint8 *buffer_res = NULL;
2702         GstMapInfo map = {0,};
2703         GstBuffer *buffer = NULL;
2704
2705         ms_debug_fenter();
2706
2707         ms_retvm_if(sink_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2708         ms_retvm_if(packet == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2709
2710         /* Retrieve the buffer */
2711         g_signal_emit_by_name(sink_element, "pull-sample", &sample, NULL);
2712         ms_retvm_if(sample == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pull sample failed!");
2713
2714         ret = ms_element_get_pad_fmt(sink_element, "sink", &fmt);
2715         if (ret == MEDIA_STREAMER_ERROR_NONE) {
2716                 buffer = gst_sample_get_buffer(sample);
2717                 if (!buffer) {
2718                         ms_error("Failed to get buffer from sample");
2719                         media_format_unref(fmt);
2720                         gst_sample_unref(sample);
2721                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2722                 }
2723                 gst_buffer_map(buffer, &map, GST_MAP_READ);
2724
2725                 buffer_res = (guint8 *) malloc(map.size * sizeof(guint8));
2726                 if (buffer_res != NULL) {
2727                         memcpy(buffer_res, map.data, map.size);
2728
2729                         media_packet_create_from_external_memory(fmt, (void *)buffer_res, map.size, NULL, NULL, packet);
2730                         media_packet_set_pts(*packet, GST_BUFFER_PTS(buffer));
2731                         media_packet_set_dts(*packet, GST_BUFFER_DTS(buffer));
2732                         media_packet_set_pts(*packet, GST_BUFFER_DURATION(buffer));
2733                 } else {
2734                         ms_error("Error allocation memory for packet data");
2735                         ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2736                 }
2737                 gst_buffer_unmap(buffer, &map);
2738         }
2739
2740         media_format_unref(fmt);
2741         gst_sample_unref(sample);
2742
2743         ms_debug_fleave();
2744
2745         return ret;
2746 }
2747
2748 static void __ms_typefound_cb(GstElement *typefind, guint probability, GstCaps *caps, gpointer data)
2749 {
2750         media_streamer_s *ms_streamer = (media_streamer_s *) data;
2751         GstElement *decodebin = NULL;
2752         media_streamer_node_s *adaptive_sink = NULL;
2753         gchar *type = NULL;
2754         GstPad *src_pad = NULL;
2755
2756         ms_debug_fenter();
2757
2758         ms_retm_if(!typefind, "typefind is NULL");
2759         ms_retm_if(!ms_streamer, "data is NULL");
2760
2761         adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
2762         src_pad = gst_element_get_static_pad(typefind, "src");
2763
2764         type = gst_caps_to_string(caps);
2765         if (g_strrstr(type, "video/mpegts") && adaptive_sink) {
2766                 __ms_link_two_elements(typefind, src_pad, adaptive_sink->gst_element);
2767         } else {
2768                 decodebin = __ms_decodebin_create(ms_streamer, NULL);
2769                 __ms_link_two_elements(typefind, src_pad, decodebin);
2770         }
2771
2772         MS_SAFE_UNREF(src_pad);
2773         g_free(type);
2774
2775         ms_debug_fleave();
2776 }
2777
2778 int ms_find_type(media_streamer_s *ms_streamer, GstElement *src_element)
2779 {
2780         GstElement *typefind = NULL;
2781         GstPad *src_pad = NULL;
2782
2783         ms_debug_fenter();
2784
2785         ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2786         ms_retvm_if(!src_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "src_element is NULL");
2787
2788         src_pad = gst_element_get_static_pad(src_element, "src");
2789         ms_retvm_if(src_pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
2790                         "Error getting static_pad [src_pad]");
2791
2792         typefind = gst_element_factory_make("typefind", "typefinder");
2793         ms_retvm_if(typefind == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
2794                         "Error creating element [typefind]");
2795
2796         ms_bin_add_element(ms_streamer->transform_bin, typefind, TRUE);
2797
2798         gst_element_sync_state_with_parent(typefind);
2799
2800         g_signal_connect(typefind, "have-type", G_CALLBACK(__ms_typefound_cb), ms_streamer);
2801
2802         __ms_link_two_elements(src_element, src_pad, typefind);
2803
2804         MS_SAFE_UNREF(src_pad);
2805
2806         ms_debug_fleave();
2807
2808         return MEDIA_STREAMER_ERROR_NONE;
2809 }