From c996ac4c53dbcfcea9a0c94d1503fc4d0a36d072 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 10 Dec 2009 16:53:19 -0300 Subject: [PATCH] qtmux: Maps 'classification' tag for 3gpp files Adds the mapping of 'classification' tags to writing of 'clsf' atoms for gppmux. Based on a patch by: Lasse Laukkanen --- gst/qtmux/fourcc.h | 1 + gst/qtmux/gstqtmux.c | 126 +++++++++++++++++++++++++++++++++++++++++++ gst/qtmux/gstqtmux.h | 8 +++ 3 files changed, 135 insertions(+) diff --git a/gst/qtmux/fourcc.h b/gst/qtmux/fourcc.h index c78bf80704..647ab231b2 100644 --- a/gst/qtmux/fourcc.h +++ b/gst/qtmux/fourcc.h @@ -195,6 +195,7 @@ G_BEGIN_DECLS #define FOURCC_albm GST_MAKE_FOURCC('a','l','b','m') #define FOURCC_loci GST_MAKE_FOURCC('l','o','c','i') #define FOURCC_kywd GST_MAKE_FOURCC('k','y','w','d') +#define FOURCC_clsf GST_MAKE_FOURCC('c','l','s','f') /* For Microsoft Wave formats embedded in quicktime, the FOURCC is 'm', 's', then the 16 bit wave codec id */ diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 5162a9eef2..3824d25aae 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -642,6 +642,118 @@ gst_qt_mux_add_3gp_keywords (GstQTMux * qtmux, const GstTagList * list, g_free (ddata); } +static gboolean +gst_qt_mux_parse_classification_string (GstQTMux * qtmux, const gchar * input, + guint32 * p_fourcc, guint16 * p_table, gchar ** p_content) +{ + guint32 fourcc; + gint table; + gint size; + const gchar *data; + + data = input; + size = strlen (input); + + if (size < 4 + 3 + 1 + 1 + 1) { + /* at least the minimum xxxx://y/z */ + GST_WARNING_OBJECT (qtmux, "Classification tag input (%s) too short, " + "ignoring", input); + return FALSE; + } + + /* read the fourcc */ + memcpy (&fourcc, data, 4); + size -= 4; + data += 4; + + if (strncmp (data, "://", 3) != 0) { + goto mismatch; + } + data += 3; + size -= 3; + + /* read the table number */ + if (sscanf (data, "%d", &table) != 1) { + goto mismatch; + } + if (table < 0) { + GST_WARNING_OBJECT (qtmux, "Invalid table number in classification tag (%d)" + ", table numbers should be positive, ignoring tag", table); + return FALSE; + } + + /* find the next / */ + while (size > 0 && data[0] != '/') { + data += 1; + size -= 1; + } + if (size == 0) { + goto mismatch; + } + g_assert (data[0] == '/'); + + /* skip the '/' */ + data += 1; + size -= 1; + if (size == 0) { + goto mismatch; + } + + /* read up the rest of the string */ + *p_content = g_strdup (data); + *p_table = (guint16) table; + *p_fourcc = fourcc; + return TRUE; + +mismatch: + { + GST_WARNING_OBJECT (qtmux, "Ignoring classification tag as " + "input (%s) didn't match the expected entitycode://table/content", + input); + return FALSE; + } +} + +static void +gst_qt_mux_add_3gp_classification (GstQTMux * qtmux, const GstTagList * list, + const char *tag, const char *tag2, guint32 fourcc) +{ + gchar *clsf_data = NULL; + gint size = 0; + guint32 entity = 0; + guint16 table = 0; + gchar *content = NULL; + guint8 *data; + + g_return_if_fail (strcmp (tag, GST_TAG_3GP_CLASSIFICATION) == 0); + + if (!gst_tag_list_get_string (list, tag, &clsf_data) || !clsf_data) + return; + + GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s", + GST_FOURCC_ARGS (fourcc), clsf_data); + + /* parse the string, format is: + * entityfourcc://table/content + */ + gst_qt_mux_parse_classification_string (qtmux, clsf_data, &entity, &table, + &content); + g_free (clsf_data); + /* +1 for the \0 */ + size = strlen (content) + 1; + + /* now we have everything, build the atom + * atom description is at 3GPP TS 26.244 V8.2.0 (2009-09) */ + data = g_malloc (4 + 2 + 2 + size); + GST_WRITE_UINT32_LE (data, entity); + GST_WRITE_UINT16_BE (data + 4, (guint16) table); + GST_WRITE_UINT16_BE (data + 6, 0); + memcpy (data + 8, content, size); + g_free (content); + + atom_moov_add_3gp_tag (qtmux->moov, fourcc, data, 4 + 2 + 2 + size); + g_free (data); +} typedef void (*GstQTMuxAddTagFunc) (GstQTMux * mux, const GstTagList * list, const char *tag, const char *tag2, guint32 fourcc); @@ -690,6 +802,8 @@ static const GstTagToFourcc tag_matches_3gp[] = { {FOURCC_yrrc, GST_TAG_DATE, NULL, gst_qt_mux_add_3gp_date}, {FOURCC_albm, GST_TAG_ALBUM, GST_TAG_TRACK_NUMBER, gst_qt_mux_add_3gp_str}, {FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, gst_qt_mux_add_3gp_location}, + {FOURCC_clsf, GST_TAG_3GP_CLASSIFICATION, NULL, + gst_qt_mux_add_3gp_classification}, {0, NULL,} }; @@ -2312,6 +2426,18 @@ gst_qt_mux_register (GstPlugin * plugin) GST_LOG ("Finished registering muxers"); + /* FIXME: ideally classification tag should be added and + registered in gstreamer core gsttaglist + */ + + GST_LOG ("Registering tags"); + + gst_tag_register (GST_TAG_3GP_CLASSIFICATION, GST_TAG_FLAG_META, + G_TYPE_STRING, GST_TAG_3GP_CLASSIFICATION, "content classification", + gst_tag_merge_use_first); + + GST_LOG ("Finished registering tags"); + return TRUE; } diff --git a/gst/qtmux/gstqtmux.h b/gst/qtmux/gstqtmux.h index 9d92bc1d42..5f941a2633 100644 --- a/gst/qtmux/gstqtmux.h +++ b/gst/qtmux/gstqtmux.h @@ -159,6 +159,14 @@ typedef struct _GstQTMuxClassParams GType gst_qt_mux_get_type (void); +/* FIXME: ideally classification tag should be added and + * registered in gstreamer core gsttaglist + * + * this tag is a string in the format: entityfourcc://table_num/content + * FIXME Shouldn't we add a field for 'language'? + */ +#define GST_TAG_3GP_CLASSIFICATION "classification" + G_END_DECLS #endif /* __GST_QT_MUX_H__ */