summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>2009-12-10 19:53:19 (GMT)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>2009-12-14 11:41:48 (GMT)
commitc996ac4c53dbcfcea9a0c94d1503fc4d0a36d072 (patch)
tree72098cefdb7ecc40c4bf2ae99fa012ea6c5cb995
parent4111d6321f140eb7790620ab42e5cf1d9413b56a (diff)
downloadgst-plugins-bad-c996ac4c53dbcfcea9a0c94d1503fc4d0a36d072.tar.gz
gst-plugins-bad-c996ac4c53dbcfcea9a0c94d1503fc4d0a36d072.tar.xz
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 <ext-lasse.2.laukkanen@nokia.com>
-rw-r--r--gst/qtmux/fourcc.h1
-rw-r--r--gst/qtmux/gstqtmux.c126
-rw-r--r--gst/qtmux/gstqtmux.h8
3 files changed, 135 insertions, 0 deletions
diff --git a/gst/qtmux/fourcc.h b/gst/qtmux/fourcc.h
index c78bf80..647ab23 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 5162a9e..3824d25 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 9d92bc1..5f941a2 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__ */