2 * Copyright (C) <1999> Erik Walthinsen <omega@temple-baptist.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 /* #define GST_DEBUG_ENABLED */
25 #include <gst/bytestream/bytestream.h>
26 #include <gst/riff/riff.h>
28 #define GST_TYPE_AVI_PARSE \
29 (gst_avi_parse_get_type())
30 #define GST_AVI_PARSE(obj) \
31 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVI_PARSE,GstAviParse))
32 #define GST_AVI_PARSE_CLASS(klass) \
33 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVI_PARSE,GstAviParse))
34 #define GST_IS_AVI_PARSE(obj) \
35 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVI_PARSE))
36 #define GST_IS_AVI_PARSE_CLASS(obj) \
37 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVI_PARSE))
39 typedef struct _GstAviParse GstAviParse;
40 typedef struct _GstAviParseClass GstAviParseClass;
52 struct _GstAviParseClass {
53 GstElementClass parent_class;
56 /* elementfactory information */
57 static GstElementDetails gst_avi_parse_details = {
61 "Demultiplex an avi file into audio and video",
63 "Wim Taymans <wim.taymans@tvd.be>",
67 static GstCaps* avi_type_find (GstBuffer *buf, gpointer private);
69 /* typefactory for 'avi' */
70 static GstTypeDefinition avidefinition = {
77 /* AviParse signals and args */
89 GST_PAD_TEMPLATE_FACTORY (sink_templ,
96 "format", GST_PROPS_STRING ("AVI")
100 GST_PAD_TEMPLATE_FACTORY (src_templ,
107 "format", GST_PROPS_STRING ("AVI")
111 static void gst_avi_parse_class_init (GstAviParseClass *klass);
112 static void gst_avi_parse_init (GstAviParse *avi_parse);
114 static void gst_avi_parse_loop (GstElement *element);
116 static GstElementStateReturn
117 gst_avi_parse_change_state (GstElement *element);
119 static void gst_avi_parse_get_property (GObject *object, guint prop_id,
120 GValue *value, GParamSpec *pspec);
123 static GstElementClass *parent_class = NULL;
124 /*static guint gst_avi_parse_signals[LAST_SIGNAL] = { 0 }; */
127 gst_avi_parse_get_type(void)
129 static GType avi_parse_type = 0;
131 if (!avi_parse_type) {
132 static const GTypeInfo avi_parse_info = {
133 sizeof(GstAviParseClass),
136 (GClassInitFunc)gst_avi_parse_class_init,
141 (GInstanceInitFunc)gst_avi_parse_init,
143 avi_parse_type = g_type_register_static(GST_TYPE_ELEMENT, "GstAviParse", &avi_parse_info, 0);
145 return avi_parse_type;
149 gst_avi_parse_class_init (GstAviParseClass *klass)
151 GObjectClass *gobject_class;
152 GstElementClass *gstelement_class;
154 gobject_class = (GObjectClass*)klass;
155 gstelement_class = (GstElementClass*)klass;
157 g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_BITRATE,
158 g_param_spec_long ("bitrate","bitrate","bitrate",
159 G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); /* CHECKME */
161 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
163 gobject_class->get_property = gst_avi_parse_get_property;
165 gstelement_class->change_state = gst_avi_parse_change_state;
169 gst_avi_parse_init (GstAviParse *avi_parse)
171 GST_FLAG_SET (avi_parse, GST_ELEMENT_EVENT_AWARE);
173 avi_parse->sinkpad = gst_pad_new_from_template (
174 GST_PAD_TEMPLATE_GET (sink_templ), "sink");
175 gst_element_add_pad (GST_ELEMENT (avi_parse), avi_parse->sinkpad);
177 avi_parse->srcpad = gst_pad_new_from_template (
178 GST_PAD_TEMPLATE_GET (src_templ), "src");
179 gst_element_add_pad (GST_ELEMENT (avi_parse), avi_parse->srcpad);
181 gst_element_set_loop_function (GST_ELEMENT (avi_parse), gst_avi_parse_loop);
185 avi_type_find (GstBuffer *buf,
188 gchar *data = GST_BUFFER_DATA (buf);
191 GST_DEBUG (0,"avi_parse: typefind");
193 if (GUINT32_FROM_LE (((guint32 *)data)[0]) != GST_RIFF_TAG_RIFF)
195 if (GUINT32_FROM_LE (((guint32 *)data)[2]) != GST_RIFF_RIFF_AVI)
198 new = GST_CAPS_NEW ("avi_type_find",
200 "format", GST_PROPS_STRING ("AVI"));
205 gst_avi_parse_loop (GstElement *element)
207 GstAviParse *avi_parse;
210 gst_riff_chunk chunk;
214 g_return_if_fail (element != NULL);
215 g_return_if_fail (GST_IS_AVI_PARSE (element));
217 avi_parse = GST_AVI_PARSE (element);
221 pos = gst_bytestream_tell (rp->bs);
223 res = gst_riff_parse_next_chunk (rp, &chunk);
224 if (res == GST_RIFF_EOS) {
225 gst_element_set_eos (element);
230 case GST_RIFF_TAG_RIFF:
231 case GST_RIFF_TAG_LIST:
232 g_print ("%08llx: %4.4s %08x %4.4s\n", pos, (gchar *)&chunk.id, chunk.size, (gchar *)&chunk.type);
236 g_print ("%08llx: %4.4s %08x\n", pos, (gchar *)&chunk.id, chunk.size);
237 data_size = chunk.size;
241 if (GST_PAD_IS_USABLE (avi_parse->srcpad) && data_size) {
244 gst_riff_parse_peek (rp, &buf, data_size);
245 gst_pad_push (avi_parse->srcpad, buf);
247 data_size = (data_size + 1) & ~1;
249 gst_riff_parse_flush (rp, data_size);
252 static GstElementStateReturn
253 gst_avi_parse_change_state (GstElement *element)
255 GstAviParse *avi_parse = GST_AVI_PARSE (element);
257 switch (GST_STATE_TRANSITION (element)) {
258 case GST_STATE_NULL_TO_READY:
260 case GST_STATE_READY_TO_PAUSED:
261 avi_parse->rp = gst_riff_parse_new (avi_parse->sinkpad);
263 case GST_STATE_PAUSED_TO_PLAYING:
265 case GST_STATE_PLAYING_TO_PAUSED:
267 case GST_STATE_PAUSED_TO_READY:
268 gst_riff_parse_free (avi_parse->rp);
270 case GST_STATE_READY_TO_NULL:
276 parent_class->change_state (element);
278 return GST_STATE_SUCCESS;
282 gst_avi_parse_get_property (GObject *object, guint prop_id, GValue *value,
287 g_return_if_fail (GST_IS_AVI_PARSE (object));
289 src = GST_AVI_PARSE (object);
300 plugin_init (GModule *module, GstPlugin *plugin)
302 GstElementFactory *factory;
303 GstTypeFactory *type;
305 /* this filter needs the riff parser */
306 if (!gst_library_load ("gstbytestream"))
309 /* create an elementfactory for the avi_parse element */
310 factory = gst_element_factory_new ("aviparse", GST_TYPE_AVI_PARSE,
311 &gst_avi_parse_details);
312 g_return_val_if_fail (factory != NULL, FALSE);
313 gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_PRIMARY);
315 gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_templ));
316 gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_templ));
318 type = gst_type_factory_new (&avidefinition);
319 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
321 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
326 GstPluginDesc plugin_desc = {