gstauparse.c 8.29 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
    GstBuffer *newbuf;
    gulong *head = (gulong *)data;

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

    /* but I wouldn't be surprised by a little endian version */
211
    } else if (GULONG_FROM_LE (head) == 0x2e736e64) {
212
      auparse->le = 1;
213
214
215
216
217
218
219
220
221
222
223
224
      head++;
      auparse->le = 0;
      auparse->offset 		= GULONG_FROM_LE (*head);
      head++;
      auparse->size 		= GULONG_FROM_LE (*head);
      head++;
      auparse->encoding 	= GULONG_FROM_LE (*head);
      head++;
      auparse->frequency 	= GULONG_FROM_LE (*head);
      head++;
      auparse->channels 	= GULONG_FROM_LE (*head);
      head++;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
225
226
227
228
229
230
231
232

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

260
261
262
263
    tempcaps = GST_CAPS_NEW ("auparse_src",
		             "audio/raw",
			       "format",  	GST_PROPS_STRING ("int"),
      			       "endianness", 	GST_PROPS_INT (G_BYTE_ORDER),
264
265
			       "rate",  	GST_PROPS_INT (auparse->frequency),
			       "channels",  	GST_PROPS_INT (auparse->channels),
266
267
268
269
270
			       "law",  		GST_PROPS_INT (law),
			       "depth", 	GST_PROPS_INT (depth),
			       "width", 	GST_PROPS_INT (depth),
			       "signed", 	GST_PROPS_BOOLEAN (sign));

271
    if (!gst_pad_try_set_caps (auparse->srcpad, tempcaps)) {
272
      gst_buffer_unref (buf);
273
      gst_element_error (GST_ELEMENT (auparse), "could not set audio caps");
274
275
      return;
    }
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
276
277

    newbuf = gst_buffer_new ();
278
279
280
    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
281
282
283

    gst_buffer_unref (buf);

284
    gst_pad_push (auparse->srcpad, newbuf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
285
286
287
    return;
  }

288
  gst_pad_push (auparse->srcpad, buf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
289
290
291
292
293
294
295
296
297
298
}


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

  /* create the plugin structure */
299
300
301
  /* 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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  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,
318
  "auparse",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
319
320
321
  plugin_init
};