1 /* GStreamer
2  * Copyright (C) 2017 Matthew Waters <matthew@centricular.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23 
24 #include "gstwebrtcbin.h"
25 #include "utils.h"
26 #include "webrtctransceiver.h"
27 
28 #define webrtc_transceiver_parent_class parent_class
29 G_DEFINE_TYPE (WebRTCTransceiver, webrtc_transceiver,
30     GST_TYPE_WEBRTC_RTP_TRANSCEIVER);
31 
32 #define DEFAULT_FEC_TYPE GST_WEBRTC_FEC_TYPE_NONE
33 #define DEFAULT_DO_NACK FALSE
34 #define DEFAULT_FEC_PERCENTAGE 100
35 
36 enum
37 {
38   PROP_0,
39   PROP_WEBRTC,
40   PROP_FEC_TYPE,
41   PROP_FEC_PERCENTAGE,
42   PROP_DO_NACK,
43 };
44 
45 void
webrtc_transceiver_set_transport(WebRTCTransceiver * trans,TransportStream * stream)46 webrtc_transceiver_set_transport (WebRTCTransceiver * trans,
47     TransportStream * stream)
48 {
49   GstWebRTCRTPTransceiver *rtp_trans;
50 
51   g_return_if_fail (WEBRTC_IS_TRANSCEIVER (trans));
52 
53   rtp_trans = GST_WEBRTC_RTP_TRANSCEIVER (trans);
54 
55   gst_object_replace ((GstObject **) & trans->stream, (GstObject *) stream);
56 
57   if (rtp_trans->sender)
58     gst_object_replace ((GstObject **) & rtp_trans->sender->transport,
59         (GstObject *) stream->transport);
60   if (rtp_trans->receiver)
61     gst_object_replace ((GstObject **) & rtp_trans->receiver->transport,
62         (GstObject *) stream->transport);
63 
64   if (rtp_trans->sender)
65     gst_object_replace ((GstObject **) & rtp_trans->sender->rtcp_transport,
66         (GstObject *) stream->rtcp_transport);
67   if (rtp_trans->receiver)
68     gst_object_replace ((GstObject **) & rtp_trans->receiver->rtcp_transport,
69         (GstObject *) stream->rtcp_transport);
70 }
71 
72 GstWebRTCDTLSTransport *
webrtc_transceiver_get_dtls_transport(GstWebRTCRTPTransceiver * trans)73 webrtc_transceiver_get_dtls_transport (GstWebRTCRTPTransceiver * trans)
74 {
75   g_return_val_if_fail (WEBRTC_IS_TRANSCEIVER (trans), NULL);
76 
77   if (trans->sender) {
78     return trans->sender->transport;
79   } else if (trans->receiver) {
80     return trans->receiver->transport;
81   }
82 
83   return NULL;
84 }
85 
86 GstWebRTCDTLSTransport *
webrtc_transceiver_get_rtcp_dtls_transport(GstWebRTCRTPTransceiver * trans)87 webrtc_transceiver_get_rtcp_dtls_transport (GstWebRTCRTPTransceiver * trans)
88 {
89   g_return_val_if_fail (WEBRTC_IS_TRANSCEIVER (trans), NULL);
90 
91   if (trans->sender) {
92     return trans->sender->rtcp_transport;
93   } else if (trans->receiver) {
94     return trans->receiver->rtcp_transport;
95   }
96 
97   return NULL;
98 }
99 
100 static void
webrtc_transceiver_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)101 webrtc_transceiver_set_property (GObject * object, guint prop_id,
102     const GValue * value, GParamSpec * pspec)
103 {
104   WebRTCTransceiver *trans = WEBRTC_TRANSCEIVER (object);
105 
106   switch (prop_id) {
107     case PROP_WEBRTC:
108       gst_object_set_parent (GST_OBJECT (trans), g_value_get_object (value));
109       break;
110   }
111 
112   GST_OBJECT_LOCK (trans);
113   switch (prop_id) {
114     case PROP_WEBRTC:
115       break;
116     case PROP_FEC_TYPE:
117       trans->fec_type = g_value_get_enum (value);
118       break;
119     case PROP_DO_NACK:
120       trans->do_nack = g_value_get_boolean (value);
121       break;
122     case PROP_FEC_PERCENTAGE:
123       trans->fec_percentage = g_value_get_uint (value);
124       break;
125     default:
126       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
127       break;
128   }
129   GST_OBJECT_UNLOCK (trans);
130 }
131 
132 static void
webrtc_transceiver_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)133 webrtc_transceiver_get_property (GObject * object, guint prop_id,
134     GValue * value, GParamSpec * pspec)
135 {
136   WebRTCTransceiver *trans = WEBRTC_TRANSCEIVER (object);
137 
138   GST_OBJECT_LOCK (trans);
139   switch (prop_id) {
140     case PROP_FEC_TYPE:
141       g_value_set_enum (value, trans->fec_type);
142       break;
143     case PROP_DO_NACK:
144       g_value_set_boolean (value, trans->do_nack);
145       break;
146     case PROP_FEC_PERCENTAGE:
147       g_value_set_uint (value, trans->fec_percentage);
148       break;
149     default:
150       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
151       break;
152   }
153   GST_OBJECT_UNLOCK (trans);
154 }
155 
156 static void
webrtc_transceiver_finalize(GObject * object)157 webrtc_transceiver_finalize (GObject * object)
158 {
159   WebRTCTransceiver *trans = WEBRTC_TRANSCEIVER (object);
160 
161   if (trans->stream)
162     gst_object_unref (trans->stream);
163   trans->stream = NULL;
164 
165   if (trans->local_rtx_ssrc_map)
166     gst_structure_free (trans->local_rtx_ssrc_map);
167   trans->local_rtx_ssrc_map = NULL;
168 
169   G_OBJECT_CLASS (parent_class)->finalize (object);
170 }
171 
172 static void
webrtc_transceiver_class_init(WebRTCTransceiverClass * klass)173 webrtc_transceiver_class_init (WebRTCTransceiverClass * klass)
174 {
175   GObjectClass *gobject_class = (GObjectClass *) klass;
176 
177   gobject_class->get_property = webrtc_transceiver_get_property;
178   gobject_class->set_property = webrtc_transceiver_set_property;
179   gobject_class->finalize = webrtc_transceiver_finalize;
180 
181   /* some acrobatics are required to set the parent before _constructed()
182    * has been called */
183   g_object_class_install_property (gobject_class,
184       PROP_WEBRTC,
185       g_param_spec_object ("webrtc", "Parent webrtcbin",
186           "Parent webrtcbin",
187           GST_TYPE_WEBRTC_BIN,
188           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
189 
190   g_object_class_install_property (gobject_class,
191       PROP_FEC_TYPE,
192       g_param_spec_enum ("fec-type", "FEC type",
193           "The type of Forward Error Correction to use",
194           GST_TYPE_WEBRTC_FEC_TYPE,
195           DEFAULT_FEC_TYPE,
196           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
197 
198   g_object_class_install_property (gobject_class,
199       PROP_DO_NACK,
200       g_param_spec_boolean ("do-nack", "Do nack",
201           "Whether to send negative acknowledgements for feedback",
202           DEFAULT_DO_NACK,
203           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
204 
205   g_object_class_install_property (gobject_class,
206       PROP_FEC_PERCENTAGE,
207       g_param_spec_uint ("fec-percentage", "FEC percentage",
208           "The amount of Forward Error Correction to apply",
209           0, 100, DEFAULT_FEC_PERCENTAGE,
210           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
211 }
212 
213 static void
webrtc_transceiver_init(WebRTCTransceiver * trans)214 webrtc_transceiver_init (WebRTCTransceiver * trans)
215 {
216 }
217 
218 WebRTCTransceiver *
webrtc_transceiver_new(GstWebRTCBin * webrtc,GstWebRTCRTPSender * sender,GstWebRTCRTPReceiver * receiver)219 webrtc_transceiver_new (GstWebRTCBin * webrtc, GstWebRTCRTPSender * sender,
220     GstWebRTCRTPReceiver * receiver)
221 {
222   WebRTCTransceiver *trans;
223 
224   trans = g_object_new (webrtc_transceiver_get_type (), "sender", sender,
225       "receiver", receiver, "webrtc", webrtc, NULL);
226 
227   return trans;
228 }
229