diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | PORTED_09 | 3 | ||||
-rw-r--r-- | configure.ac | 24 | ||||
-rw-r--r-- | ext/Makefile.am | 789 | ||||
-rw-r--r-- | ext/mad/Makefile.am | 5 | ||||
-rw-r--r-- | ext/mad/gstid3demuxbin.c | 197 | ||||
-rw-r--r-- | ext/mad/gstid3tag.c | 391 | ||||
-rw-r--r-- | ext/mad/gstmad.c | 209 | ||||
-rw-r--r-- | ext/mad/gstmad.h | 1 |
10 files changed, 683 insertions, 945 deletions
@@ -1,3 +1,8 @@ +2005-05-06 Christian Schaller <uraeus@gnome.org> + + * ext/mad: ported plugin from threaded branch + * gst/effectv: ported plugins from threaded branch + 2005-05-06 Zaheer Abbas Merali <zaheerabbas at merali dot org> * configure.ac: diff --git a/Makefile.am b/Makefile.am index 1475e53f29..866b95a91e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,14 +13,14 @@ endif # endif SUBDIRS = \ - gst sys \ + gst sys ext \ $(GCONF_DIR) \ m4 # disabled # $(SUBDIRS_DOCS) DIST_SUBDIRS = \ - gst sys \ + gst sys ext \ m4 # disabled @@ -1,6 +1,7 @@ List of ported plugins (update when you commit a ported plugin): -osssink (wim) +osssink (wim) - partially done in threaded effectv (wim) +mad (wim) - Remember that some plugins are already ported and now in the gst-plugins-base module. diff --git a/configure.ac b/configure.ac index 6e48fc24e6..60420bd4b9 100644 --- a/configure.ac +++ b/configure.ac @@ -345,9 +345,25 @@ dnl ]) dnl ]) dnl ]) - - - +dnl *** mad *** +dnl FIXME: we could use header checks here as well IMO +translit(dnm, m, l) AM_CONDITIONAL(USE_MAD, true) +GST_CHECK_FEATURE(MAD, [mad mp3 decoder], mad, [ + dnl check with pkg-config first + PKG_CHECK_MODULES(MAD, mad >= 0.15 id3tag >= 0.15, HAVE_MAD="yes", HAVE_MAD="no") + if test "x$HAVE_MAD" = "xno"; then + dnl fall back to oldskool detection + AC_CHECK_LIB(mad, mad_decoder_finish, HAVE_MAD="yes" MAD_LIBS="-lmad") + if test "x$HAVE_MAD" = "xyes"; then + HAVE_MAD="no" + save_LIBS=$LIBS + LIBS="-lz" + AC_CHECK_LIB(id3tag, id3_tag_options, HAVE_MAD="yes" MAD_LIBS="-lmad -lid3tag -lz") + LIBS=$save_LIBS + fi + fi +]) +AC_SUBST(MAD_LIBS) AC_SUBST(GST_LIBS) @@ -408,6 +424,8 @@ gst-plugins.spec gst/Makefile gst/effectv/Makefile sys/Makefile +ext/Makefile +ext/mad/Makefile common/Makefile common/m4/Makefile m4/Makefile diff --git a/ext/Makefile.am b/ext/Makefile.am index 19c8c3dcf6..055ae52119 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -1,122 +1,116 @@ -if USE_A52DEC -A52DEC_DIR=a52dec -else -A52DEC_DIR= -endif - -if USE_AALIB -AALIB_DIR=aalib -else -AALIB_DIR= -endif - -if USE_ALSA -ALSA_DIR=alsa -else -ALSA_DIR= -endif - -if USE_AMRNB -AMRNB_DIR=amrnb -else -AMRNB= -endif - -if USE_ARTS -ARTS_DIR=arts -else -ARTS_DIR= -endif - -if USE_ARTSC -ARTSC_DIR=artsd -else -ARTSC_DIR= -endif - -if USE_AUDIOFILE -AUDIOFILE_DIR=audiofile -else -AUDIOFILE_DIR= -endif - -if USE_AUDIORESAMPLE -AUDIORESAMPLE_DIR=audioresample -else -AUDIORESAMPLE_DIR= -endif - -if USE_CAIRO -CAIRO_DIR=cairo -else -CAIRO_DIR= -endif - -if USE_CDAUDIO -CDAUDIO_DIR=cdaudio -else -CDAUDIO_DIR= -endif - -if USE_CDPARANOIA -CDPARANOIA_DIR=cdparanoia -else -CDPARANOIA_DIR= -endif - -if USE_DIRAC -DIRAC_DIR=dirac -else -DIRAC_DIR= -endif - -if USE_DIRECTFB -DIRECTFB_DIR=directfb -else -DIRECTFB_DIR= -endif - -if USE_DIVX -DIVX_DIR=divx -else -DIVX_DIR= -endif - -if USE_DTS -DTS_DIR=dts -else -DTS_DIR= -endif - -if USE_DVDREAD -DVDREAD_DIR=dvdread -else -DVDREAD_DIR= -endif - -if USE_DVDNAV -DVDNAV_DIR=dvdnav -else -DVDNAV_DIR= -endif - -if USE_ESD -ESD_DIR=esd -else -ESD_DIR= -endif - -if USE_FAAC -FAAC_DIR=faac -else -FAAC_DIR= -endif - -if USE_FAAD -FAAD_DIR=faad -else -FAAD_DIR= -endif +# if USE_A52DEC +# A52DEC_DIR=a52dec +# else +# A52DEC_DIR= +# endif + +# if USE_AALIB +# AALIB_DIR=aalib +# else +# AALIB_DIR= +# endif + +# if USE_AMRNB +# AMRNB_DIR=amrnb +# else +# AMRNB= +# endif + +# if USE_ARTS +# ARTS_DIR=arts +# else +# ARTS_DIR= +# endif + +# if USE_ARTSC +# ARTSC_DIR=artsd +# else +# ARTSC_DIR= +# endif + +# if USE_AUDIOFILE +# AUDIOFILE_DIR=audiofile +# else +# AUDIOFILE_DIR= +# endif + +# if USE_AUDIORESAMPLE +# AUDIORESAMPLE_DIR=audioresample +# else +# AUDIORESAMPLE_DIR= +# endif + +# if USE_CAIRO +# CAIRO_DIR=cairo +# else +# CAIRO_DIR= +# endif + +# if USE_CDAUDIO +# CDAUDIO_DIR=cdaudio +# else +# CDAUDIO_DIR= +# endif + +# if USE_CDPARANOIA +# CDPARANOIA_DIR=cdparanoia +# else +# CDPARANOIA_DIR= +# endif + +# if USE_DIRAC +# DIRAC_DIR=dirac +# else +# DIRAC_DIR= +# endif + +# if USE_DIRECTFB +# DIRECTFB_DIR=directfb +# else +# DIRECTFB_DIR= +# endif + +# if USE_DIVX +# DIVX_DIR=divx +# else +# DIVX_DIR= +# endif + +# if USE_DTS +# DTS_DIR=dts +# else +# DTS_DIR= +# endif + +# if USE_DVDREAD +# DVDREAD_DIR=dvdread +# else +# DVDREAD_DIR= +# endif + +# if USE_DVDNAV +# DVDNAV_DIR=dvdnav +# else +# DVDNAV_DIR= +# endif + +# if USE_ESD +# ESD_DIR=esd +# else +# ESD_DIR= +# endif + +# if USE_FAAC +# FAAC_DIR=faac +# else +# FAAC_DIR= +# endif + +# if USE_FAAD +# FAAD_DIR=faad +# else +# FAAD_DIR= +# endif ## if USE_FESTIVAL ## FESTIVAL_DIR=festival @@ -124,113 +118,113 @@ endif ## FESTIVAL_DIR= ## endif -if USE_FLAC -FLAC_DIR=flac -else -FLAC_DIR= -endif - -if USE_GDK_PIXBUF -GDK_PIXBUF_DIR=gdk_pixbuf -else -GDK_PIXBUF_DIR= -endif - -if USE_GNOME_VFS -GNOMEVFS_DIR=gnomevfs -else -GNOMEVFS_DIR= -endif - -if USE_GSM -GSM_DIR=gsm -else -GSM_DIR= -endif - -if USE_HERMES -HERMES_DIR=hermes -else -HERMES_DIR= -endif - -if USE_JACK -JACK_DIR=jack -else -JACK_DIR= -endif - -if USE_JPEG -JPEG_DIR=jpeg -else -JPEG_DIR= -endif - -if USE_LADSPA -LADSPA_DIR=ladspa -else -LADPSA_DIR= -endif - -if USE_LAME -LAME_DIR=lame -else -LAME_DIR= -endif - -if USE_LCS -LCS_DIR=lcs -else -LCS_DIR= -endif - -if USE_LIBCACA -LIBCACA_DIR=libcaca -else -LIBCACA_DIR= -endif - -if USE_LIBDV -LIBDV_DIR=dv -else -LIBDV_DIR= -endif - -if USE_LIBFAME -LIBFAME_DIR=libfame -else -LIBFAME_DIR= -endif - -if USE_LIBMNG -LIBMNG_DIR=libmng -else -LIBMNG_DIR= -endif - -if USE_LIBPNG -LIBPNG_DIR=libpng -else -LIBPNG_DIR= -endif - -if USE_POLYP -POLYP_DIR=polyp -else -POLYP_DIR= -endif - -if USE_LIBVISUAL -LIBVISUAL_DIR=libvisual -else -LIBVISUAL_DIR= -endif - -if USE_LIBMMS -LIBMMS_DIR=libmms -else -LIBMMS_DIR= -endif +# if USE_FLAC +# FLAC_DIR=flac +# else +# FLAC_DIR= +# endif + +# if USE_GDK_PIXBUF +# GDK_PIXBUF_DIR=gdk_pixbuf +# else +# GDK_PIXBUF_DIR= +# endif + +# if USE_GNOME_VFS +# GNOMEVFS_DIR=gnomevfs +# else +# GNOMEVFS_DIR= +# endif + +# if USE_GSM +# GSM_DIR=gsm +# else +# GSM_DIR= +# endif + +# if USE_HERMES +# HERMES_DIR=hermes +# else +# HERMES_DIR= +# endif + +# if USE_JACK +# JACK_DIR=jack +# else +# JACK_DIR= +# endif + +# if USE_JPEG +# JPEG_DIR=jpeg +# else +# JPEG_DIR= +# endif + +# if USE_LADSPA +# LADSPA_DIR=ladspa +# else +# LADPSA_DIR= +# endif + +# if USE_LAME +# LAME_DIR=lame +# else +# LAME_DIR= +# endif + +# if USE_LCS +# LCS_DIR=lcs +# else +# LCS_DIR= +# endif + +# if USE_LIBCACA +# LIBCACA_DIR=libcaca +# else +# LIBCACA_DIR= +# endif + +# if USE_LIBDV +# LIBDV_DIR=dv +# else +# LIBDV_DIR= +# endif + +# if USE_LIBFAME +# LIBFAME_DIR=libfame +# else +# LIBFAME_DIR= +# endif + +# if USE_LIBMNG +# LIBMNG_DIR=libmng +# else +# LIBMNG_DIR= +# endif + +# if USE_LIBPNG +# LIBPNG_DIR=libpng +# else +# LIBPNG_DIR= +# endif + +# if USE_POLYP +# POLYP_DIR=polyp +# else +# POLYP_DIR= +# endif + +# if USE_LIBVISUAL +# LIBVISUAL_DIR=libvisual +# else +# LIBVISUAL_DIR= +# endif + +# if USE_LIBMMS +# LIBMMS_DIR=libmms +# else +# LIBMMS_DIR= +# endif if USE_MAD MAD_DIR=mad @@ -238,29 +232,29 @@ else MAD_DIR= endif -if USE_MIKMOD -MIKMOD_DIR=mikmod -else -MIKMOD_DIR= -endif +# if USE_MIKMOD +# MIKMOD_DIR=mikmod +# else +# MIKMOD_DIR= +# endif -if USE_MPEG2DEC -MPEG2DEC_DIR=mpeg2dec -else -MPEG2DEC_DIR= -endif +# if USE_MPEG2DEC +# MPEG2DEC_DIR=mpeg2dec +# else +#MPEG2DEC_DIR= +#endif -if USE_MPEG2ENC -MPEG2ENC_DIR=mpeg2enc -else -MPEG2ENC_DIR= -endif +# if USE_MPEG2ENC +# MPEG2ENC_DIR=mpeg2enc +# else +# MPEG2ENC_DIR= +# endif -if USE_MPLEX -MPLEX_DIR=mplex -else -MPLEX_DIR= -endif +# if USE_MPLEX +# MPLEX_DIR=mplex +# else +# MPLEX_DIR= +# endif #if USE_MAS #MAS_DIR=mas @@ -268,131 +262,119 @@ endif #MAS_DIR= #endif -if USE_MUSEPACK -MUSEPACK_DIR=musepack -else -MUSEPACK_DIR= -endif - -if USE_MUSICBRAINZ -MUSICBRAINZ_DIR=musicbrainz -else -MUSICBRAINZ_DIR= -endif - -if USE_NAS -NAS_DIR=nas -else -NAS_DIR= -endif - -if USE_OGG -OGG_DIR=ogg -else -OGG_DIR= -endif - -if USE_PANGO -PANGO_DIR=pango -else -PANGO_DIR= -endif - -if USE_DV1394 -DV1394_DIR=raw1394 -else -DV1394_DIR= -endif - -if USE_SDL -SDL_DIR=sdl -else -SDL_DIR= -endif - -if USE_SHOUT -SHOUT_DIR=shout -else -SHOUT_DIR= -endif - -if USE_SHOUT2 -SHOUT2_DIR=shout2 -else -SHOUT2_DIR= -endif - -if USE_SIDPLAY -SIDPLAY_DIR=sidplay -else -SIDDPLAY_DIR= -endif - -if USE_SMOOTHWAVE -SMOOTHWAVE_DIR=smoothwave -else -SMOOTHWAVE_DIR= -endif - -if USE_SNDFILE -SNDFILE_DIR=sndfile -else -SNDFILE_DIR= -endif - -if USE_SWFDEC -SWFDEC_DIR=swfdec -else -SWFDEC_DIR= -endif - -if USE_TARKIN -TARKIN_DIR=tarkin -else -TARKIN_DIR= -endif - -if USE_IVORBIS -IVORBIS_DIR=ivorbis -else -IVORBIS_DIR= -endif - -if USE_VORBIS -VORBIS_DIR=vorbis -else -VORBIS_DIR= -endif - -if USE_THEORA -THEORA_DIR=theora -else -THEORA_DIR= -endif - -if USE_XVID -XVID_DIR=xvid -else -XVID_DIR= -endif - -if USE_LIBPNG -SNAPSHOT_DIR=snapshot -else -SNAPSHOT_DIR= -endif - -if USE_SPEEX -SPEEX_DIR=speex -else -SPEEX_DIR= -endif - -if USE_XINE -XINE_DIR=xine -else -XINE_DIR= -endif +# if USE_MUSEPACK +# MUSEPACK_DIR=musepack +# else +# MUSEPACK_DIR= +# endif + +# if USE_MUSICBRAINZ +# MUSICBRAINZ_DIR=musicbrainz +# else +# MUSICBRAINZ_DIR= +# endif + +# if USE_NAS +# NAS_DIR=nas +# else +# NAS_DIR= +# endif + +# if USE_OGG +# OGG_DIR=ogg +# else +# OGG_DIR= +# endif + +# if USE_PANGO +# PANGO_DIR=pango +# else +# PANGO_DIR= +# endif + +# if USE_DV1394 +# DV1394_DIR=raw1394 +# else +# DV1394_DIR= +# endif + +# if USE_SDL +# SDL_DIR=sdl +# else +# SDL_DIR= +# endif + +# if USE_SHOUT +# SHOUT_DIR=shout +# else +# SHOUT_DIR= +# endif + +# if USE_SHOUT2 +# SHOUT2_DIR=shout2 +# else +# SHOUT2_DIR= +# endif + +# if USE_SIDPLAY +# SIDPLAY_DIR=sidplay +# else +# SIDDPLAY_DIR= +# endif + +# if USE_SMOOTHWAVE +# SMOOTHWAVE_DIR=smoothwave +# else +# SMOOTHWAVE_DIR= +# endif + +# if USE_SNDFILE +# SNDFILE_DIR=sndfile +# else +# SNDFILE_DIR= +# endif + +# if USE_SWFDEC +# SWFDEC_DIR=swfdec +# else +# SWFDEC_DIR= +# endif + +# if USE_TARKIN +# TARKIN_DIR=tarkin +# else +# TARKIN_DIR= +# endif + +# if USE_IVORBIS +# IVORBIS_DIR=ivorbis +# else +# IVORBIS_DIR= +# endif + +# if USE_XVID +# XVID_DIR=xvid +# else +# XVID_DIR= +# endif + +# if USE_LIBPNG +# SNAPSHOT_DIR=snapshot +# else +# SNAPSHOT_DIR= +# endif + +# if USE_SPEEX +# SPEEX_DIR=speex +# else +# SPEEX_DIR= +# endif + +# if USE_XINE +# XINE_DIR=xine +# else +# XINE_DIR= +# endif SUBDIRS=\ $(A52DEC_DIR) \ @@ -461,67 +443,4 @@ SUBDIRS=\ $(XVID_DIR) DIST_SUBDIRS=\ - a52dec \ - aalib \ - alsa \ - amrnb \ - arts \ - artsd \ - audiofile \ - audioresample \ - cairo \ - cdaudio \ - cdparanoia \ - dirac \ - directfb \ - divx \ - dts \ - dv \ - dvdread \ - dvdnav \ - esd \ - faac \ - faad \ - flac \ - gdk_pixbuf \ - gnomevfs \ - gsm \ - hermes \ - ivorbis \ - jack \ - jpeg \ - ladspa \ - lame \ - lcs \ - libcaca \ - libfame \ - libmng \ - libmms \ - libpng \ - libvisual \ - mad \ - mikmod \ - mpeg2dec \ - mpeg2enc \ - mplex \ - musepack \ - musicbrainz \ - nas \ - ogg \ - pango \ - polyp \ - raw1394 \ - sdl \ - snapshot \ - sndfile \ - shout \ - shout2 \ - sidplay \ - smoothwave \ - speex \ - swfdec \ - tarkin \ - theora \ - vorbis \ - xine \ - xvid + mad diff --git a/ext/mad/Makefile.am b/ext/mad/Makefile.am index c0775aaf27..1452e256a5 100644 --- a/ext/mad/Makefile.am +++ b/ext/mad/Makefile.am @@ -1,9 +1,6 @@ plugin_LTLIBRARIES = libgstmad.la -libgstmad_la_SOURCES = \ - gstmad.c \ - gstid3tag.c \ - gstid3demuxbin.c +libgstmad_la_SOURCES = gstmad.c gstid3tag.c libgstmad_la_CFLAGS = $(GST_CFLAGS) $(MAD_CFLAGS) $(ID3_CFLAGS) libgstmad_la_LIBADD = $(MAD_LIBS) $(ID3_LIBS) diff --git a/ext/mad/gstid3demuxbin.c b/ext/mad/gstid3demuxbin.c deleted file mode 100644 index e4db40c719..0000000000 --- a/ext/mad/gstid3demuxbin.c +++ /dev/null @@ -1,197 +0,0 @@ -/* GStreamer - * (c) 2005 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * gstid3demuxbin.c: hack around autoplugging. - * - * 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. - */ - -#ifdef HAVE_CONFIG_G -#include "config.h" -#endif - -#include <gst/gst.h> - -#define GST_TYPE_ID3DEMUX_BIN \ - (gst_id3demux_bin_get_type()) -#define GST_ID3DEMUX_BIN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_ID3DEMUX_BIN, \ - GstId3DemuxBin)) -#define GST_ID3DEMUX_BIN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_ID3DEMUX_BIN, \ - GstId3DemuxBinClass)) -#define GST_IS_ID3DEMUX_BIN(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_ID3DEMUX_BIN)) -#define GST_IS_ID3DEMUX_BIN_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_ID3DEMUX_BIN)) - -typedef struct _GstId3DemuxBin -{ - GstBin parent; - - /* ghost pads */ - GstPad *srcpad; - - /* kids */ - GstElement *demux, *typefind; -} GstId3DemuxBin; - -typedef struct _GstId3DemuxBinClass -{ - GstBinClass parent; -} GstId3DemuxBinClass; - -static GstStaticPadTemplate id3demux_bin_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS ("ANY") - ); - -static GstStaticPadTemplate id3demux_bin_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("application/x-id3") - ); - -static void gst_id3demux_bin_class_init (GstId3DemuxBinClass * klass); -static void gst_id3demux_bin_base_init (GstId3DemuxBinClass * klass); -static void gst_id3demux_bin_init (GstId3DemuxBin * manager); - -static void found_type (GstElement * element, guint probability, - const GstCaps * caps, gpointer data); -static GstElementStateReturn gst_id3demux_bin_change_state (GstElement * - element); - -static GstBinClass *parent_class; - -GType -gst_id3demux_bin_get_type (void) -{ - static GType gst_id3demux_bin_type = 0; - - if (!gst_id3demux_bin_type) { - static const GTypeInfo gst_id3demux_bin_info = { - sizeof (GstId3DemuxBinClass), - (GBaseInitFunc) gst_id3demux_bin_base_init, - NULL, - (GClassInitFunc) gst_id3demux_bin_class_init, - NULL, - NULL, - sizeof (GstId3DemuxBin), - 0, - (GInstanceInitFunc) gst_id3demux_bin_init, - NULL - }; - - gst_id3demux_bin_type = - g_type_register_static (GST_TYPE_BIN, - "GstId3DemuxBin", &gst_id3demux_bin_info, 0); - } - - return gst_id3demux_bin_type; -} - -static void -gst_id3demux_bin_base_init (GstId3DemuxBinClass * klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - static GstElementDetails gst_id3demux_bin_details = - GST_ELEMENT_DETAILS ("ID3-demux bin", - "Codec/Demuxer/Audio", - "Manages typefinding for an ID3 demuxer", - "Ronald Bultje <rbultje@ronald.bitfreak.net>"); - - gst_element_class_set_details (element_class, &gst_id3demux_bin_details); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&id3demux_bin_src_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&id3demux_bin_sink_template)); -} - -static void -gst_id3demux_bin_class_init (GstId3DemuxBinClass * klass) -{ - parent_class = g_type_class_ref (GST_TYPE_BIN); - - GST_ELEMENT_CLASS (klass)->change_state = gst_id3demux_bin_change_state; -} - -static void -gst_id3demux_bin_init (GstId3DemuxBin * id3) -{ - id3->demux = gst_element_factory_make ("id3demux", NULL); - id3->typefind = gst_element_factory_make ("typefind", NULL); - - g_signal_connect (id3->typefind, "have-type", G_CALLBACK (found_type), id3); - gst_pad_use_explicit_caps (gst_element_get_pad (id3->typefind, "src")); - gst_element_add_ghost_pad (GST_ELEMENT (id3), - gst_element_get_pad (id3->demux, "sink"), "sink"); - gst_bin_add_many (GST_BIN (id3), id3->demux, id3->typefind, NULL); - gst_element_link (id3->demux, id3->typefind); -} - -static void -gst_id3demux_bin_remove_pad (GstId3DemuxBin * id3) -{ - if (id3->srcpad) { - gst_element_remove_pad (GST_ELEMENT (id3), id3->srcpad); - id3->srcpad = NULL; - } -} - -static void -found_type (GstElement * element, guint probability, - const GstCaps * caps, gpointer data) -{ - GstId3DemuxBin *id3 = GST_ID3DEMUX_BIN (data); - - /* get rid of old */ - gst_id3demux_bin_remove_pad (id3); - - GST_LOG ("Found type"); - - /* add new */ - if (!gst_pad_set_explicit_caps (gst_element_get_pad (id3->typefind, - "src"), caps)) { - GST_ELEMENT_ERROR (id3, CORE, NEGOTIATION, (NULL), (NULL)); - return; - } - - id3->srcpad = gst_ghost_pad_new ("src", - gst_element_get_pad (id3->typefind, "src")); - gst_element_add_pad (GST_ELEMENT (id3), id3->srcpad); -} - -static GstElementStateReturn -gst_id3demux_bin_change_state (GstElement * element) -{ - GstId3DemuxBin *id3 = GST_ID3DEMUX_BIN (element); - - switch (GST_STATE_TRANSITION (element)) { - case GST_STATE_PAUSED_TO_READY: - gst_id3demux_bin_remove_pad (id3); - break; - default: - break; - } - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - - return GST_STATE_SUCCESS; -} diff --git a/ext/mad/gstid3tag.c b/ext/mad/gstid3tag.c index 58c6702c26..f2c02eb462 100644 --- a/ext/mad/gstid3tag.c +++ b/ext/mad/gstid3tag.c @@ -76,6 +76,7 @@ struct _GstID3Tag /* caps */ GstID3ParseMode parse_mode; + GstCaps *found_caps; /* tags */ GstTagList *event_tags; @@ -123,7 +124,8 @@ GST_DEBUG_CATEGORY_EXTERN (mad_debug); static GstStaticPadTemplate id3_tag_src_any_template_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, - GST_PAD_ALWAYS, + /* FIXME: for spider - should be GST_PAD_ALWAYS, */ + GST_PAD_SOMETIMES, GST_STATIC_CAPS ("ANY") ); @@ -164,9 +166,9 @@ static const GstQueryType *gst_id3_tag_get_query_types (GstPad * pad); static gboolean gst_id3_tag_src_query (GstPad * pad, GstQueryType type, GstFormat * format, gint64 * value); -static void gst_id3_tag_chain (GstPad * pad, GstData * data); -static GstPadLinkReturn gst_id3_tag_src_link (GstPad * pad, - const GstCaps * caps); +static gboolean gst_id3_tag_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_id3_tag_chain (GstPad * pad, GstBuffer * buffer); +static GstPadLinkReturn gst_id3_tag_src_link (GstPad * pad, GstPad * peer); static GstElementStateReturn gst_id3_tag_change_state (GstElement * element); @@ -247,6 +249,9 @@ gst_id3_tag_class_init (gpointer g_class, gpointer class_data) &gst_id3_tag_details[tag_class->type - 1]); } + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_id3_tag_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_id3_tag_get_property); + if (tag_class->type & GST_ID3_TAG_PARSE_DEMUX) { g_object_class_install_property (gobject_class, ARG_PREFER_V1, g_param_spec_boolean ("prefer-v1", "prefer version 1 tag", @@ -276,14 +281,30 @@ gst_id3_tag_class_init (gpointer g_class, gpointer class_data) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&id3_tag_sink_id3_template_factory)); } +} - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_id3_tag_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_id3_tag_get_property); +static GstCaps * +gst_id3_tag_get_caps (GstPad * pad) +{ + GstID3Tag *tag = GST_ID3_TAG (gst_pad_get_parent (pad)); + + if (tag->found_caps) { + GstCaps *caps = gst_caps_copy (tag->found_caps); + + if (CAN_BE_MUXER (tag)) { + gst_caps_append (caps, + gst_caps_from_string ("application/x-gst-tags; application/x-id3")); + } + return caps; + } else { + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } } static void gst_id3_tag_add_src_pad (GstID3Tag * tag) { + g_assert (tag->srcpad == NULL); tag->srcpad = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (tag), "src"), "src"); @@ -295,6 +316,8 @@ gst_id3_tag_add_src_pad (GstID3Tag * tag) GST_DEBUG_FUNCPTR (gst_id3_tag_src_query)); gst_pad_set_query_type_function (tag->srcpad, GST_DEBUG_FUNCPTR (gst_id3_tag_get_query_types)); + gst_pad_set_getcaps_function (tag->srcpad, + GST_DEBUG_FUNCPTR (gst_id3_tag_get_caps)); gst_pad_set_link_function (tag->srcpad, GST_DEBUG_FUNCPTR (gst_id3_tag_src_link)); gst_element_add_pad (GST_ELEMENT (tag), tag->srcpad); @@ -311,17 +334,20 @@ gst_id3_tag_init (GTypeInstance * instance, gpointer g_class) gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"), "sink"); gst_element_add_pad (GST_ELEMENT (tag), tag->sinkpad); + gst_pad_set_event_function (tag->sinkpad, + GST_DEBUG_FUNCPTR (gst_id3_tag_sink_event)); gst_pad_set_chain_function (tag->sinkpad, GST_DEBUG_FUNCPTR (gst_id3_tag_chain)); - + } + if (GST_ID3_TAG_GET_CLASS (tag)->type == GST_ID3_TAG_PARSE_MUX) { + /* only the muxer class here, all other use sometimes pads */ gst_id3_tag_add_src_pad (tag); - - tag->parse_mode = GST_ID3_TAG_GET_CLASS (tag)->type; } + /* FIXME: for the alli^H^H^H^Hspider - gst_id3_tag_add_src_pad (tag); */ + tag->parse_mode = GST_ID3_TAG_PARSE_BASE; tag->buffer = NULL; - - GST_FLAG_SET (tag, GST_ELEMENT_EVENT_AWARE); } + static void gst_id3_tag_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -497,113 +523,6 @@ gst_id3_tag_src_event (GstPad * pad, GstEvent * event) return FALSE; } -static id3_utf8_t * -mad_id3_parse_latin1_string (const id3_ucs4_t * ucs4) -{ - gsize bytes_read, size; - const gchar *env; - char *latin1, *ret = NULL; - - latin1 = id3_ucs4_latin1duplicate (ucs4); - if (latin1 == NULL) - return NULL; - - size = strlen (latin1); - - env = g_getenv ("GST_ID3V2_TAG_ENCODING"); - if (!env || *env == '\0') - env = g_getenv ("GST_ID3_TAG_ENCODING"); - if (!env || *env == '\0') - env = g_getenv ("GST_TAG_ENCODING"); - - if (env && *env != '\0') { - gchar **c, **csets; - - csets = g_strsplit (env, G_SEARCHPATH_SEPARATOR_S, -1); - - for (c = csets; !ret && c && *c; ++c) { - gchar *utf8; - - if ((utf8 = - g_convert (latin1, size, "UTF-8", *c, &bytes_read, NULL, NULL))) { - if (bytes_read == size) { - ret = strdup (utf8); - } - g_free (utf8); - } - } - g_strfreev (csets); - } - - /* Try current locale (if not UTF-8). Should we really do this? - * What if the tag is really correct and in ISO-8859-1 and the - * current locale is some other charset where the full byte range - * is valid? In those cases ISO-8859-1 would have to be put into - * one of the above environment variables. Do the most common - * non-Western and non-UTF8 character sets modify only the range - * from 0x80-0xff, so that ASCII is still covered at least?) */ - if (!ret && !g_get_charset (&env)) { - gchar *utf8; - - if ((utf8 = g_locale_to_utf8 (latin1, size, &bytes_read, NULL, NULL))) { - if (bytes_read == size) { - ret = strdup (utf8); - } - g_free (utf8); - } - } - - /* Try ISO-8859-1 (this conversion should always suceed) */ - if (!ret) { - gchar *utf8; - - utf8 = - g_convert (latin1, size, "UTF-8", "ISO-8859-1", &bytes_read, NULL, - NULL); - if (utf8 != NULL && bytes_read == size) { - ret = strdup (utf8); - } - g_free (utf8); - } - - free (latin1); - return ret; -} - -static void -mad_id3_parse_comment_frame (GstTagList * tlist, const struct id3_frame *frame) -{ - const id3_ucs4_t *ucs4; - id3_utf8_t *utf8; - - g_assert (frame->nfields >= 4); - - ucs4 = id3_field_getfullstring (&frame->fields[3]); - g_assert (ucs4); - - if (frame->fields[0].type == ID3_FIELD_TYPE_TEXTENCODING - && frame->fields[0].number.value == ID3_FIELD_TEXTENCODING_ISO_8859_1) { - utf8 = mad_id3_parse_latin1_string (ucs4); - } else { - utf8 = id3_ucs4_utf8duplicate (ucs4); - } - - if (utf8 == NULL) - return; - - if (!g_utf8_validate (utf8, -1, NULL)) { - g_warning ("converted string is not valid utf-8"); - g_free (utf8); - return; - } - - g_strchomp (utf8); - - gst_tag_list_add (tlist, GST_TAG_MERGE_APPEND, GST_TAG_COMMENT, utf8, NULL); - - g_free (utf8); -} - GstTagList * gst_mad_id3_to_tag_list (const struct id3_tag * tag) { @@ -616,45 +535,52 @@ gst_mad_id3_to_tag_list (const struct id3_tag * tag) tag_list = gst_tag_list_new (); while ((frame = id3_tag_findframe (tag, NULL, i++)) != NULL) { - const union id3_field *field, *encfield; + const union id3_field *field; unsigned int nstrings, j; const gchar *tag_name; - tag_name = gst_tag_from_id3_tag (frame->id); - if (tag_name == NULL) - continue; + /* find me the function to query the frame id */ + gchar *id = g_strndup (frame->id, 5); - if (strncmp (frame->id, "COMM", 5) == 0) { - mad_id3_parse_comment_frame (tag_list, frame); + tag_name = gst_tag_from_id3_tag (id); + if (tag_name == NULL) { + g_free (id); continue; } - if (frame->id[0] != 'T') { - g_warning ("don't know how to parse ID3v2 frame with ID '%s'", frame->id); + if (strcmp (id, "COMM") == 0) { + ucs4 = id3_field_getfullstring (&frame->fields[3]); + g_assert (ucs4); + + utf8 = id3_ucs4_utf8duplicate (ucs4); + if (utf8 == 0) + continue; + + if (!g_utf8_validate (utf8, -1, NULL)) { + g_warning ("converted string is not valid utf-8"); + g_free (utf8); + continue; + } + + gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, + GST_TAG_COMMENT, utf8, NULL); + + g_free (utf8); continue; } - g_assert (frame->nfields >= 2); - field = &frame->fields[1]; nstrings = id3_field_getnstrings (field); - encfield = &frame->fields[0]; for (j = 0; j < nstrings; ++j) { ucs4 = id3_field_getstrings (field, j); g_assert (ucs4); - if (strncmp (frame->id, ID3_FRAME_GENRE, 5) == 0) + if (strcmp (id, ID3_FRAME_GENRE) == 0) ucs4 = id3_genre_name (ucs4); - if (encfield->type == ID3_FIELD_TYPE_TEXTENCODING - && encfield->number.value == ID3_FIELD_TEXTENCODING_ISO_8859_1) { - utf8 = mad_id3_parse_latin1_string (ucs4); - } else { - utf8 = id3_ucs4_utf8duplicate (ucs4); - } - - if (utf8 == NULL) + utf8 = id3_ucs4_utf8duplicate (ucs4); + if (utf8 == 0) continue; if (!g_utf8_validate (utf8, -1, NULL)) { @@ -729,13 +655,13 @@ gst_mad_id3_to_tag_list (const struct id3_tag * tag) } default: g_assert (gst_tag_get_type (tag_name) == G_TYPE_STRING); - g_strchomp (utf8); gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, utf8, NULL); break; } free (utf8); } + g_free (id); } return tag_list; @@ -857,8 +783,9 @@ gst_id3_tag_get_tag_to_render (GstID3Tag * tag) } return ret; } -static void -gst_id3_tag_handle_event (GstPad * pad, GstEvent * event) + +static gboolean +gst_id3_tag_sink_event (GstPad * pad, GstEvent * event) { GstID3Tag *tag = GST_ID3_TAG (gst_pad_get_parent (pad)); @@ -866,10 +793,12 @@ gst_id3_tag_handle_event (GstPad * pad, GstEvent * event) case GST_EVENT_DISCONTINUOUS: switch (tag->state) { case GST_ID3_TAG_STATE_READING_V2_TAG:{ - guint64 value; + guint64 value, end_value; - if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value) || - gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value)) { + if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value, + &end_value) + || gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value, + &end_value)) { if (value != (tag->buffer ? GST_BUFFER_OFFSET (tag->buffer) + GST_BUFFER_SIZE (tag->buffer) @@ -909,10 +838,11 @@ gst_id3_tag_handle_event (GstPad * pad, GstEvent * event) /* fall through */ } case GST_ID3_TAG_STATE_NORMAL:{ - gint64 value; + gint64 value, end_value; GstEvent *new; - if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value)) { + if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value, + &end_value)) { if (value > tag->v2tag_size) { value -= tag->v2tag_size; } else { @@ -922,7 +852,7 @@ gst_id3_tag_handle_event (GstPad * pad, GstEvent * event) new = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, value, 0); gst_data_unref (GST_DATA (event)); - gst_pad_push (tag->srcpad, GST_DATA (new)); + gst_pad_push_event (tag->srcpad, new); } else { gst_pad_event_default (pad, event); } @@ -957,7 +887,7 @@ gst_id3_tag_handle_event (GstPad * pad, GstEvent * event) tag_buffer = gst_buffer_new_and_alloc (128); if (128 != id3_tag_render (id3, tag_buffer->data)) g_assert_not_reached (); - gst_pad_push (tag->srcpad, GST_DATA (tag_buffer)); + gst_pad_push (tag->srcpad, tag_buffer); id3_tag_delete (id3); } gst_tag_list_free (merged); @@ -968,17 +898,108 @@ gst_id3_tag_handle_event (GstPad * pad, GstEvent * event) gst_pad_event_default (pad, event); break; } - return; + return TRUE; +} +typedef struct +{ + guint best_probability; + GstCaps *caps; + GstBuffer *buffer; +} +SimpleTypeFind; +guint8 * +simple_find_peek (gpointer data, gint64 offset, guint size) +{ + SimpleTypeFind *find = (SimpleTypeFind *) data; + + if (offset < 0) + return NULL; + + if (GST_BUFFER_SIZE (find->buffer) >= offset + size) { + return GST_BUFFER_DATA (find->buffer) + offset; + } + return NULL; +} +static void +simple_find_suggest (gpointer data, guint probability, const GstCaps * caps) +{ + SimpleTypeFind *find = (SimpleTypeFind *) data; + + if (probability > find->best_probability) { + gst_caps_replace (&find->caps, gst_caps_copy (caps)); + find->best_probability = probability; + } +} +static GstCaps * +gst_id3_tag_do_typefind (GstID3Tag * tag, GstBuffer * buffer) +{ + GList *walk, *type_list; + SimpleTypeFind find; + GstTypeFind gst_find; + + /* this will help us detecting the media stream type after + * this id3 thingy... Please note that this is a cruel hack + * for as long as spider doesn't support multi-type-finding. + */ + walk = type_list = gst_type_find_factory_get_list (); + + find.buffer = buffer; + find.best_probability = 0; + find.caps = NULL; + gst_find.data = &find; + gst_find.peek = simple_find_peek; + gst_find.get_length = NULL; + gst_find.suggest = simple_find_suggest; + while (walk) { + GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data); + + gst_type_find_factory_call_function (factory, &gst_find); + if (find.best_probability >= GST_TYPE_FIND_MAXIMUM) + break; + walk = g_list_next (walk); + } + g_list_free (type_list); + if (find.best_probability > 0) { + return find.caps; + } else { + GST_ELEMENT_ERROR (tag, CORE, CAPS, (NULL), ("no caps found")); + return NULL; + } +} +static gboolean +gst_id3_tag_do_caps_nego (GstID3Tag * tag, GstBuffer * buffer) +{ + if (buffer != NULL && CAN_BE_DEMUXER (tag)) { + tag->found_caps = gst_id3_tag_do_typefind (tag, buffer); + if (!tag->found_caps) { + return FALSE; + } + } + if (!tag->srcpad) + gst_id3_tag_add_src_pad (tag); + if (!gst_pad_is_linked (tag->srcpad)) { + GST_DEBUG_OBJECT (tag, "srcpad not linked, not proceeding"); + tag->parse_mode = GST_ID3_TAG_GET_CLASS (tag)->type; + return TRUE; + } else { + GST_DEBUG_OBJECT (tag, "renegotiating"); + //return gst_pad_renegotiate (tag->srcpad) != GST_PAD_LINK_REFUSED; + return TRUE; + } } static GstPadLinkReturn -gst_id3_tag_src_link (GstPad * pad, const GstCaps * caps) +gst_id3_tag_src_link (GstPad * pad, GstPad * peer) { GstID3Tag *tag; - const gchar *mimetype; + + //const gchar *mimetype; tag = GST_ID3_TAG (gst_pad_get_parent (pad)); +#if 0 + if (!tag->found_caps && CAN_BE_DEMUXER (tag)) + return GST_PAD_LINK_DELAYED; if (!CAN_BE_MUXER (tag) || !CAN_BE_DEMUXER (tag)) { tag->parse_mode = GST_ID3_TAG_GET_CLASS (tag)->type; return GST_PAD_LINK_OK; @@ -996,8 +1017,8 @@ gst_id3_tag_src_link (GstPad * pad, const GstCaps * caps) tag->parse_mode = GST_ID3_TAG_PARSE_DEMUX; GST_LOG_OBJECT (tag, "parsing operation, extracting tags"); } - - return GST_PAD_LINK_OK; +#endif + return GST_RPAD_LINKFUNC (peer) (peer, pad); } static void gst_id3_tag_send_tag_event (GstID3Tag * tag) @@ -1007,26 +1028,20 @@ gst_id3_tag_send_tag_event (GstID3Tag * tag) GST_TAG_MERGE_KEEP); if (tag->parsed_tags) - gst_element_found_tags (GST_ELEMENT (tag), tag->parsed_tags); + gst_element_post_message (GST_ELEMENT (tag), + gst_message_new_tag (GST_OBJECT (tag), tag->parsed_tags)); + if (merged) { GstEvent *event = gst_event_new_tag (merged); GST_EVENT_TIMESTAMP (event) = 0; - gst_pad_push (tag->srcpad, GST_DATA (event)); + gst_pad_push_event (tag->srcpad, event); } } -static void -gst_id3_tag_chain (GstPad * pad, GstData * data) +static GstFlowReturn +gst_id3_tag_chain (GstPad * pad, GstBuffer * buffer) { GstID3Tag *tag; - GstBuffer *buffer; - - /* handle events */ - if (GST_IS_EVENT (data)) { - gst_id3_tag_handle_event (pad, GST_EVENT (data)); - return; - } - buffer = GST_BUFFER (data); tag = GST_ID3_TAG (gst_pad_get_parent (pad)); @@ -1035,7 +1050,7 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) case GST_ID3_TAG_STATE_SEEKING_TO_NORMAL: /* we're waiting for the seek to finish, just discard all the stuff */ gst_data_unref (GST_DATA (buffer)); - return; + return GST_FLOW_OK; case GST_ID3_TAG_STATE_READING_V1_TAG: if (tag->buffer) { GstBuffer *temp; @@ -1049,7 +1064,7 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) tag->v1tag_offset = buffer->offset; } if (GST_BUFFER_SIZE (tag->buffer) < 128) - return; + return GST_FLOW_OK; g_assert (tag->v1tag_size == 0); tag->v1tag_size = id3_tag_query (GST_BUFFER_DATA (tag->buffer), GST_BUFFER_SIZE (tag->buffer)); @@ -1097,10 +1112,10 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) /* set eos, we're done parsing tags */ GST_LOG_OBJECT (tag, "setting EOS after reading ID3v1 tag"); gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL); - gst_element_set_eos (GST_ELEMENT (tag)); - gst_pad_push (tag->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS))); + //gst_element_set_eos (GST_ELEMENT (tag)); + gst_pad_push_event (tag->srcpad, gst_event_new (GST_EVENT_EOS)); } - return; + return GST_FLOW_OK; case GST_ID3_TAG_STATE_READING_V2_TAG: if (tag->buffer) { GstBuffer *temp; @@ -1113,7 +1128,7 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) tag->buffer = buffer; } if (GST_BUFFER_SIZE (tag->buffer) < 10) - return; + return GST_FLOW_OK; if (tag->v2tag_size == 0) { tag->v2tag_size = id3_tag_query (GST_BUFFER_DATA (tag->buffer), GST_BUFFER_SIZE (tag->buffer)); @@ -1122,7 +1137,7 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) tag->v2tag_size = 0; } if (GST_BUFFER_SIZE (tag->buffer) < tag->v2tag_size + ID3_TYPE_FIND_SIZE) - return; + return GST_FLOW_OK; if (tag->v2tag_size != 0) { struct id3_tag *v2tag; @@ -1157,13 +1172,16 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) GST_BUFFER_OFFSET_END (tag->buffer) + tag->v2tag_size; gst_data_unref (GST_DATA (tag->buffer)); tag->buffer = NULL; + if (tag->found_caps == NULL) + if (!gst_id3_tag_do_caps_nego (tag, buffer)) + return GST_FLOW_OK; /* seek to ID3v1 tag */ if (gst_pad_send_event (GST_PAD_PEER (tag->sinkpad), gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH, -128))) { gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG); gst_data_unref (GST_DATA (buffer)); - return; + return GST_FLOW_OK; } gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START); /* fall through */ @@ -1190,7 +1208,7 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) id3_tag_render (id3, GST_BUFFER_DATA (tag_buffer)); g_assert (estimated >= tag->v2tag_size_new); GST_BUFFER_SIZE (tag_buffer) = tag->v2tag_size_new; - gst_pad_push (tag->srcpad, GST_DATA (tag_buffer)); + gst_pad_push (tag->srcpad, tag_buffer); id3_tag_delete (id3); } gst_tag_list_free (merged); @@ -1206,18 +1224,17 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) case GST_ID3_TAG_STATE_NORMAL: if (tag->parse_mode == GST_ID3_TAG_PARSE_ANY) { gst_data_unref (GST_DATA (buffer)); - gst_element_set_eos (GST_ELEMENT (tag)); - gst_pad_push (tag->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS))); + //gst_element_set_eos (GST_ELEMENT (tag)); + gst_pad_push_event (tag->srcpad, gst_event_new (GST_EVENT_EOS)); } else { if (GST_BUFFER_OFFSET_IS_VALID (buffer)) { if (buffer->offset >= tag->v1tag_offset) { gst_data_unref (GST_DATA (buffer)); - return; + return GST_FLOW_OK; } else if (buffer->offset + buffer->size > tag->v1tag_offset) { GstBuffer *sub = gst_buffer_create_sub (buffer, 0, buffer->size - 128); - GST_BUFFER_OFFSET (sub) = GST_BUFFER_OFFSET (buffer); gst_data_unref (GST_DATA (buffer)); buffer = sub; } @@ -1236,11 +1253,11 @@ gst_id3_tag_chain (GstPad * pad, GstData * data) gst_data_unref (GST_DATA (buffer)); buffer = sub; } - gst_pad_push (tag->srcpad, GST_DATA (buffer)); + gst_pad_push (tag->srcpad, buffer); } - return; + return GST_FLOW_OK; } - g_assert_not_reached (); + return GST_FLOW_OK; } static GstElementStateReturn @@ -1282,7 +1299,11 @@ gst_id3_tag_change_state (GstElement * element) gst_data_unref (GST_DATA (tag->buffer)); tag->buffer = NULL; } - tag->parse_mode = GST_ID3_TAG_GET_CLASS (tag)->type; + if (tag->found_caps) { + gst_caps_unref (tag->found_caps); + tag->found_caps = NULL; + } + tag->parse_mode = GST_ID3_TAG_PARSE_BASE; break; case GST_STATE_READY_TO_NULL: break; @@ -1301,15 +1322,13 @@ plugin_init (GstPlugin * plugin) if (!gst_element_register (plugin, "mad", GST_RANK_PRIMARY, gst_mad_get_type ()) - || !gst_element_register (plugin, "id3demux", GST_RANK_NONE, + || !gst_element_register (plugin, "id3demux", GST_RANK_PRIMARY, gst_id3_tag_get_type (GST_ID3_TAG_PARSE_DEMUX)) || !gst_element_register (plugin, "id3mux", GST_RANK_NONE, /* removed for spider */ gst_id3_tag_get_type (GST_ID3_TAG_PARSE_MUX)) /* FIXME 0.9: remove this element */ || !gst_element_register (plugin, "id3tag", GST_RANK_NONE, - gst_id3_tag_get_type (GST_ID3_TAG_PARSE_ANY)) - || !gst_element_register (plugin, "id3demuxbin", GST_RANK_PRIMARY, - gst_id3demux_bin_get_type ())) { + gst_id3_tag_get_type (GST_ID3_TAG_PARSE_ANY))) { return FALSE; } diff --git a/ext/mad/gstmad.c b/ext/mad/gstmad.c index 1dd0493cc7..703967be3e 100644 --- a/ext/mad/gstmad.c +++ b/ext/mad/gstmad.c @@ -165,7 +165,8 @@ static gboolean gst_mad_convert_sink (GstPad * pad, GstFormat src_format, static gboolean gst_mad_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value, GstFormat * dest_format, gint64 * dest_value); -static void gst_mad_chain (GstPad * pad, GstData * _data); +static gboolean gst_mad_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_mad_chain (GstPad * pad, GstBuffer * buffer); static GstElementStateReturn gst_mad_change_state (GstElement * element); @@ -324,6 +325,8 @@ gst_mad_init (GstMad * mad) (&mad_sink_template_factory), "sink"); gst_element_add_pad (GST_ELEMENT (mad), mad->sinkpad); gst_pad_set_chain_function (mad->sinkpad, GST_DEBUG_FUNCPTR (gst_mad_chain)); + gst_pad_set_event_function (mad->sinkpad, + GST_DEBUG_FUNCPTR (gst_mad_sink_event)); gst_pad_set_convert_function (mad->sinkpad, GST_DEBUG_FUNCPTR (gst_mad_convert_sink)); gst_pad_set_formats_function (mad->sinkpad, @@ -345,7 +348,6 @@ gst_mad_init (GstMad * mad) GST_DEBUG_FUNCPTR (gst_mad_convert_src)); gst_pad_set_formats_function (mad->srcpad, GST_DEBUG_FUNCPTR (gst_mad_get_formats)); - gst_pad_use_explicit_caps (mad->srcpad); mad->tempbuffer = g_malloc (MAD_BUFFER_MDLEN * 3); mad->tempsize = 0; @@ -365,7 +367,6 @@ gst_mad_init (GstMad * mad) mad->half = FALSE; mad->ignore_crc = TRUE; mad->check_for_xing = TRUE; - GST_FLAG_SET (mad, GST_ELEMENT_EVENT_AWARE); } static void @@ -435,7 +436,7 @@ gst_mad_convert_sink (GstPad * pad, GstFormat src_format, gint64 src_value, gboolean res = TRUE; GstMad *mad; - mad = GST_MAD (gst_pad_get_parent (pad)); + mad = GST_MAD (GST_PAD_PARENT (pad)); if (mad->vbr_average == 0) return FALSE; @@ -476,7 +477,7 @@ gst_mad_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value, gint bytes_per_sample; GstMad *mad; - mad = GST_MAD (gst_pad_get_parent (pad)); + mad = GST_MAD (GST_PAD_PARENT (pad)); bytes_per_sample = MAD_NCHANNELS (&mad->frame.header) << 1; @@ -553,7 +554,7 @@ gst_mad_src_query (GstPad * pad, GstQueryType type, gboolean res = TRUE; GstMad *mad; - mad = GST_MAD (gst_pad_get_parent (pad)); + mad = GST_MAD (GST_PAD_PARENT (pad)); switch (type) { case GST_QUERY_TOTAL: @@ -739,30 +740,15 @@ gst_mad_src_event (GstPad * pad, GstEvent * event) gboolean res = TRUE; GstMad *mad; - mad = GST_MAD (gst_pad_get_parent (pad)); + mad = GST_MAD (GST_PAD_PARENT (pad)); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK_SEGMENT: - GST_DEBUG ("forwarding seek event to sink pad"); - gst_event_ref (event); - if (gst_pad_send_event (GST_PAD_PEER (mad->sinkpad), event)) { - /* seek worked, we're done, loop will exit */ - res = TRUE; - } - break; /* the all-formats seek logic */ case GST_EVENT_SEEK: - GST_DEBUG ("forwarding seek event to sink pad"); - gst_event_ref (event); - if (gst_pad_send_event (GST_PAD_PEER (mad->sinkpad), event)) { - /* seek worked, we're done, loop will exit */ - res = TRUE; - } else { - if (mad->index) - res = index_seek (mad, pad, event); - else - res = normal_seek (mad, pad, event); - } + if (mad->index) + res = index_seek (mad, pad, event); + else + res = normal_seek (mad, pad, event); break; default: @@ -887,18 +873,17 @@ G_STMT_START{ \ GST_TAG_LAYER, mad->header.layer, GST_TAG_MODE, mode->value_nick, GST_TAG_EMPHASIS, emphasis->value_nick, NULL); - gst_element_found_tags (GST_ELEMENT (mad), list); - gst_tag_list_free (list); + gst_element_post_message (GST_ELEMENT (mad), + gst_message_new_tag (GST_OBJECT (mad), list)); } #undef CHECK_HEADER } -static void -gst_mad_handle_event (GstPad * pad, GstBuffer * buffer) +static gboolean +gst_mad_sink_event (GstPad * pad, GstEvent * event) { - GstEvent *event = GST_EVENT (buffer); - GstMad *mad = GST_MAD (gst_pad_get_parent (pad)); + GstMad *mad = GST_MAD (GST_PAD_PARENT (pad)); GST_DEBUG ("handling event %d", GST_EVENT_TYPE (event)); switch (GST_EVENT_TYPE (event)) { @@ -916,7 +901,9 @@ gst_mad_handle_event (GstPad * pad, GstBuffer * buffer) if (gst_formats_contains (formats, GST_EVENT_DISCONT_OFFSET (event, i).format)) { - gint64 value = GST_EVENT_DISCONT_OFFSET (event, i).value; + gint64 start_value = GST_EVENT_DISCONT_OFFSET (event, i).start_value; + + //gint64 end_value = GST_EVENT_DISCONT_OFFSET (event, i).end_value; gint64 time; GstFormat format; GstEvent *discont; @@ -926,11 +913,11 @@ gst_mad_handle_event (GstPad * pad, GstBuffer * buffer) format = GST_FORMAT_TIME; if (!gst_pad_convert (pad, GST_EVENT_DISCONT_OFFSET (event, i).format, - value, &format, &time)) { + start_value, &format, &time)) { continue; } } else { - time = value; + time = start_value; } /* for now, this is the best we can do to get the total number @@ -946,7 +933,7 @@ gst_mad_handle_event (GstPad * pad, GstBuffer * buffer) if (GST_PAD_IS_USABLE (mad->srcpad)) { discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL); - gst_pad_push (mad->srcpad, GST_DATA (discont)); + gst_pad_push_event (mad->srcpad, discont); } gst_event_unref (event); goto done; @@ -969,6 +956,7 @@ gst_mad_handle_event (GstPad * pad, GstBuffer * buffer) gst_pad_event_default (pad, event); break; } + return TRUE; } static gboolean @@ -1133,7 +1121,7 @@ mpg123_parse_xing_header (struct mad_header *header, /* internal function to check if the header has changed and thus the * caps need to be reset. Only call during normal mode, not resyncing */ -static gboolean +static void gst_mad_check_caps_reset (GstMad * mad) { guint nchannels; @@ -1146,12 +1134,6 @@ gst_mad_check_caps_reset (GstMad * mad) #else rate = mad->frame.header.samplerate; #endif - if (mad->stream.options & MAD_OPTION_HALFSAMPLERATE) { - GST_INFO_OBJECT (mad, - "MAD_OPTION_HALFSAMPLERATE is set, adapting rate from %u to %u", rate, - rate >> 1); - rate >>= 1; - } /* rate and channels are not supposed to change in a continuous stream, * so check this first before doing anything */ @@ -1170,10 +1152,8 @@ gst_mad_check_caps_reset (GstMad * mad) mad->pending_channels = nchannels; mad->pending_rate = rate; } - /* Now, we already have a valid caps set and will continue to use - * that for a while longer, so we cans afely return TRUE here. */ if (++mad->times_pending < 3) - return TRUE; + return; } } gst_mad_update_info (mad); @@ -1181,6 +1161,11 @@ gst_mad_check_caps_reset (GstMad * mad) if (mad->channels != nchannels || mad->rate != rate) { GstCaps *caps; + if (mad->stream.options & MAD_OPTION_HALFSAMPLERATE) + rate >>= 1; + + /* FIXME see if peer can accept the caps */ + /* we set the caps even when the pad is not connected so they * can be gotten for streaminfo */ caps = gst_caps_new_simple ("audio/x-raw-int", @@ -1190,39 +1175,27 @@ gst_mad_check_caps_reset (GstMad * mad) "depth", G_TYPE_INT, 16, "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, nchannels, NULL); - if (gst_pad_set_explicit_caps (mad->srcpad, caps)) { - mad->caps_set = TRUE; /* set back to FALSE on discont */ - mad->channels = nchannels; - mad->rate = rate; - } else { - GST_ELEMENT_ERROR (mad, CORE, NEGOTIATION, (NULL), - ("Failed to negotiate %d Hz, %d channels", rate, nchannels)); - return FALSE; - } - gst_caps_free (caps); + gst_pad_set_caps (mad->srcpad, caps); + mad->caps_set = TRUE; /* set back to FALSE on discont */ + mad->channels = nchannels; + mad->rate = rate; } - - return TRUE; } -static void -gst_mad_chain (GstPad * pad, GstData * _data) +static GstFlowReturn +gst_mad_chain (GstPad * pad, GstBuffer * buffer) { - GstBuffer *buffer = GST_BUFFER (_data); GstMad *mad; gchar *data; glong size; gboolean new_pts = FALSE; GstClockTime timestamp; + GstFlowReturn result = GST_FLOW_OK; - mad = GST_MAD (gst_pad_get_parent (pad)); - g_return_if_fail (GST_IS_MAD (mad)); + mad = GST_MAD (GST_PAD_PARENT (pad)); + g_return_val_if_fail (GST_IS_MAD (mad), GST_FLOW_ERROR); - /* handle events */ - if (GST_IS_EVENT (buffer)) { - gst_mad_handle_event (pad, buffer); - return; - } + GST_STREAM_LOCK (pad); /* restarts happen on discontinuities, ie. seek, flush, PAUSED to PLAYING */ if (gst_mad_check_restart (mad)) @@ -1266,7 +1239,8 @@ gst_mad_chain (GstPad * pad, GstData * _data) GST_ELEMENT_ERROR (mad, STREAM, DECODE, (NULL), ("mad claims to need more data than %u bytes, we don't have that much", MAD_BUFFER_MDLEN * 3)); - return; + result = GST_FLOW_ERROR; + goto end; } /* append the chunk to process to our internal temporary buffer */ @@ -1287,7 +1261,7 @@ gst_mad_chain (GstPad * pad, GstData * _data) guint nsamples; guint64 time_offset; guint64 time_duration; - gboolean resync = TRUE; + unsigned char const *before_sync, *after_sync; mad->in_error = FALSE; @@ -1295,6 +1269,12 @@ gst_mad_chain (GstPad * pad, GstData * _data) /* added separate header decoding to catch errors earlier, also fixes * some weird decoding errors... */ + GST_LOG ("decoding the header now"); + if (mad_header_decode (&mad->frame.header, &mad->stream) == -1) { + GST_DEBUG ("mad_frame_decode had an error: %s", + mad_stream_errorstr (&mad->stream)); + } + GST_LOG ("decoding one frame now"); if (mad_frame_decode (&mad->frame, &mad->stream) == -1) { @@ -1317,7 +1297,8 @@ gst_mad_chain (GstPad * pad, GstData * _data) mad_stream_errorstr (&mad->stream)); if (!MAD_RECOVERABLE (mad->stream.error)) { GST_ELEMENT_ERROR (mad, STREAM, DECODE, (NULL), (NULL)); - return; + result = GST_FLOW_ERROR; + goto end; } else if (mad->stream.error == MAD_ERROR_LOSTSYNC) { /* lost sync, force a resync */ signed long tagsize; @@ -1341,9 +1322,6 @@ gst_mad_chain (GstPad * pad, GstData * _data) * id3 tags, so we need to flush one byte less than the tagsize */ mad_stream_skip (&mad->stream, tagsize - 1); - /* When we skip, we don't want to call sync */ - resync = FALSE; - tag = id3_tag_parse (data, tagsize); if (tag) { GstTagList *list; @@ -1351,47 +1329,39 @@ gst_mad_chain (GstPad * pad, GstData * _data) list = gst_mad_id3_to_tag_list (tag); id3_tag_delete (tag); GST_DEBUG ("found tag"); - gst_element_found_tags (GST_ELEMENT (mad), list); + gst_element_post_message (GST_ELEMENT (mad), + gst_message_new_tag (GST_OBJECT (mad), + gst_tag_list_copy (list))); if (mad->tags) { gst_tag_list_insert (mad->tags, list, GST_TAG_MERGE_PREPEND); } else { mad->tags = gst_tag_list_copy (list); } if (GST_PAD_IS_USABLE (mad->srcpad)) { - gst_pad_push (mad->srcpad, GST_DATA (gst_event_new_tag (list))); + gst_pad_push_event (mad->srcpad, gst_event_new_tag (list)); } else { gst_tag_list_free (list); } } } } - //Should not sync here if mad_skip has been used before, the offset - //is "pending" inside mad and will be applied on next call to decode. - if (resync) { - unsigned char const *before_sync, *after_sync; - - before_sync = mad->stream.ptr.byte; - if (mad_stream_sync (&mad->stream) != 0) { - consumed = MAD_BUFFER_GUARD < mad->tempsize ? - mad->tempsize - MAD_BUFFER_GUARD : 0; - GST_DEBUG_OBJECT (mad, - "mad_stream_sync failed, skipping all %u bytes we have", - consumed); - } else { - after_sync = mad->stream.ptr.byte; - /* a succesful resync should make us drop bytes as consumed, so - calculate from the byte pointers before and after resync */ - consumed = after_sync - before_sync; - GST_DEBUG_OBJECT (mad, "resynchronization consumes %d bytes", - consumed); - GST_DEBUG_OBJECT (mad, "synced to data: 0x%0x 0x%0x", - *mad->stream.ptr.byte, *(mad->stream.ptr.byte + 1)); - - /* recoverable errors pass */ - } - resync = FALSE; - } + mad_frame_mute (&mad->frame); + mad_synth_mute (&mad->synth); + before_sync = mad->stream.ptr.byte; + if (mad_stream_sync (&mad->stream) != 0) + GST_WARNING ("mad_stream_sync failed"); + after_sync = mad->stream.ptr.byte; + /* a succesful resync should make us drop bytes as consumed, so + calculate from the byte pointers before and after resync */ + consumed = after_sync - before_sync; + GST_DEBUG ("resynchronization consumes %d bytes", consumed); + GST_DEBUG ("synced to data: 0x%0x 0x%0x", *mad->stream.ptr.byte, + *(mad->stream.ptr.byte + 1)); + + + mad_stream_sync (&mad->stream); + /* recoverable errors pass */ goto next; } @@ -1407,9 +1377,10 @@ gst_mad_chain (GstPad * pad, GstData * _data) gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_DURATION, (gint64) time * 1000 * 1000 * 1000, GST_TAG_BITRATE, bitrate, NULL); - gst_element_found_tags (GST_ELEMENT (mad), list); + gst_element_post_message (GST_ELEMENT (mad), + gst_message_new_tag (GST_OBJECT (mad), gst_tag_list_copy (list))); if (GST_PAD_IS_USABLE (mad->srcpad)) { - gst_pad_push (mad->srcpad, GST_DATA (gst_event_new_tag (list))); + gst_pad_push_event (mad->srcpad, gst_event_new_tag (list)); } else { gst_tag_list_free (list); } @@ -1420,10 +1391,8 @@ gst_mad_chain (GstPad * pad, GstData * _data) } /* if we're not resyncing/in error, check if caps need to be set again */ - if (!mad->in_error) { - if (!gst_mad_check_caps_reset (mad)) - goto end; - } + if (!mad->in_error) + gst_mad_check_caps_reset (mad); nsamples = MAD_NSBSAMPLES (&mad->frame.header) * (mad->stream.options & MAD_OPTION_HALFSAMPLERATE ? 16 : 32); @@ -1441,9 +1410,8 @@ gst_mad_chain (GstPad * pad, GstData * _data) &mad->total_samples); mad->last_ts = GST_CLOCK_TIME_NONE; } - time_offset = - mad->total_samples * GST_SECOND / mad->frame.header.samplerate; - time_duration = (nsamples * GST_SECOND / mad->frame.header.samplerate); + time_offset = mad->total_samples * GST_SECOND / mad->rate; + time_duration = (nsamples * GST_SECOND / mad->rate); } if (mad->index) { @@ -1468,7 +1436,10 @@ gst_mad_chain (GstPad * pad, GstData * _data) left_ch = mad->synth.pcm.samples[0]; right_ch = mad->synth.pcm.samples[1]; - outbuffer = gst_buffer_new_and_alloc (nsamples * mad->channels * 2); + /* will attach the caps to the buffer */ + outbuffer = + gst_pad_alloc_buffer (mad->srcpad, 0, nsamples * mad->channels * 2, + GST_PAD_CAPS (mad->srcpad)); outdata = (gint16 *) GST_BUFFER_DATA (outbuffer); GST_BUFFER_TIMESTAMP (outbuffer) = time_offset; @@ -1491,7 +1462,10 @@ gst_mad_chain (GstPad * pad, GstData * _data) } } - gst_pad_push (mad->srcpad, GST_DATA (outbuffer)); + result = gst_pad_push (mad->srcpad, outbuffer); + if (result != GST_FLOW_OK) { + goto end; + } } mad->total_samples += nsamples; @@ -1517,21 +1491,22 @@ gst_mad_chain (GstPad * pad, GstData * _data) if (consumed == 0) consumed = mad->stream.next_frame - mad_input_buffer; - if (mad->stream.skiplen > consumed) - consumed = mad->stream.skiplen; GST_LOG ("mad consumed %d bytes", consumed); /* move out pointer to where mad want the next data */ mad_input_buffer += consumed; mad->tempsize -= consumed; mad->bytes_consumed += consumed; - mad->stream.skiplen = 0; } /* we only get here from breaks, tempsize never actually drops below 0 */ memmove (mad->tempbuffer, mad_input_buffer, mad->tempsize); } + result = GST_FLOW_OK; end: + GST_STREAM_UNLOCK (pad); gst_buffer_unref (buffer); + + return result; } static GstElementStateReturn @@ -1577,6 +1552,7 @@ gst_mad_change_state (GstElement * element) case GST_STATE_PLAYING_TO_PAUSED: break; case GST_STATE_PAUSED_TO_READY: + GST_STREAM_LOCK (mad->sinkpad); mad_synth_finish (&mad->synth); mad_frame_finish (&mad->frame); mad_stream_finish (&mad->stream); @@ -1585,6 +1561,7 @@ gst_mad_change_state (GstElement * element) gst_tag_list_free (mad->tags); mad->tags = NULL; } + GST_STREAM_UNLOCK (mad->sinkpad); break; case GST_STATE_READY_TO_NULL: break; diff --git a/ext/mad/gstmad.h b/ext/mad/gstmad.h index 16acce31cd..a19a6c6096 100644 --- a/ext/mad/gstmad.h +++ b/ext/mad/gstmad.h @@ -31,7 +31,6 @@ G_BEGIN_DECLS GType gst_mad_get_type (void); GType gst_id3_tag_get_type (guint type); -GType gst_id3demux_bin_get_type (void); GstTagList* gst_mad_id3_to_tag_list (const struct id3_tag * tag); struct id3_tag * gst_mad_tag_list_to_id3_tag (GstTagList * list); |