audioconvert: If we have to lose precision, try to lose as less precision as possible

https://bugzilla.gnome.org/show_bug.cgi?id=706624
This commit is contained in:
Sebastian Dröge 2013-08-23 18:51:59 +02:00
parent f9ebfd57f8
commit cebae4514a

View file

@ -442,7 +442,7 @@ gst_audio_convert_fixate_format (GstBaseTransform * base, GstStructure * ins,
const gchar *in_format; const gchar *in_format;
const GValue *format; const GValue *format;
const GstAudioFormatInfo *in_info, *out_info = NULL; const GstAudioFormatInfo *in_info, *out_info = NULL;
GstAudioFormatFlags in_flags, out_flags; GstAudioFormatFlags in_flags, out_flags = 0;
in_format = gst_structure_get_string (ins, "format"); in_format = gst_structure_get_string (ins, "format");
if (!in_format) if (!in_format)
@ -473,6 +473,8 @@ gst_audio_convert_fixate_format (GstBaseTransform * base, GstStructure * ins,
val = gst_value_list_get_value (format, i); val = gst_value_list_get_value (format, i);
if (G_VALUE_HOLDS_STRING (val)) { if (G_VALUE_HOLDS_STRING (val)) {
const GstAudioFormatInfo *t_info; const GstAudioFormatInfo *t_info;
GstAudioFormatFlags t_flags;
fname = g_value_get_string (val); fname = g_value_get_string (val);
t_info = t_info =
gst_audio_format_get_info (gst_audio_format_from_string (fname)); gst_audio_format_get_info (gst_audio_format_from_string (fname));
@ -484,33 +486,43 @@ gst_audio_convert_fixate_format (GstBaseTransform * base, GstStructure * ins,
break; break;
} }
out_flags = GST_AUDIO_FORMAT_INFO_FLAGS (t_info); t_flags = GST_AUDIO_FORMAT_INFO_FLAGS (t_info);
out_flags &= ~(GST_AUDIO_FORMAT_FLAG_UNPACK); t_flags &= ~(GST_AUDIO_FORMAT_FLAG_UNPACK);
out_flags &= ~(GST_AUDIO_FORMAT_FLAG_SIGNED); t_flags &= ~(GST_AUDIO_FORMAT_FLAG_SIGNED);
/* or another format without losing precision */
if (in_flags == out_flags) { if (GST_AUDIO_FORMAT_INFO_DEPTH (t_info) ==
if (GST_AUDIO_FORMAT_INFO_DEPTH (t_info) == GST_AUDIO_FORMAT_INFO_DEPTH (in_info) && (!out_info
GST_AUDIO_FORMAT_INFO_DEPTH (in_info) && || GST_AUDIO_FORMAT_INFO_DEPTH (out_info) !=
(!out_info GST_AUDIO_FORMAT_INFO_DEPTH (in_info)
|| GST_AUDIO_FORMAT_INFO_DEPTH (out_info) >= || (t_flags == in_flags && out_flags != in_flags))) {
GST_AUDIO_FORMAT_INFO_DEPTH (in_info))) { /* Prefer to use the first format that has the same depth with the same
/* exact match of depth, we still continue * flags, and if none with the same flags exist use the first other one
* to iterate to see if we can get exactly * that has the same depth */
* the same format. out_info = t_info;
* Only go here if we don't have another out_flags = t_flags;
* format with the same depth already. We } else if (GST_AUDIO_FORMAT_INFO_DEPTH (t_info) >=
* always take the first to prefer caps GST_AUDIO_FORMAT_INFO_DEPTH (in_info) && (!out_info
* order. */ || GST_AUDIO_FORMAT_INFO_DEPTH (in_info) >
out_info = t_info; GST_AUDIO_FORMAT_INFO_DEPTH (out_info)
} else if ((GST_AUDIO_FORMAT_INFO_DEPTH (t_info) >= || (GST_AUDIO_FORMAT_INFO_DEPTH (out_info) >=
GST_AUDIO_FORMAT_INFO_DEPTH (in_info)) && !out_info) { GST_AUDIO_FORMAT_INFO_DEPTH (in_info) && t_flags == in_flags
/* match where we do not lose precision. This could && out_flags != in_flags))) {
* be ok, but keep searching for an exact match. /* Otherwise use the first format that has a higher depth with the same flags,
* Only go here if we don't have another format with * if none with the same flags exist use the first other one that has a higher
* a bigger/equal depth already. We always take the * depth */
* first to prefer caps order. */ out_info = t_info;
out_info = t_info; out_flags = t_flags;
} } else if (!out_info
|| (GST_AUDIO_FORMAT_INFO_DEPTH (t_info) >
GST_AUDIO_FORMAT_INFO_DEPTH (out_info)
&& GST_AUDIO_FORMAT_INFO_DEPTH (out_info) <
GST_AUDIO_FORMAT_INFO_DEPTH (in_info)) || (t_flags == in_flags
&& out_flags != in_flags
&& GST_AUDIO_FORMAT_INFO_DEPTH (out_info) ==
GST_AUDIO_FORMAT_INFO_DEPTH (t_info))) {
/* Else get at least the one with the highest depth, ideally with the same flags */
out_info = t_info;
out_flags = t_flags;
} }
} }
} }