From d03eea36b2c329241f63c8aca2d6adbb6ea81d9c Mon Sep 17 00:00:00 2001 From: Jan Gerber Date: Fri, 15 Nov 2013 19:00:37 +0100 Subject: [PATCH] lavf/matroska*: add support for signed integers Signed-off-by: Michael Niedermayer --- libavformat/matroskadec.c | 30 ++++++++++++++++++++++++++++++ libavformat/matroskaenc.c | 21 +++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index f770d67af7..6bb75457cb 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -62,6 +62,7 @@ typedef enum { EBML_NEST, EBML_PASS, EBML_STOP, + EBML_SINT, EBML_TYPE_COUNT } EbmlType; @@ -758,6 +759,34 @@ static int ebml_read_uint(AVIOContext *pb, int size, uint64_t *num) return 0; } +/* + * Read the next element as a signed int. + * 0 is success, < 0 is failure. + */ +static int ebml_read_sint(AVIOContext *pb, int size, int64_t *num) +{ + int n = 1; + + if (size > 8) + return AVERROR_INVALIDDATA; + + if (size == 0) { + *num = 0; + } else { + *num = avio_r8(pb); + /* negative value */ + if (*num & 0x80) { + *num = (-1 << 8) | *num; + } + + /* big-endian ordering; build up number */ + while (n++ < size) + *num = (*num << 8) | avio_r8(pb); + } + + return 0; +} + /* * Read the next element as a float. * 0 is success, < 0 is failure. @@ -985,6 +1014,7 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska, switch (syntax->type) { case EBML_UINT: res = ebml_read_uint (pb, length, data); break; + case EBML_SINT: res = ebml_read_sint (pb, length, data); break; case EBML_FLOAT: res = ebml_read_float (pb, length, data); break; case EBML_STR: case EBML_UTF8: res = ebml_read_ascii (pb, length, data); break; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index d8355b23cc..8db4795d8c 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -202,6 +202,27 @@ static void put_ebml_uint(AVIOContext *pb, unsigned int elementid, uint64_t val) avio_w8(pb, (uint8_t)(val >> i*8)); } +static void put_ebml_sint(AVIOContext *pb, unsigned int elementid, int64_t val) +{ + int i, bytes = 1; + uint64_t uval = (val < 0 ? (-val - 1) << 1 : val << 1); + while (uval>>=8) bytes++; + + /* make unsigned */ + if (val >= 0) { + uval = val; + } else { + uval = 0x80 << (bytes - 1); + uval += val; + uval |= 0x80 << (bytes - 1); + } + + put_ebml_id(pb, elementid); + put_ebml_num(pb, bytes, 0); + for (i = bytes - 1; i >= 0; i--) + avio_w8(pb, (uint8_t)(uval >> i*8)); +} + static void put_ebml_float(AVIOContext *pb, unsigned int elementid, double val) { put_ebml_id(pb, elementid);