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>
This commit is contained in:
Thiago Santos 2009-12-10 16:53:19 -03:00
parent 4111d6321f
commit c996ac4c53
3 changed files with 135 additions and 0 deletions

View file

@ -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 */

View file

@ -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;
}

View file

@ -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__ */