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