Initial revision

Original commit message from CVS:
Initial revision
This commit is contained in:
Andy Wingo 2001-12-22 23:22:30 +00:00
parent a2c423bbad
commit 61a50361fb
15 changed files with 2720 additions and 0 deletions

8
gst/avi/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs
codectest

31
gst/avi/Makefile.am Normal file
View file

@ -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

72
gst/avi/README Normal file
View file

@ -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.

3
gst/avi/README_win32dll Normal file
View file

@ -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.

189
gst/avi/audiocodecs.c Normal file
View file

@ -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);
}

View file

@ -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
};

View file

@ -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__ */

367
gst/avi/gstavidecoder.c Normal file
View file

@ -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
};

67
gst/avi/gstavidecoder.h Normal file
View file

@ -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__ */

757
gst/avi/gstavidemux.c Normal file
View file

@ -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
};

109
gst/avi/gstavidemux.h Normal file
View file

@ -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__ */

376
gst/avi/gstavimux.c Normal file
View file

@ -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
};

93
gst/avi/gstavimux.h Normal file
View file

@ -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__ */

323
gst/avi/gstavitypes.c Normal file
View file

@ -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
};

65
gst/avi/gstavitypes.h Normal file
View file

@ -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__ */