1 From ce8841a1b178ca7e9cd139d4e687a36650392cd6 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= <tim.muller@collabora.co.uk>
3 Date: Fri, 22 May 2009 19:38:01 +0100
4 Subject: [PATCH] tag: add new GstTagReader interface to allow fine-tuning of
7 API: gst_tag_reader_get_type
8 API: gst_tag_reader_add_interface_to_type
9 API: gst_tag_reader_set_tag_reading_mode
10 API: gst_tag_reader_get_tag_reading_mode
11 API: gst_tag_reading_mode_get_type
13 The GstTagReader interface may be implemented by elements that
14 extract metadata to allow the fine-tuning of the tag-reading
15 process (see #564749).
17 docs/libs/gst-plugins-base-libs-docs.sgml | 1 +
18 docs/libs/gst-plugins-base-libs-sections.txt | 17 ++
19 gst-libs/gst/tag/Makefile.am | 5 +-
20 gst-libs/gst/tag/gsttagreader.c | 286 ++++++++++++++++++++++++++
21 gst-libs/gst/tag/gsttagreader.h | 110 ++++++++++
22 5 files changed, 417 insertions(+), 2 deletions(-)
23 create mode 100644 gst-libs/gst/tag/gsttagreader.c
24 create mode 100644 gst-libs/gst/tag/gsttagreader.h
26 diff --git a/docs/libs/gst-plugins-base-libs-docs.sgml b/docs/libs/gst-plugins-base-libs-docs.sgml
27 index b7b61a7..453fb9a 100644
28 --- a/docs/libs/gst-plugins-base-libs-docs.sgml
29 +++ b/docs/libs/gst-plugins-base-libs-docs.sgml
31 <xi:include href="xml/gsttagxmp.xml" />
32 <xi:include href="xml/gsttagdemux.xml" />
33 <xi:include href="xml/gsttaglanguagecodes.xml" />
34 + <xi:include href="xml/gsttagreader.xml" />
37 <chapter id="gstreamer-base-utils">
38 diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt
39 index 41235a0..b667b45 100644
40 --- a/docs/libs/gst-plugins-base-libs-sections.txt
41 +++ b/docs/libs/gst-plugins-base-libs-sections.txt
42 @@ -1822,6 +1822,23 @@ gst_tag_get_language_code_iso_639_2B
43 gst_tag_get_language_code_iso_639_2T
47 +<FILE>gsttagreader</FILE>
48 +<INCLUDE>gst/tag/gsttagreader.h</INCLUDE>
51 +gst_tag_reader_add_interface_to_type
52 +gst_tag_reader_set_tag_reading_mode
53 +gst_tag_reader_get_tag_reading_mode
54 +<SUBSECTION Standard>
55 +gst_tag_reading_mode_get_type
59 +GST_TAG_READER_GET_IFACE
60 +GstTagReaderInterface
66 diff --git a/gst-libs/gst/tag/Makefile.am b/gst-libs/gst/tag/Makefile.am
67 index 9977d66..d12c7b7 100644
68 --- a/gst-libs/gst/tag/Makefile.am
69 +++ b/gst-libs/gst/tag/Makefile.am
70 @@ -2,13 +2,14 @@ libgsttagincludedir = \
71 $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/tag
73 libgsttaginclude_HEADERS = \
74 - tag.h gsttagdemux.h xmpwriter.h
75 + tag.h gsttagdemux.h xmpwriter.h gsttagreader.h
77 lib_LTLIBRARIES = libgsttag-@GST_MAJORMINOR@.la
79 libgsttag_@GST_MAJORMINOR@_la_SOURCES = \
80 gstvorbistag.c gstid3tag.c gstxmptag.c gstexiftag.c \
81 - lang.c tags.c gsttagdemux.c gsttageditingprivate.c xmpwriter.c
82 + lang.c tags.c gsttagdemux.c gsttageditingprivate.c xmpwriter.c \
84 libgsttag_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
85 libgsttag_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM)
86 libgsttag_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
87 diff --git a/gst-libs/gst/tag/gsttagreader.c b/gst-libs/gst/tag/gsttagreader.c
89 index 0000000..cfbd480
91 +++ b/gst-libs/gst/tag/gsttagreader.c
93 +/* GStreamer Tag Reader interface
94 + * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
95 + * Copyright (C) 2008 Nokia Corporation.
97 + * Contact: Stefan Kost <stefan.kost@nokia.com>
99 + * tagreader.c: Tag Reader interface design
101 + * This library is free software; you can redistribute it and/or
102 + * modify it under the terms of the GNU Library General Public
103 + * License as published by the Free Software Foundation; either
104 + * version 2 of the License, or (at your option) any later version.
106 + * This library is distributed in the hope that it will be useful,
107 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
108 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
109 + * Library General Public License for more details.
111 + * You should have received a copy of the GNU Library General Public
112 + * License along with this library; if not, write to the
113 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
114 + * Boston, MA 02111-1307, USA.
118 + * SECTION:gsttagreader
119 + * @short_description: Interface for setting a tag reading mode on elements
124 + * The #GstTagReader interface may be implemented by elements that extract
125 + * metadata to allow the fine-tuning of the tag-reading process. The interface
126 + * is not required by all elements that extract tags - it is perfectly
127 + * acceptable to post tag messages on the bus and not implement this
128 + * interface. The interface merely serves to indicate that an element supports
129 + * one or more special tag reading modes which when set might result in
130 + * more efficient tag processing in certain cases.
134 + * <title>Use cases</title>
136 + * There are currently two main use cases for this interface:
139 + * by-passing possibly time- or memory-consuming tag extraction: useful
140 + * for example if the goal is to just play a file, but things like embedded
141 + * coverart or tags are not of interest.
144 + * optimised tag and stream info extraction: useful if all that's of interest
145 + * is tags and other metadata and full-scale playback functionality is not
146 + * required; this allows demuxers to bypass possibly expensive index processing
147 + * or index building, for example.
153 + * <title>How to use #GstTagReader in applications</title>
155 + * Application writers who want to avoid the (usually very small) overhead of
156 + * tag extraction when playing back media can put uridecodebin or decodebin2
157 + * (or the elements in their pipeline directly, if they implement the
158 + * interface) into tag reading mode #GST_TAG_READING_MODE_SKIP_TAGS using
159 + * gst_tag_reader_set_tag_reading_mode() before starting the pipeline.
162 + * Application writers who want to extract tags and other metadata as fast and
163 + * efficiently as possible should use the 'tagreadbin' element, which will
164 + * handle everything for them, and which will then use the #GstTagReader
165 + * interface internally.
169 + * <title>How to implement the #GstTagReader in elements</title>
171 + * #GstTagReader is a 'dummy interface' similar to #GstTagSetter, meaning that
172 + * there are no interface methods to implement. All that needs to be done is
173 + * to add the interface to an element's GType in the element's _get_type()
174 + * function or GST_BOILERPLATE_FULL macro. This can be done using the
175 + * convenience function gst_tag_reader_add_interface_to_type().
178 + * Elements implementing the interface should then query the configured tag
179 + * reading mode when starting up (ie. in the start function or in the
180 + * state change function in the NULL to READY transition), using
181 + * gst_tag_reader_get_tag_reading_mode().
184 + * In #GST_TAG_READING_MODE_SKIP_TAGS mode elements should skip metadata
185 + * processing wherever this is possible without affecting functionality
186 + * otherwise. Element should not post TAG messages on the bus in this mode.
189 + * In #GST_TAG_READING_MODE_DEFAULT mode elements should behave like they
190 + * normally would. For most elements this means tag extraction and normal
194 + * In #GST_TAG_READING_MODE_TAGS_ONLY mode elements are requested to skip
195 + * any non-essential data processing. Demuxers, for example, may choose not
196 + * to parse a seek index or build a seek table, but should still parse
197 + * file headers and add pads and push newsegment events and data as they
198 + * usually would (however, they are not required to reproduce output in the
199 + * way they would for normal playback, e.g. they may push only key frames,
200 + * which is all that is required for thumbnailing purposes).
203 + * Elements in #GST_TAG_READING_MODE_TAGS_ONLY are required to properly
204 + * aggregate or pass upstream flow returns. If they are driving the pipeline
205 + * they will also need to EOS on #GST_FLOW_UNEXPECTED flow returns from
206 + * downstream. This is how the <literal>tagreadbin</literal> element will
207 + * stop streaming once it has collected all information.
211 + * <title>Tag-handling guidelines for all demuxers and parsers</title>
213 + * Below some general guidelines on how demuxers, parsers and decoders should
217 + * Demuxers should push tag events for 'global' tag before pushing tags
218 + * with per-stream information. This global tag list should contain a
219 + * #GST_TAG_CONTAINER_FORMAT tag. They also should push global tags and
220 + * per-stream tags separately.
223 + * Parsers and decoders should ensure that they cache tag events received from
224 + * upstream and push them on their source pad before any tags of their own
225 + * are pushed, maintaining the order of the tag events as they came in.
233 +#ifdef HAVE_CONFIG_H
237 +#include "gsttagreader.h"
239 +/* key for g_object_{set|get}_qdata() */
240 +static GQuark tag_reading_mode_quark = 0;
242 +#define GST_TAG_READER_GET_MODE(obj) \
243 + GPOINTER_TO_INT (g_object_get_qdata (obj, tag_reading_mode_quark))
244 +#define GST_TAG_READER_SET_MODE(obj,mode) \
245 + g_object_set_qdata (obj, tag_reading_mode_quark, GINT_TO_POINTER (mode))
248 +gst_tag_reader_get_type (void)
250 + static GType gst_tag_reader_type = 0;
252 + if (!gst_tag_reader_type) {
253 + static const GTypeInfo gst_tag_reader_info = {
254 + sizeof (GstTagReaderInterface),
255 + (GBaseInitFunc) NULL,
265 + gst_tag_reader_type = g_type_register_static (G_TYPE_INTERFACE,
266 + "GstTagReader", &gst_tag_reader_info, 0);
268 + tag_reading_mode_quark = g_quark_from_static_string ("GstTagReadingMode");
271 + return gst_tag_reader_type;
275 + * gst_tag_reader_add_interface_to_type:
276 + * @type: a newly-registered GType
278 + * Convenience function to add the #GstTagReader interface to an element.
279 + * Use from within the element's _get_type() function or in connection
280 + * with GST_BOILERPLATE_FULL.
285 +gst_tag_reader_add_interface_to_type (GType type)
287 + static const GInterfaceInfo tr_iface_info = { NULL, NULL, NULL, };
289 + g_type_add_interface_static (type, GST_TYPE_TAG_READER, &tr_iface_info);
293 + * gst_tag_reader_set_tag_reading_mode:
294 + * @reader: a #GstTagReader to set the tag reading mode on.
295 + * @mode: tag reading mode to operate in.
297 + * This will set the tag reader's mode of operation. You should
298 + * use this method to tell a tag reader capable element in which
299 + * #GstTagReadingMode the reader should operate in.
301 + * This function will take the object lock and must not be called with the
302 + * object lock already held.
307 +gst_tag_reader_set_tag_reading_mode (GstTagReader * reader,
308 + GstTagReadingMode mode)
312 + g_return_if_fail (reader != NULL);
313 + g_return_if_fail (GST_IS_TAG_READER (reader));
314 + g_return_if_fail (GST_IS_ELEMENT (reader));
316 + obj = G_OBJECT (reader);
318 + GST_OBJECT_LOCK (obj);
319 + if (GST_STATE (obj) == GST_STATE_NULL) {
320 + GST_TAG_READER_SET_MODE (obj, mode);
321 + GST_LOG_OBJECT (obj, "configured mode: %d", mode);
322 + } else if (GST_TAG_READER_GET_MODE (obj) != mode) {
323 + g_warning ("Can't set tag reading mode on element '%s': element must be "
324 + "in NULL state", GST_ELEMENT_NAME (obj));
326 + GST_OBJECT_UNLOCK (obj);
330 + * gst_tag_reader_get_tag_reading_mode:
331 + * @reader: a #GstTagReader to get the tag reading mode from.
333 + * Query the currently configured #GstTagReadingMode.
335 + * This function will take the object lock and must not be called with the
336 + * object lock already held.
338 + * Returns: configured tag reading mode.
343 +gst_tag_reader_get_tag_reading_mode (GstTagReader * reader)
345 + GstTagReadingMode mode;
348 + g_return_val_if_fail (reader != NULL, GST_TAG_READING_MODE_DEFAULT);
349 + g_return_val_if_fail (GST_IS_TAG_READER (reader),
350 + GST_TAG_READING_MODE_DEFAULT);
351 + g_return_val_if_fail (GST_IS_ELEMENT (reader), GST_TAG_READING_MODE_DEFAULT);
353 + obj = G_OBJECT (reader);
355 + GST_OBJECT_LOCK (obj);
356 + mode = GST_TAG_READER_GET_MODE (obj);
357 + GST_OBJECT_UNLOCK (obj);
363 +gst_tag_reading_mode_get_type (void)
365 + static GType etype = 0;
367 + static const GEnumValue values[] = {
368 + {GST_TAG_READING_MODE_DEFAULT, "GST_TAG_READING_MODE_DEFAULT", "default"},
369 + {GST_TAG_READING_MODE_TAGS_ONLY, "GST_TAG_READING_MODE_TAGS_ONLY",
371 + {GST_TAG_READING_MODE_SKIP_TAGS, "GST_TAG_READING_MODE_SKIP_TAGS",
375 + etype = g_enum_register_static ("GstTagReadingMode", values);
379 diff --git a/gst-libs/gst/tag/gsttagreader.h b/gst-libs/gst/tag/gsttagreader.h
381 index 0000000..5c39f85
383 +++ b/gst-libs/gst/tag/gsttagreader.h
385 +/* GStreamer Tag Reader interface
386 + * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
387 + * Copyright (C) 2008 Nokia Corporation.
389 + * Contact: Stefan Kost <stefan.kost@nokia.com>
391 + * tagreader.h: Tag Reader interface design
393 + * This library is free software; you can redistribute it and/or
394 + * modify it under the terms of the GNU Library General Public
395 + * License as published by the Free Software Foundation; either
396 + * version 2 of the License, or (at your option) any later version.
398 + * This library is distributed in the hope that it will be useful,
399 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
400 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
401 + * Library General Public License for more details.
403 + * You should have received a copy of the GNU Library General Public
404 + * License along with this library; if not, write to the
405 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
406 + * Boston, MA 02111-1307, USA.
409 +#ifndef __GST_TAG_READER_H__
410 +#define __GST_TAG_READER_H__
412 +#include <gst/gst.h>
417 + * GstTagReadingMode:
418 + * @GST_TAG_READING_MODE_DEFAULT: parse both metadata and audio/video stream
420 + * @GST_TAG_READING_MODE_TAGS_ONLY: parse metadata and process only as much
421 + * audio/video data as required to extract basic information about the
422 + * stream such as tags, available streams and duration
423 + * @GST_TAG_READING_MODE_SKIP_TAGS: don't extract any metadata, just process
424 + * the audio/video stream data (behaviour should generally be the same as
425 + * with #GST_TAG_READING_MODE_DEFAULT, only that tag extraction is skipped)
427 + * Available tag reading modes.
431 +/* keep gst_tag_reading_mode_get_type() in sync when adding enums here */
433 + GST_TAG_READING_MODE_DEFAULT = 0,
434 + GST_TAG_READING_MODE_TAGS_ONLY,
435 + GST_TAG_READING_MODE_SKIP_TAGS
436 +} GstTagReadingMode;
438 +#define GST_TYPE_TAG_READING_MODE (gst_tag_reading_mode_get_type())
439 +GType gst_tag_reading_mode_get_type (void);
442 +#define GST_TYPE_TAG_READER \
443 + (gst_tag_reader_get_type ())
444 +#define GST_TAG_READER(obj) \
445 + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_READER, GstTagReader))
446 +#define GST_IS_TAG_READER(obj) \
447 + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_READER))
448 +#define GST_TAG_READER_GET_IFACE(inst) \
449 + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TAG_READER, \
450 + GstTagReaderInterface))
455 + * Opaque #GstTagReader structure (dummy typedef to denote object instances
456 + * which implement the #GstTagReader interface).
460 +typedef struct _GstTagReader GstTagReader;
461 +typedef struct _GstTagReaderInterface GstTagReaderInterface;
464 + * GstTagReaderInterface:
466 + * Dummy interface structure. Elements do not need to implement any interface
467 + * methods, all they need to do is query the desired tag reading mode via
468 + * gst_tag_reader_get_tag_reading_mode() where and when appropriate/required.
472 +struct _GstTagReaderInterface {
473 + GTypeInterface iface;
475 + /* methods: no methods to implement at this time */
477 + /* interfaces don't need padding, so no padding here */
480 +GType gst_tag_reader_get_type (void);
482 +void gst_tag_reader_add_interface_to_type (GType type);
484 +/* public methods */
486 +void gst_tag_reader_set_tag_reading_mode (GstTagReader * reader,
487 + GstTagReadingMode mode);
489 +GstTagReadingMode gst_tag_reader_get_tag_reading_mode (GstTagReader * reader);
493 +#endif /* __GST_TAG_READER_H__ */