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