Add explanatory comments to the #endif part of multiple inclusion guards.
[mplayer/greg.git] / libmpdemux / ebml.c
blob756d1713ce2638692a3a560d9f47c43ccfd95312
1 /*
2 * native ebml reader for the Matroska demuxer
3 * Written by Aurelien Jacobs <aurel@gnuage.org>
4 * Based on the one written by Ronald Bultje for gstreamer
5 * Licence: GPL
6 */
8 #include "config.h"
10 #include <stdlib.h>
12 #include "stream/stream.h"
13 #include "ebml.h"
14 #include "libavutil/common.h"
15 #include "mpbswap.h"
16 #include "libavutil/intfloat_readwrite.h"
19 #ifndef SIZE_MAX
20 #define SIZE_MAX ((size_t)-1)
21 #endif
24 * Read: the element content data ID.
25 * Return: the ID.
27 uint32_t
28 ebml_read_id (stream_t *s, int *length)
30 int i, len_mask = 0x80;
31 uint32_t id;
33 for (i=0, id=stream_read_char (s); i<4 && !(id & len_mask); i++)
34 len_mask >>= 1;
35 if (i >= 4)
36 return EBML_ID_INVALID;
37 if (length)
38 *length = i + 1;
39 while (i--)
40 id = (id << 8) | stream_read_char (s);
41 return id;
45 * Read a variable length unsigned int.
47 uint64_t
48 ebml_read_vlen_uint (uint8_t *buffer, int *length)
50 int i, j, num_ffs = 0, len_mask = 0x80;
51 uint64_t num;
53 for (i=0, num=*buffer++; i<8 && !(num & len_mask); i++)
54 len_mask >>= 1;
55 if (i >= 8)
56 return EBML_UINT_INVALID;
57 j = i+1;
58 if (length)
59 *length = j;
60 if ((int)(num &= (len_mask - 1)) == len_mask - 1)
61 num_ffs++;
62 while (i--)
64 num = (num << 8) | *buffer++;
65 if ((num & 0xFF) == 0xFF)
66 num_ffs++;
68 if (j == num_ffs)
69 return EBML_UINT_INVALID;
70 return num;
74 * Read a variable length signed int.
76 int64_t
77 ebml_read_vlen_int (uint8_t *buffer, int *length)
79 uint64_t unum;
80 int l;
82 /* read as unsigned number first */
83 unum = ebml_read_vlen_uint (buffer, &l);
84 if (unum == EBML_UINT_INVALID)
85 return EBML_INT_INVALID;
86 if (length)
87 *length = l;
89 return unum - ((1 << ((7 * l) - 1)) - 1);
93 * Read: element content length.
95 uint64_t
96 ebml_read_length (stream_t *s, int *length)
98 int i, j, num_ffs = 0, len_mask = 0x80;
99 uint64_t len;
101 for (i=0, len=stream_read_char (s); i<8 && !(len & len_mask); i++)
102 len_mask >>= 1;
103 if (i >= 8)
104 return EBML_UINT_INVALID;
105 j = i+1;
106 if (length)
107 *length = j;
108 if ((int)(len &= (len_mask - 1)) == len_mask - 1)
109 num_ffs++;
110 while (i--)
112 len = (len << 8) | stream_read_char (s);
113 if ((len & 0xFF) == 0xFF)
114 num_ffs++;
116 if (j == num_ffs)
117 return EBML_UINT_INVALID;
118 return len;
122 * Read the next element as an unsigned int.
124 uint64_t
125 ebml_read_uint (stream_t *s, uint64_t *length)
127 uint64_t len, value = 0;
128 int l;
130 len = ebml_read_length (s, &l);
131 if (len == EBML_UINT_INVALID || len < 1 || len > 8)
132 return EBML_UINT_INVALID;
133 if (length)
134 *length = len + l;
136 while (len--)
137 value = (value << 8) | stream_read_char (s);
139 return value;
143 * Read the next element as a signed int.
145 int64_t
146 ebml_read_int (stream_t *s, uint64_t *length)
148 int64_t value = 0;
149 uint64_t len;
150 int l;
152 len = ebml_read_length (s, &l);
153 if (len == EBML_UINT_INVALID || len < 1 || len > 8)
154 return EBML_INT_INVALID;
155 if (length)
156 *length = len + l;
158 len--;
159 l = stream_read_char (s);
160 if (l & 0x80)
161 value = -1;
162 value = (value << 8) | l;
163 while (len--)
164 value = (value << 8) | stream_read_char (s);
166 return value;
170 * Read the next element as a float.
172 long double
173 ebml_read_float (stream_t *s, uint64_t *length)
175 long double value;
176 uint64_t len;
177 int l;
179 len = ebml_read_length (s, &l);
180 switch (len)
182 case 4:
183 value = av_int2flt(stream_read_dword(s));
184 break;
186 case 8:
187 value = av_int2dbl(stream_read_qword(s));
188 break;
190 default:
191 return EBML_FLOAT_INVALID;
194 if (length)
195 *length = len + l;
197 return value;
201 * Read the next element as an ASCII string.
203 char *
204 ebml_read_ascii (stream_t *s, uint64_t *length)
206 uint64_t len;
207 char *str;
208 int l;
210 len = ebml_read_length (s, &l);
211 if (len == EBML_UINT_INVALID)
212 return NULL;
213 if (len > SIZE_MAX - 1)
214 return NULL;
215 if (length)
216 *length = len + l;
218 str = (char *) malloc (len+1);
219 if (stream_read(s, str, len) != (int) len)
221 free (str);
222 return NULL;
224 str[len] = '\0';
226 return str;
230 * Read the next element as a UTF-8 string.
232 char *
233 ebml_read_utf8 (stream_t *s, uint64_t *length)
235 return ebml_read_ascii (s, length);
239 * Skip the next element.
242 ebml_read_skip (stream_t *s, uint64_t *length)
244 uint64_t len;
245 int l;
247 len = ebml_read_length (s, &l);
248 if (len == EBML_UINT_INVALID)
249 return 1;
250 if (length)
251 *length = len + l;
253 stream_skip(s, len);
255 return 0;
259 * Read the next element, but only the header. The contents
260 * are supposed to be sub-elements which can be read separately.
262 uint32_t
263 ebml_read_master (stream_t *s, uint64_t *length)
265 uint64_t len;
266 uint32_t id;
268 id = ebml_read_id (s, NULL);
269 if (id == EBML_ID_INVALID)
270 return id;
272 len = ebml_read_length (s, NULL);
273 if (len == EBML_UINT_INVALID)
274 return EBML_ID_INVALID;
275 if (length)
276 *length = len;
278 return id;
283 * Read an EBML header.
285 char *
286 ebml_read_header (stream_t *s, int *version)
288 uint64_t length, l, num;
289 uint32_t id;
290 char *str = NULL;
292 if (ebml_read_master (s, &length) != EBML_ID_HEADER)
293 return 0;
295 if (version)
296 *version = 1;
298 while (length > 0)
300 id = ebml_read_id (s, NULL);
301 if (id == EBML_ID_INVALID)
302 return NULL;
303 length -= 2;
305 switch (id)
307 /* is our read version uptodate? */
308 case EBML_ID_EBMLREADVERSION:
309 num = ebml_read_uint (s, &l);
310 if (num != EBML_VERSION)
311 return NULL;
312 break;
314 /* we only handle 8 byte lengths at max */
315 case EBML_ID_EBMLMAXSIZELENGTH:
316 num = ebml_read_uint (s, &l);
317 if (num != sizeof (uint64_t))
318 return NULL;
319 break;
321 /* we handle 4 byte IDs at max */
322 case EBML_ID_EBMLMAXIDLENGTH:
323 num = ebml_read_uint (s, &l);
324 if (num != sizeof (uint32_t))
325 return NULL;
326 break;
328 case EBML_ID_DOCTYPE:
329 str = ebml_read_ascii (s, &l);
330 if (str == NULL)
331 return NULL;
332 break;
334 case EBML_ID_DOCTYPEREADVERSION:
335 num = ebml_read_uint (s, &l);
336 if (num == EBML_UINT_INVALID)
337 return NULL;
338 if (version)
339 *version = num;
340 break;
342 /* we ignore these two, they don't tell us anything we care about */
343 case EBML_ID_VOID:
344 case EBML_ID_EBMLVERSION:
345 case EBML_ID_DOCTYPEVERSION:
346 default:
347 if (ebml_read_skip (s, &l))
348 return NULL;
349 break;
351 length -= l;
354 return str;