Merge svn changes up to r30216
[mplayer/glamo.git] / libmpdemux / ebml.c
blob30528e15cb32bd9bc227c395cf7a9d350394e688
1 /*
2 * native ebml reader for the Matroska demuxer
3 * copyright (c) 2004 Aurelien Jacobs <aurel@gnuage.org>
4 * based on the one written by Ronald Bultje for gstreamer
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "config.h"
25 #include <stdlib.h>
27 #include "stream/stream.h"
28 #include "ebml.h"
29 #include "libavutil/common.h"
30 #include "mpbswap.h"
31 #include "libavutil/intfloat_readwrite.h"
34 #ifndef SIZE_MAX
35 #define SIZE_MAX ((size_t)-1)
36 #endif
39 * Read: the element content data ID.
40 * Return: the ID.
42 uint32_t ebml_read_id(stream_t *s, int *length)
44 int i, len_mask = 0x80;
45 uint32_t id;
47 for (i = 0, id = stream_read_char(s); i < 4 && !(id & len_mask); i++)
48 len_mask >>= 1;
49 if (i >= 4)
50 return EBML_ID_INVALID;
51 if (length)
52 *length = i + 1;
53 while (i--)
54 id = (id << 8) | stream_read_char(s);
55 return id;
59 * Read a variable length unsigned int.
61 uint64_t ebml_read_vlen_uint(uint8_t *buffer, int *length)
63 int i, j, num_ffs = 0, len_mask = 0x80;
64 uint64_t num;
66 for (i = 0, num = *buffer++; i < 8 && !(num & len_mask); i++)
67 len_mask >>= 1;
68 if (i >= 8)
69 return EBML_UINT_INVALID;
70 j = i + 1;
71 if (length)
72 *length = j;
73 if ((int) (num &= (len_mask - 1)) == len_mask - 1)
74 num_ffs++;
75 while (i--) {
76 num = (num << 8) | *buffer++;
77 if ((num & 0xFF) == 0xFF)
78 num_ffs++;
80 if (j == num_ffs)
81 return EBML_UINT_INVALID;
82 return num;
86 * Read a variable length signed int.
88 int64_t ebml_read_vlen_int(uint8_t *buffer, int *length)
90 uint64_t unum;
91 int l;
93 /* read as unsigned number first */
94 unum = ebml_read_vlen_uint(buffer, &l);
95 if (unum == EBML_UINT_INVALID)
96 return EBML_INT_INVALID;
97 if (length)
98 *length = l;
100 return unum - ((1 << ((7 * l) - 1)) - 1);
104 * Read: element content length.
106 uint64_t ebml_read_length(stream_t *s, int *length)
108 int i, j, num_ffs = 0, len_mask = 0x80;
109 uint64_t len;
111 for (i = 0, len = stream_read_char(s); i < 8 && !(len & len_mask); i++)
112 len_mask >>= 1;
113 if (i >= 8)
114 return EBML_UINT_INVALID;
115 j = i + 1;
116 if (length)
117 *length = j;
118 if ((int) (len &= (len_mask - 1)) == len_mask - 1)
119 num_ffs++;
120 while (i--) {
121 len = (len << 8) | stream_read_char(s);
122 if ((len & 0xFF) == 0xFF)
123 num_ffs++;
125 if (j == num_ffs)
126 return EBML_UINT_INVALID;
127 return len;
131 * Read the next element as an unsigned int.
133 uint64_t ebml_read_uint(stream_t *s, uint64_t *length)
135 uint64_t len, value = 0;
136 int l;
138 len = ebml_read_length(s, &l);
139 if (len == EBML_UINT_INVALID || len < 1 || len > 8)
140 return EBML_UINT_INVALID;
141 if (length)
142 *length = len + l;
144 while (len--)
145 value = (value << 8) | stream_read_char(s);
147 return value;
151 * Read the next element as a signed int.
153 int64_t ebml_read_int(stream_t *s, uint64_t *length)
155 int64_t value = 0;
156 uint64_t len;
157 int l;
159 len = ebml_read_length(s, &l);
160 if (len == EBML_UINT_INVALID || len < 1 || len > 8)
161 return EBML_INT_INVALID;
162 if (length)
163 *length = len + l;
165 len--;
166 l = stream_read_char(s);
167 if (l & 0x80)
168 value = -1;
169 value = (value << 8) | l;
170 while (len--)
171 value = (value << 8) | stream_read_char(s);
173 return value;
177 * Read the next element as a float.
179 long double ebml_read_float(stream_t *s, uint64_t *length)
181 long double value;
182 uint64_t len;
183 int l;
185 len = ebml_read_length(s, &l);
186 switch (len) {
187 case 4:
188 value = av_int2flt(stream_read_dword(s));
189 break;
191 case 8:
192 value = av_int2dbl(stream_read_qword(s));
193 break;
195 default:
196 return EBML_FLOAT_INVALID;
199 if (length)
200 *length = len + l;
202 return value;
206 * Read the next element as an ASCII string.
208 char *ebml_read_ascii(stream_t *s, uint64_t *length)
210 uint64_t len;
211 char *str;
212 int l;
214 len = ebml_read_length(s, &l);
215 if (len == EBML_UINT_INVALID)
216 return NULL;
217 if (len > SIZE_MAX - 1)
218 return NULL;
219 if (length)
220 *length = len + l;
222 str = (char *) malloc(len + 1);
223 if (stream_read(s, str, len) != (int) len) {
224 free(str);
225 return NULL;
227 str[len] = '\0';
229 return str;
233 * Read the next element as a UTF-8 string.
235 char *ebml_read_utf8(stream_t *s, uint64_t *length)
237 return ebml_read_ascii(s, length);
241 * Skip the next element.
243 int ebml_read_skip(stream_t *s, uint64_t *length)
245 uint64_t len;
246 int l;
248 len = ebml_read_length(s, &l);
249 if (len == EBML_UINT_INVALID)
250 return 1;
251 if (length)
252 *length = len + l;
254 stream_skip(s, len);
256 return 0;
260 * Read the next element, but only the header. The contents
261 * are supposed to be sub-elements which can be read separately.
263 uint32_t 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 *ebml_read_header(stream_t *s, int *version)
287 uint64_t length, l, num;
288 uint32_t id;
289 char *str = NULL;
291 if (ebml_read_master(s, &length) != EBML_ID_HEADER)
292 return 0;
294 if (version)
295 *version = 1;
297 while (length > 0) {
298 id = ebml_read_id(s, NULL);
299 if (id == EBML_ID_INVALID)
300 return NULL;
301 length -= 2;
303 switch (id) {
304 /* is our read version uptodate? */
305 case EBML_ID_EBMLREADVERSION:
306 num = ebml_read_uint(s, &l);
307 if (num != EBML_VERSION)
308 return NULL;
309 break;
311 /* we only handle 8 byte lengths at max */
312 case EBML_ID_EBMLMAXSIZELENGTH:
313 num = ebml_read_uint(s, &l);
314 if (num != sizeof(uint64_t))
315 return NULL;
316 break;
318 /* we handle 4 byte IDs at max */
319 case EBML_ID_EBMLMAXIDLENGTH:
320 num = ebml_read_uint(s, &l);
321 if (num != sizeof(uint32_t))
322 return NULL;
323 break;
325 case EBML_ID_DOCTYPE:
326 str = ebml_read_ascii(s, &l);
327 if (str == NULL)
328 return NULL;
329 break;
331 case EBML_ID_DOCTYPEREADVERSION:
332 num = ebml_read_uint(s, &l);
333 if (num == EBML_UINT_INVALID)
334 return NULL;
335 if (version)
336 *version = num;
337 break;
339 /* we ignore these two, they don't tell us anything we care about */
340 case EBML_ID_VOID:
341 case EBML_ID_EBMLVERSION:
342 case EBML_ID_DOCTYPEVERSION:
343 default:
344 if (ebml_read_skip(s, &l))
345 return NULL;
346 break;
348 length -= l;
351 return str;