mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
Initial revision
Original commit message from CVS: Initial revision
This commit is contained in:
parent
a2c423bbad
commit
61a50361fb
15 changed files with 2720 additions and 0 deletions
8
gst/avi/.gitignore
vendored
Normal file
8
gst/avi/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
||||
codectest
|
31
gst/avi/Makefile.am
Normal file
31
gst/avi/Makefile.am
Normal 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
72
gst/avi/README
Normal 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
3
gst/avi/README_win32dll
Normal 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
189
gst/avi/audiocodecs.c
Normal 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);
|
||||
}
|
195
gst/avi/gstaviaudiodecoder.c
Normal file
195
gst/avi/gstaviaudiodecoder.c
Normal 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
|
||||
};
|
||||
|
65
gst/avi/gstaviaudiodecoder.h
Normal file
65
gst/avi/gstaviaudiodecoder.h
Normal 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
367
gst/avi/gstavidecoder.c
Normal 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
67
gst/avi/gstavidecoder.h
Normal 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
757
gst/avi/gstavidemux.c
Normal 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
109
gst/avi/gstavidemux.h
Normal 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
376
gst/avi/gstavimux.c
Normal 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
93
gst/avi/gstavimux.h
Normal 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
323
gst/avi/gstavitypes.c
Normal 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
65
gst/avi/gstavitypes.h
Normal 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__ */
|
Loading…
Reference in a new issue