gst_plugins_base/tests/check/elements/audioconvert.c
changeset 0 0e761a78d257
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  *
       
     3  * unit test for audioconvert
       
     4  *
       
     5  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public
       
    18  * License along with this library; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 #include <unistd.h>
       
    24 
       
    25 #include <gst/floatcast/floatcast.h>
       
    26 #include <gst/check/gstcheck.h>
       
    27 #include <gst/audio/multichannel.h>
       
    28 
       
    29 /* For ease of programming we use globals to keep refs for our floating
       
    30  * src and sink pads we create; otherwise we always have to do get_pad,
       
    31  * get_peer, and then remove references in every test function */
       
    32 static GstPad *mysrcpad, *mysinkpad;
       
    33 
       
    34 #define CONVERT_CAPS_TEMPLATE_STRING    \
       
    35   "audio/x-raw-float, " \
       
    36     "rate = (int) [ 1, MAX ], " \
       
    37     "channels = (int) [ 1, 8 ], " \
       
    38     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
       
    39     "width = (int) { 32, 64 };" \
       
    40   "audio/x-raw-int, " \
       
    41     "rate = (int) [ 1, MAX ], " \
       
    42     "channels = (int) [ 1, 8 ], " \
       
    43     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
       
    44     "width = (int) 32, " \
       
    45     "depth = (int) [ 1, 32 ], " \
       
    46     "signed = (boolean) { true, false }; " \
       
    47   "audio/x-raw-int, " \
       
    48     "rate = (int) [ 1, MAX ], " \
       
    49     "channels = (int) [ 1, 8 ], " \
       
    50     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
       
    51     "width = (int) 24, " \
       
    52     "depth = (int) [ 1, 24 ], " \
       
    53     "signed = (boolean) { true, false }; " \
       
    54   "audio/x-raw-int, " \
       
    55     "rate = (int) [ 1, MAX ], " \
       
    56     "channels = (int) [ 1, 8 ], " \
       
    57     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
       
    58     "width = (int) 16, " \
       
    59     "depth = (int) [ 1, 16 ], " \
       
    60     "signed = (boolean) { true, false }; " \
       
    61   "audio/x-raw-int, " \
       
    62     "rate = (int) [ 1, MAX ], " \
       
    63     "channels = (int) [ 1, 8 ], " \
       
    64     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
       
    65     "width = (int) 8, " \
       
    66     "depth = (int) [ 1, 8 ], " \
       
    67     "signed = (boolean) { true, false } "
       
    68 
       
    69 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
       
    70     GST_PAD_SINK,
       
    71     GST_PAD_ALWAYS,
       
    72     GST_STATIC_CAPS (CONVERT_CAPS_TEMPLATE_STRING)
       
    73     );
       
    74 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
       
    75     GST_PAD_SRC,
       
    76     GST_PAD_ALWAYS,
       
    77     GST_STATIC_CAPS (CONVERT_CAPS_TEMPLATE_STRING)
       
    78     );
       
    79 
       
    80 /* takes over reference for outcaps */
       
    81 static GstElement *
       
    82 setup_audioconvert (GstCaps * outcaps)
       
    83 {
       
    84   GstElement *audioconvert;
       
    85 
       
    86   GST_DEBUG ("setup_audioconvert with caps %" GST_PTR_FORMAT, outcaps);
       
    87   audioconvert = gst_check_setup_element ("audioconvert");
       
    88   g_object_set (G_OBJECT (audioconvert), "dithering", 0, NULL);
       
    89   g_object_set (G_OBJECT (audioconvert), "noise-shaping", 0, NULL);
       
    90   mysrcpad = gst_check_setup_src_pad (audioconvert, &srctemplate, NULL);
       
    91   mysinkpad = gst_check_setup_sink_pad (audioconvert, &sinktemplate, NULL);
       
    92   /* this installs a getcaps func that will always return the caps we set
       
    93    * later */
       
    94   gst_pad_use_fixed_caps (mysinkpad);
       
    95   gst_pad_set_caps (mysinkpad, outcaps);
       
    96   gst_caps_unref (outcaps);
       
    97   outcaps = gst_pad_get_negotiated_caps (mysinkpad);
       
    98   fail_unless (gst_caps_is_fixed (outcaps));
       
    99   gst_caps_unref (outcaps);
       
   100 
       
   101   gst_pad_set_active (mysrcpad, TRUE);
       
   102   gst_pad_set_active (mysinkpad, TRUE);
       
   103 
       
   104   return audioconvert;
       
   105 }
       
   106 
       
   107 static void
       
   108 cleanup_audioconvert (GstElement * audioconvert)
       
   109 {
       
   110   GST_DEBUG ("cleanup_audioconvert");
       
   111 
       
   112   gst_pad_set_active (mysrcpad, FALSE);
       
   113   gst_pad_set_active (mysinkpad, FALSE);
       
   114   gst_check_teardown_src_pad (audioconvert);
       
   115   gst_check_teardown_sink_pad (audioconvert);
       
   116   gst_check_teardown_element (audioconvert);
       
   117 }
       
   118 
       
   119 /* returns a newly allocated caps */
       
   120 static GstCaps *
       
   121 get_int_caps (guint channels, gchar * endianness, guint width,
       
   122     guint depth, gboolean signedness)
       
   123 {
       
   124   GstCaps *caps;
       
   125   gchar *string;
       
   126 
       
   127   string = g_strdup_printf ("audio/x-raw-int, "
       
   128       "rate = (int) 44100, "
       
   129       "channels = (int) %d, "
       
   130       "endianness = (int) %s, "
       
   131       "width = (int) %d, "
       
   132       "depth = (int) %d, "
       
   133       "signed = (boolean) %s ",
       
   134       channels, endianness, width, depth, signedness ? "true" : "false");
       
   135   GST_DEBUG ("creating caps from %s", string);
       
   136   caps = gst_caps_from_string (string);
       
   137   g_free (string);
       
   138   fail_unless (caps != NULL);
       
   139   GST_DEBUG ("returning caps %p", caps);
       
   140   return caps;
       
   141 }
       
   142 
       
   143 /* returns a newly allocated caps */
       
   144 static GstCaps *
       
   145 get_float_caps (guint channels, gchar * endianness, guint width)
       
   146 {
       
   147   GstCaps *caps;
       
   148   gchar *string;
       
   149 
       
   150   string = g_strdup_printf ("audio/x-raw-float, "
       
   151       "rate = (int) 44100, "
       
   152       "channels = (int) %d, "
       
   153       "endianness = (int) %s, "
       
   154       "width = (int) %d ", channels, endianness, width);
       
   155   GST_DEBUG ("creating caps from %s", string);
       
   156   caps = gst_caps_from_string (string);
       
   157   g_free (string);
       
   158   fail_unless (caps != NULL);
       
   159   GST_DEBUG ("returning caps %p", caps);
       
   160   return caps;
       
   161 }
       
   162 
       
   163 /* Copied from vorbis; the particular values used don't matter */
       
   164 static GstAudioChannelPosition channelpositions[][6] = {
       
   165   {                             /* Mono */
       
   166       GST_AUDIO_CHANNEL_POSITION_FRONT_MONO},
       
   167   {                             /* Stereo */
       
   168         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   169       GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
       
   170   {                             /* Stereo + Centre */
       
   171         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   172         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   173       GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
       
   174   {                             /* Quadraphonic */
       
   175         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   176         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   177         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   178         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   179       },
       
   180   {                             /* Stereo + Centre + rear stereo */
       
   181         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   182         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   183         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   184         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   185         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   186       },
       
   187   {                             /* Full 5.1 Surround */
       
   188         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   189         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   190         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   191         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   192         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   193         GST_AUDIO_CHANNEL_POSITION_LFE,
       
   194       }
       
   195 };
       
   196 
       
   197 /* these are a bunch of random positions, they are mostly just
       
   198  * different from the ones above, don't use elsewhere */
       
   199 static GstAudioChannelPosition mixed_up_positions[][6] = {
       
   200   {
       
   201       GST_AUDIO_CHANNEL_POSITION_FRONT_MONO},
       
   202   {
       
   203         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   204       GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT},
       
   205   {
       
   206         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   207         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   208       GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT},
       
   209   {
       
   210         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   211         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   212         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   213         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   214       },
       
   215   {
       
   216         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   217         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   218         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   219         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   220         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   221       },
       
   222   {
       
   223         GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   224         GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   225         GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   226         GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   227         GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   228         GST_AUDIO_CHANNEL_POSITION_LFE,
       
   229       }
       
   230 };
       
   231 
       
   232 static void
       
   233 set_channel_positions (GstCaps * caps, int channels,
       
   234     GstAudioChannelPosition * channelpositions)
       
   235 {
       
   236   GValue chanpos = { 0 };
       
   237   GValue pos = { 0 };
       
   238   GstStructure *structure = gst_caps_get_structure (caps, 0);
       
   239   int c;
       
   240 
       
   241   g_value_init (&chanpos, GST_TYPE_ARRAY);
       
   242   g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
       
   243 
       
   244   for (c = 0; c < channels; c++) {
       
   245     g_value_set_enum (&pos, channelpositions[c]);
       
   246     gst_value_array_append_value (&chanpos, &pos);
       
   247   }
       
   248   g_value_unset (&pos);
       
   249 
       
   250   gst_structure_set_value (structure, "channel-positions", &chanpos);
       
   251   g_value_unset (&chanpos);
       
   252 }
       
   253 
       
   254 /* For channels > 2, caps have to have channel positions. This adds some simple
       
   255  * ones. Only implemented for channels between 1 and 6.
       
   256  */
       
   257 static GstCaps *
       
   258 get_float_mc_caps (guint channels, gchar * endianness, guint width,
       
   259     gboolean mixed_up_layout)
       
   260 {
       
   261   GstCaps *caps = get_float_caps (channels, endianness, width);
       
   262 
       
   263   if (channels <= 6) {
       
   264     if (mixed_up_layout)
       
   265       set_channel_positions (caps, channels, mixed_up_positions[channels - 1]);
       
   266     else
       
   267       set_channel_positions (caps, channels, channelpositions[channels - 1]);
       
   268   }
       
   269 
       
   270   return caps;
       
   271 }
       
   272 
       
   273 static GstCaps *
       
   274 get_int_mc_caps (guint channels, gchar * endianness, guint width,
       
   275     guint depth, gboolean signedness, gboolean mixed_up_layout)
       
   276 {
       
   277   GstCaps *caps = get_int_caps (channels, endianness, width, depth, signedness);
       
   278 
       
   279   if (channels <= 6) {
       
   280     if (mixed_up_layout)
       
   281       set_channel_positions (caps, channels, mixed_up_positions[channels - 1]);
       
   282     else
       
   283       set_channel_positions (caps, channels, channelpositions[channels - 1]);
       
   284   }
       
   285 
       
   286   return caps;
       
   287 }
       
   288 
       
   289 /* eats the refs to the caps */
       
   290 static void
       
   291 verify_convert (const gchar * which, void *in, int inlength,
       
   292     GstCaps * incaps, void *out, int outlength, GstCaps * outcaps)
       
   293 {
       
   294   GstBuffer *inbuffer, *outbuffer;
       
   295   GstElement *audioconvert;
       
   296 
       
   297   GST_DEBUG ("verifying conversion %s", which);
       
   298   GST_DEBUG ("incaps: %" GST_PTR_FORMAT, incaps);
       
   299   GST_DEBUG ("outcaps: %" GST_PTR_FORMAT, outcaps);
       
   300   ASSERT_CAPS_REFCOUNT (incaps, "incaps", 1);
       
   301   ASSERT_CAPS_REFCOUNT (outcaps, "outcaps", 1);
       
   302   audioconvert = setup_audioconvert (outcaps);
       
   303   ASSERT_CAPS_REFCOUNT (outcaps, "outcaps", 1);
       
   304 
       
   305   fail_unless (gst_element_set_state (audioconvert,
       
   306           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
       
   307       "could not set to playing");
       
   308 
       
   309   GST_DEBUG ("Creating buffer of %d bytes", inlength);
       
   310   inbuffer = gst_buffer_new_and_alloc (inlength);
       
   311   memcpy (GST_BUFFER_DATA (inbuffer), in, inlength);
       
   312   gst_buffer_set_caps (inbuffer, incaps);
       
   313   ASSERT_CAPS_REFCOUNT (incaps, "incaps", 2);
       
   314   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
       
   315 
       
   316   /* pushing gives away my reference ... */
       
   317   GST_DEBUG ("push it");
       
   318   fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
       
   319   GST_DEBUG ("pushed it");
       
   320   /* ... and puts a new buffer on the global list */
       
   321   fail_unless (g_list_length (buffers) == 1);
       
   322   fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
       
   323 
       
   324   ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
       
   325   fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), outlength);
       
   326 
       
   327   if (memcmp (GST_BUFFER_DATA (outbuffer), out, outlength) != 0) {
       
   328     g_print ("\nInput data:\n");
       
   329     gst_util_dump_mem (in, inlength);
       
   330     g_print ("\nConverted data:\n");
       
   331     gst_util_dump_mem (GST_BUFFER_DATA (outbuffer), outlength);
       
   332     g_print ("\nExpected data:\n");
       
   333     gst_util_dump_mem (out, outlength);
       
   334   }
       
   335   fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, outlength) == 0,
       
   336       "failed converting %s", which);
       
   337 
       
   338   /* make sure that the channel positions are not lost */
       
   339   {
       
   340     GstStructure *in_s, *out_s;
       
   341     gint out_chans;
       
   342 
       
   343     in_s = gst_caps_get_structure (incaps, 0);
       
   344     out_s = gst_caps_get_structure (GST_BUFFER_CAPS (outbuffer), 0);
       
   345     fail_unless (gst_structure_get_int (out_s, "channels", &out_chans));
       
   346 
       
   347     /* positions for 1 and 2 channels are implicit if not provided */
       
   348     if (out_chans > 2 && gst_structure_has_field (in_s, "channel-positions")) {
       
   349       if (!gst_structure_has_field (out_s, "channel-positions")) {
       
   350         g_error ("Channel layout got lost somewhere:\n\nIns : %s\nOuts: %s\n",
       
   351             gst_structure_to_string (in_s), gst_structure_to_string (out_s));
       
   352       }
       
   353     }
       
   354   }
       
   355 
       
   356   buffers = g_list_remove (buffers, outbuffer);
       
   357   gst_buffer_unref (outbuffer);
       
   358   fail_unless (gst_element_set_state (audioconvert,
       
   359           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
       
   360   /* cleanup */
       
   361   GST_DEBUG ("cleanup audioconvert");
       
   362   cleanup_audioconvert (audioconvert);
       
   363   GST_DEBUG ("cleanup, unref incaps");
       
   364   ASSERT_CAPS_REFCOUNT (incaps, "incaps", 1);
       
   365   gst_caps_unref (incaps);
       
   366 }
       
   367 
       
   368 
       
   369 #define RUN_CONVERSION(which, inarray, in_get_caps, outarray, out_get_caps)    \
       
   370   verify_convert (which, inarray, sizeof (inarray),                            \
       
   371         in_get_caps, outarray, sizeof (outarray), out_get_caps)
       
   372 
       
   373 
       
   374 GST_START_TEST (test_int16)
       
   375 {
       
   376   /* stereo to mono */
       
   377   {
       
   378     gint16 in[] = { 16384, -256, 1024, 1024 };
       
   379     gint16 out[] = { 8064, 1024 };
       
   380 
       
   381     RUN_CONVERSION ("int16 stereo to mono",
       
   382         in, get_int_caps (2, "BYTE_ORDER", 16, 16, TRUE),
       
   383         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE));
       
   384   }
       
   385   /* mono to stereo */
       
   386   {
       
   387     gint16 in[] = { 512, 1024 };
       
   388     gint16 out[] = { 512, 512, 1024, 1024 };
       
   389 
       
   390     RUN_CONVERSION ("int16 mono to stereo",
       
   391         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   392         out, get_int_caps (2, "BYTE_ORDER", 16, 16, TRUE));
       
   393   }
       
   394   /* signed -> unsigned */
       
   395   {
       
   396     gint16 in[] = { 0, -32767, 32767, -32768 };
       
   397     guint16 out[] = { 32768, 1, 65535, 0 };
       
   398 
       
   399     RUN_CONVERSION ("int16 signed to unsigned",
       
   400         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   401         out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE));
       
   402     RUN_CONVERSION ("int16 unsigned to signed",
       
   403         out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE),
       
   404         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE));
       
   405   }
       
   406 }
       
   407 
       
   408 GST_END_TEST;
       
   409 
       
   410 
       
   411 GST_START_TEST (test_float32)
       
   412 {
       
   413   /* stereo to mono */
       
   414   {
       
   415     gfloat in[] = { 0.6, -0.0078125, 0.03125, 0.03125 };
       
   416     gfloat out[] = { 0.29609375, 0.03125 };
       
   417 
       
   418     RUN_CONVERSION ("float32 stereo to mono",
       
   419         in, get_float_caps (2, "BYTE_ORDER", 32),
       
   420         out, get_float_caps (1, "BYTE_ORDER", 32));
       
   421   }
       
   422   /* mono to stereo */
       
   423   {
       
   424     gfloat in[] = { 0.015625, 0.03125 };
       
   425     gfloat out[] = { 0.015625, 0.015625, 0.03125, 0.03125 };
       
   426 
       
   427     RUN_CONVERSION ("float32 mono to stereo",
       
   428         in, get_float_caps (1, "BYTE_ORDER", 32),
       
   429         out, get_float_caps (2, "BYTE_ORDER", 32));
       
   430   }
       
   431 }
       
   432 
       
   433 GST_END_TEST;
       
   434 
       
   435 
       
   436 GST_START_TEST (test_int_conversion)
       
   437 {
       
   438   /* 8 <-> 16 signed */
       
   439   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   440   {
       
   441     gint8 in[] = { 0, 1, 2, 127, -127 };
       
   442     gint16 out[] = { 0, 256, 512, 32512, -32512 };
       
   443 
       
   444     RUN_CONVERSION ("int 8bit to 16bit signed",
       
   445         in, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE),
       
   446         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)
       
   447         );
       
   448     RUN_CONVERSION ("int 16bit signed to 8bit",
       
   449         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   450         in, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE)
       
   451         );
       
   452   }
       
   453   /* 16 -> 8 signed */
       
   454   {
       
   455     gint16 in[] = { 0, 127, 128, 256, 256 + 127, 256 + 128 };
       
   456     gint8 out[] = { 0, 0, 1, 1, 1, 2 };
       
   457 
       
   458     RUN_CONVERSION ("16 bit to 8 signed",
       
   459         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   460         out, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE)
       
   461         );
       
   462   }
       
   463   /* 8 unsigned <-> 16 signed */
       
   464   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   465   {
       
   466     guint8 in[] = { 128, 129, 130, 255, 1 };
       
   467     gint16 out[] = { 0, 256, 512, 32512, -32512 };
       
   468     GstCaps *incaps, *outcaps;
       
   469 
       
   470     /* exploded for easier valgrinding */
       
   471     incaps = get_int_caps (1, "BYTE_ORDER", 8, 8, FALSE);
       
   472     outcaps = get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE);
       
   473     GST_DEBUG ("incaps: %" GST_PTR_FORMAT, incaps);
       
   474     GST_DEBUG ("outcaps: %" GST_PTR_FORMAT, outcaps);
       
   475     RUN_CONVERSION ("8 unsigned to 16 signed", in, incaps, out, outcaps);
       
   476     RUN_CONVERSION ("16 signed to 8 unsigned", out, get_int_caps (1,
       
   477             "BYTE_ORDER", 16, 16, TRUE), in, get_int_caps (1, "BYTE_ORDER", 8,
       
   478             8, FALSE)
       
   479         );
       
   480   }
       
   481   /* 8 <-> 24 signed */
       
   482   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   483   {
       
   484     gint8 in[] = { 0, 1, 127 };
       
   485     guint8 out[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7f };
       
   486     /* out has the bytes in little-endian, so that's how they should be
       
   487      * interpreted during conversion */
       
   488 
       
   489     RUN_CONVERSION ("8 to 24 signed", in, get_int_caps (1, "BYTE_ORDER", 8, 8,
       
   490             TRUE), out, get_int_caps (1, "LITTLE_ENDIAN", 24, 24, TRUE)
       
   491         );
       
   492     RUN_CONVERSION ("24 signed to 8", out, get_int_caps (1, "LITTLE_ENDIAN", 24,
       
   493             24, TRUE), in, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE)
       
   494         );
       
   495   }
       
   496 
       
   497   /* 16 bit signed <-> unsigned */
       
   498   {
       
   499     gint16 in[] = { 0, 128, -128 };
       
   500     guint16 out[] = { 32768, 32896, 32640 };
       
   501     RUN_CONVERSION ("16 signed to 16 unsigned",
       
   502         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   503         out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE)
       
   504         );
       
   505     RUN_CONVERSION ("16 unsigned to 16 signed",
       
   506         out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE),
       
   507         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)
       
   508         );
       
   509   }
       
   510 
       
   511   /* 16 bit signed <-> 8 in 16 bit signed */
       
   512   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   513   {
       
   514     gint16 in[] = { 0, 64 << 8, -64 << 8 };
       
   515     gint16 out[] = { 0, 64, -64 };
       
   516     RUN_CONVERSION ("16 signed to 8 in 16 signed",
       
   517         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   518         out, get_int_caps (1, "BYTE_ORDER", 16, 8, TRUE)
       
   519         );
       
   520     RUN_CONVERSION ("8 in 16 signed to 16 signed",
       
   521         out, get_int_caps (1, "BYTE_ORDER", 16, 8, TRUE),
       
   522         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)
       
   523         );
       
   524   }
       
   525 
       
   526   /* 16 bit unsigned <-> 8 in 16 bit unsigned */
       
   527   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   528   {
       
   529     guint16 in[] = { 1 << 15, (1 << 15) - (64 << 8), (1 << 15) + (64 << 8) };
       
   530     guint16 out[] = { 1 << 7, (1 << 7) - 64, (1 << 7) + 64 };
       
   531     RUN_CONVERSION ("16 unsigned to 8 in 16 unsigned",
       
   532         in, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE),
       
   533         out, get_int_caps (1, "BYTE_ORDER", 16, 8, FALSE)
       
   534         );
       
   535     RUN_CONVERSION ("8 in 16 unsigned to 16 unsigned",
       
   536         out, get_int_caps (1, "BYTE_ORDER", 16, 8, FALSE),
       
   537         in, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE)
       
   538         );
       
   539   }
       
   540 
       
   541   /* 32 bit signed -> 16 bit signed for rounding check */
       
   542   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   543   {
       
   544     gint32 in[] = { 0, G_MININT32, G_MAXINT32,
       
   545       (32 << 16), (32 << 16) + (1 << 15), (32 << 16) - (1 << 15),
       
   546       (32 << 16) + (2 << 15), (32 << 16) - (2 << 15),
       
   547       (-32 << 16) + (1 << 15), (-32 << 16) - (1 << 15),
       
   548       (-32 << 16) + (2 << 15), (-32 << 16) - (2 << 15),
       
   549       (-32 << 16)
       
   550     };
       
   551     gint16 out[] = { 0, G_MININT16, G_MAXINT16,
       
   552       32, 33, 32,
       
   553       33, 31,
       
   554       -31, -32,
       
   555       -31, -33,
       
   556       -32
       
   557     };
       
   558     RUN_CONVERSION ("32 signed to 16 signed for rounding",
       
   559         in, get_int_caps (1, "BYTE_ORDER", 32, 32, TRUE),
       
   560         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)
       
   561         );
       
   562   }
       
   563 
       
   564   /* 32 bit signed -> 16 bit unsigned for rounding check */
       
   565   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   566   {
       
   567     gint32 in[] = { 0, G_MININT32, G_MAXINT32,
       
   568       (32 << 16), (32 << 16) + (1 << 15), (32 << 16) - (1 << 15),
       
   569       (32 << 16) + (2 << 15), (32 << 16) - (2 << 15),
       
   570       (-32 << 16) + (1 << 15), (-32 << 16) - (1 << 15),
       
   571       (-32 << 16) + (2 << 15), (-32 << 16) - (2 << 15),
       
   572       (-32 << 16)
       
   573     };
       
   574     guint16 out[] = { (1 << 15), 0, G_MAXUINT16,
       
   575       (1 << 15) + 32, (1 << 15) + 33, (1 << 15) + 32,
       
   576       (1 << 15) + 33, (1 << 15) + 31,
       
   577       (1 << 15) - 31, (1 << 15) - 32,
       
   578       (1 << 15) - 31, (1 << 15) - 33,
       
   579       (1 << 15) - 32
       
   580     };
       
   581     RUN_CONVERSION ("32 signed to 16 unsigned for rounding",
       
   582         in, get_int_caps (1, "BYTE_ORDER", 32, 32, TRUE),
       
   583         out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE)
       
   584         );
       
   585   }
       
   586 }
       
   587 
       
   588 GST_END_TEST;
       
   589 
       
   590 GST_START_TEST (test_float_conversion)
       
   591 {
       
   592   /* 32 float <-> 16 signed */
       
   593   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   594   {
       
   595     gfloat in_le[] =
       
   596         { GFLOAT_TO_LE (0.0), GFLOAT_TO_LE (1.0), GFLOAT_TO_LE (-1.0),
       
   597       GFLOAT_TO_LE (0.5), GFLOAT_TO_LE (-0.5), GFLOAT_TO_LE (1.1),
       
   598       GFLOAT_TO_LE (-1.1)
       
   599     };
       
   600     gfloat in_be[] =
       
   601         { GFLOAT_TO_BE (0.0), GFLOAT_TO_BE (1.0), GFLOAT_TO_BE (-1.0),
       
   602       GFLOAT_TO_BE (0.5), GFLOAT_TO_BE (-0.5), GFLOAT_TO_BE (1.1),
       
   603       GFLOAT_TO_BE (-1.1)
       
   604     };
       
   605     gint16 out[] = { 0, 32767, -32768, 16384, -16384, 32767, -32768 };
       
   606 
       
   607     /* only one direction conversion, the other direction does
       
   608      * not produce exactly the same as the input due to floating
       
   609      * point rounding errors etc. */
       
   610     RUN_CONVERSION ("32 float le to 16 signed",
       
   611         in_le, get_float_caps (1, "LITTLE_ENDIAN", 32),
       
   612         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE));
       
   613     RUN_CONVERSION ("32 float be to 16 signed",
       
   614         in_be, get_float_caps (1, "BIG_ENDIAN", 32),
       
   615         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE));
       
   616   }
       
   617 
       
   618   {
       
   619     gint16 in[] = { 0, -32768, 16384, -16384 };
       
   620     gfloat out[] = { 0.0, -1.0, 0.5, -0.5 };
       
   621 
       
   622     RUN_CONVERSION ("16 signed to 32 float",
       
   623         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   624         out, get_float_caps (1, "BYTE_ORDER", 32));
       
   625   }
       
   626 
       
   627   /* 64 float <-> 16 signed */
       
   628   /* NOTE: if audioconvert was doing dithering we'd have a problem */
       
   629   {
       
   630     gdouble in_le[] =
       
   631         { GDOUBLE_TO_LE (0.0), GDOUBLE_TO_LE (1.0), GDOUBLE_TO_LE (-1.0),
       
   632       GDOUBLE_TO_LE (0.5), GDOUBLE_TO_LE (-0.5), GDOUBLE_TO_LE (1.1),
       
   633       GDOUBLE_TO_LE (-1.1)
       
   634     };
       
   635     gdouble in_be[] =
       
   636         { GDOUBLE_TO_BE (0.0), GDOUBLE_TO_BE (1.0), GDOUBLE_TO_BE (-1.0),
       
   637       GDOUBLE_TO_BE (0.5), GDOUBLE_TO_BE (-0.5), GDOUBLE_TO_BE (1.1),
       
   638       GDOUBLE_TO_BE (-1.1)
       
   639     };
       
   640     gint16 out[] = { 0, 32767, -32768, 16384, -16384, 32767, -32768 };
       
   641 
       
   642     /* only one direction conversion, the other direction does
       
   643      * not produce exactly the same as the input due to floating
       
   644      * point rounding errors etc. */
       
   645     RUN_CONVERSION ("64 float LE to 16 signed",
       
   646         in_le, get_float_caps (1, "LITTLE_ENDIAN", 64),
       
   647         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE));
       
   648     RUN_CONVERSION ("64 float BE to 16 signed",
       
   649         in_be, get_float_caps (1, "BIG_ENDIAN", 64),
       
   650         out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE));
       
   651   }
       
   652   {
       
   653     gint16 in[] = { 0, -32768, 16384, -16384 };
       
   654     gdouble out[] = { 0.0,
       
   655       (gdouble) (-32768L << 16) / 2147483647.0, /* ~ -1.0 */
       
   656       (gdouble) (16384L << 16) / 2147483647.0,  /* ~  0.5 */
       
   657       (gdouble) (-16384L << 16) / 2147483647.0, /* ~ -0.5 */
       
   658     };
       
   659 
       
   660     RUN_CONVERSION ("16 signed to 64 float",
       
   661         in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE),
       
   662         out, get_float_caps (1, "BYTE_ORDER", 64));
       
   663   }
       
   664   {
       
   665     gint32 in[] = { 0, (-1L << 31), (1L << 30), (-1L << 30) };
       
   666     gdouble out[] = { 0.0,
       
   667       (gdouble) (-1L << 31) / 2147483647.0,     /* ~ -1.0 */
       
   668       (gdouble) (1L << 30) / 2147483647.0,      /* ~  0.5 */
       
   669       (gdouble) (-1L << 30) / 2147483647.0,     /* ~ -0.5 */
       
   670     };
       
   671 
       
   672     RUN_CONVERSION ("32 signed to 64 float",
       
   673         in, get_int_caps (1, "BYTE_ORDER", 32, 32, TRUE),
       
   674         out, get_float_caps (1, "BYTE_ORDER", 64));
       
   675   }
       
   676 
       
   677   /* 64-bit float <-> 32-bit float */
       
   678   {
       
   679     gdouble in[] = { 0.0, 1.0, -1.0, 0.5, -0.5 };
       
   680     gfloat out[] = { 0.0, 1.0, -1.0, 0.5, -0.5 };
       
   681 
       
   682     RUN_CONVERSION ("64 float to 32 float",
       
   683         in, get_float_caps (1, "BYTE_ORDER", 64),
       
   684         out, get_float_caps (1, "BYTE_ORDER", 32));
       
   685 
       
   686     RUN_CONVERSION ("32 float to 64 float",
       
   687         out, get_float_caps (1, "BYTE_ORDER", 32),
       
   688         in, get_float_caps (1, "BYTE_ORDER", 64));
       
   689   }
       
   690 
       
   691   /* 32-bit float little endian <-> big endian */
       
   692   {
       
   693     gfloat le[] = { GFLOAT_TO_LE (0.0), GFLOAT_TO_LE (1.0), GFLOAT_TO_LE (-1.0),
       
   694       GFLOAT_TO_LE (0.5), GFLOAT_TO_LE (-0.5)
       
   695     };
       
   696     gfloat be[] = { GFLOAT_TO_BE (0.0), GFLOAT_TO_BE (1.0), GFLOAT_TO_BE (-1.0),
       
   697       GFLOAT_TO_BE (0.5), GFLOAT_TO_BE (-0.5)
       
   698     };
       
   699 
       
   700     RUN_CONVERSION ("32 float LE to BE",
       
   701         le, get_float_caps (1, "LITTLE_ENDIAN", 32),
       
   702         be, get_float_caps (1, "BIG_ENDIAN", 32));
       
   703 
       
   704     RUN_CONVERSION ("32 float BE to LE",
       
   705         be, get_float_caps (1, "BIG_ENDIAN", 32),
       
   706         le, get_float_caps (1, "LITTLE_ENDIAN", 32));
       
   707   }
       
   708 
       
   709   /* 64-bit float little endian <-> big endian */
       
   710   {
       
   711     gdouble le[] =
       
   712         { GDOUBLE_TO_LE (0.0), GDOUBLE_TO_LE (1.0), GDOUBLE_TO_LE (-1.0),
       
   713       GDOUBLE_TO_LE (0.5), GDOUBLE_TO_LE (-0.5)
       
   714     };
       
   715     gdouble be[] =
       
   716         { GDOUBLE_TO_BE (0.0), GDOUBLE_TO_BE (1.0), GDOUBLE_TO_BE (-1.0),
       
   717       GDOUBLE_TO_BE (0.5), GDOUBLE_TO_BE (-0.5)
       
   718     };
       
   719 
       
   720     RUN_CONVERSION ("64 float LE to BE",
       
   721         le, get_float_caps (1, "LITTLE_ENDIAN", 64),
       
   722         be, get_float_caps (1, "BIG_ENDIAN", 64));
       
   723 
       
   724     RUN_CONVERSION ("64 float BE to LE",
       
   725         be, get_float_caps (1, "BIG_ENDIAN", 64),
       
   726         le, get_float_caps (1, "LITTLE_ENDIAN", 64));
       
   727   }
       
   728 }
       
   729 
       
   730 GST_END_TEST;
       
   731 
       
   732 
       
   733 GST_START_TEST (test_multichannel_conversion)
       
   734 {
       
   735   {
       
   736     /* Ensure that audioconvert prefers to convert to integer, rather than mix
       
   737      * to mono
       
   738      */
       
   739     gfloat in[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
       
   740     gfloat out[] = { 0.0, 0.0 };
       
   741 
       
   742     /* only one direction conversion, the other direction does
       
   743      * not produce exactly the same as the input due to floating
       
   744      * point rounding errors etc. */
       
   745     RUN_CONVERSION ("3 channels to 1", in, get_float_mc_caps (3,
       
   746             "BYTE_ORDER", 32, FALSE), out, get_float_caps (1, "BYTE_ORDER",
       
   747             32));
       
   748   }
       
   749 }
       
   750 
       
   751 GST_END_TEST;
       
   752 
       
   753 
       
   754 GST_START_TEST (test_channel_remapping)
       
   755 {
       
   756   /* float */
       
   757   {
       
   758     gfloat in[] = { 0.0, 1.0, -0.5 };
       
   759     gfloat out[] = { -0.5, 1.0, 0.0 };
       
   760     GstCaps *in_caps = get_float_mc_caps (3, "BYTE_ORDER", 32, FALSE);
       
   761     GstCaps *out_caps = get_float_mc_caps (3, "BYTE_ORDER", 32, TRUE);
       
   762 
       
   763     RUN_CONVERSION ("3 channels layout remapping float", in, in_caps,
       
   764         out, out_caps);
       
   765   }
       
   766 
       
   767   /* int */
       
   768   {
       
   769     guint16 in[] = { 0, 65535, 0x9999 };
       
   770     guint16 out[] = { 0x9999, 65535, 0 };
       
   771     GstCaps *in_caps = get_int_mc_caps (3, "BYTE_ORDER", 16, 16, FALSE, FALSE);
       
   772     GstCaps *out_caps = get_int_mc_caps (3, "BYTE_ORDER", 16, 16, FALSE, TRUE);
       
   773 
       
   774     RUN_CONVERSION ("3 channels layout remapping int", in, in_caps,
       
   775         out, out_caps);
       
   776   }
       
   777 
       
   778   /* TODO: float => int conversion with remapping and vice versa,
       
   779    *       int   => int conversion with remapping */
       
   780 }
       
   781 
       
   782 GST_END_TEST;
       
   783 
       
   784 GST_START_TEST (test_caps_negotiation)
       
   785 {
       
   786   GstElement *src, *ac1, *ac2, *ac3, *sink;
       
   787   GstElement *pipeline;
       
   788   GstPad *ac3_src;
       
   789   GstCaps *caps1, *caps2;
       
   790 
       
   791   pipeline = gst_pipeline_new ("test");
       
   792 
       
   793   /* create elements */
       
   794   src = gst_element_factory_make ("audiotestsrc", "src");
       
   795   ac1 = gst_element_factory_make ("audioconvert", "ac1");
       
   796   ac2 = gst_element_factory_make ("audioconvert", "ac2");
       
   797   ac3 = gst_element_factory_make ("audioconvert", "ac3");
       
   798   sink = gst_element_factory_make ("fakesink", "sink");
       
   799   ac3_src = gst_element_get_pad (ac3, "src");
       
   800 
       
   801   /* test with 2 audioconvert elements */
       
   802   gst_bin_add_many (GST_BIN (pipeline), src, ac1, ac3, sink, NULL);
       
   803   gst_element_link_many (src, ac1, ac3, sink, NULL);
       
   804 
       
   805   /* Set to PAUSED and wait for PREROLL */
       
   806   fail_if (gst_element_set_state (pipeline, GST_STATE_PAUSED) ==
       
   807       GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline to PAUSED");
       
   808   fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) !=
       
   809       GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline to PAUSED");
       
   810 
       
   811   caps1 = gst_pad_get_caps (ac3_src);
       
   812   fail_if (caps1 == NULL, "gst_pad_get_caps returned NULL");
       
   813   GST_DEBUG ("Caps size 1 : %d", gst_caps_get_size (caps1));
       
   814 
       
   815   fail_if (gst_element_set_state (pipeline, GST_STATE_READY) ==
       
   816       GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline back to READY");
       
   817   fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) !=
       
   818       GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline back to READY");
       
   819 
       
   820   /* test with 3 audioconvert elements */
       
   821   gst_element_unlink (ac1, ac3);
       
   822   gst_bin_add (GST_BIN (pipeline), ac2);
       
   823   gst_element_link_many (ac1, ac2, ac3, NULL);
       
   824 
       
   825   fail_if (gst_element_set_state (pipeline, GST_STATE_PAUSED) ==
       
   826       GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline back to PAUSED");
       
   827   fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) !=
       
   828       GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline back to PAUSED");
       
   829 
       
   830   caps2 = gst_pad_get_caps (ac3_src);
       
   831 
       
   832   fail_if (caps2 == NULL, "gst_pad_get_caps returned NULL");
       
   833   GST_DEBUG ("Caps size 2 : %d", gst_caps_get_size (caps2));
       
   834   fail_unless (gst_caps_get_size (caps1) == gst_caps_get_size (caps2));
       
   835 
       
   836   gst_caps_unref (caps1);
       
   837   gst_caps_unref (caps2);
       
   838 
       
   839   fail_if (gst_element_set_state (pipeline, GST_STATE_NULL) ==
       
   840       GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline back to NULL");
       
   841   fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) !=
       
   842       GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline back to NULL");
       
   843 
       
   844   gst_object_unref (ac3_src);
       
   845   gst_object_unref (pipeline);
       
   846 }
       
   847 
       
   848 GST_END_TEST;
       
   849 
       
   850 
       
   851 static Suite *
       
   852 audioconvert_suite (void)
       
   853 {
       
   854   Suite *s = suite_create ("audioconvert");
       
   855   TCase *tc_chain = tcase_create ("general");
       
   856 
       
   857   suite_add_tcase (s, tc_chain);
       
   858   tcase_add_test (tc_chain, test_int16);
       
   859   tcase_add_test (tc_chain, test_float32);
       
   860   tcase_add_test (tc_chain, test_int_conversion);
       
   861   tcase_add_test (tc_chain, test_float_conversion);
       
   862   tcase_add_test (tc_chain, test_multichannel_conversion);
       
   863   tcase_add_test (tc_chain, test_channel_remapping);
       
   864   tcase_add_test (tc_chain, test_caps_negotiation);
       
   865 
       
   866   return s;
       
   867 }
       
   868 
       
   869 int
       
   870 main (int argc, char **argv)
       
   871 {
       
   872   int nf;
       
   873 
       
   874   Suite *s = audioconvert_suite ();
       
   875   SRunner *sr = srunner_create (s);
       
   876 
       
   877   gst_check_init (&argc, &argv);
       
   878 
       
   879   srunner_run_all (sr, CK_NORMAL);
       
   880   nf = srunner_ntests_failed (sr);
       
   881   srunner_free (sr);
       
   882 
       
   883   return nf;
       
   884 }