mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 00:31:13 +00:00
ext/vorbis/: Add new vorbistag element which derives from vorbisparse and is essentially the same as well, only that ...
Original commit message from CVS: Patch by: James "Doc" Livingston <doclivingston at gmail com> * ext/vorbis/Makefile.am: * ext/vorbis/vorbis.c: (plugin_init): * ext/vorbis/vorbisparse.c: (gst_vorbis_parse_class_init), (vorbis_parse_parse_packet), (vorbis_parse_chain): * ext/vorbis/vorbisparse.h: * ext/vorbis/vorbistag.c: (gst_vorbis_tag_base_init), (gst_vorbis_tag_class_init), (gst_vorbis_tag_init), (gst_vorbis_tag_parse_packet): * ext/vorbis/vorbistag.h: Add new vorbistag element which derives from vorbisparse and is essentially the same as well, only that it implements the GstTagSetter interface and can modify the stream's vorbiscomment on the fly (#335635). * tests/check/Makefile.am: * tests/check/elements/.cvsignore: * tests/check/elements/vorbistag.c: (setup_vorbistag), (cleanup_vorbistag), (buffer_probe), (start_pipeline), (get_buffer), (stop_pipeline), (_create_codebook_header_buffer), (_create_audio_buffer), (GST_START_TEST), (vorbistag_suite): Add unit test for new vorbistag element.
This commit is contained in:
parent
623b0b5339
commit
f88fbe139d
10 changed files with 694 additions and 9 deletions
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
||||||
|
2006-10-03 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
|
Patch by: James "Doc" Livingston <doclivingston at gmail com>
|
||||||
|
|
||||||
|
* ext/vorbis/Makefile.am:
|
||||||
|
* ext/vorbis/vorbis.c: (plugin_init):
|
||||||
|
* ext/vorbis/vorbisparse.c: (gst_vorbis_parse_class_init),
|
||||||
|
(vorbis_parse_parse_packet), (vorbis_parse_chain):
|
||||||
|
* ext/vorbis/vorbisparse.h:
|
||||||
|
* ext/vorbis/vorbistag.c: (gst_vorbis_tag_base_init),
|
||||||
|
(gst_vorbis_tag_class_init), (gst_vorbis_tag_init),
|
||||||
|
(gst_vorbis_tag_parse_packet):
|
||||||
|
* ext/vorbis/vorbistag.h:
|
||||||
|
Add new vorbistag element which derives from vorbisparse
|
||||||
|
and is essentially the same as well, only that it implements
|
||||||
|
the GstTagSetter interface and can modify the stream's
|
||||||
|
vorbiscomment on the fly (#335635).
|
||||||
|
|
||||||
|
* tests/check/Makefile.am:
|
||||||
|
* tests/check/elements/.cvsignore:
|
||||||
|
* tests/check/elements/vorbistag.c: (setup_vorbistag),
|
||||||
|
(cleanup_vorbistag), (buffer_probe), (start_pipeline),
|
||||||
|
(get_buffer), (stop_pipeline), (_create_codebook_header_buffer),
|
||||||
|
(_create_audio_buffer), (GST_START_TEST), (vorbistag_suite):
|
||||||
|
Add unit test for new vorbistag element.
|
||||||
|
|
||||||
2006-10-03 Tim-Philipp Müller <tim at centricular dot net>
|
2006-10-03 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
* ext/vorbis/vorbisparse.c: (gst_vorbis_parse_init),
|
* ext/vorbis/vorbisparse.c: (gst_vorbis_parse_init),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
plugin_LTLIBRARIES = libgstvorbis.la
|
plugin_LTLIBRARIES = libgstvorbis.la
|
||||||
|
|
||||||
libgstvorbis_la_SOURCES = vorbis.c \
|
libgstvorbis_la_SOURCES = vorbis.c \
|
||||||
vorbisdec.c vorbisenc.c vorbisparse.c
|
vorbisdec.c vorbisenc.c vorbisparse.c vorbistag.c
|
||||||
|
|
||||||
libgstvorbis_la_CFLAGS = $(GST_CFLAGS) $(VORBIS_CFLAGS)
|
libgstvorbis_la_CFLAGS = $(GST_CFLAGS) $(VORBIS_CFLAGS)
|
||||||
## AM_PATH_VORBIS also sets VORBISENC_LIBS
|
## AM_PATH_VORBIS also sets VORBISENC_LIBS
|
||||||
|
@ -12,4 +12,4 @@ libgstvorbis_la_LIBADD = \
|
||||||
$(VORBIS_LIBS) $(VORBISENC_LIBS)
|
$(VORBIS_LIBS) $(VORBISENC_LIBS)
|
||||||
libgstvorbis_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
libgstvorbis_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
|
|
||||||
noinst_HEADERS = vorbisenc.h vorbisdec.h vorbisparse.h
|
noinst_HEADERS = vorbisenc.h vorbisdec.h vorbisparse.h vorbistag.h
|
||||||
|
|
|
@ -26,10 +26,12 @@
|
||||||
#include "vorbisenc.h"
|
#include "vorbisenc.h"
|
||||||
#include "vorbisdec.h"
|
#include "vorbisdec.h"
|
||||||
#include "vorbisparse.h"
|
#include "vorbisparse.h"
|
||||||
|
#include "vorbistag.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY (vorbisenc_debug);
|
GST_DEBUG_CATEGORY (vorbisenc_debug);
|
||||||
GST_DEBUG_CATEGORY (vorbisdec_debug);
|
GST_DEBUG_CATEGORY (vorbisdec_debug);
|
||||||
GST_DEBUG_CATEGORY (vorbisparse_debug);
|
GST_DEBUG_CATEGORY (vorbisparse_debug);
|
||||||
|
GST_DEBUG_CATEGORY (vorbistag_debug);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GstPlugin * plugin)
|
plugin_init (GstPlugin * plugin)
|
||||||
|
@ -46,12 +48,18 @@ plugin_init (GstPlugin * plugin)
|
||||||
gst_vorbis_parse_get_type ()))
|
gst_vorbis_parse_get_type ()))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (!gst_element_register (plugin, "vorbistag", GST_RANK_NONE,
|
||||||
|
gst_vorbis_tag_get_type ()))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (vorbisenc_debug, "vorbisenc", 0,
|
GST_DEBUG_CATEGORY_INIT (vorbisenc_debug, "vorbisenc", 0,
|
||||||
"vorbis encoding element");
|
"vorbis encoding element");
|
||||||
GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "vorbisdec", 0,
|
GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "vorbisdec", 0,
|
||||||
"vorbis decoding element");
|
"vorbis decoding element");
|
||||||
GST_DEBUG_CATEGORY_INIT (vorbisparse_debug, "vorbisparse", 0,
|
GST_DEBUG_CATEGORY_INIT (vorbisparse_debug, "vorbisparse", 0,
|
||||||
"vorbis parsing element");
|
"vorbis parsing element");
|
||||||
|
GST_DEBUG_CATEGORY_INIT (vorbistag_debug, "vorbistag", 0,
|
||||||
|
"vorbis tagging element");
|
||||||
|
|
||||||
gst_tag_register_musicbrainz_tags ();
|
gst_tag_register_musicbrainz_tags ();
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,8 @@ static gboolean vorbis_parse_src_query (GstPad * pad, GstQuery * query);
|
||||||
static gboolean vorbis_parse_convert (GstPad * pad,
|
static gboolean vorbis_parse_convert (GstPad * pad,
|
||||||
GstFormat src_format, gint64 src_value,
|
GstFormat src_format, gint64 src_value,
|
||||||
GstFormat * dest_format, gint64 * dest_value);
|
GstFormat * dest_format, gint64 * dest_value);
|
||||||
|
static GstFlowReturn vorbis_parse_parse_packet (GstVorbisParse * parse,
|
||||||
|
GstBuffer * buf);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_vorbis_parse_base_init (gpointer g_class)
|
gst_vorbis_parse_base_init (gpointer g_class)
|
||||||
|
@ -118,6 +120,8 @@ gst_vorbis_parse_class_init (GstVorbisParseClass * klass)
|
||||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
gstelement_class->change_state = vorbis_parse_change_state;
|
gstelement_class->change_state = vorbis_parse_change_state;
|
||||||
|
|
||||||
|
klass->parse_packet = GST_DEBUG_FUNCPTR (vorbis_parse_parse_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -395,15 +399,10 @@ vorbis_parse_queue_buffer (GstVorbisParse * parse, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
vorbis_parse_chain (GstPad * pad, GstBuffer * buffer)
|
vorbis_parse_parse_packet (GstVorbisParse * parse, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstBuffer *buf;
|
|
||||||
GstVorbisParse *parse;
|
|
||||||
|
|
||||||
parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
|
|
||||||
|
|
||||||
buf = GST_BUFFER (buffer);
|
|
||||||
parse->packetno++;
|
parse->packetno++;
|
||||||
|
|
||||||
if (parse->packetno <= 3) {
|
if (parse->packetno <= 3) {
|
||||||
|
@ -421,6 +420,20 @@ vorbis_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
vorbis_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstVorbisParseClass *klass;
|
||||||
|
GstVorbisParse *parse;
|
||||||
|
|
||||||
|
parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
|
||||||
|
klass = GST_VORBIS_PARSE_CLASS (G_OBJECT_GET_CLASS (parse));
|
||||||
|
|
||||||
|
g_assert (klass->parse_packet != NULL);
|
||||||
|
|
||||||
|
return klass->parse_packet (parse, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
vorbis_parse_queue_event (GstVorbisParse * parse, GstEvent * event)
|
vorbis_parse_queue_event (GstVorbisParse * parse, GstEvent * event)
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,6 +70,9 @@ struct _GstVorbisParse {
|
||||||
|
|
||||||
struct _GstVorbisParseClass {
|
struct _GstVorbisParseClass {
|
||||||
GstElementClass parent_class;
|
GstElementClass parent_class;
|
||||||
|
|
||||||
|
/* virtual functions */
|
||||||
|
GstFlowReturn (*parse_packet) (GstVorbisParse * parse, GstBuffer * buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_vorbis_parse_get_type(void);
|
GType gst_vorbis_parse_get_type(void);
|
||||||
|
|
158
ext/vorbis/vorbistag.c
Normal file
158
ext/vorbis/vorbistag.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2006 James Livingston <doclivingston@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-vorbistag
|
||||||
|
* @see_also: #oggdemux, #oggmux, #vorbisparse, #GstTagSetter
|
||||||
|
* @short_description: retags vorbis streams
|
||||||
|
*
|
||||||
|
* <refsect2>
|
||||||
|
* <para>
|
||||||
|
* The vorbistags element can change the tag contained within a raw
|
||||||
|
* vorbis stream. Specifically, it modifies the comments header packet
|
||||||
|
* of the vorbis stream.
|
||||||
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* The element will also process the stream as the #vorbisparse element does
|
||||||
|
* so it can be used when remuxing an Ogg Vorbis stream, without additional
|
||||||
|
* elements.
|
||||||
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* Applications can set the tags to write using the #GstTagSetter interface.
|
||||||
|
* Tags contained withing the vorbis bitstream will be picked up
|
||||||
|
* automatically (and merged according to the merge mode set via the tag
|
||||||
|
* setter interface).
|
||||||
|
* </para>
|
||||||
|
* <title>Example pipelines</title>
|
||||||
|
* <para>
|
||||||
|
* This element is not useful with gst-launch, because it does not support
|
||||||
|
* setting the tags on a #GstTagSetter interface. Conceptually, the element
|
||||||
|
* will usually be used like:
|
||||||
|
* <programlisting>
|
||||||
|
* gst-launch -v filesrc location=foo.ogg ! oggdemux ! vorbistag ! oggmux ! filesink location=bar.ogg
|
||||||
|
* </programlisting>
|
||||||
|
* </para>
|
||||||
|
* </refsect2>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gst/tag/tag.h>
|
||||||
|
#include <gst/gsttagsetter.h>
|
||||||
|
|
||||||
|
#include <vorbis/codec.h>
|
||||||
|
|
||||||
|
#include "vorbistag.h"
|
||||||
|
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_EXTERN (vorbisparse_debug);
|
||||||
|
#define GST_CAT_DEFAULT vorbisparse_debug
|
||||||
|
|
||||||
|
static void gst_vorbis_tag_base_init (gpointer g_class);
|
||||||
|
static void gst_vorbis_tag_class_init (GstVorbisTagClass * klass);
|
||||||
|
static void gst_vorbis_tag_init (GstVorbisTag * tagger,
|
||||||
|
GstVorbisTagClass * g_class);
|
||||||
|
static GstFlowReturn gst_vorbis_tag_parse_packet (GstVorbisParse * parse,
|
||||||
|
GstBuffer * buffer);
|
||||||
|
|
||||||
|
#define _do_init(type) \
|
||||||
|
G_STMT_START{ \
|
||||||
|
static const GInterfaceInfo tag_setter_info = { \
|
||||||
|
NULL, \
|
||||||
|
NULL, \
|
||||||
|
NULL \
|
||||||
|
}; \
|
||||||
|
g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, \
|
||||||
|
&tag_setter_info); \
|
||||||
|
}G_STMT_END
|
||||||
|
|
||||||
|
GST_BOILERPLATE_FULL (GstVorbisTag, gst_vorbis_tag, GstVorbisParse,
|
||||||
|
GST_TYPE_VORBIS_PARSE, _do_init);
|
||||||
|
|
||||||
|
static GstElementDetails vorbis_tag_details = {
|
||||||
|
"VorbisTag",
|
||||||
|
"Formatter/Metadata",
|
||||||
|
"Retags vorbis streams",
|
||||||
|
"James Livingston <doclivingston@gmail.com>"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vorbis_tag_base_init (gpointer g_class)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||||
|
|
||||||
|
gst_element_class_set_details (element_class, &vorbis_tag_details);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vorbis_tag_class_init (GstVorbisTagClass * klass)
|
||||||
|
{
|
||||||
|
GstVorbisParseClass *vorbisparse_class = GST_VORBIS_PARSE_CLASS (klass);
|
||||||
|
|
||||||
|
vorbisparse_class->parse_packet = gst_vorbis_tag_parse_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vorbis_tag_init (GstVorbisTag * tagger, GstVorbisTagClass * g_class)
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vorbis_tag_parse_packet (GstVorbisParse * parse, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstTagList *old_tags, *new_tags;
|
||||||
|
const GstTagList *user_tags;
|
||||||
|
GstVorbisTag *tagger;
|
||||||
|
gchar *encoder = NULL;
|
||||||
|
GstBuffer *new_buf;
|
||||||
|
|
||||||
|
/* just pass everything except the comments packet */
|
||||||
|
if (GST_BUFFER_SIZE (buffer) >= 1 && GST_BUFFER_DATA (buffer)[0] != 0x03) {
|
||||||
|
return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
tagger = GST_VORBIS_TAG (parse);
|
||||||
|
|
||||||
|
old_tags =
|
||||||
|
gst_tag_list_from_vorbiscomment_buffer (buffer, (guint8 *) "\003vorbis",
|
||||||
|
7, &encoder);
|
||||||
|
user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tagger));
|
||||||
|
|
||||||
|
/* build new tag list */
|
||||||
|
new_tags = gst_tag_list_merge (user_tags, old_tags,
|
||||||
|
gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tagger)));
|
||||||
|
gst_tag_list_free (old_tags);
|
||||||
|
|
||||||
|
new_buf =
|
||||||
|
gst_tag_list_to_vorbiscomment_buffer (new_tags, (guint8 *) "\003vorbis",
|
||||||
|
7, encoder);
|
||||||
|
gst_buffer_stamp (new_buf, buffer);
|
||||||
|
|
||||||
|
gst_tag_list_free (new_tags);
|
||||||
|
g_free (encoder);
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
|
||||||
|
return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, new_buf);
|
||||||
|
}
|
63
ext/vorbis/vorbistag.h
Normal file
63
ext/vorbis/vorbistag.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* -*- c-basic-offset: 2 -*-
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) <2006> James Livingston <doclivingston@gmail.com>
|
||||||
|
*
|
||||||
|
* 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_VORBIS_TAG_H__
|
||||||
|
#define __GST_VORBIS_TAG_H__
|
||||||
|
|
||||||
|
#include "vorbisparse.h"
|
||||||
|
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#define GST_TYPE_VORBIS_TAG \
|
||||||
|
(gst_vorbis_tag_get_type())
|
||||||
|
#define GST_VORBIS_TAG(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_TAG,GstVorbisTag))
|
||||||
|
#define GST_VORBIS_TAG_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_TAG,GstVorbisTagClass))
|
||||||
|
#define GST_IS_VORBIS_TAG(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_TAG))
|
||||||
|
#define GST_IS_VORBIS_TAG_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_TAG))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GstVorbisTag GstVorbisTag;
|
||||||
|
typedef struct _GstVorbisTagClass GstVorbisTagClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstVorbisTag:
|
||||||
|
*
|
||||||
|
* Opaque data structure.
|
||||||
|
*/
|
||||||
|
struct _GstVorbisTag {
|
||||||
|
GstVorbisParse parse;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVorbisTagClass {
|
||||||
|
GstVorbisParseClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_vorbis_tag_get_type(void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_VORBIS_TAG_H__ */
|
|
@ -34,7 +34,7 @@ check_ogg =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if USE_VORBIS
|
if USE_VORBIS
|
||||||
check_vorbis = elements/vorbisdec pipelines/vorbisenc
|
check_vorbis = elements/vorbisdec pipelines/vorbisenc elements/vorbistag
|
||||||
else
|
else
|
||||||
check_vorbis =
|
check_vorbis =
|
||||||
endif
|
endif
|
||||||
|
@ -120,6 +120,14 @@ elements_volume_CFLAGS = \
|
||||||
$(GST_BASE_CFLAGS) \
|
$(GST_BASE_CFLAGS) \
|
||||||
$(AM_CFLAGS)
|
$(AM_CFLAGS)
|
||||||
|
|
||||||
|
elements_vorbistag_LDADD = \
|
||||||
|
$(VORBIS_LIBS) \
|
||||||
|
$(LDADD)
|
||||||
|
|
||||||
|
elements_vorbistag_CFLAGS = \
|
||||||
|
$(VORBIS_CFLAGS) \
|
||||||
|
$(CFLAGS) $(AM_CFLAGS)
|
||||||
|
|
||||||
libs_video_LDADD = \
|
libs_video_LDADD = \
|
||||||
$(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \
|
$(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \
|
||||||
$(LDADD)
|
$(LDADD)
|
||||||
|
|
1
tests/check/elements/.gitignore
vendored
1
tests/check/elements/.gitignore
vendored
|
@ -12,3 +12,4 @@ videotestsrc
|
||||||
volume
|
volume
|
||||||
vorbisdec
|
vorbisdec
|
||||||
ffmpegcolorspace
|
ffmpegcolorspace
|
||||||
|
vorbistag
|
||||||
|
|
405
tests/check/elements/vorbistag.c
Normal file
405
tests/check/elements/vorbistag.c
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* unit test for vorbisdec
|
||||||
|
*
|
||||||
|
* Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <vorbis/codec.h>
|
||||||
|
#include <vorbis/vorbisenc.h>
|
||||||
|
|
||||||
|
#include <gst/gsttagsetter.h>
|
||||||
|
#include <gst/check/gstcheck.h>
|
||||||
|
|
||||||
|
/* a valid first header packet */
|
||||||
|
guchar identification_header[30] = {
|
||||||
|
1, /* packet_type */
|
||||||
|
'v', 'o', 'r', 'b', 'i', 's',
|
||||||
|
0, 0, 0, 0, /* vorbis_version */
|
||||||
|
2, /* audio_channels */
|
||||||
|
0x44, 0xac, 0, 0, /* sample_rate */
|
||||||
|
0xff, 0xff, 0xff, 0xff, /* bitrate_maximum */
|
||||||
|
0x00, 0xee, 0x02, 0x00, /* bitrate_nominal */
|
||||||
|
0xff, 0xff, 0xff, 0xff, /* bitrate_minimum */
|
||||||
|
0xb8, /* blocksize_0, blocksize_1 */
|
||||||
|
0x01 /* framing_flag */
|
||||||
|
};
|
||||||
|
|
||||||
|
guchar artist_comment_header[] = {
|
||||||
|
3, /* packet_type */
|
||||||
|
'v', 'o', 'r', 'b', 'i', 's',
|
||||||
|
2, 0, 0, 0, /* vendor_length */
|
||||||
|
'm', 'e',
|
||||||
|
1, 0, 0, 0, /* user_comment_list_length */
|
||||||
|
9, 0, 0, 0, /* length comment[0] */
|
||||||
|
'A', 'R', 'T', 'I', 'S', 'T', '=', 'm', 'e',
|
||||||
|
0x01, /* framing bit */
|
||||||
|
};
|
||||||
|
|
||||||
|
guchar title_comment_header[] = {
|
||||||
|
3, /* packet_type */
|
||||||
|
'v', 'o', 'r', 'b', 'i', 's',
|
||||||
|
2, 0, 0, 0, /* vendor_length */
|
||||||
|
'm', 'e',
|
||||||
|
1, 0, 0, 0, /* user_comment_list_length */
|
||||||
|
12, 0, 0, 0, /* length comment[0] */
|
||||||
|
'T', 'I', 'T', 'L', 'E', '=', 'f', 'o', 'o', 'b', 'a', 'r',
|
||||||
|
0x01, /* framing bit */
|
||||||
|
};
|
||||||
|
|
||||||
|
guchar empty_comment_header[] = {
|
||||||
|
3, /* packet_type */
|
||||||
|
'v', 'o', 'r', 'b', 'i', 's',
|
||||||
|
2, 0, 0, 0, /* vendor_length */
|
||||||
|
'm', 'e',
|
||||||
|
0, 0, 0, 0, /* user_comment_list_length */
|
||||||
|
0x01, /* framing bit */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS_ANY);
|
||||||
|
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
|
GstPad *mysrcpad, *mysinkpad;
|
||||||
|
GAsyncQueue *pending_buffers;
|
||||||
|
static gulong id;
|
||||||
|
|
||||||
|
|
||||||
|
static GstElement *
|
||||||
|
setup_vorbistag (void)
|
||||||
|
{
|
||||||
|
GstElement *vorbistag;
|
||||||
|
|
||||||
|
GST_DEBUG ("setup_vorbistag");
|
||||||
|
vorbistag = gst_check_setup_element ("vorbistag");
|
||||||
|
mysrcpad = gst_check_setup_src_pad (vorbistag, &srctemplate, NULL);
|
||||||
|
mysinkpad = gst_check_setup_sink_pad (vorbistag, &sinktemplate, NULL);
|
||||||
|
|
||||||
|
return vorbistag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup_vorbistag (GstElement * vorbistag)
|
||||||
|
{
|
||||||
|
GST_DEBUG ("cleanup_vorbistag");
|
||||||
|
gst_element_set_state (vorbistag, GST_STATE_NULL);
|
||||||
|
|
||||||
|
gst_check_teardown_src_pad (vorbistag);
|
||||||
|
gst_check_teardown_sink_pad (vorbistag);
|
||||||
|
gst_check_teardown_element (vorbistag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused)
|
||||||
|
{
|
||||||
|
g_async_queue_push (pending_buffers, gst_buffer_ref (buffer));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_pipeline (GstElement * element)
|
||||||
|
{
|
||||||
|
id = gst_pad_add_buffer_probe (mysinkpad, G_CALLBACK (buffer_probe), NULL);
|
||||||
|
|
||||||
|
pending_buffers = g_async_queue_new ();
|
||||||
|
gst_element_set_state (element, GST_STATE_PLAYING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstBuffer *
|
||||||
|
get_buffer (void)
|
||||||
|
{
|
||||||
|
return GST_BUFFER (g_async_queue_pop (pending_buffers));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stop_pipeline (GstElement * element)
|
||||||
|
{
|
||||||
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
while ((buf = g_async_queue_try_pop (pending_buffers)))
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
gst_pad_remove_buffer_probe (mysinkpad, (guint) id);
|
||||||
|
id = 0;
|
||||||
|
|
||||||
|
gst_element_set_state (element, GST_STATE_NULL);
|
||||||
|
|
||||||
|
while ((buf = g_async_queue_try_pop (pending_buffers)))
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
g_async_queue_unref (pending_buffers);
|
||||||
|
pending_buffers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vorbis_comment vc;
|
||||||
|
vorbis_dsp_state vd;
|
||||||
|
vorbis_info vi;
|
||||||
|
vorbis_block vb;
|
||||||
|
|
||||||
|
static GstBuffer *
|
||||||
|
_create_codebook_header_buffer (void)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
ogg_packet header;
|
||||||
|
ogg_packet header_comm;
|
||||||
|
ogg_packet header_code;
|
||||||
|
|
||||||
|
vorbis_info_init (&vi);
|
||||||
|
vorbis_encode_setup_vbr (&vi, 1, 44000, 0.5);
|
||||||
|
vorbis_encode_setup_init (&vi);
|
||||||
|
vorbis_analysis_init (&vd, &vi);
|
||||||
|
vorbis_block_init (&vd, &vb);
|
||||||
|
vorbis_comment_init (&vc);
|
||||||
|
vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);
|
||||||
|
|
||||||
|
buffer = gst_buffer_new_and_alloc (header_code.bytes);
|
||||||
|
memcpy (GST_BUFFER_DATA (buffer), header_code.packet, header_code.bytes);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstBuffer *
|
||||||
|
_create_audio_buffer (void)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
ogg_packet packet;
|
||||||
|
float **vorbis_buffer;
|
||||||
|
|
||||||
|
vorbis_buffer = vorbis_analysis_buffer (&vd, 0);
|
||||||
|
vorbis_analysis_wrote (&vd, 0);
|
||||||
|
vorbis_analysis_blockout (&vd, &vb);
|
||||||
|
vorbis_analysis (&vb, NULL);
|
||||||
|
vorbis_bitrate_addblock (&vb);
|
||||||
|
vorbis_bitrate_flushpacket (&vd, &packet);
|
||||||
|
buffer = gst_buffer_new_and_alloc (packet.bytes);
|
||||||
|
memcpy (GST_BUFFER_DATA (buffer), packet.packet, packet.bytes);
|
||||||
|
|
||||||
|
vorbis_comment_clear (&vc);
|
||||||
|
vorbis_block_clear (&vb);
|
||||||
|
vorbis_dsp_clear (&vd);
|
||||||
|
vorbis_info_clear (&vi);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GST_START_TEST (test_empty_tags_set)
|
||||||
|
{
|
||||||
|
GstTagList *tags;
|
||||||
|
GstElement *vorbistag;
|
||||||
|
GstBuffer *inbuffer, *outbuffer;
|
||||||
|
|
||||||
|
vorbistag = setup_vorbistag ();
|
||||||
|
|
||||||
|
tags = gst_tag_list_new ();
|
||||||
|
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL);
|
||||||
|
gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
|
||||||
|
GST_TAG_MERGE_REPLACE);
|
||||||
|
gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
|
||||||
|
GST_TAG_MERGE_KEEP_ALL);
|
||||||
|
gst_tag_list_free (tags);
|
||||||
|
|
||||||
|
start_pipeline (vorbistag);
|
||||||
|
|
||||||
|
/* send identification header */
|
||||||
|
inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
|
||||||
|
memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
|
||||||
|
sizeof (identification_header));
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
/* send empty comment buffer */
|
||||||
|
inbuffer = gst_buffer_new_and_alloc (sizeof (empty_comment_header));
|
||||||
|
memcpy (GST_BUFFER_DATA (inbuffer), empty_comment_header,
|
||||||
|
sizeof (empty_comment_header));
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
/* send minimal codebook header and audio packers */
|
||||||
|
inbuffer = _create_codebook_header_buffer ();
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
inbuffer = _create_audio_buffer ();
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
|
||||||
|
/* check identification header is unchanged */
|
||||||
|
outbuffer = get_buffer ();
|
||||||
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
||||||
|
sizeof (identification_header));
|
||||||
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
||||||
|
identification_header, sizeof (identification_header)), 0);
|
||||||
|
gst_buffer_unref (outbuffer);
|
||||||
|
|
||||||
|
/* check comment header is correct */
|
||||||
|
outbuffer = get_buffer ();
|
||||||
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
||||||
|
sizeof (title_comment_header));
|
||||||
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
||||||
|
title_comment_header, sizeof (title_comment_header)), 0);
|
||||||
|
gst_buffer_unref (outbuffer);
|
||||||
|
|
||||||
|
stop_pipeline (vorbistag);
|
||||||
|
cleanup_vorbistag (vorbistag);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
|
GST_START_TEST (test_filled_tags_unset)
|
||||||
|
{
|
||||||
|
GstTagList *tags;
|
||||||
|
GstElement *vorbistag;
|
||||||
|
GstBuffer *inbuffer, *outbuffer;
|
||||||
|
|
||||||
|
vorbistag = setup_vorbistag ();
|
||||||
|
|
||||||
|
tags = gst_tag_list_new ();
|
||||||
|
gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
|
||||||
|
GST_TAG_MERGE_REPLACE);
|
||||||
|
gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
|
||||||
|
GST_TAG_MERGE_KEEP_ALL);
|
||||||
|
gst_tag_list_free (tags);
|
||||||
|
|
||||||
|
start_pipeline (vorbistag);
|
||||||
|
|
||||||
|
/* send identification header */
|
||||||
|
inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
|
||||||
|
memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
|
||||||
|
sizeof (identification_header));
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
/* send empty comment buffer */
|
||||||
|
inbuffer = gst_buffer_new_and_alloc (sizeof (title_comment_header));
|
||||||
|
memcpy (GST_BUFFER_DATA (inbuffer), title_comment_header,
|
||||||
|
sizeof (title_comment_header));
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
/* send minimal codebook header and audio packers */
|
||||||
|
inbuffer = _create_codebook_header_buffer ();
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
inbuffer = _create_audio_buffer ();
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
|
||||||
|
/* check identification header is unchanged */
|
||||||
|
outbuffer = get_buffer ();
|
||||||
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
||||||
|
sizeof (identification_header));
|
||||||
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
||||||
|
identification_header, sizeof (identification_header)), 0);
|
||||||
|
gst_buffer_unref (outbuffer);
|
||||||
|
|
||||||
|
/* check comment header is correct */
|
||||||
|
outbuffer = get_buffer ();
|
||||||
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
||||||
|
sizeof (empty_comment_header));
|
||||||
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
||||||
|
empty_comment_header, sizeof (empty_comment_header)), 0);
|
||||||
|
gst_buffer_unref (outbuffer);
|
||||||
|
|
||||||
|
stop_pipeline (vorbistag);
|
||||||
|
cleanup_vorbistag (vorbistag);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
|
GST_START_TEST (test_filled_tags_change)
|
||||||
|
{
|
||||||
|
GstTagList *tags;
|
||||||
|
GstElement *vorbistag;
|
||||||
|
GstBuffer *inbuffer, *outbuffer;
|
||||||
|
|
||||||
|
vorbistag = setup_vorbistag ();
|
||||||
|
|
||||||
|
tags = gst_tag_list_new ();
|
||||||
|
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL);
|
||||||
|
gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
|
||||||
|
GST_TAG_MERGE_REPLACE);
|
||||||
|
gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
|
||||||
|
GST_TAG_MERGE_KEEP_ALL);
|
||||||
|
gst_tag_list_free (tags);
|
||||||
|
|
||||||
|
start_pipeline (vorbistag);
|
||||||
|
|
||||||
|
/* send identification header */
|
||||||
|
inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
|
||||||
|
memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
|
||||||
|
sizeof (identification_header));
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
/* send empty comment buffer */
|
||||||
|
inbuffer = gst_buffer_new_and_alloc (sizeof (artist_comment_header));
|
||||||
|
memcpy (GST_BUFFER_DATA (inbuffer), artist_comment_header,
|
||||||
|
sizeof (artist_comment_header));
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
/* send minimal codebook header and audio packers */
|
||||||
|
inbuffer = _create_codebook_header_buffer ();
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
inbuffer = _create_audio_buffer ();
|
||||||
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||||
|
|
||||||
|
|
||||||
|
/* check identification header is unchanged */
|
||||||
|
outbuffer = get_buffer ();
|
||||||
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
||||||
|
sizeof (identification_header));
|
||||||
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
||||||
|
identification_header, sizeof (identification_header)), 0);
|
||||||
|
gst_buffer_unref (outbuffer);
|
||||||
|
|
||||||
|
/* check comment header is correct */
|
||||||
|
outbuffer = get_buffer ();
|
||||||
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
||||||
|
sizeof (title_comment_header));
|
||||||
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
||||||
|
title_comment_header, sizeof (title_comment_header)), 0);
|
||||||
|
gst_buffer_unref (outbuffer);
|
||||||
|
|
||||||
|
stop_pipeline (vorbistag);
|
||||||
|
cleanup_vorbistag (vorbistag);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Suite *
|
||||||
|
vorbistag_suite (void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create ("vorbistag");
|
||||||
|
TCase *tc_chain = tcase_create ("general");
|
||||||
|
|
||||||
|
suite_add_tcase (s, tc_chain);
|
||||||
|
tcase_add_test (tc_chain, test_empty_tags_set);
|
||||||
|
tcase_add_test (tc_chain, test_filled_tags_unset);
|
||||||
|
tcase_add_test (tc_chain, test_filled_tags_change);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_CHECK_MAIN (vorbistag)
|
Loading…
Reference in a new issue