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