close #333784 unref the result of gst_pad_get_parent() by: Christophe Fergeau.
[platform/upstream/gstreamer.git] / gst / law / mulaw-encode.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <gst/gst.h>
24 #include "mulaw-encode.h"
25 #include "mulaw-conversion.h"
26
27 extern GstPadTemplate *mulawenc_src_template, *mulawenc_sink_template;
28
29 /* Stereo signals and args */
30 enum
31 {
32   /* FILL ME */
33   LAST_SIGNAL
34 };
35
36 enum
37 {
38   ARG_0
39 };
40
41 static void gst_mulawenc_class_init (GstMuLawEncClass * klass);
42 static void gst_mulawenc_base_init (GstMuLawEncClass * klass);
43 static void gst_mulawenc_init (GstMuLawEnc * mulawenc);
44
45 static GstFlowReturn gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer);
46
47 static GstElementClass *parent_class = NULL;
48
49 /*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
50
51 static GstCaps *
52 mulawenc_getcaps (GstPad * pad)
53 {
54   GstMuLawEnc *mulawenc;
55   GstPad *otherpad;
56   GstCaps *base_caps, *othercaps;
57
58   mulawenc = GST_MULAWENC (GST_PAD_PARENT (pad));
59
60   base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
61
62   if (pad == mulawenc->srcpad) {
63     otherpad = mulawenc->sinkpad;
64   } else {
65     otherpad = mulawenc->srcpad;
66   }
67   othercaps = gst_pad_peer_get_caps (otherpad);
68   if (othercaps) {
69     GstStructure *structure;
70     const GValue *orate, *ochans;
71     const GValue *rate, *chans;
72     GValue irate = { 0 }, ichans = {
73     0};
74
75     structure = gst_caps_get_structure (othercaps, 0);
76     orate = gst_structure_get_value (structure, "rate");
77     ochans = gst_structure_get_value (structure, "channels");
78     if (!orate || !ochans)
79       goto done;
80
81     structure = gst_caps_get_structure (base_caps, 0);
82     rate = gst_structure_get_value (structure, "rate");
83     chans = gst_structure_get_value (structure, "channels");
84     if (!rate || !chans)
85       goto done;
86
87     gst_value_intersect (&irate, orate, rate);
88     gst_value_intersect (&ichans, ochans, chans);
89
90     /* Set the samplerate/channels on the to-be-returned caps */
91     structure = gst_caps_get_structure (base_caps, 0);
92     gst_structure_set_value (structure, "rate", &irate);
93     gst_structure_set_value (structure, "channels", &ichans);
94
95     gst_caps_unref (othercaps);
96   }
97 done:
98   return base_caps;
99 }
100
101 static gboolean
102 mulawenc_setcaps (GstPad * pad, GstCaps * caps)
103 {
104   GstMuLawEnc *mulawenc;
105   GstPad *otherpad;
106   GstStructure *structure;
107   GstCaps *base_caps;
108
109   mulawenc = GST_MULAWENC (gst_pad_get_parent (pad));
110
111   structure = gst_caps_get_structure (caps, 0);
112   gst_structure_get_int (structure, "channels", &mulawenc->channels);
113   gst_structure_get_int (structure, "rate", &mulawenc->rate);
114
115   if (pad == mulawenc->sinkpad) {
116     otherpad = mulawenc->srcpad;
117   } else {
118     otherpad = mulawenc->sinkpad;
119   }
120   base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
121
122   structure = gst_caps_get_structure (base_caps, 0);
123   gst_structure_set (structure, "rate", G_TYPE_INT, mulawenc->rate, NULL);
124   gst_structure_set (structure, "channels", G_TYPE_INT, mulawenc->channels,
125       NULL);
126
127   gst_pad_set_caps (otherpad, base_caps);
128
129   gst_object_unref (mulawenc);
130   gst_caps_unref (base_caps);
131
132   return TRUE;
133 }
134
135 GType
136 gst_mulawenc_get_type (void)
137 {
138   static GType mulawenc_type = 0;
139
140   if (!mulawenc_type) {
141     static const GTypeInfo mulawenc_info = {
142       sizeof (GstMuLawEncClass),
143       (GBaseInitFunc) gst_mulawenc_base_init,
144       NULL,
145       (GClassInitFunc) gst_mulawenc_class_init,
146       NULL,
147       NULL,
148       sizeof (GstMuLawEnc),
149       0,
150       (GInstanceInitFunc) gst_mulawenc_init,
151     };
152
153     mulawenc_type =
154         g_type_register_static (GST_TYPE_ELEMENT, "GstMuLawEnc", &mulawenc_info,
155         0);
156   }
157   return mulawenc_type;
158 }
159
160 static void
161 gst_mulawenc_base_init (GstMuLawEncClass * klass)
162 {
163   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
164   GstElementDetails mulawenc_details = {
165     "PCM to Mu Law conversion",
166     "Codec/Encoder/Audio",
167     "Convert 16bit PCM to 8bit mu law",
168     "Zaheer Abbas Merali <zaheerabbas at merali dot org>"
169   };
170
171   gst_element_class_add_pad_template (element_class, mulawenc_src_template);
172   gst_element_class_add_pad_template (element_class, mulawenc_sink_template);
173   gst_element_class_set_details (element_class, &mulawenc_details);
174 }
175
176 static void
177 gst_mulawenc_class_init (GstMuLawEncClass * klass)
178 {
179   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
180 }
181
182 static void
183 gst_mulawenc_init (GstMuLawEnc * mulawenc)
184 {
185   mulawenc->sinkpad =
186       gst_pad_new_from_template (mulawenc_sink_template, "sink");
187   gst_pad_set_setcaps_function (mulawenc->sinkpad, mulawenc_setcaps);
188   gst_pad_set_getcaps_function (mulawenc->sinkpad, mulawenc_getcaps);
189   gst_pad_set_chain_function (mulawenc->sinkpad, gst_mulawenc_chain);
190   gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->sinkpad);
191
192   mulawenc->srcpad = gst_pad_new_from_template (mulawenc_src_template, "src");
193   gst_pad_set_setcaps_function (mulawenc->srcpad, mulawenc_setcaps);
194   gst_pad_set_getcaps_function (mulawenc->srcpad, mulawenc_getcaps);
195   gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->srcpad);
196
197   /* init rest */
198   mulawenc->channels = 0;
199   mulawenc->rate = 0;
200   mulawenc->ts = 0;
201 }
202
203 static GstFlowReturn
204 gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer)
205 {
206   GstMuLawEnc *mulawenc;
207   gint16 *linear_data;
208   guint8 *mulaw_data;
209   GstBuffer *outbuf;
210   gint bufsize;
211
212   mulawenc = GST_MULAWENC (GST_OBJECT_PARENT (pad));
213
214   if (!mulawenc->rate || !mulawenc->channels)
215     goto not_negotiated;
216
217   linear_data = (gint16 *) GST_BUFFER_DATA (buffer);
218   bufsize = GST_BUFFER_SIZE (buffer) / 2;
219   outbuf = gst_buffer_new_and_alloc (bufsize);
220
221   GST_BUFFER_DURATION (outbuf) = GST_SECOND * (bufsize) /
222       (mulawenc->rate * mulawenc->channels);
223   GST_BUFFER_TIMESTAMP (outbuf) = mulawenc->ts;
224   mulawenc->ts += GST_BUFFER_DURATION (outbuf);
225
226   gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawenc->srcpad));
227   mulaw_data = (guint8 *) GST_BUFFER_DATA (outbuf);
228
229   mulaw_encode (linear_data, mulaw_data, GST_BUFFER_SIZE (outbuf));
230
231   gst_buffer_unref (buffer);
232
233   return gst_pad_push (mulawenc->srcpad, outbuf);
234
235 not_negotiated:
236   {
237     return GST_FLOW_NOT_NEGOTIATED;
238   }
239 }