docs: hook up new RTP FEC elements
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpstorage.c
1 /* GStreamer plugin for forward error correction
2  * Copyright (C) 2017 Pexip
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Author: Mikhail Fludkov <misha@pexip.com>
19  */
20
21 /**
22  * SECTION:element-rtpstorage
23  * @short_description: RTP storage for forward error correction (FEC) in rtpbin
24  * @title: rtpstorage
25  *
26  * Helper element for storing packets to aid later packet recovery from packet
27  * loss using RED/FEC (Forward Error Correction).
28  *
29  * This element is used internally by rtpbin and is usually created
30  * automatically.
31  *
32  * Since: 1.14
33  */
34
35 #include "gstrtpstorage.h"
36
37 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
38     GST_PAD_SINK,
39     GST_PAD_ALWAYS,
40     GST_STATIC_CAPS ("application/x-rtp")
41     );
42
43 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
44     GST_PAD_SRC,
45     GST_PAD_ALWAYS,
46     GST_STATIC_CAPS ("application/x-rtp")
47     );
48
49 enum
50 {
51   PROP_0,
52   PROP_SIZE_TIME,
53   PROP_INTERNAL_STORAGE,
54   N_PROPERTIES
55 };
56
57 static GParamSpec *klass_properties[N_PROPERTIES] = { NULL, };
58
59 #define DEFAULT_SIZE_TIME (0)
60
61 GST_DEBUG_CATEGORY_STATIC (gst_rtp_storage_debug);
62 #define GST_CAT_DEFAULT (gst_rtp_storage_debug)
63
64 G_DEFINE_TYPE (GstRtpStorage, gst_rtp_storage, GST_TYPE_ELEMENT);
65
66 static GstFlowReturn
67 gst_rtp_storage_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
68 {
69   GstRtpStorage *self = GST_RTP_STORAGE (parent);;
70
71   if (rtp_storage_append_buffer (self->storage, buf))
72     return gst_pad_push (self->srcpad, buf);
73   return GST_FLOW_OK;
74 }
75
76 static void
77 gst_rtp_storage_set_property (GObject * object, guint prop_id,
78     const GValue * value, GParamSpec * pspec)
79 {
80   GstRtpStorage *self = GST_RTP_STORAGE (object);
81
82   switch (prop_id) {
83     case PROP_SIZE_TIME:
84       rtp_storage_set_size (self->storage, g_value_get_uint64 (value));
85       break;
86     default:
87       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
88       break;
89   }
90 }
91
92 static void
93 gst_rtp_storage_get_property (GObject * object, guint prop_id,
94     GValue * value, GParamSpec * pspec)
95 {
96   GstRtpStorage *self = GST_RTP_STORAGE (object);
97   switch (prop_id) {
98     case PROP_SIZE_TIME:
99       g_value_set_uint64 (value, rtp_storage_get_size (self->storage));
100       break;
101     case PROP_INTERNAL_STORAGE:
102     {
103       g_value_set_object (value, self->storage);
104       break;
105     }
106     default:
107       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
108       break;
109   }
110 }
111
112 static void
113 gst_rtp_storage_init (GstRtpStorage * self)
114 {
115   self->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
116   self->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
117   GST_PAD_SET_PROXY_CAPS (self->sinkpad);
118   GST_PAD_SET_PROXY_ALLOCATION (self->sinkpad);
119   gst_pad_set_chain_function (self->sinkpad, gst_rtp_storage_chain);
120
121   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
122   gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
123
124   self->storage = rtp_storage_new ();
125 }
126
127 static void
128 gst_rtp_storage_dispose (GObject * obj)
129 {
130   GstRtpStorage *self = GST_RTP_STORAGE (obj);
131   g_object_unref (self->storage);
132   G_OBJECT_CLASS (gst_rtp_storage_parent_class)->dispose (obj);
133 }
134
135 static void
136 gst_rtp_storage_class_init (GstRtpStorageClass * klass)
137 {
138   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
139   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
140
141   GST_DEBUG_CATEGORY_INIT (gst_rtp_storage_debug,
142       "rtpstorage", 0, "RTP Storage");
143
144   gst_element_class_add_pad_template (element_class,
145       gst_static_pad_template_get (&srctemplate));
146   gst_element_class_add_pad_template (element_class,
147       gst_static_pad_template_get (&sinktemplate));
148
149   gst_element_class_set_static_metadata (element_class,
150       "RTP storage",
151       "Analyzer/RTP",
152       "Helper element for various purposes "
153       "(ex. recovering from packet loss using RED/FEC). "
154       "Saves given number of RTP packets. "
155       "Should be instantiated before jitterbuffer",
156       "Mikhail Fludkov <misha@pexip.com>");
157
158   gobject_class->set_property = gst_rtp_storage_set_property;
159   gobject_class->get_property = gst_rtp_storage_get_property;
160   gobject_class->dispose = gst_rtp_storage_dispose;
161
162   klass_properties[PROP_SIZE_TIME] =
163       g_param_spec_uint64 ("size-time", "Storage size (in ns)",
164       "The amount of data to keep in the storage (in ns, 0-disable)", 0,
165       G_MAXUINT64, DEFAULT_SIZE_TIME,
166       G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
167
168   klass_properties[PROP_INTERNAL_STORAGE] =
169       g_param_spec_object ("internal-storage", "Internal storage",
170       "Internal RtpStorage object", G_TYPE_OBJECT,
171       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
172
173   g_object_class_install_properties (gobject_class, N_PROPERTIES,
174       klass_properties);
175 }