/* * sydra * * sydra is a toolbox which allows you to set up multiple bidirectional * Video/Audio streams from external locations. * sydra has been written to be used for the Elevate Festival in Graz * Austria in order to involve external locations to present themselves * at the festival. * * * Copyright (C) 2014 Christian Pointner * * This file is part of sydra. * * sydra is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * sydra is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with sydra. If not, see . * * In addition, as a special exception, the copyright holders hereby * grant permission for non-GPL-compatible GStreamer plugins to be used * and distributed together with GStreamer and sydra. * This permission goes above and beyond the permissions granted by the * GPL license sydra is covered by. */ #include "datatypes.h" #include "utils.h" #include "log.h" #include #include gint cmp_udp_client(gconstpointer A, gconstpointer B) { const struct udp_client *a = (const struct udp_client *)A; const struct udp_client *b = (const struct udp_client *)B; if(a->host_.type_ != b->host_.type_ || a->host_.port_ != b->host_.port_) return -1; return strncmp(a->host_.addr_, b->host_.addr_, sizeof(a->host_.addr_)); } GstElement* sydra_create_bin_from_desc(const char* name, const char* desc, gboolean ghost_unlinked_pads) { GError *error = NULL; GstElement *bin = gst_parse_bin_from_description(desc, ghost_unlinked_pads, &error); if(!bin) { log_printf(ERROR, "Bin description for %s parser error: %s", name, error ? error->message : "unknown"); g_error_free(error); return NULL; } if(error) { log_printf(WARNING, "Bin description for %s parser warning: %s", name, error ? error->message : "unknown"); g_error_free(error); } gst_element_set_name(bin, name); return bin; } GstElement* sydra_create_element(const char* type, const char* name) { GstElement *e = gst_element_factory_make (type, name); if(!e) { log_printf(ERROR, "Error creating element %s%sof type %s", name ? name : "", name ? " " : "", type); return NULL; } return e; } static gboolean sydra_link_pads(GstElement* src, GstPad* src_pad, const char* src_pad_name, GstElement* sink, GstPad* sink_pad, const char* sink_pad_name) { if(!src_pad || !sink_pad) return FALSE; GstPadLinkReturn ret = gst_pad_link(src_pad, sink_pad); gst_object_unref(GST_OBJECT(src_pad)); gst_object_unref(GST_OBJECT(sink_pad)); if(GST_PAD_LINK_FAILED(ret)) { gchar* src_name = gst_element_get_name(src); gchar* sink_name = gst_element_get_name(sink); log_printf(ERROR, "Error linking pad '%s' of '%s' with pad '%s' of '%s': %s", src_pad_name, src_name, sink_pad_name, sink_name, gst_pad_link_get_name(ret)); g_free(src_name); g_free(sink_name); return FALSE; } return TRUE; } gboolean sydra_link_request_request(GstElement* src, const char* src_pad_name, GstElement* sink, const char* sink_pad_name) { GstPad *src_pad = gst_element_get_request_pad(src, src_pad_name); GstPad *sink_pad = gst_element_get_request_pad(sink, sink_pad_name); return sydra_link_pads(src, src_pad, src_pad_name, sink, sink_pad, sink_pad_name); } gboolean sydra_link_request_static(GstElement* src, const char* src_pad_name, GstElement* sink, const char* sink_pad_name) { GstPad *src_pad = gst_element_get_request_pad(src, src_pad_name); GstPad *sink_pad = gst_element_get_static_pad(sink, sink_pad_name); return sydra_link_pads(src, src_pad, src_pad_name, sink, sink_pad, sink_pad_name); } gboolean sydra_link_static_request(GstElement* src, const char* src_pad_name, GstElement* sink, const char* sink_pad_name) { GstPad *src_pad = gst_element_get_static_pad(src, src_pad_name); GstPad *sink_pad = gst_element_get_request_pad(sink, sink_pad_name); return sydra_link_pads(src, src_pad, src_pad_name, sink, sink_pad, sink_pad_name); } gboolean sydra_link_static_static(GstElement* src, const char* src_pad_name, GstElement* sink, const char* sink_pad_name) { GstPad *src_pad = gst_element_get_static_pad(src, src_pad_name); GstPad *sink_pad = gst_element_get_static_pad(sink, sink_pad_name); return sydra_link_pads(src, src_pad, src_pad_name, sink, sink_pad, sink_pad_name); } gboolean sydra_link_static_compatible(GstElement* src, const char* src_pad_name, GstElement* sink) { GstPad *src_pad = gst_element_get_static_pad(src, src_pad_name); if(!src_pad) return FALSE; GstPad *sink_pad = gst_element_get_compatible_pad(sink, src_pad, NULL); if(!sink_pad) return FALSE; gchar* sink_pad_name = gst_pad_get_name(sink_pad); gboolean res = sydra_link_pads(src, src_pad, src_pad_name, sink, sink_pad, sink_pad_name); g_free(sink_pad_name); return res; }