2 * GStreamer - GStreamer SRTP encoder
4 * Copyright 2009-2011 Collabora Ltd.
5 * @author: Gabriel Millaire <gabriel.millaire@collabora.com>
6 * @author: Olivier Crete <olivier.crete@collabora.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * Alternatively, the contents of this file may be used under the
27 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
28 * which case the following provisions apply instead of the ones
31 * This library is free software; you can redistribute it and/or
32 * modify it under the terms of the GNU Library General Public
33 * License as published by the Free Software Foundation; either
34 * version 2 of the License, or (at your option) any later version.
36 * This library is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 * Library General Public License for more details.
41 * You should have received a copy of the GNU Library General Public
42 * License along with this library; if not, write to the
43 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
44 * Boston, MA 02111-1307, USA.
48 * SECTION:element-srtpenc
52 * gstrtpenc acts as an encoder that adds security to RTP and RTCP
53 * packets in the form of encryption and authentication. It outs SRTP
56 * An application can request multiple RTP and RTCP pads to protect,
57 * but every sink pad requested must receive packets from the same
58 * source (identical SSRC). If a packet received contains a different
59 * SSRC, a warning is emited and the valid SSRC is forced on the packet.
61 * This element uses libsrtp library. When receiving the first packet,
62 * the library is initialized with a new stream (based on the SSRC). It
63 * uses the default RTP and RTCP encryption and authentication mechanisms,
64 * unless the user has set the relevant properties first. It also uses
65 * a master key that MUST be set by property (key) at the beginning. The
66 * master key must be of a maximum length of 46 characters (14 characters
67 * for the salt plus the key). The encryption and authentication mechanisms
70 * Encryption (properties rtp-cipher and rtcp-cipher)
71 * - AES_ICM 256 bits (maximum security)
72 * - AES_ICM 128 bits (default)
75 * Authentication (properties rtp-auth and rtcp-auth)
76 * - HMAC_SHA1 80 bits (default, maximum protection)
80 * Note that for SRTP protection, authentication is mandatory (non-null)
81 * if encryption is used (non-null).
83 * When requested to create a sink pad, a linked source pad is created.
84 * Each packet received is first analysed (checked for valid SSRC) then
85 * its buffer is protected with libsrtp, then pushed on the source pad.
86 * If protection failed or the stream could not be created, the buffer
87 * is dropped and a warning is emitted. The packets pushed on the source
88 * pad are of type 'application/x-srtp' or 'application/x-srtcp'.
90 * When the maximum usage of the master key is reached, a soft-limit
91 * signal is sent to the user. The user must then set a new master key
92 * by property. If the hard limit is reached, a flag is set and every
93 * subsequent packet is dropped, until a new key is set and the stream
96 * If a stream is to be shared between multiple clients it is also
97 * possible to request the internal SRTP rollover counter for a given
98 * SSRC. The rollover counter should be then transmitted and used by the
99 * clients to authenticate and decrypt the packets. Failing to do that
100 * the clients will start with a rollover counter of 0 which will
101 * probably be incorrect if the stream has been transmitted for a
102 * while to other clients.
104 * This element supports sending with a single Master Key, it is possible to set the
105 * Master Key Identifier (MKI) using the "mki" property. If this property is set, the MKI
106 * will be added to every buffer.
109 #include "gstsrtpenc.h"
111 #include <gst/rtp/gstrtpbuffer.h>
112 #include <gst/rtp/gstrtcpbuffer.h>
116 GST_DEBUG_CATEGORY_STATIC (gst_srtp_enc_debug);
117 #define GST_CAT_DEFAULT gst_srtp_enc_debug
119 /* 128 bit key size: 14 (salt) + 16 */
120 #define MASTER_128_KEY_SIZE 30
122 /* 256 bit key size: 14 (salt) + 16 + 16 */
123 #define MASTER_256_KEY_SIZE 46
125 /* Properties default values */
126 #define DEFAULT_MASTER_KEY NULL
127 #define DEFAULT_RTP_CIPHER GST_SRTP_CIPHER_AES_128_ICM
128 #define DEFAULT_RTP_AUTH GST_SRTP_AUTH_HMAC_SHA1_80
129 #define DEFAULT_RTCP_CIPHER DEFAULT_RTP_CIPHER
130 #define DEFAULT_RTCP_AUTH DEFAULT_RTP_AUTH
131 #define DEFAULT_RANDOM_KEY FALSE
132 #define DEFAULT_REPLAY_WINDOW_SIZE 128
133 #define DEFAULT_ALLOW_REPEAT_TX FALSE
135 #define HAS_CRYPTO(filter) (filter->rtp_cipher != GST_SRTP_CIPHER_NULL || \
136 filter->rtcp_cipher != GST_SRTP_CIPHER_NULL || \
137 filter->rtp_auth != GST_SRTP_AUTH_NULL || \
138 filter->rtcp_auth != GST_SRTP_AUTH_NULL)
140 /* Filter signals and args */
144 SIGNAL_GET_ROLLOVER_COUNTER,
157 PROP_REPLAY_WINDOW_SIZE,
158 PROP_ALLOW_REPEAT_TX,
163 typedef struct ProcessBufferItData
167 GstBufferList *out_list;
168 GstFlowReturn flowret;
170 } ProcessBufferItData;
172 /* the capabilities of the inputs and outputs.
174 * describe the real formats here.
176 static GstStaticPadTemplate rtp_sink_template =
177 GST_STATIC_PAD_TEMPLATE ("rtp_sink_%u",
180 GST_STATIC_CAPS ("application/x-rtp")
183 static GstStaticPadTemplate rtp_src_template =
184 GST_STATIC_PAD_TEMPLATE ("rtp_src_%u",
187 GST_STATIC_CAPS ("application/x-srtp")
190 static GstStaticPadTemplate rtcp_sink_template =
191 GST_STATIC_PAD_TEMPLATE ("rtcp_sink_%u",
194 GST_STATIC_CAPS ("application/x-rtcp")
197 static GstStaticPadTemplate rtcp_src_template =
198 GST_STATIC_PAD_TEMPLATE ("rtcp_src_%u",
201 GST_STATIC_CAPS ("application/x-srtcp")
204 G_DEFINE_TYPE (GstSrtpEnc, gst_srtp_enc, GST_TYPE_ELEMENT);
206 static guint gst_srtp_enc_signals[LAST_SIGNAL] = { 0 };
208 static void gst_srtp_enc_dispose (GObject * object);
210 static void gst_srtp_enc_set_property (GObject * object, guint prop_id,
211 const GValue * value, GParamSpec * pspec);
212 static void gst_srtp_enc_get_property (GObject * object, guint prop_id,
213 GValue * value, GParamSpec * pspec);
215 static gboolean gst_srtp_enc_sink_query_rtp (GstPad * pad, GstObject * parent,
217 static gboolean gst_srtp_enc_sink_query_rtcp (GstPad * pad, GstObject * parent,
220 static GstIterator *gst_srtp_enc_iterate_internal_links_rtp (GstPad * pad,
222 static GstIterator *gst_srtp_enc_iterate_internal_links_rtcp (GstPad * pad,
225 static GstFlowReturn gst_srtp_enc_chain_rtp (GstPad * pad, GstObject * parent,
227 static GstFlowReturn gst_srtp_enc_chain_rtcp (GstPad * pad, GstObject * parent,
229 static GstFlowReturn gst_srtp_enc_chain_list_rtp (GstPad * pad,
230 GstObject * parent, GstBufferList * buf);
231 static GstFlowReturn gst_srtp_enc_chain_list_rtcp (GstPad * pad,
232 GstObject * parent, GstBufferList * buf);
234 static gboolean gst_srtp_enc_sink_event_rtp (GstPad * pad, GstObject * parent,
236 static gboolean gst_srtp_enc_sink_event_rtcp (GstPad * pad, GstObject * parent,
239 static GstStateChangeReturn gst_srtp_enc_change_state (GstElement * element,
240 GstStateChange transition);
242 static GstPad *gst_srtp_enc_request_new_pad (GstElement * element,
243 GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
245 static void gst_srtp_enc_release_pad (GstElement * element, GstPad * pad);
248 /* initialize the srtpenc's class
251 gst_srtp_enc_class_init (GstSrtpEncClass * klass)
253 GObjectClass *gobject_class;
254 GstElementClass *gstelement_class;
256 gobject_class = (GObjectClass *) klass;
257 gstelement_class = (GstElementClass *) klass;
259 gst_element_class_add_static_pad_template (gstelement_class,
261 gst_element_class_add_static_pad_template (gstelement_class,
263 gst_element_class_add_static_pad_template (gstelement_class,
265 gst_element_class_add_static_pad_template (gstelement_class,
266 &rtcp_sink_template);
268 gst_element_class_set_static_metadata (gstelement_class, "SRTP encoder",
269 "Filter/Network/SRTP",
270 "A SRTP and SRTCP encoder",
271 "Gabriel Millaire <millaire.gabriel@collabora.com>");
274 /* Install callbacks */
275 gobject_class->set_property = gst_srtp_enc_set_property;
276 gobject_class->get_property = gst_srtp_enc_get_property;
277 gobject_class->dispose = gst_srtp_enc_dispose;
278 gstelement_class->request_new_pad =
279 GST_DEBUG_FUNCPTR (gst_srtp_enc_request_new_pad);
280 gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_srtp_enc_release_pad);
281 gstelement_class->change_state =
282 GST_DEBUG_FUNCPTR (gst_srtp_enc_change_state);
284 /* Install properties */
285 g_object_class_install_property (gobject_class, PROP_MKEY,
286 g_param_spec_boxed ("key", "Key", "Master key (minimum of "
287 G_STRINGIFY (MASTER_128_KEY_SIZE) " and maximum of "
288 G_STRINGIFY (MASTER_256_KEY_SIZE) " bytes)",
289 GST_TYPE_BUFFER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
290 GST_PARAM_MUTABLE_PLAYING));
291 g_object_class_install_property (gobject_class, PROP_RTP_CIPHER,
292 g_param_spec_enum ("rtp-cipher", "RTP Cipher", "RTP Cipher",
293 GST_TYPE_SRTP_CIPHER_TYPE, DEFAULT_RTP_CIPHER,
294 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
295 g_object_class_install_property (gobject_class, PROP_RTP_AUTH,
296 g_param_spec_enum ("rtp-auth", "RTP Authentication",
297 "RTP Authentication", GST_TYPE_SRTP_AUTH_TYPE, DEFAULT_RTP_AUTH,
298 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
299 g_object_class_install_property (gobject_class, PROP_RTCP_CIPHER,
300 g_param_spec_enum ("rtcp-cipher", "RTCP Cipher",
301 "RTCP Cipher", GST_TYPE_SRTP_CIPHER_TYPE, DEFAULT_RTCP_CIPHER,
302 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
303 g_object_class_install_property (gobject_class, PROP_RTCP_AUTH,
304 g_param_spec_enum ("rtcp-auth", "RTCP Authentication",
305 "RTCP Authentication", GST_TYPE_SRTP_AUTH_TYPE, DEFAULT_RTCP_AUTH,
306 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
307 g_object_class_install_property (gobject_class, PROP_RANDOM_KEY,
308 g_param_spec_boolean ("random-key", "Generate random key",
309 "Generate a random key if TRUE",
310 DEFAULT_RANDOM_KEY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
311 g_object_class_install_property (gobject_class, PROP_REPLAY_WINDOW_SIZE,
312 g_param_spec_uint ("replay-window-size", "Replay window size",
313 "Size of the replay protection window",
314 64, 0x8000, DEFAULT_REPLAY_WINDOW_SIZE,
315 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
316 g_object_class_install_property (gobject_class, PROP_ALLOW_REPEAT_TX,
317 g_param_spec_boolean ("allow-repeat-tx",
318 "Allow repeat packets transmission",
319 "Whether retransmissions of packets with the same sequence number are allowed"
320 "(Note that such repeated transmissions must have the same RTP payload, "
321 "or a severe security weakness is introduced!)",
322 DEFAULT_ALLOW_REPEAT_TX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
323 g_object_class_install_property (gobject_class, PROP_STATS,
324 g_param_spec_boxed ("stats", "Statistics", "Various statistics",
325 GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
327 g_object_class_install_property (gobject_class, PROP_MKI,
328 g_param_spec_boxed ("mki", "MKI",
329 "Master key Identifier (NULL means no MKI)", GST_TYPE_BUFFER,
330 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
331 GST_PARAM_MUTABLE_PLAYING));
335 * GstSrtpEnc::soft-limit:
336 * @gstsrtpenc: the element on which the signal is emitted
338 * Signal emited when the stream with @ssrc has reached the soft
339 * limit of utilisation of it's master encryption key. User should
340 * provide a new key by setting the #GstSrtpEnc:key property.
342 gst_srtp_enc_signals[SIGNAL_SOFT_LIMIT] =
343 g_signal_new ("soft-limit", G_TYPE_FROM_CLASS (klass),
344 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
348 /* initialize the new element
351 gst_srtp_enc_init (GstSrtpEnc * filter)
353 filter->key_changed = TRUE;
354 filter->first_session = TRUE;
355 filter->key = DEFAULT_MASTER_KEY;
356 filter->rtp_cipher = DEFAULT_RTP_CIPHER;
357 filter->rtp_auth = DEFAULT_RTP_AUTH;
358 filter->rtcp_cipher = DEFAULT_RTCP_CIPHER;
359 filter->rtcp_auth = DEFAULT_RTCP_AUTH;
360 filter->replay_window_size = DEFAULT_REPLAY_WINDOW_SIZE;
361 filter->allow_repeat_tx = DEFAULT_ALLOW_REPEAT_TX;
362 filter->ssrcs_set = g_hash_table_new (g_direct_hash, g_direct_equal);
366 max_cipher_key_size (GstSrtpEnc * filter)
368 guint rtp_size, rtcp_size;
370 rtp_size = cipher_key_size (filter->rtp_cipher);
371 rtcp_size = cipher_key_size (filter->rtcp_cipher);
373 return (rtp_size > rtcp_size) ? rtp_size : rtcp_size;
378 * Should be called with the filter locked
380 static srtp_err_status_t
381 gst_srtp_enc_create_session (GstSrtpEnc * filter)
383 srtp_err_status_t ret;
384 srtp_policy_t policy;
388 srtp_master_key_t mkey;
389 srtp_master_key_t *mkey_ptr = &mkey;
390 gboolean has_mki = FALSE;
394 memset (&policy, 0, sizeof (srtp_policy_t));
396 if (HAS_CRYPTO (filter)) {
400 if (filter->key == NULL) {
401 GST_OBJECT_UNLOCK (filter);
402 GST_ELEMENT_ERROR (filter, LIBRARY, SETTINGS,
403 ("Cipher is not NULL, key must be set"),
404 ("Cipher is not NULL, key must be set"));
405 GST_OBJECT_LOCK (filter);
406 return srtp_err_status_fail;
409 expected = max_cipher_key_size (filter);
410 keysize = gst_buffer_get_size (filter->key);
412 if (expected != keysize) {
413 GST_OBJECT_UNLOCK (filter);
414 GST_ELEMENT_ERROR (filter, LIBRARY, SETTINGS,
415 ("Master key size is wrong"),
416 ("Expected master key of %d bytes, but received %" G_GSIZE_FORMAT
417 " bytes", expected, keysize));
418 GST_OBJECT_LOCK (filter);
419 return srtp_err_status_fail;
423 GST_DEBUG_OBJECT (filter, "Setting RTP/RTCP policy to %d / %d",
424 filter->rtp_cipher, filter->rtcp_cipher);
425 set_crypto_policy_cipher_auth (filter->rtp_cipher, filter->rtp_auth,
427 set_crypto_policy_cipher_auth (filter->rtcp_cipher, filter->rtcp_auth,
430 if (HAS_CRYPTO (filter)) {
431 gst_buffer_map (filter->key, &map, GST_MAP_READ);
432 policy.key = (guchar *) map.data;
439 if (!gst_buffer_map (filter->mki, &mki_map, GST_MAP_READ)) {
440 GST_OBJECT_UNLOCK (filter);
441 GST_ELEMENT_ERROR (filter, LIBRARY, SETTINGS, ("Could not map MKI"),
443 GST_OBJECT_LOCK (filter);
445 ret = srtp_err_status_fail;
450 policy.num_master_keys = 1;
451 policy.keys = &mkey_ptr;
452 mkey.key = policy.key;
455 mkey.mki_id = (guchar *) mki_map.data;
456 mkey.mki_size = mki_map.size;
460 policy.ssrc.value = 0;
461 policy.ssrc.type = ssrc_any_outbound;
464 policy.window_size = filter->replay_window_size;
465 policy.allow_repeat_tx = filter->allow_repeat_tx;
467 /* If it is the first stream, create the session
468 * If not, add the stream to the session
470 ret = srtp_create (&filter->session, &policy);
471 filter->first_session = FALSE;
477 gst_buffer_unmap (filter->mki, &mki_map);
480 if (HAS_CRYPTO (filter))
481 gst_buffer_unmap (filter->key, &map);
487 /* Release ressources and set default values
490 gst_srtp_enc_reset_no_lock (GstSrtpEnc * filter)
492 if (!filter->first_session) {
493 if (filter->session) {
494 srtp_dealloc (filter->session);
495 filter->session = NULL;
498 g_hash_table_remove_all (filter->ssrcs_set);
501 filter->first_session = TRUE;
502 filter->key_changed = FALSE;
506 gst_srtp_enc_reset (GstSrtpEnc * filter)
508 GST_OBJECT_LOCK (filter);
509 gst_srtp_enc_reset_no_lock (filter);
510 GST_OBJECT_UNLOCK (filter);
513 /* Create sinkpad to receive RTP packets from encers
514 * and a srcpad for the RTP packets
517 create_rtp_sink (GstSrtpEnc * filter, const gchar * name)
519 GstPad *sinkpad, *srcpad;
520 gchar *sinkpadname, *srcpadname;
523 GST_DEBUG_OBJECT (filter, "creating RTP sink pad");
524 sinkpad = gst_pad_new_from_static_template (&rtp_sink_template, name);
526 sinkpadname = gst_pad_get_name (sinkpad);
527 sscanf (sinkpadname, "rtp_sink_%u", &nb);
528 srcpadname = g_strdup_printf ("rtp_src_%u", nb);
530 GST_DEBUG_OBJECT (filter, "creating RTP source pad");
531 srcpad = gst_pad_new_from_static_template (&rtp_src_template, srcpadname);
533 g_free (sinkpadname);
535 gst_pad_set_element_private (sinkpad, srcpad);
536 gst_pad_set_element_private (srcpad, sinkpad);
538 gst_pad_set_query_function (sinkpad,
539 GST_DEBUG_FUNCPTR (gst_srtp_enc_sink_query_rtp));
540 gst_pad_set_iterate_internal_links_function (sinkpad,
541 GST_DEBUG_FUNCPTR (gst_srtp_enc_iterate_internal_links_rtp));
542 gst_pad_set_chain_function (sinkpad,
543 GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_rtp));
544 gst_pad_set_chain_list_function (sinkpad,
545 GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_list_rtp));
546 gst_pad_set_event_function (sinkpad,
547 GST_DEBUG_FUNCPTR (gst_srtp_enc_sink_event_rtp));
548 gst_pad_set_active (sinkpad, TRUE);
549 gst_element_add_pad (GST_ELEMENT_CAST (filter), sinkpad);
551 gst_pad_set_iterate_internal_links_function (srcpad,
552 GST_DEBUG_FUNCPTR (gst_srtp_enc_iterate_internal_links_rtp));
553 gst_pad_set_active (srcpad, TRUE);
554 gst_element_add_pad (GST_ELEMENT_CAST (filter), srcpad);
559 /* Create sinkpad to receive RTCP packets from encers
560 * and a srcpad for the RTCP packets
563 create_rtcp_sink (GstSrtpEnc * filter, const gchar * name)
565 GstPad *srcpad, *sinkpad;
566 gchar *sinkpadname, *srcpadname;
569 GST_DEBUG_OBJECT (filter, "creating RTCP sink pad");
570 sinkpad = gst_pad_new_from_static_template (&rtcp_sink_template, name);
572 sinkpadname = gst_pad_get_name (sinkpad);
573 sscanf (sinkpadname, "rtcp_sink_%u", &nb);
574 srcpadname = g_strdup_printf ("rtcp_src_%u", nb);
576 GST_DEBUG_OBJECT (filter, "creating RTCP source pad");
577 srcpad = gst_pad_new_from_static_template (&rtcp_src_template, srcpadname);
579 g_free (sinkpadname);
581 gst_pad_set_element_private (sinkpad, srcpad);
582 gst_pad_set_element_private (srcpad, sinkpad);
584 gst_pad_set_query_function (sinkpad,
585 GST_DEBUG_FUNCPTR (gst_srtp_enc_sink_query_rtcp));
586 gst_pad_set_iterate_internal_links_function (sinkpad,
587 GST_DEBUG_FUNCPTR (gst_srtp_enc_iterate_internal_links_rtcp));
588 gst_pad_set_chain_function (sinkpad,
589 GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_rtcp));
590 gst_pad_set_chain_list_function (sinkpad,
591 GST_DEBUG_FUNCPTR (gst_srtp_enc_chain_list_rtcp));
592 gst_pad_set_event_function (sinkpad,
593 GST_DEBUG_FUNCPTR (gst_srtp_enc_sink_event_rtcp));
594 gst_pad_set_active (sinkpad, TRUE);
595 gst_element_add_pad (GST_ELEMENT_CAST (filter), sinkpad);
597 gst_pad_set_iterate_internal_links_function (srcpad,
598 GST_DEBUG_FUNCPTR (gst_srtp_enc_iterate_internal_links_rtcp));
599 gst_pad_set_active (srcpad, TRUE);
600 gst_element_add_pad (GST_ELEMENT_CAST (filter), srcpad);
605 /* Handling new pad request
608 gst_srtp_enc_request_new_pad (GstElement * element,
609 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
611 GstElementClass *klass;
614 filter = GST_SRTP_ENC (element);
615 klass = GST_ELEMENT_GET_CLASS (element);
617 GST_INFO_OBJECT (element, "New pad requested");
619 if (templ == gst_element_class_get_pad_template (klass, "rtp_sink_%u"))
620 return create_rtp_sink (filter, name);
622 if (templ == gst_element_class_get_pad_template (klass, "rtcp_sink_%u"))
623 return create_rtcp_sink (filter, name);
625 GST_ERROR_OBJECT (element, "Could not find specified template");
632 gst_srtp_enc_dispose (GObject * object)
634 GstSrtpEnc *filter = GST_SRTP_ENC (object);
638 GST_DEBUG_OBJECT (object, "Dispose...");
640 it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (object));
641 while (gst_iterator_next (it, &val) == GST_ITERATOR_OK) {
642 gst_srtp_enc_release_pad (GST_ELEMENT_CAST (object),
643 g_value_get_object (&val));
644 g_value_unset (&val);
645 gst_iterator_resync (it);
647 gst_iterator_free (it);
649 gst_buffer_replace (&filter->key, NULL);
650 gst_buffer_replace (&filter->mki, NULL);
652 if (filter->ssrcs_set)
653 g_hash_table_unref (filter->ssrcs_set);
654 filter->ssrcs_set = NULL;
656 G_OBJECT_CLASS (gst_srtp_enc_parent_class)->dispose (object);
659 static GstStructure *
660 gst_srtp_enc_create_stats (GstSrtpEnc * filter)
663 GValue va = G_VALUE_INIT;
664 GValue v = G_VALUE_INIT;
666 s = gst_structure_new_empty ("application/x-srtp-encoder-stats");
668 g_value_init (&va, GST_TYPE_ARRAY);
669 g_value_init (&v, GST_TYPE_STRUCTURE);
671 if (filter->session) {
675 g_hash_table_iter_init (&iter, filter->ssrcs_set);
676 while (g_hash_table_iter_next (&iter, &key, NULL)) {
678 guint32 ssrc = GPOINTER_TO_UINT (key);
679 srtp_err_status_t status;
682 status = srtp_get_stream_roc (filter->session, ssrc, &roc);
683 if (status != srtp_err_status_ok) {
687 ss = gst_structure_new ("application/x-srtp-stream",
688 "ssrc", G_TYPE_UINT, ssrc, "roc", G_TYPE_UINT, roc, NULL);
690 g_value_take_boxed (&v, ss);
691 gst_value_array_append_value (&va, &v);
695 gst_structure_take_value (s, "streams", &va);
702 gst_srtp_enc_set_property (GObject * object, guint prop_id,
703 const GValue * value, GParamSpec * pspec)
705 GstSrtpEnc *filter = GST_SRTP_ENC (object);
707 GST_OBJECT_LOCK (filter);
711 gst_clear_buffer (&filter->key);
712 filter->key = g_value_dup_boxed (value);
713 filter->key_changed = TRUE;
714 GST_INFO_OBJECT (object, "Set property: key=[%p]", filter->key);
717 case PROP_RTP_CIPHER:
718 filter->rtp_cipher = g_value_get_enum (value);
719 GST_INFO_OBJECT (object, "Set property: rtp cipher=%d",
723 filter->rtp_auth = g_value_get_enum (value);
724 GST_INFO_OBJECT (object, "Set property: rtp auth=%d", filter->rtp_auth);
727 case PROP_RTCP_CIPHER:
728 filter->rtcp_cipher = g_value_get_enum (value);
729 GST_INFO_OBJECT (object, "Set property: rtcp cipher=%d",
730 filter->rtcp_cipher);
734 filter->rtcp_auth = g_value_get_enum (value);
735 GST_INFO_OBJECT (object, "Set property: rtcp auth=%d", filter->rtcp_auth);
738 case PROP_RANDOM_KEY:
739 filter->random_key = g_value_get_boolean (value);
742 case PROP_REPLAY_WINDOW_SIZE:
743 filter->replay_window_size = g_value_get_uint (value);
746 case PROP_ALLOW_REPEAT_TX:
747 filter->allow_repeat_tx = g_value_get_boolean (value);
751 gst_clear_buffer (&filter->mki);
752 filter->mki = g_value_dup_boxed (value);
753 filter->key_changed = TRUE;
754 GST_INFO_OBJECT (object, "Set property: mki=[%p]", filter->mki);
758 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
762 GST_OBJECT_UNLOCK (filter);
766 gst_srtp_enc_get_property (GObject * object, guint prop_id,
767 GValue * value, GParamSpec * pspec)
769 GstSrtpEnc *filter = GST_SRTP_ENC (object);
770 GST_OBJECT_LOCK (filter);
775 g_value_set_boxed (value, filter->key);
777 case PROP_RTP_CIPHER:
778 g_value_set_enum (value, filter->rtp_cipher);
780 case PROP_RTCP_CIPHER:
781 g_value_set_enum (value, filter->rtcp_cipher);
784 g_value_set_enum (value, filter->rtp_auth);
787 g_value_set_enum (value, filter->rtcp_auth);
789 case PROP_RANDOM_KEY:
790 g_value_set_boolean (value, filter->random_key);
792 case PROP_REPLAY_WINDOW_SIZE:
793 g_value_set_uint (value, filter->replay_window_size);
795 case PROP_ALLOW_REPEAT_TX:
796 g_value_set_boolean (value, filter->allow_repeat_tx);
799 g_value_take_boxed (value, gst_srtp_enc_create_stats (filter));
804 g_value_set_boxed (value, filter->mki);
808 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
812 GST_OBJECT_UNLOCK (filter);
815 /* Returns the source pad linked with the sink pad
818 get_rtp_other_pad (GstPad * pad)
820 return GST_PAD (gst_pad_get_element_private (pad));
824 gst_srtp_enc_add_ssrc (GstSrtpEnc * filter, guint ssrc)
827 g_hash_table_add (filter->ssrcs_set, GUINT_TO_POINTER (ssrc));
829 GST_DEBUG_OBJECT (filter, "Added ssrc %u", ssrc);
833 /* Release a sink pad and it's linked source pad
836 gst_srtp_enc_release_pad (GstElement * element, GstPad * sinkpad)
840 GST_INFO_OBJECT (element, "Releasing pad %s:%s",
841 GST_DEBUG_PAD_NAME (sinkpad));
843 srcpad = GST_PAD (gst_pad_get_element_private (sinkpad));
844 gst_pad_set_element_private (sinkpad, NULL);
845 gst_pad_set_element_private (srcpad, NULL);
847 /* deactivate from source to sink */
848 gst_pad_set_active (srcpad, FALSE);
849 gst_pad_set_active (sinkpad, FALSE);
852 gst_element_remove_pad (element, srcpad);
853 gst_element_remove_pad (element, sinkpad);
856 /* Common setcaps function
857 * Handles the link with other elements
860 gst_srtp_enc_sink_setcaps (GstPad * pad, GstSrtpEnc * filter,
861 GstCaps * caps, gboolean is_rtcp)
863 GstPad *otherpad = NULL;
864 GstStructure *ps = NULL;
865 gboolean ret = FALSE;
867 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
869 caps = gst_caps_copy (caps);
871 ps = gst_caps_get_structure (caps, 0);
873 GST_DEBUG_OBJECT (pad, "Sink caps: %" GST_PTR_FORMAT, caps);
876 gst_structure_set_name (ps, "application/x-srtcp");
878 gst_structure_set_name (ps, "application/x-srtp");
880 GST_OBJECT_LOCK (filter);
882 if (gst_structure_has_field_typed (ps, "ssrc", G_TYPE_UINT)) {
884 gst_structure_get_uint (ps, "ssrc", &ssrc);
885 gst_srtp_enc_add_ssrc (filter, ssrc);
888 if (HAS_CRYPTO (filter))
889 gst_structure_set (ps, "srtp-key", GST_TYPE_BUFFER, filter->key, NULL);
893 gst_structure_set (ps, "mki", GST_TYPE_BUFFER, filter->mki, NULL);
896 /* Add srtp-specific params to source caps */
897 gst_structure_set (ps,
898 "srtp-cipher", G_TYPE_STRING,
899 enum_nick_from_value (GST_TYPE_SRTP_CIPHER_TYPE, filter->rtp_cipher),
900 "srtp-auth", G_TYPE_STRING,
901 enum_nick_from_value (GST_TYPE_SRTP_AUTH_TYPE, filter->rtp_auth),
902 "srtcp-cipher", G_TYPE_STRING,
903 enum_nick_from_value (GST_TYPE_SRTP_CIPHER_TYPE, filter->rtcp_cipher),
904 "srtcp-auth", G_TYPE_STRING,
905 enum_nick_from_value (GST_TYPE_SRTP_AUTH_TYPE, filter->rtcp_auth), NULL);
907 GST_OBJECT_UNLOCK (filter);
909 GST_DEBUG_OBJECT (pad, "Source caps: %" GST_PTR_FORMAT, caps);
911 /* Set caps on source pad */
912 otherpad = get_rtp_other_pad (pad);
914 ret = gst_pad_set_caps (otherpad, caps);
916 gst_caps_unref (caps);
922 gst_srtp_enc_sink_query (GstPad * pad, GstObject * parent, GstQuery * query,
925 switch (GST_QUERY_TYPE (query)) {
928 GstCaps *filter = NULL;
929 GstCaps *other_filter = NULL;
933 GstCaps *template_caps;
936 otherpad = get_rtp_other_pad (pad);
938 gst_query_parse_caps (query, &filter);
940 other_filter = gst_caps_copy (filter);
942 for (i = 0; i < gst_caps_get_size (other_filter); i++) {
943 GstStructure *ps = gst_caps_get_structure (other_filter, i);
945 gst_structure_set_name (ps, "application/x-srtcp");
947 gst_structure_set_name (ps, "application/x-srtp");
951 other_caps = gst_pad_peer_query_caps (otherpad, other_filter);
954 gst_caps_unref (other_filter);
957 goto return_template;
959 template_caps = gst_pad_get_pad_template_caps (otherpad);
960 ret = gst_caps_intersect_full (other_caps, template_caps,
961 GST_CAPS_INTERSECT_FIRST);
962 gst_caps_unref (other_caps);
963 gst_caps_unref (template_caps);
965 ret = gst_caps_make_writable (ret);
967 for (i = 0; i < gst_caps_get_size (ret); i++) {
968 GstStructure *ps = gst_caps_get_structure (ret, i);
970 gst_structure_set_name (ps, "application/x-rtcp");
972 gst_structure_set_name (ps, "application/x-rtp");
973 gst_structure_remove_fields (ps, "srtp-key", "srtp-cipher", "srtp-auth",
974 "srtcp-cipher", "srtcp-auth", "mki", NULL);
977 gst_query_set_caps_result (query, ret);
978 gst_caps_unref (ret);
982 ret = gst_pad_get_pad_template_caps (pad);
983 gst_query_set_caps_result (query, ret);
984 gst_caps_unref (ret);
989 return gst_pad_query_default (pad, parent, query);
994 gst_srtp_enc_sink_query_rtp (GstPad * pad, GstObject * parent, GstQuery * query)
996 return gst_srtp_enc_sink_query (pad, parent, query, FALSE);
1000 gst_srtp_enc_sink_query_rtcp (GstPad * pad, GstObject * parent,
1003 return gst_srtp_enc_sink_query (pad, parent, query, TRUE);
1006 static GstIterator *
1007 gst_srtp_enc_iterate_internal_links (GstPad * pad, GstObject * parent,
1010 GstSrtpEnc *filter = GST_SRTP_ENC (parent);
1011 GstPad *otherpad = NULL;
1012 GstIterator *it = NULL;
1014 otherpad = get_rtp_other_pad (pad);
1019 g_value_init (&val, GST_TYPE_PAD);
1020 g_value_set_object (&val, otherpad);
1021 it = gst_iterator_new_single (GST_TYPE_PAD, &val);
1022 g_value_unset (&val);
1024 GST_ELEMENT_ERROR (GST_ELEMENT_CAST (filter), CORE, PAD, (NULL),
1025 ("Unable to get linked pad"));
1031 static GstIterator *
1032 gst_srtp_enc_iterate_internal_links_rtp (GstPad * pad, GstObject * parent)
1034 return gst_srtp_enc_iterate_internal_links (pad, parent, FALSE);
1037 static GstIterator *
1038 gst_srtp_enc_iterate_internal_links_rtcp (GstPad * pad, GstObject * parent)
1040 return gst_srtp_enc_iterate_internal_links (pad, parent, TRUE);
1045 gst_srtp_enc_replace_random_key (GstSrtpEnc * filter)
1051 GST_DEBUG_OBJECT (filter, "Generating random key");
1054 gst_buffer_unref (filter->key);
1056 key_size = max_cipher_key_size (filter);
1058 filter->key = gst_buffer_new_allocate (NULL, key_size, NULL);
1060 gst_buffer_map (filter->key, &map, GST_MAP_WRITE);
1061 for (i = 0; i < map.size; i += 4)
1062 GST_WRITE_UINT32_BE (map.data + i, g_random_int ());
1063 gst_buffer_unmap (filter->key, &map);
1065 filter->key_changed = TRUE;
1068 static GstFlowReturn
1069 gst_srtp_enc_check_set_caps (GstSrtpEnc * filter, GstPad * pad,
1072 gboolean do_setcaps = FALSE;
1074 GST_OBJECT_LOCK (filter);
1076 if (filter->key_changed) {
1077 gst_srtp_enc_reset_no_lock (filter);
1081 if (filter->first_session) {
1082 srtp_err_status_t status = gst_srtp_enc_create_session (filter);
1084 if (status != srtp_err_status_ok) {
1085 GST_OBJECT_UNLOCK (filter);
1086 GST_ELEMENT_ERROR (filter, LIBRARY, INIT,
1087 ("Could not initialize SRTP encoder"),
1088 ("Failed to add stream to SRTP encoder (err: %d)", status));
1089 return GST_FLOW_ERROR;
1093 GST_OBJECT_UNLOCK (filter);
1095 /* Update source caps if asked */
1099 caps = gst_pad_get_current_caps (pad);
1100 if (!gst_srtp_enc_sink_setcaps (pad, filter, caps, is_rtcp)) {
1101 gst_caps_unref (caps);
1102 return GST_FLOW_NOT_NEGOTIATED;
1104 gst_caps_unref (caps);
1111 gst_srtp_enc_ensure_ssrc (GstSrtpEnc * filter, GstBuffer * buf)
1113 GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
1114 if (gst_rtp_buffer_map (buf,
1115 GST_MAP_READ | GST_RTP_BUFFER_MAP_FLAG_SKIP_PADDING, &rtpbuf)) {
1116 guint32 ssrc = gst_rtp_buffer_get_ssrc (&rtpbuf);
1117 gst_srtp_enc_add_ssrc (filter, ssrc);
1118 gst_rtp_buffer_unmap (&rtpbuf);
1122 static GstFlowReturn
1123 gst_srtp_enc_process_buffer (GstSrtpEnc * filter, GstPad * pad,
1124 GstBuffer * buf, gboolean is_rtcp, GstBuffer ** outbuf_ptr)
1126 GstFlowReturn ret = GST_FLOW_OK;
1127 gint size_max, size;
1128 GstBuffer *bufout = NULL;
1130 srtp_err_status_t err;
1132 /* Create a bigger buffer to add protection */
1133 size = gst_buffer_get_size (buf);
1134 size_max = size + SRTP_MAX_TRAILER_LEN + 10;
1135 bufout = gst_buffer_new_allocate (NULL, size_max, NULL);
1137 gst_buffer_map (bufout, &mapout, GST_MAP_READWRITE);
1139 gst_buffer_extract (buf, 0, mapout.data, size);
1141 GST_OBJECT_LOCK (filter);
1143 gst_srtp_init_event_reporter ();
1145 if (filter->session == NULL) {
1146 /* The rtcp session disappeared (element shutting down) */
1147 GST_OBJECT_UNLOCK (filter);
1148 ret = GST_FLOW_FLUSHING;
1152 gst_srtp_enc_ensure_ssrc (filter, buf);
1156 err = srtp_protect_rtcp_mki (filter->session, mapout.data, &size,
1157 (filter->mki != NULL), 0);
1159 err = srtp_protect_mki (filter->session, mapout.data, &size,
1160 (filter->mki != NULL), 0);
1163 err = srtp_protect_rtcp (filter->session, mapout.data, &size);
1165 err = srtp_protect (filter->session, mapout.data, &size);
1168 GST_OBJECT_UNLOCK (filter);
1170 gst_buffer_unmap (bufout, &mapout);
1172 if (err == srtp_err_status_ok) {
1173 /* Buffer protected */
1174 gst_buffer_set_size (bufout, size);
1175 gst_buffer_copy_into (bufout, buf, GST_BUFFER_COPY_METADATA, 0, -1);
1177 GST_LOG_OBJECT (pad, "Encoding %s buffer of size %d",
1178 is_rtcp ? "RTCP" : "RTP", size);
1180 } else if (err == srtp_err_status_key_expired) {
1182 GST_ELEMENT_ERROR (GST_ELEMENT_CAST (filter), STREAM, ENCODE,
1183 ("Key usage limit has been reached"),
1184 ("Unable to protect buffer (hard key usage limit reached)"));
1185 ret = GST_FLOW_ERROR;
1189 /* srtp_protect failed */
1190 GST_ELEMENT_ERROR (filter, LIBRARY, FAILED, (NULL),
1191 ("Unable to protect buffer (protect failed) code %d", err));
1192 ret = GST_FLOW_ERROR;
1196 *outbuf_ptr = bufout;
1200 gst_buffer_unref (bufout);
1204 static GstFlowReturn
1205 gst_srtp_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
1208 GstSrtpEnc *filter = GST_SRTP_ENC (parent);
1209 GstFlowReturn ret = GST_FLOW_OK;
1211 GstBuffer *bufout = NULL;
1213 if ((ret = gst_srtp_enc_check_set_caps (filter, pad, is_rtcp)) != GST_FLOW_OK) {
1217 GST_OBJECT_LOCK (filter);
1219 if (!HAS_CRYPTO (filter)) {
1220 GST_OBJECT_UNLOCK (filter);
1221 otherpad = get_rtp_other_pad (pad);
1222 return gst_pad_push (otherpad, buf);
1225 GST_OBJECT_UNLOCK (filter);
1227 ret = gst_srtp_enc_process_buffer (filter, pad, buf, is_rtcp, &bufout);
1228 if (ret != GST_FLOW_OK)
1231 /* Push buffer to source pad */
1232 otherpad = get_rtp_other_pad (pad);
1233 ret = gst_pad_push (otherpad, bufout);
1236 if (ret != GST_FLOW_OK)
1239 GST_OBJECT_LOCK (filter);
1241 if (gst_srtp_get_soft_limit_reached ()) {
1242 GST_OBJECT_UNLOCK (filter);
1243 g_signal_emit (filter, gst_srtp_enc_signals[SIGNAL_SOFT_LIMIT], 0);
1244 GST_OBJECT_LOCK (filter);
1245 if (filter->random_key && !filter->key_changed)
1246 gst_srtp_enc_replace_random_key (filter);
1249 GST_OBJECT_UNLOCK (filter);
1252 gst_buffer_unref (buf);
1257 process_buffer_it (GstBuffer ** buffer, guint index, gpointer user_data)
1259 ProcessBufferItData *data = user_data;
1263 ret = gst_srtp_enc_process_buffer (data->filter, data->pad, *buffer,
1264 data->is_rtcp, &bufout);
1265 if (ret != GST_FLOW_OK) {
1266 data->flowret = ret;
1270 gst_buffer_list_add (data->out_list, bufout);
1275 static GstFlowReturn
1276 gst_srtp_enc_chain_list (GstPad * pad, GstObject * parent,
1277 GstBufferList * buf_list, gboolean is_rtcp)
1279 GstSrtpEnc *filter = GST_SRTP_ENC (parent);
1280 GstFlowReturn ret = GST_FLOW_OK;
1282 GstBufferList *out_list = NULL;
1283 ProcessBufferItData process_data;
1285 GST_LOG_OBJECT (pad, "Buffer chain with list of %d",
1286 gst_buffer_list_length (buf_list));
1288 if (!gst_buffer_list_length (buf_list))
1291 if ((ret = gst_srtp_enc_check_set_caps (filter, pad, is_rtcp)) != GST_FLOW_OK)
1294 GST_OBJECT_LOCK (filter);
1296 if (!HAS_CRYPTO (filter)) {
1297 GST_OBJECT_UNLOCK (filter);
1298 otherpad = get_rtp_other_pad (pad);
1299 return gst_pad_push_list (otherpad, buf_list);
1302 GST_OBJECT_UNLOCK (filter);
1304 out_list = gst_buffer_list_new ();
1306 process_data.filter = filter;
1307 process_data.pad = pad;
1308 process_data.is_rtcp = is_rtcp;
1309 process_data.out_list = out_list;
1310 process_data.flowret = GST_FLOW_OK;
1312 if (!gst_buffer_list_foreach (buf_list, process_buffer_it, &process_data)) {
1313 ret = process_data.flowret;
1317 if (!gst_buffer_list_length (out_list)) {
1318 gst_buffer_list_unref (out_list);
1323 /* Push buffer to source pad */
1324 otherpad = get_rtp_other_pad (pad);
1325 GST_LOG_OBJECT (pad, "Pushing buffer chain of %d",
1326 gst_buffer_list_length (buf_list));
1327 ret = gst_pad_push_list (otherpad, out_list);
1329 if (ret != GST_FLOW_OK) {
1333 GST_OBJECT_LOCK (filter);
1335 if (gst_srtp_get_soft_limit_reached ()) {
1336 GST_OBJECT_UNLOCK (filter);
1337 g_signal_emit (filter, gst_srtp_enc_signals[SIGNAL_SOFT_LIMIT], 0);
1338 GST_OBJECT_LOCK (filter);
1339 if (filter->random_key && !filter->key_changed)
1340 gst_srtp_enc_replace_random_key (filter);
1343 GST_OBJECT_UNLOCK (filter);
1347 gst_buffer_list_unref (buf_list);
1352 static GstFlowReturn
1353 gst_srtp_enc_chain_rtp (GstPad * pad, GstObject * parent, GstBuffer * buf)
1355 return gst_srtp_enc_chain (pad, parent, buf, FALSE);
1358 static GstFlowReturn
1359 gst_srtp_enc_chain_rtcp (GstPad * pad, GstObject * parent, GstBuffer * buf)
1361 return gst_srtp_enc_chain (pad, parent, buf, TRUE);
1364 static GstFlowReturn
1365 gst_srtp_enc_chain_list_rtp (GstPad * pad, GstObject * parent,
1366 GstBufferList * buf_list)
1368 return gst_srtp_enc_chain_list (pad, parent, buf_list, FALSE);
1371 static GstFlowReturn
1372 gst_srtp_enc_chain_list_rtcp (GstPad * pad, GstObject * parent,
1373 GstBufferList * buf_list)
1375 return gst_srtp_enc_chain_list (pad, parent, buf_list, TRUE);
1381 static GstStateChangeReturn
1382 gst_srtp_enc_change_state (GstElement * element, GstStateChange transition)
1384 GstStateChangeReturn res;
1387 filter = GST_SRTP_ENC (element);
1389 switch (transition) {
1390 case GST_STATE_CHANGE_NULL_TO_READY:
1391 if (filter->rtp_cipher != GST_SRTP_CIPHER_NULL ||
1392 filter->rtcp_cipher != GST_SRTP_CIPHER_NULL ||
1393 filter->rtp_auth != GST_SRTP_AUTH_NULL ||
1394 filter->rtcp_auth != GST_SRTP_AUTH_NULL) {
1396 if (filter->random_key) {
1397 gst_srtp_enc_replace_random_key (filter);
1399 GST_ERROR_OBJECT (element, "Need a key to get to READY");
1400 return GST_STATE_CHANGE_FAILURE;
1405 /* RFC 3711 says in "3. SRTP Framework" that SRTCP message authentication
1406 * is MANDATORY. In case of GCM let the pipeline handle any errors.
1408 if (filter->rtcp_cipher != GST_SRTP_CIPHER_AES_128_GCM
1409 && filter->rtcp_cipher != GST_SRTP_CIPHER_AES_256_GCM
1410 && filter->rtcp_cipher != GST_SRTP_CIPHER_NULL
1411 && filter->rtcp_auth == GST_SRTP_AUTH_NULL) {
1412 GST_ERROR_OBJECT (filter,
1413 "RTCP authentication can't be NULL if encryption is not NULL.");
1414 return GST_STATE_CHANGE_FAILURE;
1416 GST_OBJECT_LOCK (filter);
1417 if (!filter->first_session)
1418 gst_srtp_enc_reset_no_lock (filter);
1419 GST_OBJECT_UNLOCK (filter);
1421 case GST_STATE_CHANGE_READY_TO_PAUSED:
1423 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1429 res = GST_ELEMENT_CLASS (gst_srtp_enc_parent_class)->change_state (element,
1432 switch (transition) {
1433 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1435 case GST_STATE_CHANGE_PAUSED_TO_READY:
1436 gst_srtp_enc_reset (filter);
1438 case GST_STATE_CHANGE_READY_TO_NULL:
1448 gst_srtp_enc_sink_event (GstPad * pad, GstObject * parent, GstEvent * event,
1451 GstSrtpEnc *filter = GST_SRTP_ENC (parent);
1455 otherpad = get_rtp_other_pad (pad);
1457 switch (GST_EVENT_TYPE (event)) {
1458 case GST_EVENT_FLUSH_STOP:
1459 GST_DEBUG_OBJECT (pad, "Encing event Flush stop (%d)",
1460 GST_EVENT_TYPE (event));
1461 gst_srtp_enc_reset (filter);
1462 ret = gst_pad_push_event (otherpad, event);
1464 case GST_EVENT_CAPS:
1468 gst_event_parse_caps (event, &caps);
1469 ret = gst_srtp_enc_sink_setcaps (pad, filter, caps, is_rtcp);
1470 gst_event_unref (event);
1474 GST_DEBUG_OBJECT (pad, "Encing event default (%d)",
1475 GST_EVENT_TYPE (event));
1476 ret = gst_pad_event_default (pad, parent, event);
1484 gst_srtp_enc_sink_event_rtp (GstPad * pad, GstObject * parent, GstEvent * event)
1486 return gst_srtp_enc_sink_event (pad, parent, event, FALSE);
1490 gst_srtp_enc_sink_event_rtcp (GstPad * pad, GstObject * parent,
1493 return gst_srtp_enc_sink_event (pad, parent, event, TRUE);
1496 /* entry point to initialize the plug-in
1497 * initialize the plug-in itself
1498 * register the element factories and other features
1501 gst_srtp_enc_plugin_init (GstPlugin * srtpenc)
1503 GST_DEBUG_CATEGORY_INIT (gst_srtp_enc_debug, "srtpenc", 0, "SRTP Enc");
1505 return gst_element_register (srtpenc, "srtpenc", GST_RANK_NONE,