Git init
[framework/multimedia/gstreamer0.10.git] / docs / manual / advanced-metadata.xml
1 <chapter id="chapter-metadata">
2   <title>Metadata</title>
3
4   <para>
5     &GStreamer; makes a clear distinction between two types of metadata, and
6     has support for both types. The first is stream tags, which describe the
7     content of a stream in a non-technical way. Examples include the author
8     of a song, the title of that very same song or the album it is a part of.
9     The other type of metadata is stream-info, which is a somewhat technical
10     description of the properties of a stream. This can include video size,
11     audio samplerate, codecs used and so on. Tags are handled using the
12     &GStreamer; tagging system. Stream-info can be retrieved from a
13     <classname>GstPad</classname>.
14   </para>
15
16   <sect1 id="section-tags-read">
17     <title>Metadata reading</title>
18
19     <para>
20       Stream information can most easily be read by reading it from a
21       <classname>GstPad</classname>. This has already been discussed before
22       in <xref linkend="section-caps-metadata"/>. Therefore, we will skip
23       it here. Note that this requires access to all pads of which you
24       want stream information.
25     </para>
26
27     <para>
28       Tag reading is done through a bus in &GStreamer;, which has been
29       discussed previously in <xref linkend="chapter-bus"/>. You can
30       listen for <classname>GST_MESSAGE_TAG</classname> messages and handle
31       them as you wish.
32     </para>
33     <para>
34       Note, however, that the <classname>GST_MESSAGE_TAG</classname>
35       message may be fired multiple times in the pipeline. It is the
36       application's responsibility to put all those tags together and
37       display them to the user in a nice, coherent way. Usually, using
38       <function>gst_tag_list_merge ()</function> is a good enough way
39       of doing this; make sure to empty the cache when loading a new song,
40       or after every few minutes when listening to internet radio. Also,
41       make sure you use <classname>GST_TAG_MERGE_PREPEND</classname> as
42       merging mode, so that a new title (which came in later) has a
43       preference over the old one for display.
44     </para>
45     <para>
46       The following example will extract tags from a file and print them:
47     </para>
48     <programlisting>
49 /* compile with:
50  * gcc -o tags tags.c `pkg-config --cflags --libs gstreamer-0.10` */
51 #include &lt;gst/gst.h&gt;
52
53 static void
54 print_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data)
55 {
56   int i, num;
57
58   num = gst_tag_list_get_tag_size (list, tag);
59   for (i = 0; i &lt; num; ++i) {
60     const GValue *val;
61
62     /* Note: when looking for specific tags, use the g_tag_list_get_xyz() API,
63      * we only use the GValue approach here because it is more generic */
64     val = gst_tag_list_get_value_index (list, tag, i);
65     if (G_VALUE_HOLDS_STRING (val)) {
66       g_print ("\t%20s : %s\n", tag, g_value_get_string (val));
67     } else if (G_VALUE_HOLDS_UINT (val)) {
68       g_print ("\t%20s : %u\n", tag, g_value_get_uint (val));
69     } else if (G_VALUE_HOLDS_DOUBLE (val)) {
70       g_print ("\t%20s : %g\n", tag, g_value_get_double (val));
71     } else if (G_VALUE_HOLDS_BOOLEAN (val)) {
72       g_print ("\t%20s : %s\n", tag,
73           (g_value_get_boolean (val)) ? "true" : "false");
74     } else if (GST_VALUE_HOLDS_BUFFER (val)) {
75       g_print ("\t%20s : buffer of size %u\n", tag,
76           GST_BUFFER_SIZE (gst_value_get_buffer (val)));
77     } else if (GST_VALUE_HOLDS_DATE (val)) {
78       g_print ("\t%20s : date (year=%u,...)\n", tag,
79           g_date_get_year (gst_value_get_date (val)));
80     } else {
81       g_print ("\t%20s : tag of type '%s'\n", tag, G_VALUE_TYPE_NAME (val));
82     }
83   }
84 }
85
86 static void
87 on_new_pad (GstElement * dec, GstPad * pad, GstElement * fakesink)
88 {
89   GstPad *sinkpad;
90
91   sinkpad = gst_element_get_static_pad (fakesink, "sink");
92   if (!gst_pad_is_linked (sinkpad)) {
93     if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)
94       g_error ("Failed to link pads!");
95   }
96   gst_object_unref (sinkpad);
97 }
98
99 int
100 main (int argc, char ** argv)
101 {
102   GstElement *pipe, *dec, *sink;
103   GstMessage *msg;
104
105   gst_init (&amp;argc, &amp;argv);
106
107   if (argc &lt; 2 || !gst_uri_is_valid (argv[1]))
108     g_error ("Usage: %s file:///path/to/file", argv[0]);
109
110   pipe = gst_pipeline_new ("pipeline");
111
112   dec = gst_element_factory_make ("uridecodebin", NULL);
113   g_object_set (dec, "uri", argv[1], NULL);
114   gst_bin_add (GST_BIN (pipe), dec);
115
116   sink = gst_element_factory_make ("fakesink", NULL);
117   gst_bin_add (GST_BIN (pipe), sink);
118
119   g_signal_connect (dec, "pad-added", G_CALLBACK (on_new_pad), sink);
120
121   gst_element_set_state (pipe, GST_STATE_PAUSED);
122
123   while (TRUE) {
124     GstTagList *tags = NULL;
125
126     msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe),
127         GST_CLOCK_TIME_NONE,
128         GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_TAG | GST_MESSAGE_ERROR);
129
130     if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_TAG) /* error or async_done */
131       break;
132
133     gst_message_parse_tag (msg, &amp;tags);
134
135     g_print ("Got tags from element %s:\n", GST_OBJECT_NAME (msg-&gt;src));
136     gst_tag_list_foreach (tags, print_one_tag, NULL);
137     g_print ("\n");
138     gst_tag_list_free (tags);
139
140     gst_message_unref (msg);
141   };
142
143   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR)
144     g_error ("Got error");
145
146   gst_message_unref (msg);
147   gst_element_set_state (pipe, GST_STATE_NULL);
148   gst_object_unref (pipe);
149   return 0;
150 }
151     </programlisting>
152   </sect1>
153
154   <sect1 id="section-tags-write">
155     <title>Tag writing</title>
156
157     <para>
158       Tag writing is done using the <ulink type="http"
159         url="&URLAPI;GstTagSetter.html"><classname>GstTagSetter</classname></ulink>
160       interface. All that's required is a tag-set-supporting element in
161       your pipeline. In order to see if any of the elements in your
162       pipeline supports tag writing, you can use the function
163       <function>gst_bin_iterate_all_by_interface (pipeline,
164       GST_TYPE_TAG_SETTER)</function>. On the resulting element, usually
165       an encoder or muxer, you can use <function>gst_tag_setter_merge
166       ()</function> (with a taglist) or <function>gst_tag_setter_add
167       ()</function> (with individual tags) to set tags on it.
168     </para>
169     <para>
170       A nice extra feature in &GStreamer; tag support is that tags are
171       preserved in pipelines. This means that if you transcode one file
172       containing tags into another media type, and that new media type
173       supports tags too, then the tags will be handled as part of the
174       data stream and be merged into the newly written media file, too.
175     </para>
176   </sect1>
177 </chapter>