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