gstauparse.c 8.47 KB
Newer Older
Andy Wingo Wingo's avatar
Andy Wingo Wingo 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
20
21
22
23
 * 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.
 */

/* 2001/04/03 - Updated parseau to use caps nego
 *              Zaheer Merali <zaheer@grid9.net
 */

24
25
26
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
27
28
29
#include <stdlib.h>
#include <string.h>

30
#include <gstauparse.h>
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
31
32
33


/* elementfactory information */
34
static GstElementDetails gst_auparse_details = {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
35
  ".au parser",
36
  "Codec/Parser",
37
  "LGPL",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
38
39
40
41
42
43
44
  "Parse an .au file into raw audio",
  VERSION,
  "Erik Walthinsen <omega@cse.ogi.edu>",
  "(C) 1999",
};

static GstCaps*
45
au_type_find (GstBuffer *buf, gpointer private)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
46
47
48
49
50
{
  GstCaps *new = NULL;
  gulong *head = (gulong *) GST_BUFFER_DATA (buf);

  if (*head == 0x2e736e64 || *head == 0x646e732e)
51
    new = gst_caps_new ("au_type_find", "audio/au", NULL);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
52
53
54
55
56
57

  return new;
}

/* typefactory for 'au' */
static GstTypeDefinition audefinition = {
58
  "auparse_audio/au",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
59
60
  "audio/au",
  ".au",
61
  au_type_find,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
62
63
};

64
GST_PAD_TEMPLATE_FACTORY (sink_factory_templ,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
65
66
67
68
69
70
71
72
73
74
75
  "sink",
  GST_PAD_SINK,
  GST_PAD_ALWAYS,
  GST_CAPS_NEW (
    "auparse_sink",
    "audio/au",
    NULL
  )
)


76
GST_PAD_TEMPLATE_FACTORY (src_factory_templ,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
77
78
79
80
81
82
83
  "src",
  GST_PAD_SRC,
  GST_PAD_ALWAYS,
  GST_CAPS_NEW (
    "auparse_src",
    "audio/raw",
      "format",     GST_PROPS_STRING ("int"),
84
      "law",        GST_PROPS_INT_RANGE (0, 1),
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
      "endianness", GST_PROPS_INT (G_BYTE_ORDER),
      "signed",     GST_PROPS_LIST(
		      GST_PROPS_BOOLEAN (FALSE),
		      GST_PROPS_BOOLEAN (TRUE)
	  	    ),
      "width",      GST_PROPS_LIST(
		      GST_PROPS_INT (8),
		      GST_PROPS_INT (16)
		    ),
      "depth",      GST_PROPS_LIST(
		      GST_PROPS_INT (8),
		      GST_PROPS_INT (16)
		    ),
      "rate",       GST_PROPS_INT_RANGE (8000,48000),
      "channels",   GST_PROPS_INT_RANGE (1, 2)
  )
)

103
/* AuParse signals and args */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
104
105
106
107
108
109
110
111
112
113
enum {
  /* FILL ME */
  LAST_SIGNAL
};

enum {
  ARG_0,
  /* FILL ME */
};

114
115
static void 	gst_auparse_class_init		(GstAuParseClass *klass);
static void 	gst_auparse_init		(GstAuParse *auparse);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
116

117
static void 	gst_auparse_chain		(GstPad *pad,GstBuffer *buf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
118
119

static GstElementClass *parent_class = NULL;
120
/*static guint gst_auparse_signals[LAST_SIGNAL] = { 0 }; */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
121
122

GType
123
gst_auparse_get_type (void) 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
124
{
125
  static GType auparse_type = 0;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
126

127
128
129
  if (!auparse_type) {
    static const GTypeInfo auparse_info = {
      sizeof(GstAuParseClass),      NULL,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
130
      NULL,
131
      (GClassInitFunc) gst_auparse_class_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
132
133
      NULL,
      NULL,
134
      sizeof(GstAuParse),
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
135
      0,
136
      (GInstanceInitFunc) gst_auparse_init,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
137
    };
138
    auparse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAuParse", &auparse_info, 0);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
139
  }
140
  return auparse_type;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
141
142
143
}

static void
144
gst_auparse_class_init (GstAuParseClass *klass) 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
145
146
147
148
149
150
151
152
153
{
  GstElementClass *gstelement_class;

  gstelement_class = (GstElementClass*) klass;

  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
}

static void 
154
gst_auparse_init (GstAuParse *auparse) 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
155
{
156
  auparse->sinkpad = gst_pad_new_from_template (
157
		  GST_PAD_TEMPLATE_GET (sink_factory_templ), "sink");
158
159
  gst_element_add_pad (GST_ELEMENT (auparse), auparse->sinkpad);
  gst_pad_set_chain_function (auparse->sinkpad, gst_auparse_chain);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
160

161
  auparse->srcpad = gst_pad_new_from_template (
162
		  GST_PAD_TEMPLATE_GET (src_factory_templ), "src");
163
  gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
164

165
166
167
168
169
  auparse->offset = 0;
  auparse->size = 0;
  auparse->encoding = 0;
  auparse->frequency = 0;
  auparse->channels = 0;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
170
171
172
}

static void 
173
gst_auparse_chain (GstPad *pad, GstBuffer *buf) 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
174
{
175
  GstAuParse *auparse;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
176
177
178
  gchar *data;
  glong size;
  GstCaps* tempcaps;
179
180
  gint law, depth;
  gboolean sign;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
181
182
183
184
185

  g_return_if_fail (pad != NULL);
  g_return_if_fail (GST_IS_PAD (pad));
  g_return_if_fail (buf != NULL);

186
  auparse = GST_AUPARSE (gst_pad_get_parent (pad));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
187
  
188
  GST_DEBUG ("gst_auparse_chain: got buffer in '%s'",
189
          gst_element_get_name (GST_ELEMENT (auparse)));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
190
191
192
193
194

  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);

  /* if we haven't seen any data yet... */
195
  if (auparse->size == 0) {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
196
    GstBuffer *newbuf;
197
    guint32 *head = (guint32 *)data;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
198
199

    /* normal format is big endian (au is a Sparc format) */
200
    if (GUINT32_FROM_BE (*head) == 0x2e736e64) {
201
      head++;
202
      auparse->le = 0;
203
      auparse->offset 		= GUINT32_FROM_BE (*head);
204
      head++;
205
      auparse->size 		= GUINT32_FROM_BE (*head);
206
      head++;
207
      auparse->encoding 	= GUINT32_FROM_BE (*head);
208
      head++;
209
      auparse->frequency 	= GUINT32_FROM_BE (*head);
210
      head++;
211
      auparse->channels 	= GUINT32_FROM_BE (*head);
212
      head++;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
213

214
215
216
    /* and of course, someone had to invent a little endian
     * version.  Used by DEC systems. */
    } else if (GUINT32_FROM_LE (*head) == 0x0064732E) {
217
      auparse->le = 1;
218
219
      head++;
      auparse->le = 0;
220
      auparse->offset 		= GUINT32_FROM_LE (*head);
221
      head++;
222
      auparse->size 		= GUINT32_FROM_LE (*head);
223
      head++;
224
      auparse->encoding 	= GUINT32_FROM_LE (*head);
225
      head++;
226
      auparse->frequency 	= GUINT32_FROM_LE (*head);
227
      head++;
228
      auparse->channels 	= GUINT32_FROM_LE (*head);
229
      head++;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
230
231
232
233
234
235
236
237

    } else {
      g_warning ("help, dunno what I'm looking at!\n");
      gst_buffer_unref(buf);
      return;
    }

    g_print ("offset %ld, size %ld, encoding %ld, frequency %ld, channels %ld\n",
238
239
             auparse->offset,auparse->size,auparse->encoding,
             auparse->frequency,auparse->channels);
240
    GST_DEBUG ("offset %ld, size %ld, encoding %ld, frequency %ld, channels %ld",
241
242
             auparse->offset,auparse->size,auparse->encoding,
             auparse->frequency,auparse->channels);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
243
    
244
    switch (auparse->encoding) {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
245
      case 1:
246
247
248
	law = 1;
	depth = 8;
	sign = FALSE;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
249
250
	break;
      case 2:
251
252
253
	law = 0;
	depth = 8;
	sign = TRUE;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
254
255
	break;
      case 3:
256
257
258
	law = 0;
	depth = 16;
	sign = TRUE;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
259
260
261
262
263
264
	break;
      default:
	g_warning ("help!, dont know how to deal with this format yet\n");
	return;
    }

265
266
267
268
    tempcaps = GST_CAPS_NEW ("auparse_src",
		             "audio/raw",
			       "format",  	GST_PROPS_STRING ("int"),
      			       "endianness", 	GST_PROPS_INT (G_BYTE_ORDER),
269
270
			       "rate",  	GST_PROPS_INT (auparse->frequency),
			       "channels",  	GST_PROPS_INT (auparse->channels),
271
272
273
274
275
			       "law",  		GST_PROPS_INT (law),
			       "depth", 	GST_PROPS_INT (depth),
			       "width", 	GST_PROPS_INT (depth),
			       "signed", 	GST_PROPS_BOOLEAN (sign));

276
    if (gst_pad_try_set_caps (auparse->srcpad, tempcaps) <= 0) {
277
      gst_buffer_unref (buf);
278
      gst_element_error (GST_ELEMENT (auparse), "could not set audio caps");
279
280
      return;
    }
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
281
282

    newbuf = gst_buffer_new ();
283
284
285
    GST_BUFFER_DATA (newbuf) = (gpointer) malloc (size-(auparse->offset));
    memcpy (GST_BUFFER_DATA (newbuf), data+24, size-(auparse->offset));
    GST_BUFFER_SIZE (newbuf) = size-(auparse->offset);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
286
287
288

    gst_buffer_unref (buf);

289
    gst_pad_push (auparse->srcpad, newbuf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
290
291
292
    return;
  }

293
  gst_pad_push (auparse->srcpad, buf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
294
295
296
297
298
299
300
301
302
303
}


static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
  GstElementFactory *factory;
  GstTypeFactory *type;

  /* create the plugin structure */
304
  /* create an elementfactory for the auparse element and list it */
305
  factory = gst_element_factory_new ("auparse", GST_TYPE_AUPARSE,
306
                                    &gst_auparse_details);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
307
  g_return_val_if_fail (factory != NULL, FALSE);
308
  gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_SECONDARY);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
309

310
311
  gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_factory_templ));
  gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_factory_templ));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
312

313
  type = gst_type_factory_new (&audefinition);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
314
315
316
317
318
319
320
321
322
323

  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));

  return TRUE;
}

GstPluginDesc plugin_desc = {
  GST_VERSION_MAJOR,
  GST_VERSION_MINOR,
324
  "auparse",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
325
326
327
  plugin_init
};