Don't run inplace if that overwrites source data as we go. Add more tests. Fixes...
authorStefan Kost <ensonic@users.sourceforge.net>
Wed, 28 Feb 2007 11:47:45 +0000 (11:47 +0000)
committerStefan Kost <ensonic@users.sourceforge.net>
Wed, 28 Feb 2007 11:47:45 +0000 (11:47 +0000)
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.

ChangeLog
gst/audioconvert/audioconvert.c
gst/audioconvert/gstaudioconvert.c
tests/check/elements/audioconvert.c

index f3a6cc9d5d3b1e58c89e4b12fff9805f924de7e8..d10d0fc17c50b27db360022c4ee2b42c1d7a5aca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+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),
index 049e101b20a79ddf46e9458b3a97eebd2454dbf4..d06f6ac48584eba1ebb7235bbfab34033840e435 100644 (file)
@@ -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) {
index 6eff1d653cba7e98011e1ad956f90d8045116de7..c18529bc926003f58a097e0690d0795077615c70 100644 (file)
@@ -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 {
index deb2cc2d0fce9f4cabc249241875ac1c3f2112a5..3517b825b96bbab3b11e4a6196fb9243e8b158d5 100644 (file)
@@ -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);