diff options
author | Michael Smith <msmith@xiph.org> | 2006-02-24 19:07:10 +0000 |
---|---|---|
committer | Michael Smith <msmith@xiph.org> | 2006-02-24 19:07:10 +0000 |
commit | 73ce8c5b9e9a9cb27c1307dbfee300939265650c (patch) | |
tree | 207f645f3849f86026894e7411d9335353a12e53 /ext/annodex/gstcmmltag.c | |
parent | dd8f37faac9ea109550d630f4d7dcbf295cd5fc1 (diff) |
Add Annodex elements from Alessendro Decina: skeleton and CMML.
Original commit message from CVS:
* configure.ac:
* docs/plugins/gst-plugins-good-plugins-sections.txt:
* ext/Makefile.am:
* ext/annodex/Makefile.am:
* ext/annodex/gstannodex.c:
* ext/annodex/gstannodex.h:
* ext/annodex/gstcmmldec.c:
* ext/annodex/gstcmmldec.h:
* ext/annodex/gstcmmlenc.c:
* ext/annodex/gstcmmlenc.h:
* ext/annodex/gstcmmlparser.c:
* ext/annodex/gstcmmlparser.h:
* ext/annodex/gstcmmltag.c:
* ext/annodex/gstcmmltag.h:
* ext/annodex/gstcmmlutils.c:
* ext/annodex/gstcmmlutils.h:
* ext/annodex/gstskeldec.c:
* ext/annodex/gstskeldec.h:
* ext/annodex/gstskeltag.c:
* ext/annodex/gstskeltag.h:
* tests/check/Makefile.am:
* tests/check/elements/cmmldec.c:
* tests/check/elements/cmmlenc.c:
* tests/check/elements/skeldec.c:
Add Annodex elements from Alessendro Decina: skeleton and CMML.
Includes tests & docs, oh my! Passes Thomas's -good checklist
entirely. Wow.
Diffstat (limited to 'ext/annodex/gstcmmltag.c')
-rw-r--r-- | ext/annodex/gstcmmltag.c | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/ext/annodex/gstcmmltag.c b/ext/annodex/gstcmmltag.c new file mode 100644 index 00000000..1a49d791 --- /dev/null +++ b/ext/annodex/gstcmmltag.c @@ -0,0 +1,565 @@ +/* + * gstcmmltags.c - GStreamer CMML tag support + * Copyright (C) 2005 Alessandro Decina + * + * Authors: + * Alessandro Decina <alessandro@nnva.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include "gstcmmlparser.h" +#include "gstcmmltag.h" +#include "gstannodex.h" + +enum +{ + ARG_0, + GST_CMML_TAG_STREAM_TIMEBASE, + GST_CMML_TAG_STREAM_UTC, + GST_CMML_TAG_STREAM_IMPORTS, + GST_CMML_TAG_HEAD_TITLE, + GST_CMML_TAG_HEAD_BASE, + GST_CMML_TAG_HEAD_META, + GST_CMML_TAG_CLIP_EMPTY, + GST_CMML_TAG_CLIP_ID, + GST_CMML_TAG_CLIP_TRACK, + GST_CMML_TAG_CLIP_START_TIME, + GST_CMML_TAG_CLIP_END_TIME, + GST_CMML_TAG_CLIP_ANCHOR_HREF, + GST_CMML_TAG_CLIP_ANCHOR_TEXT, + GST_CMML_TAG_CLIP_IMG_SRC, + GST_CMML_TAG_CLIP_IMG_ALT, + GST_CMML_TAG_CLIP_DESC_TEXT, + GST_CMML_TAG_CLIP_META, +}; + +G_DEFINE_TYPE (GstCmmlTagStream, gst_cmml_tag_stream, G_TYPE_OBJECT); +static void gst_cmml_tag_stream_finalize (GObject * object); +static void gst_cmml_tag_stream_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_cmml_tag_stream_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_cmml_tag_stream_value_from_string_value (const GValue * src, + GValue * dest); + +G_DEFINE_TYPE (GstCmmlTagHead, gst_cmml_tag_head, G_TYPE_OBJECT); +static void gst_cmml_tag_head_finalize (GObject * object); +static void gst_cmml_tag_head_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void gst_cmml_tag_head_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); +static void gst_cmml_tag_head_value_from_string_value (const GValue * src, + GValue * dest); + +G_DEFINE_TYPE (GstCmmlTagClip, gst_cmml_tag_clip, G_TYPE_OBJECT); +static void gst_cmml_tag_clip_finalize (GObject * object); +static void gst_cmml_tag_clip_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void gst_cmml_tag_clip_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); + +static void gst_cmml_tag_clip_value_from_string_value (const GValue * src, + GValue * dest); + +static void set_object_on_value (GObject * object, GValue * dest); + +static const gchar *default_preamble = + "<?xml version=\"1.0\" standalone=\"yes\"?>"; + +/* Stream tag */ +static void +gst_cmml_tag_stream_class_init (GstCmmlTagStreamClass * stream_class) +{ + GObjectClass *klass = G_OBJECT_CLASS (stream_class); + + klass->set_property = gst_cmml_tag_stream_set_property; + klass->get_property = gst_cmml_tag_stream_get_property; + klass->finalize = gst_cmml_tag_stream_finalize; + + g_object_class_install_property (klass, GST_CMML_TAG_STREAM_TIMEBASE, + g_param_spec_string ("base-time", + "Base time", + "Playback time (in seconds) of the first data packet", + "0", G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_STREAM_UTC, + g_param_spec_string ("calendar-base-time", + "Calendar base time", + "Date and wall-clock time (expressed as UTC time in the format " + "YYYYMMDDTHHMMSS.sssZ) associated with the base-time", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_STREAM_IMPORTS, + g_param_spec_value_array ("input-streams", + "Input streams", + "List of input streams that compose this bitstream", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_CMML_TAG_STREAM, + gst_cmml_tag_stream_value_from_string_value); +} + +static void +gst_cmml_tag_stream_init (GstCmmlTagStream * stream) +{ +} + +static void +gst_cmml_tag_stream_finalize (GObject * object) +{ + GstCmmlTagStream *stream = GST_CMML_TAG_STREAM (object); + + g_free (stream->timebase); + g_free (stream->utc); + if (stream->imports) + g_value_array_free (stream->imports); + + if (G_OBJECT_CLASS (gst_cmml_tag_stream_parent_class)->finalize) + G_OBJECT_CLASS (gst_cmml_tag_stream_parent_class)->finalize (object); +} + +static void +gst_cmml_tag_stream_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstCmmlTagStream *stream = GST_CMML_TAG_STREAM (object); + + switch (property_id) { + case GST_CMML_TAG_STREAM_TIMEBASE: + g_free (stream->timebase); + stream->timebase = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_STREAM_UTC: + g_free (stream->utc); + stream->utc = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_STREAM_IMPORTS: + { + GValueArray *va = g_value_get_boxed (value); + + if (stream->imports) + g_value_array_free (stream->imports); + stream->imports = va != NULL ? g_value_array_copy (va) : NULL; + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + + +static void +gst_cmml_tag_stream_value_from_string_value (const GValue * src, GValue * dest) +{ + GstCmmlParser *parser; + const gchar *str; + guint size; + + parser = gst_cmml_parser_new (GST_CMML_PARSER_DECODE); + parser->user_data = dest; + parser->stream_callback = (GstCmmlParserStreamCallback) set_object_on_value; + gst_cmml_parser_parse_chunk (parser, + default_preamble, strlen (default_preamble), NULL); + + str = g_value_get_string (src); + size = strlen (str); + gst_cmml_parser_parse_chunk (parser, str, size, NULL); + + gst_cmml_parser_free (parser); +} + +static void +gst_cmml_tag_stream_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstCmmlTagStream *stream = GST_CMML_TAG_STREAM (object); + + switch (property_id) { + case GST_CMML_TAG_STREAM_TIMEBASE: + g_value_set_string (value, (gchar *) stream->timebase); + break; + case GST_CMML_TAG_STREAM_UTC: + g_value_set_string (value, (gchar *) stream->utc); + break; + case GST_CMML_TAG_STREAM_IMPORTS: + g_value_set_boxed (value, stream->imports); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +/* Head tag */ +static void +gst_cmml_tag_head_class_init (GstCmmlTagHeadClass * head_class) +{ + GObjectClass *klass = G_OBJECT_CLASS (head_class); + + klass->set_property = gst_cmml_tag_head_set_property; + klass->get_property = gst_cmml_tag_head_get_property; + klass->finalize = gst_cmml_tag_head_finalize; + + g_object_class_install_property (klass, GST_CMML_TAG_HEAD_TITLE, + g_param_spec_string ("title", + "Title", + "Title of the bitstream", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_HEAD_BASE, + g_param_spec_string ("base-uri", + "Base URI", + "Base URI of the bitstream. All relative URIs are relative to this", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_HEAD_META, + g_param_spec_value_array ("meta", + "Meta annotations", + "Meta annotations for the complete Annodex bitstream", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_CMML_TAG_HEAD, + gst_cmml_tag_head_value_from_string_value); +} + +static void +gst_cmml_tag_head_init (GstCmmlTagHead * head) +{ +} + +static void +gst_cmml_tag_head_finalize (GObject * object) +{ + GstCmmlTagHead *head = GST_CMML_TAG_HEAD (object); + + g_free (head->title); + g_free (head->base); + if (head->meta) + g_value_array_free (head->meta); + + if (G_OBJECT_CLASS (gst_cmml_tag_head_parent_class)->finalize) + G_OBJECT_CLASS (gst_cmml_tag_head_parent_class)->finalize (object); +} + +static void +gst_cmml_tag_head_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstCmmlTagHead *head = GST_CMML_TAG_HEAD (object); + + switch (property_id) { + case GST_CMML_TAG_HEAD_TITLE: + g_free (head->title); + head->title = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_HEAD_BASE: + g_free (head->base); + head->base = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_HEAD_META: + { + GValueArray *va = g_value_get_boxed (value); + + if (head->meta) + g_value_array_free (head->meta); + head->meta = va != NULL ? g_value_array_copy (va) : NULL; + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +gst_cmml_tag_head_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstCmmlTagHead *head = GST_CMML_TAG_HEAD (object); + + switch (property_id) { + case GST_CMML_TAG_HEAD_TITLE: + g_value_set_string (value, (gchar *) head->title); + break; + case GST_CMML_TAG_HEAD_BASE: + g_value_set_string (value, (gchar *) head->base); + break; + case GST_CMML_TAG_HEAD_META: + g_value_set_boxed (value, head->meta); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +gst_cmml_tag_head_value_from_string_value (const GValue * src, GValue * dest) +{ + GstCmmlParser *parser; + const gchar *str; + guint size; + + parser = gst_cmml_parser_new (GST_CMML_PARSER_DECODE); + parser->user_data = dest; + parser->head_callback = (GstCmmlParserHeadCallback) set_object_on_value; + gst_cmml_parser_parse_chunk (parser, + default_preamble, strlen (default_preamble), NULL); + + str = g_value_get_string (src); + size = strlen (str); + gst_cmml_parser_parse_chunk (parser, str, size, NULL); + + gst_cmml_parser_free (parser); +} + +/* Clip tag */ +static void +gst_cmml_tag_clip_class_init (GstCmmlTagClipClass * clip_class) +{ + GObjectClass *klass = G_OBJECT_CLASS (clip_class); + + klass->set_property = gst_cmml_tag_clip_set_property; + klass->get_property = gst_cmml_tag_clip_get_property; + klass->finalize = gst_cmml_tag_clip_finalize; + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_EMPTY, + g_param_spec_boolean ("empty", + "Empty clip flag", + "An empty clip only marks the end of the previous clip", + TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_ID, + g_param_spec_string ("id", + "Clip id", + "Id of the clip", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_TRACK, + g_param_spec_string ("track", + "Track number", + "The track this clip belongs to", + "default", G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_START_TIME, + g_param_spec_uint64 ("start-time", + "Start time", + "The start time (in seconds) of the clip", + 0, G_MAXUINT64, GST_CLOCK_TIME_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_END_TIME, + g_param_spec_uint64 ("end-time", + "End time", + "The end time (in seconds) of the clip (only set if extract-mode=true)", + 0, G_MAXUINT64, GST_CLOCK_TIME_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_ANCHOR_HREF, + g_param_spec_string ("anchor-uri", + "Anchor URI", + "The location of a Web resource closely connected to the clip", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_ANCHOR_TEXT, + g_param_spec_string ("anchor-text", + "Anchor text", + "A short description of the resource pointed by anchor-uri", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_IMG_SRC, + g_param_spec_string ("img-uri", + "Image URI", + "The URI of a representative image for the clip", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_IMG_ALT, + g_param_spec_string ("img-alt", + "Image alternative text", + "Alternative text to be displayed instead of the image " + "specified in img-uri", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_DESC_TEXT, + g_param_spec_string ("description", + "Description", + "A textual description of the content of the clip", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (klass, GST_CMML_TAG_CLIP_META, + g_param_spec_value_array ("meta", + "Meta annotations", + "Meta annotations for the clip", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_CMML_TAG_CLIP, + gst_cmml_tag_clip_value_from_string_value); +} + +static void +gst_cmml_tag_clip_init (GstCmmlTagClip * clip) +{ +} + +static void +gst_cmml_tag_clip_finalize (GObject * object) +{ + GstCmmlTagClip *clip = GST_CMML_TAG_CLIP (object); + + g_free (clip->id); + g_free (clip->track); + g_free (clip->anchor_href); + g_free (clip->anchor_text); + g_free (clip->img_src); + g_free (clip->img_alt); + g_free (clip->desc_text); + if (clip->meta) + g_value_array_free (clip->meta); + + if (G_OBJECT_CLASS (gst_cmml_tag_clip_parent_class)->finalize) + G_OBJECT_CLASS (gst_cmml_tag_clip_parent_class)->finalize (object); +} + +static void +gst_cmml_tag_clip_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstCmmlTagClip *clip = GST_CMML_TAG_CLIP (object); + + switch (property_id) { + case GST_CMML_TAG_CLIP_EMPTY: + clip->empty = g_value_get_boolean (value); + break; + case GST_CMML_TAG_CLIP_ID: + g_free (clip->id); + clip->id = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_CLIP_TRACK: + g_free (clip->track); + clip->track = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_CLIP_START_TIME: + clip->start_time = g_value_get_uint64 (value); + break; + case GST_CMML_TAG_CLIP_END_TIME: + clip->end_time = g_value_get_uint64 (value); + break; + case GST_CMML_TAG_CLIP_ANCHOR_HREF: + g_free (clip->anchor_href); + clip->anchor_href = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_CLIP_ANCHOR_TEXT: + g_free (clip->anchor_text); + clip->anchor_text = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_CLIP_IMG_SRC: + g_free (clip->img_src); + clip->img_src = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_CLIP_IMG_ALT: + g_free (clip->img_alt); + clip->img_alt = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_CLIP_DESC_TEXT: + g_free (clip->desc_text); + clip->desc_text = (guchar *) g_value_dup_string (value); + break; + case GST_CMML_TAG_CLIP_META: + { + GValueArray *va = (GValueArray *) g_value_get_boxed (value); + + if (clip->meta) + g_value_array_free (clip->meta); + + clip->meta = va != NULL ? g_value_array_copy (va) : NULL; + + break; + } + } +} + +static void +gst_cmml_tag_clip_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstCmmlTagClip *clip = GST_CMML_TAG_CLIP (object); + + switch (property_id) { + case GST_CMML_TAG_CLIP_EMPTY: + g_value_set_boolean (value, clip->empty); + break; + case GST_CMML_TAG_CLIP_ID: + g_value_set_string (value, (gchar *) clip->id); + break; + case GST_CMML_TAG_CLIP_TRACK: + g_value_set_string (value, (gchar *) clip->track); + break; + case GST_CMML_TAG_CLIP_START_TIME: + g_value_set_uint64 (value, clip->start_time); + break; + case GST_CMML_TAG_CLIP_END_TIME: + g_value_set_uint64 (value, clip->end_time); + break; + case GST_CMML_TAG_CLIP_ANCHOR_HREF: + g_value_set_string (value, (gchar *) clip->anchor_href); + break; + case GST_CMML_TAG_CLIP_ANCHOR_TEXT: + g_value_set_string (value, (gchar *) clip->anchor_text); + break; + case GST_CMML_TAG_CLIP_IMG_SRC: + g_value_set_string (value, (gchar *) clip->img_src); + break; + case GST_CMML_TAG_CLIP_IMG_ALT: + g_value_set_string (value, (gchar *) clip->img_alt); + break; + case GST_CMML_TAG_CLIP_DESC_TEXT: + g_value_set_string (value, (gchar *) clip->desc_text); + break; + case GST_CMML_TAG_CLIP_META: + g_value_set_boxed (value, clip->meta); + break; + } +} + +static void +gst_cmml_tag_clip_value_from_string_value (const GValue * src, GValue * dest) +{ + GstCmmlParser *parser; + const gchar *str; + guint size; + + parser = gst_cmml_parser_new (GST_CMML_PARSER_DECODE); + parser->user_data = dest; + parser->clip_callback = (GstCmmlParserClipCallback) set_object_on_value; + + gst_cmml_parser_parse_chunk (parser, default_preamble, + strlen (default_preamble), NULL); + + str = g_value_get_string (src); + size = strlen (str); + + gst_cmml_parser_parse_chunk (parser, str, size, NULL); + + gst_cmml_parser_free (parser); +} + +static void +set_object_on_value (GObject * tag, GValue * dest) +{ + g_value_take_object (dest, tag); +} |