mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 14:56:36 +00:00
audioconvert: Prefer output formats with the same depth or at least a higher depth
Enhance current code to prefer an exact match on sample depth if possible. Also ignore GST_AUDIO_FORMAT_FLAG_UNPACK when checking equality on the flags.
This commit is contained in:
parent
5f44303925
commit
c286f8ffa2
2 changed files with 84 additions and 8 deletions
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue