• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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