Initial revision
authorAndy Wingo <wingo@pobox.com>
Sat, 22 Dec 2001 23:22:30 +0000 (23:22 +0000)
committerAndy Wingo <wingo@pobox.com>
Sat, 22 Dec 2001 23:22:30 +0000 (23:22 +0000)
Original commit message from CVS:
Initial revision

15 files changed:
gst/avi/.gitignore [new file with mode: 0644]
gst/avi/Makefile.am [new file with mode: 0644]
gst/avi/README [new file with mode: 0644]
gst/avi/README_win32dll [new file with mode: 0644]
gst/avi/audiocodecs.c [new file with mode: 0644]
gst/avi/gstaviaudiodecoder.c [new file with mode: 0644]
gst/avi/gstaviaudiodecoder.h [new file with mode: 0644]
gst/avi/gstavidecoder.c [new file with mode: 0644]
gst/avi/gstavidecoder.h [new file with mode: 0644]
gst/avi/gstavidemux.c [new file with mode: 0644]
gst/avi/gstavidemux.h [new file with mode: 0644]
gst/avi/gstavimux.c [new file with mode: 0644]
gst/avi/gstavimux.h [new file with mode: 0644]
gst/avi/gstavitypes.c [new file with mode: 0644]
gst/avi/gstavitypes.h [new file with mode: 0644]

diff --git a/gst/avi/.gitignore b/gst/avi/.gitignore
new file mode 100644 (file)
index 0000000..3df96ad
--- /dev/null
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+codectest
diff --git a/gst/avi/Makefile.am b/gst/avi/Makefile.am
new file mode 100644 (file)
index 0000000..16ef66e
--- /dev/null
@@ -0,0 +1,31 @@
+if HAVE_AVIFILE
+ARCHSUBDIRS = wincodec
+else
+ARCHSUBDIRS =
+endif
+
+SUBDIRS = $(ARCHSUBDIRS) winaudio
+DIST_SUBDIRS = wincodec winaudio
+
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstavimux.la libgstavidecoder.la libgstavidemux.la libgstavitypes.la libgstaviaudiodecoder.la
+
+libgstavidemux_la_SOURCES = gstavidemux.c 
+libgstavitypes_la_SOURCES = gstavitypes.c 
+libgstavidecoder_la_SOURCES = gstavidecoder.c 
+libgstavimux_la_SOURCES = gstavimux.c 
+libgstaviaudiodecoder_la_SOURCES = gstaviaudiodecoder.c 
+
+noinst_HEADERS = gstavidecoder.h gstavimux.h gstavitypes.h gstavidemux.h gstaviaudiodecoder.h
+
+#CFLAGS += -Wall -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions -ffast-math -DNDEBUG
+libgstavidecoder_la_CFLAGS = -O2 -ffast-math $(GST_CFLAGS)
+libgstavidemux_la_CFLAGS = -O2 -ffast-math $(GST_CFLAGS)
+libgstavitypes_la_CFLAGS = -O2 -ffast-math $(GST_CFLAGS)
+libgstavimux_la_CFLAGS = -O2 -ffast-math $(GST_CFLAGS)
+libgstaviaudiodecoder_la_CFLAGS = -O2 -ffast-math $(GST_CFLAGS)
+
+EXTRA_DIST = README_win32dll README
+
+noinst_HEADERS = aviaudiodecoder.h
diff --git a/gst/avi/README b/gst/avi/README
new file mode 100644 (file)
index 0000000..7ccd620
--- /dev/null
@@ -0,0 +1,72 @@
+The avi decoder plugins 
+-----------------------
+
+The avi decoder consists of a set of gstreamer plugins:
+
+ - demuxer (avidemux)
+ - avi to gstreamer type converter (avitypes)
+ - windows dlls wrappers.
+
+the avidecoder element uses the above plugins to perform the avi
+decoding. It is constructed as a custom bin which initially only has
+the demuxer element in it. The demuxer has a set of padtemplates for
+raw audio and video.
+
+  (------------------------------------)
+  ! avidecoder                         !
+  !                                 (video/raw)...
+  !     (----------)                   !
+  !     ! demuxer (video/avi, auds)..  !
+  !     !          !                   !
+  !   -src         !                   !
+  !  /  !         (video/avi, vids)..  !
+ - src  !          !                   !
+  !     (----------)                (audio/raw)...
+  !                                    !
+  (------------------------------------)
+
+the demuxer has a set of padtemplates for the raw avi header properties.
+
+The avi decoder will act on the new_pad signal of the demuxer element
+and will attach an avitype plugin to the new pad. Caps negotiation will
+convert the raw avi caps to the gstreamer caps. If the src pad of the
+avitypes plugin are compatible with the avidecoder padtemplate, the 
+avitype pad is ghosted to the avidecoder bin, this is the case where no
+codec is needed (for raw PCM samples, for example).
+
+When the avitypes caps are not compatible with one of the avidecoder 
+templates, a static autoplugger is used the find an element to connect
+the demuxers pad to the decoders padtemplate.
+
+When no element could be found, an windec plugin is attached to the 
+demuxers pad and the avitypes plugin is removed from the decoder.
+
+
+example:
+--------
+
+ An avidecoder that has a video pad (decoded with windows dlls) and an
+ audio pad (raw PCM).
+
+  (----------------------------------------------------------------)
+  ! avidecoder               (--------)    (------)                !
+  !                          !avitypes!    !windec!       /-- (video/raw)
+  !     (----------)     /-sink      src--sink   src -----         !
+  !     !demuxer (video/avi, !        !    !      !                !
+  !     !          ! auds).. (--------)    (------)                !  
+  !   -sink        !         (--------)                            !
+  !  /  !        (video/avi, !avitypes!                            !
+ -sink  !          ! vids).. !        !                            !
+  !     (----------)     \-sink      src -------------------- (audio/raw)
+  !                          (--------)                            !
+  (----------------------------------------------------------------)
+
+
+
+TODO
+----
+
+automatically generate the padtemplates from all possible avi types
+found in the registry.
+
+
diff --git a/gst/avi/README_win32dll b/gst/avi/README_win32dll
new file mode 100644 (file)
index 0000000..ed34a3b
--- /dev/null
@@ -0,0 +1,3 @@
+The current win32 dll loader don't work with all versions availble
+out there. Make sure to get the windows dll where divxc32.dll has the date
+older than 24 january 2000. The 24 january one does currently not work.
diff --git a/gst/avi/audiocodecs.c b/gst/avi/audiocodecs.c
new file mode 100644 (file)
index 0000000..9415055
--- /dev/null
@@ -0,0 +1,189 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+
+//#define DEBUG_ENABLED
+
+
+#include <wine/winbase.h>
+#include <wine/winerror.h>
+#include <wine/driver.h>
+#include <wine/msacm.h>
+#define WIN32
+#include <gstavidecoder.h>
+
+typedef struct _GstWinLoaderAudioData GstWinLoaderAudioData;
+
+struct _GstWinLoaderAudioData {
+  guchar ext_info[64];
+  WAVEFORMATEX wf;
+  HACMSTREAM srcstream;
+  GstPad *out;
+};
+
+
+static GstPad *gst_avi_decoder_get_audio_srcpad_MPEG(GstAviDecoder *avi_decoder, guint pad_nr, GstPadTemplate *temp);
+static GstPad *gst_avi_decoder_get_audio_srcpad_winloader(GstAviDecoder *avi_decoder, guint pad_nr, gst_riff_strf_auds *strf, GstPadTemplate *temp);
+static void gst_avi_decoder_winloader_audio_chain(GstPad *pad, GstBuffer *buf);
+
+GstPad *gst_avi_decoder_get_audio_srcpad(GstAviDecoder *avi_decoder, guint pad_nr, gst_riff_strf_auds *strf, GstPadTemplate *temp) 
+{
+  GstPad *newpad;
+
+  switch (strf->format) {
+    case GST_RIFF_WAVE_FORMAT_PCM:
+      newpad = gst_pad_new("audio_00", GST_PAD_SRC);
+      gst_pad_set_caps (newpad, gst_caps_new (
+                             "avidecoder_caps",
+                             "audio/raw",
+                             gst_props_new (
+                                     "format",         GST_PROPS_STRING ("int"),
+                                       "law",          GST_PROPS_INT (0),
+                                       "endianness",   GST_PROPS_INT (G_BYTE_ORDER),
+                                       "signed",       GST_PROPS_BOOLEAN (TRUE),
+                                       "width",        GST_PROPS_INT ((gint)strf->size),
+                                       "depth",        GST_PROPS_INT ((gint)strf->size),
+                                       "rate",         GST_PROPS_INT ((gint)strf->rate),
+                                       "channels",     GST_PROPS_INT ((gint)strf->channels),
+                                       NULL)));
+
+      avi_decoder->audio_pad[pad_nr] = newpad;
+      return newpad;
+    case GST_RIFF_WAVE_FORMAT_MPEGL12:
+    case GST_RIFF_WAVE_FORMAT_MPEGL3:
+      return gst_avi_decoder_get_audio_srcpad_MPEG(avi_decoder, pad_nr, temp);
+    default:
+      newpad = gst_avi_decoder_get_audio_srcpad_winloader(avi_decoder, pad_nr, strf, temp); 
+      if (newpad) return newpad;
+      printf("audio format %04x not supported\n", strf->format);
+      break;
+  }
+  return NULL;
+}
+
+static GstPad *gst_avi_decoder_get_audio_srcpad_MPEG(GstAviDecoder *avi_decoder, guint pad_nr, GstPadTemplate *temp) 
+{
+  GstElement *parse_audio, *decode;
+  GstPad *srcpad, *sinkpad, *newpad;
+
+  parse_audio = gst_elementfactory_make("mp3parse", "parse_audio");
+  g_return_val_if_fail(parse_audio != NULL, NULL);
+  decode = gst_elementfactory_make("mpg123", "decode_audio");
+  g_return_val_if_fail(decode != NULL, NULL);
+
+  gst_element_set_state(GST_ELEMENT(gst_object_get_parent(GST_OBJECT(avi_decoder))), GST_STATE_PAUSED);
+
+  gst_bin_add(GST_BIN(gst_object_get_parent(GST_OBJECT(avi_decoder))), parse_audio);
+  gst_bin_add(GST_BIN(gst_object_get_parent(GST_OBJECT(avi_decoder))), decode);
+
+  newpad = gst_pad_new("video", GST_PAD_SRC);
+  gst_pad_set_parent(newpad, GST_OBJECT(avi_decoder));
+
+  sinkpad = gst_element_get_pad(parse_audio,"sink");
+  gst_pad_connect(gst_element_get_pad(parse_audio,"src"),
+                  gst_element_get_pad(decode,"sink"));
+  gst_pad_set_chain_function (gst_element_get_pad(parse_audio,"src"),
+                              GST_RPAD_CHAINFUNC (gst_element_get_pad(decode,"sink")));
+  srcpad = gst_element_get_pad(decode,"src");
+
+  gst_pad_connect(newpad, sinkpad);
+  gst_pad_set_name(srcpad, "audio_00");
+  gst_pad_set_chain_function (newpad, GST_RPAD_CHAINFUNC (sinkpad));
+
+  avi_decoder->audio_pad[pad_nr] = newpad;
+  gst_element_set_state(GST_ELEMENT(gst_object_get_parent(GST_OBJECT(avi_decoder))), GST_STATE_PLAYING);
+
+  return srcpad;
+}
+
+static GstPad *gst_avi_decoder_get_audio_srcpad_winloader(GstAviDecoder *avi_decoder, guint pad_nr, gst_riff_strf_auds *strf, GstPadTemplate *temp) 
+{
+  HRESULT h;
+  GstWinLoaderAudioData *data;
+  GstPad *sinkpad, *newpad;
+
+  if (!gst_library_load("winloader")) {
+    gst_info("audiocodecs: could not load support library: 'winloader'\n");
+    return NULL;
+  }
+  gst_info("audiocodecs: winloader loaded\n");
+
+  avi_decoder->extra_data = g_malloc0(sizeof(GstWinLoaderAudioData));
+
+  data = (GstWinLoaderAudioData *)avi_decoder->extra_data;
+
+  memcpy(data->ext_info, strf, sizeof(WAVEFORMATEX));
+  memset(data->ext_info+18, 0, 32);
+
+  if (strf->rate == 0) 
+    return NULL;
+
+  data->wf.nChannels=strf->channels;
+  data->wf.nSamplesPerSec=strf->rate;
+  data->wf.nAvgBytesPerSec=2*data->wf.nSamplesPerSec*data->wf.nChannels;
+  data->wf.wFormatTag=strf->format;
+  data->wf.nBlockAlign=strf->blockalign;
+  data->wf.wBitsPerSample=strf->av_bps;
+  data->wf.cbSize=0;
+
+  gst_info("audiocodecs: trying to open library %p\n", data);
+  h = acmStreamOpen(
+           &data->srcstream,
+           (HACMDRIVER)NULL,       
+           (WAVEFORMATEX*)data->ext_info,  
+           (WAVEFORMATEX*)&data->wf,  
+           NULL,  
+           0,     
+           0,     
+           0);
+
+  if(h != S_OK)
+  {
+     if(h == ACMERR_NOTPOSSIBLE) {
+       printf("audiocodecs:: Unappropriate audio format\n");
+     }
+     printf("audiocodecs:: acmStreamOpen error\n");
+     return NULL;
+  }
+
+  newpad = gst_pad_new("audio", GST_PAD_SINK);
+  gst_pad_set_parent(newpad, GST_OBJECT(avi_decoder));
+  gst_pad_set_chain_function(newpad, gst_avi_decoder_winloader_audio_chain);
+
+  sinkpad = gst_pad_new("audio_00", GST_PAD_SRC);
+  gst_pad_set_parent(sinkpad, GST_OBJECT(avi_decoder));
+  gst_pad_connect(newpad, sinkpad);
+  gst_pad_set_chain_function (newpad, GST_RPAD_CHAINFUNC (sinkpad));
+
+  //gst_pad_connect(newpad, sinkpad);
+  avi_decoder->audio_pad[pad_nr] = newpad;
+
+  data->out = sinkpad;
+
+  GST_DEBUG (0,"gst_avi_decoder: pads created\n");
+  return sinkpad;
+}
+
+static void gst_avi_decoder_winloader_audio_chain(GstPad *pad, GstBuffer *buf) 
+{
+
+  GST_DEBUG (0,"gst_avi_decoder: got buffer %08lx %p\n", *(gulong *)GST_BUFFER_DATA(buf), GST_BUFFER_DATA(buf));
+  gst_buffer_unref(buf);  
+}
diff --git a/gst/avi/gstaviaudiodecoder.c b/gst/avi/gstaviaudiodecoder.c
new file mode 100644 (file)
index 0000000..0626774
--- /dev/null
@@ -0,0 +1,195 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+//#define GST_DEBUG_ENABLED
+#include <string.h>
+
+#include "gstaviaudiodecoder.h"
+
+
+
+/* elementfactory information */
+static GstElementDetails gst_avi_audio_decoder_details = {
+  ".avi parser",
+  "Parser/Video",
+  "Parse a .avi file into audio and video",
+  VERSION,
+  "Erik Walthinsen <omega@cse.ogi.edu>\n"
+  "Wim Taymans <wim.taymans@tvd.be>",
+  "(C) 1999",
+};
+
+/* AviAudioDecoder signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  /* FILL ME */
+};
+
+GST_PADTEMPLATE_FACTORY (sink_templ,
+  "sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "avidecoder_sink",
+     "video/avi",
+      "format", GST_PROPS_STRING ("strf_auds")
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (src_audio_templ,
+  "src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "src_audio",
+    "audio/raw",
+      "format",           GST_PROPS_STRING ("int"),
+       "law",              GST_PROPS_INT (0),
+       "endianness",       GST_PROPS_INT (G_BYTE_ORDER),
+       "signed",           GST_PROPS_BOOLEAN (TRUE),
+       "width",            GST_PROPS_INT (16),
+       "depth",            GST_PROPS_INT (16),
+       "rate",             GST_PROPS_INT_RANGE (11025, 44100),
+       "channels",         GST_PROPS_INT_RANGE (1, 2)
+  )
+)
+
+static void    gst_avi_audio_decoder_class_init        (GstAviAudioDecoderClass *klass);
+static void    gst_avi_audio_decoder_init              (GstAviAudioDecoder *avi_audio_decoder);
+
+static void    gst_avi_audio_decoder_chain             (GstPad *pad, GstBuffer *buf);
+
+static void     gst_avi_audio_decoder_get_property      (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_avi_audio_decoder_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_avi_audio_decoder_get_type(void) 
+{
+  static GType avi_audio_decoder_type = 0;
+
+  if (!avi_audio_decoder_type) {
+    static const GTypeInfo avi_audio_decoder_info = {
+      sizeof(GstAviAudioDecoderClass),      
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_avi_audio_decoder_class_init,
+      NULL,
+      NULL,
+      sizeof(GstAviAudioDecoder),
+      0,
+      (GInstanceInitFunc)gst_avi_audio_decoder_init,
+    };
+    avi_audio_decoder_type = g_type_register_static(GST_TYPE_ELEMENT, "GstAviAudioDecoder", &avi_audio_decoder_info, 0);
+  }
+  return avi_audio_decoder_type;
+}
+
+static void
+gst_avi_audio_decoder_class_init (GstAviAudioDecoderClass *klass) 
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_BIN);
+  
+  gobject_class->get_property = gst_avi_audio_decoder_get_property;
+}
+
+static void 
+gst_avi_audio_decoder_init (GstAviAudioDecoder *avi_audio_decoder) 
+{
+}
+
+static void
+gst_avi_audio_decoder_chain (GstPad *pad,
+                      GstBuffer *buf)
+{
+  GstAviAudioDecoder *avi_audio_decoder;
+  guchar *data;
+  gulong size;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD(pad));
+  g_return_if_fail (buf != NULL);
+  g_return_if_fail (GST_BUFFER_DATA(buf) != NULL);
+
+  avi_audio_decoder = GST_AVI_AUDIO_DECODER (gst_pad_get_parent (pad));
+  GST_DEBUG (0,"gst_avi_audio_decoder_chain: got buffer in %u\n", GST_BUFFER_OFFSET (buf));
+  g_print ("gst_avi_audio_decoder_chain: got buffer in %u\n", GST_BUFFER_OFFSET (buf));
+  data = (guchar *)GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  gst_buffer_unref (buf);
+}
+
+static void     
+gst_avi_audio_decoder_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstAviAudioDecoder *src;
+
+  g_return_if_fail (GST_IS_AVI_AUDIO_DECODER (object));
+
+  src = GST_AVI_AUDIO_DECODER (object);
+
+  switch(prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+
+  /* create an elementfactory for the avi_audio_decoder element */
+  factory = gst_elementfactory_new ("aviaudiodecoder",GST_TYPE_AVI_AUDIO_DECODER,
+                                    &gst_avi_audio_decoder_details);
+  g_return_val_if_fail (factory != NULL, FALSE);
+
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_templ));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_audio_templ));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "aviaudiodecoder",
+  plugin_init
+};
+
diff --git a/gst/avi/gstaviaudiodecoder.h b/gst/avi/gstaviaudiodecoder.h
new file mode 100644 (file)
index 0000000..0f98c23
--- /dev/null
@@ -0,0 +1,65 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+#ifndef __GST_AVI_AUDIO_DECODER_H__
+#define __GST_AVI_AUDIO_DECODER_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+#include <libs/riff/gstriff.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GST_TYPE_AVI_AUDIO_DECODER \
+  (gst_avi_audio_decoder_get_type())
+#define GST_AVI_AUDIO_DECODER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVI_AUDIO_DECODER,GstAviAudioDecoder))
+#define GST_AVI_AUDIO_DECODER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVI_AUDIO_DECODER,GstAviAudioDecoder))
+#define GST_IS_AVI_AUDIO_DECODER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVI_AUDIO_DECODER))
+#define GST_IS_AVI_AUDIO_DECODER_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVI_AUDIO_DECODER))
+
+
+typedef struct _GstAviAudioDecoder GstAviAudioDecoder;
+typedef struct _GstAviAudioDecoderClass GstAviAudioDecoderClass;
+
+struct _GstAviAudioDecoder {
+  GstBin bin;
+
+};
+
+struct _GstAviAudioDecoderClass {
+  GstBinClass parent_class;
+};
+
+GType          gst_avi_audio_decoder_get_type          (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_AVI_AUDIO_DECODER_H__ */
diff --git a/gst/avi/gstavidecoder.c b/gst/avi/gstavidecoder.c
new file mode 100644 (file)
index 0000000..e9210a7
--- /dev/null
@@ -0,0 +1,367 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+//#define GST_DEBUG_ENABLED
+#include <string.h>
+
+#include "gstavidecoder.h"
+
+
+
+/* elementfactory information */
+static GstElementDetails gst_avi_decoder_details = {
+  ".avi decoder",
+  "Decoder/Video",
+  "Decodes a .avi file into audio and video",
+  VERSION,
+  "Erik Walthinsen <omega@cse.ogi.edu>\n"
+  "Wim Taymans <wim.taymans@tvd.be>",
+  "(C) 1999",
+};
+
+static GstCaps* avi_typefind (GstBuffer *buf, gpointer private);
+
+/* typefactory for 'avi' */
+static GstTypeDefinition avidefinition = {
+  "avidecoder_video/avi",
+  "video/avi",
+  ".avi",
+  avi_typefind,
+};
+
+/* AviDecoder signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_BITRATE,
+  ARG_MEDIA_TIME,
+  ARG_CURRENT_TIME,
+  /* FILL ME */
+};
+
+GST_PADTEMPLATE_FACTORY (sink_templ,
+  "sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "avidecoder_sink",
+     "video/avi",
+     NULL
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (src_video_templ,
+  "video_src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "wincodec_src",
+    "video/raw",
+      "format",         GST_PROPS_LIST (
+                          GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','2')),
+                          GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
+                          GST_PROPS_FOURCC (GST_MAKE_FOURCC ('R','G','B',' '))
+                        ),
+      "width",          GST_PROPS_INT_RANGE (16, 4096),
+      "height",         GST_PROPS_INT_RANGE (16, 4096)
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (src_audio_templ,
+  "audio_src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "src_audio",
+    "audio/raw",
+      "format",           GST_PROPS_STRING ("int"),
+      "law",              GST_PROPS_INT (0),
+      "endianness",       GST_PROPS_INT (G_BYTE_ORDER),
+      "signed",           GST_PROPS_LIST (
+                           GST_PROPS_BOOLEAN (TRUE),
+                           GST_PROPS_BOOLEAN (FALSE)
+                         ),
+      "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 (11025, 48000),
+      "channels",         GST_PROPS_INT_RANGE (1, 2)
+  )
+)
+
+static void    gst_avi_decoder_class_init      (GstAviDecoderClass *klass);
+static void    gst_avi_decoder_init            (GstAviDecoder *avi_decoder);
+
+static void     gst_avi_decoder_get_property    (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_avi_decoder_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_avi_decoder_get_type(void) 
+{
+  static GType avi_decoder_type = 0;
+
+  if (!avi_decoder_type) {
+    static const GTypeInfo avi_decoder_info = {
+      sizeof(GstAviDecoderClass),      
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_avi_decoder_class_init,
+      NULL,
+      NULL,
+      sizeof(GstAviDecoder),
+      0,
+      (GInstanceInitFunc)gst_avi_decoder_init,
+    };
+    avi_decoder_type = g_type_register_static(GST_TYPE_BIN, "GstAviDecoder", &avi_decoder_info, 0);
+  }
+  return avi_decoder_type;
+}
+
+static void
+gst_avi_decoder_class_init (GstAviDecoderClass *klass) 
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_BITRATE,
+    g_param_spec_long ("bitrate","bitrate","bitrate",
+                     G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); // CHECKME
+  g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_MEDIA_TIME,
+    g_param_spec_long ("media_time","media_time","media_time",
+                     G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); // CHECKME
+  g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_CURRENT_TIME,
+    g_param_spec_long ("current_time","current_time","current_time",
+                     G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); // CHECKME
+
+  parent_class = g_type_class_ref (GST_TYPE_BIN);
+  
+  gobject_class->get_property = gst_avi_decoder_get_property;
+}
+
+static void 
+gst_avi_decoder_new_pad (GstElement *element, GstPad *pad, GstAviDecoder *avi_decoder) 
+{
+  GstCaps *caps;
+  GstCaps *targetcaps = NULL;
+  const gchar *format;
+  gboolean type_found;
+  GstElement *type;
+  GstElement *new_element = NULL;
+  gchar *padname = NULL;
+  gchar *gpadname = NULL;
+#define AVI_TYPE_VIDEO  1
+#define AVI_TYPE_AUDIO  2
+  gint media_type = 0;
+  
+  GST_DEBUG (0, "avidecoder: new pad for element \"%s\"\n", gst_element_get_name (element));
+
+  caps = gst_pad_get_caps (pad);
+  format = gst_caps_get_string (caps, "format");
+
+  if (!strcmp (format, "strf_vids")) { 
+    targetcaps = gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_video_templ));
+    media_type = AVI_TYPE_VIDEO;
+    gpadname = g_strdup_printf ("video_%02d", avi_decoder->count);
+  }
+  else if (!strcmp (format, "strf_auds")) {
+    targetcaps = gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_audio_templ));
+    media_type = AVI_TYPE_AUDIO;
+    gpadname = g_strdup_printf ("audio_%02d", avi_decoder->count);
+  }
+  else if (!strcmp (format, "strf_iavs")) {
+    targetcaps = gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_video_templ));
+    media_type = AVI_TYPE_VIDEO;
+    gpadname = g_strdup_printf ("video_%02d", avi_decoder->count);
+  }
+  else {
+    g_assert_not_reached ();
+  }
+
+  gst_element_set_state (GST_ELEMENT (avi_decoder), GST_STATE_PAUSED);
+
+  type = gst_elementfactory_make ("avitypes", 
+                 g_strdup_printf ("typeconvert%d", avi_decoder->count));
+
+  gst_pad_connect (pad, gst_element_get_pad (type, "sink"));
+  type_found = gst_util_get_bool_arg (G_OBJECT (type), "type_found");
+
+  if (type_found) {
+
+    gst_bin_add (GST_BIN (avi_decoder), type);
+    
+    pad = gst_element_get_pad (type, "src");
+    caps = gst_pad_get_caps (pad);
+
+    if (gst_caps_check_compatibility (caps, targetcaps)) {
+      gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), 
+           gst_element_get_pad (type, "src"), gpadname);
+
+      avi_decoder->count++;
+      goto done;
+    }
+#ifndef GST_DISABLE_AUTOPLUG
+    else {
+      GstAutoplug *autoplug;
+      autoplug = gst_autoplugfactory_make("static");
+
+      new_element = gst_autoplug_to_caps (autoplug, caps, targetcaps, NULL);
+
+      padname = "src_00";
+    }
+#endif // GST_DISABLE_AUTOPLUG
+  }
+
+  if (!new_element && (media_type == AVI_TYPE_VIDEO)) {
+    gst_pad_disconnect (pad, gst_element_get_pad (type, "sink"));
+
+    new_element = gst_elementfactory_make ("windec", "decoder");
+
+    padname = "src";
+  }
+  else if (!new_element && (media_type == AVI_TYPE_AUDIO)) {
+    //FIXME
+    padname = "src";
+  }
+
+  if (new_element) {
+    gst_pad_connect (pad, gst_element_get_pad (new_element, "sink"));
+    gst_element_set_name (new_element, g_strdup_printf ("element%d", avi_decoder->count));
+    gst_bin_add (GST_BIN (avi_decoder), new_element);
+
+    gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), 
+           gst_element_get_pad (new_element, padname), gpadname);
+
+    avi_decoder->count++;
+  }
+  else {
+    g_warning ("avidecoder: could not autoplug\n");
+  }
+
+done: 
+  gst_element_set_state (GST_ELEMENT (avi_decoder), GST_STATE_PLAYING);
+}
+
+static void 
+gst_avi_decoder_init (GstAviDecoder *avi_decoder) 
+{
+  avi_decoder->demuxer = gst_elementfactory_make ("avidemux", "demux");
+
+  if (avi_decoder->demuxer) {
+    gst_bin_add (GST_BIN (avi_decoder), avi_decoder->demuxer);
+
+    gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), 
+                   gst_element_get_pad (avi_decoder->demuxer, "sink"), "sink");
+
+    g_signal_connect (G_OBJECT (avi_decoder->demuxer),"new_pad", G_CALLBACK (gst_avi_decoder_new_pad),
+                   avi_decoder);
+  }
+  else {
+    g_warning ("wow!, no avi demuxer found. help me\n");
+  }
+
+  avi_decoder->count = 0;
+}
+
+static GstCaps*
+avi_typefind (GstBuffer *buf,
+              gpointer private)
+{
+  gchar *data = GST_BUFFER_DATA (buf);
+  GstCaps *new;
+
+  GST_DEBUG (0,"avi_decoder: typefind\n");
+  if (strncmp (&data[0], "RIFF", 4)) return NULL;
+  if (strncmp (&data[8], "AVI ", 4)) return NULL;
+
+  new = gst_caps_new ("avi_typefind","video/avi", NULL);
+
+  return new;
+}
+
+static void
+gst_avi_decoder_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstAviDecoder *src;
+
+  g_return_if_fail (GST_IS_AVI_DECODER (object));
+
+  src = GST_AVI_DECODER (object);
+
+  switch(prop_id) {
+    case ARG_BITRATE:
+      break;
+    case ARG_MEDIA_TIME:
+      g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer), "media_time"));
+      break;
+    case ARG_CURRENT_TIME:
+      g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer), "current_time"));
+      break;
+    default:
+      break;
+  }
+}
+
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+  GstTypeFactory *type;
+
+  /* create an elementfactory for the avi_decoder element */
+  factory = gst_elementfactory_new ("avidecoder", GST_TYPE_AVI_DECODER,
+                                    &gst_avi_decoder_details);
+  g_return_val_if_fail (factory != NULL, FALSE);
+
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_audio_templ));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_video_templ));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_templ));
+
+  type = gst_typefactory_new (&avidefinition);
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "avidecoder",
+  plugin_init
+};
+
diff --git a/gst/avi/gstavidecoder.h b/gst/avi/gstavidecoder.h
new file mode 100644 (file)
index 0000000..bd18c5c
--- /dev/null
@@ -0,0 +1,67 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+#ifndef __GST_AVI_DECODER_H__
+#define __GST_AVI_DECODER_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_AVI_DECODER \
+  (gst_avi_decoder_get_type())
+#define GST_AVI_DECODER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVI_DECODER,GstAviDecoder))
+#define GST_AVI_DECODER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVI_DECODER,GstAviDecoder))
+#define GST_IS_AVI_DECODER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVI_DECODER))
+#define GST_IS_AVI_DECODER_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVI_DECODER))
+
+
+typedef struct _GstAviDecoder GstAviDecoder;
+typedef struct _GstAviDecoderClass GstAviDecoderClass;
+
+struct _GstAviDecoder {
+  GstBin element;
+
+  GstElement *demuxer;
+
+  gint count;
+};
+
+struct _GstAviDecoderClass {
+  GstBinClass parent_class;
+};
+
+GType          gst_avi_decoder_get_type                (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_AVI_DECODER_H__ */
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
new file mode 100644 (file)
index 0000000..1aca1ad
--- /dev/null
@@ -0,0 +1,757 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+//#define GST_DEBUG_ENABLED
+#include <string.h>
+
+#include "gstavidemux.h"
+
+
+/* elementfactory information */
+static GstElementDetails gst_avi_demux_details = {
+  ".avi parser",
+  "Parser/Video",
+  "Parse a .avi file into audio and video",
+  VERSION,
+  "Erik Walthinsen <omega@cse.ogi.edu>\n"
+  "Wim Taymans <wim.taymans@tvd.be>",
+  "(C) 1999",
+};
+
+static GstCaps* avi_typefind (GstBuffer *buf, gpointer private);
+
+/* typefactory for 'avi' */
+static GstTypeDefinition avidefinition = {
+  "avidemux_video/avi",
+  "video/avi",
+  ".avi",
+  avi_typefind,
+};
+
+/* AviDemux signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_BITRATE,
+  ARG_MEDIA_TIME,
+  ARG_CURRENT_TIME,
+  /* FILL ME */
+};
+
+GST_PADTEMPLATE_FACTORY (sink_templ,
+  "sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "avidemux_sink",
+     "video/avi",
+     NULL
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (src_video_templ,
+  "video_[00-32]",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "src_video",
+    "video/avi",
+      "format",  GST_PROPS_LIST (
+                  GST_PROPS_STRING ("strf_vids"),
+                  GST_PROPS_STRING ("strf_iavs")
+                )
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (src_audio_templ,
+  "src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "src_audio",
+    "video/avi",
+      "format", GST_PROPS_STRING ("strf_auds")
+  )
+)
+
+static void    gst_avi_demux_class_init        (GstAviDemuxClass *klass);
+static void    gst_avi_demux_init              (GstAviDemux *avi_demux);
+
+static void    gst_avi_demux_loop              (GstElement *element);
+
+static void     gst_avi_demux_get_property      (GObject *object, guint prop_id,       
+                                                GValue *value, GParamSpec *pspec);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_avi_demux_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_avi_demux_get_type(void) 
+{
+  static GType avi_demux_type = 0;
+
+  if (!avi_demux_type) {
+    static const GTypeInfo avi_demux_info = {
+      sizeof(GstAviDemuxClass),      
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_avi_demux_class_init,
+      NULL,
+      NULL,
+      sizeof(GstAviDemux),
+      0,
+      (GInstanceInitFunc)gst_avi_demux_init,
+    };
+    avi_demux_type = g_type_register_static(GST_TYPE_ELEMENT, "GstAviDemux", &avi_demux_info, 0);
+  }
+  return avi_demux_type;
+}
+
+static void
+gst_avi_demux_class_init (GstAviDemuxClass *klass) 
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_BITRATE,
+    g_param_spec_long ("bitrate","bitrate","bitrate",
+                       G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); // CHECKME
+  g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_MEDIA_TIME,
+    g_param_spec_long ("media_time","media_time","media_time",
+                       G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); // CHECKME
+  g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_CURRENT_TIME,
+    g_param_spec_long ("current_time","current_time","current_time",
+                       G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); // CHECKME
+
+  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  
+  gobject_class->get_property = gst_avi_demux_get_property;
+}
+
+static void 
+gst_avi_demux_init (GstAviDemux *avi_demux) 
+{
+  guint i;
+
+  GST_FLAG_SET (avi_demux, GST_ELEMENT_EVENT_AWARE);
+                               
+  avi_demux->sinkpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (sink_templ), "sink");
+  gst_element_add_pad (GST_ELEMENT (avi_demux), avi_demux->sinkpad);
+
+  gst_element_set_loop_function (GST_ELEMENT (avi_demux), gst_avi_demux_loop);
+
+  avi_demux->state = GST_AVI_DEMUX_UNKNOWN;
+  avi_demux->num_audio_pads = 0;
+  avi_demux->num_video_pads = 0;
+  avi_demux->next_time = 0;
+  avi_demux->flags = 0;
+  avi_demux->index_entries = NULL;
+  avi_demux->index_size = 0;
+  avi_demux->resync_offset = 0;
+
+  //GST_FLAG_SET( GST_OBJECT (avi_demux), GST_ELEMENT_NO_SEEK);
+
+  for(i=0; i<GST_AVI_DEMUX_MAX_AUDIO_PADS; i++) 
+    avi_demux->audio_pad[i] = NULL;
+
+  for(i=0; i<GST_AVI_DEMUX_MAX_VIDEO_PADS; i++) 
+    avi_demux->video_pad[i] = NULL;
+
+}
+
+static GstCaps*
+avi_typefind (GstBuffer *buf,
+              gpointer private)
+{
+  gchar *data = GST_BUFFER_DATA (buf);
+  GstCaps *new;
+
+  GST_DEBUG (0,"avi_demux: typefind\n");
+
+  if (GUINT32_FROM_LE (((guint32 *)data)[0]) != GST_RIFF_TAG_RIFF)
+    return NULL;
+  if (GUINT32_FROM_LE (((guint32 *)data)[2]) != GST_RIFF_RIFF_AVI)
+    return NULL;
+
+  new = gst_caps_new ("avi_typefind","video/avi", NULL);
+
+  return new;
+}
+
+static gboolean
+gst_avi_demux_avih (GstAviDemux *avi_demux)
+{
+  gst_riff_avih *avih;
+  GstByteStream *bs = avi_demux->bs;
+
+  avih = (gst_riff_avih *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_avih));
+  if (avih) {
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: avih tag found");
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  us_frame    %d", GUINT32_FROM_LE (avih->us_frame));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  max_bps     %d", GUINT32_FROM_LE (avih->max_bps));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  pad_gran    %d", GUINT32_FROM_LE (avih->pad_gran));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  flags       0x%08x", GUINT32_FROM_LE (avih->flags));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  tot_frames  %d", GUINT32_FROM_LE (avih->tot_frames));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  init_frames %d", GUINT32_FROM_LE (avih->init_frames));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  streams     %d", GUINT32_FROM_LE (avih->streams));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  bufsize     %d", GUINT32_FROM_LE (avih->bufsize));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  width       %d", GUINT32_FROM_LE (avih->width));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  height      %d", GUINT32_FROM_LE (avih->height));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  scale       %d", GUINT32_FROM_LE (avih->scale));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  rate        %d", GUINT32_FROM_LE (avih->rate));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  start       %d", GUINT32_FROM_LE (avih->start));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  length      %d", GUINT32_FROM_LE (avih->length));
+
+    avi_demux->time_interval = GUINT32_FROM_LE (avih->us_frame);
+    avi_demux->tot_frames = GUINT32_FROM_LE (avih->tot_frames);
+    avi_demux->flags = GUINT32_FROM_LE (avih->flags);
+
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static gboolean 
+gst_avi_demux_strh (GstAviDemux *avi_demux)
+{
+  gst_riff_strh *strh;
+  GstByteStream *bs = avi_demux->bs;
+
+  strh = (gst_riff_strh *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_strh));
+  if (strh) {
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strh tag found");
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  type        0x%08x (%s)", 
+                 GUINT32_FROM_LE (strh->type), gst_riff_id_to_fourcc (strh->type));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  fcc_handler 0x%08x (%s)", 
+                 GUINT32_FROM_LE (strh->fcc_handler), gst_riff_id_to_fourcc (strh->fcc_handler));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  flags       0x%08x", GUINT32_FROM_LE (strh->flags));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  priority    %d", GUINT32_FROM_LE (strh->priority));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  init_frames %d", GUINT32_FROM_LE (strh->init_frames));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  scale       %d", GUINT32_FROM_LE (strh->scale));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  rate        %d", GUINT32_FROM_LE (strh->rate));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  start       %d", GUINT32_FROM_LE (strh->start));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  length      %d", GUINT32_FROM_LE (strh->length));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  bufsize     %d", GUINT32_FROM_LE (strh->bufsize));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  quality     %d", GUINT32_FROM_LE (strh->quality));
+    GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  samplesize  %d", GUINT32_FROM_LE (strh->samplesize));
+
+    avi_demux->fcc_type = GUINT32_FROM_LE (strh->type);
+
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static void 
+gst_avi_demux_strf_vids (GstAviDemux *avi_demux)
+{
+  gst_riff_strf_vids *strf;
+  GstPad *srcpad;
+  GstByteStream *bs = avi_demux->bs;
+
+  strf = (gst_riff_strf_vids *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_strf_vids));
+
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context vids");
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  size        %d", GUINT32_FROM_LE (strf->size));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  width       %d", GUINT32_FROM_LE (strf->width));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  height      %d", GUINT32_FROM_LE (strf->height));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  planes      %d", GUINT16_FROM_LE (strf->planes));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  bit_cnt     %d", GUINT16_FROM_LE (strf->bit_cnt));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  compression 0x%08x (%s)", 
+                 GUINT32_FROM_LE (strf->compression), gst_riff_id_to_fourcc (strf->compression));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  image_size  %d", GUINT32_FROM_LE (strf->image_size));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  xpels_meter %d", GUINT32_FROM_LE (strf->xpels_meter));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  ypels_meter %d", GUINT32_FROM_LE (strf->ypels_meter));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  num_colors  %d", GUINT32_FROM_LE (strf->num_colors));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  imp_colors  %d", GUINT32_FROM_LE (strf->imp_colors));
+
+  srcpad =  gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d", 
+                         avi_demux->num_video_pads));
+
+  gst_pad_set_caps (srcpad, gst_caps_new (
+                         "avidec_video_src",
+                         "video/avi",
+                         gst_props_new (
+                           "format",           GST_PROPS_STRING ("strf_vids"),
+                             "size",           GST_PROPS_INT (GUINT32_FROM_LE (strf->size)),
+                             "width",          GST_PROPS_INT (GUINT32_FROM_LE (strf->width)),
+                             "height",         GST_PROPS_INT (GUINT32_FROM_LE (strf->height)),
+                             "planes",         GST_PROPS_INT (GUINT16_FROM_LE (strf->planes)),
+                             "bit_cnt",        GST_PROPS_INT (GUINT16_FROM_LE (strf->bit_cnt)),
+                             "compression",    GST_PROPS_FOURCC (GUINT32_FROM_LE (strf->compression)),
+                             "image_size",     GST_PROPS_INT (GUINT32_FROM_LE (strf->image_size)),
+                             "xpels_meter",    GST_PROPS_INT (GUINT32_FROM_LE (strf->xpels_meter)),
+                             "ypels_meter",    GST_PROPS_INT (GUINT32_FROM_LE (strf->ypels_meter)),
+                             "num_colors",     GST_PROPS_INT (GUINT32_FROM_LE (strf->num_colors)),
+                             "imp_colors",     GST_PROPS_INT (GUINT32_FROM_LE (strf->imp_colors)),
+                             NULL)));
+
+  avi_demux->video_pad[avi_demux->num_video_pads++] = srcpad;
+  gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
+}
+
+static void 
+gst_avi_demux_strf_auds (GstAviDemux *avi_demux)
+{
+  gst_riff_strf_auds *strf;
+  GstPad *srcpad;
+  GstByteStream *bs = avi_demux->bs;
+
+  strf = (gst_riff_strf_auds *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_strf_auds));
+
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context auds");
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  format      %d", GUINT16_FROM_LE (strf->format));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  channels    %d", GUINT16_FROM_LE (strf->channels));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  rate        %d", GUINT32_FROM_LE (strf->rate));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  av_bps      %d", GUINT32_FROM_LE (strf->av_bps));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  blockalign  %d", GUINT16_FROM_LE (strf->blockalign));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  size        %d", GUINT16_FROM_LE (strf->size));
+
+  srcpad =  gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (src_audio_templ), g_strdup_printf ("audio_%02d", 
+                         avi_demux->num_audio_pads));
+
+  gst_pad_set_caps (srcpad, gst_caps_new (
+                         "avidec_audio_src",
+                         "video/avi",
+                         gst_props_new (
+                           "format",           GST_PROPS_STRING ("strf_auds"),
+                             "fmt",            GST_PROPS_INT (GUINT16_FROM_LE (strf->format)),
+                             "channels",       GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)),
+                             "rate",           GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)),
+                             "av_bps",         GST_PROPS_INT (GUINT32_FROM_LE (strf->av_bps)),
+                             "blockalign",     GST_PROPS_INT (GUINT16_FROM_LE (strf->blockalign)),
+                             "size",           GST_PROPS_INT (GUINT16_FROM_LE (strf->size)),
+                             NULL)));
+
+  avi_demux->audio_pad[avi_demux->num_audio_pads++] = srcpad;
+  gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
+}
+
+static void 
+gst_avi_demux_strf_iavs (GstAviDemux *avi_demux)
+{
+  gst_riff_strf_iavs *strf;
+  GstPad *srcpad;
+  GstByteStream *bs = avi_demux->bs;
+
+  strf = (gst_riff_strf_iavs *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_strf_iavs));
+
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context iavs");
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxSrc   %08x", GUINT32_FROM_LE (strf->DVAAuxSrc));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxCtl   %08x", GUINT32_FROM_LE (strf->DVAAuxCtl));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxSrc1  %08x", GUINT32_FROM_LE (strf->DVAAuxSrc1));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxCtl1  %08x", GUINT32_FROM_LE (strf->DVAAuxCtl1));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVVAuxSrc   %08x", GUINT32_FROM_LE (strf->DVVAuxSrc));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVVAuxCtl   %08x", GUINT32_FROM_LE (strf->DVVAuxCtl));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVReserved1 %08x", GUINT32_FROM_LE (strf->DVReserved1));
+  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVReserved2 %08x", GUINT32_FROM_LE (strf->DVReserved2));
+
+  srcpad =  gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d", 
+                         avi_demux->num_video_pads));
+
+  gst_pad_set_caps (srcpad, gst_caps_new (
+                         "avidec_iav_src",
+                         "video/avi",
+                         gst_props_new (
+                           "format",           GST_PROPS_STRING ("strf_iavs"),
+                              "DVAAuxSrc",     GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc)),
+                              "DVAAuxCtl",     GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl)),
+                              "DVAAuxSrc1",    GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc1)),
+                              "DVAAuxCtl1",    GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl1)),
+                              "DVVAuxSrc",     GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxSrc)),
+                              "DVVAuxCtl",     GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxCtl)),
+                              "DVReserved1",   GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved1)),
+                              "DVReserved2",   GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved2)),
+                             NULL)));
+
+  avi_demux->video_pad[avi_demux->num_video_pads++] = srcpad;
+  gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
+}
+
+static void
+gst_avidemux_parse_index (GstAviDemux *avi_demux,
+                           gulong offset)
+{
+  GstBuffer *buf;
+  gulong index_size;
+
+  buf = gst_pad_pullregion (avi_demux->sinkpad, GST_REGION_OFFSET_LEN, offset, 8);
+
+  if (!buf || GST_BUFFER_OFFSET (buf) != offset || GST_BUFFER_SIZE (buf) != 8) {
+    GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not get index");
+    return;
+  }
+
+  if (gst_riff_fourcc_to_id (GST_BUFFER_DATA (buf)) != GST_RIFF_TAG_idx1) {
+    GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: no index found");
+    return;
+  }
+
+  index_size = GUINT32_FROM_LE(*(guint32 *)(GST_BUFFER_DATA (buf) + 4));
+
+  buf = gst_pad_pullregion(avi_demux->sinkpad, GST_REGION_OFFSET_LEN, offset+8, index_size);
+
+  avi_demux->index_size = index_size/sizeof(gst_riff_index_entry);
+
+  GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: index size %lu", avi_demux->index_size);
+
+  avi_demux->index_entries = g_malloc (GST_BUFFER_SIZE (buf));
+  memcpy (avi_demux->index_entries, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+
+  buf = gst_pad_pullregion(avi_demux->sinkpad, GST_REGION_OFFSET_LEN, avi_demux->index_offset, 0);
+}
+
+static inline gboolean 
+gst_avidemux_read_chunk (GstByteStream *bs, guint32 *id, guint32 *size)
+{
+  gst_riff_chunk *chunk;
+
+  chunk = (gst_riff_chunk *) gst_bytestream_peek_bytes (bs, sizeof (gst_riff_chunk));
+  if (chunk) {
+    *id =   GUINT32_FROM_LE (chunk->id);
+    *size = GUINT32_FROM_LE (chunk->size);
+
+    gst_bytestream_flush (bs, sizeof (gst_riff_chunk));
+
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static void
+gst_avidemux_forall_pads (GstAviDemux *avi_demux, GFunc func, gpointer user_data)
+{
+  gint i;
+  GstPad *pad;
+  
+  for(i=0; i<GST_AVI_DEMUX_MAX_AUDIO_PADS; i++) {
+    pad = avi_demux->audio_pad[i];
+    if (pad && GST_PAD_CONNECTED (pad)) {
+      (*func) (pad, user_data);
+    }
+  }
+
+  for(i=0; i<GST_AVI_DEMUX_MAX_VIDEO_PADS; i++) {
+    pad = avi_demux->video_pad[i];
+    if (pad && GST_PAD_CONNECTED (pad)) {
+      (*func) (pad, user_data);
+    }
+  }
+}
+
+static void
+gst_avidemux_queue_event_func (GstPad *pad, gpointer user_data)
+{
+  GstEventType type = GPOINTER_TO_INT (user_data);
+
+  gst_pad_push (pad, GST_BUFFER (gst_event_new (type)));
+}
+
+static gboolean
+gst_avidemux_handle_event (GstAviDemux *avi_demux)
+{
+  guint32 remaining;
+  GstEvent *event;
+  GstEventType type;
+  
+  gst_bytestream_get_status (avi_demux->bs, &remaining, &event);
+
+  type = event? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
+
+  switch (type) {
+    case GST_EVENT_EOS:
+      gst_element_set_state (GST_ELEMENT (avi_demux), GST_STATE_PAUSED);
+      g_warning ("eos event\n");
+      gst_avidemux_forall_pads (avi_demux, (GFunc) gst_avidemux_queue_event_func, GINT_TO_POINTER (GST_EVENT_EOS));
+      break;
+    case GST_EVENT_SEEK:
+      g_warning ("seek event\n");
+      break;
+    case GST_EVENT_FLUSH:
+      g_warning ("flush event\n");
+      break;
+    case GST_EVENT_DISCONTINUOUS:
+      g_warning ("discont event\n");
+      break;
+    default:
+      g_warning ("unhandled event %d\n", type);
+      break;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_avidemux_process_chunk (GstAviDemux *avi_demux, guint64 filepos,
+                            guint32 desired_tag,
+                            gint rec_depth, guint32 *chunksize)
+{
+  guint32 chunkid;     
+  guint64 datapos;
+  GstByteStream *bs = avi_demux->bs;
+
+  if (!gst_avidemux_read_chunk (bs, &chunkid, chunksize)) {
+    printf ("  *****  Error reading chunk at filepos 0x%08llx\n", filepos);
+    return FALSE;
+  }
+  if (desired_tag) {           /* do we have to test identity? */
+    if (desired_tag != chunkid) {
+      printf ("\n\n *** Error: Expected chunk '%08x', found '%08x'\n",
+             desired_tag, chunkid);
+      return FALSE;
+    }
+  }
+
+  GST_INFO (GST_CAT_PLUGIN_INFO, "chunkid %s, size %08x, filepos %08llx", 
+                 gst_riff_id_to_fourcc (chunkid), *chunksize, filepos);
+
+  datapos = filepos + sizeof (guint32) + sizeof (guint32);
+
+  switch (chunkid) {
+    case GST_RIFF_TAG_RIFF:
+    case GST_RIFF_TAG_LIST:
+    {
+      guint32 datashowed;
+      guint32 subchunksize;    /* size of a read subchunk             */
+
+      // flush the form type
+      if (!gst_bytestream_flush (bs, sizeof (guint32)))
+       return FALSE;
+
+      datashowed = sizeof (guint32);   /* we showed the form type      */
+      datapos += datashowed;   /* for the rest of the routine  */
+
+      while (datashowed < *chunksize) {        /* while not showed all: */
+
+       guint32 subchunklen;    /* complete size of a subchunk  */
+
+       /* recurse for subchunks of RIFF and LIST chunks: */
+       if (!gst_avidemux_process_chunk (avi_demux, datapos, 0,
+                          rec_depth + 1, &subchunksize))
+         return FALSE;
+
+       subchunklen = sizeof (guint32) + sizeof (guint32) + ((subchunksize + 1) & ~1);
+
+       datashowed += subchunklen;
+       datapos += subchunklen;
+      }
+      *chunksize -= datashowed;
+      break;
+    }
+    case GST_RIFF_TAG_avih:
+      gst_avi_demux_avih (avi_demux);
+      break;
+    case GST_RIFF_TAG_strh:
+    {
+      gst_avi_demux_strh (avi_demux);
+      break;
+    }
+    case GST_RIFF_TAG_strf:
+      switch (avi_demux->fcc_type) {
+        case GST_RIFF_FCC_vids:
+          gst_avi_demux_strf_vids (avi_demux);
+         break;
+        case GST_RIFF_FCC_auds:
+          gst_avi_demux_strf_auds (avi_demux);
+         break;
+        case GST_RIFF_FCC_iavs:
+          gst_avi_demux_strf_iavs (avi_demux);
+         break;
+       case GST_RIFF_FCC_pads:
+       case GST_RIFF_FCC_txts:
+       default:
+          GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux_chain: strh type %s not supported", gst_riff_id_to_fourcc (avi_demux->fcc_type));
+         break;
+      }
+      break;
+    case GST_RIFF_00dc:
+    case GST_RIFF_00db:
+    case GST_RIFF_00__:
+    {
+      GST_DEBUG (0,"gst_avi_demux_chain: tag found %08x size %08x\n",
+                   chunkid, *chunksize);
+
+      if (GST_PAD_CONNECTED (avi_demux->video_pad[0])) {
+       GstBuffer *buf;
+
+       if (*chunksize) {
+          buf = gst_bytestream_peek (bs, *chunksize);
+       }
+       else {
+          buf = gst_buffer_new ();
+       }
+        GST_BUFFER_TIMESTAMP (buf) = avi_demux->next_time;
+        avi_demux->next_time += avi_demux->time_interval;
+
+        if (avi_demux->video_need_flush[0]) {
+          avi_demux->video_need_flush[0] = FALSE;
+         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
+        }
+
+        GST_DEBUG (0,"gst_avi_demux_chain: send video buffer %08x\n", *chunksize);
+        gst_pad_push(avi_demux->video_pad[0], buf);
+        GST_DEBUG (0,"gst_avi_demux_chain: sent video buffer %08x %p\n",
+                     *chunksize, &avi_demux->video_pad[0]);
+        avi_demux->current_frame++;
+      }
+      *chunksize = (*chunksize + 1) & ~1;
+      break;
+    }
+    case GST_RIFF_01wb:
+    {
+      GST_DEBUG (0,"gst_avi_demux_chain: tag found %08x size %08x\n",
+                   chunkid, *chunksize);
+
+      if (GST_PAD_CONNECTED (avi_demux->audio_pad[0])) {
+       GstBuffer *buf;
+
+       if (*chunksize) {
+          buf = gst_bytestream_peek (bs, *chunksize);
+       }
+       else {
+          buf = gst_buffer_new ();
+       }
+
+        if (avi_demux->audio_need_flush[0]) {
+         GST_DEBUG (0,"audio flush\n");
+          avi_demux->audio_need_flush[0] = FALSE;
+         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
+        }
+
+        GST_DEBUG (0,"gst_avi_demux_chain: send audio buffer %08x\n", *chunksize);
+        gst_pad_push (avi_demux->audio_pad[0], buf);
+        GST_DEBUG (0,"gst_avi_demux_chain: sent audio buffer %08x\n", *chunksize);
+      }
+      *chunksize = (*chunksize + 1) & ~1;
+      break;
+    }
+    default:
+      printf ("  *****  unknown chunkid %08x (%s)\n", chunkid, gst_riff_id_to_fourcc (chunkid));
+      break;
+  }
+  GST_INFO (GST_CAT_PLUGIN_INFO, "chunkid %s, flush %08x, filepos %08llx", 
+                 gst_riff_id_to_fourcc (chunkid), *chunksize, filepos);
+
+  if (!gst_bytestream_flush (bs, *chunksize)) {
+    return gst_avidemux_handle_event (avi_demux);
+  }
+
+  return TRUE;
+}
+
+static void
+gst_avi_demux_loop (GstElement *element)
+{
+  GstAviDemux *avi_demux;
+  guint32 chunksize;
+
+  g_return_if_fail (element != NULL);
+  g_return_if_fail (GST_IS_AVI_DEMUX (element));
+
+  avi_demux = GST_AVI_DEMUX (element);
+
+  avi_demux->bs = gst_bytestream_new (avi_demux->sinkpad);
+
+  do {
+    if (!gst_avidemux_process_chunk (avi_demux, 0, GST_RIFF_TAG_RIFF, 0, &chunksize)) {
+      GST_INFO (GST_CAT_PLUGIN_INFO, "sorry, isn't AVI");
+      break;
+    }
+  } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element));
+
+  gst_bytestream_destroy (avi_demux->bs);
+}
+
+static void
+gst_avi_demux_get_property (GObject *object, guint prop_id, GValue *value,
+                           GParamSpec *pspec)
+{
+  GstAviDemux *src;
+
+  g_return_if_fail (GST_IS_AVI_DEMUX (object));
+
+  src = GST_AVI_DEMUX (object);
+
+  switch (prop_id) {
+    case ARG_BITRATE:
+      break;
+    case ARG_MEDIA_TIME:
+      g_value_set_long (value, (src->tot_frames * src->time_interval) / 1000000);
+      break;
+    case ARG_CURRENT_TIME:
+      g_value_set_long (value, (src->current_frame * src->time_interval) / 1000000);
+      break;
+    default:
+      break;
+  }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+  GstTypeFactory *type;
+
+  /* this filter needs the riff parser */
+  if (!gst_library_load ("gstbytestream")) {
+    gst_info("avidemux: could not load support library: 'gstbytestream'\n");
+    return FALSE;
+  }
+  if (!gst_library_load ("gstriff")) {
+    gst_info("avidemux: could not load support library: 'gstriff'\n");
+    return FALSE;
+  }
+
+  /* create an elementfactory for the avi_demux element */
+  factory = gst_elementfactory_new ("avidemux",GST_TYPE_AVI_DEMUX,
+                                    &gst_avi_demux_details);
+  g_return_val_if_fail (factory != NULL, FALSE);
+
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_audio_templ));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_video_templ));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_templ));
+
+  type = gst_typefactory_new (&avidefinition);
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "avidemux",
+  plugin_init
+};
+
diff --git a/gst/avi/gstavidemux.h b/gst/avi/gstavidemux.h
new file mode 100644 (file)
index 0000000..d06172b
--- /dev/null
@@ -0,0 +1,109 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+#ifndef __GST_AVI_DEMUX_H__
+#define __GST_AVI_DEMUX_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+#include <libs/riff/gstriff.h>
+#include <libs/bytestream/gstbytestream.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GST_TYPE_AVI_DEMUX \
+  (gst_avi_demux_get_type())
+#define GST_AVI_DEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVI_DEMUX,GstAviDemux))
+#define GST_AVI_DEMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVI_DEMUX,GstAviDemux))
+#define GST_IS_AVI_DEMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVI_DEMUX))
+#define GST_IS_AVI_DEMUX_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVI_DEMUX))
+
+
+#define GST_AVI_DEMUX_UNKNOWN          0       /* initialized state */
+#define GST_AVI_DEMUX_REGULAR          1       /* regular parsing */
+#define GST_AVI_DEMUX_HDRL             2
+#define GST_AVI_DEMUX_STRL             3
+#define GST_AVI_DEMUX_MOVI             4
+#define GST_AVI_DEMUX_AVIH             5
+#define GST_AVI_DEMUX_STRH_VIDS                6
+#define GST_AVI_DEMUX_STRH_AUDS                7
+#define GST_AVI_DEMUX_STRH_IAVS                8
+
+#define GST_AVI_DEMUX_MAX_AUDIO_PADS   8       
+#define GST_AVI_DEMUX_MAX_VIDEO_PADS   8       
+
+typedef struct _GstAviDemux GstAviDemux;
+typedef struct _GstAviDemuxClass GstAviDemuxClass;
+
+struct _GstAviDemux {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+
+  /* AVI decoding state */
+  gint state;
+  guint32 fcc_type;
+
+  GstByteStream *bs;
+
+  gst_riff_index_entry *index_entries;
+  gulong index_size;
+  gulong index_offset;
+  gulong resync_offset;
+
+  guint64 next_time;
+  guint64 time_interval;
+  gulong tot_frames;
+  gulong current_frame;
+
+  guint32 flags;
+
+  guint num_audio_pads;
+  guint num_video_pads;
+  guint num_iavs_pads;
+  GstPad       *audio_pad[GST_AVI_DEMUX_MAX_AUDIO_PADS];
+  gboolean     audio_need_flush[GST_AVI_DEMUX_MAX_AUDIO_PADS];
+
+  GstPad       *video_pad[GST_AVI_DEMUX_MAX_VIDEO_PADS];
+  gboolean     video_need_flush[GST_AVI_DEMUX_MAX_VIDEO_PADS];
+
+  gpointer extra_data;
+};
+
+struct _GstAviDemuxClass {
+  GstElementClass parent_class;
+};
+
+GType          gst_avi_demux_get_type          (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_AVI_DEMUX_H__ */
diff --git a/gst/avi/gstavimux.c b/gst/avi/gstavimux.c
new file mode 100644 (file)
index 0000000..c7e8101
--- /dev/null
@@ -0,0 +1,376 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gstavimux.h"
+
+
+
+/* elementfactory information */
+static GstElementDetails 
+gst_avimux_details = 
+{
+  ".avi mux",
+  "Mux/Video",
+  "Encodes audio and video into an avi stream",
+  VERSION,
+  "Wim Taymans <wim.taymans@chello.be>",
+  "(C) 2000",
+};
+
+/* AviMux signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  /* FILL ME */
+};
+
+GST_PADTEMPLATE_FACTORY (src_factory,
+  "src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "sink_video",
+    "video/avi",
+    NULL
+  )
+)
+    
+GST_PADTEMPLATE_FACTORY (video_sink_factory,
+  "video_%02d",
+  GST_PAD_SINK,
+  GST_PAD_REQUEST,
+  GST_CAPS_NEW (
+    "sink_video",
+    "video/avi",
+      "format",   GST_PROPS_STRING ("strf_vids")
+  )
+)
+    
+GST_PADTEMPLATE_FACTORY (audio_sink_factory,
+  "audio_%02d",
+  GST_PAD_SINK,
+  GST_PAD_REQUEST,
+  GST_CAPS_NEW (
+    "sink_audio",
+    "video/avi",
+      "format",   GST_PROPS_STRING ("strf_auds")
+  )
+)
+    
+
+static void    gst_avimux_class_init           (GstAviMuxClass *klass);
+static void    gst_avimux_init                 (GstAviMux *avimux);
+
+static void    gst_avimux_chain                (GstPad *pad, GstBuffer *buf);
+static GstPad*         gst_avimux_request_new_pad      (GstElement *element, GstPadTemplate *templ, const gchar *name);
+       
+static void     gst_avimux_set_property         (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void     gst_avimux_get_property         (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_avimux_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_avimux_get_type (void) 
+{
+  static GType avimux_type = 0;
+
+  if (!avimux_type) {
+    static const GTypeInfo avimux_info = {
+      sizeof(GstAviMuxClass),      
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_avimux_class_init,
+      NULL,
+      NULL,
+      sizeof(GstAviMux),
+      0,
+      (GInstanceInitFunc)gst_avimux_init,
+    };
+    avimux_type = g_type_register_static(GST_TYPE_ELEMENT, "GstAviMux", &avimux_info, 0);
+  }
+  return avimux_type;
+}
+
+static void
+gst_avimux_class_init (GstAviMuxClass *klass) 
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+
+  gobject_class->set_property = gst_avimux_set_property;
+  gobject_class->get_property = gst_avimux_get_property;
+
+  gstelement_class->request_new_pad = gst_avimux_request_new_pad;
+}
+
+static void 
+gst_avimux_init (GstAviMux *avimux) 
+{
+  avimux->srcpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (src_factory), "src");
+  gst_element_add_pad (GST_ELEMENT (avimux), avimux->srcpad);
+
+  avimux->state = GST_AVIMUX_INITIAL;
+  avimux->riff = NULL;
+  avimux->num_audio_pads = 0;
+  avimux->num_video_pads = 0;
+  avimux->next_time = 0;
+
+  avimux->riff = gst_riff_encoder_new (GST_RIFF_RIFF_AVI);
+  avimux->aviheader = g_malloc0 (sizeof (gst_riff_avih));
+}
+
+static void
+gst_avimux_newcaps (GstPad *pad, GstCaps *caps)
+{
+  GstAviMux *avimux;
+  const gchar* format = gst_caps_get_string (caps, "format");
+  gint padnum = GPOINTER_TO_INT (gst_pad_get_element_private (pad));
+
+  avimux = GST_AVIMUX (gst_pad_get_parent (pad));
+
+  GST_DEBUG (0, "avimux: newcaps triggered on %s (%d), %s\n", gst_pad_get_name (pad), 
+                 padnum, format);
+
+  if (!strncmp (format, "strf_vids", 9)) {
+    gst_riff_strf_vids *strf_vids = g_malloc(sizeof(gst_riff_strf_vids));
+
+    strf_vids->size        = sizeof(gst_riff_strf_vids);
+    strf_vids->width       = gst_caps_get_int (caps, "width");
+    strf_vids->height      = gst_caps_get_int (caps, "height");;
+    strf_vids->planes      = gst_caps_get_int (caps, "planes");;
+    strf_vids->bit_cnt     = gst_caps_get_int (caps, "bit_cnt");;
+    strf_vids->compression = gst_caps_get_fourcc_int (caps, "compression");;
+    strf_vids->image_size  = gst_caps_get_int (caps, "image_size");;
+    strf_vids->xpels_meter = gst_caps_get_int (caps, "xpels_meter");;
+    strf_vids->ypels_meter = gst_caps_get_int (caps, "ypels_meter");;
+    strf_vids->num_colors  = gst_caps_get_int (caps, "num_colors");;
+    strf_vids->imp_colors  = gst_caps_get_int (caps, "imp_colors");;
+
+    avimux->video_header[padnum] = strf_vids;
+  }
+  else if (!strncmp (format, "strf_auds", 9)) {
+
+  }
+}
+
+static GstPad*
+gst_avimux_request_new_pad (GstElement     *element,
+                           GstPadTemplate *templ,
+                           const gchar    *req_name)
+{
+  GstAviMux *avimux;
+  gchar *name = NULL;
+  GstPad *newpad;
+  
+  g_return_val_if_fail (templ != NULL, NULL);
+
+  if (templ->direction != GST_PAD_SINK) {
+    g_warning ("avimux: request pad that is not a SINK pad\n");
+    return NULL;
+  }
+
+  g_return_val_if_fail (GST_IS_AVIMUX (element), NULL);
+
+  avimux = GST_AVIMUX (element);
+
+  if (templ == GST_PADTEMPLATE_GET (audio_sink_factory)) {
+    name = g_strdup_printf ("audio_%02d", avimux->num_audio_pads);
+    newpad = gst_pad_new_from_template (templ, name);
+    gst_pad_set_element_private (newpad, GINT_TO_POINTER (avimux->num_audio_pads));
+
+    avimux->audio_pad[avimux->num_audio_pads] = newpad;
+    avimux->num_audio_pads++;
+  }
+  else if (templ == GST_PADTEMPLATE_GET (video_sink_factory)) {
+    name = g_strdup_printf ("video_%02d", avimux->num_video_pads);
+    newpad = gst_pad_new_from_template (templ, name);
+    gst_pad_set_element_private (newpad, GINT_TO_POINTER (avimux->num_video_pads));
+
+    avimux->video_pad[avimux->num_video_pads] = newpad;
+    avimux->num_video_pads++;
+  }
+  else {
+    g_warning ("avimux: this is not our template!\n");
+    return NULL;
+  }
+
+  gst_pad_set_chain_function (newpad, gst_avimux_chain);
+  gst_pad_set_newcaps_function (newpad, gst_avimux_newcaps);
+  gst_element_add_pad (element, newpad);
+  
+  return newpad;
+}
+
+static void
+gst_avimux_make_header (GstAviMux *avimux)
+{
+  gint i;
+
+  gst_riff_strh strh;
+
+  avimux->aviheader->us_frame = 40000;
+  avimux->aviheader->streams  = avimux->num_video_pads + avimux->num_audio_pads;
+  avimux->aviheader->width    = -1;
+  avimux->aviheader->height   = -1;
+  gst_riff_encoder_avih(avimux->riff, avimux->aviheader, sizeof(gst_riff_avih));
+
+  memset(&strh, 0, sizeof(gst_riff_strh));
+  strh.scale = 40000;
+
+  gst_riff_encoder_strh(avimux->riff, GST_RIFF_FCC_vids, &strh, sizeof(gst_riff_strh));
+
+  for (i=0; i<avimux->num_video_pads; i++) {
+    gst_riff_encoder_strf(avimux->riff, avimux->video_header[i], sizeof(gst_riff_strf_vids));
+  }
+}
+
+static void
+gst_avimux_chain (GstPad *pad, GstBuffer *buf)
+{
+  GstAviMux *avimux;
+  guchar *data;
+  gulong size;
+  const gchar *padname;
+  gint channel;
+  GstBuffer *newbuf;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+  g_return_if_fail (GST_BUFFER_DATA (buf) != NULL);
+
+  avimux = GST_AVIMUX (gst_pad_get_parent (pad));
+
+  data = (guchar *)GST_BUFFER_DATA(buf);
+  size = GST_BUFFER_SIZE(buf);
+
+  switch(avimux->state) {
+    case GST_AVIMUX_INITIAL:
+      GST_DEBUG (0,"gst_avimux_chain: writing header\n");
+      gst_avimux_make_header(avimux);
+      newbuf = gst_riff_encoder_get_and_reset_buffer(avimux->riff);
+      gst_pad_push(avimux->srcpad, newbuf);
+      avimux->state = GST_AVIMUX_MOVI;
+    case GST_AVIMUX_MOVI:
+      padname = gst_pad_get_name (pad);
+      channel = GPOINTER_TO_INT (gst_pad_get_element_private (pad));
+
+      if (strncmp(padname, "audio_", 6) == 0) {
+        GST_DEBUG (0,"gst_avimux_chain: got audio buffer in from channel %02d %lu\n", channel, size);
+        gst_riff_encoder_chunk(avimux->riff, GST_RIFF_01wb, NULL, size); 
+        newbuf = gst_riff_encoder_get_and_reset_buffer(avimux->riff);
+        gst_pad_push(avimux->srcpad, newbuf);
+      }
+      else if (strncmp(padname, "video_", 6) == 0) {
+        GST_DEBUG (0,"gst_avimux_chain: got video buffer in from channel %02d %lu\n", channel, size);
+        gst_riff_encoder_chunk(avimux->riff, GST_RIFF_00db, NULL, size); 
+        newbuf = gst_riff_encoder_get_and_reset_buffer(avimux->riff);
+        GST_DEBUG (0,"gst_avimux_chain: encoded %u\n", GST_BUFFER_SIZE(newbuf));
+        gst_pad_push(avimux->srcpad, newbuf);
+      }
+      GST_BUFFER_SIZE(buf) = (GST_BUFFER_SIZE(buf)+1)&~1;
+      gst_pad_push(avimux->srcpad, buf);
+      break;
+    default:
+      break;
+  }
+
+  //gst_buffer_unref(buf);
+}
+
+static void 
+gst_avimux_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstAviMux *src;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_AVIMUX(object));
+  src = GST_AVIMUX(object);
+
+  switch(prop_id) {
+    default:
+      break;
+  }
+}
+
+static void 
+gst_avimux_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstAviMux *src;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_AVIMUX(object));
+  src = GST_AVIMUX(object);
+
+  switch(prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+
+  /* this filter needs the riff parser */
+  if (!gst_library_load ("gstriff")) {
+    gst_info ("avimux: could not load support library: 'gstriff'\n");
+    return FALSE;
+  }
+
+  /* create an elementfactory for the avimux element */
+  factory = gst_elementfactory_new ("avimux", GST_TYPE_AVIMUX,
+                                    &gst_avimux_details);
+  g_return_val_if_fail (factory != NULL, FALSE);
+
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (audio_sink_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (video_sink_factory));
+  
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "avimux",
+  plugin_init
+};
+
diff --git a/gst/avi/gstavimux.h b/gst/avi/gstavimux.h
new file mode 100644 (file)
index 0000000..9de5694
--- /dev/null
@@ -0,0 +1,93 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+#ifndef __GST_AVIMUX_H__
+#define __GST_AVIMUX_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+#include <libs/riff/gstriff.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_AVIMUX \
+  (gst_avimux_get_type())
+#define GST_AVIMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVIMUX,GstAviMux))
+#define GST_AVIMUX_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVIMUX,GstAviMux))
+#define GST_IS_AVIMUX(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVIMUX))
+#define GST_IS_AVIMUX_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVIMUX))
+
+
+#define GST_AVIMUX_INITIAL       0     /* initialized state */
+#define GST_AVIMUX_MOVI          1     /* encoding movi */
+
+#define GST_AVIMUX_MAX_AUDIO_PADS      8       
+#define GST_AVIMUX_MAX_VIDEO_PADS      8       
+
+typedef struct _GstAviMux GstAviMux;
+typedef struct _GstAviMuxClass GstAviMuxClass;
+
+struct _GstAviMux {
+  GstElement element;
+
+  /* pads */
+  GstPad *srcpad;
+
+  /* AVI encoding state */
+  gint state;
+
+  /* RIFF encoding state */
+  GstRiff *riff;
+
+  guint64 next_time;
+  guint64 time_interval;
+
+  gst_riff_avih  *aviheader;    /* the avi header */
+  guint num_audio_pads;
+  guint num_video_pads;
+
+  GstPad             *audio_pad[GST_AVIMUX_MAX_AUDIO_PADS];
+  gst_riff_strf_auds *audio_header[GST_AVIMUX_MAX_AUDIO_PADS];
+  
+  GstPad             *video_pad[GST_AVIMUX_MAX_VIDEO_PADS];
+  gst_riff_strf_vids *video_header[GST_AVIMUX_MAX_VIDEO_PADS];
+};
+
+struct _GstAviMuxClass {
+  GstElementClass parent_class;
+};
+
+GType gst_avimux_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_AVIMUX_H__ */
diff --git a/gst/avi/gstavitypes.c b/gst/avi/gstavitypes.c
new file mode 100644 (file)
index 0000000..b43f2a0
--- /dev/null
@@ -0,0 +1,323 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+//#define GST_DEBUG_ENABLED
+#include <string.h>
+
+#include "gstavitypes.h"
+
+
+
+/* elementfactory information */
+static GstElementDetails gst_avi_types_details = {
+  "avi type converter",
+  "Decoder/Video",
+  "Converts avi types into gstreamer types",
+  VERSION,
+  "Wim Taymans <wim.taymans@tvd.be>",
+  "(C) 1999",
+};
+
+/* AviTypes signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_TYPE_FOUND,
+  /* FILL ME */
+};
+
+GST_PADTEMPLATE_FACTORY (sink_templ,
+  "sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "avitypes_sink",
+     "video/avi",
+      "format",         GST_PROPS_LIST (
+                         GST_PROPS_STRING ("strf_vids"),
+                         GST_PROPS_STRING ("strf_auds"),
+                         GST_PROPS_STRING ("strf_iavs")
+                       )
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (src_templ,
+  "video_src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "avitypes_src",
+    "video/raw",
+      "format",         GST_PROPS_LIST (
+                          GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','2')),
+                          GST_PROPS_FOURCC (GST_MAKE_FOURCC ('R','G','B',' '))
+                        ),
+      "width",          GST_PROPS_INT_RANGE (16, 4096),
+      "height",         GST_PROPS_INT_RANGE (16, 4096)
+  ),
+  GST_CAPS_NEW (
+    "avitypes_src",
+    "video/avi",
+      "format",         GST_PROPS_STRING ("strf_vids")
+  ),
+  GST_CAPS_NEW (
+    "src_audio",
+    "audio/raw",
+      "format",           GST_PROPS_STRING ("int"),
+      "law",              GST_PROPS_INT (0),
+      "endianness",       GST_PROPS_INT (G_BYTE_ORDER),
+      "signed",           GST_PROPS_LIST (
+                           GST_PROPS_BOOLEAN (TRUE),
+                           GST_PROPS_BOOLEAN (FALSE)
+                         ),
+      "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 (11025, 44100),
+      "channels",         GST_PROPS_INT_RANGE (1, 2)
+  ),
+  GST_CAPS_NEW (
+    "src_audio",
+    "audio/mp3",
+    NULL
+  ),
+  GST_CAPS_NEW (
+    "src_video",
+    "video/jpeg",
+    NULL
+  ),
+  GST_CAPS_NEW (
+    "src_dv",
+    "video/dv",
+    NULL
+  )
+)
+
+static void    gst_avi_types_class_init        (GstAviTypesClass *klass);
+static void    gst_avi_types_init              (GstAviTypes *avi_types);
+
+static void    gst_avi_types_chain             (GstPad *pad, GstBuffer *buffer); 
+
+static void     gst_avi_types_get_property      (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_avi_types_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_avi_types_get_type(void) 
+{
+  static GType avi_types_type = 0;
+
+  if (!avi_types_type) {
+    static const GTypeInfo avi_types_info = {
+      sizeof(GstAviTypesClass),      
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_avi_types_class_init,
+      NULL,
+      NULL,
+      sizeof(GstAviTypes),
+      0,
+      (GInstanceInitFunc)gst_avi_types_init,
+    };
+    avi_types_type = g_type_register_static(GST_TYPE_ELEMENT, "GstAviTypes", &avi_types_info, 0);
+  }
+  return avi_types_type;
+}
+
+static void
+gst_avi_types_class_init (GstAviTypesClass *klass) 
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TYPE_FOUND,
+    g_param_spec_boolean ("type_found","type_found","type_found",
+                     FALSE, G_PARAM_READABLE));
+
+  gobject_class->get_property = gst_avi_types_get_property;
+}
+
+static void 
+gst_avi_types_newcaps (GstPad *pad, GstCaps *caps) 
+{
+  GstAviTypes *avi_types;
+  const gchar *format;
+  GstCaps *newcaps = NULL;
+
+  avi_types = GST_AVI_TYPES (gst_pad_get_parent (pad));
+
+  format = gst_caps_get_string (caps, "format");
+
+  if (!strcmp (format, "strf_vids")) {
+    gulong video_format = gst_caps_get_fourcc_int (caps, "compression");
+
+    switch (video_format) {
+      case GST_MAKE_FOURCC ('M','J','P','G'):
+        newcaps = gst_caps_new ("avi_type_mjpg",
+                     "video/jpeg", NULL);
+        break;
+      case GST_MAKE_FOURCC ('d','v','s','d'):
+        newcaps = gst_caps_new ("avi_type_dv", 
+                           "video/dv", 
+                           gst_props_new (
+                             "format",         GST_PROPS_STRING ("NTSC"),
+                             NULL));
+      default:
+        break;
+    }
+  }
+  else if (!strcmp (format, "strf_auds")) {
+    gint16 audio_format        = gst_caps_get_int (caps, "fmt");
+    gint blockalign            = gst_caps_get_int (caps, "blockalign");
+    gint size                  = gst_caps_get_int (caps, "size");
+    gint channels              = gst_caps_get_int (caps, "channels");
+    gint rate                  = gst_caps_get_int (caps, "rate");
+    gboolean sign              = (size == 8 ? FALSE : TRUE);
+
+    GST_DEBUG (GST_CAT_PLUGIN_INFO, "avitypes: new caps with audio format:%04x\n", audio_format);
+
+    switch (audio_format) {
+      case 0x0001:
+        newcaps = gst_caps_new ("avi_type_pcm",
+                   "audio/raw",
+                   gst_props_new (
+                     "format",           GST_PROPS_STRING ("int"),
+                     "law",              GST_PROPS_INT (0),
+                     "endianness",       GST_PROPS_INT (G_BYTE_ORDER),
+                     "signed",           GST_PROPS_BOOLEAN (sign),
+                     "width",            GST_PROPS_INT ((blockalign*8)/channels),
+                     "depth",            GST_PROPS_INT (size),
+                     "rate",             GST_PROPS_INT (rate),
+                     "channels",         GST_PROPS_INT (channels),
+                     NULL
+                   ));
+        break;
+      case 0x0050:
+      case 0x0055:
+        newcaps = gst_caps_new ("avi_type_mp3",
+                     "audio/mp3", NULL);
+        break;
+      default:
+        break;
+    }
+  }
+  else if (!strcmp (format, "strf_iavs")) {
+    newcaps = gst_caps_new ("avi_type_dv", 
+                           "video/dv", 
+                           gst_props_new (
+                             "format",         GST_PROPS_STRING ("NTSC"),
+                             NULL));
+  }
+  
+  if (newcaps) {
+    gst_pad_set_caps (avi_types->srcpad, newcaps);
+    avi_types->type_found = TRUE;
+  }
+}
+
+static void 
+gst_avi_types_init (GstAviTypes *avi_types) 
+{
+  avi_types->sinkpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (sink_templ), "sink");
+  gst_element_add_pad (GST_ELEMENT (avi_types), avi_types->sinkpad);
+  gst_pad_set_newcaps_function (avi_types->sinkpad, gst_avi_types_newcaps);
+  gst_pad_set_chain_function (avi_types->sinkpad, gst_avi_types_chain);
+
+  avi_types->srcpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (src_templ), "src");
+  gst_element_add_pad (GST_ELEMENT (avi_types), avi_types->srcpad);
+
+  avi_types->type_found = FALSE;
+}
+
+static void 
+gst_avi_types_chain (GstPad *pad, GstBuffer *buffer) 
+{
+  GstAviTypes *avi_types;
+
+  avi_types = GST_AVI_TYPES (gst_pad_get_parent (pad));
+
+  if (GST_PAD_CONNECTED (avi_types->srcpad))
+    gst_pad_push (avi_types->srcpad, buffer);
+  else
+    gst_buffer_unref (buffer);
+}
+
+static void
+gst_avi_types_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstAviTypes *src;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_AVI_TYPES (object));
+
+  src = GST_AVI_TYPES (object);
+
+  switch (prop_id) {
+    case ARG_TYPE_FOUND:
+      g_value_set_boolean (value, src->type_found);
+      break;
+    default:
+      break;
+  }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+
+  /* create an elementfactory for the avi_types element */
+  factory = gst_elementfactory_new ("avitypes",GST_TYPE_AVI_TYPES,
+                                    &gst_avi_types_details);
+  g_return_val_if_fail (factory != NULL, FALSE);
+
+  //gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_templ));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_templ));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "avitypes",
+  plugin_init
+};
+
diff --git a/gst/avi/gstavitypes.h b/gst/avi/gstavitypes.h
new file mode 100644 (file)
index 0000000..43136e6
--- /dev/null
@@ -0,0 +1,65 @@
+/* Gnome-Streamer
+ * 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.
+ */
+
+
+#ifndef __GST_AVI_TYPES_H__
+#define __GST_AVI_TYPES_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GST_TYPE_AVI_TYPES \
+  (gst_avi_types_get_type())
+#define GST_AVI_TYPES(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVI_TYPES,GstAviTypes))
+#define GST_AVI_TYPES_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVI_TYPES,GstAviTypes))
+#define GST_IS_AVI_TYPES(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVI_TYPES))
+#define GST_IS_AVI_TYPES_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVI_TYPES))
+
+typedef struct _GstAviTypes GstAviTypes;
+typedef struct _GstAviTypesClass GstAviTypesClass;
+
+struct _GstAviTypes {
+  GstElement element;
+
+  GstPad *srcpad, *sinkpad;
+
+  gboolean type_found;
+};
+
+struct _GstAviTypesClass {
+  GstElementClass parent_class;
+};
+
+GType          gst_avi_types_get_type          (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_AVI_TYPES_H__ */