reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
GStreamerUtils.hxx
Go to the documentation of this file.
1#ifndef RESIP_GSTREAMER_UTILS
2#define RESIP_GSTREAMER_UTILS
3
4#ifdef HAVE_CONFIG_H
5#include "config.h"
6#endif
7
8#ifdef USE_GSTREAMER
9#include <map>
10#include <utility>
11#include <type_traits>
12#include <glibmm/main.h>
13#include <glibmm/exceptionhandler.h>
14#include <glibmm/ustring.h>
15#include <gstreamermm.h>
16
17#include <gst/webrtc/webrtc.h>
18
19#include "rutil/Subsystem.hxx"
20#include "rutil/Log.hxx"
23#include "resip/stack/Tuple.hxx"
24
25#include "GstSubsystem.hxx"
26
27extern "C"
28{
31
32 void
34 const gchar *file,
35 const gchar *function, gint line, GObject *object,
37};
38
39namespace resip
40{
41
42static const std::map<GstWebRTCICEConnectionState, const resip::Data> iCEConnectionStates =
43 {
44 {GST_WEBRTC_ICE_CONNECTION_STATE_NEW, "new"},
45 {GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING, "checking"},
46 {GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED, "connected"},
47 {GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED, "completed"},
48 {GST_WEBRTC_ICE_CONNECTION_STATE_FAILED, "failed"},
49 {GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED, "disconnected"},
50 {GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED, "closed"}
51 };
52
53static const std::map<GstWebRTCICEGatheringState, const resip::Data> iCEGatheringStates =
54 {
55 {GST_WEBRTC_ICE_GATHERING_STATE_NEW, "new"},
56 {GST_WEBRTC_ICE_GATHERING_STATE_GATHERING, "gathering"},
57 {GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE, "complete"}
58 };
59
60static const std::map<GstWebRTCSignalingState, const resip::Data> signalingStates =
61 {
62 {GST_WEBRTC_SIGNALING_STATE_STABLE, "stable"},
63 {GST_WEBRTC_SIGNALING_STATE_CLOSED, "closed"},
64 {GST_WEBRTC_SIGNALING_STATE_HAVE_LOCAL_OFFER, "local-offer"},
65 {GST_WEBRTC_SIGNALING_STATE_HAVE_REMOTE_OFFER, "remote-offer"},
66 {GST_WEBRTC_SIGNALING_STATE_HAVE_LOCAL_PRANSWER, "local-pranswer"},
67 {GST_WEBRTC_SIGNALING_STATE_HAVE_REMOTE_PRANSWER, "remote-pranswer"}
68 };
69
70template<typename T>
71const Data& lookupGstreamerStateName(std::map<T, const Data> m, T v)
72{
73 auto it = m.find(v);
74 if(it == m.end())
75 {
76 resip_assert(0);
77 static Data unknown("UNKNOWN STATE");
78 return unknown;
79 }
80 return it->second;
81};
82
83Glib::RefPtr<Gst::Element> buildTestSource(const Data& streamName);
84
85typedef resip::Data MediaTypeName;
86
87MediaTypeName getMediaTypeName(const Glib::RefPtr<Gst::Caps>& caps);
88
89int getStreamIdFromPadName(const Glib::ustring padName);
90
91resip::Data deduceKeyForPadName(const Glib::ustring padName);
92
93/*
94 * Must set the environment variable GST_DEBUG_DUMP_DOT_DIR
95 * or no Gstreamer graph files will be created.
96 *
97 * In gdb:
98 * set env GST_DEBUG_DUMP_DOT_DIR=/tmp
99 */
100void storeGstreamerGraph(Glib::RefPtr<Gst::Bin>& bin, const resip::Data& fileNamePrefix);
101
102void gstWebRTCSetDescription(Glib::RefPtr<Gst::Element> element, const gchar* signalName, GstWebRTCSessionDescription* gstwebrtcdesc);
103
104resip::SdpContents* createSdpContentsFromGstreamer(GstWebRTCSessionDescription *gSdp);
105
106std::shared_ptr<GstWebRTCSessionDescription> createGstWebRTCSessionDescriptionFromSdpContents(GstWebRTCSDPType sdpType, const resip::SdpContents& sdp);
107
108void addGstreamerKeyframeProbe(const Glib::RefPtr<Gst::Pad>& pad, std::function<void()> onKeyframeRequired);
109
110struct RtcpPeerSpec
111{
112 resip::Tuple local;
113 resip::Tuple remote;
114};
115typedef std::vector<RtcpPeerSpec> RtcpPeerSpecVector;
116
117// call this after all the pads have been created on the rtpbin
118bool addGstreamerRtcpMonitoringPads(Glib::RefPtr<Gst::Bin> bin, std::shared_ptr<HepAgent> hepAgent, const RtcpPeerSpecVector& peerSpecs, const Data& correlationId);
119
120// For scenario's where we obtain access to individual elements
121// in the rtpbin and insert Tee (GstTee) elements to intercept RTCP flows,
122// the pad-added handler must call this to complete the pipeline setup
123// and insert an AppSink to handle the RTCP from our new ghost pads.
124// This does not need to be called at all if using signals from RTPSession
125// to obtain the RTCP.
126void linkGstreamerRtcpHomer(Glib::RefPtr<Gst::Bin> bin, Glib::RefPtr<Gst::Pad> pad, std::shared_ptr<resip::HepAgent> hepAgent, const RtcpPeerSpecVector& peerSpecs, const resip::Data& correlationId);
127
128RtcpPeerSpecVector createRtcpPeerSpecs(const SdpContents& local, const SdpContents& remote);
129
130}
131
132
133namespace Glib
134{
135
136template<typename T>
137static inline T transform(T p) { return p; }
138
139static inline Glib::RefPtr<Gst::Caps> transform (GstCaps* c) { return Glib::wrap(c, true); }
140static inline Glib::RefPtr<Gst::Pad> transform (GstPad* c) { return Glib::wrap(c, true); }
141static inline Glib::RefPtr<Gst::Element> transform (GstElement* c) { return Glib::wrap(c, true); }
142
143template<class T>
145{
146 template<class U, typename=typename U::element_type::BaseObjectType>
147 static typename U::element_type::BaseObjectType* test (int);
148
149 template<class U>
150 static U test (...);
151
152 using type = decltype (test<T> (0));
153};
154
155
156template<typename SlotType, typename ...T>
157static void signal_callback(GstElement* self, T... x, void* data)
158{
159 using namespace Gst;
160 Gst::Element* obj = dynamic_cast<Gst::Element*>(Glib::ObjectBase::_get_current_wrapper((GObject*) self));
162 if(obj)
163 {
164 try
165 {
166 if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
167 {
168 (*static_cast<SlotType*>(slot))(transform(x)...);
169 }
170 }
171 catch(...)
172 {
173 Glib::exception_handlers_invoke();
174 }
175 }
176}
177
178// FIXME - thread safety of map insertion
179typedef std::pair<GType,Glib::ustring> SIDictKey;
180static std::map<SIDictKey,std::shared_ptr<SignalProxyInfo>> signalProxyInfoDict;
181
182template<typename ReturnType, typename ...T>
183static Glib::SignalProxy< ReturnType, T... > signal_any(const Glib::RefPtr<Gst::Element>& element, const Glib::ustring name)
184{
185 std::shared_ptr<SignalProxyInfo> info;
186 SIDictKey key(element->get_type(), name);
187 if(signalProxyInfoDict.find(key) != signalProxyInfoDict.cend())
188 {
189 info = signalProxyInfoDict.at(key);
190 }
191 else
192 {
193 info.reset(new SignalProxyInfo
194 {
195 name.c_str(),
196 (GCallback) &signal_callback<sigc::slot< ReturnType, T...>, typename deduce_result_type<T>::type...>,
197 (GCallback) &signal_callback<sigc::slot< ReturnType, T...>, typename deduce_result_type<T>::type...>
198 });
199 signalProxyInfoDict[key] = info;
200 }
201
202 return Glib::SignalProxy< ReturnType,T...>(element.operator->(), info.get());
203}
204
205}
206
207
208
209#endif
210
211#endif
212
213/* ====================================================================
214 *
215 * Copyright (c) 2022, Software Freedom Institute https://softwarefreedom.institute
216 * Copyright (c) 2021-2022, Daniel Pocock https://danielpocock.com
217 *
218 * Redistribution and use in source and binary forms, with or without
219 * modification, are permitted provided that the following conditions
220 * are met:
221 *
222 * 1. Redistributions of source code must retain the above copyright
223 * notice, this list of conditions and the following disclaimer.
224 *
225 * 2. Redistributions in binary form must reproduce the above copyright
226 * notice, this list of conditions and the following disclaimer in
227 * the documentation and/or other materials provided with the
228 * distribution.
229 *
230 * 3. Neither the name of the author(s) nor the names of any contributors
231 * may be used to endorse or promote products derived from this software
232 * without specific prior written permission.
233 *
234 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
235 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
236 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
238 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
239 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
240 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
243 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244 * SUCH DAMAGE.
245 *
246 * ====================================================================
247 *
248 *
249 */
static const Data pad("\0\0\0\0\0\0\0", 7)
#define resip_assert(x)
This file needs to work for both C and C++ code.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Provides an interface to process and generate SDP bodies (MIME content-type application/sdp).
Represents a network address.
Definition Tuple.hxx:59
dcm! – add UnusedChecking(_enum) below;
void list()
Definition userAdmin.cxx:66