+2007-02-28 Stefan Kost <ensonic@users.sf.net>
+
+ * gst/audioconvert/audioconvert.c: (float), (double), (float_hq),
+ (double_hq), (audio_convert_get_func_index),
+ (audio_convert_prepare_context), (audio_convert_convert):
+ * gst/audioconvert/gstaudioconvert.c:
+ (gst_audio_convert_class_init), (gst_audio_convert_get_unit_size),
+ (gst_audio_convert_transform_caps):
+ * tests/check/elements/audioconvert.c: (GST_START_TEST),
+ (audioconvert_suite):
+ Don't run inplace if that overwrites source data as we go. Add more
+ tests. Fixes #339837 even more.
+
2007-02-27 Julien MOUTTE <julien@moutte.net>
* tests/examples/seek/seek.c: (do_seek), (set_update_scale),
#define MAKE_UNPACK_FUNC(name, stride, sign, READ_FUNC) \
static void \
-MAKE_UNPACK_FUNC_NAME (name) (gpointer src, gint32 *dst, \
+MAKE_UNPACK_FUNC_NAME (name) (guint8 *src, gint32 *dst, \
gint scale, gint count) \
{ \
- guint8* p = (guint8 *) src; \
for (;count; count--) { \
- *dst++ = (((gint32) READ_FUNC (p)) << scale) ^ (sign); \
- p+=stride; \
+ *dst++ = (((gint32) READ_FUNC (src)) << scale) ^ (sign); \
+ src+=stride; \
} \
}
gint count)
{
for (; count; count--)
- *dst++ = (gdouble) * src++;
+ *dst++ = (gdouble) (*src++);
}
static void
MAKE_UNPACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s,
gint count)
{
- /* FIXME: memcpy */
- for (; count; count--)
- *dst++ = *src++;
+ memcpy (dst, src, count * sizeof (gdouble));
}
#define READ8(p) GST_READ_UINT8(p)
MAKE_PACK_FUNC_NAME (double) (gint32 * src, gdouble * dst, gint scale,
gint count)
{
- for (; count; count--)
+ for (; count; count--) {
*dst++ = INT2DOUBLE (*src++);
+ }
}
static void
MAKE_PACK_FUNC_NAME (double_hq) (gdouble * src, gdouble * dst, gint s,
gint count)
{
- /* FIXME: memcpy */
- for (; count; count--)
- *dst++ = *src++;
+ memcpy (dst, src, count * sizeof (gdouble));
}
#define WRITE8(p, v) GST_WRITE_UINT8 (p, v)
/* if both formats are float/double use double as intermediate format and
* and switch mixing */
if (in->is_int || out->is_int) {
- GST_DEBUG ("use int mixing");
+ GST_INFO ("use int mixing");
ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_int;
} else {
- GST_DEBUG ("use float mixing");
+ 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;
}
+ GST_INFO ("unitsizes: %d -> %d", in->unit_size, out->unit_size);
/* check if input is in default format */
ctx->in_default = check_default (in);
/* check if output is in default format */
ctx->out_default = check_default (out);
- ctx->in_scale = 32 - in->depth;
- ctx->out_scale = 32 - out->depth;
+ GST_INFO ("in default %d, mix passthrough %d, out default %d",
+ ctx->in_default, ctx->mix_passthrough, ctx->out_default);
+
+ ctx->in_scale = (in->is_int) ? (32 - in->depth) : 0;
+ ctx->out_scale = (out->is_int) ? (32 - out->depth) : 0;
return TRUE;
{
gint insize, outsize, size;
gpointer outbuf, tmpbuf;
- gint biggest = 0;
+ gint intemp = 0, outtemp = 0, biggest;
g_return_val_if_fail (ctx != NULL, FALSE);
g_return_val_if_fail (src != NULL, FALSE);
outsize = ctx->out.unit_size * samples;
/* find biggest temp buffer size */
- size = (ctx->in.is_int || ctx->out.is_int) ? 32 : 64;
+ size = (ctx->in.is_int || ctx->out.is_int) ?
+ sizeof (gint32) : sizeof (gdouble);
+
if (!ctx->in_default)
- biggest = insize * size / ctx->in.width;
+ intemp = insize * size * 8 / ctx->in.width;
if (!ctx->mix_passthrough)
- biggest = MAX (biggest, outsize * size / ctx->out.width);
+ outtemp = outsize * size * 8 / ctx->out.width;
+ biggest = MAX (intemp, outtemp);
/* see if one of the buffers can be used as temp */
- if (outsize >= biggest)
+ if ((outsize >= biggest) && (ctx->out.unit_size <= size))
tmpbuf = dst;
- else if (insize >= biggest && src_writable)
+ else if ((insize >= biggest) && src_writable && (ctx->in.unit_size >= size))
tmpbuf = src;
else {
if (biggest > ctx->tmpbufsize) {
gst_audio_convert_class_init (GstAudioConvertClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS (klass);
gint i;
gobject_class->dispose = gst_audio_convert_dispose;
for (i = 0; i < GST_AUDIO_CHANNEL_POSITION_NUM; i++)
supported_positions[i] = i;
- GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size =
+ basetransform_class->get_unit_size =
GST_DEBUG_FUNCPTR (gst_audio_convert_get_unit_size);
- GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
+ basetransform_class->transform_caps =
GST_DEBUG_FUNCPTR (gst_audio_convert_transform_caps);
- GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps =
+ basetransform_class->fixate_caps =
GST_DEBUG_FUNCPTR (gst_audio_convert_fixate_caps);
- GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
+ basetransform_class->set_caps =
GST_DEBUG_FUNCPTR (gst_audio_convert_set_caps);
- GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
+ basetransform_class->transform_ip =
GST_DEBUG_FUNCPTR (gst_audio_convert_transform_ip);
- GST_BASE_TRANSFORM_CLASS (klass)->transform =
+ basetransform_class->transform =
GST_DEBUG_FUNCPTR (gst_audio_convert_transform);
- GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE;
+ basetransform_class->passthrough_on_same_caps = TRUE;
}
static void
if (!gst_audio_convert_parse_caps (caps, &fmt))
goto parse_error;
+ GST_INFO_OBJECT (base, "unit_size = %u", fmt.unit_size);
*size = fmt.unit_size;
audio_convert_clean_fmt (&fmt);
parse_error:
{
+ GST_INFO_OBJECT (base, "failed to parse caps to get unit_size");
return FALSE;
}
}
* done the equivalent above. */
if (!gst_structure_get_int (structure, "width", &width) || width > 16) {
if (isfloat) {
- /* These are invalid widths/depths for float, but we don't actually use
- * them - we just pass it to append_with_other_format, which makes them
- * valid
- */
GstStructure *s2 = gst_structure_copy (s);
- set_structure_widths (s2, 16, 32);
- gst_structure_set (s2, "depth", GST_TYPE_INT_RANGE, 16, 32, NULL);
+ set_structure_widths_32_and_64 (s2);
append_with_other_format (ret, s2, TRUE);
gst_structure_free (s2);
} else {
verify_convert (which, inarray, sizeof (inarray), \
in_get_caps, outarray, sizeof (outarray), out_get_caps)
+
GST_START_TEST (test_int16)
{
/* stereo to mono */
GST_END_TEST;
+
+GST_START_TEST (test_float32)
+{
+ /* stereo to mono */
+ {
+ gfloat in[] = { 0.6, -0.0078125, 0.03125, 0.03125 };
+ gfloat out[] = { 0.29609375, 0.03125 };
+
+ RUN_CONVERSION ("float32 stereo to mono",
+ in, get_float_caps (2, "BYTE_ORDER", 32),
+ out, get_float_caps (1, "BYTE_ORDER", 32));
+ }
+ /* mono to stereo */
+ {
+ gfloat in[] = { 0.015625, 0.03125 };
+ gfloat out[] = { 0.015625, 0.015625, 0.03125, 0.03125 };
+
+ RUN_CONVERSION ("float32 mono to stereo",
+ in, get_float_caps (1, "BYTE_ORDER", 32),
+ out, get_float_caps (2, "BYTE_ORDER", 32));
+ }
+}
+
+GST_END_TEST;
+
+
GST_START_TEST (test_int_conversion)
{
/* 8 <-> 16 signed */
GST_END_TEST;
+
GST_START_TEST (test_float_conversion)
{
/* 32 float <-> 16 signed */
/* 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), out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)
- );
+ RUN_CONVERSION ("32 float to 16 signed",
+ in, get_float_caps (1, "BYTE_ORDER", 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 };
+
+ RUN_CONVERSION ("16 signed to 32 float",
+ in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
+ out, get_float_caps (1, "BYTE_ORDER", 32));
+ }
+
+ /* 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 };
+ 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),
+ out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE));
+ }
+ {
+ gint16 in[] = { 0, -32768, 16384, -16384 };
+ gdouble out[] = { 0.0,
+ 4.6566128752457969e-10 * (gdouble) (-32768L << 16), /* ~ -1.0 */
+ 4.6566128752457969e-10 * (gdouble) (16384L << 16), /* ~ 0.5 */
+ 4.6566128752457969e-10 * (gdouble) (-16384L << 16), /* ~ -0.5 */
+ };
+
+ RUN_CONVERSION ("16 signed to 64 float",
+ in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
+ out, get_float_caps (1, "BYTE_ORDER", 64));
+ }
+ {
+ gint32 in[] = { 0, (-1L << 31), (1L << 30), (-1L << 30) };
+ gdouble out[] = { 0.0,
+ 4.6566128752457969e-10 * (gdouble) (-1L << 31), /* ~ -1.0 */
+ 4.6566128752457969e-10 * (gdouble) (1L << 30), /* ~ 0.5 */
+ 4.6566128752457969e-10 * (gdouble) (-1L << 30), /* ~ -0.5 */
+ };
+
+ RUN_CONVERSION ("32 signed to 64 float",
+ in, get_int_caps (1, "BYTE_ORDER", 32, 32, TRUE),
+ out, get_float_caps (1, "BYTE_ORDER", 64));
}
/* 64-bit float <-> 32-bit float */
GST_END_TEST;
+
GST_START_TEST (test_multichannel_conversion)
{
{
GST_END_TEST;
+
GST_START_TEST (test_channel_remapping)
{
/* float */
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_int16);
+ tcase_add_test (tc_chain, test_float32);
tcase_add_test (tc_chain, test_int_conversion);
tcase_add_test (tc_chain, test_float_conversion);
tcase_add_test (tc_chain, test_multichannel_conversion);