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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19 /**
20 * SECTION:element-mulawenc
21 * @title: mulawenc
22 *
23 * This element encode mulaw audio. Mulaw coding is also known as G.711.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #include <gst/gst.h>
30 #include <gst/audio/audio.h>
31
32 #include "mulaw-encode.h"
33 #include "mulaw-conversion.h"
34
35 extern GstStaticPadTemplate mulaw_enc_src_factory;
36 extern GstStaticPadTemplate mulaw_enc_sink_factory;
37
38 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
39 #define INT_FORMAT "S16LE"
40 #else
41 #define INT_FORMAT "S16BE"
42 #endif
43
44 GstStaticPadTemplate mulaw_enc_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
45 GST_PAD_SINK,
46 GST_PAD_ALWAYS,
47 GST_STATIC_CAPS ("audio/x-raw, "
48 "format = (string) " INT_FORMAT ", "
49 "layout = (string) interleaved, "
50 "rate = (int) [ 8000, 192000 ], " "channels = (int) [ 1, 2 ]")
51 );
52
53 GstStaticPadTemplate mulaw_enc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
54 GST_PAD_SRC,
55 GST_PAD_ALWAYS,
56 GST_STATIC_CAPS ("audio/x-mulaw, "
57 "rate = [ 8000 , 192000 ], " "channels = [ 1 , 2 ]")
58 );
59 /* Stereo signals and args */
60 enum
61 {
62 /* FILL ME */
63 LAST_SIGNAL
64 };
65
66 enum
67 {
68 PROP_0
69 };
70
71 static gboolean gst_mulawenc_start (GstAudioEncoder * audioenc);
72 static gboolean gst_mulawenc_set_format (GstAudioEncoder * enc,
73 GstAudioInfo * info);
74 static GstFlowReturn gst_mulawenc_handle_frame (GstAudioEncoder * enc,
75 GstBuffer * buffer);
76 static void gst_mulawenc_set_tags (GstMuLawEnc * mulawenc);
77
78
79 #define gst_mulawenc_parent_class parent_class
80 G_DEFINE_TYPE (GstMuLawEnc, gst_mulawenc, GST_TYPE_AUDIO_ENCODER);
81 GST_ELEMENT_REGISTER_DEFINE (mulawenc, "mulawenc", GST_RANK_PRIMARY,
82 GST_TYPE_MULAWENC);
83
84 /*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
85
86 static gboolean
gst_mulawenc_start(GstAudioEncoder * audioenc)87 gst_mulawenc_start (GstAudioEncoder * audioenc)
88 {
89 GstMuLawEnc *mulawenc = GST_MULAWENC (audioenc);
90
91 mulawenc->channels = 0;
92 mulawenc->rate = 0;
93
94 return TRUE;
95 }
96
97
98 static void
gst_mulawenc_set_tags(GstMuLawEnc * mulawenc)99 gst_mulawenc_set_tags (GstMuLawEnc * mulawenc)
100 {
101 GstTagList *taglist;
102 guint bitrate;
103
104 /* bitrate of mulaw is 8 bits/sample * sample rate * number of channels */
105 bitrate = 8 * mulawenc->rate * mulawenc->channels;
106
107 taglist = gst_tag_list_new_empty ();
108 gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
109 GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
110 gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
111 GST_TAG_MINIMUM_BITRATE, bitrate, NULL);
112 gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
113 GST_TAG_BITRATE, bitrate, NULL);
114
115 gst_audio_encoder_merge_tags (GST_AUDIO_ENCODER (mulawenc),
116 taglist, GST_TAG_MERGE_REPLACE);
117
118 gst_tag_list_unref (taglist);
119 }
120
121
122 static gboolean
gst_mulawenc_set_format(GstAudioEncoder * audioenc,GstAudioInfo * info)123 gst_mulawenc_set_format (GstAudioEncoder * audioenc, GstAudioInfo * info)
124 {
125 GstCaps *base_caps;
126 GstStructure *structure;
127 GstMuLawEnc *mulawenc = GST_MULAWENC (audioenc);
128 gboolean ret;
129
130 mulawenc->rate = info->rate;
131 mulawenc->channels = info->channels;
132
133 base_caps =
134 gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (audioenc));
135 g_assert (base_caps);
136 base_caps = gst_caps_make_writable (base_caps);
137 g_assert (base_caps);
138
139 structure = gst_caps_get_structure (base_caps, 0);
140 g_assert (structure);
141 gst_structure_set (structure, "rate", G_TYPE_INT, mulawenc->rate, NULL);
142 gst_structure_set (structure, "channels", G_TYPE_INT, mulawenc->channels,
143 NULL);
144
145 gst_mulawenc_set_tags (mulawenc);
146
147 ret = gst_audio_encoder_set_output_format (audioenc, base_caps);
148 gst_caps_unref (base_caps);
149
150 return ret;
151 }
152
153 static GstFlowReturn
gst_mulawenc_handle_frame(GstAudioEncoder * audioenc,GstBuffer * buffer)154 gst_mulawenc_handle_frame (GstAudioEncoder * audioenc, GstBuffer * buffer)
155 {
156 GstMuLawEnc *mulawenc;
157 GstMapInfo inmap, outmap;
158 gint16 *linear_data;
159 gsize linear_size;
160 guint8 *mulaw_data;
161 guint mulaw_size;
162 GstBuffer *outbuf;
163 GstFlowReturn ret;
164
165 if (!buffer) {
166 ret = GST_FLOW_OK;
167 goto done;
168 }
169
170 mulawenc = GST_MULAWENC (audioenc);
171
172 if (!mulawenc->rate || !mulawenc->channels)
173 goto not_negotiated;
174
175 gst_buffer_map (buffer, &inmap, GST_MAP_READ);
176 linear_data = (gint16 *) inmap.data;
177 linear_size = inmap.size;
178
179 mulaw_size = linear_size / 2;
180
181 outbuf = gst_audio_encoder_allocate_output_buffer (audioenc, mulaw_size);
182
183 g_assert (outbuf);
184
185 gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
186 mulaw_data = outmap.data;
187
188 mulaw_encode (linear_data, mulaw_data, mulaw_size);
189
190 gst_buffer_unmap (outbuf, &outmap);
191 gst_buffer_unmap (buffer, &inmap);
192
193 ret = gst_audio_encoder_finish_frame (audioenc, outbuf, -1);
194
195 done:
196
197 return ret;
198
199 not_negotiated:
200 {
201 GST_DEBUG_OBJECT (mulawenc, "no format negotiated");
202 ret = GST_FLOW_NOT_NEGOTIATED;
203 goto done;
204 }
205 }
206
207
208
209 static void
gst_mulawenc_class_init(GstMuLawEncClass * klass)210 gst_mulawenc_class_init (GstMuLawEncClass * klass)
211 {
212 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
213 GstAudioEncoderClass *audio_encoder_class = GST_AUDIO_ENCODER_CLASS (klass);
214
215 audio_encoder_class->start = GST_DEBUG_FUNCPTR (gst_mulawenc_start);
216 audio_encoder_class->set_format = GST_DEBUG_FUNCPTR (gst_mulawenc_set_format);
217 audio_encoder_class->handle_frame =
218 GST_DEBUG_FUNCPTR (gst_mulawenc_handle_frame);
219
220 gst_element_class_add_static_pad_template (element_class,
221 &mulaw_enc_src_factory);
222 gst_element_class_add_static_pad_template (element_class,
223 &mulaw_enc_sink_factory);
224
225 gst_element_class_set_static_metadata (element_class, "Mu Law audio encoder",
226 "Codec/Encoder/Audio",
227 "Convert 16bit PCM to 8bit mu law",
228 "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
229 }
230
231 static void
gst_mulawenc_init(GstMuLawEnc * mulawenc)232 gst_mulawenc_init (GstMuLawEnc * mulawenc)
233 {
234 GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (mulawenc));
235 }
236