Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > f0a9f2b9c81d34eadc43f527947c0b70 > files > 194

libgstreamer0.7-devel-0.7.4-2mdk.i586.rpm

<!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
>&#13;    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
>&#13;    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
>&#13;    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
>&#13;      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
>&#13;      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"
>&#13;
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 = &#38;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 (&#38;from, G_TYPE_STRING);
      g_value_set_string (&#38;from, colon_pos);
      g_value_init (&#38;to, to_type);
      g_value_transform (&#38;from, &#38;to);
      g_value_unset (&#38;from);
      gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
			       type, &#38;to, NULL);
      g_value_unset (&#38;to);
    }

next:
    g_free (type);
    gst_buffer_unref (buf);
  }

  /* signal metadata */
  gst_element_found_tags_for_pad (element, filter-&#62;srcpad, 0, taglist);
  gst_tag_list_free (taglist);

  /* send EOS */
  gst_pad_send_event (filter-&#62;srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
  gst_element_set_eos (element);
}

    </PRE
><P
>&#13;      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"
>&#13;
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
>