--- /dev/null
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+codectest
--- /dev/null
+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
--- /dev/null
+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.
+
+
--- /dev/null
+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.
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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
+};
+
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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
+};
+
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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
+};
+
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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
+};
+
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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
+};
+
--- /dev/null
+/* 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__ */