mulaw-decode.c 5.95 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
19
 * 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.
 */

20
21
22
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
23
24
25
26
27
28
29
#include <gst/gst.h>
#include "mulaw-decode.h"
#include "mulaw-conversion.h"

extern GstPadTemplate *mulawdec_src_template, *mulawdec_sink_template;

/* Stereo signals and args */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
30
31
enum
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
32
33
34
35
  /* FILL ME */
  LAST_SIGNAL
};

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
36
37
enum
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
38
39
40
  ARG_0
};

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
41
42
43
static void gst_mulawdec_class_init (GstMuLawDecClass * klass);
static void gst_mulawdec_base_init (GstMuLawDecClass * klass);
static void gst_mulawdec_init (GstMuLawDec * mulawdec);
44
45
static GstStateChangeReturn
gst_mulawdec_change_state (GstElement * element, GstStateChange transition);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
46

47
static GstFlowReturn gst_mulawdec_chain (GstPad * pad, GstBuffer * buffer);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
48
49

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

51
static gboolean
52
mulawdec_sink_setcaps (GstPad * pad, GstCaps * caps)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
53
{
54
  GstMuLawDec *mulawdec;
David Schleef's avatar
David Schleef committed
55
  GstStructure *structure;
56
57
  int rate, channels;
  gboolean ret;
58

59
  mulawdec = GST_MULAWDEC (GST_PAD_PARENT (pad));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
60

David Schleef's avatar
David Schleef committed
61
  structure = gst_caps_get_structure (caps, 0);
62
63
64
  ret = gst_structure_get_int (structure, "rate", &rate);
  ret = ret && gst_structure_get_int (structure, "channels", &channels);
  if (!ret)
65
    return FALSE;
David Schleef's avatar
David Schleef committed
66

67
68
69
70
71
72
73
74
  if (mulawdec->srccaps)
    gst_caps_unref (mulawdec->srccaps);
  mulawdec->srccaps = gst_caps_new_simple ("audio/x-raw-int",
      "width", G_TYPE_INT, 16,
      "depth", G_TYPE_INT, 16,
      "endianness", G_TYPE_INT, G_BYTE_ORDER,
      "signed", G_TYPE_BOOLEAN, TRUE,
      "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);
75

76
77
78
  mulawdec->rate = rate;
  mulawdec->channels = channels;

79
  return TRUE;
Benjamin Otte's avatar
Benjamin Otte committed
80
}
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
81
82

GType
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
83
84
gst_mulawdec_get_type (void)
{
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
85
86
87
88
  static GType mulawdec_type = 0;

  if (!mulawdec_type) {
    static const GTypeInfo mulawdec_info = {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
89
90
      sizeof (GstMuLawDecClass),
      (GBaseInitFunc) gst_mulawdec_base_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
91
      NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
92
      (GClassInitFunc) gst_mulawdec_class_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
93
94
      NULL,
      NULL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
95
      sizeof (GstMuLawDec),
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
96
      0,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
97
      (GInstanceInitFunc) gst_mulawdec_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
98
    };
99

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
100
    mulawdec_type =
101
102
        g_type_register_static (GST_TYPE_ELEMENT, "GstMuLawDec", &mulawdec_info,
        0);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
103
104
105
106
  }
  return mulawdec_type;
}

Ronald S. Bultje's avatar
......    
Ronald S. Bultje committed
107
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
108
gst_mulawdec_base_init (GstMuLawDecClass * klass)
Ronald S. Bultje's avatar
......    
Ronald S. Bultje committed
109
110
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
111
  const GstElementDetails mulawdec_details =
Wim Taymans's avatar
Wim Taymans committed
112
113
114
115
      GST_ELEMENT_DETAILS ("Mu Law audio decoder",
      "Codec/Decoder/Audio",
      "Convert 8bit mu law to 16bit PCM",
      "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
Ronald S. Bultje's avatar
......    
Ronald S. Bultje committed
116
117
118
119
120
121

  gst_element_class_add_pad_template (element_class, mulawdec_src_template);
  gst_element_class_add_pad_template (element_class, mulawdec_sink_template);
  gst_element_class_set_details (element_class, &mulawdec_details);
}

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
122
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
123
gst_mulawdec_class_init (GstMuLawDecClass * klass)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
124
{
125
126
127
128
129
  GstElementClass *element_class = (GstElementClass *) klass;

  parent_class = g_type_class_peek_parent (klass);

  element_class->change_state = GST_DEBUG_FUNCPTR (gst_mulawdec_change_state);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
130
131
132
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
133
gst_mulawdec_init (GstMuLawDec * mulawdec)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
134
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
135
136
  mulawdec->sinkpad =
      gst_pad_new_from_template (mulawdec_sink_template, "sink");
137
  gst_pad_set_setcaps_function (mulawdec->sinkpad, mulawdec_sink_setcaps);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
138
  gst_pad_set_chain_function (mulawdec->sinkpad, gst_mulawdec_chain);
139
140
141
  gst_element_add_pad (GST_ELEMENT (mulawdec), mulawdec->sinkpad);

  mulawdec->srcpad = gst_pad_new_from_template (mulawdec_src_template, "src");
142
  gst_pad_use_fixed_caps (mulawdec->srcpad);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
143
  gst_element_add_pad (GST_ELEMENT (mulawdec), mulawdec->srcpad);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
144
145
}

146
147
static GstFlowReturn
gst_mulawdec_chain (GstPad * pad, GstBuffer * buffer)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
148
149
150
151
{
  GstMuLawDec *mulawdec;
  gint16 *linear_data;
  guint8 *mulaw_data;
152
  guint mulaw_size;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
153
  GstBuffer *outbuf;
154
  GstFlowReturn ret;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
155

156
  mulawdec = GST_MULAWDEC (gst_pad_get_parent (pad));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
157

158
  mulaw_data = (guint8 *) GST_BUFFER_DATA (buffer);
159
160
161
162
163
164
165
166
167
  mulaw_size = GST_BUFFER_SIZE (buffer);

  outbuf = gst_buffer_new_and_alloc (mulaw_size * 2);
  linear_data = (gint16 *) GST_BUFFER_DATA (outbuf);

  /* copy discont flag */
  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);

168
  GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
169
170
171
172
173
  if (GST_BUFFER_DURATION (outbuf) == GST_CLOCK_TIME_NONE)
    GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (GST_SECOND,
        mulaw_size * 2, 2 * mulawdec->rate * mulawdec->channels);
  else
    GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
174
  gst_buffer_set_caps (outbuf, mulawdec->srccaps);
175

176
  mulaw_decode (mulaw_data, linear_data, mulaw_size);
177
178

  gst_buffer_unref (buffer);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
179

180
181
182
183
184
  ret = gst_pad_push (mulawdec->srcpad, outbuf);

  gst_object_unref (mulawdec);

  return ret;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
185
}
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

static GstStateChangeReturn
gst_mulawdec_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstMuLawDec *dec = GST_MULAWDEC (element);

  switch (transition) {
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  if (ret != GST_STATE_CHANGE_SUCCESS)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      if (dec->srccaps) {
        gst_caps_unref (dec->srccaps);
        dec->srccaps = NULL;
      }
      break;
    default:
      break;
  }

  return ret;
}