audio-converter: Avoid conversion when possible
authorWim Taymans <wtaymans@redhat.com>
Tue, 12 Jan 2016 14:27:16 +0000 (15:27 +0100)
committerWim Taymans <wtaymans@redhat.com>
Tue, 12 Jan 2016 14:27:16 +0000 (15:27 +0100)
When the input and output formats are the same and in a possible
intermediate format, avoid unpack and pack.
Never do passthrough channel mixing.
Only do dithering and noise shaping in S32 format

gst-libs/gst/audio/audio-converter.c

index e8f5846..e513e22 100644 (file)
@@ -407,15 +407,17 @@ do_unpack (AudioChain * chain, gpointer user_data)
   if (!chain->allow_ip || !in_writable || !convert->in_default) {
     gint i;
 
-    if (in_writable && chain->allow_ip)
+    if (in_writable && chain->allow_ip) {
       tmp = convert->in_data;
-    else
+      GST_LOG ("unpack in-place %p, %" G_GSIZE_FORMAT, tmp, num_samples);
+    } else {
       tmp = audio_chain_alloc_samples (chain, num_samples);
-
-    GST_LOG ("unpack %p, %p, %" G_GSIZE_FORMAT, tmp, convert->in_data,
-        num_samples);
+      GST_LOG ("unpack to tmp %p, %" G_GSIZE_FORMAT, tmp, num_samples);
+    }
 
     for (i = 0; i < chain->blocks; i++) {
+      GST_LOG ("unpack %p, %p, %" G_GSIZE_FORMAT, tmp[i], convert->in_data[i],
+          num_samples);
       convert->in.finfo->unpack_func (convert->in.finfo,
           GST_AUDIO_PACK_FLAG_TRUNCATE_RANGE, tmp[i], convert->in_data[i],
           num_samples * chain->inc);
@@ -505,23 +507,42 @@ do_quantize (AudioChain * chain, gpointer user_data)
   return TRUE;
 }
 
+static gboolean
+is_intermediate_format (GstAudioFormat format)
+{
+  return (format == GST_AUDIO_FORMAT_S16 ||
+      format == GST_AUDIO_FORMAT_S32 ||
+      format == GST_AUDIO_FORMAT_F32 || format == GST_AUDIO_FORMAT_F64);
+}
+
 static AudioChain *
 chain_unpack (GstAudioConverter * convert)
 {
   AudioChain *prev;
   GstAudioInfo *in = &convert->in;
+  GstAudioInfo *out = &convert->out;
   const GstAudioFormatInfo *fup;
+  gboolean same_format;
 
-  convert->current_format = in->finfo->unpack_format;
+  same_format = in->finfo->format == out->finfo->format;
+
+  /* do not unpack if we have the same input format as the output format
+   * and it is a possible intermediate format */
+  if (same_format && is_intermediate_format (in->finfo->format)) {
+    convert->current_format = in->finfo->format;
+  } else {
+    convert->current_format = in->finfo->unpack_format;
+  }
   convert->current_layout = in->layout;
   convert->current_channels = in->channels;
-  convert->in_default = in->finfo->unpack_format == in->finfo->format;
+
+  convert->in_default = convert->current_format == in->finfo->format;
 
   GST_INFO ("unpack format %s to %s",
       gst_audio_format_to_string (in->finfo->format),
       gst_audio_format_to_string (convert->current_format));
 
-  fup = gst_audio_format_get_info (in->finfo->unpack_format);
+  fup = gst_audio_format_get_info (convert->current_format);
 
   prev = convert->unpack_chain = audio_chain_new (NULL, convert);
   prev->allow_ip = fup->width <= in->finfo->width;
@@ -582,10 +603,8 @@ chain_mix (GstAudioConverter * convert, AudioChain * prev)
 
   if (!convert->mix_passthrough) {
     prev = convert->mix_chain = audio_chain_new (prev, convert);
-    /* we can only do in-place when in >= out, else we don't have enough
-     * memory. */
-    prev->allow_ip = in->channels >= out->channels;
-    prev->pass_alloc = in->channels <= out->channels;
+    prev->allow_ip = FALSE;
+    prev->pass_alloc = FALSE;
     audio_chain_set_make_func (prev, do_mix, convert, NULL);
   }
   return prev;
@@ -651,7 +670,8 @@ chain_quantize (GstAudioConverter * convert, AudioChain * prev)
   }
   /* we still want to run the quantization step when reducing bits to get
    * the rounding correct */
-  if (out_int && out_depth < 32) {
+  if (out_int && out_depth < 32
+      && convert->current_format == GST_AUDIO_FORMAT_S32) {
     GST_INFO ("quantize to %d bits, dither %d, ns %d", out_depth, dither, ns);
     convert->quant =
         gst_audio_quantize_new (dither, ns, 0, convert->current_format,
@@ -673,7 +693,6 @@ chain_pack (GstAudioConverter * convert, AudioChain * prev)
 
   convert->current_format = out->finfo->format;
 
-  g_assert (out->finfo->unpack_format == format);
   convert->out_default = format == out->finfo->format;
   GST_INFO ("pack format %s to %s", gst_audio_format_to_string (format),
       gst_audio_format_to_string (out->finfo->format));
@@ -933,7 +952,7 @@ gst_audio_converter_samples (GstAudioConverter * convert,
     return TRUE;
   }
 
-  GST_LOG ("converting %" G_GSIZE_FORMAT, in_samples);
+  GST_LOG ("converting %p %p %" G_GSIZE_FORMAT, in, out, in_samples);
 
   convert->in_writable = flags & GST_AUDIO_CONVERTER_FLAG_IN_WRITABLE;
   convert->in_data = in;