qtdemux: parse stream tags

Keep global and stream tags separately and parse the udta node
that can be found under the trak atom. The udta will contain
stream specific tags and will be pushed as such

https://bugzilla.gnome.org/show_bug.cgi?id=692473
This commit is contained in:
Thiago Santos 2015-02-02 13:35:59 -03:00
parent e52b2cb2cf
commit 75dee31b0d

View file

@ -466,6 +466,8 @@ static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
const guint8 * buffer, guint length);
static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
GNode * udta);
static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
QtDemuxStream * stream, GNode * esds, GstTagList * list);
@ -2247,20 +2249,23 @@ qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
}
static void
qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist)
qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
GstTagList * xmptaglist)
{
/* Strip out bogus fields */
if (taglist) {
gst_tag_list_remove_tag (taglist, GST_TAG_VIDEO_CODEC);
if (xmptaglist) {
if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
} else {
gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
}
GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, taglist);
GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
if (qtdemux->tag_list) {
/* prioritize native tags using _KEEP mode */
gst_tag_list_insert (qtdemux->tag_list, taglist, GST_TAG_MERGE_KEEP);
gst_tag_list_unref (taglist);
} else
qtdemux->tag_list = taglist;
/* prioritize native tags using _KEEP mode */
gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
gst_tag_list_unref (xmptaglist);
}
}
@ -2297,7 +2302,7 @@ qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
taglist = gst_tag_list_from_xmp_buffer (buf);
gst_buffer_unref (buf);
qtdemux_handle_xmp_taglist (qtdemux, taglist);
qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
} else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
int len;
@ -7580,10 +7585,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
GNode *esds;
GNode *pasp;
GNode *tref;
GNode *udta;
QtDemuxStream *stream = NULL;
gboolean new_stream = FALSE;
GstTagList *list = NULL;
gchar *codec = NULL;
const guint8 *stsd_data;
guint16 lang_code; /* quicktime lang code or packed iso code */
@ -7621,6 +7626,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
}
if (stream->pending_tags == NULL)
stream->pending_tags = gst_tag_list_new_empty ();
if ((tkhd_flags & 1) == 0)
stream->disabled = TRUE;
@ -7789,7 +7797,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
stream->display_width = w >> 16;
stream->display_height = h >> 16;
qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix, &list);
qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
&stream->pending_tags);
offset = 16;
if (len < 86)
@ -7894,9 +7903,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
if (codec) {
if (list == NULL)
list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_VIDEO_CODEC, codec, NULL);
g_free (codec);
codec = NULL;
@ -7955,7 +7962,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
if (esds) {
gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
} else {
switch (fourcc) {
case FOURCC_H264:
@ -8046,15 +8053,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
max_bitrate = temp;
}
if (!list)
list = gst_tag_list_new_empty ();
if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
}
if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_BITRATE, avg_bitrate, NULL);
}
@ -8821,9 +8825,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
GstStructure *s;
gint bitrate = 0;
if (list == NULL)
list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_AUDIO_CODEC, codec, NULL);
g_free (codec);
codec = NULL;
@ -8832,8 +8834,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
s = gst_caps_get_structure (stream->caps, 0);
gst_structure_get_int (s, "bitrate", &bitrate);
if (bitrate > 0)
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
bitrate, NULL);
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_BITRATE, bitrate, NULL);
}
mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
@ -8903,7 +8905,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
g_node_destroy (wavenode);
}
} else if (esds) {
gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
} else {
switch (fourcc) {
#if 0
@ -8990,9 +8992,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
* the 3GPP container spec (26.244) for more details. */
if ((len - 0x34) > 8 &&
(bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
if (!list)
list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
}
@ -9063,8 +9063,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
stream->caps =
qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
if (codec) {
list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_SUBTITLE_CODEC, codec, NULL);
g_free (codec);
codec = NULL;
@ -9087,7 +9086,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
break;
}
gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags);
break;
}
default:
@ -9109,8 +9108,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
goto unknown_stream;
if (codec) {
list = gst_tag_list_new_empty ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_SUBTITLE_CODEC, codec, NULL);
g_free (codec);
codec = NULL;
@ -9168,21 +9166,22 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
strcmp (stream->lang_id, "und")) {
const gchar *lang_code;
if (!list)
list = gst_tag_list_new_empty ();
/* convert ISO 639-2 code to ISO 639-1 */
lang_code = gst_tag_get_language_code (stream->lang_id);
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
}
/* Check for UDTA tags */
if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
qtdemux_parse_udta (qtdemux, stream->pending_tags, udta);
}
/* now we are ready to add the stream */
if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
goto too_many_streams;
if (!qtdemux->got_moov) {
stream->pending_tags = list;
qtdemux->streams[qtdemux->n_streams] = stream;
qtdemux->n_streams++;
GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
@ -9521,8 +9520,8 @@ qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
}
static void
qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag,
const char *dummy, GNode * node)
qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
int offset;
@ -9549,7 +9548,7 @@ qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag,
"giving up", tag);
}
} else {
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
GST_TAG_GEO_LOCATION_NAME, name, NULL);
offset += strlen (name);
g_free (name);
@ -9572,7 +9571,7 @@ qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag,
/* one invalid means all are invalid */
if (longitude >= -180.0 && longitude <= 180.0 &&
latitude >= -90.0 && latitude <= 90.0) {
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
GST_TAG_GEO_LOCATION_LATITUDE, latitude,
GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
@ -9592,8 +9591,8 @@ short_read:
static void
qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy,
GNode * node)
qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
guint16 y;
GDate *date;
@ -9611,13 +9610,13 @@ qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy,
GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
date = g_date_new_dmy (1, 1, y);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, date, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
g_date_free (date);
}
static void
qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag,
const char *dummy, GNode * node)
qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
int offset;
char *tag_str = NULL;
@ -9656,8 +9655,7 @@ qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag,
memcpy (tag_str, entity, 4);
GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_APPEND, tag,
tag_str, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
g_free (tag_str);
@ -9672,8 +9670,8 @@ short_read:
}
static gboolean
qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag,
const char *dummy, GNode * node)
qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
GNode *data;
@ -9693,8 +9691,7 @@ qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag,
env_vars);
if (s) {
GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s,
NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
g_free (s);
} else {
GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
@ -9766,7 +9763,7 @@ qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag,
}
if (s) {
GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
g_free (s);
ret = TRUE;
} else {
@ -9777,15 +9774,15 @@ qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag,
}
static void
qtdemux_tag_add_str (GstQTDemux * qtdemux, const char *tag,
const char *dummy, GNode * node)
qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
qtdemux_tag_add_str_full (qtdemux, tag, dummy, node);
qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
}
static void
qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag,
const char *dummy, GNode * node)
qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
guint8 *data;
@ -9796,7 +9793,7 @@ qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag,
/* first try normal string tag if major brand not 3GP */
if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
if (!qtdemux_tag_add_str_full (qtdemux, tag, dummy, node)) {
if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
/* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
* let's try it 3gpp way after minor safety check */
data = node->data;
@ -9846,7 +9843,7 @@ qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag,
done:
if (k) {
GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, k, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
}
g_free (k);
@ -9861,8 +9858,8 @@ short_read:
}
static void
qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1,
const char *tag2, GNode * node)
qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag1, const char *tag2, GNode * node)
{
GNode *data;
int len;
@ -9878,21 +9875,19 @@ qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1,
n2 = QT_UINT16 ((guint8 *) data->data + 20);
if (n1 > 0) {
GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
tag1, n1, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
}
if (n2 > 0) {
GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
tag2, n2, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
}
}
}
}
static void
qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
GNode * node)
qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag1, const char *dummy, GNode * node)
{
GNode *data;
int len;
@ -9910,16 +9905,16 @@ qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
if (n1) {
/* do not add bpm=0 */
GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
tag1, (gdouble) n1, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
NULL);
}
}
}
}
static void
qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, const char *tag1,
const char *dummy, GNode * node)
qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag1, const char *dummy, GNode * node)
{
GNode *data;
int len;
@ -9937,16 +9932,15 @@ qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, const char *tag1,
if (num) {
/* do not add num=0 */
GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
tag1, num, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
}
}
}
}
static void
qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
GNode * node)
qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag1, const char *dummy, GNode * node)
{
GNode *data;
int len;
@ -9963,8 +9957,7 @@ qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
len - 16, GST_TAG_IMAGE_TYPE_NONE))) {
GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
tag1, sample, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
gst_sample_unref (sample);
}
}
@ -9972,8 +9965,8 @@ qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy,
}
static void
qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
GNode * node)
qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
GNode *data;
char *s;
@ -9995,8 +9988,7 @@ qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
GDate *date;
date = g_date_new_dmy (d, m, y);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag,
date, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
g_date_free (date);
} else {
GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
@ -10007,8 +9999,8 @@ qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy,
}
static void
qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
GNode * node)
qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
const char *tag, const char *dummy, GNode * node)
{
GNode *data;
@ -10018,7 +10010,7 @@ qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
* or no data atom and compatible brand suggests so */
if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
(qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
qtdemux_tag_add_str (qtdemux, tag, dummy, node);
qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
return;
}
@ -10035,8 +10027,7 @@ qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
genre = gst_tag_id3_genre_get (n - 1);
if (genre != NULL) {
GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE,
tag, genre, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
}
}
}
@ -10044,8 +10035,8 @@ qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy,
}
static void
qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag,
guint8 * data, guint32 datasize)
qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
const gchar * tag, guint8 * data, guint32 datasize)
{
gdouble value;
gchar *datacopy;
@ -10056,7 +10047,7 @@ qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag,
/* convert the str to double */
if (sscanf (datacopy, "%lf", &value) == 1) {
GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_REPLACE, tag, value, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
} else {
GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
datacopy);
@ -10066,8 +10057,8 @@ qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag,
static void
qtdemux_tag_add_revdns (GstQTDemux * demux, const char *tag,
const char *tag_bis, GNode * node)
qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
const char *tag, const char *tag_bis, GNode * node)
{
GNode *mean;
GNode *name;
@ -10157,11 +10148,11 @@ qtdemux_tag_add_revdns (GstQTDemux * demux, const char *tag,
if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
switch (gst_tag_get_type (tags[i].tag)) {
case G_TYPE_DOUBLE:
qtdemux_add_double_tag_from_str (demux, tags[i].tag,
qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
((guint8 *) data->data) + 16, datasize - 16);
break;
case G_TYPE_STRING:
qtdemux_tag_add_str (demux, tags[i].tag, NULL, node);
qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
break;
default:
/* not reached */
@ -10199,13 +10190,13 @@ unknown_tag:
}
static void
qtdemux_tag_add_id32 (GstQTDemux * demux, const char *tag,
qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
const char *tag_bis, GNode * node)
{
guint8 *data;
GstBuffer *buf;
guint len;
GstTagList *taglist = NULL;
GstTagList *id32_taglist = NULL;
GST_LOG_OBJECT (demux, "parsing ID32");
@ -10219,21 +10210,19 @@ qtdemux_tag_add_id32 (GstQTDemux * demux, const char *tag,
buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
gst_buffer_fill (buf, 0, data + 14, len - 14);
taglist = gst_tag_list_from_id3v2_tag (buf);
if (taglist) {
id32_taglist = gst_tag_list_from_id3v2_tag (buf);
if (id32_taglist) {
GST_LOG_OBJECT (demux, "parsing ok");
gst_tag_list_insert (demux->tag_list, taglist, GST_TAG_MERGE_KEEP);
gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
gst_tag_list_unref (id32_taglist);
} else {
GST_LOG_OBJECT (demux, "parsing failed");
}
if (taglist)
gst_tag_list_unref (taglist);
gst_buffer_unref (buf);
}
typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
const char *tag, const char *tag_bis, GNode * node);
/* unmapped tags
@ -10310,8 +10299,15 @@ static const struct
FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
};
struct _GstQtDemuxTagList
{
GstQTDemux *demux;
GstTagList *taglist;
};
typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
static void
qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
{
gint len;
guint8 *data;
@ -10322,6 +10318,8 @@ qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
GstStructure *s;
guint i;
guint8 ndata[4];
GstQTDemux *demux = qtdemuxtaglist->demux;
GstTagList *taglist = qtdemuxtaglist->taglist;
data = node->data;
len = QT_UINT32 (data);
@ -10359,20 +10357,24 @@ qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
len, s);
gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND,
gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
gst_sample_unref (sample);
}
static void
qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
{
GNode *meta;
GNode *ilst;
GNode *xmp_;
GNode *node;
gint i;
GstQtDemuxTagList demuxtaglist;
demuxtaglist.demux = qtdemux;
demuxtaglist.taglist = taglist;
meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
if (meta != NULL) {
@ -10386,14 +10388,6 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
}
GST_DEBUG_OBJECT (qtdemux, "new tag list");
if (!qtdemux->tag_list) {
qtdemux->tag_list = gst_tag_list_new_empty ();
gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
} else {
qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
}
i = 0;
while (i < G_N_ELEMENTS (add_funcs)) {
node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
@ -10405,7 +10399,7 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (add_funcs[i].fourcc));
} else {
add_funcs[i].func (qtdemux, add_funcs[i].gst_tag,
add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
add_funcs[i].gst_tag_bis, node);
}
g_node_destroy (node);
@ -10416,24 +10410,23 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
/* parsed nodes have been removed, pass along remainder as blob */
g_node_children_foreach (ilst, G_TRAVERSE_ALL,
(GNodeForeachFunc) qtdemux_tag_add_blob, qtdemux);
(GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
/* parse up XMP_ node if existing */
xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
if (xmp_ != NULL) {
GstBuffer *buf;
GstTagList *taglist;
GstTagList *xmptaglist;
buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
taglist = gst_tag_list_from_xmp_buffer (buf);
xmptaglist = gst_tag_list_from_xmp_buffer (buf);
gst_buffer_unref (buf);
qtdemux_handle_xmp_taglist (qtdemux, taglist);
qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
} else {
GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
}
}
typedef struct
@ -10747,10 +10740,18 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
}
if (!qtdemux->tag_list) {
GST_DEBUG_OBJECT (qtdemux, "new tag list");
qtdemux->tag_list = gst_tag_list_new_empty ();
gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
} else {
qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
}
/* find tags */
udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
if (udta) {
qtdemux_parse_udta (qtdemux, udta);
qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
} else {
GST_LOG_OBJECT (qtdemux, "No udta node found.");
}
@ -10759,7 +10760,7 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
if (udta) {
GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
qtdemux_parse_udta (qtdemux, udta);
qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
} else {
GST_LOG_OBJECT (qtdemux, "No meta node found.");
}