mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
docs/pwg/advanced-tagging.xml: Add a part about tag reading and application signalling... Tag writing still needs to ...
Original commit message from CVS: 2004-01-29 Ronald Bultje <rbultje@ronald.bitfreak.net> * docs/pwg/advanced-tagging.xml: Add a part about tag reading and application signalling... Tag writing still needs to be documented. * gst/elements/gstfilesrc.c: (gst_filesrc_set_location): We can set file locations in READY, too.
This commit is contained in:
parent
7e586c017f
commit
7d41ae65f4
4 changed files with 114 additions and 3 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2004-01-29 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
|
* docs/pwg/advanced-tagging.xml:
|
||||||
|
Add a part about tag reading and application signalling... Tag
|
||||||
|
writing still needs to be documented.
|
||||||
|
* gst/elements/gstfilesrc.c: (gst_filesrc_set_location):
|
||||||
|
We can set file locations in READY, too.
|
||||||
|
|
||||||
2004-01-29 Julien MOUTTE <julien@moutte.net>
|
2004-01-29 Julien MOUTTE <julien@moutte.net>
|
||||||
|
|
||||||
* docs/random/ds/element-checklist: Adding some notes about src
|
* docs/random/ds/element-checklist: Adding some notes about src
|
||||||
|
|
|
@ -40,8 +40,109 @@
|
||||||
<sect1 id="section-tagging-read" xreflabel="Reading Tags from Streams">
|
<sect1 id="section-tagging-read" xreflabel="Reading Tags from Streams">
|
||||||
<title>Reading Tags from Streams</title>
|
<title>Reading Tags from Streams</title>
|
||||||
<para>
|
<para>
|
||||||
WRITEME
|
The basic object for tags is a <classname>GstTagList</classname>. An
|
||||||
|
element that is reading tags from a stream should create an empty taglist
|
||||||
|
and fill this with individual tags. Empty tag lists can be created with
|
||||||
|
<function>gst_tag_list_new ()</function>. Then, the element can fill the
|
||||||
|
list using <function>gst_tag_list_add_values ()</function>. Note that
|
||||||
|
an element probably reads metadata as strings, but values might not
|
||||||
|
necessarily be strings. Be sure to use <function>gst_value_transform ()</function>
|
||||||
|
to make sure that your data is of the right type. After data reading, the
|
||||||
|
application can be notified of the new taglist by calling
|
||||||
|
<function>gst_element_found_tags ()</function>. The tags should also be
|
||||||
|
part of the datastream, so they should be pushed over all source pads.
|
||||||
|
The function <function>gst_event_new_tag ()</function> creates an event
|
||||||
|
from a taglist. This can be pushed over source pads using
|
||||||
|
<function>gst_pad_push ()</function>. Simple elements with only one
|
||||||
|
source pad can combine all these steps all-in-one by using the function
|
||||||
|
<function>gst_element_found_tags_for_pad ()</function>.
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
The following example program will parse a file and parse the data as
|
||||||
|
metadata/tags rathen than as actual content-data. It will parse each
|
||||||
|
line as <quote>name:value</quote>, where name is the type of metadata
|
||||||
|
(title, author, ...) and value is the metadata value. The
|
||||||
|
<function>_getline ()</function> is the same as the one given in
|
||||||
|
<xref linkend="section-reqpad-sometimes"/>.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
static void
|
||||||
|
gst_my_filter_loopfunc (GstElement *element)
|
||||||
|
{
|
||||||
|
GstMyFilter *filter = GST_MY_FILTER (element);
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstTagList *taglist = gst_tag_list_new ();
|
||||||
|
|
||||||
|
/* get each line and parse as metadata */
|
||||||
|
while ((buf = gst_my_filter_getline (filter))) {
|
||||||
|
gchar *line = GST_BUFFER_DATA (buf), *colon_pos, *type = NULL;a
|
||||||
|
|
||||||
|
/* get the position of the ':' and go beyond it */
|
||||||
|
if (!(colon_pos = strchr (line, ';')))
|
||||||
|
goto next:
|
||||||
|
|
||||||
|
/* get the string before that as type of metadata */
|
||||||
|
type = g_strndup (line, colon_pos - line);
|
||||||
|
|
||||||
|
/* content is one character beyond the ':' */
|
||||||
|
colon_pos = &colon_pos[1];
|
||||||
|
if (*colon_pos == '\0')
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
/* get the metadata category, it's value type, store it in that
|
||||||
|
* type and add it to the taglist. */
|
||||||
|
if (gst_tag_exists (type)) {
|
||||||
|
GValue from = { 0 }, to = { 0 };
|
||||||
|
GType to_type;
|
||||||
|
|
||||||
|
to_type = gst_tag_get_type (type);
|
||||||
|
g_value_init (&from, G_TYPE_STRING);
|
||||||
|
g_value_set_string (&from, colon_pos);
|
||||||
|
g_value_init (&to, to_type);
|
||||||
|
g_value_transform (&from, &to);
|
||||||
|
g_value_unset (&from);
|
||||||
|
gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
|
||||||
|
type, &to, NULL);
|
||||||
|
g_value_unset (&to);
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
g_free (type);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* signal metadata */
|
||||||
|
gst_element_found_tags_for_pad (element, filter->srcpad, 0, taglist);
|
||||||
|
gst_tag_list_free (taglist);
|
||||||
|
|
||||||
|
/* send EOS */
|
||||||
|
gst_pad_send_event (filter->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
|
||||||
|
gst_element_set_eos (element);
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
We currently assume the core to already <emphasis>know</emphasis> the
|
||||||
|
mimetype (<function>gst_tag_exists ()</function>). You can add new tags
|
||||||
|
to the list of known tags using <function>gst_tag_register ()</function>.
|
||||||
|
If you think the tag will be useful in more cases than just your own
|
||||||
|
element, it might be a good idea to add it to <filename>gsttag.c</filename>
|
||||||
|
instead. That's up to you to decide. If you want to do it in your own
|
||||||
|
element, it's easiest to register the tag in one of your class init
|
||||||
|
functions, preferrably <function>_class_init ()</function>.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
static void
|
||||||
|
gst_my_filter_class_init (GstMyFilterClass *klass)
|
||||||
|
{
|
||||||
|
[..]
|
||||||
|
gst_tag_register ("my_tag_name", GST_TAG_FLAG_META,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
_("my own tag"),
|
||||||
|
_("a tag that is specific to my own element"),
|
||||||
|
NULL);
|
||||||
|
[..]
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="section-tagging-write" xreflabel="Writing Tags to Streams">
|
<sect1 id="section-tagging-write" xreflabel="Writing Tags to Streams">
|
||||||
|
|
|
@ -257,7 +257,8 @@ static gboolean
|
||||||
gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
|
gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
|
||||||
{
|
{
|
||||||
/* the element must be stopped in order to do this */
|
/* the element must be stopped in order to do this */
|
||||||
if (GST_STATE (src) != GST_STATE_NULL)
|
if (GST_STATE (src) != GST_STATE_READY &&
|
||||||
|
GST_STATE (src) != GST_STATE_NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (src->filename) g_free (src->filename);
|
if (src->filename) g_free (src->filename);
|
||||||
|
|
|
@ -257,7 +257,8 @@ static gboolean
|
||||||
gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
|
gst_filesrc_set_location (GstFileSrc *src, const gchar *location)
|
||||||
{
|
{
|
||||||
/* the element must be stopped in order to do this */
|
/* the element must be stopped in order to do this */
|
||||||
if (GST_STATE (src) != GST_STATE_NULL)
|
if (GST_STATE (src) != GST_STATE_READY &&
|
||||||
|
GST_STATE (src) != GST_STATE_NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (src->filename) g_free (src->filename);
|
if (src->filename) g_free (src->filename);
|
||||||
|
|
Loading…
Reference in a new issue