with some minor changes

Original commit message from CVS:
Patch by: René Stadler <mail at renestadler dot de>
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.
This commit is contained in:
René Stadler 2007-03-29 18:42:34 +00:00 committed by Sebastian Dröge
parent 76462ceb45
commit 6ac8ff9ec3
5 changed files with 254 additions and 163 deletions

View file

@ -1,3 +1,21 @@
2007-03-29 Sebastian Dröge <slomo@circular-chaos.org>
Patch by: René Stadler <mail at renestadler dot de>
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 <wim@fluendo.com>
* gst-libs/gst/rtp/gstbasertpdepayload.c:

View file

@ -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

View file

@ -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

View file

@ -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++) {

View file

@ -22,6 +22,7 @@
#include <unistd.h>
#include <gst/floatcast/floatcast.h>
#include <gst/check/gstcheck.h>
#include <gst/audio/multichannel.h>
@ -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;