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