diff --git a/ChangeLog b/ChangeLog index 84ad4ed1e1..ab9b2368a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2007-03-29 Sebastian Dröge + + Patch by: René Stadler + with some minor changes + + * gst-libs/gst/floatcast/floatcast.h: + Use more efficient float endianness conversion functions that don't + involve 2 function calls per value. + * gst/audioconvert/audioconvert.c: (audio_convert_get_func_index), + (check_default), (audio_convert_prepare_context): + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_parse_caps), (make_lossless_changes): + Support non-native endianness floats as input and output. + Fixes #339838. + * tests/check/elements/audioconvert.c: (verify_convert), + (GST_START_TEST): + Add unit tests for the non-native endianness float conversions. + 2007-03-29 Wim Taymans * gst-libs/gst/rtp/gstbasertpdepayload.c: diff --git a/gst-libs/gst/floatcast/floatcast.h b/gst-libs/gst/floatcast/floatcast.h index 518d7a6e3b..f95dfed25c 100644 --- a/gst-libs/gst/floatcast/floatcast.h +++ b/gst-libs/gst/floatcast/floatcast.h @@ -65,23 +65,29 @@ G_BEGIN_DECLS inline static gfloat GFLOAT_SWAP_LE_BE(gfloat in) { - gint32 swap; - gfloat out; - memcpy(&swap, &in, 4); - swap = GUINT32_SWAP_LE_BE_CONSTANT (swap); - memcpy(&out, &swap, 4); - return out; + union + { + guint32 i; + gfloat f; + } u; + + u.f = in; + u.i = GUINT32_SWAP_LE_BE (u.i); + return u.f; } inline static gdouble GDOUBLE_SWAP_LE_BE(gdouble in) { - gint64 swap; - gdouble out; - memcpy(&swap, &in, 8); - swap = GUINT64_SWAP_LE_BE_CONSTANT (swap); - memcpy(&out, &swap, 8); - return out; + union + { + guint64 i; + gdouble d; + } u; + + u.d = in; + u.i = GUINT64_SWAP_LE_BE (u.i); + return u.d; } #if G_BYTE_ORDER == G_LITTLE_ENDIAN diff --git a/gst/audioconvert/audioconvert.c b/gst/audioconvert/audioconvert.c index cadb82773e..17599ecd60 100644 --- a/gst/audioconvert/audioconvert.c +++ b/gst/audioconvert/audioconvert.c @@ -27,6 +27,7 @@ #include "gstchannelmix.h" #include "audioconvert.h" +#include "gst/floatcast/floatcast.h" /* int to float/double conversion: int2xxx(i) = 1 / (2^31-1) * i */ #define INT2FLOAT(i) (4.6566128752457969e-10 * ((gfloat)i)) @@ -41,7 +42,8 @@ #define MAKE_UNPACK_FUNC_NAME(name) \ audio_convert_unpack_##name -#define MAKE_UNPACK_FUNC(name, stride, sign, READ_FUNC) \ +/* unpack from integer to signed integer 32 */ +#define MAKE_UNPACK_FUNC_II(name, stride, sign, READ_FUNC) \ static void \ MAKE_UNPACK_FUNC_NAME (name) (guint8 *src, gint32 *dst, \ gint scale, gint count) \ @@ -52,44 +54,28 @@ MAKE_UNPACK_FUNC_NAME (name) (guint8 *src, gint32 *dst, \ } \ } -/* special unpack code for float/double */ -static void -MAKE_UNPACK_FUNC_NAME (float) (gfloat * src, gint32 * dst, gint s, gint count) -{ - gdouble temp; - - for (; count; count--) { - /* blow up to 32 bit */ - temp = (*src++ * 2147483647.0) + 0.5; - *dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32); - } +/* unpack from float to signed integer 32 */ +#define MAKE_UNPACK_FUNC_FI(name, type, READ_FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (type * src, gint32 * dst, gint s, gint count) \ +{ \ + gdouble temp; \ + \ + for (; count; count--) { \ + /* blow up to 32 bit */ \ + temp = (READ_FUNC (*src++) * 2147483647.0) + 0.5; \ + *dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32); \ + } \ } -static void -MAKE_UNPACK_FUNC_NAME (double) (gdouble * src, gint32 * dst, gint s, gint count) -{ - gdouble temp; - - for (; count; count--) { - /* blow up to 32 bit */ - temp = (*src++ * 2147483647.0) + 0.5; - *dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32); - } -} - -static void -MAKE_UNPACK_FUNC_NAME (float_hq) (gfloat * src, gdouble * dst, gint s, - gint count) -{ - for (; count; count--) - *dst++ = (gdouble) (*src++); -} - -static void -MAKE_UNPACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s, - gint count) -{ - memcpy (dst, src, count * sizeof (gdouble)); +/* unpack from float to float 64 (double) */ +#define MAKE_UNPACK_FUNC_FF(name, type, FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (type * src, gdouble * dst, gint s, \ + gint count) \ +{ \ + for (; count; count--) \ + *dst++ = (gdouble) FUNC (*src++); \ } #define READ8(p) GST_READ_UINT8(p) @@ -100,20 +86,31 @@ MAKE_UNPACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s, #define READ32_FROM_LE(p) GST_READ_UINT32_LE (p) #define READ32_FROM_BE(p) GST_READ_UINT32_BE (p) -MAKE_UNPACK_FUNC (u8, 1, SIGNED, READ8); -MAKE_UNPACK_FUNC (s8, 1, 0, READ8); -MAKE_UNPACK_FUNC (u16_le, 2, SIGNED, READ16_FROM_LE); -MAKE_UNPACK_FUNC (s16_le, 2, 0, READ16_FROM_LE); -MAKE_UNPACK_FUNC (u16_be, 2, SIGNED, READ16_FROM_BE); -MAKE_UNPACK_FUNC (s16_be, 2, 0, READ16_FROM_BE); -MAKE_UNPACK_FUNC (u24_le, 3, SIGNED, READ24_FROM_LE); -MAKE_UNPACK_FUNC (s24_le, 3, 0, READ24_FROM_LE); -MAKE_UNPACK_FUNC (u24_be, 3, SIGNED, READ24_FROM_BE); -MAKE_UNPACK_FUNC (s24_be, 3, 0, READ24_FROM_BE); -MAKE_UNPACK_FUNC (u32_le, 4, SIGNED, READ32_FROM_LE); -MAKE_UNPACK_FUNC (s32_le, 4, 0, READ32_FROM_LE); -MAKE_UNPACK_FUNC (u32_be, 4, SIGNED, READ32_FROM_BE); -MAKE_UNPACK_FUNC (s32_be, 4, 0, READ32_FROM_BE); +MAKE_UNPACK_FUNC_II (u8, 1, SIGNED, READ8); +MAKE_UNPACK_FUNC_II (s8, 1, 0, READ8); +MAKE_UNPACK_FUNC_II (u16_le, 2, SIGNED, READ16_FROM_LE); +MAKE_UNPACK_FUNC_II (s16_le, 2, 0, READ16_FROM_LE); +MAKE_UNPACK_FUNC_II (u16_be, 2, SIGNED, READ16_FROM_BE); +MAKE_UNPACK_FUNC_II (s16_be, 2, 0, READ16_FROM_BE); +MAKE_UNPACK_FUNC_II (u24_le, 3, SIGNED, READ24_FROM_LE); +MAKE_UNPACK_FUNC_II (s24_le, 3, 0, READ24_FROM_LE); +MAKE_UNPACK_FUNC_II (u24_be, 3, SIGNED, READ24_FROM_BE); +MAKE_UNPACK_FUNC_II (s24_be, 3, 0, READ24_FROM_BE); +MAKE_UNPACK_FUNC_II (u32_le, 4, SIGNED, READ32_FROM_LE); +MAKE_UNPACK_FUNC_II (s32_le, 4, 0, READ32_FROM_LE); +MAKE_UNPACK_FUNC_II (u32_be, 4, SIGNED, READ32_FROM_BE); +MAKE_UNPACK_FUNC_II (s32_be, 4, 0, READ32_FROM_BE); +MAKE_UNPACK_FUNC_FI (float_le, gfloat, GFLOAT_FROM_LE); +MAKE_UNPACK_FUNC_FI (float_be, gfloat, GFLOAT_FROM_BE); +MAKE_UNPACK_FUNC_FI (double_le, gdouble, GDOUBLE_FROM_LE); +MAKE_UNPACK_FUNC_FI (double_be, gdouble, GDOUBLE_FROM_BE); +MAKE_UNPACK_FUNC_FF (float_hq_le, gfloat, GFLOAT_FROM_LE); +MAKE_UNPACK_FUNC_FF (float_hq_be, gfloat, GFLOAT_FROM_BE); +MAKE_UNPACK_FUNC_FF (double_hq_le, gdouble, GDOUBLE_FROM_LE); +MAKE_UNPACK_FUNC_FF (double_hq_be, gdouble, GDOUBLE_FROM_BE); + +/* One of the double_hq_* functions generated above is ineffecient, but it's + * never used anyway. The same is true for one of the s32_* functions. */ /*** * packing code @@ -144,7 +141,8 @@ audio_convert_pack_##name * function for the target width. */ -#define MAKE_PACK_FUNC(name, stride, sign, WRITE_FUNC) \ +/* pack from signed integer 32 to integer */ +#define MAKE_PACK_FUNC_II(name, stride, sign, WRITE_FUNC) \ static void \ MAKE_PACK_FUNC_NAME (name) (gint32 *src, gpointer dst, \ gint scale, gint count) \ @@ -174,35 +172,24 @@ MAKE_PACK_FUNC_NAME (name) (gint32 *src, gpointer dst, \ } \ } -/* special pack code for float/double */ -static void -MAKE_PACK_FUNC_NAME (float) (gint32 * src, gfloat * dst, gint scale, gint count) -{ - for (; count; count--) - *dst++ = INT2FLOAT (*src++); +/* pack from signed integer 32 to float */ +#define MAKE_PACK_FUNC_IF(name, type, FUNC, FUNC2) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gint32 * src, type * dst, gint scale, \ + gint count) \ +{ \ + for (; count; count--) \ + *dst++ = FUNC (FUNC2 (*src++)); \ } -static void -MAKE_PACK_FUNC_NAME (double) (gint32 * src, gdouble * dst, gint scale, - gint count) -{ - for (; count; count--) { - *dst++ = INT2DOUBLE (*src++); - } -} - -static void -MAKE_PACK_FUNC_NAME (float_hq) (gdouble * src, gfloat * dst, gint s, gint count) -{ - for (; count; count--) - *dst++ = (gfloat) (*src++); -} - -static void -MAKE_PACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s, - gint count) -{ - memcpy (dst, src, count * sizeof (gdouble)); +/* pack from float 64 (double) to float */ +#define MAKE_PACK_FUNC_FF(name, type, FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gdouble * src, type * dst, gint s, \ + gint count) \ +{ \ + for (; count; count--) \ + *dst++ = FUNC ((type) (*src++)); \ } #define WRITE8(p, v) GST_WRITE_UINT8 (p, v) @@ -213,20 +200,30 @@ MAKE_PACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s, #define WRITE32_TO_LE(p,v) GST_WRITE_UINT32_LE (p, (guint32)(v)) #define WRITE32_TO_BE(p,v) GST_WRITE_UINT32_BE (p, (guint32)(v)) -MAKE_PACK_FUNC (u8, 1, SIGNED, WRITE8); -MAKE_PACK_FUNC (s8, 1, 0, WRITE8); -MAKE_PACK_FUNC (u16_le, 2, SIGNED, WRITE16_TO_LE); -MAKE_PACK_FUNC (s16_le, 2, 0, WRITE16_TO_LE); -MAKE_PACK_FUNC (u16_be, 2, SIGNED, WRITE16_TO_BE); -MAKE_PACK_FUNC (s16_be, 2, 0, WRITE16_TO_BE); -MAKE_PACK_FUNC (u24_le, 3, SIGNED, WRITE24_TO_LE); -MAKE_PACK_FUNC (s24_le, 3, 0, WRITE24_TO_LE); -MAKE_PACK_FUNC (u24_be, 3, SIGNED, WRITE24_TO_BE); -MAKE_PACK_FUNC (s24_be, 3, 0, WRITE24_TO_BE); -MAKE_PACK_FUNC (u32_le, 4, SIGNED, WRITE32_TO_LE); -MAKE_PACK_FUNC (s32_le, 4, 0, WRITE32_TO_LE); -MAKE_PACK_FUNC (u32_be, 4, SIGNED, WRITE32_TO_BE); -MAKE_PACK_FUNC (s32_be, 4, 0, WRITE32_TO_BE); +MAKE_PACK_FUNC_II (u8, 1, SIGNED, WRITE8); +MAKE_PACK_FUNC_II (s8, 1, 0, WRITE8); +MAKE_PACK_FUNC_II (u16_le, 2, SIGNED, WRITE16_TO_LE); +MAKE_PACK_FUNC_II (s16_le, 2, 0, WRITE16_TO_LE); +MAKE_PACK_FUNC_II (u16_be, 2, SIGNED, WRITE16_TO_BE); +MAKE_PACK_FUNC_II (s16_be, 2, 0, WRITE16_TO_BE); +MAKE_PACK_FUNC_II (u24_le, 3, SIGNED, WRITE24_TO_LE); +MAKE_PACK_FUNC_II (s24_le, 3, 0, WRITE24_TO_LE); +MAKE_PACK_FUNC_II (u24_be, 3, SIGNED, WRITE24_TO_BE); +MAKE_PACK_FUNC_II (s24_be, 3, 0, WRITE24_TO_BE); +MAKE_PACK_FUNC_II (u32_le, 4, SIGNED, WRITE32_TO_LE); +MAKE_PACK_FUNC_II (s32_le, 4, 0, WRITE32_TO_LE); +MAKE_PACK_FUNC_II (u32_be, 4, SIGNED, WRITE32_TO_BE); +MAKE_PACK_FUNC_II (s32_be, 4, 0, WRITE32_TO_BE); +MAKE_PACK_FUNC_IF (float_le, gfloat, GFLOAT_TO_LE, INT2FLOAT); +MAKE_PACK_FUNC_IF (float_be, gfloat, GFLOAT_TO_BE, INT2FLOAT); +MAKE_PACK_FUNC_IF (double_le, gdouble, GDOUBLE_TO_LE, INT2DOUBLE); +MAKE_PACK_FUNC_IF (double_be, gdouble, GDOUBLE_TO_BE, INT2DOUBLE); +MAKE_PACK_FUNC_FF (float_hq_le, gfloat, GFLOAT_TO_LE); +MAKE_PACK_FUNC_FF (float_hq_be, gfloat, GFLOAT_TO_BE); +/* For double_hq, packing and unpacking is the same, so we reuse the unpacking + * functions here. */ +#define audio_convert_pack_double_hq_le MAKE_UNPACK_FUNC_NAME (double_hq_le) +#define audio_convert_pack_double_hq_be MAKE_UNPACK_FUNC_NAME (double_hq_be) static AudioConvertUnpack unpack_funcs[] = { (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8), @@ -245,10 +242,14 @@ static AudioConvertUnpack unpack_funcs[] = { (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_le), (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_be), (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_be), - (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float), - (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double), - (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq), - (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq_be), }; static AudioConvertPack pack_funcs[] = { @@ -268,10 +269,14 @@ static AudioConvertPack pack_funcs[] = { (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_le), (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_be), (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_be), - (AudioConvertPack) MAKE_PACK_FUNC_NAME (float), - (AudioConvertPack) MAKE_PACK_FUNC_NAME (double), - (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq), - (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq_be), }; static gint @@ -285,7 +290,9 @@ audio_convert_get_func_index (AudioConvertFmt * fmt) index += fmt->sign ? 1 : 0; } else { /* this is float/double */ - index = (fmt->width == 32) ? 16 : 17; + index = 16; + index += (fmt->width == 32) ? 0 : 2; + index += (fmt->endianness == G_LITTLE_ENDIAN) ? 0 : 1; } return index; } @@ -297,7 +304,7 @@ check_default (AudioConvertCtx * ctx, AudioConvertFmt * fmt) return (fmt->width == 32 && fmt->depth == 32 && fmt->endianness == G_BYTE_ORDER && fmt->sign == TRUE); } else { - return (fmt->width == 64); + return (fmt->width == 64 && fmt->endianness == G_BYTE_ORDER); } } @@ -332,12 +339,10 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in, gst_channel_mix_setup_matrix (ctx); idx_in = audio_convert_get_func_index (in); - if (!(ctx->unpack = unpack_funcs[idx_in])) - goto not_supported; + ctx->unpack = unpack_funcs[idx_in]; idx_out = audio_convert_get_func_index (out); - if (!(ctx->pack = pack_funcs[idx_out])) - goto not_supported; + ctx->pack = pack_funcs[idx_out]; /* if both formats are float/double use double as intermediate format and * and switch mixing */ @@ -347,10 +352,10 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in, } else { GST_INFO ("use float mixing"); ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_float; - if (!(ctx->unpack = unpack_funcs[idx_in + 2])) - goto not_supported; - if (!(ctx->pack = pack_funcs[idx_out + 2])) - goto not_supported; + /* Bump the pack/unpack function indices by 4 to use double as intermediary + * format (float_hq_*, double_hq_* functions).*/ + ctx->unpack = unpack_funcs[idx_in + 4]; + ctx->pack = pack_funcs[idx_out + 4]; } GST_INFO ("unitsizes: %d -> %d", in->unit_size, out->unit_size); @@ -368,12 +373,6 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in, ctx->out_scale = (out->is_int) ? (32 - out->depth) : 0; return TRUE; - -not_supported: - { - GST_INFO ("missing pack/unpack function"); - return FALSE; - } } gboolean diff --git a/gst/audioconvert/gstaudioconvert.c b/gst/audioconvert/gstaudioconvert.c index 6768ef6b59..d94f8ab8f9 100644 --- a/gst/audioconvert/gstaudioconvert.c +++ b/gst/audioconvert/gstaudioconvert.c @@ -129,12 +129,12 @@ GST_STATIC_CAPS ( \ "audio/x-raw-float, " \ "rate = (int) [ 1, MAX ], " \ "channels = (int) [ 1, 8 ], " \ - "endianness = (int) BYTE_ORDER, " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ "width = (int) 64;" \ "audio/x-raw-float, " \ "rate = (int) [ 1, MAX ], " \ "channels = (int) [ 1, 8 ], " \ - "endianness = (int) BYTE_ORDER, " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ "width = (int) 32;" \ "audio/x-raw-int, " \ "rate = (int) [ 1, MAX ], " \ @@ -267,6 +267,11 @@ gst_audio_convert_parse_caps (const GstCaps * caps, AudioConvertFmt * fmt) goto no_values; if (!gst_structure_get_int (structure, "rate", &fmt->rate)) goto no_values; + /* width != 8 needs an endianness field */ + if (fmt->width != 8) { + if (!gst_structure_get_int (structure, "endianness", &fmt->endianness)) + goto no_values; + } if (fmt->is_int) { /* int specific fields */ @@ -275,11 +280,6 @@ gst_audio_convert_parse_caps (const GstCaps * caps, AudioConvertFmt * fmt) if (!gst_structure_get_int (structure, "depth", &fmt->depth)) goto no_values; - /* width != 8 can have an endianness field */ - if (fmt->width != 8) { - if (!gst_structure_get_int (structure, "endianness", &fmt->endianness)) - goto no_values; - } /* depth cannot be bigger than the width */ if (fmt->depth > fmt->width) goto not_allowed; @@ -379,31 +379,30 @@ set_structure_widths_32_and_64 (GstStructure * s) static GstStructure * make_lossless_changes (GstStructure * s, gboolean isfloat) { + GValue list = { 0 }; + GValue val = { 0 }; + int i; + const gint endian[] = { G_LITTLE_ENDIAN, G_BIG_ENDIAN }; + const gboolean booleans[] = { TRUE, FALSE }; + + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_INT); + for (i = 0; i < 2; i++) { + g_value_set_int (&val, endian[i]); + gst_value_list_append_value (&list, &val); + } + gst_structure_set_value (s, "endianness", &list); + g_value_unset (&val); + g_value_unset (&list); + if (isfloat) { /* float doesn't have a depth or signedness field and only supports - * widths of 32/64 and native endianness */ + * widths of 32 and 64 bits */ gst_structure_remove_field (s, "depth"); gst_structure_remove_field (s, "signed"); set_structure_widths_32_and_64 (s); - gst_structure_set (s, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL); } else { - /* int supports either endian, and signed or unsigned. GValues are a pain */ - GValue list = { 0 }; - GValue val = { 0 }; - int i; - const gint endian[] = { G_LITTLE_ENDIAN, G_BIG_ENDIAN }; - const gboolean booleans[] = { TRUE, FALSE }; - - g_value_init (&list, GST_TYPE_LIST); - g_value_init (&val, G_TYPE_INT); - for (i = 0; i < 2; i++) { - g_value_set_int (&val, endian[i]); - gst_value_list_append_value (&list, &val); - } - gst_structure_set_value (s, "endianness", &list); - g_value_unset (&val); - g_value_unset (&list); - + /* int supports signed and unsigned. GValues are a pain */ g_value_init (&list, GST_TYPE_LIST); g_value_init (&val, G_TYPE_BOOLEAN); for (i = 0; i < 2; i++) { diff --git a/tests/check/elements/audioconvert.c b/tests/check/elements/audioconvert.c index 65ee7e00e3..41f23c0d6e 100644 --- a/tests/check/elements/audioconvert.c +++ b/tests/check/elements/audioconvert.c @@ -22,6 +22,7 @@ #include +#include #include #include @@ -36,7 +37,7 @@ GstPad *mysrcpad, *mysinkpad; "audio/x-raw-float, " \ "rate = (int) [ 1, MAX ], " \ "channels = (int) [ 1, 8 ], " \ - "endianness = (int) BYTE_ORDER, " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ "width = (int) { 32, 64 };" \ "audio/x-raw-int, " \ "rate = (int) [ 1, MAX ], " \ @@ -324,6 +325,8 @@ verify_convert (const gchar * which, void *in, int inlength, fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), outlength); if (memcmp (GST_BUFFER_DATA (outbuffer), out, outlength) != 0) { + g_print ("\nInput data:\n"); + gst_util_dump_mem (in, inlength); g_print ("\nConverted data:\n"); gst_util_dump_mem (GST_BUFFER_DATA (outbuffer), outlength); g_print ("\nExpected data:\n"); @@ -487,6 +490,7 @@ GST_START_TEST (test_int_conversion) } /* 16 bit signed <-> 8 in 16 bit signed */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ { gint16 in[] = { 0, 64 << 8, -64 << 8 }; gint16 out[] = { 0, 64, -64 }; @@ -501,6 +505,7 @@ GST_START_TEST (test_int_conversion) } /* 16 bit unsigned <-> 8 in 16 bit unsigned */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ { guint16 in[] = { 1 << 15, (1 << 15) - (64 << 8), (1 << 15) + (64 << 8) }; guint16 out[] = { 1 << 7, (1 << 7) - 64, (1 << 7) + 64 }; @@ -515,6 +520,7 @@ GST_START_TEST (test_int_conversion) } /* 32 bit signed -> 16 bit signed for rounding check */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ { gint32 in[] = { 0, G_MININT32, G_MAXINT32, (32 << 16), (32 << 16) + (1 << 15), (32 << 16) - (1 << 15), @@ -537,6 +543,7 @@ GST_START_TEST (test_int_conversion) } /* 32 bit signed -> 16 bit unsigned for rounding check */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ { gint32 in[] = { 0, G_MININT32, G_MAXINT32, (32 << 16), (32 << 16) + (1 << 15), (32 << 16) - (1 << 15), @@ -561,22 +568,34 @@ GST_START_TEST (test_int_conversion) GST_END_TEST; - GST_START_TEST (test_float_conversion) { /* 32 float <-> 16 signed */ /* NOTE: if audioconvert was doing dithering we'd have a problem */ { - gfloat in[] = { 0.0, 1.0, -1.0, 0.5, -0.5, 1.1, -1.1 }; + gfloat in_le[] = + { GFLOAT_TO_LE (0.0), GFLOAT_TO_LE (1.0), GFLOAT_TO_LE (-1.0), + GFLOAT_TO_LE (0.5), GFLOAT_TO_LE (-0.5), GFLOAT_TO_LE (1.1), + GFLOAT_TO_LE (-1.1) + }; + gfloat in_be[] = + { GFLOAT_TO_BE (0.0), GFLOAT_TO_BE (1.0), GFLOAT_TO_BE (-1.0), + GFLOAT_TO_BE (0.5), GFLOAT_TO_BE (-0.5), GFLOAT_TO_BE (1.1), + GFLOAT_TO_BE (-1.1) + }; gint16 out[] = { 0, 32767, -32768, 16384, -16384, 32767, -32768 }; /* only one direction conversion, the other direction does * not produce exactly the same as the input due to floating * point rounding errors etc. */ - RUN_CONVERSION ("32 float to 16 signed", - in, get_float_caps (1, "BYTE_ORDER", 32), + RUN_CONVERSION ("32 float le to 16 signed", + in_le, get_float_caps (1, "LITTLE_ENDIAN", 32), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + RUN_CONVERSION ("32 float be to 16 signed", + in_be, get_float_caps (1, "BIG_ENDIAN", 32), out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); } + { gint16 in[] = { 0, -32768, 16384, -16384 }; gfloat out[] = { 0.0, -1.0, 0.5, -0.5 }; @@ -589,14 +608,26 @@ GST_START_TEST (test_float_conversion) /* 64 float <-> 16 signed */ /* NOTE: if audioconvert was doing dithering we'd have a problem */ { - gdouble in[] = { 0.0, 1.0, -1.0, 0.5, -0.5, 1.1, -1.1 }; + gdouble in_le[] = + { GDOUBLE_TO_LE (0.0), GDOUBLE_TO_LE (1.0), GDOUBLE_TO_LE (-1.0), + GDOUBLE_TO_LE (0.5), GDOUBLE_TO_LE (-0.5), GDOUBLE_TO_LE (1.1), + GDOUBLE_TO_LE (-1.1) + }; + gdouble in_be[] = + { GDOUBLE_TO_BE (0.0), GDOUBLE_TO_BE (1.0), GDOUBLE_TO_BE (-1.0), + GDOUBLE_TO_BE (0.5), GDOUBLE_TO_BE (-0.5), GDOUBLE_TO_BE (1.1), + GDOUBLE_TO_BE (-1.1) + }; gint16 out[] = { 0, 32767, -32768, 16384, -16384, 32767, -32768 }; /* only one direction conversion, the other direction does * not produce exactly the same as the input due to floating * point rounding errors etc. */ - RUN_CONVERSION ("64 float to 16 signed", - in, get_float_caps (1, "BYTE_ORDER", 64), + RUN_CONVERSION ("64 float LE to 16 signed", + in_le, get_float_caps (1, "LITTLE_ENDIAN", 64), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + RUN_CONVERSION ("64 float BE to 16 signed", + in_be, get_float_caps (1, "BIG_ENDIAN", 64), out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); } { @@ -637,6 +668,44 @@ GST_START_TEST (test_float_conversion) out, get_float_caps (1, "BYTE_ORDER", 32), in, get_float_caps (1, "BYTE_ORDER", 64)); } + + /* 32-bit float little endian <-> big endian */ + { + gfloat le[] = { GFLOAT_TO_LE (0.0), GFLOAT_TO_LE (1.0), GFLOAT_TO_LE (-1.0), + GFLOAT_TO_LE (0.5), GFLOAT_TO_LE (-0.5) + }; + gfloat be[] = { GFLOAT_TO_BE (0.0), GFLOAT_TO_BE (1.0), GFLOAT_TO_BE (-1.0), + GFLOAT_TO_BE (0.5), GFLOAT_TO_BE (-0.5) + }; + + RUN_CONVERSION ("32 float LE to BE", + le, get_float_caps (1, "LITTLE_ENDIAN", 32), + be, get_float_caps (1, "BIG_ENDIAN", 32)); + + RUN_CONVERSION ("32 float BE to LE", + be, get_float_caps (1, "BIG_ENDIAN", 32), + le, get_float_caps (1, "LITTLE_ENDIAN", 32)); + } + + /* 64-bit float little endian <-> big endian */ + { + gdouble le[] = + { GDOUBLE_TO_LE (0.0), GDOUBLE_TO_LE (1.0), GDOUBLE_TO_LE (-1.0), + GDOUBLE_TO_LE (0.5), GDOUBLE_TO_LE (-0.5) + }; + gdouble be[] = + { GDOUBLE_TO_BE (0.0), GDOUBLE_TO_BE (1.0), GDOUBLE_TO_BE (-1.0), + GDOUBLE_TO_BE (0.5), GDOUBLE_TO_BE (-0.5) + }; + + RUN_CONVERSION ("64 float LE to BE", + le, get_float_caps (1, "LITTLE_ENDIAN", 64), + be, get_float_caps (1, "BIG_ENDIAN", 64)); + + RUN_CONVERSION ("64 float BE to LE", + be, get_float_caps (1, "BIG_ENDIAN", 64), + le, get_float_caps (1, "LITTLE_ENDIAN", 64)); + } } GST_END_TEST;