diff --git a/gst/audioconvert/gstaudioconvert.c b/gst/audioconvert/gstaudioconvert.c index e7a1f1da15..67ee3173eb 100644 --- a/gst/audioconvert/gstaudioconvert.c +++ b/gst/audioconvert/gstaudioconvert.c @@ -442,6 +442,7 @@ gst_audio_convert_fixate_format (GstBaseTransform * base, GstStructure * ins, const gchar *in_format; const GValue *format; const GstAudioFormatInfo *in_info, *out_info = NULL; + GstAudioFormatFlags in_flags, out_flags; in_format = gst_structure_get_string (ins, "format"); if (!in_format) @@ -457,6 +458,9 @@ gst_audio_convert_fixate_format (GstBaseTransform * base, GstStructure * ins, if (!in_info) return; + in_flags = GST_AUDIO_FORMAT_INFO_FLAGS (in_info); + in_flags &= ~(GST_AUDIO_FORMAT_FLAG_UNPACK); + if (GST_VALUE_HOLDS_LIST (format)) { gint i, len; @@ -467,22 +471,32 @@ gst_audio_convert_fixate_format (GstBaseTransform * base, GstStructure * ins, val = gst_value_list_get_value (format, i); if (G_VALUE_HOLDS_STRING (val)) { + const GstAudioFormatInfo *t_info; fname = g_value_get_string (val); - out_info = + t_info = gst_audio_format_get_info (gst_audio_format_from_string (fname)); - if (!out_info) + if (!t_info) continue; /* accept input format */ if (strcmp (fname, in_format) == 0) break; + out_flags = GST_AUDIO_FORMAT_INFO_FLAGS (t_info); + out_flags &= ~(GST_AUDIO_FORMAT_FLAG_UNPACK); /* or another format without losing precision */ - if ((GST_AUDIO_FORMAT_INFO_FLAGS (out_info) == - GST_AUDIO_FORMAT_INFO_FLAGS (in_info)) && - (GST_AUDIO_FORMAT_INFO_DEPTH (out_info) >= - GST_AUDIO_FORMAT_INFO_DEPTH (in_info))) - break; + if (in_flags == out_flags) { + if (GST_AUDIO_FORMAT_INFO_DEPTH (t_info) == + GST_AUDIO_FORMAT_INFO_DEPTH (in_info)) { + /* exact match. We are done */ + out_info = t_info; + break; + } else if ((GST_AUDIO_FORMAT_INFO_DEPTH (t_info) >= + GST_AUDIO_FORMAT_INFO_DEPTH (in_info))) { + /* match where we do not lose precision. This could + be ok, but keep searching for an exact match */ + out_info = t_info; + } + } } - out_info = NULL; } if (out_info) gst_structure_set (outs, "format", G_TYPE_STRING, diff --git a/tests/check/elements/audioconvert.c b/tests/check/elements/audioconvert.c index 4e28c0d6e9..47ffb0b278 100644 --- a/tests/check/elements/audioconvert.c +++ b/tests/check/elements/audioconvert.c @@ -1441,6 +1441,67 @@ GST_START_TEST (test_convert_undefined_multichannel) GST_END_TEST; +#define SIMPLE_CAPS_TEMPLATE_STRING \ + "audio/x-raw, " \ + "format = (string) {S8, S16LE, S24LE, S32LE}, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ]" + +static GstStaticPadTemplate simple_sinktemplate = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (SIMPLE_CAPS_TEMPLATE_STRING) + ); + +GST_START_TEST (test_preserve_width) +{ + static const struct _test_formats + { + int width; + const gchar *outf; + } test_formats[] = { { + 8, "S8"}, { + 16, "S16LE"}, { + 24, "S24LE"}, { + 32, "S32LE"}, { + 0, NULL}}; + + gint i; + GstStructure *structure; + GstElement *audioconvert; + GstCaps *incaps, *convert_outcaps; + + audioconvert = gst_check_setup_element ("audioconvert"); + mysrcpad = gst_check_setup_src_pad (audioconvert, &srctemplate); + mysinkpad = gst_check_setup_sink_pad (audioconvert, &simple_sinktemplate); + + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + fail_unless (gst_element_set_state (audioconvert, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + for (i = 0; test_formats[i].width; i++) { + gint width = test_formats[i].width; + incaps = get_int_caps (1, G_BIG_ENDIAN, width, width, TRUE); + gst_pad_set_caps (mysrcpad, incaps); + + convert_outcaps = gst_pad_get_current_caps (mysinkpad); + structure = gst_caps_get_structure (convert_outcaps, 0); + fail_unless_equals_string (gst_structure_get_string (structure, "format"), + test_formats[i].outf); + + gst_caps_unref (convert_outcaps); + gst_caps_unref (incaps); + } + + cleanup_audioconvert (audioconvert); +} + +GST_END_TEST; + static Suite * audioconvert_suite (void) { @@ -1455,6 +1516,7 @@ audioconvert_suite (void) tcase_add_test (tc_chain, test_multichannel_conversion); tcase_add_test (tc_chain, test_caps_negotiation); tcase_add_test (tc_chain, test_convert_undefined_multichannel); + tcase_add_test (tc_chain, test_preserve_width); return s; }