mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
tagging stuff and build fixes. In detail:
Original commit message from CVS: tagging stuff and build fixes. In detail: - make gdk-pixbuf loader work when distchecking - fix invalid syntax in ffmpeg Makefile. wildcards for EXTRA_DIST are not allowed. This broke builds where distdir != srcdir - fix ffmpeg cvs grabbing when srcdir != distdir - new id3tag plugin for id3 tag reading/writing (uses mad's libid3tag) - mad and libid3tag require mad/libid3tag v0.15. Fixed configure to require that - added ogg demuxer in ext/ogg. The demuxer does not handle events yet. Especially getting seeking right will require some effort or code copying from libvorbis. - added raw vorbis detection to typefinding. oggdemux requires a typefind function to detect its contents. - tags plugin in gst/tags. Provides API in <gst/tags/gsttagediting.h>. API includes tag matching GStreamer <=> ID3 and GStreamer <=> vorbis and writing/reading vorbiscomments or ID3v1 tags. Also included is a simple vorbiscomment reader/writer. Writing will not really work though until someone writes oggmux. - various build fixes. Mostly missing (DIST)CLEANFILES. - vorbisenc handles tag writing. Now it's YOUR turn to fix and write more plugins that handle writing/reading of tags. :)
This commit is contained in:
parent
64e2396520
commit
c5ca1b712d
9 changed files with 1190 additions and 255 deletions
24
configure.ac
24
configure.ac
|
@ -12,7 +12,7 @@ AM_MAINTAINER_MODE
|
|||
|
||||
dnl when going to/from release please set the nano (fourth number) right !
|
||||
dnl releases only do Wall, cvs and prerelease does Werror too
|
||||
AS_VERSION(gst-plugins, GST_PLUGINS_VERSION, 0, 7, 1, 1, GST_CVS="no", GST_CVS="yes")
|
||||
AS_VERSION(gst-plugins, GST_PLUGINS_VERSION, 0, 7, 2, 1, GST_CVS="no", GST_CVS="yes")
|
||||
|
||||
dnl add a suffix to apps
|
||||
if test x$program_suffix = xNONE ; then
|
||||
|
@ -189,7 +189,6 @@ fi
|
|||
|
||||
AC_SUBST(GST_CONTROL_LIBS)
|
||||
|
||||
|
||||
dnl Set up conditionals for (target) architecture:
|
||||
dnl ==============================================
|
||||
|
||||
|
@ -241,6 +240,8 @@ if test "x$HAVE_GTK_22" = "xyes"; then
|
|||
AC_SUBST(GTK_VERSION)
|
||||
GTK_PREFIX=`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`
|
||||
GTK_SYSCONFDIR=`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`
|
||||
GDK_PIXBUF_LIBDIR=`$PKG_CONFIG --variable=libdir gdk-pixbuf-2.0`
|
||||
GDK_PIXBUF_PREFIXDIR=`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`
|
||||
AC_SUBST(GTK_BASE_DIR)
|
||||
else
|
||||
PKG_CHECK_MODULES(GTK2, gtk+-2.0, HAVE_GTK_20=yes, HAVE_GTK_20=no)
|
||||
|
@ -255,7 +256,7 @@ AC_SUBST(GTK_CFLAGS)
|
|||
AC_SUBST(HAVE_GTK)
|
||||
AM_CONDITIONAL(HAVE_GDK_LOADERS, test "x$HAVE_GTK_22" = "xyes")
|
||||
|
||||
GDK_PIXBUF_LOADER_DIR="\$(libdir)/gtk-2.0/\$(GTK_VERSION)/\loaders"
|
||||
GDK_PIXBUF_LOADER_DIR="$GDK_PIXBUF_LIBDIR/gtk-2.0/\$(GTK_VERSION)/loaders"
|
||||
AC_ARG_WITH(gdk-pixbuf-loader-dir,
|
||||
AC_HELP_STRING([--with-gdk-pixbuf-loader-dir],
|
||||
[directory to install the gdk_pixbuf loader]),
|
||||
|
@ -265,7 +266,7 @@ AC_ARG_WITH(gdk-pixbuf-loader-dir,
|
|||
])
|
||||
AC_SUBST(GDK_PIXBUF_LOADER_DIR)
|
||||
|
||||
GDK_PIXBUF_CONFFILE="\$(sysconfdir)/gtk-2.0/gdk-pixbuf.loaders"
|
||||
GDK_PIXBUF_CONFFILE="$GDK_PIXBUF_PREFIXDIR/gtk-2.0/gdk-pixbuf.loaders"
|
||||
AC_ARG_WITH(gdk-pixbuf-conffile,
|
||||
AC_HELP_STRING([--with-gdk-pixbuf-conffile],
|
||||
[path to the gdk_pixbuf config file]),
|
||||
|
@ -334,6 +335,7 @@ GST_PLUGINS_ALL="\
|
|||
speed \
|
||||
stereo \
|
||||
synaesthesia \
|
||||
tags \
|
||||
tcp \
|
||||
typefind \
|
||||
udp \
|
||||
|
@ -970,16 +972,15 @@ 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 id3tag, HAVE_MAD="yes", HAVE_MAD="no")
|
||||
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
|
||||
# installed with mad >= 0.14
|
||||
HAVE_MAD="no"
|
||||
save_libs=$LIBS
|
||||
LIBS="-lz"
|
||||
AC_CHECK_LIB(id3tag, id3_tag_query, HAVE_MAD="yes" MAD_LIBS="$MAD_LIBS -lid3tag")
|
||||
AC_CHECK_LIB(id3tag, id3_tag_options, HAVE_MAD="yes" MAD_LIBS="-lmad -lid3tag -lz")
|
||||
LIBS=$save_LIBS
|
||||
fi
|
||||
fi
|
||||
|
@ -1096,6 +1097,13 @@ GST_CHECK_FEATURE(TARKIN, [tarkinenc tarkindec], tarkin, [
|
|||
HAVE_TARKIN="yes"
|
||||
])
|
||||
|
||||
dnl *** ogg ***
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_OGG, true)
|
||||
GST_CHECK_FEATURE(OGG, [ogg de/encoder], oggdemux oggmux, [
|
||||
XIPH_PATH_OGG(HAVE_OGG=yes, HAVE_OGG=no)
|
||||
AS_SCRUB_INCLUDE(OGG_CFLAGS)
|
||||
])
|
||||
|
||||
dnl *** vorbis ***
|
||||
dnl AM_PATH_VORBIS only takes two options
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_VORBIS, true)
|
||||
|
@ -1365,6 +1373,7 @@ gst/spectrum/Makefile
|
|||
gst/speed/Makefile
|
||||
gst/stereo/Makefile
|
||||
gst/synaesthesia/Makefile
|
||||
gst/tags/Makefile
|
||||
gst/tcp/Makefile
|
||||
gst/typefind/Makefile
|
||||
gst/udp/Makefile
|
||||
|
@ -1427,6 +1436,7 @@ ext/mas/Makefile
|
|||
ext/mikmod/Makefile
|
||||
ext/mpeg2dec/Makefile
|
||||
ext/mplex/Makefile
|
||||
ext/ogg/Makefile
|
||||
ext/pango/Makefile
|
||||
ext/raw1394/Makefile
|
||||
ext/sdl/Makefile
|
||||
|
|
|
@ -196,6 +196,12 @@ else
|
|||
MPLEX_DIR=
|
||||
endif
|
||||
|
||||
if USE_OGG
|
||||
OGG_DIR=ogg
|
||||
else
|
||||
OGG_DIR=
|
||||
endif
|
||||
|
||||
if USE_PANGO
|
||||
PANGO_DIR=pango
|
||||
else
|
||||
|
@ -313,6 +319,7 @@ SUBDIRS=\
|
|||
$(MIKMOD_DIR) \
|
||||
$(MPEG2DEC_DIR) \
|
||||
$(MPLEX_DIR) \
|
||||
$(OGG_DIR) \
|
||||
$(PANGO_DIR) \
|
||||
$(RAW1394_DIR) \
|
||||
$(SDL_DIR) \
|
||||
|
@ -361,6 +368,7 @@ DIST_SUBDIRS=\
|
|||
mikmod \
|
||||
mpeg2dec \
|
||||
mplex \
|
||||
ogg \
|
||||
pango \
|
||||
raw1394 \
|
||||
sdl \
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
plugin_LTLIBRARIES = libgstmad.la
|
||||
|
||||
plugin_LTLIBRARIES = libgstmad.la
|
||||
libgstmad_la_SOURCES = gstmad.c gstid3tag.c
|
||||
|
||||
libgstmad_la_SOURCES = gstmad.c
|
||||
libgstmad_la_CFLAGS = $(GST_CFLAGS)
|
||||
libgstmad_la_LIBADD = $(MAD_LIBS)
|
||||
libgstmad_la_LIBADD = $(MAD_LIBS) $(ID3_LIBS)
|
||||
libgstmad_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
noinst_HEADERS = gstmad.h
|
||||
|
|
895
ext/mad/gstid3tag.c
Normal file
895
ext/mad/gstid3tag.c
Normal file
|
@ -0,0 +1,895 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gstid3tagsetter.c: plugin for reading / modifying id3 tags
|
||||
*
|
||||
* 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_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "gstmad.h"
|
||||
#include <gst/gsttaginterface.h>
|
||||
#include <string.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_id3_tag_debug);
|
||||
#define GST_CAT_DEFAULT gst_id3_tag_debug
|
||||
|
||||
#define GST_TYPE_ID3_TAG (gst_id3_tag_get_type())
|
||||
#define GST_ID3_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ID3_TAG, GstID3Tag))
|
||||
#define GST_ID3_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ID3_TAG, GstID3Tag))
|
||||
#define GST_IS_ID3_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ID3_TAG))
|
||||
#define GST_IS_ID3_TAG_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ID3_TAG))
|
||||
|
||||
typedef struct _GstID3Tag GstID3Tag;
|
||||
typedef struct _GstID3TagClass GstID3TagClass;
|
||||
|
||||
typedef enum {
|
||||
GST_ID3_TAG_STATE_READING_V2_TAG,
|
||||
GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG,
|
||||
GST_ID3_TAG_STATE_READING_V1_TAG,
|
||||
GST_ID3_TAG_STATE_SEEKING_TO_NORMAL,
|
||||
GST_ID3_TAG_STATE_NORMAL_START,
|
||||
GST_ID3_TAG_STATE_NORMAL,
|
||||
} GstID3TagState;
|
||||
|
||||
struct _GstID3Tag {
|
||||
GstElement element;
|
||||
|
||||
/* pads */
|
||||
GstPad * sinkpad;
|
||||
GstPad * srcpad;
|
||||
|
||||
/* caps */
|
||||
gint layer;
|
||||
gboolean parse_mode;
|
||||
|
||||
/* tags */
|
||||
GstTagList * parsed_tags;
|
||||
|
||||
/* state */
|
||||
GstID3TagState state;
|
||||
|
||||
GstBuffer * buffer;
|
||||
gboolean prefer_v1tag;
|
||||
glong v1tag_size;
|
||||
glong v1tag_size_new;
|
||||
guint64 v1tag_offset;
|
||||
gboolean v1tag_render;
|
||||
glong v2tag_size;
|
||||
glong v2tag_size_new;
|
||||
gboolean v2tag_render;
|
||||
};
|
||||
|
||||
struct _GstID3TagClass {
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
/* elementfactory information */
|
||||
static GstElementDetails gst_id3_tag_details = GST_ELEMENT_DETAILS (
|
||||
"id3 tag extractor",
|
||||
"Tag",
|
||||
"Extract tagging information from mp3s",
|
||||
"Benjamin Otte <in7y118@public.uni-hamburg.de>"
|
||||
);
|
||||
|
||||
|
||||
/* signals and args */
|
||||
enum {
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_V1_TAG,
|
||||
ARG_V2_TAG,
|
||||
ARG_PREFER_V1
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
GST_PAD_TEMPLATE_FACTORY (id3_tag_src_template_factory,
|
||||
"src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_CAPS_NEW (
|
||||
"id3_tag_data_src",
|
||||
"audio/mpeg",
|
||||
"layer", GST_PROPS_INT_RANGE (1, 3)
|
||||
),
|
||||
GST_CAPS_NEW (
|
||||
"id3_tag_tag_src",
|
||||
"application/x-gst-tags",
|
||||
NULL
|
||||
)
|
||||
)
|
||||
|
||||
GST_PAD_TEMPLATE_FACTORY (id3_tag_sink_template_factory,
|
||||
"sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_CAPS_NEW (
|
||||
"id3_tag_data_sink",
|
||||
"audio/mpeg",
|
||||
"layer", GST_PROPS_INT_RANGE (1, 3)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
static void gst_id3_tag_base_init (gpointer g_class);
|
||||
static void gst_id3_tag_class_init (GstID3TagClass * klass);
|
||||
static void gst_id3_tag_init (GstID3Tag * tag);
|
||||
static void gst_id3_tag_set_property (GObject * object,
|
||||
guint prop_id,
|
||||
const GValue * value,
|
||||
GParamSpec * pspec);
|
||||
static void gst_id3_tag_get_property (GObject * object,
|
||||
guint prop_id,
|
||||
GValue * value,
|
||||
GParamSpec * pspec);
|
||||
|
||||
static gboolean gst_id3_tag_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
static const GstEventMask* gst_id3_tag_get_event_masks (GstPad * pad);
|
||||
static const GstQueryType* gst_id3_tag_get_query_types (GstPad * pad);
|
||||
|
||||
static GstPadLinkReturn gst_id3_tag_link_sink (GstPad * pad,
|
||||
GstCaps * caps);
|
||||
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 GstElementStateReturn gst_id3_tag_change_state (GstElement * element);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
/* static guint gst_id3_tag_signals[LAST_SIGNAL] = { 0 }; */
|
||||
|
||||
GType
|
||||
gst_id3_tag_get_type (void)
|
||||
{
|
||||
static GType id3_tag_type = 0;
|
||||
|
||||
if (!id3_tag_type) {
|
||||
static const GTypeInfo id3_tag_info = {
|
||||
sizeof (GstID3TagClass),
|
||||
gst_id3_tag_base_init,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_id3_tag_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstID3Tag),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_id3_tag_init,
|
||||
};
|
||||
static const GInterfaceInfo tag_setter_info = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
id3_tag_type = g_type_register_static(GST_TYPE_ELEMENT, "GstID3Tag", &id3_tag_info, 0);
|
||||
|
||||
g_type_add_interface_static (id3_tag_type, GST_TYPE_TAG_SETTER, &tag_setter_info);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_id3_tag_debug, "id3tag", 0, "id3 tag reader / setter");
|
||||
}
|
||||
return id3_tag_type;
|
||||
}
|
||||
static void
|
||||
gst_id3_tag_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_set_details (element_class, &gst_id3_tag_details);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
GST_PAD_TEMPLATE_GET (id3_tag_sink_template_factory));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
GST_PAD_TEMPLATE_GET (id3_tag_src_template_factory));
|
||||
}
|
||||
static void
|
||||
gst_id3_tag_class_init (GstID3TagClass *klass)
|
||||
{
|
||||
GstElementClass *gstelement_class;
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
gstelement_class = (GstElementClass*) klass;
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
|
||||
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
|
||||
|
||||
gstelement_class->change_state = gst_id3_tag_change_state;
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_V1_TAG,
|
||||
g_param_spec_boolean ("v1-tag", "add version 1 tag", "Add version 1 tag at end of file",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (gobject_class, ARG_V2_TAG,
|
||||
g_param_spec_boolean ("v2-tag", "add version 2 tag", "Add version 2 tag at start of file",
|
||||
TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (gobject_class, ARG_PREFER_V1,
|
||||
g_param_spec_boolean ("prefer-v1", "prefer version 1 tag", "Prefer tags from tag at end of file",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
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 void
|
||||
gst_id3_tag_init (GstID3Tag *tag)
|
||||
{
|
||||
/* create the sink and src pads */
|
||||
tag->sinkpad = gst_pad_new_from_template(
|
||||
GST_PAD_TEMPLATE_GET (id3_tag_sink_template_factory), "sink");
|
||||
gst_element_add_pad (GST_ELEMENT (tag), tag->sinkpad);
|
||||
gst_pad_set_chain_function (tag->sinkpad, GST_DEBUG_FUNCPTR (gst_id3_tag_chain));
|
||||
gst_pad_set_link_function (tag->sinkpad, GST_DEBUG_FUNCPTR (gst_id3_tag_link_sink));
|
||||
|
||||
tag->srcpad = gst_pad_new_from_template(
|
||||
GST_PAD_TEMPLATE_GET (id3_tag_src_template_factory), "src");
|
||||
gst_element_add_pad (GST_ELEMENT (tag), tag->srcpad);
|
||||
gst_pad_set_event_function (tag->srcpad, GST_DEBUG_FUNCPTR (gst_id3_tag_src_event));
|
||||
gst_pad_set_event_mask_function (tag->srcpad, GST_DEBUG_FUNCPTR (gst_id3_tag_get_event_masks));
|
||||
gst_pad_set_query_function (tag->srcpad, 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));
|
||||
|
||||
tag->parsed_tags = NULL;
|
||||
tag->state = GST_ID3_TAG_STATE_READING_V2_TAG;
|
||||
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)
|
||||
{
|
||||
GstID3Tag *tag;
|
||||
|
||||
tag = GST_ID3_TAG (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_V1_TAG:
|
||||
tag->v1tag_render = g_value_get_boolean (value);
|
||||
tag->v1tag_size_new = (tag->v1tag_render && (tag->parsed_tags != NULL ||
|
||||
gst_tag_setter_get_list (GST_TAG_SETTER (tag)) != NULL)) ? 128 : 0;
|
||||
g_object_notify (object, "v1-tag");
|
||||
break;
|
||||
case ARG_V2_TAG:
|
||||
tag->v2tag_render = g_value_get_boolean (value);
|
||||
g_object_notify (object, "v2-tag");
|
||||
break;
|
||||
case ARG_PREFER_V1:
|
||||
tag->prefer_v1tag = g_value_get_boolean (value);
|
||||
g_object_notify (object, "prefer-v1");
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
gst_id3_tag_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstID3Tag *tag;
|
||||
tag = GST_ID3_TAG (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_V1_TAG:
|
||||
g_value_set_boolean (value, tag->v1tag_render);
|
||||
break;
|
||||
case ARG_V2_TAG:
|
||||
g_value_set_boolean (value, tag->v2tag_render);
|
||||
break;
|
||||
case ARG_PREFER_V1:
|
||||
g_value_set_boolean (value, tag->prefer_v1tag);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static const GstEventMask*
|
||||
gst_id3_tag_get_event_masks (GstPad *pad)
|
||||
{
|
||||
static const GstEventMask gst_id3_tag_src_event_masks[] = {
|
||||
{ GST_EVENT_SEEK, GST_SEEK_METHOD_SET |
|
||||
GST_SEEK_FLAG_FLUSH },
|
||||
{ 0, }
|
||||
};
|
||||
return gst_id3_tag_src_event_masks;
|
||||
}
|
||||
static const GstQueryType*
|
||||
gst_id3_tag_get_query_types (GstPad *pad)
|
||||
{
|
||||
static const GstQueryType gst_id3_tag_src_query_types[] = {
|
||||
GST_QUERY_TOTAL,
|
||||
GST_QUERY_POSITION,
|
||||
0
|
||||
};
|
||||
return gst_id3_tag_src_query_types;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_id3_tag_src_query (GstPad *pad, GstQueryType type,
|
||||
GstFormat *format, gint64 *value)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
GstID3Tag *tag;
|
||||
|
||||
tag = GST_ID3_TAG (gst_pad_get_parent (pad));
|
||||
|
||||
switch (type) {
|
||||
case GST_QUERY_TOTAL: {
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_PAD_PEER (tag->sinkpad) &&
|
||||
tag->state == GST_ID3_TAG_STATE_NORMAL &&
|
||||
gst_pad_query (GST_PAD_PEER (tag->sinkpad), GST_QUERY_TOTAL, format, value)) {
|
||||
*value -= tag->v2tag_size + tag->v1tag_size;
|
||||
*value += tag->v2tag_size_new + tag->v1tag_size;
|
||||
res = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_POSITION:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
if (GST_PAD_PEER (tag->sinkpad) &&
|
||||
gst_pad_query (GST_PAD_PEER (tag->sinkpad), GST_QUERY_POSITION, format, value)) {
|
||||
if (tag->state == GST_ID3_TAG_STATE_NORMAL) {
|
||||
*value -= tag->v2tag_size + tag->v2tag_size_new;
|
||||
} else {
|
||||
*value = 0;
|
||||
}
|
||||
res = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_id3_tag_src_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
GstID3Tag *tag;
|
||||
|
||||
tag = GST_ID3_TAG (gst_pad_get_parent (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
if (GST_EVENT_SEEK_FORMAT (event) == GST_FORMAT_BYTES &&
|
||||
tag->state == GST_ID3_TAG_STATE_NORMAL &&
|
||||
GST_PAD_PEER (tag->sinkpad)) {
|
||||
GstEvent *new;
|
||||
gint diff;
|
||||
|
||||
switch (GST_EVENT_SEEK_METHOD (event)) {
|
||||
case GST_SEEK_METHOD_SET: diff = tag->v2tag_size_new - tag->v2tag_size;
|
||||
case GST_SEEK_METHOD_CUR: diff = 0;
|
||||
case GST_SEEK_METHOD_END: diff = GST_EVENT_SEEK_OFFSET(event) ? tag->v1tag_size_new - tag->v1tag_size : 0;
|
||||
default: g_assert_not_reached();
|
||||
}
|
||||
new = gst_event_new_seek (GST_EVENT_SEEK_TYPE (event),
|
||||
GST_EVENT_SEEK_OFFSET(event) + diff);
|
||||
gst_event_unref (event);
|
||||
return gst_pad_send_event (GST_PAD_PEER (tag->sinkpad), new);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gst_event_unref (event);
|
||||
return FALSE;
|
||||
}
|
||||
static GstPadLinkReturn
|
||||
gst_id3_tag_link_sink (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstID3Tag *tag;
|
||||
|
||||
tag = GST_ID3_TAG (gst_pad_get_parent (pad));
|
||||
|
||||
if (!GST_CAPS_IS_FIXED (caps))
|
||||
return GST_PAD_LINK_DELAYED;
|
||||
|
||||
if (!gst_caps_get_int (caps, "layer", &tag->layer))
|
||||
return GST_PAD_LINK_DELAYED;
|
||||
|
||||
return GST_PAD_LINK_OK;
|
||||
}
|
||||
GstTagList*
|
||||
gst_mad_id3_to_tag_list(const struct id3_tag *tag)
|
||||
{
|
||||
const struct id3_frame *frame;
|
||||
const id3_ucs4_t *ucs4;
|
||||
id3_utf8_t *utf8;
|
||||
GstTagList *tag_list;
|
||||
guint i = 0;
|
||||
|
||||
tag_list = gst_tag_list_new ();
|
||||
|
||||
while ((frame = id3_tag_findframe(tag, NULL, i++)) != NULL) {
|
||||
const union id3_field *field;
|
||||
unsigned int nstrings, j;
|
||||
const gchar *tag_name;
|
||||
/* find me the function to query the frame id */
|
||||
gchar *id = g_strndup (frame->id, 5);
|
||||
|
||||
tag_name = gst_tag_from_id3_tag (id);
|
||||
if (tag_name == NULL) {
|
||||
g_free (id);
|
||||
continue;
|
||||
}
|
||||
|
||||
field = &frame->fields[1];
|
||||
nstrings = id3_field_getnstrings(field);
|
||||
|
||||
for (j = 0; j < nstrings; ++j) {
|
||||
ucs4 = id3_field_getstrings(field, j);
|
||||
g_assert(ucs4);
|
||||
|
||||
if (strcmp(id, ID3_FRAME_GENRE) == 0)
|
||||
ucs4 = id3_genre_name(ucs4);
|
||||
|
||||
utf8 = id3_ucs4_utf8duplicate(ucs4);
|
||||
if (utf8 == 0)
|
||||
continue;
|
||||
|
||||
/* be sure to add non-string tags here */
|
||||
switch (gst_tag_get_type (tag_name)) {
|
||||
case G_TYPE_UINT:
|
||||
{
|
||||
guint tmp;
|
||||
gchar *check;
|
||||
tmp = strtoul (utf8, &check, 10);
|
||||
if (*check != '\0') break;
|
||||
if (strcmp (tag_name, GST_TAG_DATE) == 0) {
|
||||
if (tmp == 0) break;
|
||||
GDate *d = g_date_new_dmy (1, 1, tmp);
|
||||
tmp = g_date_get_julian (d);
|
||||
g_date_free (d);
|
||||
}
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, tmp, NULL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert (gst_tag_get_type (tag_name) == G_TYPE_STRING);
|
||||
gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, utf8, NULL);
|
||||
break;
|
||||
}
|
||||
free (utf8);
|
||||
}
|
||||
g_free (id);
|
||||
}
|
||||
|
||||
return tag_list;
|
||||
}
|
||||
static void
|
||||
tag_list_to_id3_tag_foreach (const GstTagList *list, const gchar *tag_name, gpointer user_data)
|
||||
{
|
||||
struct id3_frame *frame;
|
||||
union id3_field *field;
|
||||
guint values = gst_tag_list_get_tag_size (list, tag_name);
|
||||
const gchar *id = gst_tag_to_id3_tag (tag_name);
|
||||
struct id3_tag *tag = (struct id3_tag *) user_data;
|
||||
|
||||
if (id == NULL)
|
||||
return;
|
||||
|
||||
if (values == 0)
|
||||
return;
|
||||
|
||||
frame = id3_frame_new (id);
|
||||
if (id3_tag_attachframe (tag, frame) != 0) {
|
||||
GST_WARNING ("could not attach frame (%s) to id3 tag", id);
|
||||
return;
|
||||
}
|
||||
field = id3_frame_field (frame, 1);
|
||||
g_assert (field);
|
||||
while (values-- > 0) {
|
||||
id3_ucs4_t *put;
|
||||
|
||||
if (strcmp (tag_name, GST_TAG_DATE) == 0) {
|
||||
gchar *str;
|
||||
guint u;
|
||||
GDate *d;
|
||||
|
||||
g_assert (gst_tag_list_get_uint_index (list, tag_name, values, &u));
|
||||
d = g_date_new_julian (u);
|
||||
str = g_strdup_printf ("%u", (guint) (g_date_get_year (d)));
|
||||
put = id3_utf8_ucs4duplicate (str);
|
||||
g_date_free (d);
|
||||
g_free (str);
|
||||
} else if (strcmp (tag_name, GST_TAG_TRACK_NUMBER) == 0) {
|
||||
gchar *str;
|
||||
guint u;
|
||||
|
||||
g_assert (gst_tag_list_get_uint_index (list, tag_name, values, &u));
|
||||
str = g_strdup_printf ("%u", u);
|
||||
put = id3_utf8_ucs4duplicate (str);
|
||||
g_free (str);
|
||||
} else {
|
||||
gchar *str;
|
||||
|
||||
if (gst_tag_get_type (tag_name) != G_TYPE_STRING) {
|
||||
GST_WARNING ("unhandled GStreamer tag %s", tag_name);
|
||||
return;
|
||||
}
|
||||
g_assert (gst_tag_list_get_string_index (list, tag_name, values, &str));
|
||||
put = id3_utf8_ucs4duplicate (str);
|
||||
g_free (str);
|
||||
}
|
||||
if (id3_field_addstring (field, put) != 0) {
|
||||
GST_WARNING ("could not add a string to id3 tag field");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct id3_tag *
|
||||
gst_mad_tag_list_to_id3_tag (GstTagList *list)
|
||||
{
|
||||
struct id3_tag *tag;
|
||||
|
||||
tag = id3_tag_new ();
|
||||
|
||||
gst_tag_list_foreach (list, tag_list_to_id3_tag_foreach, tag);
|
||||
return tag;
|
||||
}
|
||||
static void
|
||||
gst_id3_tag_handle_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
GstID3Tag *tag = GST_ID3_TAG (gst_pad_get_parent (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
switch (tag->state) {
|
||||
case GST_ID3_TAG_STATE_READING_V2_TAG:
|
||||
gst_element_error (GST_ELEMENT (tag), "Seek during ID3v2 tag reading");
|
||||
break;
|
||||
case GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG:
|
||||
/* just assume it's the right seek for now */
|
||||
tag->state = GST_ID3_TAG_STATE_READING_V1_TAG;
|
||||
break;
|
||||
case GST_ID3_TAG_STATE_READING_V1_TAG:
|
||||
gst_element_error (GST_ELEMENT (tag), "Seek during ID3v1 tag reading");
|
||||
break;
|
||||
case GST_ID3_TAG_STATE_SEEKING_TO_NORMAL:
|
||||
/* just assume it's the right seek for now */
|
||||
tag->state = GST_ID3_TAG_STATE_NORMAL_START;
|
||||
break;
|
||||
case GST_ID3_TAG_STATE_NORMAL_START:
|
||||
GST_ERROR_OBJECT (tag, "tag event loss, FIXME");
|
||||
tag->state = GST_ID3_TAG_STATE_NORMAL;
|
||||
/* fall through */
|
||||
case GST_ID3_TAG_STATE_NORMAL: {
|
||||
gint64 value;
|
||||
GstEvent *new;
|
||||
|
||||
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value)) {
|
||||
value += tag->v1tag_size;
|
||||
new = gst_event_new_discontinuous (GST_FORMAT_BYTES, value, 0);
|
||||
gst_data_unref (GST_DATA (event));
|
||||
gst_pad_push (tag->srcpad, GST_DATA (new));
|
||||
} else {
|
||||
gst_pad_event_default (pad, event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_TAG:
|
||||
gst_tag_list_insert (tag->parsed_tags, gst_event_tag_get_list (event), GST_TAG_MERGE_PREPEND);
|
||||
gst_data_unref (GST_DATA (event));
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
if (tag->v1tag_render && !tag->parse_mode) {
|
||||
GstTagList *merged;
|
||||
struct id3_tag *id3;
|
||||
|
||||
GST_LOG_OBJECT (tag, "rendering v1 tag after eos event");
|
||||
merged = gst_tag_list_merge (gst_tag_setter_get_list (GST_TAG_SETTER (tag)), tag->parsed_tags,
|
||||
gst_tag_setter_get_merge_mode (GST_TAG_SETTER (tag)));
|
||||
if (merged) {
|
||||
id3 = gst_mad_tag_list_to_id3_tag (merged);
|
||||
if (id3) {
|
||||
GstBuffer *tag_buffer;
|
||||
|
||||
id3_tag_options (id3, ID3_TAG_OPTION_ID3V1, ID3_TAG_OPTION_ID3V1);
|
||||
tag_buffer = gst_buffer_new_and_alloc (128);
|
||||
g_assert (128 == id3_tag_render (id3, tag_buffer->data));
|
||||
gst_pad_push (tag->srcpad, GST_DATA (tag_buffer));
|
||||
id3_tag_delete (id3);
|
||||
}
|
||||
gst_tag_list_free (merged);
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
gst_pad_event_default (pad, event);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
static void
|
||||
gst_id3_tag_chain (GstPad *pad, GstData *data)
|
||||
{
|
||||
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));
|
||||
|
||||
switch (tag->state) {
|
||||
case GST_ID3_TAG_STATE_READING_V2_TAG:
|
||||
if (tag->buffer) {
|
||||
tag->buffer = gst_buffer_merge (tag->buffer, buffer);
|
||||
} else {
|
||||
GstCaps *caps;
|
||||
/* do caps nego */
|
||||
capsnego:
|
||||
if (tag->layer > 0) {
|
||||
caps = GST_CAPS_NEW ("id3_tag_data_src", "audio/mpeg", "layer", GST_PROPS_INT (tag->layer));
|
||||
} else {
|
||||
caps = GST_CAPS_NEW ("id3_tag_data_src", "audio/mpeg", NULL);
|
||||
}
|
||||
if (gst_pad_try_set_caps (tag->srcpad, caps) != GST_PAD_LINK_REFUSED) {
|
||||
tag->parse_mode = FALSE;
|
||||
GST_LOG_OBJECT (tag, "normal operation, using audio/mpeg output");
|
||||
} else {
|
||||
if (gst_pad_try_set_caps (tag->srcpad,
|
||||
GST_CAPS_NEW ("id3_tag_tag_src", "application/x-gst-tags", NULL))
|
||||
!= GST_PAD_LINK_REFUSED) {
|
||||
tag->parse_mode = TRUE;
|
||||
GST_LOG_OBJECT (tag, "fast operation, just outputting tags");
|
||||
} else {
|
||||
GstCaps *caps = gst_pad_template_get_caps (GST_PAD_TEMPLATE_GET (id3_tag_src_template_factory));
|
||||
if (gst_pad_recover_caps_error (tag->srcpad, caps)) {
|
||||
goto capsnego;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* done caps nego */
|
||||
tag->buffer = buffer;
|
||||
}
|
||||
if (GST_BUFFER_SIZE (tag->buffer) < 10)
|
||||
return;
|
||||
if (tag->v2tag_size == 0) {
|
||||
tag->v2tag_size = id3_tag_query (GST_BUFFER_DATA (tag->buffer),
|
||||
GST_BUFFER_SIZE (tag->buffer));
|
||||
/* no footers supported */
|
||||
if (tag->v2tag_size < 0)
|
||||
tag->v2tag_size = 0;
|
||||
}
|
||||
if (tag->v2tag_size != 0) {
|
||||
if (GST_BUFFER_SIZE (tag->buffer) > tag->v2tag_size) {
|
||||
struct id3_tag *v2tag;
|
||||
|
||||
v2tag = id3_tag_parse (GST_BUFFER_DATA (tag->buffer),
|
||||
GST_BUFFER_SIZE (tag->buffer));
|
||||
if (v2tag) {
|
||||
g_assert (tag->parsed_tags == NULL);
|
||||
tag->parsed_tags = gst_mad_id3_to_tag_list (v2tag);
|
||||
id3_tag_delete (v2tag);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (tag, "detected ID3v2 tag, but couldn't parse it");
|
||||
tag->v2tag_size = 0;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* 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))) {
|
||||
tag->state = GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG;
|
||||
} else {
|
||||
GstBuffer *sub;
|
||||
|
||||
tag->state = GST_ID3_TAG_STATE_NORMAL_START;
|
||||
sub = gst_buffer_create_sub (tag->buffer, tag->v2tag_size,
|
||||
GST_BUFFER_SIZE (tag->buffer) - tag->v2tag_size);
|
||||
gst_pad_push (tag->srcpad, GST_DATA (sub));
|
||||
}
|
||||
gst_data_unref (GST_DATA (tag->buffer));
|
||||
tag->buffer = NULL;
|
||||
return;
|
||||
case GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG:
|
||||
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;
|
||||
case GST_ID3_TAG_STATE_READING_V1_TAG:
|
||||
if (tag->buffer) {
|
||||
tag->buffer = gst_buffer_merge (tag->buffer, buffer);
|
||||
} else {
|
||||
tag->buffer = buffer;
|
||||
tag->v1tag_offset = buffer->offset;
|
||||
}
|
||||
if (GST_BUFFER_SIZE (tag->buffer) < 128)
|
||||
return;
|
||||
g_assert (tag->v1tag_size == 0);
|
||||
tag->v1tag_size = id3_tag_query (GST_BUFFER_DATA (tag->buffer),
|
||||
GST_BUFFER_SIZE (tag->buffer));
|
||||
if (tag->v1tag_size == 128) {
|
||||
struct id3_tag *v1tag;
|
||||
|
||||
v1tag = id3_tag_parse (GST_BUFFER_DATA (tag->buffer),
|
||||
GST_BUFFER_SIZE (tag->buffer));
|
||||
if (v1tag) {
|
||||
GstTagList *newtag;
|
||||
|
||||
newtag = gst_mad_id3_to_tag_list (v1tag);
|
||||
id3_tag_delete (v1tag);
|
||||
if (tag->parsed_tags) {
|
||||
gst_tag_list_insert (tag->parsed_tags, newtag,
|
||||
tag->prefer_v1tag ? GST_TAG_MERGE_REPLACE : GST_TAG_MERGE_KEEP);
|
||||
gst_tag_list_free (newtag);
|
||||
} else {
|
||||
tag->parsed_tags = newtag;
|
||||
}
|
||||
} else {
|
||||
GST_WARNING_OBJECT (tag, "detected ID3v1 tag, but couldn't parse it");
|
||||
tag->v2tag_size = 0;
|
||||
}
|
||||
} else if (tag->v1tag_size != 0) {
|
||||
GST_WARNING_OBJECT (tag, "bad non-ID3v1 tag at end of file");
|
||||
tag->v1tag_size = 0;
|
||||
}
|
||||
gst_data_unref (GST_DATA (tag->buffer));
|
||||
tag->buffer = NULL;
|
||||
if (!tag->parse_mode) {
|
||||
/* seek to beginning */
|
||||
GST_LOG_OBJECT (tag, "seeking back to beginning");
|
||||
if (gst_pad_send_event (GST_PAD_PEER (tag->sinkpad),
|
||||
gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET |
|
||||
GST_SEEK_FLAG_FLUSH, tag->v2tag_size))) {
|
||||
tag->state = GST_ID3_TAG_STATE_SEEKING_TO_NORMAL;
|
||||
} else {
|
||||
gst_element_error (GST_ELEMENT (tag), "can't seek back to beginning from reading ID3v1 tag");
|
||||
}
|
||||
} else {
|
||||
if (tag->parsed_tags)
|
||||
gst_element_found_tags_for_pad (GST_ELEMENT (tag), tag->srcpad, 0,
|
||||
gst_tag_list_copy (tag->parsed_tags));
|
||||
/* set eos, we're done parsing tags */
|
||||
GST_LOG_OBJECT (tag, "setting EOS after reading ID3v1 tag");
|
||||
tag->state = 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)));
|
||||
}
|
||||
return;
|
||||
case GST_ID3_TAG_STATE_NORMAL_START:
|
||||
if (tag->parse_mode) {
|
||||
if (tag->parsed_tags)
|
||||
gst_element_found_tags_for_pad (GST_ELEMENT (tag), tag->srcpad, 0,
|
||||
gst_tag_list_copy (tag->parsed_tags));
|
||||
} else {
|
||||
struct id3_tag *id3;
|
||||
GstTagList *merged;
|
||||
GstBuffer *tag_buffer;
|
||||
|
||||
/* send event */
|
||||
if (tag->parsed_tags)
|
||||
gst_element_found_tags (GST_ELEMENT (tag), tag->parsed_tags);
|
||||
/* render tag */
|
||||
tag->v2tag_size_new = 0;
|
||||
if (tag->v2tag_render) {
|
||||
merged = gst_tag_list_merge (gst_tag_setter_get_list (GST_TAG_SETTER (tag)), tag->parsed_tags,
|
||||
gst_tag_setter_get_merge_mode (GST_TAG_SETTER (tag)));
|
||||
if (merged) {
|
||||
id3 = gst_mad_tag_list_to_id3_tag (merged);
|
||||
if (id3) {
|
||||
glong estimated;
|
||||
estimated = id3_tag_render (id3, NULL);
|
||||
tag_buffer = gst_buffer_new_and_alloc (estimated);
|
||||
tag->v2tag_size_new = 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));
|
||||
id3_tag_delete (id3);
|
||||
}
|
||||
gst_tag_list_free (merged);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
tag->state = GST_ID3_TAG_STATE_NORMAL;
|
||||
tag->v1tag_size_new = (tag->v1tag_render && (tag->parsed_tags != NULL ||
|
||||
gst_tag_setter_get_list (GST_TAG_SETTER (tag)) != NULL)) ? 128 : 0;
|
||||
case GST_ID3_TAG_STATE_NORMAL:
|
||||
if (tag->parse_mode) {
|
||||
gst_element_set_eos (GST_ELEMENT (tag));
|
||||
gst_pad_push (tag->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
|
||||
} else {
|
||||
if (buffer->offset >= tag->v1tag_offset) {
|
||||
gst_data_unref (GST_DATA (buffer));
|
||||
return;
|
||||
} else if (buffer->offset + buffer->size > tag->v1tag_offset) {
|
||||
GstBuffer *sub = gst_buffer_create_sub (buffer, 0,
|
||||
buffer->size - 128);
|
||||
gst_data_unref (GST_DATA (buffer));
|
||||
buffer = sub;
|
||||
}
|
||||
gst_pad_push (tag->srcpad, GST_DATA (buffer));
|
||||
}
|
||||
return;
|
||||
}
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_id3_tag_change_state (GstElement *element)
|
||||
{
|
||||
GstID3Tag *tag;
|
||||
|
||||
tag = GST_ID3_TAG (element);
|
||||
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
break;
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
g_assert (tag->parsed_tags == NULL);
|
||||
g_assert (tag->buffer == NULL);
|
||||
tag->v1tag_size = 0;
|
||||
tag->v1tag_offset = G_MAXUINT64;
|
||||
tag->v2tag_size = 0;
|
||||
tag->layer = 0;
|
||||
break;
|
||||
case GST_STATE_PAUSED_TO_PLAYING:
|
||||
/* do something to get out of the chain function faster */
|
||||
break;
|
||||
case GST_STATE_PLAYING_TO_PAUSED:
|
||||
break;
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
if (tag->parsed_tags) {
|
||||
gst_tag_list_free (tag->parsed_tags);
|
||||
tag->parsed_tags = NULL;
|
||||
}
|
||||
if (tag->buffer) {
|
||||
gst_data_unref (GST_DATA (tag->buffer));
|
||||
tag->buffer = NULL;
|
||||
}
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
break;
|
||||
}
|
||||
|
||||
return parent_class->change_state (element);
|
||||
}
|
232
ext/mad/gstmad.c
232
ext/mad/gstmad.c
|
@ -20,13 +20,9 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <gst/gst.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_SEEK);
|
||||
|
||||
#include <string.h>
|
||||
#include <mad.h>
|
||||
#include "id3tag.h"
|
||||
#include "gstmad.h"
|
||||
|
||||
#define GST_TYPE_MAD \
|
||||
(gst_mad_get_type())
|
||||
|
@ -73,8 +69,7 @@ struct _GstMad {
|
|||
gboolean half;
|
||||
gboolean ignore_crc;
|
||||
|
||||
GstCaps *metadata;
|
||||
GstCaps *streaminfo;
|
||||
GstTagList * tags;
|
||||
|
||||
/* negotiated format */
|
||||
gint rate;
|
||||
|
@ -294,12 +289,6 @@ gst_mad_class_init (GstMadClass *klass)
|
|||
g_object_class_install_property (gobject_class, ARG_IGNORE_CRC,
|
||||
g_param_spec_boolean ("ignore_crc", "Ignore CRC", "Ignore CRC errors",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_METADATA,
|
||||
g_param_spec_boxed ("metadata", "Metadata", "Metadata",
|
||||
GST_TYPE_CAPS, G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class, ARG_STREAMINFO,
|
||||
g_param_spec_boxed ("streaminfo", "Streaminfo", "Streaminfo",
|
||||
GST_TYPE_CAPS, G_PARAM_READABLE));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -337,8 +326,7 @@ gst_mad_init (GstMad *mad)
|
|||
mad->segment_start = 0;
|
||||
mad->header.mode = -1;
|
||||
mad->header.emphasis = -1;
|
||||
mad->metadata = NULL;
|
||||
mad->streaminfo = NULL;
|
||||
mad->tags = NULL;
|
||||
|
||||
mad->half = FALSE;
|
||||
mad->ignore_crc = FALSE;
|
||||
|
@ -625,7 +613,7 @@ index_seek (GstMad *mad, GstPad *pad, GstEvent *event)
|
|||
if (gst_index_entry_assoc_map (entry, *try_formats, &value)) {
|
||||
/* lookup succeeded, create the seek */
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_SEEK, "index %s %" G_GINT64_FORMAT
|
||||
GST_DEBUG ("index %s %" G_GINT64_FORMAT
|
||||
" -> %s %" G_GINT64_FORMAT,
|
||||
gst_format_get_details (GST_EVENT_SEEK_FORMAT (event))->nick,
|
||||
GST_EVENT_SEEK_OFFSET (event),
|
||||
|
@ -799,54 +787,12 @@ gst_mad_get_property (GObject *object, guint prop_id,
|
|||
case ARG_IGNORE_CRC:
|
||||
g_value_set_boolean (value, mad->ignore_crc);
|
||||
break;
|
||||
case ARG_METADATA:
|
||||
g_value_set_boxed (value, mad->metadata);
|
||||
break;
|
||||
case ARG_STREAMINFO:
|
||||
g_value_set_boxed (value, mad->streaminfo);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GstCaps*
|
||||
gst_mad_get_streaminfo (GstMad *mad)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GstProps *props;
|
||||
GstPropsEntry *entry;
|
||||
GEnumValue *value;
|
||||
GEnumClass *klass;
|
||||
|
||||
props = gst_props_empty_new ();
|
||||
|
||||
entry = gst_props_entry_new ("layer", GST_PROPS_INT (mad->header.layer));
|
||||
gst_props_add_entry (props, (GstPropsEntry *) entry);
|
||||
|
||||
klass = g_type_class_ref (GST_TYPE_MAD_MODE);
|
||||
value = g_enum_get_value (klass,
|
||||
mad->header.mode);
|
||||
if (value)
|
||||
entry = gst_props_entry_new ("mode", GST_PROPS_STRING (value->value_nick));
|
||||
g_type_class_unref (klass);
|
||||
gst_props_add_entry (props, (GstPropsEntry *) entry);
|
||||
|
||||
klass = g_type_class_ref (GST_TYPE_MAD_EMPHASIS);
|
||||
value = g_enum_get_value (klass,
|
||||
mad->header.emphasis);
|
||||
if (value)
|
||||
entry = gst_props_entry_new ("emphasis", GST_PROPS_STRING (value->value_nick));
|
||||
g_type_class_unref (klass);
|
||||
gst_props_add_entry (props, (GstPropsEntry *) entry);
|
||||
|
||||
caps = gst_caps_new ("mad_streaminfo",
|
||||
"application/x-gst-streaminfo",
|
||||
props);
|
||||
return caps;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_mad_update_info (GstMad *mad)
|
||||
{
|
||||
|
@ -882,148 +828,10 @@ G_STMT_START{ \
|
|||
}
|
||||
mad->new_header = FALSE;
|
||||
|
||||
if (changed) {
|
||||
gst_caps_replace_sink (&mad->streaminfo, gst_mad_get_streaminfo (mad));
|
||||
g_object_notify (G_OBJECT (mad), "streaminfo");
|
||||
}
|
||||
#undef CHECK_HEADER
|
||||
|
||||
}
|
||||
|
||||
/* gracefuly ripped from madplay */
|
||||
static GstCaps*
|
||||
id3_to_caps(struct id3_tag const *tag)
|
||||
{
|
||||
unsigned int i;
|
||||
struct id3_frame const *frame;
|
||||
id3_ucs4_t const *ucs4;
|
||||
id3_utf8_t *utf8;
|
||||
GstProps *props;
|
||||
GstPropsEntry *entry;
|
||||
GstCaps *caps;
|
||||
GList *values;
|
||||
|
||||
struct {
|
||||
char const *id;
|
||||
char const *name;
|
||||
} const info[] = {
|
||||
{ ID3_FRAME_TITLE, "Title" },
|
||||
{ "TIT3", "Subtitle" },
|
||||
{ "TCOP", "Copyright" },
|
||||
{ "TPRO", "Produced" },
|
||||
{ "TCOM", "Composer" },
|
||||
{ ID3_FRAME_ARTIST, "Artist" },
|
||||
{ "TPE2", "Orchestra" },
|
||||
{ "TPE3", "Conductor" },
|
||||
{ "TEXT", "Lyricist" },
|
||||
{ ID3_FRAME_ALBUM, "Album" },
|
||||
{ ID3_FRAME_YEAR, "Year" },
|
||||
{ ID3_FRAME_TRACK, "Track" },
|
||||
{ "TPUB", "Publisher" },
|
||||
{ ID3_FRAME_GENRE, "Genre" },
|
||||
{ "TRSN", "Station" },
|
||||
{ "TENC", "Encoder" },
|
||||
};
|
||||
|
||||
/* text information */
|
||||
props = gst_props_empty_new ();
|
||||
|
||||
for (i = 0; i < sizeof(info) / sizeof(info[0]); ++i) {
|
||||
union id3_field const *field;
|
||||
unsigned int nstrings, namelen, j;
|
||||
char const *name;
|
||||
|
||||
frame = id3_tag_findframe(tag, info[i].id, 0);
|
||||
if (frame == 0)
|
||||
continue;
|
||||
|
||||
field = &frame->fields[1];
|
||||
nstrings = id3_field_getnstrings(field);
|
||||
|
||||
name = info[i].name;
|
||||
|
||||
if (name) {
|
||||
namelen = name ? strlen(name) : 0;
|
||||
|
||||
values = NULL;
|
||||
for (j = 0; j < nstrings; ++j) {
|
||||
ucs4 = id3_field_getstrings(field, j);
|
||||
g_assert(ucs4);
|
||||
|
||||
if (strcmp(info[i].id, ID3_FRAME_GENRE) == 0)
|
||||
ucs4 = id3_genre_name(ucs4);
|
||||
|
||||
utf8 = id3_ucs4_utf8duplicate(ucs4);
|
||||
if (utf8 == 0)
|
||||
goto fail;
|
||||
|
||||
entry = gst_props_entry_new (name, GST_PROPS_STRING_TYPE, utf8);
|
||||
values = g_list_prepend (values, entry);
|
||||
free(utf8);
|
||||
}
|
||||
if (values) {
|
||||
values = g_list_reverse (values);
|
||||
|
||||
if (g_list_length (values) == 1) {
|
||||
gst_props_add_entry (props, (GstPropsEntry *) values->data);
|
||||
}
|
||||
else {
|
||||
entry = gst_props_entry_new(name, GST_PROPS_GLIST_TYPE, values);
|
||||
gst_props_add_entry (props, (GstPropsEntry *) entry);
|
||||
}
|
||||
g_list_free (values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
values = NULL;
|
||||
i = 0;
|
||||
while ((frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, i++))) {
|
||||
ucs4 = id3_field_getstring(&frame->fields[2]);
|
||||
g_assert(ucs4);
|
||||
|
||||
if (*ucs4)
|
||||
continue;
|
||||
|
||||
ucs4 = id3_field_getfullstring(&frame->fields[3]);
|
||||
g_assert(ucs4);
|
||||
|
||||
utf8 = id3_ucs4_utf8duplicate(ucs4);
|
||||
if (utf8 == 0)
|
||||
goto fail;
|
||||
|
||||
entry = gst_props_entry_new ("Comment", GST_PROPS_STRING_TYPE, utf8);
|
||||
values = g_list_prepend (values, entry);
|
||||
free(utf8);
|
||||
}
|
||||
if (values) {
|
||||
values = g_list_reverse (values);
|
||||
|
||||
if (g_list_length (values) == 1) {
|
||||
gst_props_add_entry (props, (GstPropsEntry *) values->data);
|
||||
}
|
||||
else {
|
||||
entry = gst_props_entry_new("Comment", GST_PROPS_GLIST_TYPE, values);
|
||||
gst_props_add_entry (props, (GstPropsEntry *) entry);
|
||||
}
|
||||
g_list_free (values);
|
||||
}
|
||||
|
||||
gst_props_debug (props);
|
||||
|
||||
caps = gst_caps_new ("mad_metadata",
|
||||
"application/x-gst-metadata",
|
||||
props);
|
||||
if (0) {
|
||||
fail:
|
||||
g_warning ("mad: could not parse ID3 tag");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_mad_handle_event (GstPad *pad, GstBuffer *buffer)
|
||||
{
|
||||
|
@ -1212,9 +1020,22 @@ gst_mad_chain (GstPad *pad, GstData *_data)
|
|||
|
||||
tag = id3_tag_parse (data, tagsize);
|
||||
if (tag) {
|
||||
gst_caps_replace_sink (&mad->metadata, id3_to_caps (tag));
|
||||
GstTagList *list;
|
||||
|
||||
list = gst_mad_id3_to_tag_list (tag);
|
||||
id3_tag_delete (tag);
|
||||
g_object_notify (G_OBJECT (mad), "metadata");
|
||||
GST_DEBUG_OBJECT (mad, "found tag");
|
||||
gst_element_found_tags (GST_ELEMENT (mad), 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)));
|
||||
} else {
|
||||
gst_tag_list_free (list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1405,8 +1226,10 @@ gst_mad_change_state (GstElement *element)
|
|||
mad_frame_finish (&mad->frame);
|
||||
mad_stream_finish (&mad->stream);
|
||||
mad->restart = TRUE;
|
||||
gst_caps_replace (&mad->metadata, NULL);
|
||||
gst_caps_replace (&mad->streaminfo, NULL);
|
||||
if (mad->tags) {
|
||||
gst_tag_list_free (mad->tags);
|
||||
mad->tags = NULL;
|
||||
}
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
break;
|
||||
|
@ -1418,8 +1241,13 @@ gst_mad_change_state (GstElement *element)
|
|||
static gboolean
|
||||
plugin_init (GstPlugin *plugin)
|
||||
{
|
||||
/* we need the gsttags plugin for metadata querying */
|
||||
if (!gst_plugin_load ("gsttags"))
|
||||
return FALSE;
|
||||
|
||||
/* create an elementfactory for the mad element */
|
||||
if (!gst_element_register (plugin, "mad", GST_RANK_PRIMARY, GST_TYPE_MAD))
|
||||
if (!gst_element_register (plugin, "mad", GST_RANK_PRIMARY, GST_TYPE_MAD) ||
|
||||
!gst_element_register (plugin, "id3tag", GST_RANK_PRIMARY, gst_id3_tag_get_type ()))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
@ -1429,7 +1257,7 @@ GST_PLUGIN_DEFINE (
|
|||
GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"mad",
|
||||
"mp3 decoding based on the mad library",
|
||||
"mp3 decoding and tag editing based on the mad library",
|
||||
plugin_init,
|
||||
VERSION,
|
||||
"GPL",
|
||||
|
|
41
ext/mad/gstmad.h
Normal file
41
ext/mad/gstmad.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* 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_GNOME_VFS_H__
|
||||
#define __GST_GNOME_VFS_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/tags/gsttagediting.h>
|
||||
#include <mad.h>
|
||||
#include <id3tag.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
GType gst_mad_get_type (void);
|
||||
GType gst_id3_tag_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);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_GNOME_VFS_H__ */
|
|
@ -25,43 +25,6 @@ patches:
|
|||
|
||||
SUBDIRS =
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(PATCHES) \
|
||||
Tag \
|
||||
ffmpeg/CREDITS \
|
||||
ffmpeg/INSTALL \
|
||||
ffmpeg/README \
|
||||
ffmpeg/config.mak \
|
||||
ffmpeg/configure \
|
||||
ffmpeg/cygwin_inttypes.h \
|
||||
ffmpeg/ffserver.h \
|
||||
ffmpeg/ffmpeg.c \
|
||||
ffmpeg/ffserver.c \
|
||||
ffmpeg/berrno.h \
|
||||
ffmpeg/config.h \
|
||||
ffmpeg/libavcodec/alpha/*.c \
|
||||
ffmpeg/libavcodec/alpha/*.h \
|
||||
ffmpeg/libavcodec/alpha/*.S \
|
||||
ffmpeg/libavcodec/armv4l/*.c \
|
||||
ffmpeg/libavcodec/armv4l/*.S \
|
||||
ffmpeg/libavcodec/i386/*.c \
|
||||
ffmpeg/libavcodec/i386/*.h \
|
||||
ffmpeg/libavcodec/liba52/*.c \
|
||||
ffmpeg/libavcodec/liba52/*.h \
|
||||
ffmpeg/libavcodec/ppc/*.c \
|
||||
ffmpeg/libavcodec/ppc/*.h \
|
||||
ffmpeg/libavcodec/ps2/*.c \
|
||||
ffmpeg/libavcodec/ps2/*.h \
|
||||
ffmpeg/libavcodec/*.c \
|
||||
ffmpeg/libavcodec/*.h \
|
||||
ffmpeg/libavformat/*.c \
|
||||
ffmpeg/libavformat/*.h \
|
||||
ffmpeg/tests/*.c \
|
||||
ffmpeg/tests/*.ref \
|
||||
ffmpeg/tests/*.sh \
|
||||
ffmpeg/tests/test.conf \
|
||||
ffmpeg/vhook/*.c
|
||||
|
||||
|
||||
checkout:
|
||||
cvs -d:pserver:anonymous@mplayerhq.hu:/cvsroot/ffmpeg co ffmpeg
|
||||
|
@ -164,9 +127,7 @@ libavformat_la_CFLAGS = $(defs) -Wall -I$(srcdir) -I$(srcdir)/ffmpeg \
|
|||
-I$(top_srcdir)/gst-libs/ext/linux/ -DHAVE_AV_CONFIG_H \
|
||||
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE
|
||||
|
||||
|
||||
if HAVE_CPU_I386
|
||||
sources_i386 = \
|
||||
files_i386 = \
|
||||
ffmpeg/libavcodec/i386/cputest.c \
|
||||
ffmpeg/libavcodec/i386/dsputil_mmx.c \
|
||||
ffmpeg/libavcodec/i386/fdct_mmx.c \
|
||||
|
@ -175,12 +136,13 @@ sources_i386 = \
|
|||
ffmpeg/libavcodec/i386/motion_est_mmx.c \
|
||||
ffmpeg/libavcodec/i386/mpegvideo_mmx.c \
|
||||
ffmpeg/libavcodec/i386/simple_idct_mmx.c
|
||||
if HAVE_CPU_I386
|
||||
sources_i386 = $(files_i386)
|
||||
else
|
||||
sources_i386 =
|
||||
endif
|
||||
|
||||
if HAVE_CPU_PPC
|
||||
sources_powerpc = \
|
||||
files_powerpc = \
|
||||
ffmpeg/libavcodec/ppc/dsputil_ppc.c \
|
||||
ffmpeg/libavcodec/ppc/mpegvideo_ppc.c
|
||||
# disabled Altivec support for now until someone shows up that make them compile conditionally
|
||||
|
@ -189,6 +151,8 @@ sources_powerpc = \
|
|||
# ffmpeg/libavcodec/ppc/gmc_altivec.c \
|
||||
# ffmpeg/libavcodec/ppc/idct_altivec.c \
|
||||
# ffmpeg/libavcodec/ppc/mpegvideo_altivec.c
|
||||
if HAVE_CPU_PPC
|
||||
sources_powerpc = $(files_powerpc)
|
||||
else
|
||||
sources_powerpc =
|
||||
endif
|
||||
|
@ -270,3 +234,86 @@ libavcodec_la_SOURCES = \
|
|||
$(sources_i386) \
|
||||
$(sources_powerpc)
|
||||
|
||||
more_libavcodec_files = \
|
||||
ffmpeg/libavcodec/mdec.c \
|
||||
ffmpeg/libavcodec/motion_est_template.c \
|
||||
ffmpeg/libavcodec/svq3.c \
|
||||
ffmpeg/libavcodec/wmv2.c
|
||||
|
||||
|
||||
all_headers = \
|
||||
ffmpeg/berrno.h \
|
||||
ffmpeg/cmdutils.h \
|
||||
ffmpeg/cygwin_inttypes.h \
|
||||
ffmpeg/ffserver.h \
|
||||
ffmpeg/xvmc_render.h \
|
||||
ffmpeg/libavcodec/ac3.h \
|
||||
ffmpeg/libavcodec/ac3tab.h \
|
||||
ffmpeg/libavcodec/avcodec.h \
|
||||
ffmpeg/libavcodec/bswap.h \
|
||||
ffmpeg/libavcodec/cabac.h \
|
||||
ffmpeg/libavcodec/common.h \
|
||||
ffmpeg/libavcodec/dsputil.h \
|
||||
ffmpeg/libavcodec/dvdata.h \
|
||||
ffmpeg/libavcodec/faandct.h \
|
||||
ffmpeg/libavcodec/fastmemcpy.h \
|
||||
ffmpeg/libavcodec/golomb.h \
|
||||
ffmpeg/libavcodec/h263data.h \
|
||||
ffmpeg/libavcodec/h264data.h \
|
||||
ffmpeg/libavcodec/imgconvert_template.h \
|
||||
ffmpeg/libavcodec/indeo3data.h \
|
||||
ffmpeg/libavcodec/mpeg12data.h \
|
||||
ffmpeg/libavcodec/mpeg4data.h \
|
||||
ffmpeg/libavcodec/mpegaudio.h \
|
||||
ffmpeg/libavcodec/mpegaudiodectab.h \
|
||||
ffmpeg/libavcodec/mpegaudiotab.h \
|
||||
ffmpeg/libavcodec/mpegvideo.h \
|
||||
ffmpeg/libavcodec/msmpeg4data.h \
|
||||
ffmpeg/libavcodec/oggvorbis.h \
|
||||
ffmpeg/libavcodec/ra144.h \
|
||||
ffmpeg/libavcodec/ra288.h \
|
||||
ffmpeg/libavcodec/rational.h \
|
||||
ffmpeg/libavcodec/simple_idct.h \
|
||||
ffmpeg/libavcodec/sp5x.h \
|
||||
ffmpeg/libavcodec/svq1_cb.h \
|
||||
ffmpeg/libavcodec/svq1_vlc.h \
|
||||
ffmpeg/libavcodec/vp3data.h \
|
||||
ffmpeg/libavcodec/wmadata.h \
|
||||
ffmpeg/libavcodec/i386/dsputil_mmx_avg.h \
|
||||
ffmpeg/libavcodec/i386/dsputil_mmx_rnd.h \
|
||||
ffmpeg/libavcodec/i386/mmx.h \
|
||||
ffmpeg/libavcodec/ppc/dsputil_altivec.h \
|
||||
ffmpeg/libavcodec/ppc/dsputil_ppc.h \
|
||||
ffmpeg/libavcodec/ppc/gcc_fixes.h \
|
||||
ffmpeg/libavformat/avformat.h \
|
||||
ffmpeg/libavformat/avi.h \
|
||||
ffmpeg/libavformat/avio.h \
|
||||
ffmpeg/libavformat/barpainet.h \
|
||||
ffmpeg/libavformat/dv.h \
|
||||
ffmpeg/libavformat/dv1394.h \
|
||||
ffmpeg/libavformat/framehook.h \
|
||||
ffmpeg/libavformat/mpegts.h \
|
||||
ffmpeg/libavformat/os_support.h \
|
||||
ffmpeg/libavformat/rtp.h \
|
||||
ffmpeg/libavformat/rtsp.h \
|
||||
ffmpeg/libavformat/rtspcodes.h
|
||||
|
||||
DISTCLEANFILES = \
|
||||
ffmpeg/config.h \
|
||||
ffmpeg/config.mak
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(PATCHES) \
|
||||
Tag \
|
||||
ffmpeg/CREDITS \
|
||||
ffmpeg/INSTALL \
|
||||
ffmpeg/README \
|
||||
ffmpeg/configure \
|
||||
ffmpeg/ffmpeg.c \
|
||||
ffmpeg/ffserver.c \
|
||||
$(libavcodec_la_SOURCES) \
|
||||
$(more_libavcodec_files) \
|
||||
$(libavformat_la_SOURCES) \
|
||||
$(files_i386) \
|
||||
$(files_powerpc) \
|
||||
$(all_headers)
|
||||
|
|
|
@ -22,7 +22,10 @@ AC_DEFUN(AS_SLURP_FFMPEG,
|
|||
DIRECTORY=`pwd`
|
||||
# get/update cvs
|
||||
if test ! -d $1; then mkdir -p $1; fi
|
||||
cd $1
|
||||
dnl we need to check $srcdir/$1 or it will always checkout ffmpeg even if it is there
|
||||
dnl at least when top_srcdir != top_builddir.
|
||||
dnl FIXME: unfortunately this makes the checkout go into top_srcdir
|
||||
cd $srcdir/$1
|
||||
|
||||
if test ! -e ffmpeg/README; then
|
||||
# check out cvs code
|
||||
|
|
102
m4/ogg.m4
Normal file
102
m4/ogg.m4
Normal file
|
@ -0,0 +1,102 @@
|
|||
# Configure paths for libogg
|
||||
# Jack Moffitt <jack@icecast.org> 10-21-2000
|
||||
# Shamelessly stolen from Owen Taylor and Manish Singh
|
||||
|
||||
dnl XIPH_PATH_OGG([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for libogg, and define OGG_CFLAGS and OGG_LIBS
|
||||
dnl
|
||||
AC_DEFUN(XIPH_PATH_OGG,
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(ogg,[ --with-ogg=PFX Prefix where libogg is installed (optional)], ogg_prefix="$withval", ogg_prefix="")
|
||||
AC_ARG_WITH(ogg-libraries,[ --with-ogg-libraries=DIR Directory where libogg library is installed (optional)], ogg_libraries="$withval", ogg_libraries="")
|
||||
AC_ARG_WITH(ogg-includes,[ --with-ogg-includes=DIR Directory where libogg header files are installed (optional)], ogg_includes="$withval", ogg_includes="")
|
||||
AC_ARG_ENABLE(oggtest, [ --disable-oggtest Do not try to compile and run a test Ogg program],, enable_oggtest=yes)
|
||||
|
||||
if test "x$ogg_libraries" != "x" ; then
|
||||
OGG_LIBS="-L$ogg_libraries"
|
||||
elif test "x$ogg_prefix" != "x" ; then
|
||||
OGG_LIBS="-L$ogg_prefix/lib"
|
||||
elif test "x$prefix" != "xNONE" ; then
|
||||
OGG_LIBS="-L$prefix/lib"
|
||||
fi
|
||||
|
||||
OGG_LIBS="$OGG_LIBS -logg"
|
||||
|
||||
if test "x$ogg_includes" != "x" ; then
|
||||
OGG_CFLAGS="-I$ogg_includes"
|
||||
elif test "x$ogg_prefix" != "x" ; then
|
||||
OGG_CFLAGS="-I$ogg_prefix/include"
|
||||
elif test "$prefix" != "xNONE"; then
|
||||
OGG_CFLAGS="-I$prefix/include"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for Ogg)
|
||||
no_ogg=""
|
||||
|
||||
|
||||
if test "x$enable_oggtest" = "xyes" ; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $OGG_CFLAGS"
|
||||
LIBS="$LIBS $OGG_LIBS"
|
||||
dnl
|
||||
dnl Now check if the installed Ogg is sufficiently new.
|
||||
dnl
|
||||
rm -f conf.oggtest
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
system("touch conf.oggtest");
|
||||
return 0;
|
||||
}
|
||||
|
||||
],, no_ogg=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
if test "x$no_ogg" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.oggtest ; then
|
||||
:
|
||||
else
|
||||
echo "*** Could not run Ogg test program, checking why..."
|
||||
CFLAGS="$CFLAGS $OGG_CFLAGS"
|
||||
LIBS="$LIBS $OGG_LIBS"
|
||||
AC_TRY_LINK([
|
||||
#include <stdio.h>
|
||||
#include <ogg/ogg.h>
|
||||
], [ return 0; ],
|
||||
[ echo "*** The test program compiled, but did not run. This usually means"
|
||||
echo "*** that the run-time linker is not finding Ogg or finding the wrong"
|
||||
echo "*** version of Ogg. If it is not finding Ogg, you'll need to set your"
|
||||
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
|
||||
echo "*** to the installed location Also, make sure you have run ldconfig if that"
|
||||
echo "*** is required on your system"
|
||||
echo "***"
|
||||
echo "*** If you have an old version installed, it is best to remove it, although"
|
||||
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
|
||||
[ echo "*** The test program failed to compile or link. See the file config.log for the"
|
||||
echo "*** exact error that occured. This usually means Ogg was incorrectly installed"
|
||||
echo "*** or that you have moved Ogg since it was installed." ])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
OGG_CFLAGS=""
|
||||
OGG_LIBS=""
|
||||
ifelse([$2], , :, [$2])
|
||||
fi
|
||||
AC_SUBST(OGG_CFLAGS)
|
||||
AC_SUBST(OGG_LIBS)
|
||||
rm -f conf.oggtest
|
||||
])
|
Loading…
Reference in a new issue