<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML ><HEAD ><TITLE >Tagging (Metadata and Streaminfo)</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK REL="HOME" TITLE="GStreamer Plugin Writer's Guide" HREF="index.html"><LINK REL="UP" TITLE="Advanced Filter Concepts" HREF="part-advanced.html"><LINK REL="PREVIOUS" TITLE="Navigation Interface" HREF="section-iface-navigation.html"><LINK REL="NEXT" TITLE="Writing Tags to Streams" HREF="section-tagging-write.html"></HEAD ><BODY CLASS="chapter" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" ><SPAN CLASS="application" >GStreamer</SPAN > Plugin Writer's Guide</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="section-iface-navigation.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="section-tagging-write.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="chapter" ><H1 ><A NAME="chapter-advanced-tagging" ></A >Chapter 19. Tagging (Metadata and Streaminfo)</H1 ><P > Tags are pieces of information stored in a stream that are not the content itself, butthey rather <SPAN CLASS="emphasis" ><I CLASS="emphasis" >describe</I ></SPAN > the content. Most media container formats support tagging in one way or another. Ogg uses VorbisComment for this, MP3 uses ID3, AVI and WAV use RIFF's INFO list chunk, etc. GStreamer provides a general way for elements to read tags from the stream and expose this to the user. The tags (at least the metadata) will be part of the stream inside the pipeline. The consequence of this is that transcoding of files from one format to another will automatically preserve tags, as long as the input and output format elements both support tagging. </P ><P > Tags are separated in two categories in GStreamer, even though applications won't notice anything of this. The first are called <SPAN CLASS="emphasis" ><I CLASS="emphasis" >metadata</I ></SPAN >, the second are called <SPAN CLASS="emphasis" ><I CLASS="emphasis" >streaminfo</I ></SPAN >. Metadata are tags that describe the non-technical parts of stream content. They can be changed without needing to re-encode the stream completely. Examples are <SPAN CLASS="QUOTE" >"author"</SPAN >, <SPAN CLASS="QUOTE" >"title"</SPAN > or <SPAN CLASS="QUOTE" >"album"</SPAN >. The container format might still need to be re-written for the tags to fit in, though. Streaminfo, on the other hand, are tags that describe the stream contents technically. To change them, the stream needs to be re-encoded. Examples are <SPAN CLASS="QUOTE" >"codec"</SPAN > or <SPAN CLASS="QUOTE" >"bitrate"</SPAN >. Note that some container formats (like ID3) store various streaminfo tags as metadata in the file container, which means that they can be changed so that they don't match the content in the file anymore. Still, they are called metadata because <SPAN CLASS="emphasis" ><I CLASS="emphasis" >technically</I ></SPAN >, they can be changed without re-encoding the whole stream, even though that makes them invalid. Files with such metadata tags will have the same tag twice: once as metadata, once as streaminfo. </P ><P > A tag reading element is called <CODE CLASS="classname" >TagGetter</CODE > in <SPAN CLASS="application" >GStreamer</SPAN >. A tag writer is called <CODE CLASS="classname" >TagSetter</CODE >. An element supporting both can be used in a tag editor for quick tag changing. </P ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="section-tagging-read" >19.1. Reading Tags from Streams</A ></H1 ><P > The basic object for tags is a <CODE CLASS="classname" >GstTagList</CODE >. 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 <CODE CLASS="function" >gst_tag_list_new ()</CODE >. Then, the element can fill the list using <CODE CLASS="function" >gst_tag_list_add_values ()</CODE >. Note that an element probably reads metadata as strings, but values might not necessarily be strings. Be sure to use <CODE CLASS="function" >gst_value_transform ()</CODE > 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 <CODE CLASS="function" >gst_element_found_tags ()</CODE >. The tags should also be part of the datastream, so they should be pushed over all source pads. The function <CODE CLASS="function" >gst_event_new_tag ()</CODE > creates an event from a taglist. This can be pushed over source pads using <CODE CLASS="function" >gst_pad_push ()</CODE >. Simple elements with only one source pad can combine all these steps all-in-one by using the function <CODE CLASS="function" >gst_element_found_tags_for_pad ()</CODE >. </P ><P > 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 <SPAN CLASS="QUOTE" >"name:value"</SPAN >, where name is the type of metadata (title, author, ...) and value is the metadata value. The <CODE CLASS="function" >_getline ()</CODE > is the same as the one given in <A HREF="chapter-advanced-request.html#section-reqpad-sometimes" >Sometimes pads</A >. </P ><PRE CLASS="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); } </PRE ><P > We currently assume the core to already <SPAN CLASS="emphasis" ><I CLASS="emphasis" >know</I ></SPAN > the mimetype (<CODE CLASS="function" >gst_tag_exists ()</CODE >). You can add new tags to the list of known tags using <CODE CLASS="function" >gst_tag_register ()</CODE >. 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 <TT CLASS="filename" >gsttag.c</TT > 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 <CODE CLASS="function" >_class_init ()</CODE >. </P ><PRE CLASS="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); [..] } </PRE ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="section-iface-navigation.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="section-tagging-write.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Navigation Interface</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="part-advanced.html" ACCESSKEY="U" >Up</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Writing Tags to Streams</TD ></TR ></TABLE ></DIV ></BODY ></HTML >