gstauparse.c 8.14 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
24
25
26
 * 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
 */

#include <stdlib.h>
#include <string.h>

27
#include <gstauparse.h>
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
28
29
30


/* elementfactory information */
31
static GstElementDetails gst_auparse_details = {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  ".au parser",
  "Parser/Audio",
  "Parse an .au file into raw audio",
  VERSION,
  "Erik Walthinsen <omega@cse.ogi.edu>",
  "(C) 1999",
};

static GstCaps*
au_typefind (GstBuffer *buf, gpointer private)
{
  GstCaps *new = NULL;
  gulong *head = (gulong *) GST_BUFFER_DATA (buf);

  if (*head == 0x2e736e64 || *head == 0x646e732e)
    new = gst_caps_new ("au_typefind", "audio/au", NULL);

  return new;
}

/* typefactory for 'au' */
static GstTypeDefinition audefinition = {
54
  "auparse_audio/au",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  "audio/au",
  ".au",
  au_typefind,
};

GST_PADTEMPLATE_FACTORY (sink_factory_templ,
  "sink",
  GST_PAD_SINK,
  GST_PAD_ALWAYS,
  GST_CAPS_NEW (
    "auparse_sink",
    "audio/au",
    NULL
  )
)


GST_PADTEMPLATE_FACTORY (src_factory_templ,
  "src",
  GST_PAD_SRC,
  GST_PAD_ALWAYS,
  GST_CAPS_NEW (
    "auparse_src",
    "audio/raw",
      "format",     GST_PROPS_STRING ("int"),
80
      "law",        GST_PROPS_INT_RANGE (0, 1),
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
      "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)
  )
)

99
/* AuParse signals and args */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
100
101
102
103
104
105
106
107
108
109
enum {
  /* FILL ME */
  LAST_SIGNAL
};

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

110
111
static void 	gst_auparse_class_init		(GstAuParseClass *klass);
static void 	gst_auparse_init		(GstAuParse *auparse);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
112

113
static void 	gst_auparse_chain		(GstPad *pad,GstBuffer *buf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
114
115

static GstElementClass *parent_class = NULL;
116
/*static guint gst_auparse_signals[LAST_SIGNAL] = { 0 }; */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
117
118

GType
119
gst_auparse_get_type (void) 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
120
{
121
  static GType auparse_type = 0;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
122

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

static void
140
gst_auparse_class_init (GstAuParseClass *klass) 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
141
142
143
144
145
146
147
148
149
{
  GstElementClass *gstelement_class;

  gstelement_class = (GstElementClass*) klass;

  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
}

static void 
150
gst_auparse_init (GstAuParse *auparse) 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
151
{
152
  auparse->sinkpad = gst_pad_new_from_template (
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
153
		  GST_PADTEMPLATE_GET (sink_factory_templ), "sink");
154
155
  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
156

157
  auparse->srcpad = gst_pad_new_from_template (
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
158
		  GST_PADTEMPLATE_GET (src_factory_templ), "src");
159
  gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
160

161
162
163
164
165
  auparse->offset = 0;
  auparse->size = 0;
  auparse->encoding = 0;
  auparse->frequency = 0;
  auparse->channels = 0;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
166
167
168
}

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

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

182
  auparse = GST_AUPARSE (gst_pad_get_parent (pad));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
183
  
184
  GST_DEBUG (0, "gst_auparse_chain: got buffer in '%s'",
185
          gst_element_get_name (GST_ELEMENT (auparse)));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
186
187
188
189
190

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

  /* if we haven't seen any data yet... */
191
  if (auparse->size == 0) {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
192
193
194
195
196
    GstBuffer *newbuf;
    gulong *head = (gulong *)data;

    /* normal format is big endian (au is a Sparc format) */
    if (GULONG_FROM_BE (*(head++)) == 0x2e736e64) {
197
198
199
200
201
202
      auparse->le = 0;
      auparse->offset 		= GULONG_FROM_BE (*(head++));
      auparse->size 		= GULONG_FROM_BE (*(head++));
      auparse->encoding 	= GULONG_FROM_BE (*(head++));
      auparse->frequency 	= GULONG_FROM_BE (*(head++));
      auparse->channels 	= GULONG_FROM_BE (*(head++));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
203
204
205

    /* but I wouldn't be surprised by a little endian version */
    } else if (GULONG_FROM_LE (*(head++)) == 0x2e736e64) {
206
207
208
209
210
211
      auparse->le = 1;
      auparse->offset 		= GULONG_FROM_LE(*(head++));
      auparse->size 		= GULONG_FROM_LE(*(head++));
      auparse->encoding 	= GULONG_FROM_LE(*(head++));
      auparse->frequency 	= GULONG_FROM_LE(*(head++));
      auparse->channels 	= GULONG_FROM_LE(*(head++));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
212
213
214
215
216
217
218
219

    } 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",
220
221
             auparse->offset,auparse->size,auparse->encoding,
             auparse->frequency,auparse->channels);
222
    GST_DEBUG (0, "offset %ld, size %ld, encoding %ld, frequency %ld, channels %ld",
223
224
             auparse->offset,auparse->size,auparse->encoding,
             auparse->frequency,auparse->channels);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
225
    
226
    switch (auparse->encoding) {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
227
      case 1:
228
229
230
	law = 1;
	depth = 8;
	sign = FALSE;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
231
232
	break;
      case 2:
233
234
235
	law = 0;
	depth = 8;
	sign = TRUE;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
236
237
	break;
      case 3:
238
239
240
	law = 0;
	depth = 16;
	sign = TRUE;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
241
242
243
244
245
246
	break;
      default:
	g_warning ("help!, dont know how to deal with this format yet\n");
	return;
    }

247
248
249
250
    tempcaps = GST_CAPS_NEW ("auparse_src",
		             "audio/raw",
			       "format",  	GST_PROPS_STRING ("int"),
      			       "endianness", 	GST_PROPS_INT (G_BYTE_ORDER),
251
252
			       "rate",  	GST_PROPS_INT (auparse->frequency),
			       "channels",  	GST_PROPS_INT (auparse->channels),
253
254
255
256
257
			       "law",  		GST_PROPS_INT (law),
			       "depth", 	GST_PROPS_INT (depth),
			       "width", 	GST_PROPS_INT (depth),
			       "signed", 	GST_PROPS_BOOLEAN (sign));

258
    if (!gst_pad_try_set_caps (auparse->srcpad, tempcaps)) {
259
      gst_buffer_unref (buf);
260
      gst_element_error (GST_ELEMENT (auparse), "could not set audio caps");
261
262
      return;
    }
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
263
264

    newbuf = gst_buffer_new ();
265
266
267
    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
268
269
270

    gst_buffer_unref (buf);

271
    gst_pad_push (auparse->srcpad, newbuf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
272
273
274
    return;
  }

275
  gst_pad_push (auparse->srcpad, buf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
276
277
278
279
280
281
282
283
284
285
}


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

  /* create the plugin structure */
286
287
288
  /* create an elementfactory for the auparse element and list it */
  factory = gst_elementfactory_new ("auparse", GST_TYPE_AUPARSE,
                                    &gst_auparse_details);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  g_return_val_if_fail (factory != NULL, FALSE);

  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_factory_templ));
  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_factory_templ));

  type = gst_typefactory_new (&audefinition);

  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,
305
  "auparse",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
306
307
308
  plugin_init
};