gst/matroska/ebml-read.c: Prevent unaligned memory access when reading floats.
[platform/upstream/gst-plugins-good.git] / gst / matroska / ebml-read.c
1 /* GStreamer EBML I/O
2  * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  *
4  * ebml-read.c: read EBML data from file/stream
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <string.h>
27 #include <gst/floatcast/floatcast.h>
28
29 #include "ebml-read.h"
30 #include "ebml-ids.h"
31
32 #include <math.h>
33
34 GST_DEBUG_CATEGORY_STATIC (ebmlread_debug);
35 #define GST_CAT_DEFAULT ebmlread_debug
36
37 static void gst_ebml_read_class_init (GstEbmlReadClass * klass);
38
39 static void gst_ebml_read_init (GstEbmlRead * ebml);
40
41 static GstStateChangeReturn gst_ebml_read_change_state (GstElement * element,
42     GstStateChange transition);
43
44 /* convenience functions */
45 static GstFlowReturn gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size,
46     GstBuffer ** p_buf, guint8 ** bytes);
47 static GstFlowReturn gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size,
48     GstBuffer ** p_buf, guint8 ** bytes);
49
50
51 static GstElementClass *parent_class;   /* NULL */
52
53 GType
54 gst_ebml_read_get_type (void)
55 {
56   static GType gst_ebml_read_type;      /* 0 */
57
58   if (!gst_ebml_read_type) {
59     static const GTypeInfo gst_ebml_read_info = {
60       sizeof (GstEbmlReadClass),
61       NULL,
62       NULL,
63       (GClassInitFunc) gst_ebml_read_class_init,
64       NULL,
65       NULL,
66       sizeof (GstEbmlRead),
67       0,
68       (GInstanceInitFunc) gst_ebml_read_init,
69     };
70
71     gst_ebml_read_type =
72         g_type_register_static (GST_TYPE_ELEMENT, "GstEbmlRead",
73         &gst_ebml_read_info, 0);
74   }
75
76   return gst_ebml_read_type;
77 }
78
79 void
80 gst_ebml_level_free (GstEbmlLevel * level)
81 {
82   g_slice_free (GstEbmlLevel, level);
83 }
84
85 static void
86 gst_ebml_finalize (GObject * obj)
87 {
88   GstEbmlRead *ebml = GST_EBML_READ (obj);
89
90   g_list_foreach (ebml->level, (GFunc) gst_ebml_level_free, NULL);
91   g_list_free (ebml->level);
92   ebml->level = NULL;
93   if (ebml->cached_buffer) {
94     gst_buffer_unref (ebml->cached_buffer);
95     ebml->cached_buffer = NULL;
96   }
97
98   G_OBJECT_CLASS (parent_class)->finalize (obj);
99 }
100
101 static void
102 gst_ebml_read_class_init (GstEbmlReadClass * klass)
103 {
104   GstElementClass *gstelement_class = (GstElementClass *) klass;
105
106   GObjectClass *gobject_class = (GObjectClass *) klass;
107
108   parent_class = g_type_class_peek_parent (klass);
109
110   GST_DEBUG_CATEGORY_INIT (ebmlread_debug, "ebmlread",
111       0, "EBML stream helper class");
112
113   gobject_class->finalize = gst_ebml_finalize;
114
115   gstelement_class->change_state =
116       GST_DEBUG_FUNCPTR (gst_ebml_read_change_state);
117 }
118
119 static void
120 gst_ebml_read_init (GstEbmlRead * ebml)
121 {
122   ebml->sinkpad = NULL;
123   ebml->level = NULL;
124 }
125
126 static GstStateChangeReturn
127 gst_ebml_read_change_state (GstElement * element, GstStateChange transition)
128 {
129   GstStateChangeReturn ret;
130
131   GstEbmlRead *ebml = GST_EBML_READ (element);
132
133   switch (transition) {
134     case GST_STATE_CHANGE_READY_TO_PAUSED:
135       if (!ebml->sinkpad) {
136         g_return_val_if_reached (GST_STATE_CHANGE_FAILURE);
137       }
138       break;
139     default:
140       break;
141   }
142
143   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
144
145   switch (transition) {
146     case GST_STATE_CHANGE_PAUSED_TO_READY:
147     {
148       g_list_foreach (ebml->level, (GFunc) gst_ebml_level_free, NULL);
149       g_list_free (ebml->level);
150       ebml->level = NULL;
151       if (ebml->cached_buffer) {
152         gst_buffer_unref (ebml->cached_buffer);
153         ebml->cached_buffer = NULL;
154       }
155       ebml->offset = 0;
156       break;
157     }
158     default:
159       break;
160   }
161
162   return ret;
163 }
164
165 /*
166  * Return: the amount of levels in the hierarchy that the
167  * current element lies higher than the previous one.
168  * The opposite isn't done - that's auto-done using master
169  * element reading.
170  */
171
172 static guint
173 gst_ebml_read_element_level_up (GstEbmlRead * ebml)
174 {
175   guint num = 0;
176
177   guint64 pos = ebml->offset;
178
179   while (ebml->level != NULL) {
180     GstEbmlLevel *level = ebml->level->data;
181
182     if (pos >= level->start + level->length) {
183       ebml->level = g_list_delete_link (ebml->level, ebml->level);
184       gst_ebml_level_free (level);
185       num++;
186     } else {
187       break;
188     }
189   }
190
191   return num;
192 }
193
194 /*
195  * Calls pull_range for (offset,size) without advancing our offset
196  */
197 static GstFlowReturn
198 gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
199     guint8 ** bytes)
200 {
201   GstFlowReturn ret;
202
203   /* Caching here actually makes much less difference than one would expect.
204    * We do it mainly to avoid pulling buffers of 1 byte all the time */
205   if (ebml->cached_buffer) {
206     guint64 cache_offset = GST_BUFFER_OFFSET (ebml->cached_buffer);
207
208     guint cache_size = GST_BUFFER_SIZE (ebml->cached_buffer);
209
210     if (cache_offset <= ebml->offset &&
211         (ebml->offset + size) < (cache_offset + cache_size)) {
212       if (p_buf)
213         *p_buf = gst_buffer_create_sub (ebml->cached_buffer,
214             ebml->offset - cache_offset, size);
215       if (bytes)
216         *bytes =
217             GST_BUFFER_DATA (ebml->cached_buffer) + ebml->offset - cache_offset;
218       return GST_FLOW_OK;
219     }
220     /* not enough data in the cache, free cache and get a new one */
221     gst_buffer_unref (ebml->cached_buffer);
222     ebml->cached_buffer = NULL;
223   }
224
225   /* refill the cache */
226   ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024),
227       &ebml->cached_buffer);
228   if (ret != GST_FLOW_OK) {
229     ebml->cached_buffer = NULL;
230     return ret;
231   }
232
233   if (GST_BUFFER_SIZE (ebml->cached_buffer) >= size) {
234     if (p_buf)
235       *p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
236     if (bytes)
237       *bytes = GST_BUFFER_DATA (ebml->cached_buffer);
238     return GST_FLOW_OK;
239   }
240
241   /* Not possible to get enough data, try a last time with
242    * requesting exactly the size we need */
243   gst_buffer_unref (ebml->cached_buffer);
244   ebml->cached_buffer = NULL;
245
246   ret =
247       gst_pad_pull_range (ebml->sinkpad, ebml->offset, size,
248       &ebml->cached_buffer);
249   if (ret != GST_FLOW_OK) {
250     GST_DEBUG ("pull_range returned %d", ret);
251     if (p_buf)
252       *p_buf = NULL;
253     if (bytes)
254       *bytes = NULL;
255     return ret;
256   }
257
258   if (GST_BUFFER_SIZE (ebml->cached_buffer) < size) {
259     GST_WARNING_OBJECT (ebml, "Dropping short buffer at offset %"
260         G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", ebml->offset,
261         size, GST_BUFFER_SIZE (ebml->cached_buffer));
262
263     gst_buffer_unref (ebml->cached_buffer);
264     ebml->cached_buffer = NULL;
265     if (p_buf)
266       *p_buf = NULL;
267     if (bytes)
268       *bytes = NULL;
269     return GST_FLOW_ERROR;
270   }
271
272   if (p_buf)
273     *p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
274   if (bytes)
275     *bytes = GST_BUFFER_DATA (*p_buf);
276
277   return GST_FLOW_OK;
278 }
279
280 /*
281  * Calls pull_range for (offset,size) and advances our offset by size
282  */
283 static GstFlowReturn
284 gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
285     guint8 ** bytes)
286 {
287   GstFlowReturn ret;
288
289   ret = gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes);
290   if (ret != GST_FLOW_OK)
291     return ret;
292
293   ebml->offset += size;
294   return GST_FLOW_OK;
295 }
296
297 /*
298  * Read: the element content data ID.
299  * Return: FALSE on error.
300  */
301
302 static GstFlowReturn
303 gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
304 {
305   guint8 *buf;
306
307   gint len_mask = 0x80, read = 1, n = 1;
308
309   guint32 total;
310
311   guint8 b;
312
313   GstFlowReturn ret;
314
315   ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
316   if (ret != GST_FLOW_OK)
317     return ret;
318
319   b = GST_READ_UINT8 (buf);
320
321   total = (guint32) b;
322
323   while (read <= 4 && !(total & len_mask)) {
324     read++;
325     len_mask >>= 1;
326   }
327   if (read > 4) {
328     guint64 pos = ebml->offset;
329
330     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
331         ("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT
332             " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
333     return GST_FLOW_ERROR;
334   }
335
336   ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
337   if (ret != GST_FLOW_OK)
338     return ret;
339
340   while (n < read) {
341     b = GST_READ_UINT8 (buf + n);
342     total = (total << 8) | b;
343     ++n;
344   }
345
346   *id = total;
347
348   /* level */
349   if (level_up)
350     *level_up = gst_ebml_read_element_level_up (ebml);
351
352   ebml->offset += read;
353   return GST_FLOW_OK;
354 }
355
356 /*
357  * Read: element content length.
358  * Return: the number of bytes read or -1 on error.
359  */
360
361 static GstFlowReturn
362 gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length,
363     gint * rread)
364 {
365   GstFlowReturn ret;
366
367   guint8 *buf;
368
369   gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
370
371   guint64 total;
372
373   guint8 b;
374
375   ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
376   if (ret != GST_FLOW_OK)
377     return ret;
378
379   b = GST_READ_UINT8 (buf);
380
381   total = (guint64) b;
382
383   while (read <= 8 && !(total & len_mask)) {
384     read++;
385     len_mask >>= 1;
386   }
387   if (read > 8) {
388     guint64 pos = ebml->offset;
389
390     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
391         ("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT
392             " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
393     return GST_FLOW_ERROR;
394   }
395
396   if ((total &= (len_mask - 1)) == len_mask - 1)
397     num_ffs++;
398
399   ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
400   if (ret != GST_FLOW_OK)
401     return ret;
402
403   while (n < read) {
404     guint8 b = GST_READ_UINT8 (buf + n);
405
406     if (b == 0xff)
407       num_ffs++;
408     total = (total << 8) | b;
409     ++n;
410   }
411
412   if (read == num_ffs)
413     *length = G_MAXUINT64;
414   else
415     *length = total;
416
417   if (rread)
418     *rread = read;
419
420   ebml->offset += read;
421
422   return GST_FLOW_OK;
423 }
424
425 /*
426  * Return: the ID of the next element.
427  * Level_up contains the amount of levels that this
428  * next element lies higher than the previous one.
429  */
430
431 GstFlowReturn
432 gst_ebml_peek_id (GstEbmlRead * ebml, guint * level_up, guint32 * id)
433 {
434   guint64 off;
435
436   guint level_up_tmp = 0;
437
438   GstFlowReturn ret;
439
440   g_assert (level_up);
441   g_assert (id);
442
443   *level_up = 0;
444
445 next:
446   off = ebml->offset;           /* save offset */
447
448   if ((ret = gst_ebml_read_element_id (ebml, id, &level_up_tmp)) != GST_FLOW_OK)
449     return ret;
450
451   ebml->offset = off;           /* restore offset */
452
453   *level_up += level_up_tmp;
454   level_up_tmp = 0;
455
456   switch (*id) {
457     case GST_EBML_ID_VOID:
458       GST_DEBUG_OBJECT (ebml, "Skipping EBML Void element");
459       if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
460         return ret;
461       goto next;
462       break;
463     case GST_EBML_ID_CRC32:
464       GST_DEBUG_OBJECT (ebml, "Skipping EBML CRC32 element");
465       if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
466         return ret;
467       goto next;
468       break;
469   }
470
471   return ret;
472 }
473
474 /*
475  * Return the length of the stream in bytes
476  */
477
478 gint64
479 gst_ebml_read_get_length (GstEbmlRead * ebml)
480 {
481   GstFormat fmt = GST_FORMAT_BYTES;
482
483   gint64 end;
484
485   /* FIXME: what to do if we don't get the upstream length */
486   if (!gst_pad_query_peer_duration (ebml->sinkpad, &fmt, &end) ||
487       fmt != GST_FORMAT_BYTES || end < 0)
488     g_return_val_if_reached (0);
489
490   return end;
491 }
492
493 /*
494  * Seek to a given offset.
495  */
496
497 GstFlowReturn
498 gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset)
499 {
500   if (offset >= gst_ebml_read_get_length (ebml))
501     return GST_FLOW_UNEXPECTED;
502
503   ebml->offset = offset;
504
505   return GST_FLOW_OK;
506 }
507
508 /*
509  * Skip the next element.
510  */
511
512 GstFlowReturn
513 gst_ebml_read_skip (GstEbmlRead * ebml)
514 {
515   guint64 length;
516
517   guint32 id;
518
519   GstFlowReturn ret;
520
521   ret = gst_ebml_read_element_id (ebml, &id, NULL);
522   if (ret != GST_FLOW_OK)
523     return ret;
524
525   ret = gst_ebml_read_element_length (ebml, &length, NULL);
526   if (ret != GST_FLOW_OK)
527     return ret;
528
529   ebml->offset += length;
530   return ret;
531 }
532
533 /*
534  * Read the next element as a GstBuffer (binary).
535  */
536
537 GstFlowReturn
538 gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf)
539 {
540   guint64 length;
541
542   GstFlowReturn ret;
543
544   ret = gst_ebml_read_element_id (ebml, id, NULL);
545   if (ret != GST_FLOW_OK)
546     return ret;
547
548   ret = gst_ebml_read_element_length (ebml, &length, NULL);
549   if (ret != GST_FLOW_OK)
550     return ret;
551
552   if (length == 0) {
553     *buf = gst_buffer_new ();
554     return GST_FLOW_OK;
555   }
556
557   *buf = NULL;
558   ret = gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL);
559
560   return ret;
561 }
562
563 /*
564  * Read the next element, return a pointer to it and its size.
565  */
566
567 static GstFlowReturn
568 gst_ebml_read_bytes (GstEbmlRead * ebml, guint32 * id, guint8 ** data,
569     guint * size)
570 {
571   guint64 length;
572
573   GstFlowReturn ret;
574
575   *size = 0;
576
577   ret = gst_ebml_read_element_id (ebml, id, NULL);
578   if (ret != GST_FLOW_OK)
579     return ret;
580
581   ret = gst_ebml_read_element_length (ebml, &length, NULL);
582   if (ret != GST_FLOW_OK)
583     return ret;
584
585   if (length == 0) {
586     *data = NULL;
587     return ret;
588   }
589
590   *data = NULL;
591   ret = gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data);
592   if (ret != GST_FLOW_OK)
593     return ret;
594
595   *size = (guint) length;
596
597   return ret;
598 }
599
600 /*
601  * Read the next element as an unsigned int.
602  */
603
604 GstFlowReturn
605 gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
606 {
607   guint8 *data;
608
609   guint size;
610
611   GstFlowReturn ret;
612
613   ret = gst_ebml_read_bytes (ebml, id, &data, &size);
614   if (ret != GST_FLOW_OK)
615     return ret;
616
617   if (size < 1 || size > 8) {
618     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
619         ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
620             " (0x%" G_GINT64_MODIFIER "x)",
621             size, ebml->offset - size, ebml->offset - size));
622     return GST_FLOW_ERROR;
623   }
624   *num = 0;
625   while (size > 0) {
626     *num = (*num << 8) | *data;
627     size--;
628     data++;
629   }
630
631   return ret;
632 }
633
634 /*
635  * Read the next element as a signed int.
636  */
637
638 GstFlowReturn
639 gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
640 {
641   guint8 *data;
642
643   guint size;
644
645   gboolean negative = 0;
646
647   GstFlowReturn ret;
648
649   ret = gst_ebml_read_bytes (ebml, id, &data, &size);
650   if (ret != GST_FLOW_OK)
651     return ret;
652
653   if (size < 1 || size > 8) {
654     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
655         ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
656             " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
657             ebml->offset - size));
658     return GST_FLOW_ERROR;
659   }
660
661   *num = 0;
662   if (*data & 0x80) {
663     negative = 1;
664     *num = *data & ~0x80;
665     size--;
666     data++;
667   }
668
669   while (size > 0) {
670     *num = (*num << 8) | *data;
671     size--;
672     data++;
673   }
674
675   /* make signed */
676   if (negative) {
677     *num = 0 - *num;
678   }
679
680   return ret;
681 }
682
683 /* Convert 80 bit extended precision float in big endian format to double.
684  * Code taken from libavutil/intfloat_readwrite.c from ffmpeg,
685  * licensed under LGPL */
686
687 struct _ext_float
688 {
689   guint8 exponent[2];
690   guint8 mantissa[8];
691 };
692
693 static gdouble
694 _ext2dbl (guint8 * data)
695 {
696   struct _ext_float ext;
697
698   guint64 m = 0;
699
700   gint e, i;
701
702   memcpy (&ext.exponent, data, 2);
703   memcpy (&ext.mantissa, data + 2, 8);
704
705   for (i = 0; i < 8; i++)
706     m = (m << 8) + ext.mantissa[i];
707   e = (((gint) ext.exponent[0] & 0x7f) << 8) | ext.exponent[1];
708   if (e == 0x7fff && m)
709     return 0.0 / 0.0;
710   e -= 16383 + 63;              /* In IEEE 80 bits, the whole (i.e. 1.xxxx)
711                                  * mantissa bit is written as opposed to the
712                                  * single and double precision formats */
713   if (ext.exponent[0] & 0x80)
714     m = -m;
715   return ldexp (m, e);
716 }
717
718 /*
719  * Read the next element as a float.
720  */
721
722 GstFlowReturn
723 gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
724 {
725   guint8 *data;
726
727   guint size;
728
729   GstFlowReturn ret;
730
731   ret = gst_ebml_read_bytes (ebml, id, &data, &size);
732   if (ret != GST_FLOW_OK)
733     return ret;
734
735   if (size != 4 && size != 8 && size != 10) {
736     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
737         ("Invalid float element size %d at position %" G_GUINT64_FORMAT
738             " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
739             ebml->offset - size));
740     return GST_FLOW_ERROR;
741   }
742
743   if (size == 4) {
744     gfloat f;
745
746     memcpy (&f, data, 4);
747     f = GFLOAT_FROM_BE (f);
748
749     *num = f;
750   } else if (size == 8) {
751     gdouble d;
752
753     memcpy (&d, data, 8);
754     d = GDOUBLE_FROM_BE (d);
755
756     *num = d;
757   } else {
758     *num = _ext2dbl (data);
759   }
760
761   return ret;
762 }
763
764 /*
765  * Read the next element as an ASCII string.
766  */
767
768 GstFlowReturn
769 gst_ebml_read_ascii (GstEbmlRead * ebml, guint32 * id, gchar ** str)
770 {
771   guint8 *data;
772
773   guint size;
774
775   GstFlowReturn ret;
776
777   ret = gst_ebml_read_bytes (ebml, id, &data, &size);
778   if (ret != GST_FLOW_OK)
779     return ret;
780
781   *str = g_malloc (size + 1);
782   memcpy (*str, data, size);
783   (*str)[size] = '\0';
784
785   return ret;
786 }
787
788 /*
789  * Read the next element as a UTF-8 string.
790  */
791
792 GstFlowReturn
793 gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str)
794 {
795   GstFlowReturn ret;
796
797 #ifndef GST_DISABLE_GST_DEBUG
798   guint64 oldoff = ebml->offset;
799 #endif
800
801   ret = gst_ebml_read_ascii (ebml, id, str);
802   if (ret != GST_FLOW_OK)
803     return ret;
804
805   if (str != NULL && *str != NULL && **str != '\0' &&
806       !g_utf8_validate (*str, -1, NULL)) {
807     GST_WARNING ("Invalid UTF-8 string at offset %" G_GUINT64_FORMAT, oldoff);
808   }
809
810   return ret;
811 }
812
813 /*
814  * Read the next element as a date.
815  * Returns the seconds since the unix epoch.
816  */
817
818 GstFlowReturn
819 gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date)
820 {
821   gint64 ebml_date;
822
823   GstFlowReturn ret;
824
825   ret = gst_ebml_read_sint (ebml, id, &ebml_date);
826   if (ret != GST_FLOW_OK)
827     return ret;
828
829   *date = (ebml_date / GST_SECOND) + GST_EBML_DATE_OFFSET;
830
831   return ret;
832 }
833
834 /*
835  * Read the next element, but only the header. The contents
836  * are supposed to be sub-elements which can be read separately.
837  */
838
839 GstFlowReturn
840 gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id)
841 {
842   GstEbmlLevel *level;
843
844   guint64 length;
845
846   GstFlowReturn ret;
847
848   ret = gst_ebml_read_element_id (ebml, id, NULL);
849   if (ret != GST_FLOW_OK)
850     return ret;
851
852   ret = gst_ebml_read_element_length (ebml, &length, NULL);
853   if (ret != GST_FLOW_OK)
854     return ret;
855
856   /* remember level */
857   level = g_slice_new (GstEbmlLevel);
858   level->start = ebml->offset;
859   level->length = length;
860   ebml->level = g_list_prepend (ebml->level, level);
861
862   return GST_FLOW_OK;
863 }
864
865 /*
866  * Read the next element as binary data.
867  */
868
869 GstFlowReturn
870 gst_ebml_read_binary (GstEbmlRead * ebml,
871     guint32 * id, guint8 ** binary, guint64 * length)
872 {
873   guint8 *data;
874
875   guint size;
876
877   GstFlowReturn ret;
878
879   ret = gst_ebml_read_bytes (ebml, id, &data, &size);
880   if (ret != GST_FLOW_OK)
881     return ret;
882
883   *length = size;
884   *binary = g_memdup (data, size);
885
886   return GST_FLOW_OK;
887 }
888
889 /*
890  * Read an EBML header.
891  */
892
893 GstFlowReturn
894 gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
895 {
896   /* this function is the first to be called */
897   guint32 id;
898
899   guint level_up;
900
901   GstFlowReturn ret;
902
903   /* default init */
904   if (doctype)
905     *doctype = NULL;
906   if (version)
907     *version = 1;
908
909   ret = gst_ebml_peek_id (ebml, &level_up, &id);
910   if (ret != GST_FLOW_OK)
911     return ret;
912
913   GST_DEBUG_OBJECT (ebml, "id: %08x", GST_READ_UINT32_BE (&id));
914
915   if (level_up != 0 || id != GST_EBML_ID_HEADER) {
916     GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
917     return GST_FLOW_ERROR;
918   }
919   ret = gst_ebml_read_master (ebml, &id);
920   if (ret != GST_FLOW_OK)
921     return ret;
922
923   while (TRUE) {
924     ret = gst_ebml_peek_id (ebml, &level_up, &id);
925     if (ret != GST_FLOW_OK)
926       return ret;
927
928     /* end-of-header */
929     if (level_up)
930       break;
931
932     switch (id) {
933         /* is our read version uptodate? */
934       case GST_EBML_ID_EBMLREADVERSION:{
935         guint64 num;
936
937         ret = gst_ebml_read_uint (ebml, &id, &num);
938         if (ret != GST_FLOW_OK)
939           return ret;
940         g_assert (id == GST_EBML_ID_EBMLREADVERSION);
941         if (num != GST_EBML_VERSION) {
942           GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
943           return GST_FLOW_ERROR;
944         }
945         break;
946       }
947
948         /* we only handle 8 byte lengths at max */
949       case GST_EBML_ID_EBMLMAXSIZELENGTH:{
950         guint64 num;
951
952         ret = gst_ebml_read_uint (ebml, &id, &num);
953         if (ret != GST_FLOW_OK)
954           return ret;
955         g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
956         if (num > sizeof (guint64)) {
957           GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
958           return GST_FLOW_ERROR;
959         }
960         break;
961       }
962
963         /* we handle 4 byte IDs at max */
964       case GST_EBML_ID_EBMLMAXIDLENGTH:{
965         guint64 num;
966
967         ret = gst_ebml_read_uint (ebml, &id, &num);
968         if (ret != GST_FLOW_OK)
969           return ret;
970         g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
971         if (num > sizeof (guint32)) {
972           GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
973           return GST_FLOW_ERROR;
974         }
975         break;
976       }
977
978       case GST_EBML_ID_DOCTYPE:{
979         gchar *text;
980
981         ret = gst_ebml_read_ascii (ebml, &id, &text);
982         if (ret != GST_FLOW_OK)
983           return ret;
984         g_assert (id == GST_EBML_ID_DOCTYPE);
985         if (doctype) {
986           g_free (*doctype);
987           *doctype = text;
988         } else
989           g_free (text);
990         break;
991       }
992
993       case GST_EBML_ID_DOCTYPEREADVERSION:{
994         guint64 num;
995
996         ret = gst_ebml_read_uint (ebml, &id, &num);
997         if (ret != GST_FLOW_OK)
998           return ret;
999         g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION);
1000         if (version)
1001           *version = num;
1002         break;
1003       }
1004
1005       default:
1006         GST_WARNING ("Unknown data type 0x%x in EBML header (ignored)", id);
1007         /* pass-through */
1008
1009         /* we ignore these two, as they don't tell us anything we care about */
1010       case GST_EBML_ID_EBMLVERSION:
1011       case GST_EBML_ID_DOCTYPEVERSION:
1012         ret = gst_ebml_read_skip (ebml);
1013         if (ret != GST_FLOW_OK)
1014           return ret;
1015         break;
1016     }
1017   }
1018
1019   return GST_FLOW_OK;
1020 }