mulaw-encode.c 8.23 KB
Newer Older
Christian Schaller's avatar
Christian Schaller committed
1
/* GStreamer
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
19 20 21 22 23
/**
 * SECTION:element-mulawenc
 *
 * This element encode mulaw audio. Mulaw coding is also known as G.711.
 */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
24

25 26 27
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
28 29 30 31
#include <gst/gst.h>
#include "mulaw-encode.h"
#include "mulaw-conversion.h"

32 33
extern GstStaticPadTemplate mulaw_enc_src_factory;
extern GstStaticPadTemplate mulaw_enc_sink_factory;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
34 35

/* Stereo signals and args */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
36 37
enum
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
38 39 40 41
  /* FILL ME */
  LAST_SIGNAL
};

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
42 43
enum
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
44 45 46
  ARG_0
};

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
47 48 49
static void gst_mulawenc_class_init (GstMuLawEncClass * klass);
static void gst_mulawenc_base_init (GstMuLawEncClass * klass);
static void gst_mulawenc_init (GstMuLawEnc * mulawenc);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
50

51
static GstFlowReturn gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
52 53

static GstElementClass *parent_class = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
54

Christian Schaller's avatar
Christian Schaller committed
55
/*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
56

57 58 59
static GstCaps *
mulawenc_getcaps (GstPad * pad)
{
60
  GstMuLawEnc *mulawenc;
61
  GstPad *otherpad;
Wim Taymans's avatar
Wim Taymans committed
62 63
  GstCaps *othercaps, *result;
  const GstCaps *templ;
64
  const gchar *name;
Wim Taymans's avatar
Wim Taymans committed
65
  gint i;
66 67 68

  mulawenc = GST_MULAWENC (GST_PAD_PARENT (pad));

Wim Taymans's avatar
Wim Taymans committed
69
  /* figure out the name of the caps we are going to return */
70
  if (pad == mulawenc->srcpad) {
Wim Taymans's avatar
Wim Taymans committed
71
    name = "audio/x-mulaw";
72 73
    otherpad = mulawenc->sinkpad;
  } else {
Wim Taymans's avatar
Wim Taymans committed
74
    name = "audio/x-raw-int";
75 76
    otherpad = mulawenc->srcpad;
  }
Wim Taymans's avatar
Wim Taymans committed
77
  /* get caps from the peer, this can return NULL when there is no peer */
78 79
  othercaps = gst_pad_peer_get_caps (otherpad);

Wim Taymans's avatar
Wim Taymans committed
80 81
  /* get the template caps to make sure we return something acceptable */
  templ = gst_pad_get_pad_template_caps (pad);
82

Wim Taymans's avatar
Wim Taymans committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
  if (othercaps) {
    /* there was a peer */
    othercaps = gst_caps_make_writable (othercaps);

    /* go through the caps and remove the fields we don't want */
    for (i = 0; i < gst_caps_get_size (othercaps); i++) {
      GstStructure *structure;

      structure = gst_caps_get_structure (othercaps, i);

      /* adjust the name */
      gst_structure_set_name (structure, name);

      if (pad == mulawenc->srcpad) {
        /* remove the fields we don't want */
        gst_structure_remove_fields (structure, "width", "depth", "endianness",
            "signed", NULL);
      } else {
        /* add fixed fields */
        gst_structure_set (structure, "width", G_TYPE_INT, 16,
            "depth", G_TYPE_INT, 16,
            "endianness", G_TYPE_INT, G_BYTE_ORDER,
            "signed", G_TYPE_BOOLEAN, TRUE, NULL);
      }
    }
    /* filter against the allowed caps of the pad to return our result */
    result = gst_caps_intersect (othercaps, templ);
110
    gst_caps_unref (othercaps);
Wim Taymans's avatar
Wim Taymans committed
111 112 113
  } else {
    /* there was no peer, return the template caps */
    result = gst_caps_copy (templ);
114
  }
Wim Taymans's avatar
Wim Taymans committed
115
  return result;
116 117
}

118 119
static gboolean
mulawenc_setcaps (GstPad * pad, GstCaps * caps)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
120
{
121
  GstMuLawEnc *mulawenc;
122
  GstPad *otherpad;
David Schleef's avatar
David Schleef committed
123
  GstStructure *structure;
124
  GstCaps *base_caps;
125 126

  mulawenc = GST_MULAWENC (gst_pad_get_parent (pad));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
127

David Schleef's avatar
David Schleef committed
128
  structure = gst_caps_get_structure (caps, 0);
129 130
  gst_structure_get_int (structure, "channels", &mulawenc->channels);
  gst_structure_get_int (structure, "rate", &mulawenc->rate);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
131

132 133 134 135 136
  if (pad == mulawenc->sinkpad) {
    otherpad = mulawenc->srcpad;
  } else {
    otherpad = mulawenc->sinkpad;
  }
137
  base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
138 139

  structure = gst_caps_get_structure (base_caps, 0);
140 141 142
  gst_structure_set (structure, "rate", G_TYPE_INT, mulawenc->rate, NULL);
  gst_structure_set (structure, "channels", G_TYPE_INT, mulawenc->channels,
      NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
143

144
  gst_pad_set_caps (otherpad, base_caps);
145

146
  gst_object_unref (mulawenc);
147
  gst_caps_unref (base_caps);
148

149
  return TRUE;
David Schleef's avatar
David Schleef committed
150
}
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
151 152

GType
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
153 154
gst_mulawenc_get_type (void)
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
155 156 157 158
  static GType mulawenc_type = 0;

  if (!mulawenc_type) {
    static const GTypeInfo mulawenc_info = {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
159 160
      sizeof (GstMuLawEncClass),
      (GBaseInitFunc) gst_mulawenc_base_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
161
      NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
162
      (GClassInitFunc) gst_mulawenc_class_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
163 164
      NULL,
      NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
165
      sizeof (GstMuLawEnc),
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
166
      0,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
167
      (GInstanceInitFunc) gst_mulawenc_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
168
    };
169

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
170
    mulawenc_type =
171 172
        g_type_register_static (GST_TYPE_ELEMENT, "GstMuLawEnc", &mulawenc_info,
        0);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
173 174 175 176
  }
  return mulawenc_type;
}

Ronald S. Bultje's avatar
......  
Ronald S. Bultje committed
177
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
178
gst_mulawenc_base_init (GstMuLawEncClass * klass)
Ronald S. Bultje's avatar
......  
Ronald S. Bultje committed
179 180 181
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

182 183 184 185
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&mulaw_enc_src_factory));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&mulaw_enc_sink_factory));
186 187 188 189
  gst_element_class_set_details_simple (element_class, "Mu Law audio encoder",
      "Codec/Encoder/Audio",
      "Convert 16bit PCM to 8bit mu law",
      "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
Ronald S. Bultje's avatar
......  
Ronald S. Bultje committed
190 191
}

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
192
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
193
gst_mulawenc_class_init (GstMuLawEncClass * klass)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
194
{
195
  parent_class = g_type_class_peek_parent (klass);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
196 197 198
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
199
gst_mulawenc_init (GstMuLawEnc * mulawenc)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
200
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
201
  mulawenc->sinkpad =
202
      gst_pad_new_from_static_template (&mulaw_enc_sink_factory, "sink");
203
  gst_pad_set_setcaps_function (mulawenc->sinkpad, mulawenc_setcaps);
204
  gst_pad_set_getcaps_function (mulawenc->sinkpad, mulawenc_getcaps);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
205
  gst_pad_set_chain_function (mulawenc->sinkpad, gst_mulawenc_chain);
206 207
  gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->sinkpad);

208 209
  mulawenc->srcpad =
      gst_pad_new_from_static_template (&mulaw_enc_src_factory, "src");
210
  gst_pad_set_setcaps_function (mulawenc->srcpad, mulawenc_setcaps);
211
  gst_pad_set_getcaps_function (mulawenc->srcpad, mulawenc_getcaps);
212
  gst_pad_use_fixed_caps (mulawenc->srcpad);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
213
  gst_element_add_pad (GST_ELEMENT (mulawenc), mulawenc->srcpad);
214 215 216 217

  /* init rest */
  mulawenc->channels = 0;
  mulawenc->rate = 0;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
218 219
}

220 221
static GstFlowReturn
gst_mulawenc_chain (GstPad * pad, GstBuffer * buffer)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
222 223 224
{
  GstMuLawEnc *mulawenc;
  gint16 *linear_data;
225
  guint linear_size;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
226
  guint8 *mulaw_data;
227
  guint mulaw_size;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
228
  GstBuffer *outbuf;
229
  GstFlowReturn ret;
230
  GstClockTime timestamp, duration;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
231

232
  mulawenc = GST_MULAWENC (gst_pad_get_parent (pad));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
233

234 235 236
  if (!mulawenc->rate || !mulawenc->channels)
    goto not_negotiated;

237
  linear_data = (gint16 *) GST_BUFFER_DATA (buffer);
238 239 240 241 242 243
  linear_size = GST_BUFFER_SIZE (buffer);

  mulaw_size = linear_size / 2;

  timestamp = GST_BUFFER_TIMESTAMP (buffer);
  duration = GST_BUFFER_DURATION (buffer);
244

245
  ret = gst_pad_alloc_buffer_and_set_caps (mulawenc->srcpad,
246 247 248 249 250
      GST_BUFFER_OFFSET_NONE, mulaw_size, GST_PAD_CAPS (mulawenc->srcpad),
      &outbuf);
  if (ret != GST_FLOW_OK)
    goto alloc_failed;

251 252 253 254 255 256 257 258 259 260 261
  if (duration == -1) {
    duration = gst_util_uint64_scale_int (mulaw_size,
        GST_SECOND, mulawenc->rate * mulawenc->channels);
  }

  if (GST_BUFFER_SIZE (outbuf) < mulaw_size) {
    /* pad-alloc can suggest a smaller size */
    gst_buffer_unref (outbuf);
    outbuf = gst_buffer_new_and_alloc (mulaw_size);
  }

262
  mulaw_data = (guint8 *) GST_BUFFER_DATA (outbuf);
263

264 265 266
  /* copy discont flag */
  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
267

268 269 270
  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
  GST_BUFFER_DURATION (outbuf) = duration;

271 272
  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mulawenc->srcpad));

273
  mulaw_encode (linear_data, mulaw_data, mulaw_size);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
274

275 276
  gst_buffer_unref (buffer);

277 278 279 280 281 282
  ret = gst_pad_push (mulawenc->srcpad, outbuf);

done:
  gst_object_unref (mulawenc);

  return ret;
283 284 285

not_negotiated:
  {
286
    GST_DEBUG_OBJECT (mulawenc, "no format negotiated");
287
    ret = GST_FLOW_NOT_NEGOTIATED;
288 289 290 291 292 293 294
    gst_buffer_unref (buffer);
    goto done;
  }
alloc_failed:
  {
    GST_DEBUG_OBJECT (mulawenc, "pad alloc failed");
    gst_buffer_unref (buffer);
295
    goto done;
296
  }
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
297
}