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