Mercurial > mplayer.hg
view libmpdemux/ebml.c @ 19422:718624aec009
r19361: Reintroduce an ugly variant of the -gui/-nogui options.
r19348: Add matroska chapter seeking capability.
r19286: clarification on -mpegopts :vaspect
r19285: New sentences should start on a new line.
r19281: don't use vaspect on mpeg1 video streams
r19274: Move the section describing the per movie config files
up, so it doesn't get seperated from the rest of the
config file doc by the config file example
r19241: missed some escaping
r19240: use DOCS writing standards for default values (asked by diego)
r19233: english manpage for pvr:// input
r19231: updated en/fr manpages for ao_ivtv
r19228: removed default outfile for -ao mpegpes
r19206: Improve ao_mpegpes description.
r19191: description of the arnd scale video filter parameter
r19190: new -ao mpegpes options
r19181: - Add missing "00" in -af pan usage line.
- Change -af pan usage and description to use a capital 'L' to make the
letter easily distinguishable from a '1'.
r19161: cosmetics/punctuation/spelling
r19149: updated english man page with vo_ivtv description
author | kraymer |
---|---|
date | Thu, 17 Aug 2006 21:57:01 +0000 |
parents | 8fb542b97815 |
children | c1d8b530ce40 |
line wrap: on
line source
/* * native ebml reader for the Matroska demuxer * Written by Aurelien Jacobs <aurel@gnuage.org> * Based on the one written by Ronald Bultje for gstreamer * Licence: GPL */ #include "config.h" #include <stdlib.h> #include "stream.h" #include "ebml.h" #include "bswap.h" #ifndef SIZE_MAX #define SIZE_MAX ((size_t)-1) #endif /* * Read: the element content data ID. * Return: the ID. */ uint32_t ebml_read_id (stream_t *s, int *length) { int i, len_mask = 0x80; uint32_t id; for (i=0, id=stream_read_char (s); i<4 && !(id & len_mask); i++) len_mask >>= 1; if (i >= 4) return EBML_ID_INVALID; if (length) *length = i + 1; while (i--) id = (id << 8) | stream_read_char (s); return id; } /* * Read a variable length unsigned int. */ uint64_t ebml_read_vlen_uint (uint8_t *buffer, int *length) { int i, j, num_ffs = 0, len_mask = 0x80; uint64_t num; for (i=0, num=*buffer++; i<8 && !(num & len_mask); i++) len_mask >>= 1; if (i >= 8) return EBML_UINT_INVALID; j = i+1; if (length) *length = j; if ((int)(num &= (len_mask - 1)) == len_mask - 1) num_ffs++; while (i--) { num = (num << 8) | *buffer++; if ((num & 0xFF) == 0xFF) num_ffs++; } if (j == num_ffs) return EBML_UINT_INVALID; return num; } /* * Read a variable length signed int. */ int64_t ebml_read_vlen_int (uint8_t *buffer, int *length) { uint64_t unum; int l; /* read as unsigned number first */ unum = ebml_read_vlen_uint (buffer, &l); if (unum == EBML_UINT_INVALID) return EBML_INT_INVALID; if (length) *length = l; return unum - ((1 << ((7 * l) - 1)) - 1); } /* * Read: element content length. */ uint64_t ebml_read_length (stream_t *s, int *length) { int i, j, num_ffs = 0, len_mask = 0x80; uint64_t len; for (i=0, len=stream_read_char (s); i<8 && !(len & len_mask); i++) len_mask >>= 1; if (i >= 8) return EBML_UINT_INVALID; j = i+1; if (length) *length = j; if ((int)(len &= (len_mask - 1)) == len_mask - 1) num_ffs++; while (i--) { len = (len << 8) | stream_read_char (s); if ((len & 0xFF) == 0xFF) num_ffs++; } if (j == num_ffs) return EBML_UINT_INVALID; return len; } /* * Read the next element as an unsigned int. */ uint64_t ebml_read_uint (stream_t *s, uint64_t *length) { uint64_t len, value = 0; int l; len = ebml_read_length (s, &l); if (len == EBML_UINT_INVALID || len < 1 || len > 8) return EBML_UINT_INVALID; if (length) *length = len + l; while (len--) value = (value << 8) | stream_read_char (s); return value; } /* * Read the next element as a signed int. */ int64_t ebml_read_int (stream_t *s, uint64_t *length) { int64_t value = 0; uint64_t len; int l; len = ebml_read_length (s, &l); if (len == EBML_UINT_INVALID || len < 1 || len > 8) return EBML_INT_INVALID; if (length) *length = len + l; len--; l = stream_read_char (s); if (l & 0x80) value = -1; value = (value << 8) | l; while (len--) value = (value << 8) | stream_read_char (s); return value; } /* * Read the next element as a float. */ long double ebml_read_float (stream_t *s, uint64_t *length) { long double value; uint64_t len; int l; len = ebml_read_length (s, &l); switch (len) { case 4: { union {uint32_t i; float f;} u; u.i = stream_read_dword (s); value = u.f; break; } case 8: { union {uint64_t i; double d;} u; u.i = stream_read_qword (s); value = u.d; break; } case 10: { union {uint8_t data[10]; long double ld;} u; if (stream_read (s, u.data, 10) != 10) return EBML_FLOAT_INVALID; value = be2me_ldbl(u.ld); break; } default: return EBML_FLOAT_INVALID; } if (length) *length = len + l; return value; } /* * Read the next element as an ASCII string. */ char * ebml_read_ascii (stream_t *s, uint64_t *length) { uint64_t len; char *str; int l; len = ebml_read_length (s, &l); if (len == EBML_UINT_INVALID) return NULL; if (len > SIZE_MAX - 1) return NULL; if (length) *length = len + l; str = (char *) malloc (len+1); if (stream_read(s, str, len) != (int) len) { free (str); return NULL; } str[len] = '\0'; return str; } /* * Read the next element as a UTF-8 string. */ char * ebml_read_utf8 (stream_t *s, uint64_t *length) { return ebml_read_ascii (s, length); } /* * Skip the next element. */ int ebml_read_skip (stream_t *s, uint64_t *length) { uint64_t len; int l; len = ebml_read_length (s, &l); if (len == EBML_UINT_INVALID) return 1; if (length) *length = len + l; stream_skip(s, len); return 0; } /* * Read the next element, but only the header. The contents * are supposed to be sub-elements which can be read separately. */ uint32_t ebml_read_master (stream_t *s, uint64_t *length) { uint64_t len; uint32_t id; id = ebml_read_id (s, NULL); if (id == EBML_ID_INVALID) return id; len = ebml_read_length (s, NULL); if (len == EBML_UINT_INVALID) return EBML_ID_INVALID; if (length) *length = len; return id; } /* * Read an EBML header. */ char * ebml_read_header (stream_t *s, int *version) { uint64_t length, l, num; uint32_t id; char *str = NULL; if (ebml_read_master (s, &length) != EBML_ID_HEADER) return 0; if (version) *version = 1; while (length > 0) { id = ebml_read_id (s, NULL); if (id == EBML_ID_INVALID) return NULL; length -= 2; switch (id) { /* is our read version uptodate? */ case EBML_ID_EBMLREADVERSION: num = ebml_read_uint (s, &l); if (num != EBML_VERSION) return NULL; break; /* we only handle 8 byte lengths at max */ case EBML_ID_EBMLMAXSIZELENGTH: num = ebml_read_uint (s, &l); if (num != sizeof (uint64_t)) return NULL; break; /* we handle 4 byte IDs at max */ case EBML_ID_EBMLMAXIDLENGTH: num = ebml_read_uint (s, &l); if (num != sizeof (uint32_t)) return NULL; break; case EBML_ID_DOCTYPE: str = ebml_read_ascii (s, &l); if (str == NULL) return NULL; break; case EBML_ID_DOCTYPEREADVERSION: num = ebml_read_uint (s, &l); if (num == EBML_UINT_INVALID) return NULL; if (version) *version = num; break; /* we ignore these two, they don't tell us anything we care about */ case EBML_ID_VOID: case EBML_ID_EBMLVERSION: case EBML_ID_DOCTYPEVERSION: default: if (ebml_read_skip (s, &l)) return NULL; break; } length -= l; } return str; }