Add some documentation.

Original commit message from CVS:
Add some documentation.
This commit is contained in:
Edgard Lima 2008-01-23 16:35:34 +00:00
parent 59c9a6a6bd
commit 90f78abd15
12 changed files with 1458 additions and 943 deletions

View file

@ -1,3 +1,18 @@
2008-01-23 Edgard Lima <edgard.lima@indt.org.br>
* docs/plugins/Makefile.am:
* docs/plugins/gst-plugins-bad-plugins-docs.sgml:
* docs/plugins/gst-plugins-bad-plugins-sections.txt:
* ext/metadata/TODO:
* ext/metadata/gstbasemetadata.c:
* ext/metadata/gstbasemetadata.h:
* ext/metadata/gstmetadatademux.c:
* ext/metadata/gstmetadatademux.h:
* ext/metadata/gstmetadatamux.c:
* ext/metadata/gstmetadatamux.h:
* ext/metadata/metadatatags.c:
Add some documentation.
2008-01-23 Sebastian Dröge <slomo@circular-chaos.org>
* configure.ac:

View file

@ -106,6 +106,9 @@ EXTRA_HFILES = \
$(top_srcdir)/ext/ivorbis/vorbisdec.h \
$(top_srcdir)/ext/jack/gstjackaudiosink.h \
$(top_srcdir)/ext/musicbrainz/gsttrm.h \
$(top_srcdir)/ext/metadata/gstbasemetadata.h \
$(top_srcdir)/ext/metadata/gstmetadatademux.h \
$(top_srcdir)/ext/metadata/gstmetadatamux.h \
$(top_srcdir)/ext/mythtv/gstmythtvsrc.h \
$(top_srcdir)/ext/sdl/sdlaudiosink.h \
$(top_srcdir)/ext/sdl/sdlvideosink.h \

View file

@ -38,6 +38,8 @@
<xi:include href="xml/element-ivorbisdec.xml" />
<xi:include href="xml/element-jackaudiosink.xml" />
<xi:include href="xml/element-lpwsinc.xml" />
<xi:include href="xml/element-metadatademux.xml" />
<xi:include href="xml/element-metadatamux.xml" />
<xi:include href="xml/element-modplug.xml" />
<xi:include href="xml/element-multifilesink.xml" />
<xi:include href="xml/element-multifilesrc.xml" />

View file

@ -312,6 +312,34 @@ GST_TYPE_JACK_AUDIO_SINK
gst_jack_audio_sink_get_type
</SECTION>
<SECTION>
<FILE>element-metadatademux</FILE>
<TITLE>metadatademux</TITLE>
GstMetadataDemux
<SUBSECTION Standard>
GstMetadataDemuxClass
GST_METADATA_DEMUX
GST_METADATA_DEMUX_CLASS
GST_IS_METADATA_DEMUX
GST_IS_METADATA_DEMUX_CLASS
GST_TYPE_METADATA_DEMUX
gst_metadata_demux_get_type
</SECTION>
<SECTION>
<FILE>element-metadatamux</FILE>
<TITLE>metadatamux</TITLE>
GstMetadataMux
<SUBSECTION Standard>
GstMetadataMuxClass
GST_METADATA_MUX
GST_METADATA_MUX_CLASS
GST_IS_METADATA_MUX
GST_IS_METADATA_MUX_CLASS
GST_TYPE_METADATA_MUX
gst_metadata_mux_get_type
</SECTION>
<SECTION>
<FILE>element-modplug</FILE>
<TITLE>modplug</TITLE>

View file

@ -22,6 +22,7 @@ OPEN ISSUES:
4- Add GST_TYPE_FRACTION support for GStreamer TAGS
5- currently, in JPEG files, if there is a Photoshop segment, everything inside it but IPTC will be lost. From the point of view of implementation it is easy, but I still don't now how to solve from the point of view of "designing". Anyway I think it is not so important.
6- language is not considered in XMP (How to do it with GStreamer?)
7- Add a helper function that convert from value to string. For example, aperture-size is 2.7 and the app wants to show "f/2.7", 'contrast' is a range and the app wants to show as "Normal", "Soft", "Hard". For the time being it is up to the APP to make this conversion.
KNOWN BUGS

File diff suppressed because it is too large Load diff

View file

@ -49,14 +49,20 @@
G_BEGIN_DECLS
/* #defines don't like whitespacey bits */
#define GST_TYPE_BASE_METADATA (gst_base_metadata_get_type())
#define GST_BASE_METADATA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_METADATA,GstBaseMetadata))
#define GST_BASE_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_METADATA,GstBaseMetadataClass))
#define GST_BASE_METADATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_METADATA, GstBaseMetadataClass))
#define GST_IS_BASE_METADATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_METADATA))
#define GST_IS_BASE_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_METADATA))
#define GST_BASE_METADATA_CAST(obj) ((GstBaseMetadata *)(obj))
/* *INDENT-OFF* */
#define GST_TYPE_BASE_METADATA (gst_base_metadata_get_type())
#define GST_BASE_METADATA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
GST_TYPE_BASE_METADATA,GstBaseMetadata))
#define GST_BASE_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
GST_TYPE_BASE_METADATA,GstBaseMetadataClass))
#define GST_BASE_METADATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
GST_TYPE_BASE_METADATA, GstBaseMetadataClass))
#define GST_IS_BASE_METADATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
GST_TYPE_BASE_METADATA))
#define GST_IS_BASE_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
GST_TYPE_BASE_METADATA))
#define GST_BASE_METADATA_CAST(obj) ((GstBaseMetadata *)(obj))
/* *INDENT-ON* */
typedef struct _GstBaseMetadata GstBaseMetadata;
typedef struct _GstBaseMetadataClass GstBaseMetadataClass;
@ -98,7 +104,6 @@ typedef enum _tag_MetadataState
/**
* GstBaseMetadata:
* @element: the parent element.
*
* The opaque #GstBaseMetadata data structure.
*/
@ -165,11 +170,8 @@ extern MetaOptions
gst_base_metadata_get_option_flag(const GstBaseMetadata *base);
extern void
gst_base_metadata_update_segment_with_new_buffer (GstBaseMetadata *base,
guint8 ** buf, guint32 * size, MetadataChunkType type);
extern void
gst_base_metadata_chunk_array_remove_zero_size (GstBaseMetadata *base);
gst_base_metadata_update_inject_segment_with_new_data (GstBaseMetadata *base,
guint8 ** data, guint32 * size, MetadataChunkType type);
G_END_DECLS
#endif /* __GST_BASE_METADATA_H__ */

View file

@ -42,18 +42,57 @@
*/
/**
* SECTION:metadatademux-metadata
* SECTION: element-metadatademux
* @short_description: element that parse or demux metadata from image files
* @see_also: #metadatamux
*
* <refsect2>
* <para>
* This element parses image files JPEG and PNG, to find metadata chunks (EXIF,
* IPTC, XMP) in it, and then send individual tags as a 'tag message' do the
* application and as 'tag event' to the next element in pipeline. It also
* strips out the metadata chunks from original stream (unless the 'parse-only'
* property is set to 'true'). In addition the whole metadata chunk (striped
* or not) it also sent as a message to the application bus, so the application
* can have more controls about the metadata.
* </para>
* <title>Example launch line</title>
* <para>
* <programlisting>
* gst-launch -v -m filesrc location=./test.jpeg ! metadatademux ! fakesink silent=TRUE
* gst-launch -v -m filesrc location=./test.jpeg ! metadatademux ! fakesink
* silent=TRUE
* </programlisting>
* <programlisting>
* GST_DEBUG:*metadata:5 gst-launch filesrc location=./test.jpeg !
* metadatademux ! fakesink
* </programlisting>
* </para>
* <title>Application sample code using 'libexif' to have more control</title>
* <para>
* <programlisting>
* val = gst_tag_list_get_value_index (taglist, GST_TAG_EXIF, 0);
* if (val) {
* exif_chunk = gst_value_get_buffer (val);
* if (exif_chunk) {
* ed = exif_data_new_from_data (GST_BUFFER_DATA (exif_chunk),
* GST_BUFFER_SIZE (exif_chunk));
* }
* }
* </programlisting>
* This same idea can be used to handle IPTC and XMP directly by using
* libdata and exempi (or any other libraries). Notice: the whole metadata
* chunk sent as a message to the application contains only metadata data, i.e.
* the wrapper specific to the file format (JPEG, PNG, ...) is already
* striped out.
* </para>
* </refsect2>
*/
/*
* includes
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@ -70,16 +109,13 @@
#include <string.h>
GST_DEBUG_CATEGORY_STATIC (gst_metadata_demux_debug);
#define GST_CAT_DEFAULT gst_metadata_demux_debug
#define GOTO_DONE_IF_NULL(ptr) do { if ( NULL == (ptr) ) goto done; } while(FALSE)
#define GOTO_DONE_IF_NULL_AND_FAIL(ptr, ret) do { if ( NULL == (ptr) ) { (ret) = FALSE; goto done; } } while(FALSE)
/*
* enum and types
*/
/* Filter signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
@ -89,6 +125,19 @@ enum
ARG_PARSE_ONLY
};
/*
* defines and static global vars
*/
GST_DEBUG_CATEGORY_STATIC (gst_metadata_demux_debug);
#define GST_CAT_DEFAULT gst_metadata_demux_debug
#define GOTO_DONE_IF_NULL(ptr) \
do { if ( NULL == (ptr) ) goto done; } while(FALSE)
#define GOTO_DONE_IF_NULL_AND_FAIL(ptr, ret) \
do { if ( NULL == (ptr) ) { (ret) = FALSE; goto done; } } while(FALSE)
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
@ -105,35 +154,113 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
"image/png, " "tags-extracted = (bool) true")
);
GST_BOILERPLATE (GstMetadataDemux, gst_metadata_demux, GstBaseMetadata,
GST_TYPE_BASE_METADATA);
static GstMetadataDemuxClass *metadata_parent_class = NULL;
/*
* static helper functions declaration
*/
static gboolean
gst_metadata_demux_configure_srccaps (GstMetadataDemux * filter);
/*
* GObject callback functions declaration
*/
static void gst_metadata_demux_base_init (gpointer gclass);
static void gst_metadata_demux_class_init (GstMetadataDemuxClass * klass);
static void
gst_metadata_demux_init (GstMetadataDemux * filter,
GstMetadataDemuxClass * gclass);
static void gst_metadata_demux_dispose (GObject * object);
static void gst_metadata_demux_finalize (GObject * object);
static void gst_metadata_demux_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_metadata_demux_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstCaps *gst_metadata_demux_get_caps (GstPad * pad);
static gboolean gst_metadata_demux_set_caps (GstPad * pad, GstCaps * caps);
static gboolean gst_metadata_demux_sink_event (GstPad * pad, GstEvent * event);
/*
* GstBaseMetadata virtual functions declaration
*/
static void gst_metadata_demux_send_tags (GstBaseMetadata * base);
static gboolean gst_metadata_demux_set_caps (GstPad * pad, GstCaps * caps);
static GstCaps *gst_metadata_demux_get_caps (GstPad * pad);
static gboolean gst_metadata_demux_sink_event (GstPad * pad, GstEvent * event);
/*
* GST BOILERPLATE
*/
GST_BOILERPLATE (GstMetadataDemux, gst_metadata_demux, GstBaseMetadata,
GST_TYPE_BASE_METADATA);
/*
* static helper functions implementation
*/
static gboolean
gst_metadata_demux_configure_srccaps (GstMetadataDemux * filter)
{
GstCaps *caps = NULL;
gboolean ret = FALSE;
gchar *mime = NULL;
switch (GST_BASE_METADATA_IMG_TYPE (filter)) {
case IMG_JPEG:
mime = "image/jpeg";
break;
case IMG_PNG:
mime = "image/png";
break;
default:
ret = FALSE;
goto done;
break;
}
caps =
gst_caps_new_simple (mime, "tags-extracted", G_TYPE_BOOLEAN, TRUE, NULL);
ret = gst_pad_set_caps (GST_BASE_METADATA_SRC_PAD (filter), caps);
done:
if (caps) {
gst_caps_unref (caps);
caps = NULL;
}
return ret;
}
/*
* GObject callback functions implementation
*/
static void
gst_metadata_demux_base_init (gpointer gclass)
{
/* *INDENT-OFF* */
static GstElementDetails element_details = {
"Metadata demuxr",
"Demuxr/Extracter/Metadata",
"Send metadata tags (EXIF, IPTC and XMP) and remove metadata chunks from stream",
"Metadata demuxer",
"Demuxer/Extracter/Metadata",
"Send metadata tags (EXIF, IPTC and XMP) and "
"remove metadata chunks from stream",
"Edgard Lima <edgard.lima@indt.org.br>"
};
/* *INDENT-ON* */
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_add_pad_template (element_class,
@ -143,7 +270,6 @@ gst_metadata_demux_base_init (gpointer gclass)
gst_element_class_set_details (element_class, &element_details);
}
/* initialize the plugin's class */
static void
gst_metadata_demux_class_init (GstMetadataDemuxClass * klass)
{
@ -180,11 +306,6 @@ gst_metadata_demux_class_init (GstMetadataDemuxClass * klass)
}
/* initialize the new element
* instantiate pads and add them to element
* set functions
* initialize structure
*/
static void
gst_metadata_demux_init (GstMetadataDemux * filter,
GstMetadataDemuxClass * gclass)
@ -250,6 +371,23 @@ gst_metadata_demux_finalize (GObject * object)
G_OBJECT_CLASS (metadata_parent_class)->finalize (object);
}
/*
* GstBaseMetadata virtual functions implementation
*/
/*
* gst_metadata_demux_send_tags:
* @base: the base metadata instance
*
* Send individual tags as message to the bus and as event to the next
* element, and send the whole metadata chunk (with file specific wrapper
* striped) to the next element as a event.
*
* Returns: nothing
*
*/
static void
gst_metadata_demux_send_tags (GstBaseMetadata * base)
{
@ -260,6 +398,8 @@ gst_metadata_demux_send_tags (GstBaseMetadata * base)
GstEvent *event;
GstPad *srcpad = GST_BASE_METADATA_SRC_PAD (filter);
/* get whole chunk */
if (gst_base_metadata_get_option_flag (base) & META_OPT_EXIF)
metadataparse_exif_tag_list_add (taglist, GST_TAG_MERGE_KEEP,
GST_BASE_METADATA_EXIF_ADAPTER (base), METADATA_TAG_MAP_WHOLECHUNK);
@ -284,6 +424,8 @@ gst_metadata_demux_send_tags (GstBaseMetadata * base)
if (!taglist)
taglist = gst_tag_list_new ();
/*get individual tags */
if (gst_base_metadata_get_option_flag (base) & META_OPT_EXIF)
metadataparse_exif_tag_list_add (taglist, GST_TAG_MERGE_KEEP,
GST_BASE_METADATA_EXIF_ADAPTER (base), METADATA_TAG_MAP_INDIVIDUALS);
@ -306,44 +448,6 @@ gst_metadata_demux_send_tags (GstBaseMetadata * base)
}
static gboolean
gst_metadata_demux_configure_srccaps (GstMetadataDemux * filter)
{
GstCaps *caps = NULL;
gboolean ret = FALSE;
gchar *mime = NULL;
switch (GST_BASE_METADATA_IMG_TYPE (filter)) {
case IMG_JPEG:
mime = "image/jpeg";
break;
case IMG_PNG:
mime = "image/png";
break;
default:
ret = FALSE;
goto done;
break;
}
caps =
gst_caps_new_simple (mime, "tags-extracted", G_TYPE_BOOLEAN, TRUE, NULL);
ret = gst_pad_set_caps (GST_BASE_METADATA_SRC_PAD (filter), caps);
done:
if (caps) {
gst_caps_unref (caps);
caps = NULL;
}
return ret;
}
/* this function handles the link with other elements */
static gboolean
gst_metadata_demux_set_caps (GstPad * pad, GstCaps * caps)
{

View file

@ -49,23 +49,34 @@
#include "gstbasemetadata.h"
G_BEGIN_DECLS
/* #defines don't like whitespacey bits */
/* *INDENT-OFF* */
#define GST_TYPE_METADATA_DEMUX \
(gst_metadata_demux_get_type())
#define GST_METADATA_DEMUX(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_METADATA_DEMUX,GstMetadataDemux))
#define GST_METADATA_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_METADATA_DEMUX,GstMetadataDemuxClass))
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_METADATA_DEMUX,\
GstMetadataDemuxClass))
#define GST_IS_METADATA_DEMUX(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_METADATA_DEMUX))
#define GST_IS_METADATA_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_METADATA_DEMUX))
/* *INDENT-ON* */
typedef struct _GstMetadataDemux GstMetadataDemux;
typedef struct _GstMetadataDemuxClass GstMetadataDemuxClass;
/**
* GstMetadataDemux:
*
* The opaque #GstMetadataDemux data structure.
*/
struct _GstMetadataDemux
{
GstBaseMetadata element;
GstBaseMetadata metadata;
};
struct _GstMetadataDemuxClass

View file

@ -42,18 +42,40 @@
*/
/**
* SECTION:metadatamux-metadata
* SECTION: element-metadatamux
*
* <refsect2>
* <para>
* This element writes tags into metadata (EXIF, IPTC and XMP) chunks, and
* writes the chunks into image files (JPEG, PNG). Tags the are received as
* GST_EVENT_TAG event or set by the application using #GstTagSetter interface.
* </para>
* <title>Example launch line</title>
* <para>
* <programlisting>
* gst-launch -v -m filesrc location=./test.jpeg ! metadatamux ! fakesink silent=TRUE
* gst-launch -v -m filesrc location=orig.jpeg ! metadatamux ! filesink
* location=dest.jpeg
* </programlisting>
* <programlisting>
* gst-launch -v -m filesrc location=orig.png ! metadatademux ! pngdec !
* ffmpegcolorspace ! jpegenc ! metadatamux ! filesink location=dest.jpeg
* </programlisting>
* </para>
* <title>How it works</title>
* <para>
* If this element receives a GST_TAG_EXIF, GST_TAG_IPTC or GST_TAG_XMP which
* are whole chunk metadata tags, then this whole chunk will be modified by
* individual tags received and written to the file. Otherwise, a new chunk
* will be created from the scratch and then modified in same way.
* </para>
* </refsect2>
*/
/*
* includes
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@ -70,26 +92,35 @@
#include <string.h>
GST_DEBUG_CATEGORY_STATIC (gst_metadata_mux_debug);
#define GST_CAT_DEFAULT gst_metadata_mux_debug
/*
* enum and types
*/
#define GOTO_DONE_IF_NULL(ptr) do { if ( NULL == (ptr) ) goto done; } while(FALSE)
#define GOTO_DONE_IF_NULL_AND_FAIL(ptr, ret) do { if ( NULL == (ptr) ) { (ret) = FALSE; goto done; } } while(FALSE)
/* Filter signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
ARG_0,
ARG_PARSE_ONLY
};
/*
* defines and static global vars
*/
GST_DEBUG_CATEGORY_STATIC (gst_metadata_mux_debug);
#define GST_CAT_DEFAULT gst_metadata_mux_debug
#define GOTO_DONE_IF_NULL(ptr) \
do { if ( NULL == (ptr) ) goto done; } while(FALSE)
#define GOTO_DONE_IF_NULL_AND_FAIL(ptr, ret) \
do { if ( NULL == (ptr) ) { (ret) = FALSE; goto done; } } while(FALSE)
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
@ -103,6 +134,51 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_STATIC_CAPS ("image/jpeg; " "image/png")
);
static GstMetadataMuxClass *metadata_parent_class = NULL;
/*
* static helper functions declaration
*/
static gboolean gst_metadata_mux_configure_srccaps (GstMetadataMux * filter);
/*
* GObject callback functions declaration
*/
static void gst_metadata_mux_base_init (gpointer gclass);
static void gst_metadata_mux_class_init (GstMetadataMuxClass * klass);
static void
gst_metadata_mux_init (GstMetadataMux * filter, GstMetadataMuxClass * gclass);
static void gst_metadata_mux_dispose (GObject * object);
static void gst_metadata_mux_finalize (GObject * object);
static void gst_metadata_mux_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_metadata_mux_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
/*
* GstBaseMetadata virtual functions declaration
*/
static void gst_metadata_mux_create_chunks_from_tags (GstBaseMetadata * base);
static gboolean gst_metadata_mux_set_caps (GstPad * pad, GstCaps * caps);
static GstCaps *gst_metadata_mux_get_caps (GstPad * pad);
static gboolean gst_metadata_mux_sink_event (GstPad * pad, GstEvent * event);
/*
* GST BOILERPLATE
*/
static void
gst_metadata_mux_add_interfaces (GType type)
{
@ -115,188 +191,10 @@ gst_metadata_mux_add_interfaces (GType type)
GST_BOILERPLATE_FULL (GstMetadataMux, gst_metadata_mux, GstBaseMetadata,
GST_TYPE_BASE_METADATA, gst_metadata_mux_add_interfaces);
static GstMetadataMuxClass *metadata_parent_class = NULL;
static void gst_metadata_mux_dispose (GObject * object);
static void gst_metadata_mux_finalize (GObject * object);
static void gst_metadata_mux_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_metadata_mux_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstCaps *gst_metadata_mux_get_caps (GstPad * pad);
static gboolean gst_metadata_mux_set_caps (GstPad * pad, GstCaps * caps);
static gboolean gst_metadata_mux_sink_event (GstPad * pad, GstEvent * event);
static void gst_metadata_mux_create_chunks_from_tags (GstBaseMetadata * base);
static void
gst_metadata_mux_base_init (gpointer gclass)
{
static GstElementDetails element_details = {
"Metadata muxr",
"Muxr/Extracter/Metadata",
"Send metadata tags (EXIF, IPTC and XMP) and remove metadata chunks from stream",
"Edgard Lima <edgard.lima@indt.org.br>"
};
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details (element_class, &element_details);
}
/* initialize the plugin's class */
static void
gst_metadata_mux_class_init (GstMetadataMuxClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseMetadataClass *gstbasemetadata_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasemetadata_class = (GstBaseMetadataClass *) klass;
metadata_parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_metadata_mux_dispose);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_metadata_mux_finalize);
gobject_class->set_property = gst_metadata_mux_set_property;
gobject_class->get_property = gst_metadata_mux_get_property;
g_object_class_install_property (gobject_class, ARG_PARSE_ONLY,
g_param_spec_boolean ("parse-only", "parse-only",
"If TRUE, don't strip out any chunk", FALSE, G_PARAM_READWRITE));
gstbasemetadata_class->processing =
GST_DEBUG_FUNCPTR (gst_metadata_mux_create_chunks_from_tags);
gstbasemetadata_class->set_caps =
GST_DEBUG_FUNCPTR (gst_metadata_mux_set_caps);
gstbasemetadata_class->get_sink_caps =
GST_DEBUG_FUNCPTR (gst_metadata_mux_get_caps);
gstbasemetadata_class->get_src_caps =
GST_DEBUG_FUNCPTR (gst_metadata_mux_get_caps);
gstbasemetadata_class->sink_event =
GST_DEBUG_FUNCPTR (gst_metadata_mux_sink_event);
}
/* initialize the new element
* instantiate pads and add them to element
* set functions
* initialize structure
/*
* static helper functions implementation
*/
static void
gst_metadata_mux_init (GstMetadataMux * filter, GstMetadataMuxClass * gclass)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);
gst_base_metadata_set_option_flag (GST_BASE_METADATA (filter),
META_OPT_EXIF | META_OPT_IPTC | META_OPT_XMP | META_OPT_MUX);
}
static void
gst_metadata_mux_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstMetadataMux *filter = GST_METADATA_MUX (object);
switch (prop_id) {
case ARG_PARSE_ONLY:
if (g_value_get_boolean (value))
gst_base_metadata_set_option_flag (GST_BASE_METADATA (object),
META_OPT_PARSE_ONLY);
else
gst_base_metadata_unset_option_flag (GST_BASE_METADATA (object),
META_OPT_PARSE_ONLY);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_metadata_mux_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
guint8 option =
gst_base_metadata_get_option_flag (GST_BASE_METADATA (object));
switch (prop_id) {
case ARG_PARSE_ONLY:
g_value_set_boolean (value, option & META_OPT_PARSE_ONLY);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_metadata_mux_dispose (GObject * object)
{
GstMetadataMux *filter = NULL;
G_OBJECT_CLASS (metadata_parent_class)->dispose (object);
}
static void
gst_metadata_mux_finalize (GObject * object)
{
G_OBJECT_CLASS (metadata_parent_class)->finalize (object);
}
static void
gst_metadata_mux_create_chunks_from_tags (GstBaseMetadata * base)
{
GstMetadataMux *filter = GST_METADATA_MUX (base);
GstMessage *msg;
GstTagSetter *setter = GST_TAG_SETTER (filter);
const GstTagList *taglist = gst_tag_setter_get_tag_list (setter);
GstEvent *event;
guint8 *buf = NULL;
guint32 size = 0;
if (taglist) {
if (gst_base_metadata_get_option_flag (base) & META_OPT_EXIF) {
metadatamux_exif_create_chunk_from_tag_list (&buf, &size, taglist);
gst_base_metadata_update_segment_with_new_buffer (base, &buf, &size,
MD_CHUNK_EXIF);
}
if (gst_base_metadata_get_option_flag (base) & META_OPT_IPTC) {
metadatamux_iptc_create_chunk_from_tag_list (&buf, &size, taglist);
gst_base_metadata_update_segment_with_new_buffer (base, &buf, &size,
MD_CHUNK_IPTC);
}
if (gst_base_metadata_get_option_flag (base) & META_OPT_XMP) {
metadatamux_xmp_create_chunk_from_tag_list (&buf, &size, taglist);
gst_base_metadata_update_segment_with_new_buffer (base, &buf, &size,
MD_CHUNK_XMP);
}
}
if (buf) {
g_free (buf);
}
gst_base_metadata_chunk_array_remove_zero_size (base);
}
static gboolean
gst_metadata_mux_configure_srccaps (GstMetadataMux * filter)
@ -333,8 +231,172 @@ done:
}
/*
* GObject callback functions declaration
*/
static void
gst_metadata_mux_base_init (gpointer gclass)
{
/* *INDENT-OFF* */
static GstElementDetails element_details = {
"Metadata muxer",
"Muxer/Extracter/Metadata",
"Write metadata (EXIF, IPTC and XMP) into a image stream",
"Edgard Lima <edgard.lima@indt.org.br>"
};
/* *INDENT-ON* */
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details (element_class, &element_details);
}
static void
gst_metadata_mux_class_init (GstMetadataMuxClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseMetadataClass *gstbasemetadata_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasemetadata_class = (GstBaseMetadataClass *) klass;
metadata_parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_metadata_mux_dispose);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_metadata_mux_finalize);
gobject_class->set_property = gst_metadata_mux_set_property;
gobject_class->get_property = gst_metadata_mux_get_property;
gstbasemetadata_class->processing =
GST_DEBUG_FUNCPTR (gst_metadata_mux_create_chunks_from_tags);
gstbasemetadata_class->set_caps =
GST_DEBUG_FUNCPTR (gst_metadata_mux_set_caps);
gstbasemetadata_class->get_sink_caps =
GST_DEBUG_FUNCPTR (gst_metadata_mux_get_caps);
gstbasemetadata_class->get_src_caps =
GST_DEBUG_FUNCPTR (gst_metadata_mux_get_caps);
gstbasemetadata_class->sink_event =
GST_DEBUG_FUNCPTR (gst_metadata_mux_sink_event);
}
static void
gst_metadata_mux_init (GstMetadataMux * filter, GstMetadataMuxClass * gclass)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);
gst_base_metadata_set_option_flag (GST_BASE_METADATA (filter),
META_OPT_EXIF | META_OPT_IPTC | META_OPT_XMP | META_OPT_MUX);
}
static void
gst_metadata_mux_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstMetadataMux *filter = GST_METADATA_MUX (object);
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_metadata_mux_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
guint8 option =
gst_base_metadata_get_option_flag (GST_BASE_METADATA (object));
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_metadata_mux_dispose (GObject * object)
{
GstMetadataMux *filter = NULL;
G_OBJECT_CLASS (metadata_parent_class)->dispose (object);
}
static void
gst_metadata_mux_finalize (GObject * object)
{
G_OBJECT_CLASS (metadata_parent_class)->finalize (object);
}
/*
* GstBaseMetadata virtual functions implementation
*/
/*
* gst_metadata_mux_create_chunks_from_tags:
* @base: the base metadata instance
*
* This function creates new metadata (EXIF, IPTC, XMP) chunks with the tags
* received and add it to the list of segments that will be injected to the
* resulting file by #GstBaseMetadata.
*
* Returns: nothing
*
*/
static void
gst_metadata_mux_create_chunks_from_tags (GstBaseMetadata * base)
{
GstMetadataMux *filter = GST_METADATA_MUX (base);
GstMessage *msg;
GstTagSetter *setter = GST_TAG_SETTER (filter);
const GstTagList *taglist = gst_tag_setter_get_tag_list (setter);
GstEvent *event;
guint8 *buf = NULL;
guint32 size = 0;
if (taglist) {
if (gst_base_metadata_get_option_flag (base) & META_OPT_EXIF) {
metadatamux_exif_create_chunk_from_tag_list (&buf, &size, taglist);
gst_base_metadata_update_inject_segment_with_new_data (base, &buf, &size,
MD_CHUNK_EXIF);
}
if (gst_base_metadata_get_option_flag (base) & META_OPT_IPTC) {
metadatamux_iptc_create_chunk_from_tag_list (&buf, &size, taglist);
gst_base_metadata_update_inject_segment_with_new_data (base, &buf, &size,
MD_CHUNK_IPTC);
}
if (gst_base_metadata_get_option_flag (base) & META_OPT_XMP) {
metadatamux_xmp_create_chunk_from_tag_list (&buf, &size, taglist);
gst_base_metadata_update_inject_segment_with_new_data (base, &buf, &size,
MD_CHUNK_XMP);
}
}
if (buf) {
g_free (buf);
}
}
/* this function handles the link with other elements */
static gboolean
gst_metadata_mux_set_caps (GstPad * pad, GstCaps * caps)
{

View file

@ -49,7 +49,8 @@
#include "gstbasemetadata.h"
G_BEGIN_DECLS
/* #defines don't like whitespacey bits */
/* *INDENT-OFF* */
#define GST_TYPE_METADATA_MUX \
(gst_metadata_mux_get_type())
#define GST_METADATA_MUX(obj) \
@ -60,12 +61,20 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_METADATA_MUX))
#define GST_IS_METADATA_MUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_METADATA_MUX))
/* *INDENT-ON* */
typedef struct _GstMetadataMux GstMetadataMux;
typedef struct _GstMetadataMuxClass GstMetadataMuxClass;
/**
* GstMetadataMux:
*
* The opaque #GstMetadataMux data structure.
*/
struct _GstMetadataMux
{
GstBaseMetadata element;
GstBaseMetadata metadata;
};
struct _GstMetadataMuxClass

View file

@ -83,34 +83,34 @@ metadata_tags_exif_register (void)
gst_tag_register (GST_TAG_CAPTURE_FNUMBER, GST_TAG_FLAG_META,
GST_TYPE_FRACTION, GST_TAG_CAPTURE_FNUMBER, "F number (focal ratio)",
NULL);
/**
0 - not defined
1- Manual
2- Normal program
3- Aperture priority
4- Shutter priority
5- Creative program (biased toward death of field)
6- Action program (biased toward fast shutter speed)
7- Portrait mode (for closeup photos with the background out of focus)
8- Landscape mode (for landscape photos with the background in focus)
*** exif is until here ***
9- Night
10- Back-light
11- Spotlight
12- Snow
13- Beach
*/
/*
0 - not defined
1- Manual
2- Normal program
3- Aperture priority
4- Shutter priority
5- Creative program (biased toward death of field)
6- Action program (biased toward fast shutter speed)
7- Portrait mode (for closeup photos with the background out of focus)
8- Landscape mode (for landscape photos with the background in focus)
*** exif is until here ***
9- Night
10- Back-light
11- Spotlight
12- Snow
13- Beach
*/
gst_tag_register (GST_TAG_CAPTURE_EXPOSURE_PROGRAM, GST_TAG_FLAG_META,
G_TYPE_UINT, GST_TAG_CAPTURE_EXPOSURE_PROGRAM,
"Class of program used for exposure", NULL);
/** The unit is the APEX value.
Ordinarily it is given in the range of -99.99 to 99.99.
if numerator is 0xFFFFFFFF means unknown
*/
/* The unit is the APEX value.
Ordinarily it is given in the range of -99.99 to 99.99.
if numerator is 0xFFFFFFFF means unknown
*/
gst_tag_register (GST_TAG_CAPTURE_BRIGHTNESS, GST_TAG_FLAG_META,
GST_TYPE_FRACTION, GST_TAG_CAPTURE_BRIGHTNESS,
"Brightness (APEX from -99.99 to 99.99)", NULL);
/**
/*
0- Auto
1- Off
*** exif is until here ***
@ -122,39 +122,39 @@ metadata_tags_exif_register (void)
7- Incandescent
8- Flash
9- Horizon (sun on the horizon)
*/
*/
gst_tag_register (GST_TAG_CAPTURE_WHITE_BALANCE, GST_TAG_FLAG_META,
G_TYPE_UINT, GST_TAG_CAPTURE_WHITE_BALANCE, "White balance mode", NULL);
/** if Zero ZOOM not used
/* if Zero ZOOM not used
*/
gst_tag_register (GST_TAG_CAPTURE_DIGITAL_ZOOM, GST_TAG_FLAG_META,
GST_TYPE_FRACTION, GST_TAG_CAPTURE_DIGITAL_ZOOM, "Digital zoom ratio",
NULL);
/**
/*
0- None
1- Low gain up
2- High gain up
3- Low gain down
4- High gain down
*/
*/
gst_tag_register (GST_TAG_CAPTURE_GAIN, GST_TAG_FLAG_META, G_TYPE_UINT,
GST_TAG_CAPTURE_GAIN, "", NULL);
/**
/*
from -100 to 100
[-100, -34] - soft
[-33, 33] - normal
[34, 100] - hard
*** exif is just 0, 1, 2 (normal, soft and hard)
*/
*/
gst_tag_register (GST_TAG_CAPTURE_CONTRAST, GST_TAG_FLAG_META, G_TYPE_INT,
GST_TAG_CAPTURE_CONTRAST, "", NULL);
/**
/*
from -100 to 100
[-100, -34] - low
[-33, 33] - normal
[34, 100] - high
*** exif is just 0, 1, 2 (normal, low and high)
*/
*/
gst_tag_register (GST_TAG_CAPTURE_SATURATION, GST_TAG_FLAG_META, G_TYPE_INT,
GST_TAG_CAPTURE_SATURATION, "", NULL);