[Bug 768836] audioresample crash when sample rate changes within a buffer gap (<= 1.8 only)

GStreamer (GNOME Bugzilla) bugzilla at gnome.org
Fri Aug 12 13:48:39 UTC 2016


https://bugzilla.gnome.org/show_bug.cgi?id=768836

--- Comment #5 from Maik Scholz <Scholz.Maik at t-online.de> ---
Hi,

I did some analysis by myself.
For me (gstreamer beginner), it looks like, when the rate ratio is changed 
during a gap buffer timespan. Then the out_processed calculation results into
a wrong value.
Limiting the out_processed to out_len, avoids the assert.
      if( out_processed > out_len ) {
       /* take care that out_processed is not greater then out_len */
      out_processed = out_len;
    }

But I am not sure about the side effects?

With that change, the above testcase works fine.
I will do some tests within out application.

Maik

gstaudioresample.c:
===================
static GstFlowReturn
gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
    GstBuffer * outbuf)
{
  GstMapInfo in_map, out_map;
  gsize outsize;
  guint32 in_len, in_processed;
  guint32 out_len, out_processed;
  guint filt_len = resample->funcs->get_filt_len (resample->state);

  gst_buffer_map (inbuf, &in_map, GST_MAP_READ);
  gst_buffer_map (outbuf, &out_map, GST_MAP_WRITE);

  in_len = in_map.size / resample->channels;
  out_len = out_map.size / resample->channels;

  in_len /= (resample->width / 8);
  out_len /= (resample->width / 8);

  in_processed = in_len;
  out_processed = out_len;

  if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
    resample->num_nongap_samples = 0;
    if (resample->num_gap_samples < filt_len) {
      guint zeros_to_push;
      if (in_len >= filt_len - resample->num_gap_samples)
        zeros_to_push = filt_len - resample->num_gap_samples;
      else
        zeros_to_push = in_len;

      gst_audio_resample_push_drain (resample, zeros_to_push);
      in_len -= zeros_to_push;
      resample->num_gap_samples += zeros_to_push;
    }

    {
      guint num, den;
      resample->funcs->get_ratio (resample->state, &num, &den);
      if (resample->samples_in + in_len >= filt_len / 2)
        out_processed =
            gst_util_uint64_scale_int_ceil (resample->samples_in + in_len -
            filt_len / 2, den, num) - resample->samples_out;
      else
        out_processed = 0;

=> POSSIBLE BUGFIX
      if( out_processed > out_len ) {
       /* take care that out_processed is not greater then out_len */
      out_processed = out_len;
    }
<= POSSIBLE BUGFIX

      memset (out_map.data, 0, out_map.size);
      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
      resample->num_gap_samples += in_len;
      in_processed = in_len;
    }
  } else {                      /* not a gap */

    gint err;

    if (resample->num_gap_samples > filt_len) {
      /* push in enough zeros to restore the filter to the right offset */
      guint num, den;
      resample->funcs->get_ratio (resample->state, &num, &den);
      gst_audio_resample_dump_drain (resample,
          (resample->num_gap_samples - filt_len) % num);
    }
    resample->num_gap_samples = 0;
    if (resample->num_nongap_samples < filt_len) {
      resample->num_nongap_samples += in_len;
      if (resample->num_nongap_samples > filt_len)
        resample->num_nongap_samples = filt_len;
    }

    if (resample->funcs->width != resample->width) {
      /* need to convert data format for processing;  ensure we have enough
       * workspace available */
      if (!gst_audio_resample_workspace_realloc (&resample->tmp_in,
              &resample->tmp_in_size, in_len * resample->channels *
              (resample->funcs->width / 8)) ||
          !gst_audio_resample_workspace_realloc (&resample->tmp_out,
              &resample->tmp_out_size, out_len * resample->channels *
              (resample->funcs->width / 8))) {
        GST_ERROR_OBJECT (resample, "failed to allocate workspace");
        gst_buffer_unmap (inbuf, &in_map);
        gst_buffer_unmap (outbuf, &out_map);
        return GST_FLOW_ERROR;
      }

      /* convert input */
      gst_audio_resample_convert_buffer (resample, in_map.data,
          resample->tmp_in, in_len, FALSE);

      /* process */
      err = resample->funcs->process (resample->state,
          resample->tmp_in, &in_processed, resample->tmp_out, &out_processed);

      /* convert output */
      gst_audio_resample_convert_buffer (resample, resample->tmp_out,
          out_map.data, out_processed, TRUE);
    } else {
      /* no format conversion required;  process */
      err = resample->funcs->process (resample->state,
          in_map.data, &in_processed, out_map.data, &out_processed);
    }

    if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
      GST_ERROR_OBJECT (resample, "Failed to convert data: %s",
          resample->funcs->strerror (err));
      gst_buffer_unmap (inbuf, &in_map);
      gst_buffer_unmap (outbuf, &out_map);
      return GST_FLOW_ERROR;
    }
  }

  /* If we wrote more than allocated something is really wrong now and we
   * should better abort immediately */
  g_assert (out_len >= out_processed);

-- 
You are receiving this mail because:
You are the QA Contact for the bug.
You are the assignee for the bug.


More information about the gstreamer-bugs mailing list