diff options
author | Thomas Vander Stichele <thomas@apestaart.org> | 2001-12-21 11:46:15 +0000 |
---|---|---|
committer | Thomas Vander Stichele <thomas@apestaart.org> | 2001-12-21 11:46:15 +0000 |
commit | 3383f7c142fda4fb85faa1dfd9ae200b8277207a (patch) | |
tree | 3cf2e1cbe2dfaa95f8e90253097f5580cf1eb7ba /ext/audiofile/gstafsrc.c | |
parent | cc33fd24dbcd64369f1b6ce297f6eca9c0117b9f (diff) | |
download | gst-plugins-bad-3383f7c142fda4fb85faa1dfd9ae200b8277207a.tar.gz gst-plugins-bad-3383f7c142fda4fb85faa1dfd9ae200b8277207a.tar.bz2 gst-plugins-bad-3383f7c142fda4fb85faa1dfd9ae200b8277207a.zip |
fixed some GST_LIBS stuff added audiofile added gst-libs/audio building
Original commit message from CVS:
fixed some GST_LIBS stuff
added audiofile
added gst-libs/audio building
Diffstat (limited to 'ext/audiofile/gstafsrc.c')
-rw-r--r-- | ext/audiofile/gstafsrc.c | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/ext/audiofile/gstafsrc.c b/ext/audiofile/gstafsrc.c new file mode 100644 index 00000000..ceb548f6 --- /dev/null +++ b/ext/audiofile/gstafsrc.c @@ -0,0 +1,425 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * + * gstafsrc.c: + * + * 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 <gst/gst.h> +#include <gst-libs/audio/gstaudio.h> +#include "gstafsrc.h" + + +static GstElementDetails afsrc_details = { + "Audiofile Src", + "Src", + "Audiofile src for audio/raw", + VERSION, + "Thomas <thomas@apestaart.org>", + "(C) 2001" +}; + + +/* AFSrc signals and args */ +enum { + /* FILL ME */ + SIGNAL_HANDOFF, + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION +}; + +/* added a src factory function to force audio/raw MIME type */ +/* I think the caps can be broader, we need to change that somehow */ +GST_PADTEMPLATE_FACTORY (afsrc_src_factory, + "src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "audiofile_src", + "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_INT_RANGE (8, 16), + "depth", GST_PROPS_INT_RANGE (8, 16), + "rate", GST_PROPS_INT_RANGE (4000, 48000), //FIXME + "channels", GST_PROPS_INT_RANGE (1, 2) + ) +); + +/* we use an enum for the output type arg */ + +#define GST_TYPE_AFSRC_TYPES (gst_afsrc_types_get_type()) + +/* FIXME: fix the string ints to be string-converted from the audiofile.h types */ + +static GType +gst_afsrc_types_get_type (void) +{ + static GType afsrc_types_type = 0; + static GEnumValue afsrc_types[] = { + {AF_FILE_RAWDATA, "0", "raw PCM"}, + {AF_FILE_AIFFC, "1", "AIFFC"}, + {AF_FILE_AIFF, "2", "AIFF"}, + {AF_FILE_NEXTSND, "3", "Next/SND"}, + {AF_FILE_WAVE, "4", "Wave"}, + {0, NULL, NULL}, + }; + + if (!afsrc_types_type) + { + afsrc_types_type = g_enum_register_static ("GstAudiosrcTypes", afsrc_types); + } + return afsrc_types_type; +} + +static void gst_afsrc_class_init (GstAFSrcClass *klass); +static void gst_afsrc_init (GstAFSrc *afsrc); + +static gboolean gst_afsrc_open_file (GstAFSrc *src); +static void gst_afsrc_close_file (GstAFSrc *src); + +static GstBuffer* gst_afsrc_get (GstPad *pad); + +static void gst_afsrc_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void gst_afsrc_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); + +static GstElementStateReturn gst_afsrc_change_state (GstElement *element); + +static GstElementClass *parent_class = NULL; +static guint gst_afsrc_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_afsrc_get_type (void) +{ + static GType afsrc_type = 0; + + if (!afsrc_type) { + static const GTypeInfo afsrc_info = { + sizeof (GstAFSrcClass), NULL, + NULL, + (GClassInitFunc) gst_afsrc_class_init, + NULL, + NULL, + sizeof (GstAFSrc), + 0, + (GInstanceInitFunc) gst_afsrc_init, + }; + afsrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAFSrc", &afsrc_info, 0); + } + return afsrc_type; +} + +static void +gst_afsrc_class_init (GstAFSrcClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gst_element_install_std_props ( + GST_ELEMENT_CLASS (klass), + "location", ARG_LOCATION, G_PARAM_READWRITE, + NULL); + + gst_afsrc_signals[SIGNAL_HANDOFF] = + g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAFSrcClass, handoff), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + + gobject_class->set_property = gst_afsrc_set_property; + gobject_class->get_property = gst_afsrc_get_property; + + gstelement_class->change_state = gst_afsrc_change_state; +} + +static void +gst_afsrc_init (GstAFSrc *afsrc) +{ + // GstPad *pad; this is now done in the struct + + /* no need for a template, caps are set based on file, right ? */ + afsrc->srcpad = gst_pad_new ("src", GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (afsrc), afsrc->srcpad); + gst_pad_set_get_function (afsrc->srcpad, gst_afsrc_get); + + afsrc->bytes_per_read = 4096; + afsrc->curoffset = 0; + afsrc->seq = 0; + + afsrc->filename = NULL; + afsrc->file = NULL; + /* default values, should never be needed */ + afsrc->channels = 2; + afsrc->width = 16; + afsrc->rate = 44100; + afsrc->type = AF_FILE_WAVE; + afsrc->endianness_data = 1234; + afsrc->endianness_wanted = 1234; + afsrc->framestamp = 0; +} + +static GstBuffer * +gst_afsrc_get (GstPad *pad) +{ + GstAFSrc *src; + GstBuffer *buf; + + glong readbytes, readframes; + glong frameCount; + + g_return_val_if_fail (pad != NULL, NULL); + src = GST_AFSRC (gst_pad_get_parent (pad)); + + buf = gst_buffer_new (); + g_return_val_if_fail (buf, NULL); + + GST_BUFFER_DATA (buf) = (gpointer) g_malloc (src->bytes_per_read); + + /* calculate frameCount to read based on file info */ + + frameCount = src->bytes_per_read / (src->channels * src->width / 8); +// g_print ("DEBUG: gstafsrc: going to read %ld frames\n", frameCount); + readframes = afReadFrames (src->file, AF_DEFAULT_TRACK, GST_BUFFER_DATA (buf), + frameCount); + readbytes = readframes * (src->channels * src->width / 8); + if (readbytes == 0) { + gst_element_signal_eos (GST_ELEMENT (src)); + return NULL; + } + + GST_BUFFER_SIZE (buf) = readbytes; + GST_BUFFER_OFFSET (buf) = src->curoffset; + + src->curoffset += readbytes; + + src->framestamp += gst_audio_frame_length (src->srcpad, buf); + GST_BUFFER_TIMESTAMP (buf) = src->framestamp * 1E9 + / gst_audio_frame_rate (src->srcpad); + printf ("DEBUG: afsrc: timestamp set on output buffer: %f sec\n", + GST_BUFFER_TIMESTAMP (buf) / 1E9); + +// g_print("DEBUG: gstafsrc: pushed buffer of %ld bytes\n", readbytes); + return buf; +} + +static void +gst_afsrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstAFSrc *src; + + /* it's not null if we got it, but it might not be ours */ + src = GST_AFSRC (object); + + switch (prop_id) { + case ARG_LOCATION: + if (src->filename) + g_free (src->filename); + src->filename = g_strdup (g_value_get_string (value)); + break; + default: + break; + } +} + +static void +gst_afsrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstAFSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_AFSRC (object)); + + src = GST_AFSRC (object); + + switch (prop_id) { + case ARG_LOCATION: + g_value_set_string (value, src->filename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + factory = gst_elementfactory_new ("afsrc", GST_TYPE_AFSRC, + &afsrc_details); + g_return_val_if_fail (factory != NULL, FALSE); + + gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (afsrc_src_factory)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + /* load audio support library */ + if (!gst_library_load ("gstaudio")) + { + gst_info ("mad: could not load support library: 'gstaudio'\n"); + return FALSE; + } + + return TRUE; +} + + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "afsrc", + plugin_init +}; + +/* this is where we open the audiofile */ +static gboolean +gst_afsrc_open_file (GstAFSrc *src) +{ + g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_AFSRC_OPEN), FALSE); + + /* open the file */ + src->file = afOpenFile (src->filename, "r", AF_NULL_FILESETUP); + if (src->file == AF_NULL_FILEHANDLE) + { + g_print ("ERROR: gstafsrc: Could not open file %s for reading\n", + src->filename); + gst_element_error (GST_ELEMENT (src), g_strconcat ("opening file \"", + src->filename, "\"", NULL)); + return FALSE; + } + + /* get the audiofile audio parameters */ + { + int sampleFormat, sampleWidth; + src->channels = afGetChannels (src->file, AF_DEFAULT_TRACK); + afGetSampleFormat (src->file, AF_DEFAULT_TRACK, + &sampleFormat, &sampleWidth); + switch (sampleFormat) + { + case AF_SAMPFMT_TWOSCOMP: + src->is_signed = TRUE; + break; + case AF_SAMPFMT_UNSIGNED: + src->is_signed = FALSE; + break; + case AF_SAMPFMT_FLOAT: + case AF_SAMPFMT_DOUBLE: + GST_DEBUG (GST_CAT_PLUGIN_INFO, + "ERROR: float data not supported yet !\n"); + } + src->rate = (guint) afGetRate (src->file, AF_DEFAULT_TRACK); + src->width = sampleWidth; + GST_DEBUG (GST_CAT_PLUGIN_INFO, + "input file: %d channels, %d width, %d rate, signed %s\n", + src->channels, src->width, src->rate, + src->is_signed ? "yes" : "no"); + } + + /* set caps on src */ + //FIXME: add all the possible formats, especially float ! */ + gst_pad_set_caps (src->srcpad, gst_caps_new ( + "af_src", + "audio/raw", + gst_props_new ( + "format", GST_PROPS_STRING ("int"), + "law", GST_PROPS_INT (0), //FIXME + "endianness", GST_PROPS_INT (G_BYTE_ORDER), //FIXME + "signed", GST_PROPS_BOOLEAN (src->is_signed), + "width", GST_PROPS_INT (src->width), + "depth", GST_PROPS_INT (src->width), + "rate", GST_PROPS_INT (src->rate), + "channels", GST_PROPS_INT (src->channels), + NULL + ) + )); + + GST_FLAG_SET (src, GST_AFSRC_OPEN); + + return TRUE; +} + +static void +gst_afsrc_close_file (GstAFSrc *src) +{ +// g_print ("DEBUG: closing srcfile...\n"); + g_return_if_fail (GST_FLAG_IS_SET (src, GST_AFSRC_OPEN)); +// g_print ("DEBUG: past flag test\n"); +// if (fclose (src->file) != 0) + if (afCloseFile (src->file) != 0) + { + g_print ("WARNING: afsrc: oops, error closing !\n"); + perror ("close"); + gst_element_error (GST_ELEMENT (src), g_strconcat("closing file \"", src->filename, "\"", NULL)); + } + else { + GST_FLAG_UNSET (src, GST_AFSRC_OPEN); + } +} + +static GstElementStateReturn +gst_afsrc_change_state (GstElement *element) +{ + g_return_val_if_fail (GST_IS_AFSRC (element), GST_STATE_FAILURE); + + /* if going to NULL then close the file */ + if (GST_STATE_PENDING (element) == GST_STATE_NULL) + { +// printf ("DEBUG: afsrc state change: null pending\n"); + if (GST_FLAG_IS_SET (element, GST_AFSRC_OPEN)) + { +// g_print ("DEBUG: trying to close the src file\n"); + gst_afsrc_close_file (GST_AFSRC (element)); + } + } + else if (GST_STATE_PENDING (element) == GST_STATE_READY) + { +// g_print ("DEBUG: afsrc: ready state pending. This shouldn't happen at the *end* of a stream\n"); + if (!GST_FLAG_IS_SET (element, GST_AFSRC_OPEN)) + { +// g_print ("DEBUG: GST_AFSRC_OPEN not set\n"); + if (!gst_afsrc_open_file (GST_AFSRC (element))) + { +// g_print ("DEBUG: element tries to open file\n"); + return GST_STATE_FAILURE; + } + } + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + + return GST_STATE_SUCCESS; +} |