73381baf615d3a9bc829d2b5b96ec2f81d06ed19
[platform/upstream/gst-plugins-good.git] / gst / matroska / matroska-read-common.c
1 /* GStreamer Matroska muxer/demuxer
2  * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  * (c) 2006 Tim-Philipp Müller <tim centricular net>
4  * (c) 2008 Sebastian Dröge <slomo@circular-chaos.org>
5  * (c) 2011 Debarshi Ray <rishi@gnu.org>
6  *
7  * matroska-read-common.c: shared by matroska file/stream demuxer and parser
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <stdio.h>
30 #include <string.h>
31
32 #ifdef HAVE_ZLIB
33 #include <zlib.h>
34 #endif
35
36 #ifdef HAVE_BZ2
37 #include <bzlib.h>
38 #endif
39
40 #include <gst/tag/tag.h>
41 #include <gst/base/gsttypefindhelper.h>
42
43 #include "lzo.h"
44
45 #include "ebml-read.h"
46 #include "matroska-read-common.h"
47 #include "matroska-ids.h"
48
49 GST_DEBUG_CATEGORY (matroskareadcommon_debug);
50 #define GST_CAT_DEFAULT matroskareadcommon_debug
51
52 #define DEBUG_ELEMENT_START(common, ebml, element) \
53     GST_DEBUG_OBJECT (common, "Parsing " element " element at offset %" \
54         G_GUINT64_FORMAT, gst_ebml_read_get_pos (ebml))
55
56 #define DEBUG_ELEMENT_STOP(common, ebml, element, ret) \
57     GST_DEBUG_OBJECT (common, "Parsing " element " element " \
58         " finished with '%s'", gst_flow_get_name (ret))
59
60 #define GST_MATROSKA_TOC_UID_CHAPTER "chapter"
61 #define GST_MATROSKA_TOC_UID_EDITION "edition"
62 #define GST_MATROSKA_TOC_UID_EMPTY "empty"
63
64 typedef struct
65 {
66   GstTagList *result;
67   guint64 target_type_value;
68   gchar *target_type;
69   gboolean audio_only;
70 } TargetTypeContext;
71
72
73 static gboolean
74 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
75     gpointer * data_out, gsize * size_out,
76     GstMatroskaTrackCompressionAlgorithm algo)
77 {
78   guint8 *new_data = NULL;
79   guint new_size = 0;
80   guint8 *data = *data_out;
81   guint size = *size_out;
82   gboolean ret = TRUE;
83
84   if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
85 #ifdef HAVE_ZLIB
86     /* zlib encoded data */
87     z_stream zstream;
88     guint orig_size;
89     int result;
90
91     orig_size = size;
92     zstream.zalloc = (alloc_func) 0;
93     zstream.zfree = (free_func) 0;
94     zstream.opaque = (voidpf) 0;
95     if (inflateInit (&zstream) != Z_OK) {
96       GST_WARNING ("zlib initialization failed.");
97       ret = FALSE;
98       goto out;
99     }
100     zstream.next_in = (Bytef *) data;
101     zstream.avail_in = orig_size;
102     new_size = orig_size;
103     new_data = g_malloc (new_size);
104     zstream.avail_out = new_size;
105     zstream.next_out = (Bytef *) new_data;
106
107     do {
108       result = inflate (&zstream, Z_NO_FLUSH);
109       if (result != Z_OK && result != Z_STREAM_END) {
110         GST_WARNING ("zlib decompression failed.");
111         g_free (new_data);
112         inflateEnd (&zstream);
113         break;
114       }
115       new_size += 4000;
116       new_data = g_realloc (new_data, new_size);
117       zstream.next_out = (Bytef *) (new_data + zstream.total_out);
118       zstream.avail_out += 4000;
119     } while (zstream.avail_in != 0 && result != Z_STREAM_END);
120
121     if (result != Z_STREAM_END) {
122       ret = FALSE;
123       goto out;
124     } else {
125       new_size = zstream.total_out;
126       inflateEnd (&zstream);
127     }
128 #else
129     GST_WARNING ("zlib encoded tracks not supported.");
130     ret = FALSE;
131     goto out;
132 #endif
133   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_BZLIB) {
134 #ifdef HAVE_BZ2
135     /* bzip2 encoded data */
136     bz_stream bzstream;
137     guint orig_size;
138     int result;
139
140     bzstream.bzalloc = NULL;
141     bzstream.bzfree = NULL;
142     bzstream.opaque = NULL;
143     orig_size = size;
144
145     if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
146       GST_WARNING ("bzip2 initialization failed.");
147       ret = FALSE;
148       goto out;
149     }
150
151     bzstream.next_in = (char *) data;
152     bzstream.avail_in = orig_size;
153     new_size = orig_size;
154     new_data = g_malloc (new_size);
155     bzstream.avail_out = new_size;
156     bzstream.next_out = (char *) new_data;
157
158     do {
159       result = BZ2_bzDecompress (&bzstream);
160       if (result != BZ_OK && result != BZ_STREAM_END) {
161         GST_WARNING ("bzip2 decompression failed.");
162         g_free (new_data);
163         BZ2_bzDecompressEnd (&bzstream);
164         break;
165       }
166       new_size += 4000;
167       new_data = g_realloc (new_data, new_size);
168       bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
169       bzstream.avail_out += 4000;
170     } while (bzstream.avail_in != 0 && result != BZ_STREAM_END);
171
172     if (result != BZ_STREAM_END) {
173       ret = FALSE;
174       goto out;
175     } else {
176       new_size = bzstream.total_out_lo32;
177       BZ2_bzDecompressEnd (&bzstream);
178     }
179 #else
180     GST_WARNING ("bzip2 encoded tracks not supported.");
181     ret = FALSE;
182     goto out;
183 #endif
184   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
185     /* lzo encoded data */
186     int result;
187     int orig_size, out_size;
188
189     orig_size = size;
190     out_size = size;
191     new_size = size;
192     new_data = g_malloc (new_size);
193
194     do {
195       orig_size = size;
196       out_size = new_size;
197
198       result = lzo1x_decode (new_data, &out_size, data, &orig_size);
199
200       if (orig_size > 0) {
201         new_size += 4000;
202         new_data = g_realloc (new_data, new_size);
203       }
204     } while (orig_size > 0 && result == LZO_OUTPUT_FULL);
205
206     new_size -= out_size;
207
208     if (result != LZO_OUTPUT_FULL) {
209       GST_WARNING ("lzo decompression failed");
210       g_free (new_data);
211
212       ret = FALSE;
213       goto out;
214     }
215
216   } else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
217     /* header stripped encoded data */
218     if (enc->comp_settings_length > 0) {
219       new_data = g_malloc (size + enc->comp_settings_length);
220       new_size = size + enc->comp_settings_length;
221
222       memcpy (new_data, enc->comp_settings, enc->comp_settings_length);
223       memcpy (new_data + enc->comp_settings_length, data, size);
224     }
225   } else {
226     GST_ERROR ("invalid compression algorithm %d", algo);
227     ret = FALSE;
228   }
229
230 out:
231
232   if (!ret) {
233     *data_out = NULL;
234     *size_out = 0;
235   } else {
236     *data_out = new_data;
237     *size_out = new_size;
238   }
239
240   return ret;
241 }
242
243 GstFlowReturn
244 gst_matroska_decode_content_encodings (GArray * encodings)
245 {
246   gint i;
247
248   if (encodings == NULL)
249     return GST_FLOW_OK;
250
251   for (i = 0; i < encodings->len; i++) {
252     GstMatroskaTrackEncoding *enc =
253         &g_array_index (encodings, GstMatroskaTrackEncoding, i);
254     gpointer data = NULL;
255     gsize size;
256
257     if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
258         == 0)
259       continue;
260
261     /* Encryption not supported yet */
262     if (enc->type != 0)
263       return GST_FLOW_ERROR;
264
265     if (i + 1 >= encodings->len)
266       return GST_FLOW_ERROR;
267
268     if (enc->comp_settings_length == 0)
269       continue;
270
271     data = enc->comp_settings;
272     size = enc->comp_settings_length;
273
274     if (!gst_matroska_decompress_data (enc, &data, &size, enc->comp_algo))
275       return GST_FLOW_ERROR;
276
277     g_free (enc->comp_settings);
278
279     enc->comp_settings = data;
280     enc->comp_settings_length = size;
281   }
282
283   return GST_FLOW_OK;
284 }
285
286 gboolean
287 gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
288     gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
289 {
290   gpointer data;
291   gsize size;
292   gboolean ret = TRUE;
293   gint i;
294
295   g_return_val_if_fail (encodings != NULL, FALSE);
296   g_return_val_if_fail (data_out != NULL && *data_out != NULL, FALSE);
297   g_return_val_if_fail (size_out != NULL, FALSE);
298
299   data = *data_out;
300   size = *size_out;
301
302   for (i = 0; i < encodings->len; i++) {
303     GstMatroskaTrackEncoding *enc =
304         &g_array_index (encodings, GstMatroskaTrackEncoding, i);
305     gpointer new_data = NULL;
306     gsize new_size = 0;
307
308     if ((enc->scope & scope) == 0)
309       continue;
310
311     /* Encryption not supported yet */
312     if (enc->type != 0) {
313       ret = FALSE;
314       break;
315     }
316
317     new_data = data;
318     new_size = size;
319
320     ret =
321         gst_matroska_decompress_data (enc, &new_data, &new_size,
322         enc->comp_algo);
323
324     if (!ret)
325       break;
326
327     if ((data == *data_out && free) || (data != *data_out))
328       g_free (data);
329
330     data = new_data;
331     size = new_size;
332   }
333
334   if (!ret) {
335     if ((data == *data_out && free) || (data != *data_out))
336       g_free (data);
337
338     *data_out = NULL;
339     *size_out = 0;
340   } else {
341     *data_out = data;
342     *size_out = size;
343   }
344
345   return ret;
346 }
347
348 static gint
349 gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2)
350 {
351   if (i1->time < i2->time)
352     return -1;
353   else if (i1->time > i2->time)
354     return 1;
355   else if (i1->block < i2->block)
356     return -1;
357   else if (i1->block > i2->block)
358     return 1;
359   else
360     return 0;
361 }
362
363 gint
364 gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
365     gpointer user_data)
366 {
367   if (i1->time < *time)
368     return -1;
369   else if (i1->time > *time)
370     return 1;
371   else
372     return 0;
373 }
374
375 GstMatroskaIndex *
376 gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
377     GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
378     gint * _entry_index, gboolean next)
379 {
380   GstMatroskaIndex *entry = NULL;
381   GArray *index;
382
383   if (!common->index || !common->index->len)
384     return NULL;
385
386   /* find entry just before or at the requested position */
387   if (track && track->index_table)
388     index = track->index_table;
389   else
390     index = common->index;
391
392   entry =
393       gst_util_array_binary_search (index->data, index->len,
394       sizeof (GstMatroskaIndex),
395       (GCompareDataFunc) gst_matroska_index_seek_find,
396       next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE, &seek_pos, NULL);
397
398   if (entry == NULL) {
399     if (next) {
400       return NULL;
401     } else {
402       entry = &g_array_index (index, GstMatroskaIndex, 0);
403     }
404   }
405
406   if (_index)
407     *_index = index;
408   if (_entry_index)
409     *_entry_index = entry - (GstMatroskaIndex *) index->data;
410
411   return entry;
412 }
413
414 static gint
415 gst_matroska_read_common_encoding_cmp (GstMatroskaTrackEncoding * a,
416     GstMatroskaTrackEncoding * b)
417 {
418   if (b->order > a->order)
419     return 1;
420   else if (b->order < a->order)
421     return -1;
422   else
423     return 0;
424 }
425
426 static gboolean
427 gst_matroska_read_common_encoding_order_unique (GArray * encodings, guint64
428     order)
429 {
430   gint i;
431
432   if (encodings == NULL || encodings->len == 0)
433     return TRUE;
434
435   for (i = 0; i < encodings->len; i++)
436     if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order)
437       return FALSE;
438
439   return TRUE;
440 }
441
442 /* takes ownership of taglist */
443 void
444 gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
445     GstElement * el, GstTagList * taglist)
446 {
447   if (common->global_tags) {
448     /* nothing sent yet, add to cache */
449     gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
450     gst_tag_list_unref (taglist);
451   } else {
452     GstEvent *tag_event = gst_event_new_tag (taglist);
453     gint i;
454
455     /* hm, already sent, no need to cache and wait anymore */
456     GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT,
457         taglist);
458
459     for (i = 0; i < common->src->len; i++) {
460       GstMatroskaTrackContext *stream;
461
462       stream = g_ptr_array_index (common->src, i);
463       gst_pad_push_event (stream->pad, gst_event_ref (tag_event));
464     }
465
466     gst_event_unref (tag_event);
467   }
468 }
469
470 gint64
471 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
472 {
473   gint64 end = -1;
474
475   if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
476           &end) || end < 0)
477     GST_DEBUG_OBJECT (common, "no upstream length");
478
479   return end;
480 }
481
482 /* determine track to seek in */
483 GstMatroskaTrackContext *
484 gst_matroska_read_common_get_seek_track (GstMatroskaReadCommon * common,
485     GstMatroskaTrackContext * track)
486 {
487   gint i;
488
489   if (track && track->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
490     return track;
491
492   for (i = 0; i < common->src->len; i++) {
493     GstMatroskaTrackContext *stream;
494
495     stream = g_ptr_array_index (common->src, i);
496     if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && stream->index_table)
497       track = stream;
498   }
499
500   return track;
501 }
502
503 /* skip unknown or alike element */
504 GstFlowReturn
505 gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common,
506     GstEbmlRead * ebml, const gchar * parent_name, guint id)
507 {
508   if (id == GST_EBML_ID_VOID) {
509     GST_DEBUG_OBJECT (common, "Skipping EBML Void element");
510   } else if (id == GST_EBML_ID_CRC32) {
511     GST_DEBUG_OBJECT (common, "Skipping EBML CRC32 element");
512   } else {
513     GST_WARNING_OBJECT (common,
514         "Unknown %s subelement 0x%x - ignoring", parent_name, id);
515   }
516
517   return gst_ebml_read_skip (ebml);
518 }
519
520 static GstFlowReturn
521 gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
522     GstEbmlRead * ebml, GstTagList * taglist)
523 {
524   guint32 id;
525   GstFlowReturn ret;
526   gchar *description = NULL;
527   gchar *filename = NULL;
528   gchar *mimetype = NULL;
529   guint8 *data = NULL;
530   guint64 datalen = 0;
531
532   DEBUG_ELEMENT_START (common, ebml, "AttachedFile");
533
534   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
535     DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
536     return ret;
537   }
538
539   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
540     /* read all sub-entries */
541
542     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
543       break;
544
545     switch (id) {
546       case GST_MATROSKA_ID_FILEDESCRIPTION:
547         if (description) {
548           GST_WARNING_OBJECT (common, "FileDescription can only appear once");
549           break;
550         }
551
552         ret = gst_ebml_read_utf8 (ebml, &id, &description);
553         GST_DEBUG_OBJECT (common, "FileDescription: %s",
554             GST_STR_NULL (description));
555         break;
556       case GST_MATROSKA_ID_FILENAME:
557         if (filename) {
558           GST_WARNING_OBJECT (common, "FileName can only appear once");
559           break;
560         }
561
562         ret = gst_ebml_read_utf8 (ebml, &id, &filename);
563
564         GST_DEBUG_OBJECT (common, "FileName: %s", GST_STR_NULL (filename));
565         break;
566       case GST_MATROSKA_ID_FILEMIMETYPE:
567         if (mimetype) {
568           GST_WARNING_OBJECT (common, "FileMimeType can only appear once");
569           break;
570         }
571
572         ret = gst_ebml_read_ascii (ebml, &id, &mimetype);
573         GST_DEBUG_OBJECT (common, "FileMimeType: %s", GST_STR_NULL (mimetype));
574         break;
575       case GST_MATROSKA_ID_FILEDATA:
576         if (data) {
577           GST_WARNING_OBJECT (common, "FileData can only appear once");
578           break;
579         }
580
581         ret = gst_ebml_read_binary (ebml, &id, &data, &datalen);
582         GST_DEBUG_OBJECT (common, "FileData of size %" G_GUINT64_FORMAT,
583             datalen);
584         break;
585
586       default:
587         ret = gst_matroska_read_common_parse_skip (common, ebml,
588             "AttachedFile", id);
589         break;
590       case GST_MATROSKA_ID_FILEUID:
591         ret = gst_ebml_read_skip (ebml);
592         break;
593     }
594   }
595
596   DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret);
597
598   if (filename && mimetype && data && datalen > 0) {
599     GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
600     GstBuffer *tagbuffer = NULL;
601     GstSample *tagsample = NULL;
602     GstStructure *info = NULL;
603     GstCaps *caps = NULL;
604     gchar *filename_lc = g_utf8_strdown (filename, -1);
605
606     GST_DEBUG_OBJECT (common, "Creating tag for attachment with "
607         "filename '%s', mimetype '%s', description '%s', "
608         "size %" G_GUINT64_FORMAT, filename, mimetype,
609         GST_STR_NULL (description), datalen);
610
611     /* TODO: better heuristics for different image types */
612     if (strstr (filename_lc, "cover")) {
613       if (strstr (filename_lc, "back"))
614         image_type = GST_TAG_IMAGE_TYPE_BACK_COVER;
615       else
616         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
617     } else if (g_str_has_prefix (mimetype, "image/") ||
618         g_str_has_suffix (filename_lc, "png") ||
619         g_str_has_suffix (filename_lc, "jpg") ||
620         g_str_has_suffix (filename_lc, "jpeg") ||
621         g_str_has_suffix (filename_lc, "gif") ||
622         g_str_has_suffix (filename_lc, "bmp")) {
623       image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
624     }
625     g_free (filename_lc);
626
627     /* First try to create an image tag buffer from this */
628     if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
629       tagsample =
630           gst_tag_image_data_to_image_sample (data, datalen, image_type);
631
632       if (!tagsample)
633         image_type = GST_TAG_IMAGE_TYPE_NONE;
634       else {
635         data = NULL;
636         tagbuffer = gst_buffer_ref (gst_sample_get_buffer (tagsample));
637         caps = gst_caps_ref (gst_sample_get_caps (tagsample));
638         info = gst_structure_copy (gst_sample_get_info (tagsample));
639         gst_sample_unref (tagsample);
640       }
641     }
642
643     /* if this failed create an attachment buffer */
644     if (!tagbuffer) {
645       tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
646
647       caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
648       if (caps == NULL)
649         caps = gst_caps_new_empty_simple (mimetype);
650     }
651
652     /* Set filename and description in the info */
653     if (info == NULL)
654       info = gst_structure_new_empty ("GstTagImageInfo");
655
656     gst_structure_set (info, "filename", G_TYPE_STRING, filename, NULL);
657     if (description)
658       gst_structure_set (info, "description", G_TYPE_STRING, description, NULL);
659
660     tagsample = gst_sample_new (tagbuffer, caps, NULL, info);
661
662     gst_buffer_unref (tagbuffer);
663     gst_caps_unref (caps);
664
665     GST_DEBUG_OBJECT (common,
666         "Created attachment sample: %" GST_PTR_FORMAT, tagsample);
667
668     /* and append to the tag list */
669     if (image_type != GST_TAG_IMAGE_TYPE_NONE)
670       gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagsample,
671           NULL);
672     else
673       gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
674           tagsample, NULL);
675
676     /* the list adds it own ref */
677     gst_sample_unref (tagsample);
678   }
679
680   g_free (filename);
681   g_free (mimetype);
682   g_free (data);
683   g_free (description);
684
685   return ret;
686 }
687
688 GstFlowReturn
689 gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
690     GstElement * el, GstEbmlRead * ebml)
691 {
692   guint32 id;
693   GstFlowReturn ret = GST_FLOW_OK;
694   GstTagList *taglist;
695
696   DEBUG_ELEMENT_START (common, ebml, "Attachments");
697
698   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
699     DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
700     return ret;
701   }
702
703   taglist = gst_tag_list_new_empty ();
704   gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
705
706   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
707     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
708       break;
709
710     switch (id) {
711       case GST_MATROSKA_ID_ATTACHEDFILE:
712         ret = gst_matroska_read_common_parse_attached_file (common, ebml,
713             taglist);
714         break;
715
716       default:
717         ret = gst_matroska_read_common_parse_skip (common, ebml,
718             "Attachments", id);
719         break;
720     }
721   }
722   DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret);
723
724   if (gst_tag_list_n_tags (taglist) > 0) {
725     GST_DEBUG_OBJECT (common, "Storing attachment tags");
726     gst_matroska_read_common_found_global_tag (common, el, taglist);
727   } else {
728     GST_DEBUG_OBJECT (common, "No valid attachments found");
729     gst_tag_list_unref (taglist);
730   }
731
732   common->attachments_parsed = TRUE;
733
734   return ret;
735 }
736
737 static void
738 gst_matroska_read_common_parse_toc_tag (GstTocEntry * entry,
739     GArray * edition_targets, GArray * chapter_targtes, GstTagList * tags)
740 {
741   gchar *uid;
742   guint i;
743   guint64 tgt;
744   GArray *targets;
745   GList *cur;
746   GstTagList *etags;
747
748   targets =
749       (gst_toc_entry_get_entry_type (entry) ==
750       GST_TOC_ENTRY_TYPE_EDITION) ? edition_targets : chapter_targtes;
751
752   etags = gst_tag_list_new_empty ();
753
754   for (i = 0; i < targets->len; ++i) {
755     tgt = g_array_index (targets, guint64, i);
756
757     if (tgt == 0)
758       gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
759     else {
760       uid = g_strdup_printf ("%" G_GUINT64_FORMAT, tgt);
761       if (g_strcmp0 (gst_toc_entry_get_uid (entry), uid) == 0)
762         gst_tag_list_insert (etags, tags, GST_TAG_MERGE_APPEND);
763       g_free (uid);
764     }
765   }
766
767   gst_toc_entry_merge_tags (entry, etags, GST_TAG_MERGE_APPEND);
768
769   cur = gst_toc_entry_get_sub_entries (entry);
770   while (cur != NULL) {
771     gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
772         chapter_targtes, tags);
773     cur = cur->next;
774   }
775 }
776
777 static GstFlowReturn
778 gst_matroska_read_common_parse_metadata_targets (GstMatroskaReadCommon * common,
779     GstEbmlRead * ebml, GArray * edition_targets, GArray * chapter_targets,
780     GArray * track_targets, guint64 * target_type_value, gchar ** target_type)
781 {
782   GstFlowReturn ret = GST_FLOW_OK;
783   guint32 id;
784   guint64 uid;
785   guint64 tmp;
786   gchar *str;
787
788   DEBUG_ELEMENT_START (common, ebml, "TagTargets");
789
790   *target_type_value = 50;
791   *target_type = NULL;
792
793   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
794     DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
795     return ret;
796   }
797
798   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
799     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
800       break;
801
802     switch (id) {
803       case GST_MATROSKA_ID_TARGETCHAPTERUID:
804         if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
805           g_array_append_val (chapter_targets, uid);
806         break;
807
808       case GST_MATROSKA_ID_TARGETEDITIONUID:
809         if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
810           g_array_append_val (edition_targets, uid);
811         break;
812
813       case GST_MATROSKA_ID_TARGETTRACKUID:
814         if ((ret = gst_ebml_read_uint (ebml, &id, &uid)) == GST_FLOW_OK)
815           g_array_append_val (track_targets, uid);
816         break;
817
818       case GST_MATROSKA_ID_TARGETTYPEVALUE:
819         if ((ret = gst_ebml_read_uint (ebml, &id, &tmp)) == GST_FLOW_OK)
820           *target_type_value = tmp;
821         break;
822
823       case GST_MATROSKA_ID_TARGETTYPE:
824         if ((ret = gst_ebml_read_ascii (ebml, &id, &str)) == GST_FLOW_OK) {
825           if (*target_type != NULL)
826             g_free (*target_type);
827           *target_type = str;
828         }
829         break;
830
831       default:
832         ret =
833             gst_matroska_read_common_parse_skip (common, ebml, "TagTargets",
834             id);
835         break;
836     }
837   }
838
839   DEBUG_ELEMENT_STOP (common, ebml, "TagTargets", ret);
840
841   return ret;
842 }
843
844 static void
845 gst_matroska_read_common_postprocess_toc_entries (GList * toc_entries,
846     guint64 max, const gchar * parent_uid)
847 {
848   GstTocEntry *cur_info, *prev_info, *next_info;
849   GList *cur_list, *prev_list, *next_list;
850   gint64 cur_start, prev_start, stop;
851
852   cur_list = toc_entries;
853   while (cur_list != NULL) {
854     cur_info = cur_list->data;
855
856     switch (gst_toc_entry_get_entry_type (cur_info)) {
857       case GST_TOC_ENTRY_TYPE_ANGLE:
858       case GST_TOC_ENTRY_TYPE_VERSION:
859       case GST_TOC_ENTRY_TYPE_EDITION:
860         /* in Matroska terms edition has duration of full track */
861         gst_toc_entry_set_start_stop_times (cur_info, 0, max);
862
863         gst_matroska_read_common_postprocess_toc_entries
864             (gst_toc_entry_get_sub_entries (cur_info), max,
865             gst_toc_entry_get_uid (cur_info));
866         break;
867
868       case GST_TOC_ENTRY_TYPE_TITLE:
869       case GST_TOC_ENTRY_TYPE_TRACK:
870       case GST_TOC_ENTRY_TYPE_CHAPTER:
871         prev_list = cur_list->prev;
872         next_list = cur_list->next;
873
874         if (prev_list != NULL)
875           prev_info = prev_list->data;
876         else
877           prev_info = NULL;
878
879         if (next_list != NULL)
880           next_info = next_list->data;
881         else
882           next_info = NULL;
883
884         /* updated stop time in previous chapter and it's subchapters */
885         if (prev_info != NULL) {
886           gst_toc_entry_get_start_stop_times (prev_info, &prev_start, &stop);
887           gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
888
889           stop = cur_start;
890           gst_toc_entry_set_start_stop_times (prev_info, prev_start, stop);
891
892           gst_matroska_read_common_postprocess_toc_entries
893               (gst_toc_entry_get_sub_entries (prev_info), cur_start,
894               gst_toc_entry_get_uid (prev_info));
895         }
896
897         /* updated stop time in current chapter and it's subchapters */
898         if (next_info == NULL) {
899           gst_toc_entry_get_start_stop_times (cur_info, &cur_start, &stop);
900
901           if (stop == -1) {
902             stop = max;
903             gst_toc_entry_set_start_stop_times (cur_info, cur_start, stop);
904           }
905
906           gst_matroska_read_common_postprocess_toc_entries
907               (gst_toc_entry_get_sub_entries (cur_info), stop,
908               gst_toc_entry_get_uid (cur_info));
909         }
910         break;
911       case GST_TOC_ENTRY_TYPE_INVALID:
912         break;
913     }
914     cur_list = cur_list->next;
915   }
916 }
917
918 static GstFlowReturn
919 gst_matroska_read_common_parse_chapter_titles (GstMatroskaReadCommon * common,
920     GstEbmlRead * ebml, GstTagList * titles)
921 {
922   guint32 id;
923   gchar *title = NULL;
924   GstFlowReturn ret = GST_FLOW_OK;
925
926   DEBUG_ELEMENT_START (common, ebml, "ChaptersTitles");
927
928
929   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
930     DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
931     return ret;
932   }
933
934   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
935     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
936       break;
937
938     switch (id) {
939       case GST_MATROSKA_ID_CHAPSTRING:
940         ret = gst_ebml_read_utf8 (ebml, &id, &title);
941         break;
942
943       default:
944         ret =
945             gst_matroska_read_common_parse_skip (common, ebml, "ChaptersTitles",
946             id);
947         break;
948     }
949   }
950
951   DEBUG_ELEMENT_STOP (common, ebml, "ChaptersTitles", ret);
952
953   if (title != NULL && ret == GST_FLOW_OK)
954     gst_tag_list_add (titles, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, title, NULL);
955
956   g_free (title);
957   return ret;
958 }
959
960 static GstFlowReturn
961 gst_matroska_read_common_parse_chapter_element (GstMatroskaReadCommon * common,
962     GstEbmlRead * ebml, GList ** subentries)
963 {
964   guint32 id;
965   guint64 start_time = -1, stop_time = -1;
966   guint64 is_hidden = 0, is_enabled = 1, uid = 0;
967   GstFlowReturn ret = GST_FLOW_OK;
968   GstTocEntry *chapter_info;
969   GstTagList *tags;
970   gchar *uid_str;
971   GList *subsubentries = NULL, *l;
972
973   DEBUG_ELEMENT_START (common, ebml, "ChaptersElement");
974
975   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
976     DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
977     return ret;
978   }
979
980   tags = gst_tag_list_new_empty ();
981
982   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
983     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
984       break;
985
986     switch (id) {
987       case GST_MATROSKA_ID_CHAPTERUID:
988         ret = gst_ebml_read_uint (ebml, &id, &uid);
989         break;
990
991       case GST_MATROSKA_ID_CHAPTERTIMESTART:
992         ret = gst_ebml_read_uint (ebml, &id, &start_time);
993         break;
994
995       case GST_MATROSKA_ID_CHAPTERTIMESTOP:
996         ret = gst_ebml_read_uint (ebml, &id, &stop_time);
997         break;
998
999       case GST_MATROSKA_ID_CHAPTERATOM:
1000         ret =
1001             gst_matroska_read_common_parse_chapter_element (common, ebml,
1002             &subsubentries);
1003         break;
1004
1005       case GST_MATROSKA_ID_CHAPTERDISPLAY:
1006         ret =
1007             gst_matroska_read_common_parse_chapter_titles (common, ebml, tags);
1008         break;
1009
1010       case GST_MATROSKA_ID_CHAPTERFLAGHIDDEN:
1011         ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1012         break;
1013
1014       case GST_MATROSKA_ID_CHAPTERFLAGENABLED:
1015         ret = gst_ebml_read_uint (ebml, &id, &is_enabled);
1016         break;
1017
1018       default:
1019         ret =
1020             gst_matroska_read_common_parse_skip (common, ebml,
1021             "ChaptersElement", id);
1022         break;
1023     }
1024   }
1025
1026   if (uid == 0)
1027     uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1028   uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1029   chapter_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_CHAPTER, uid_str);
1030   g_free (uid_str);
1031
1032   gst_toc_entry_set_tags (chapter_info, tags);
1033   gst_toc_entry_set_start_stop_times (chapter_info, start_time, stop_time);
1034
1035   for (l = subsubentries; l; l = l->next)
1036     gst_toc_entry_append_sub_entry (chapter_info, l->data);
1037   g_list_free (subsubentries);
1038
1039   DEBUG_ELEMENT_STOP (common, ebml, "ChaptersElement", ret);
1040
1041   /* start time is mandatory and has no default value,
1042    * so we should skip chapters without it */
1043   if (is_hidden == 0 && is_enabled > 0 &&
1044       start_time != -1 && ret == GST_FLOW_OK) {
1045     *subentries = g_list_append (*subentries, chapter_info);
1046   } else
1047     gst_toc_entry_unref (chapter_info);
1048
1049   return ret;
1050 }
1051
1052 static GstFlowReturn
1053 gst_matroska_read_common_parse_chapter_edition (GstMatroskaReadCommon * common,
1054     GstEbmlRead * ebml, GstToc * toc)
1055 {
1056   guint32 id;
1057   guint64 is_hidden = 0, uid = 0;
1058   GstFlowReturn ret = GST_FLOW_OK;
1059   GstTocEntry *edition_info;
1060   GList *subentries = NULL, *l;
1061   gchar *uid_str;
1062
1063   DEBUG_ELEMENT_START (common, ebml, "ChaptersEdition");
1064
1065   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1066     DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1067     return ret;
1068   }
1069
1070   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1071     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1072       break;
1073
1074     switch (id) {
1075       case GST_MATROSKA_ID_EDITIONUID:
1076         ret = gst_ebml_read_uint (ebml, &id, &uid);
1077         break;
1078
1079       case GST_MATROSKA_ID_CHAPTERATOM:
1080         ret =
1081             gst_matroska_read_common_parse_chapter_element (common, ebml,
1082             &subentries);
1083         break;
1084
1085       case GST_MATROSKA_ID_EDITIONFLAGHIDDEN:
1086         ret = gst_ebml_read_uint (ebml, &id, &is_hidden);
1087         break;
1088
1089       default:
1090         ret =
1091             gst_matroska_read_common_parse_skip (common, ebml,
1092             "ChaptersEdition", id);
1093         break;
1094     }
1095   }
1096
1097   DEBUG_ELEMENT_STOP (common, ebml, "ChaptersEdition", ret);
1098
1099   if (uid == 0)
1100     uid = (((guint64) g_random_int ()) << 32) | g_random_int ();
1101   uid_str = g_strdup_printf ("%" G_GUINT64_FORMAT, uid);
1102   edition_info = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_EDITION, uid_str);
1103   gst_toc_entry_set_start_stop_times (edition_info, -1, -1);
1104   g_free (uid_str);
1105
1106   for (l = subentries; l; l = l->next)
1107     gst_toc_entry_append_sub_entry (edition_info, l->data);
1108   g_list_free (subentries);
1109
1110   if (is_hidden == 0 && subentries != NULL && ret == GST_FLOW_OK)
1111     gst_toc_append_entry (toc, edition_info);
1112   else {
1113     GST_DEBUG_OBJECT (common,
1114         "Skipping empty or hidden edition in the chapters TOC");
1115     gst_toc_entry_unref (edition_info);
1116   }
1117
1118   return ret;
1119 }
1120
1121 GstFlowReturn
1122 gst_matroska_read_common_parse_chapters (GstMatroskaReadCommon * common,
1123     GstEbmlRead * ebml)
1124 {
1125   guint32 id;
1126   GstFlowReturn ret = GST_FLOW_OK;
1127   GstToc *toc;
1128
1129   DEBUG_ELEMENT_START (common, ebml, "Chapters");
1130
1131   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1132     DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1133     return ret;
1134   }
1135
1136   /* FIXME: create CURRENT toc as well */
1137   toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1138
1139   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1140     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1141       break;
1142
1143     switch (id) {
1144       case GST_MATROSKA_ID_EDITIONENTRY:
1145         ret =
1146             gst_matroska_read_common_parse_chapter_edition (common, ebml, toc);
1147         break;
1148
1149       default:
1150         ret =
1151             gst_matroska_read_common_parse_skip (common, ebml, "Chapters", id);
1152         break;
1153     }
1154   }
1155
1156   if (gst_toc_get_entries (toc) != NULL) {
1157     gst_matroska_read_common_postprocess_toc_entries (gst_toc_get_entries (toc),
1158         common->segment.duration, "");
1159
1160     common->toc = toc;
1161   } else
1162     gst_toc_unref (toc);
1163
1164   common->chapters_parsed = TRUE;
1165
1166   DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret);
1167   return ret;
1168 }
1169
1170 GstFlowReturn
1171 gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common,
1172     GstEbmlRead * ebml)
1173 {
1174   GstFlowReturn ret;
1175   gchar *doctype;
1176   guint version;
1177   guint32 id;
1178
1179   /* this function is the first to be called */
1180
1181   /* default init */
1182   doctype = NULL;
1183   version = 1;
1184
1185   ret = gst_ebml_peek_id (ebml, &id);
1186   if (ret != GST_FLOW_OK)
1187     return ret;
1188
1189   GST_DEBUG_OBJECT (common, "id: %08x", id);
1190
1191   if (id != GST_EBML_ID_HEADER) {
1192     GST_ERROR_OBJECT (common, "Failed to read header");
1193     goto exit;
1194   }
1195
1196   ret = gst_ebml_read_master (ebml, &id);
1197   if (ret != GST_FLOW_OK)
1198     return ret;
1199
1200   while (gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1201     ret = gst_ebml_peek_id (ebml, &id);
1202     if (ret != GST_FLOW_OK)
1203       goto exit_error;
1204
1205     switch (id) {
1206         /* is our read version uptodate? */
1207       case GST_EBML_ID_EBMLREADVERSION:{
1208         guint64 num;
1209
1210         ret = gst_ebml_read_uint (ebml, &id, &num);
1211         if (ret != GST_FLOW_OK)
1212           goto exit_error;
1213         if (num != GST_EBML_VERSION) {
1214           GST_ERROR_OBJECT (ebml, "Unsupported EBML version %" G_GUINT64_FORMAT,
1215               num);
1216           goto exit_error;
1217         }
1218
1219         GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1220         break;
1221       }
1222
1223         /* we only handle 8 byte lengths at max */
1224       case GST_EBML_ID_EBMLMAXSIZELENGTH:{
1225         guint64 num;
1226
1227         ret = gst_ebml_read_uint (ebml, &id, &num);
1228         if (ret != GST_FLOW_OK)
1229           goto exit_error;
1230         if (num > sizeof (guint64)) {
1231           GST_ERROR_OBJECT (ebml,
1232               "Unsupported EBML maximum size %" G_GUINT64_FORMAT, num);
1233           return GST_FLOW_ERROR;
1234         }
1235         GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num);
1236         break;
1237       }
1238
1239         /* we handle 4 byte IDs at max */
1240       case GST_EBML_ID_EBMLMAXIDLENGTH:{
1241         guint64 num;
1242
1243         ret = gst_ebml_read_uint (ebml, &id, &num);
1244         if (ret != GST_FLOW_OK)
1245           goto exit_error;
1246         if (num > sizeof (guint32)) {
1247           GST_ERROR_OBJECT (ebml,
1248               "Unsupported EBML maximum ID %" G_GUINT64_FORMAT, num);
1249           return GST_FLOW_ERROR;
1250         }
1251         GST_DEBUG_OBJECT (ebml, "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num);
1252         break;
1253       }
1254
1255       case GST_EBML_ID_DOCTYPE:{
1256         gchar *text;
1257
1258         ret = gst_ebml_read_ascii (ebml, &id, &text);
1259         if (ret != GST_FLOW_OK)
1260           goto exit_error;
1261
1262         GST_DEBUG_OBJECT (ebml, "EbmlDocType: %s", GST_STR_NULL (text));
1263
1264         if (doctype)
1265           g_free (doctype);
1266         doctype = text;
1267         break;
1268       }
1269
1270       case GST_EBML_ID_DOCTYPEREADVERSION:{
1271         guint64 num;
1272
1273         ret = gst_ebml_read_uint (ebml, &id, &num);
1274         if (ret != GST_FLOW_OK)
1275           goto exit_error;
1276         version = num;
1277         GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num);
1278         break;
1279       }
1280
1281       default:
1282         ret = gst_matroska_read_common_parse_skip (common, ebml,
1283             "EBML header", id);
1284         if (ret != GST_FLOW_OK)
1285           goto exit_error;
1286         break;
1287
1288         /* we ignore these two, as they don't tell us anything we care about */
1289       case GST_EBML_ID_EBMLVERSION:
1290       case GST_EBML_ID_DOCTYPEVERSION:
1291         ret = gst_ebml_read_skip (ebml);
1292         if (ret != GST_FLOW_OK)
1293           goto exit_error;
1294         break;
1295     }
1296   }
1297
1298 exit:
1299
1300   if ((doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_MATROSKA)) ||
1301       (doctype != NULL && !strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM)) ||
1302       (doctype == NULL)) {
1303     if (version <= 2) {
1304       if (doctype) {
1305         GST_INFO_OBJECT (common, "Input is %s version %d", doctype, version);
1306         if (!strcmp (doctype, GST_MATROSKA_DOCTYPE_WEBM))
1307           common->is_webm = TRUE;
1308       } else {
1309         GST_WARNING_OBJECT (common, "Input is EBML without doctype, assuming "
1310             "matroska (version %d)", version);
1311       }
1312       ret = GST_FLOW_OK;
1313     } else {
1314       GST_ELEMENT_ERROR (common, STREAM, DEMUX, (NULL),
1315           ("Demuxer version (2) is too old to read %s version %d",
1316               GST_STR_NULL (doctype), version));
1317       ret = GST_FLOW_ERROR;
1318     }
1319   } else {
1320     GST_ELEMENT_ERROR (common, STREAM, WRONG_TYPE, (NULL),
1321         ("Input is not a matroska stream (doctype=%s)", doctype));
1322     ret = GST_FLOW_ERROR;
1323   }
1324
1325 exit_error:
1326
1327   g_free (doctype);
1328
1329   return ret;
1330 }
1331
1332 static GstFlowReturn
1333 gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
1334     GstEbmlRead * ebml, guint * nentries)
1335 {
1336   guint32 id;
1337   GstFlowReturn ret;
1338   GstMatroskaIndex idx;
1339
1340   idx.pos = (guint64) - 1;
1341   idx.track = 0;
1342   idx.time = GST_CLOCK_TIME_NONE;
1343   idx.block = 1;
1344
1345   DEBUG_ELEMENT_START (common, ebml, "CueTrackPositions");
1346
1347   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1348     DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1349     return ret;
1350   }
1351
1352   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1353     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1354       break;
1355
1356     switch (id) {
1357         /* track number */
1358       case GST_MATROSKA_ID_CUETRACK:
1359       {
1360         guint64 num;
1361
1362         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1363           break;
1364
1365         if (num == 0) {
1366           idx.track = 0;
1367           GST_WARNING_OBJECT (common, "Invalid CueTrack 0");
1368           break;
1369         }
1370
1371         GST_DEBUG_OBJECT (common, "CueTrack: %" G_GUINT64_FORMAT, num);
1372         idx.track = num;
1373         break;
1374       }
1375
1376         /* position in file */
1377       case GST_MATROSKA_ID_CUECLUSTERPOSITION:
1378       {
1379         guint64 num;
1380
1381         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1382           break;
1383
1384         if (num > G_MAXINT64) {
1385           GST_WARNING_OBJECT (common, "CueClusterPosition %" G_GUINT64_FORMAT
1386               " too large", num);
1387           break;
1388         }
1389
1390         idx.pos = num;
1391         break;
1392       }
1393
1394         /* number of block in the cluster */
1395       case GST_MATROSKA_ID_CUEBLOCKNUMBER:
1396       {
1397         guint64 num;
1398
1399         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1400           break;
1401
1402         if (num == 0) {
1403           GST_WARNING_OBJECT (common, "Invalid CueBlockNumber 0");
1404           break;
1405         }
1406
1407         GST_DEBUG_OBJECT (common, "CueBlockNumber: %" G_GUINT64_FORMAT, num);
1408         idx.block = num;
1409
1410         /* mild sanity check, disregard strange cases ... */
1411         if (idx.block > G_MAXUINT16) {
1412           GST_DEBUG_OBJECT (common, "... looks suspicious, ignoring");
1413           idx.block = 1;
1414         }
1415         break;
1416       }
1417
1418       default:
1419         ret = gst_matroska_read_common_parse_skip (common, ebml,
1420             "CueTrackPositions", id);
1421         break;
1422
1423       case GST_MATROSKA_ID_CUECODECSTATE:
1424       case GST_MATROSKA_ID_CUEREFERENCE:
1425         ret = gst_ebml_read_skip (ebml);
1426         break;
1427     }
1428   }
1429
1430   DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
1431
1432   /* (e.g.) lavf typically creates entries without a block number,
1433    * which is bogus and leads to contradictory information */
1434   if (common->index->len) {
1435     GstMatroskaIndex *last_idx;
1436
1437     last_idx = &g_array_index (common->index, GstMatroskaIndex,
1438         common->index->len - 1);
1439     if (last_idx->block == idx.block && last_idx->pos == idx.pos &&
1440         last_idx->track == idx.track && idx.time > last_idx->time) {
1441       GST_DEBUG_OBJECT (common, "Cue entry refers to same location, "
1442           "but has different time than previous entry; discarding");
1443       idx.track = 0;
1444     }
1445   }
1446
1447   if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
1448       && idx.pos != (guint64) - 1 && idx.track > 0) {
1449     g_array_append_val (common->index, idx);
1450     (*nentries)++;
1451   } else if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS) {
1452     GST_DEBUG_OBJECT (common, "CueTrackPositions without valid content");
1453   }
1454
1455   return ret;
1456 }
1457
1458 static GstFlowReturn
1459 gst_matroska_read_common_parse_index_pointentry (GstMatroskaReadCommon *
1460     common, GstEbmlRead * ebml)
1461 {
1462   guint32 id;
1463   GstFlowReturn ret;
1464   GstClockTime time = GST_CLOCK_TIME_NONE;
1465   guint nentries = 0;
1466
1467   DEBUG_ELEMENT_START (common, ebml, "CuePoint");
1468
1469   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1470     DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1471     return ret;
1472   }
1473
1474   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1475     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1476       break;
1477
1478     switch (id) {
1479         /* one single index entry ('point') */
1480       case GST_MATROSKA_ID_CUETIME:
1481       {
1482         if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK)
1483           break;
1484
1485         GST_DEBUG_OBJECT (common, "CueTime: %" G_GUINT64_FORMAT, time);
1486         time = time * common->time_scale;
1487         break;
1488       }
1489
1490         /* position in the file + track to which it belongs */
1491       case GST_MATROSKA_ID_CUETRACKPOSITIONS:
1492       {
1493         if ((ret =
1494                 gst_matroska_read_common_parse_index_cuetrack (common, ebml,
1495                     &nentries)) != GST_FLOW_OK)
1496           break;
1497         break;
1498       }
1499
1500       default:
1501         ret = gst_matroska_read_common_parse_skip (common, ebml, "CuePoint",
1502             id);
1503         break;
1504     }
1505   }
1506
1507   DEBUG_ELEMENT_STOP (common, ebml, "CuePoint", ret);
1508
1509   if (nentries > 0) {
1510     if (time == GST_CLOCK_TIME_NONE) {
1511       GST_WARNING_OBJECT (common, "CuePoint without valid time");
1512       g_array_remove_range (common->index, common->index->len - nentries,
1513           nentries);
1514     } else {
1515       gint i;
1516
1517       for (i = common->index->len - nentries; i < common->index->len; i++) {
1518         GstMatroskaIndex *idx =
1519             &g_array_index (common->index, GstMatroskaIndex, i);
1520
1521         idx->time = time;
1522         GST_DEBUG_OBJECT (common, "Index entry: pos=%" G_GUINT64_FORMAT
1523             ", time=%" GST_TIME_FORMAT ", track=%u, block=%u", idx->pos,
1524             GST_TIME_ARGS (idx->time), (guint) idx->track, (guint) idx->block);
1525       }
1526     }
1527   } else {
1528     GST_DEBUG_OBJECT (common, "Empty CuePoint");
1529   }
1530
1531   return ret;
1532 }
1533
1534 gint
1535 gst_matroska_read_common_stream_from_num (GstMatroskaReadCommon * common,
1536     guint track_num)
1537 {
1538   guint n;
1539
1540   g_assert (common->src->len == common->num_streams);
1541   for (n = 0; n < common->src->len; n++) {
1542     GstMatroskaTrackContext *context = g_ptr_array_index (common->src, n);
1543
1544     if (context->num == track_num) {
1545       return n;
1546     }
1547   }
1548
1549   if (n == common->num_streams)
1550     GST_WARNING_OBJECT (common,
1551         "Failed to find corresponding pad for tracknum %d", track_num);
1552
1553   return -1;
1554 }
1555
1556 GstFlowReturn
1557 gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
1558     GstEbmlRead * ebml)
1559 {
1560   guint32 id;
1561   GstFlowReturn ret = GST_FLOW_OK;
1562   guint i;
1563
1564   if (common->index)
1565     g_array_free (common->index, TRUE);
1566   common->index =
1567       g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1568
1569   DEBUG_ELEMENT_START (common, ebml, "Cues");
1570
1571   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1572     DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1573     return ret;
1574   }
1575
1576   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1577     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1578       break;
1579
1580     switch (id) {
1581         /* one single index entry ('point') */
1582       case GST_MATROSKA_ID_POINTENTRY:
1583         ret = gst_matroska_read_common_parse_index_pointentry (common, ebml);
1584         break;
1585
1586       default:
1587         ret = gst_matroska_read_common_parse_skip (common, ebml, "Cues", id);
1588         break;
1589     }
1590   }
1591   DEBUG_ELEMENT_STOP (common, ebml, "Cues", ret);
1592
1593   /* Sort index by time, smallest time first, for easier searching */
1594   g_array_sort (common->index, (GCompareFunc) gst_matroska_index_compare);
1595
1596   /* Now sort the track specific index entries into their own arrays */
1597   for (i = 0; i < common->index->len; i++) {
1598     GstMatroskaIndex *idx = &g_array_index (common->index, GstMatroskaIndex,
1599         i);
1600     gint track_num;
1601     GstMatroskaTrackContext *ctx;
1602
1603 #if 0
1604     if (common->element_index) {
1605       gint writer_id;
1606
1607       if (idx->track != 0 &&
1608           (track_num =
1609               gst_matroska_read_common_stream_from_num (common,
1610                   idx->track)) != -1) {
1611         ctx = g_ptr_array_index (common->src, track_num);
1612
1613         if (ctx->index_writer_id == -1)
1614           gst_index_get_writer_id (common->element_index,
1615               GST_OBJECT (ctx->pad), &ctx->index_writer_id);
1616         writer_id = ctx->index_writer_id;
1617       } else {
1618         if (common->element_index_writer_id == -1)
1619           gst_index_get_writer_id (common->element_index, GST_OBJECT (common),
1620               &common->element_index_writer_id);
1621         writer_id = common->element_index_writer_id;
1622       }
1623
1624       GST_LOG_OBJECT (common, "adding association %" GST_TIME_FORMAT "-> %"
1625           G_GUINT64_FORMAT " for writer id %d", GST_TIME_ARGS (idx->time),
1626           idx->pos, writer_id);
1627       gst_index_add_association (common->element_index, writer_id,
1628           GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
1629           GST_FORMAT_BYTES, idx->pos + common->ebml_segment_start, NULL);
1630     }
1631 #endif
1632
1633     if (idx->track == 0)
1634       continue;
1635
1636     track_num = gst_matroska_read_common_stream_from_num (common, idx->track);
1637     if (track_num == -1)
1638       continue;
1639
1640     ctx = g_ptr_array_index (common->src, track_num);
1641
1642     if (ctx->index_table == NULL)
1643       ctx->index_table =
1644           g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128);
1645
1646     g_array_append_vals (ctx->index_table, idx, 1);
1647   }
1648
1649   common->index_parsed = TRUE;
1650
1651   /* sanity check; empty index normalizes to no index */
1652   if (common->index->len == 0) {
1653     g_array_free (common->index, TRUE);
1654     common->index = NULL;
1655   }
1656
1657   return ret;
1658 }
1659
1660 GstFlowReturn
1661 gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
1662     GstElement * el, GstEbmlRead * ebml)
1663 {
1664   GstFlowReturn ret = GST_FLOW_OK;
1665   gdouble dur_f = -1.0;
1666   guint32 id;
1667
1668   DEBUG_ELEMENT_START (common, ebml, "SegmentInfo");
1669
1670   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1671     DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1672     return ret;
1673   }
1674
1675   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1676     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1677       break;
1678
1679     switch (id) {
1680         /* cluster timecode */
1681       case GST_MATROSKA_ID_TIMECODESCALE:{
1682         guint64 num;
1683
1684         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
1685           break;
1686
1687
1688         GST_DEBUG_OBJECT (common, "TimeCodeScale: %" G_GUINT64_FORMAT, num);
1689         common->time_scale = num;
1690         break;
1691       }
1692
1693       case GST_MATROSKA_ID_DURATION:{
1694         if ((ret = gst_ebml_read_float (ebml, &id, &dur_f)) != GST_FLOW_OK)
1695           break;
1696
1697         if (dur_f <= 0.0) {
1698           GST_WARNING_OBJECT (common, "Invalid duration %lf", dur_f);
1699           break;
1700         }
1701
1702         GST_DEBUG_OBJECT (common, "Duration: %lf", dur_f);
1703         break;
1704       }
1705
1706       case GST_MATROSKA_ID_WRITINGAPP:{
1707         gchar *text;
1708
1709         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1710           break;
1711
1712         GST_DEBUG_OBJECT (common, "WritingApp: %s", GST_STR_NULL (text));
1713         common->writing_app = text;
1714         break;
1715       }
1716
1717       case GST_MATROSKA_ID_MUXINGAPP:{
1718         gchar *text;
1719
1720         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1721           break;
1722
1723         GST_DEBUG_OBJECT (common, "MuxingApp: %s", GST_STR_NULL (text));
1724         common->muxing_app = text;
1725         break;
1726       }
1727
1728       case GST_MATROSKA_ID_DATEUTC:{
1729         gint64 time;
1730
1731         if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
1732           break;
1733
1734         GST_DEBUG_OBJECT (common, "DateUTC: %" G_GINT64_FORMAT, time);
1735         common->created = time;
1736         break;
1737       }
1738
1739       case GST_MATROSKA_ID_TITLE:{
1740         gchar *text;
1741         GstTagList *taglist;
1742
1743         if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK)
1744           break;
1745
1746         GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text));
1747         taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
1748         gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
1749         gst_matroska_read_common_found_global_tag (common, el, taglist);
1750         g_free (text);
1751         break;
1752       }
1753
1754       default:
1755         ret = gst_matroska_read_common_parse_skip (common, ebml,
1756             "SegmentInfo", id);
1757         break;
1758
1759         /* fall through */
1760       case GST_MATROSKA_ID_SEGMENTUID:
1761       case GST_MATROSKA_ID_SEGMENTFILENAME:
1762       case GST_MATROSKA_ID_PREVUID:
1763       case GST_MATROSKA_ID_PREVFILENAME:
1764       case GST_MATROSKA_ID_NEXTUID:
1765       case GST_MATROSKA_ID_NEXTFILENAME:
1766       case GST_MATROSKA_ID_SEGMENTFAMILY:
1767       case GST_MATROSKA_ID_CHAPTERTRANSLATE:
1768         ret = gst_ebml_read_skip (ebml);
1769         break;
1770     }
1771   }
1772
1773   if (dur_f > 0.0) {
1774     GstClockTime dur_u;
1775
1776     dur_u = gst_gdouble_to_guint64 (dur_f *
1777         gst_guint64_to_gdouble (common->time_scale));
1778     if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64)
1779       common->segment.duration = dur_u;
1780   }
1781
1782   DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
1783
1784   common->segmentinfo_parsed = TRUE;
1785
1786   return ret;
1787 }
1788
1789 static GstFlowReturn
1790 gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon *
1791     common, GstEbmlRead * ebml, GstTagList ** p_taglist, gchar * parent)
1792 {
1793   /* FIXME: check if there are more useful mappings */
1794   static const struct
1795   {
1796     const gchar *matroska_tagname;
1797     const gchar *gstreamer_tagname;
1798   }
1799   tag_conv[] = {
1800     {
1801       /* The following list has the _same_ order as the one in Matroska spec. Please, don't mess it up. */
1802       /* TODO: Nesting information:
1803          ORIGINAL A special tag that is meant to have other tags inside (using nested tags) to describe the original work of art that this item is based on. All tags in this list can be used "under" the ORIGINAL tag like LYRICIST, PERFORMER, etc.
1804          SAMPLE A tag that contains other tags to describe a sample used in the targeted item taken from another work of art. All tags in this list can be used "under" the SAMPLE tag like TITLE, ARTIST, DATE_RELEASED, etc.
1805          COUNTRY The name of the country (biblio ISO-639-2) that is meant to have other tags inside (using nested tags) to country specific information about the item. All tags in this list can be used "under" the COUNTRY_SPECIFIC tag like LABEL, PUBLISH_RATING, etc.
1806        */
1807
1808       /* Organizational Information */
1809     GST_MATROSKA_TAG_ID_TOTAL_PARTS, GST_TAG_TRACK_COUNT}, {
1810     GST_MATROSKA_TAG_ID_PART_NUMBER, GST_TAG_TRACK_NUMBER}, {
1811       /* TODO: PART_OFFSET A number to add to PART_NUMBER when the parts at that level don't start at 1. (e.g. if TargetType is TRACK, the track number of the second audio CD) */
1812
1813       /* Titles */
1814     GST_MATROSKA_TAG_ID_SUBTITLE, GST_TAG_TITLE}, {     /* Sub Title of the entity. Since we're concat'ing all title-like entities anyway, might as well add the sub-title. */
1815     GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, {
1816     GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, {        /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1817
1818       /* TODO: Nested Information:
1819          URL URL corresponding to the tag it's included in.
1820          SORT_WITH A child element to indicate what alternative value the parent tag can have to be sorted, for example "Pet Shop Boys" instead of "The Pet Shop Boys". Or "Marley Bob" and "Marley Ziggy" (no comma needed).
1821          INSTRUMENTS The instruments that are being used/played, separated by a comma. It should be a child of the following tags: ARTIST, LEAD_PERFORMER or ACCOMPANIMENT.
1822          EMAIL Email corresponding to the tag it's included in.
1823          ADDRESS The physical address of the entity. The address should include a country code. It can be useful for a recording label.
1824          FAX The fax number corresponding to the tag it's included in. It can be useful for a recording label.
1825          PHONE The phone number corresponding to the tag it's included in. It can be useful for a recording label.
1826        */
1827
1828       /* Entities */
1829     GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, {
1830     GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, {
1831     GST_MATROSKA_TAG_ID_ACCOMPANIMENT, GST_TAG_PERFORMER}, {    /* Band/orchestra/accompaniment/musician. This is akin to the TPE2 tag in ID3. */
1832     GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, {
1833       /* ARRANGER The person who arranged the piece, e.g., Ravel. */
1834     GST_MATROSKA_TAG_ID_LYRICS, GST_TAG_LYRICS}, {      /* The lyrics corresponding to a song (in case audio synchronization is not known or as a doublon to a subtitle track). Editing this value when subtitles are found should also result in editing the subtitle track for more consistency. */
1835       /* LYRICIST The person who wrote the lyrics for a musical item. This is akin to the TEXT tag in ID3. */
1836     GST_MATROSKA_TAG_ID_CONDUCTOR, GST_TAG_PERFORMER}, {        /* Conductor/performer refinement. This is akin to the TPE3 tag in ID3. */
1837       /* DIRECTOR This is akin to the IART tag in RIFF. */
1838     GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, {
1839       /* ASSISTANT_DIRECTOR The name of the assistant director. */
1840       /* DIRECTOR_OF_PHOTOGRAPHY The name of the director of photography, also known as cinematographer. This is akin to the ICNM tag in Extended RIFF. */
1841       /* SOUND_ENGINEER The name of the sound engineer or sound recordist. */
1842       /* ART_DIRECTOR The person who oversees the artists and craftspeople who build the sets. */
1843       /* PRODUCTION_DESIGNER Artist responsible for designing the overall visual appearance of a movie. */
1844       /* CHOREGRAPHER The name of the choregrapher */
1845       /* COSTUME_DESIGNER The name of the costume designer */
1846       /* ACTOR An actor or actress playing a role in this movie. This is the person's real name, not the character's name the person is playing. */
1847       /* CHARACTER The name of the character an actor or actress plays in this movie. This should be a sub-tag of an ACTOR tag in order not to cause ambiguities. */
1848       /* WRITTEN_BY The author of the story or script (used for movies and TV shows). */
1849       /* SCREENPLAY_BY The author of the screenplay or scenario (used for movies and TV shows). */
1850       /* EDITED_BY This is akin to the IEDT tag in Extended RIFF. */
1851       /* PRODUCER Produced by. This is akin to the IPRO tag in Extended RIFF. */
1852       /* COPRODUCER The name of a co-producer. */
1853       /* EXECUTIVE_PRODUCER The name of an executive producer. */
1854       /* DISTRIBUTED_BY This is akin to the IDST tag in Extended RIFF. */
1855       /* MASTERED_BY The engineer who mastered the content for a physical medium or for digital distribution. */
1856     GST_MATROSKA_TAG_ID_ENCODED_BY, GST_TAG_ENCODED_BY}, {      /* This is akin to the TENC tag in ID3. */
1857       /* MIXED_BY DJ mix by the artist specified */
1858       /* REMIXED_BY Interpreted, remixed, or otherwise modified by. This is akin to the TPE4 tag in ID3. */
1859       /* PRODUCTION_STUDIO This is akin to the ISTD tag in Extended RIFF. */
1860       /* THANKS_TO A very general tag for everyone else that wants to be listed. */
1861       /* PUBLISHER This is akin to the TPUB tag in ID3. */
1862       /* LABEL The record label or imprint on the disc. */
1863       /* Search / Classification */
1864     GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE}, {
1865       /* MOOD Intended to reflect the mood of the item with a few keywords, e.g. "Romantic", "Sad" or "Uplifting". The format follows that of the TMOO tag in ID3. */
1866       /* ORIGINAL_MEDIA_TYPE Describes the original type of the media, such as, "DVD", "CD", "computer image," "drawing," "lithograph," and so forth. This is akin to the TMED tag in ID3. */
1867       /* CONTENT_TYPE The type of the item. e.g. Documentary, Feature Film, Cartoon, Music Video, Music, Sound FX, ... */
1868       /* SUBJECT Describes the topic of the file, such as "Aerial view of Seattle." */
1869     GST_MATROSKA_TAG_ID_DESCRIPTION, GST_TAG_DESCRIPTION}, {    /* A short description of the content, such as "Two birds flying." */
1870     GST_MATROSKA_TAG_ID_KEYWORDS, GST_TAG_KEYWORDS}, {  /* Keywords to the item separated by a comma, used for searching. */
1871       /* SUMMARY A plot outline or a summary of the story. */
1872       /* SYNOPSIS A description of the story line of the item. */
1873       /* INITIAL_KEY The initial key that a musical track starts in. The format is identical to ID3. */
1874       /* PERIOD Describes the period that the piece is from or about. For example, "Renaissance". */
1875       /* LAW_RATING Depending on the country it's the format of the rating of a movie (P, R, X in the USA, an age in other countries or a URI defining a logo). */
1876       /* ICRA The ICRA content rating for parental control. (Previously RSACi) */
1877
1878       /* Temporal Information */
1879     GST_MATROSKA_TAG_ID_DATE_RELEASED, GST_TAG_DATE}, { /* The time that the item was originaly released. This is akin to the TDRL tag in ID3. */
1880     GST_MATROSKA_TAG_ID_DATE_RECORDED, GST_TAG_DATE}, { /* The time that the recording began. This is akin to the TDRC tag in ID3. */
1881     GST_MATROSKA_TAG_ID_DATE_ENCODED, GST_TAG_DATE}, {  /* The time that the encoding of this item was completed began. This is akin to the TDEN tag in ID3. */
1882     GST_MATROSKA_TAG_ID_DATE_TAGGED, GST_TAG_DATE}, {   /* The time that the tags were done for this item. This is akin to the TDTG tag in ID3. */
1883     GST_MATROSKA_TAG_ID_DATE_DIGITIZED, GST_TAG_DATE}, {        /* The time that the item was tranfered to a digital medium. This is akin to the IDIT tag in RIFF. */
1884     GST_MATROSKA_TAG_ID_DATE_WRITTEN, GST_TAG_DATE}, {  /* The time that the writing of the music/script began. */
1885     GST_MATROSKA_TAG_ID_DATE_PURCHASED, GST_TAG_DATE}, {        /* Information on when the file was purchased (see also purchase tags). */
1886     GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, {  /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1887
1888       /* Spacial Information */
1889     GST_MATROSKA_TAG_ID_RECORDING_LOCATION, GST_TAG_GEO_LOCATION_NAME}, {       /* The location where the item was recorded. The countries corresponding to the string, same 2 octets as in Internet domains, or possibly ISO-3166. This code is followed by a comma, then more detailed information such as state/province, another comma, and then city. For example, "US, Texas, Austin". This will allow for easy sorting. It is okay to only store the country, or the country and the state/province. More detailed information can be added after the city through the use of additional commas. In cases where the province/state is unknown, but you want to store the city, simply leave a space between the two commas. For example, "US, , Austin". */
1890       /* COMPOSITION_LOCATION Location that the item was originaly designed/written. The countries corresponding to the string, same 2 octets as in Internet domains, or possibly ISO-3166. This code is followed by a comma, then more detailed information such as state/province, another comma, and then city. For example, "US, Texas, Austin". This will allow for easy sorting. It is okay to only store the country, or the country and the state/province. More detailed information can be added after the city through the use of additional commas. In cases where the province/state is unknown, but you want to store the city, simply leave a space between the two commas. For example, "US, , Austin". */
1891       /* COMPOSER_NATIONALITY Nationality of the main composer of the item, mostly for classical music. The countries corresponding to the string, same 2 octets as in Internet domains, or possibly ISO-3166. */
1892
1893       /* Personal */
1894     GST_MATROSKA_TAG_ID_COMMENT, GST_TAG_COMMENT}, {    /* Any comment related to the content. */
1895     GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, {   /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1896       /* PLAY_COUNTER The number of time the item has been played. */
1897       /* TODO: RATING A numeric value defining how much a person likes the song/movie. The number is between 0 and 5 with decimal values possible (e.g. 2.7), 5(.0) being the highest possible rating. Other rating systems with different ranges will have to be scaled. */
1898
1899       /* Technical Information */
1900     GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, {
1901       /* ENCODER_SETTINGS A list of the settings used for encoding this item. No specific format. */
1902     GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, {
1903     GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, {     /* Matroska spec does NOT have this tag! Dunno what it was doing here, probably for compatibility. */
1904       /* WONTFIX (already handled in another way): FPS The average frames per second of the specified item. This is typically the average number of Blocks per second. In the event that lacing is used, each laced chunk is to be counted as a seperate frame. */
1905     GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, {
1906       /* MEASURE In music, a measure is a unit of time in Western music like "4/4". It represents a regular grouping of beats, a meter, as indicated in musical notation by the time signature.. The majority of the contemporary rock and pop music you hear on the radio these days is written in the 4/4 time signature. */
1907       /* TUNING It is saved as a frequency in hertz to allow near-perfect tuning of instruments to the same tone as the musical piece (e.g. "441.34" in Hertz). The default value is 440.0 Hz. */
1908       /* TODO: REPLAYGAIN_GAIN The gain to apply to reach 89dB SPL on playback. This is based on the Replay Gain standard. Note that ReplayGain information can be found at all TargetType levels (track, album, etc). */
1909       /* TODO: REPLAYGAIN_PEAK The maximum absolute peak value of the item. This is based on the Replay Gain standard. */
1910
1911       /* Identifiers */
1912     GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, {
1913       /* MCDI This is a binary dump of the TOC of the CDROM that this item was taken from. This holds the same information as the MCDI in ID3. */
1914       /* ISBN International Standard Book Number */
1915       /* BARCODE EAN-13 (European Article Numbering) or UPC-A (Universal Product Code) bar code identifier */
1916       /* CATALOG_NUMBER A label-specific string used to identify the release (TIC 01 for example). */
1917       /* LABEL_CODE A 4-digit or 5-digit number to identify the record label, typically printed as (LC) xxxx or (LC) 0xxxx on CDs medias or covers (only the number is stored). */
1918       /* LCCN Library of Congress Control Number */
1919
1920       /* Commercial */
1921       /* PURCHASE_ITEM URL to purchase this file. This is akin to the WPAY tag in ID3. */
1922       /* PURCHASE_INFO Information on where to purchase this album. This is akin to the WCOM tag in ID3. */
1923       /* PURCHASE_OWNER Information on the person who purchased the file. This is akin to the TOWN tag in ID3. */
1924       /* PURCHASE_PRICE The amount paid for entity. There should only be a numeric value in here. Only numbers, no letters or symbols other than ".". For instance, you would store "15.59" instead of "$15.59USD". */
1925       /* PURCHASE_CURRENCY The currency type used to pay for the entity. Use ISO-4217 for the 3 letter currency code. */
1926
1927       /* Legal */
1928     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, {
1929     GST_MATROSKA_TAG_ID_PRODUCTION_COPYRIGHT, GST_TAG_COPYRIGHT}, {     /* The copyright information as per the production copyright holder. This is akin to the TPRO tag in ID3. */
1930     GST_MATROSKA_TAG_ID_LICENSE, GST_TAG_LICENSE}, {    /* The license applied to the content (like Creative Commons variants). */
1931     GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}
1932   };
1933   static const struct
1934   {
1935     const gchar *matroska_tagname;
1936     const gchar *gstreamer_tagname;
1937   }
1938   child_tag_conv[] = {
1939     {
1940     "TITLE/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1941     "ARTIST/SORT_WITH=", GST_TAG_ARTIST_SORTNAME}, {
1942       /* ALBUM-stuff is handled elsewhere */
1943     "COMPOSER/SORT_WITH=", GST_TAG_TITLE_SORTNAME}, {
1944     "ORIGINAL/URL=", GST_TAG_LOCATION}, {
1945       /* EMAIL, PHONE, FAX all can be mapped to GST_TAG_CONTACT, there is special
1946        * code for that later.
1947        */
1948     "TITLE/URL=", GST_TAG_HOMEPAGE}, {
1949     "ARTIST/URL=", GST_TAG_HOMEPAGE}, {
1950     "COPYRIGHT/URL=", GST_TAG_COPYRIGHT_URI}, {
1951     "LICENSE/URL=", GST_TAG_LICENSE_URI}, {
1952     "LICENSE/URL=", GST_TAG_LICENSE_URI}
1953   };
1954   GstFlowReturn ret;
1955   guint32 id;
1956   gchar *value = NULL;
1957   gchar *tag = NULL;
1958   gchar *name_with_parent = NULL;
1959   GstTagList *child_taglist = NULL;
1960
1961   DEBUG_ELEMENT_START (common, ebml, "SimpleTag");
1962
1963   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
1964     DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
1965     return ret;
1966   }
1967
1968   if (parent)
1969     child_taglist = *p_taglist;
1970   else
1971     child_taglist = gst_tag_list_new_empty ();
1972
1973   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
1974     /* read all sub-entries */
1975
1976     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
1977       break;
1978
1979     switch (id) {
1980       case GST_MATROSKA_ID_TAGNAME:
1981         g_free (tag);
1982         tag = NULL;
1983         ret = gst_ebml_read_ascii (ebml, &id, &tag);
1984         GST_DEBUG_OBJECT (common, "TagName: %s", GST_STR_NULL (tag));
1985         g_free (name_with_parent);
1986         if (parent != NULL)
1987           name_with_parent = g_strdup_printf ("%s/%s", parent, tag);
1988         else
1989           name_with_parent = g_strdup (tag);
1990         break;
1991
1992       case GST_MATROSKA_ID_TAGSTRING:
1993         g_free (value);
1994         value = NULL;
1995         ret = gst_ebml_read_utf8 (ebml, &id, &value);
1996         GST_DEBUG_OBJECT (common, "TagString: %s", GST_STR_NULL (value));
1997         break;
1998
1999       case GST_MATROSKA_ID_SIMPLETAG:
2000         /* Recursive SimpleTag */
2001         /* This implementation requires tag name of _this_ tag to be known
2002          * in order to read its children. It's not in the spec, just the way
2003          * the code is written.
2004          */
2005         if (name_with_parent != NULL) {
2006           ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2007               ebml, &child_taglist, name_with_parent);
2008           break;
2009         }
2010         /* fall-through */
2011
2012       default:
2013         ret = gst_matroska_read_common_parse_skip (common, ebml, "SimpleTag",
2014             id);
2015         break;
2016
2017       case GST_MATROSKA_ID_TAGLANGUAGE:
2018       case GST_MATROSKA_ID_TAGDEFAULT:
2019       case GST_MATROSKA_ID_TAGBINARY:
2020         ret = gst_ebml_read_skip (ebml);
2021         break;
2022     }
2023   }
2024
2025   DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret);
2026
2027   if (parent && tag && value && *value != '\0') {
2028     /* Don't bother mapping children tags - parent will do that */
2029     gchar *key_val;
2030     /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2031     key_val = g_strdup_printf ("%s=%s", name_with_parent, value);
2032     gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2033         GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2034   } else if (tag && value && *value != '\0') {
2035     gboolean matched = FALSE;
2036     guint i;
2037
2038     for (i = 0; !matched && i < G_N_ELEMENTS (tag_conv); i++) {
2039       const gchar *tagname_gst = tag_conv[i].gstreamer_tagname;
2040
2041       const gchar *tagname_mkv = tag_conv[i].matroska_tagname;
2042
2043       if (strcmp (tagname_mkv, tag) == 0) {
2044         GValue dest = { 0, };
2045         GType dest_type = gst_tag_get_type (tagname_gst);
2046
2047         /* Ensure that any date string is complete */
2048         if (dest_type == G_TYPE_DATE) {
2049           guint year = 1901, month = 1, day = 1;
2050
2051           /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need
2052            * the first type */
2053           if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) {
2054             g_free (value);
2055             value = g_strdup_printf ("%04u-%02u-%02u", year, month, day);
2056           }
2057         }
2058
2059         g_value_init (&dest, dest_type);
2060         if (gst_value_deserialize (&dest, value)) {
2061           gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2062               tagname_gst, &dest, NULL);
2063         } else {
2064           GST_WARNING_OBJECT (common, "Can't transform tag '%s' with "
2065               "value '%s' to target type '%s'", tag, value,
2066               g_type_name (dest_type));
2067         }
2068         g_value_unset (&dest);
2069         matched = TRUE;
2070       }
2071     }
2072     if (!matched) {
2073       gchar *key_val;
2074       /* TODO: read LANGUAGE sub-tag, and use "key[lc]=val" form */
2075       key_val = g_strdup_printf ("%s=%s", tag, value);
2076       gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2077           GST_TAG_EXTENDED_COMMENT, key_val, NULL);
2078     }
2079   }
2080
2081   if (!parent) {
2082     /* Map children tags. This only supports top-anchored mapping. That is,
2083      * we start at toplevel tag (this tag), and see how its combinations
2084      * with its children can be mapped. Which means that grandchildren
2085      * are also combined here, with _this_ tag taken into consideration.
2086      * If grandchildren can be combined only with children, that combination
2087      * will not happen.
2088      */
2089     gint child_tags_n = gst_tag_list_n_tags (child_taglist);
2090     if (child_tags_n > 0) {
2091       gint i;
2092       for (i = 0; i < child_tags_n; i++) {
2093         gint j;
2094         const gchar *child_name = gst_tag_list_nth_tag_name (child_taglist, i);
2095         guint taglen = gst_tag_list_get_tag_size (child_taglist, child_name);
2096         for (j = 0; j < taglen; j++) {
2097           gchar *val;
2098           gboolean matched = FALSE;
2099           gchar *val_pre, *val_post;
2100           gint k;
2101
2102           if (!gst_tag_list_get_string_index (child_taglist, child_name,
2103                   j, &val))
2104             continue;
2105           if (!strchr (val, '=')) {
2106             g_free (val);
2107             continue;
2108           }
2109           val_post = g_strdup (strchr (val, '=') + 1);
2110           val_pre = g_strdup (val);
2111           *(strchr (val_pre, '=') + 1) = '\0';
2112
2113           for (k = 0; !matched && k < G_N_ELEMENTS (child_tag_conv); k++) {
2114             const gchar *tagname_gst = child_tag_conv[k].gstreamer_tagname;
2115
2116             const gchar *tagname_mkv = child_tag_conv[k].matroska_tagname;
2117
2118             /* TODO: Once "key[lc]=value" form support is implemented,
2119              * strip [lc] here. It can't be used in combined tags.
2120              * If a tag is not combined, leave [lc] as it is.
2121              */
2122             if (strcmp (tagname_mkv, val_pre) == 0) {
2123               GValue dest = { 0, };
2124               GType dest_type = gst_tag_get_type (tagname_gst);
2125
2126               g_value_init (&dest, dest_type);
2127               if (gst_value_deserialize (&dest, val_post)) {
2128                 gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND,
2129                     tagname_gst, &dest, NULL);
2130               } else {
2131                 GST_WARNING_OBJECT (common, "Can't transform complex tag '%s' "
2132                     "to target type '%s'", val, g_type_name (dest_type));
2133               }
2134               g_value_unset (&dest);
2135               matched = TRUE;
2136             }
2137           }
2138           if (!matched) {
2139             gchar *last_slash = strrchr (val_pre, '/');
2140             if (last_slash) {
2141               last_slash++;
2142               if (strcmp (last_slash, "EMAIL=") == 0 ||
2143                   strcmp (last_slash, "PHONE=") == 0 ||
2144                   strcmp (last_slash, "ADDRESS=") == 0 ||
2145                   strcmp (last_slash, "FAX=") == 0) {
2146                 gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2147                     GST_TAG_CONTACT, val_post, NULL);
2148                 matched = TRUE;
2149               }
2150             }
2151           }
2152           if (!matched)
2153             gst_tag_list_add (*p_taglist, GST_TAG_MERGE_APPEND,
2154                 GST_TAG_EXTENDED_COMMENT, val, NULL);
2155           g_free (val_post);
2156           g_free (val_pre);
2157           g_free (val);
2158         }
2159       }
2160     }
2161     gst_tag_list_unref (child_taglist);
2162   }
2163
2164   g_free (tag);
2165   g_free (value);
2166   g_free (name_with_parent);
2167
2168   return ret;
2169 }
2170
2171
2172 static void
2173 gst_matroska_read_common_count_streams (GstMatroskaReadCommon * common,
2174     gint * a, gint * v, gint * s)
2175 {
2176   gint i;
2177   gint video_streams = 0, audio_streams = 0, subtitle_streams = 0;
2178
2179   for (i = 0; i < common->src->len; i++) {
2180     GstMatroskaTrackContext *stream;
2181
2182     stream = g_ptr_array_index (common->src, i);
2183     if (stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO)
2184       video_streams += 1;
2185     else if (stream->type == GST_MATROSKA_TRACK_TYPE_AUDIO)
2186       audio_streams += 1;
2187     else if (stream->type == GST_MATROSKA_TRACK_TYPE_SUBTITLE)
2188       subtitle_streams += 1;
2189   }
2190   *v = video_streams;
2191   *a = audio_streams;
2192   *v = subtitle_streams;
2193 }
2194
2195
2196 static void
2197 gst_matroska_read_common_apply_target_type_foreach (const GstTagList * list,
2198     const gchar * tag, gpointer user_data)
2199 {
2200   guint vallen;
2201   guint i;
2202   TargetTypeContext *ctx = (TargetTypeContext *) user_data;
2203
2204   vallen = gst_tag_list_get_tag_size (list, tag);
2205   if (vallen == 0)
2206     return;
2207
2208   for (i = 0; i < vallen; i++) {
2209     GValue val = { 0 };
2210     const GValue *val_ref;
2211
2212     val_ref = gst_tag_list_get_value_index (list, tag, i);
2213     if (val_ref == NULL)
2214       continue;
2215     g_value_init (&val, G_VALUE_TYPE (val_ref));
2216     g_value_copy (val_ref, &val);
2217
2218     /* TODO: use the optional ctx->target_type somehow */
2219     if (strcmp (tag, GST_TAG_TITLE) == 0) {
2220       if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2221         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2222             GST_TAG_SHOW_NAME, &val);
2223         continue;
2224       } else if (ctx->target_type_value >= 50) {
2225         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2226             GST_TAG_ALBUM, &val);
2227         continue;
2228       }
2229     } else if (strcmp (tag, GST_TAG_TITLE_SORTNAME) == 0) {
2230       if (ctx->target_type_value >= 70 && !ctx->audio_only) {
2231         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2232             GST_TAG_SHOW_SORTNAME, &val);
2233         continue;
2234       } else if (ctx->target_type_value >= 50) {
2235         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2236             GST_TAG_ALBUM_SORTNAME, &val);
2237         continue;
2238       }
2239     } else if (strcmp (tag, GST_TAG_ARTIST) == 0) {
2240       if (ctx->target_type_value >= 50) {
2241         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2242             GST_TAG_ALBUM_ARTIST, &val);
2243         continue;
2244       }
2245     } else if (strcmp (tag, GST_TAG_ARTIST_SORTNAME) == 0) {
2246       if (ctx->target_type_value >= 50) {
2247         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2248             GST_TAG_ALBUM_ARTIST_SORTNAME, &val);
2249         continue;
2250       }
2251     } else if (strcmp (tag, GST_TAG_TRACK_COUNT) == 0) {
2252       if (ctx->target_type_value >= 60) {
2253         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2254             GST_TAG_ALBUM_VOLUME_COUNT, &val);
2255         continue;
2256       }
2257     } else if (strcmp (tag, GST_TAG_TRACK_NUMBER) == 0) {
2258       if (ctx->target_type_value >= 60 && !ctx->audio_only) {
2259         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2260             GST_TAG_SHOW_SEASON_NUMBER, &val);
2261         continue;
2262       } else if (ctx->target_type_value >= 50 && !ctx->audio_only) {
2263         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2264             GST_TAG_SHOW_EPISODE_NUMBER, &val);
2265         continue;
2266       } else if (ctx->target_type_value >= 50) {
2267         gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND,
2268             GST_TAG_ALBUM_VOLUME_NUMBER, &val);
2269         continue;
2270       }
2271     }
2272     gst_tag_list_add_value (ctx->result, GST_TAG_MERGE_APPEND, tag, &val);
2273     g_value_unset (&val);
2274   }
2275 }
2276
2277
2278 static GstTagList *
2279 gst_matroska_read_common_apply_target_type (GstMatroskaReadCommon * common,
2280     GstTagList * taglist, guint64 target_type_value, gchar * target_type)
2281 {
2282   TargetTypeContext ctx;
2283   gint a = 0;
2284   gint v = 0;
2285   gint s = 0;
2286
2287   gst_matroska_read_common_count_streams (common, &a, &v, &s);
2288
2289   ctx.audio_only = (a > 0 && v == 0 && s == 0);
2290   ctx.result = gst_tag_list_new_empty ();
2291   ctx.target_type_value = target_type_value;
2292   ctx.target_type = target_type;
2293
2294   gst_tag_list_foreach (taglist,
2295       gst_matroska_read_common_apply_target_type_foreach, &ctx);
2296
2297   gst_tag_list_unref (taglist);
2298   return ctx.result;
2299 }
2300
2301
2302 static GstFlowReturn
2303 gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common,
2304     GstEbmlRead * ebml, GstTagList ** p_taglist)
2305 {
2306   guint32 id;
2307   GstFlowReturn ret;
2308   GArray *chapter_targets, *edition_targets, *track_targets;
2309   GstTagList *taglist;
2310   GList *cur;
2311   guint64 target_type_value = 50;
2312   gchar *target_type = NULL;
2313
2314   DEBUG_ELEMENT_START (common, ebml, "Tag");
2315
2316   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2317     DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2318     return ret;
2319   }
2320
2321   edition_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2322   chapter_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2323   track_targets = g_array_new (FALSE, FALSE, sizeof (guint64));
2324   taglist = gst_tag_list_new_empty ();
2325   target_type = NULL;
2326
2327   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2328     /* read all sub-entries */
2329
2330     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2331       break;
2332
2333     switch (id) {
2334       case GST_MATROSKA_ID_SIMPLETAG:
2335         ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common,
2336             ebml, &taglist, NULL);
2337         break;
2338
2339       case GST_MATROSKA_ID_TARGETS:
2340         g_free (target_type);
2341         target_type = NULL;
2342         target_type_value = 50;
2343         ret = gst_matroska_read_common_parse_metadata_targets (common, ebml,
2344             edition_targets, chapter_targets, track_targets,
2345             &target_type_value, &target_type);
2346         break;
2347
2348       default:
2349         ret = gst_matroska_read_common_parse_skip (common, ebml, "Tag", id);
2350         break;
2351     }
2352   }
2353
2354   DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret);
2355
2356   taglist = gst_matroska_read_common_apply_target_type (common, taglist,
2357       target_type_value, target_type);
2358   g_free (target_type);
2359
2360   /* if tag is chapter/edition specific - try to find that entry */
2361   if (G_UNLIKELY (chapter_targets->len > 0 || edition_targets->len > 0 ||
2362           track_targets->len > 0)) {
2363     gint i;
2364     if (chapter_targets->len > 0 || edition_targets->len > 0) {
2365       if (common->toc == NULL)
2366         GST_WARNING_OBJECT (common,
2367             "Found chapter/edition specific tag, but TOC is not present");
2368       else {
2369         cur = gst_toc_get_entries (common->toc);
2370         while (cur != NULL) {
2371           gst_matroska_read_common_parse_toc_tag (cur->data, edition_targets,
2372               chapter_targets, taglist);
2373           cur = cur->next;
2374         }
2375         common->toc_updated = TRUE;
2376       }
2377     }
2378     for (i = 0; i < track_targets->len; i++) {
2379       gint j;
2380       gboolean found = FALSE;
2381       guint64 tgt = g_array_index (track_targets, guint64, i);
2382
2383       for (j = 0; j < common->src->len; j++) {
2384         GstMatroskaTrackContext *stream = g_ptr_array_index (common->src, j);
2385
2386         if (stream->uid == tgt) {
2387           gst_tag_list_insert (stream->pending_tags, taglist,
2388               GST_TAG_MERGE_REPLACE);
2389           found = TRUE;
2390         }
2391       }
2392       if (!found) {
2393         GST_WARNING_OBJECT (common,
2394             "Found track-specific tag(s), but track %" G_GUINT64_FORMAT
2395             " is not known (yet?)", tgt);
2396       }
2397     }
2398   } else
2399     gst_tag_list_insert (*p_taglist, taglist, GST_TAG_MERGE_APPEND);
2400
2401   gst_tag_list_unref (taglist);
2402   g_array_unref (chapter_targets);
2403   g_array_unref (edition_targets);
2404   g_array_unref (track_targets);
2405
2406   return ret;
2407 }
2408
2409 GstFlowReturn
2410 gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
2411     GstElement * el, GstEbmlRead * ebml)
2412 {
2413   GstTagList *taglist;
2414   GstFlowReturn ret = GST_FLOW_OK;
2415   guint32 id;
2416   GList *l;
2417   guint64 curpos;
2418
2419   curpos = gst_ebml_read_get_pos (ebml);
2420
2421   /* Make sure we don't parse a tags element twice and
2422    * post it's tags twice */
2423   curpos = gst_ebml_read_get_pos (ebml);
2424   for (l = common->tags_parsed; l; l = l->next) {
2425     guint64 *pos = l->data;
2426
2427     if (*pos == curpos) {
2428       GST_DEBUG_OBJECT (common, "Skipping already parsed Tags at offset %"
2429           G_GUINT64_FORMAT, curpos);
2430       return GST_FLOW_OK;
2431     }
2432   }
2433
2434   common->tags_parsed =
2435       g_list_prepend (common->tags_parsed, g_slice_new (guint64));
2436   *((guint64 *) common->tags_parsed->data) = curpos;
2437   /* fall-through */
2438
2439   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2440     DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2441     return ret;
2442   }
2443
2444   taglist = gst_tag_list_new_empty ();
2445   gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
2446   common->toc_updated = FALSE;
2447
2448   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2449     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2450       break;
2451
2452     switch (id) {
2453       case GST_MATROSKA_ID_TAG:
2454         ret = gst_matroska_read_common_parse_metadata_id_tag (common, ebml,
2455             &taglist);
2456         break;
2457
2458       default:
2459         ret = gst_matroska_read_common_parse_skip (common, ebml, "Tags", id);
2460         break;
2461         /* FIXME: Use to limit the tags to specific pads */
2462     }
2463   }
2464
2465   DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret);
2466
2467   if (G_LIKELY (!gst_tag_list_is_empty (taglist)))
2468     gst_matroska_read_common_found_global_tag (common, el, taglist);
2469   else
2470     gst_tag_list_unref (taglist);
2471
2472   return ret;
2473 }
2474
2475 static GstFlowReturn
2476 gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
2477     peek, const guint8 ** data)
2478 {
2479   /* Caller needs to gst_adapter_unmap. */
2480   *data = gst_adapter_map (common->adapter, peek);
2481   if (*data == NULL)
2482     return GST_FLOW_EOS;
2483
2484   return GST_FLOW_OK;
2485 }
2486
2487 /*
2488  * Calls pull_range for (offset,size) without advancing our offset
2489  */
2490 GstFlowReturn
2491 gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
2492     offset, guint size, GstBuffer ** p_buf, guint8 ** bytes)
2493 {
2494   GstFlowReturn ret;
2495
2496   /* Caching here actually makes much less difference than one would expect.
2497    * We do it mainly to avoid pulling buffers of 1 byte all the time */
2498   if (common->cached_buffer) {
2499     guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
2500     gsize cache_size = gst_buffer_get_size (common->cached_buffer);
2501
2502     if (cache_offset <= common->offset &&
2503         (common->offset + size) <= (cache_offset + cache_size)) {
2504       if (p_buf)
2505         *p_buf = gst_buffer_copy_region (common->cached_buffer,
2506             GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
2507       if (bytes) {
2508         if (!common->cached_data) {
2509           gst_buffer_map (common->cached_buffer, &common->cached_map,
2510               GST_MAP_READ);
2511           common->cached_data = common->cached_map.data;
2512         }
2513         *bytes = common->cached_data + common->offset - cache_offset;
2514       }
2515       return GST_FLOW_OK;
2516     }
2517     /* not enough data in the cache, free cache and get a new one */
2518     if (common->cached_data) {
2519       gst_buffer_unmap (common->cached_buffer, &common->cached_map);
2520       common->cached_data = NULL;
2521     }
2522     gst_buffer_unref (common->cached_buffer);
2523     common->cached_buffer = NULL;
2524   }
2525
2526   /* refill the cache */
2527   ret = gst_pad_pull_range (common->sinkpad, common->offset,
2528       MAX (size, 64 * 1024), &common->cached_buffer);
2529   if (ret != GST_FLOW_OK) {
2530     common->cached_buffer = NULL;
2531     return ret;
2532   }
2533
2534   if (gst_buffer_get_size (common->cached_buffer) >= size) {
2535     if (p_buf)
2536       *p_buf = gst_buffer_copy_region (common->cached_buffer,
2537           GST_BUFFER_COPY_ALL, 0, size);
2538     if (bytes) {
2539       gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2540       common->cached_data = common->cached_map.data;
2541       *bytes = common->cached_data;
2542     }
2543     return GST_FLOW_OK;
2544   }
2545
2546   /* Not possible to get enough data, try a last time with
2547    * requesting exactly the size we need */
2548   gst_buffer_unref (common->cached_buffer);
2549   common->cached_buffer = NULL;
2550
2551   ret =
2552       gst_pad_pull_range (common->sinkpad, common->offset, size,
2553       &common->cached_buffer);
2554   if (ret != GST_FLOW_OK) {
2555     GST_DEBUG_OBJECT (common, "pull_range returned %d", ret);
2556     if (p_buf)
2557       *p_buf = NULL;
2558     if (bytes)
2559       *bytes = NULL;
2560     return ret;
2561   }
2562
2563   if (gst_buffer_get_size (common->cached_buffer) < size) {
2564     GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
2565         G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
2566         common->offset, size, gst_buffer_get_size (common->cached_buffer));
2567
2568     gst_buffer_unref (common->cached_buffer);
2569     common->cached_buffer = NULL;
2570     if (p_buf)
2571       *p_buf = NULL;
2572     if (bytes)
2573       *bytes = NULL;
2574     return GST_FLOW_EOS;
2575   }
2576
2577   if (p_buf)
2578     *p_buf = gst_buffer_copy_region (common->cached_buffer,
2579         GST_BUFFER_COPY_ALL, 0, size);
2580   if (bytes) {
2581     gst_buffer_map (common->cached_buffer, &common->cached_map, GST_MAP_READ);
2582     common->cached_data = common->cached_map.data;
2583     *bytes = common->cached_data;
2584   }
2585
2586   return GST_FLOW_OK;
2587 }
2588
2589 static GstFlowReturn
2590 gst_matroska_read_common_peek_pull (GstMatroskaReadCommon * common, guint peek,
2591     guint8 ** data)
2592 {
2593   return gst_matroska_read_common_peek_bytes (common, common->offset, peek,
2594       NULL, data);
2595 }
2596
2597 GstFlowReturn
2598 gst_matroska_read_common_peek_id_length_pull (GstMatroskaReadCommon * common,
2599     GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2600 {
2601   return gst_ebml_peek_id_length (_id, _length, _needed,
2602       (GstPeekData) gst_matroska_read_common_peek_pull, (gpointer) common, el,
2603       common->offset);
2604 }
2605
2606 GstFlowReturn
2607 gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
2608     GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
2609 {
2610   GstFlowReturn ret;
2611
2612   ret = gst_ebml_peek_id_length (_id, _length, _needed,
2613       (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
2614       el, common->offset);
2615
2616   gst_adapter_unmap (common->adapter);
2617
2618   return ret;
2619 }
2620
2621 static GstFlowReturn
2622 gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
2623     GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2624 {
2625   GstMatroskaTrackEncoding enc = { 0, };
2626   GstFlowReturn ret;
2627   guint32 id;
2628
2629   DEBUG_ELEMENT_START (common, ebml, "ContentEncoding");
2630   /* Set default values */
2631   enc.scope = 1;
2632   /* All other default values are 0 */
2633
2634   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2635     DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2636     return ret;
2637   }
2638
2639   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2640     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2641       break;
2642
2643     switch (id) {
2644       case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
2645         guint64 num;
2646
2647         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2648           break;
2649
2650         if (!gst_matroska_read_common_encoding_order_unique (context->encodings,
2651                 num)) {
2652           GST_ERROR_OBJECT (common, "ContentEncodingOrder %" G_GUINT64_FORMAT
2653               "is not unique for track %" G_GUINT64_FORMAT, num, context->num);
2654           ret = GST_FLOW_ERROR;
2655           break;
2656         }
2657
2658         GST_DEBUG_OBJECT (common, "ContentEncodingOrder: %" G_GUINT64_FORMAT,
2659             num);
2660         enc.order = num;
2661         break;
2662       }
2663       case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
2664         guint64 num;
2665
2666         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2667           break;
2668
2669         if (num > 7 || num == 0) {
2670           GST_ERROR_OBJECT (common, "Invalid ContentEncodingScope %"
2671               G_GUINT64_FORMAT, num);
2672           ret = GST_FLOW_ERROR;
2673           break;
2674         }
2675
2676         GST_DEBUG_OBJECT (common, "ContentEncodingScope: %" G_GUINT64_FORMAT,
2677             num);
2678         enc.scope = num;
2679
2680         break;
2681       }
2682       case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
2683         guint64 num;
2684
2685         if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
2686           break;
2687
2688         if (num > 1) {
2689           GST_ERROR_OBJECT (common, "Invalid ContentEncodingType %"
2690               G_GUINT64_FORMAT, num);
2691           ret = GST_FLOW_ERROR;
2692           break;
2693         } else if (num != 0) {
2694           GST_ERROR_OBJECT (common, "Encrypted tracks are not supported yet");
2695           ret = GST_FLOW_ERROR;
2696           break;
2697         }
2698         GST_DEBUG_OBJECT (common, "ContentEncodingType: %" G_GUINT64_FORMAT,
2699             num);
2700         enc.type = num;
2701         break;
2702       }
2703       case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
2704
2705         DEBUG_ELEMENT_START (common, ebml, "ContentCompression");
2706
2707         if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
2708           break;
2709
2710         while (ret == GST_FLOW_OK &&
2711             gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2712           if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2713             break;
2714
2715           switch (id) {
2716             case GST_MATROSKA_ID_CONTENTCOMPALGO:{
2717               guint64 num;
2718
2719               if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
2720                 break;
2721               }
2722               if (num > 3) {
2723                 GST_ERROR_OBJECT (common, "Invalid ContentCompAlgo %"
2724                     G_GUINT64_FORMAT, num);
2725                 ret = GST_FLOW_ERROR;
2726                 break;
2727               }
2728               GST_DEBUG_OBJECT (common, "ContentCompAlgo: %" G_GUINT64_FORMAT,
2729                   num);
2730               enc.comp_algo = num;
2731
2732               break;
2733             }
2734             case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{
2735               guint8 *data;
2736               guint64 size;
2737
2738               if ((ret =
2739                       gst_ebml_read_binary (ebml, &id, &data,
2740                           &size)) != GST_FLOW_OK) {
2741                 break;
2742               }
2743               enc.comp_settings = data;
2744               enc.comp_settings_length = size;
2745               GST_DEBUG_OBJECT (common,
2746                   "ContentCompSettings of size %" G_GUINT64_FORMAT, size);
2747               break;
2748             }
2749             default:
2750               GST_WARNING_OBJECT (common,
2751                   "Unknown ContentCompression subelement 0x%x - ignoring", id);
2752               ret = gst_ebml_read_skip (ebml);
2753               break;
2754           }
2755         }
2756         DEBUG_ELEMENT_STOP (common, ebml, "ContentCompression", ret);
2757         break;
2758       }
2759
2760       case GST_MATROSKA_ID_CONTENTENCRYPTION:
2761         GST_ERROR_OBJECT (common, "Encrypted tracks not yet supported");
2762         gst_ebml_read_skip (ebml);
2763         ret = GST_FLOW_ERROR;
2764         break;
2765       default:
2766         GST_WARNING_OBJECT (common,
2767             "Unknown ContentEncoding subelement 0x%x - ignoring", id);
2768         ret = gst_ebml_read_skip (ebml);
2769         break;
2770     }
2771   }
2772
2773   DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
2774   if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2775     return ret;
2776
2777   /* TODO: Check if the combination of values is valid */
2778
2779   g_array_append_val (context->encodings, enc);
2780
2781   return ret;
2782 }
2783
2784 GstFlowReturn
2785 gst_matroska_read_common_read_track_encodings (GstMatroskaReadCommon * common,
2786     GstEbmlRead * ebml, GstMatroskaTrackContext * context)
2787 {
2788   GstFlowReturn ret;
2789   guint32 id;
2790
2791   DEBUG_ELEMENT_START (common, ebml, "ContentEncodings");
2792
2793   if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
2794     DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2795     return ret;
2796   }
2797
2798   context->encodings =
2799       g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
2800
2801   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
2802     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
2803       break;
2804
2805     switch (id) {
2806       case GST_MATROSKA_ID_CONTENTENCODING:
2807         ret = gst_matroska_read_common_read_track_encoding (common, ebml,
2808             context);
2809         break;
2810       default:
2811         GST_WARNING_OBJECT (common,
2812             "Unknown ContentEncodings subelement 0x%x - ignoring", id);
2813         ret = gst_ebml_read_skip (ebml);
2814         break;
2815     }
2816   }
2817
2818   DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
2819   if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
2820     return ret;
2821
2822   /* Sort encodings according to their order */
2823   g_array_sort (context->encodings,
2824       (GCompareFunc) gst_matroska_read_common_encoding_cmp);
2825
2826   return gst_matroska_decode_content_encodings (context->encodings);
2827 }
2828
2829 void
2830 gst_matroska_read_common_free_parsed_el (gpointer mem, gpointer user_data)
2831 {
2832   g_slice_free (guint64, mem);
2833 }
2834
2835 void
2836 gst_matroska_read_common_init (GstMatroskaReadCommon * ctx)
2837 {
2838   ctx->src = NULL;
2839   ctx->writing_app = NULL;
2840   ctx->muxing_app = NULL;
2841   ctx->index = NULL;
2842   ctx->global_tags = NULL;
2843   ctx->adapter = gst_adapter_new ();
2844 }
2845
2846 void
2847 gst_matroska_read_common_finalize (GstMatroskaReadCommon * ctx)
2848 {
2849   if (ctx->src) {
2850     g_ptr_array_free (ctx->src, TRUE);
2851     ctx->src = NULL;
2852   }
2853
2854   if (ctx->global_tags) {
2855     gst_tag_list_unref (ctx->global_tags);
2856     ctx->global_tags = NULL;
2857   }
2858
2859   g_object_unref (ctx->adapter);
2860 }
2861
2862 void
2863 gst_matroska_read_common_reset (GstElement * element,
2864     GstMatroskaReadCommon * ctx)
2865 {
2866   guint i;
2867
2868   GST_LOG_OBJECT (ctx, "resetting read context");
2869
2870   /* reset input */
2871   ctx->state = GST_MATROSKA_READ_STATE_START;
2872
2873   /* clean up existing streams if any */
2874   if (ctx->src) {
2875     g_assert (ctx->src->len == ctx->num_streams);
2876     for (i = 0; i < ctx->src->len; i++) {
2877       GstMatroskaTrackContext *context = g_ptr_array_index (ctx->src, i);
2878
2879       if (context->pad != NULL)
2880         gst_element_remove_pad (element, context->pad);
2881
2882       gst_caps_replace (&context->caps, NULL);
2883       gst_matroska_track_free (context);
2884     }
2885     g_ptr_array_free (ctx->src, TRUE);
2886   }
2887   ctx->src = g_ptr_array_new ();
2888   ctx->num_streams = 0;
2889
2890   /* reset media info */
2891   g_free (ctx->writing_app);
2892   ctx->writing_app = NULL;
2893   g_free (ctx->muxing_app);
2894   ctx->muxing_app = NULL;
2895
2896   /* reset stream type */
2897   ctx->is_webm = FALSE;
2898   ctx->has_video = FALSE;
2899
2900   /* reset indexes */
2901   if (ctx->index) {
2902     g_array_free (ctx->index, TRUE);
2903     ctx->index = NULL;
2904   }
2905
2906   /* reset timers */
2907   ctx->time_scale = 1000000;
2908   ctx->created = G_MININT64;
2909
2910   /* cues/tracks/segmentinfo */
2911   ctx->index_parsed = FALSE;
2912   ctx->segmentinfo_parsed = FALSE;
2913   ctx->attachments_parsed = FALSE;
2914   ctx->chapters_parsed = FALSE;
2915
2916   /* tags */
2917   g_list_foreach (ctx->tags_parsed,
2918       (GFunc) gst_matroska_read_common_free_parsed_el, NULL);
2919   g_list_free (ctx->tags_parsed);
2920   ctx->tags_parsed = NULL;
2921   if (ctx->global_tags) {
2922     gst_tag_list_unref (ctx->global_tags);
2923   }
2924   ctx->global_tags = gst_tag_list_new_empty ();
2925   gst_tag_list_set_scope (ctx->global_tags, GST_TAG_SCOPE_GLOBAL);
2926
2927   gst_segment_init (&ctx->segment, GST_FORMAT_TIME);
2928   ctx->offset = 0;
2929
2930   if (ctx->cached_buffer) {
2931     if (ctx->cached_data) {
2932       gst_buffer_unmap (ctx->cached_buffer, &ctx->cached_map);
2933       ctx->cached_data = NULL;
2934     }
2935     gst_buffer_unref (ctx->cached_buffer);
2936     ctx->cached_buffer = NULL;
2937   }
2938
2939   /* free chapters TOC if any */
2940   if (ctx->toc) {
2941     gst_toc_unref (ctx->toc);
2942     ctx->toc = NULL;
2943   }
2944 }
2945
2946 /* call with object lock held */
2947 void
2948 gst_matroska_read_common_reset_streams (GstMatroskaReadCommon * common,
2949     GstClockTime time, gboolean full)
2950 {
2951   gint i;
2952
2953   GST_DEBUG_OBJECT (common, "resetting stream state");
2954
2955   g_assert (common->src->len == common->num_streams);
2956   for (i = 0; i < common->src->len; i++) {
2957     GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2958     context->pos = time;
2959     context->set_discont = TRUE;
2960     context->eos = FALSE;
2961     context->from_time = GST_CLOCK_TIME_NONE;
2962     if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
2963       GstMatroskaTrackVideoContext *videocontext =
2964           (GstMatroskaTrackVideoContext *) context;
2965       /* demux object lock held by caller */
2966       videocontext->earliest_time = GST_CLOCK_TIME_NONE;
2967     }
2968   }
2969 }
2970
2971 gboolean
2972 gst_matroska_read_common_tracknumber_unique (GstMatroskaReadCommon * common,
2973     guint64 num)
2974 {
2975   gint i;
2976
2977   g_assert (common->src->len == common->num_streams);
2978   for (i = 0; i < common->src->len; i++) {
2979     GstMatroskaTrackContext *context = g_ptr_array_index (common->src, i);
2980
2981     if (context->num == num)
2982       return FALSE;
2983   }
2984
2985   return TRUE;
2986 }