[FFmpeg-devel] lavf/matroska*: add support for signed integers
Michael Niedermayer
michaelni at gmx.at
Fri Nov 15 17:42:32 CET 2013
On Fri, Nov 15, 2013 at 05:33:22PM +0100, Jan Gerber wrote:
> On 11/15/2013 04:37 PM, Michael Niedermayer wrote:
> >> + int n = 0;
> >> +
> >> + if (size > 8)
> >> + return AVERROR_INVALIDDATA;
> >> +
> >> + *num = avio_r8(pb);
> >> + if (*num & 0x80) {
> >> + *num = -1;
> >> + } else {
> >> + *num = 0;
> >> + }
> >
> > this discards the 7 less significant bits
> > i think these contain bits from the number to be read
>
> indeed.
>
> matroskadec.c | 32 +++++++++++++++++++++++++++++++-
> matroskaenc.c | 21 +++++++++++++++++++++
> 2 files changed, 52 insertions(+), 1 deletion(-)
> 13662a2dbf120fa0fd4fcfe6c9e45897d56fc2bd 0001-lavf-matroska-add-support-for-signed-integers.patch
> diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> index f770d67..ad7ff4f 100644
> --- a/libavformat/matroskadec.c
> +++ b/libavformat/matroskadec.c
> @@ -62,7 +62,8 @@ typedef enum {
> EBML_NEST,
> EBML_PASS,
> EBML_STOP,
> - EBML_TYPE_COUNT
> + EBML_TYPE_COUNT,
> + EBML_SINT,
> } EbmlType;
>
> typedef const struct EbmlSyntax {
EBML_TYPE_COUNT is the number of enum types its used as size for
some array
> @@ -759,6 +760,34 @@ static int ebml_read_uint(AVIOContext *pb, int size, uint64_t *num)
> }
>
> /*
> + * 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;
> + }
can be simplified with sign_extend()
> +
> + /* 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 d8355b2..8db4795 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);
> + }
this should not be needed
signed integers are already in twos complement, simply storing them
bytewise should work
> +
> + 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);
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Opposition brings concord. Out of discord comes the fairest harmony.
-- Heraclitus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20131115/96df995e/attachment.asc>
More information about the ffmpeg-devel
mailing list