Commit 2c67c894 authored by Stefan Kost's avatar Stefan Kost
Browse files

Don't run inplace if that overwrites source data as we go. Add more tests. Fixes #339837 even more.

Original commit message from CVS:
* 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.
parent 354c07de
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),
......@@ -43,13 +43,12 @@ audio_convert_unpack_##name
#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; \
} \
}
......@@ -83,16 +82,14 @@ MAKE_UNPACK_FUNC_NAME (float_hq) (gfloat * src, gdouble * dst, gint s,
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)
......@@ -150,8 +147,9 @@ static void
MAKE_PACK_FUNC_NAME (double) (gint32 * src, gdouble * dst, gint scale,
gint count)
{
for (; count; count--)
for (; count; count--) {
*dst++ = INT2DOUBLE (*src++);
}
}
static void
......@@ -165,9 +163,7 @@ 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)
......@@ -303,16 +299,17 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
/* 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);
......@@ -321,8 +318,11 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * 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;
......@@ -369,7 +369,7 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
{
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);
......@@ -383,16 +383,19 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
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) {
......
......@@ -197,6 +197,7 @@ static void
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;
......@@ -206,20 +207,20 @@ gst_audio_convert_class_init (GstAudioConvertClass * klass)
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
......@@ -315,6 +316,7 @@ gst_audio_convert_get_unit_size (GstBaseTransform * base, GstCaps * caps,
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);
......@@ -323,6 +325,7 @@ gst_audio_convert_get_unit_size (GstBaseTransform * base, GstCaps * caps,
parse_error:
{
GST_INFO_OBJECT (base, "failed to parse caps to get unit_size");
return FALSE;
}
}
......@@ -525,14 +528,9 @@ gst_audio_convert_transform_caps (GstBaseTransform * base,
* 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 {
......
......@@ -348,6 +348,7 @@ verify_convert (const gchar * which, void *in, int inlength,
verify_convert (which, inarray, sizeof (inarray), \
in_get_caps, outarray, sizeof (outarray), out_get_caps)
GST_START_TEST (test_int16)
{
/* stereo to mono */
......@@ -384,6 +385,32 @@ GST_START_TEST (test_int16)
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 */
......@@ -448,6 +475,7 @@ GST_START_TEST (test_int_conversion)
GST_END_TEST;
GST_START_TEST (test_float_conversion)
{
/* 32 float <-> 16 signed */
......@@ -459,9 +487,55 @@ GST_START_TEST (test_float_conversion)
/* 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 */
......@@ -481,6 +555,7 @@ GST_START_TEST (test_float_conversion)
GST_END_TEST;
GST_START_TEST (test_multichannel_conversion)
{
{
......@@ -501,6 +576,7 @@ GST_START_TEST (test_multichannel_conversion)
GST_END_TEST;
GST_START_TEST (test_channel_remapping)
{
/* float */
......@@ -606,6 +682,7 @@ audioconvert_suite (void)
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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment