From 400ade1e8fde0c4cf16ae8d45a81c911481757b6 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sun, 14 May 2006 18:15:17 +0000 Subject: [PATCH] gst/audioconvert/gstchannelmix.c: Fix #341696: crash when mixing L+R+C to mono or stereo. Original commit message from CVS: * gst/audioconvert/gstchannelmix.c: (gst_channel_mix_fill_others): Fix #341696: crash when mixing L+R+C to mono or stereo. * tests/check/Makefile.am: * tests/check/elements/audioconvert.c: (set_channel_positions), (get_float_mc_caps), (get_int_mc_caps), (GST_START_TEST), (audioconvert_suite): Add test for the above, including some generic framework bits for testing multichannel things. --- ChangeLog | 11 ++++ gst/audioconvert/gstchannelmix.c | 2 +- tests/check/Makefile.am | 8 +++ tests/check/elements/audioconvert.c | 102 ++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fbeac56..8fdd537 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-05-14 Michael Smith + + * gst/audioconvert/gstchannelmix.c: (gst_channel_mix_fill_others): + Fix #341696: crash when mixing L+R+C to mono or stereo. + * tests/check/Makefile.am: + * tests/check/elements/audioconvert.c: (set_channel_positions), + (get_float_mc_caps), (get_int_mc_caps), (GST_START_TEST), + (audioconvert_suite): + Add test for the above, including some generic framework bits for + testing multichannel things. + === release 0.10.7 === 2006-05-14 Jan Schmidt diff --git a/gst/audioconvert/gstchannelmix.c b/gst/audioconvert/gstchannelmix.c index ab01c93..e6b1c4c 100644 --- a/gst/audioconvert/gstchannelmix.c +++ b/gst/audioconvert/gstchannelmix.c @@ -350,7 +350,7 @@ gst_channel_mix_fill_others (AudioConvertCtx * this) GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, RATIO_FRONT_REAR); - } else if (in_has_center && !out_has_center && out_has_front) { + } else if (in_has_rear && !out_has_rear && out_has_front) { gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 07db7c4..9950280 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -77,6 +77,14 @@ libs_cddabasesrc_CFLAGS = \ -I$(top_srcdir)/gst-libs \ $(CFLAGS) $(AM_CFLAGS) +elements_audioconvert_LDADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(LDADD) + +elements_audioconvert_CFLAGS = \ + -I$(top_srcdir)/gst-libs \ + $(CFLAGS) $(AM_CFLAGS) + libs_video_LDADD = \ $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ $(LDADD) diff --git a/tests/check/elements/audioconvert.c b/tests/check/elements/audioconvert.c index 6172abe..0249a60 100644 --- a/tests/check/elements/audioconvert.c +++ b/tests/check/elements/audioconvert.c @@ -23,6 +23,7 @@ #include #include +#include GList *buffers = NULL; gboolean have_eos = FALSE; @@ -159,6 +160,88 @@ get_float_caps (guint channels, gchar * endianness, guint width) return caps; } +/* Copied from vorbis; the particular values used don't matter */ +static GstAudioChannelPosition channelpositions[][6] = { + { /* Mono */ + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}, + { /* Stereo */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, + { /* Stereo + Centre */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, + { /* Quadraphonic */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + { /* Stereo + Centre + rear stereo */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + { /* Full 5.1 Surround */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE, + }, +}; + +static void +set_channel_positions (GstCaps * caps, int channels, + GstAudioChannelPosition * channelpositions) +{ + GValue chanpos = { 0 }; + GValue pos = { 0 }; + GstStructure *structure = gst_caps_get_structure (caps, 0); + int c; + + g_value_init (&chanpos, GST_TYPE_ARRAY); + g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION); + + for (c = 0; c < channels; c++) { + g_value_set_enum (&pos, channelpositions[c]); + gst_value_array_append_value (&chanpos, &pos); + } + g_value_unset (&pos); + + gst_structure_set_value (structure, "channel-positions", &chanpos); + g_value_unset (&chanpos); +} + +/* For channels > 2, caps have to have channel positions. This adds some simple + * ones. Only implemented for channels between 1 and 6. + */ +static GstCaps * +get_float_mc_caps (guint channels, gchar * endianness, guint width) +{ + GstCaps *caps = get_float_caps (channels, endianness, width); + + if (channels <= 6) + set_channel_positions (caps, channels, channelpositions[channels - 1]); + + return caps; +} + +static GstCaps * +get_int_mc_caps (guint channels, gchar * endianness, guint width, + guint depth, gboolean signedness) +{ + GstCaps *caps = get_int_caps (channels, endianness, width, depth, signedness); + + if (channels <= 6) + set_channel_positions (caps, channels, channelpositions[channels - 1]); + + return caps; +} + /* eats the refs to the caps */ static void verify_convert (const gchar * which, void *in, int inlength, @@ -341,6 +424,24 @@ GST_START_TEST (test_float_conversion) GST_END_TEST; +GST_START_TEST (test_multichannel_conversion) +{ + { + /* Ensure that audioconvert prefers to convert to integer, rather than mix + * to mono + */ + gfloat in[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + gfloat out[] = { 0.0, 0.0 }; + + /* 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 ("3 channels to 1", in, get_float_mc_caps (3, + "BYTE_ORDER", 32), out, get_float_caps (1, "BYTE_ORDER", 32)); + } +} + +GST_END_TEST; Suite * audioconvert_suite (void) @@ -352,6 +453,7 @@ audioconvert_suite (void) tcase_add_test (tc_chain, test_int16); tcase_add_test (tc_chain, test_int_conversion); tcase_add_test (tc_chain, test_float_conversion); + tcase_add_test (tc_chain, test_multichannel_conversion); return s; } -- 2.7.4