[Bug 768836] New: audioresample crash when sample rate changes within a buffer gap

GStreamer (GNOME Bugzilla) bugzilla at gnome.org
Fri Jul 15 08:54:56 UTC 2016


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

            Bug ID: 768836
           Summary: audioresample crash when sample rate changes within a
                    buffer gap
    Classification: Platform
           Product: GStreamer
           Version: 1.8.2
                OS: Linux
            Status: NEW
          Severity: critical
          Priority: Normal
         Component: gst-plugins-base
          Assignee: gstreamer-bugs at lists.freedesktop.org
          Reporter: Scholz.Maik at t-online.de
        QA Contact: gstreamer-bugs at lists.freedesktop.org
     GNOME version: ---

Hi,
In my application, I need to change the audio samplerate dynamical during
runtime.

My code crashes with "audioresample assertion failed: (out_len >=
out_processed)", when I change the sink pad sample rate while a GAP is active.


related GStreamer-devel discussion:
===================================
http://gstreamer-devel.966125.n4.nabble.com/audioresample-assertion-failed-out-len-gt-out-processed-td4678533.html

Comment from S. Dröge:
I didn't look closely at your code (or the crash), but I can confirm
that it crashes like that with 1.8 but it doesn't seem to crash at all
here with 1.9.1. It is also using a completely new resampler, so that's
not too surprising. 

Test Results:
=============
  with 1.4.5:
    rate change not audible, no crash, but GStreamer-CRITICAL **:
gst_buffer_resize_range: assertion 'bufmax >= bufoffs + offset + size' failed

  with 1.6.4:
    rate change not audible, no crash, but GStreamer-CRITICAL **:
gst_buffer_resize_range: assertion 'bufmax >= bufoffs + offset + size' failed

  with 1.8.1 & 1.8.2:
  ./test 
  src=120ms sink=120ms set audioresample input rate to 47950
  src=1200ms sink=1200ms set audioresample input rate to 48050
  src=2279ms sink=2280ms set audioresample input rate to 47950
  src=3360ms sink=3360ms set audioresample input rate to 48050
  src=4439ms sink=4440ms set audioresample input rate to 47950
  ERROR:gstaudioresample.c:1125:gst_audio_resample_process: assertion failed:
(out_len >= out_processed)

  with 1.9.1:
    no crash but "WARN audio-resampler
audio-resampler.c:362:convert_taps_gint16_c: can't find exact taps" on each
rate change

test.c Compiled with:
=====================
gcc -o test `pkg-config --cflags --libs gstreamer-base-1.0 gstreamer-audio-1.0
gstreamer-1.0 gstreamer-app-1.0 gstreamer-plugins-good-1.0 gstreamer-audio-1.0`
test.c -lm `pkg-config --libs gstreamer-base-1.0 gstreamer-audio-1.0
gstreamer-1.0 gstreamer-app-1.0 gstreamer-plugins-good-1.0 gstreamer-audio-1.0`

test.c:
=======
#include <stdio.h>
#include <math.h>

#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/gstcaps.h>

#define TESTCAPS
"audio/x-raw,format=S16LE,channels=2,rate=48000,layout=interleaved"

GstPad* eB3_sink_pad;
GstClockTime eB3_sink_time = 0;

GstPad* eB3_src_pad;
GstClockTime eB3_src_time = 0;
GstClockTime eB3_next_src_time = 0;

typedef struct
{
    GstElement* e;
    guint       frequency;
    guint       samplerate;
    guint       period;
    GstClockTime src_timestamp;
    gboolean    gap;
} AudioSrcDataType;

gboolean appsrc_feed_function (void* me);

GstPadProbeReturn audioresample_pad_probe (GstPad          *pad,
                                           GstPadProbeInfo *info,
                                           gpointer         user_data);
/* Main */
int main(void)
{
    gst_init(NULL, NULL);
    GstElement* p = gst_pipeline_new("pipeline");

    AudioSrcDataType live_audio_B = {NULL,300,48000,120,0,TRUE};
    live_audio_B.e = gst_element_factory_make("appsrc",NULL);
   
gst_app_src_set_caps(GST_APP_SRC(live_audio_B.e),gst_caps_from_string(TESTCAPS));
    gst_base_src_set_live(GST_BASE_SRC(live_audio_B.e),TRUE);
    g_object_set (G_OBJECT(GST_APP_SRC(live_audio_B.e)), "format",
GST_FORMAT_TIME, NULL);
    g_object_set (G_OBJECT(GST_APP_SRC(live_audio_B.e)), "block", FALSE, NULL);
   
gst_app_src_set_stream_type(GST_APP_SRC(live_audio_B.e),GST_APP_STREAM_TYPE_STREAM);
   
gst_app_src_set_latency(GST_APP_SRC(live_audio_B.e),1*live_audio_B.period*GST_MSECOND,1*live_audio_B.period*GST_MSECOND);
    g_timeout_add (live_audio_B.period/2,appsrc_feed_function,&live_audio_B);

    GstElement* eB2 = gst_element_factory_make("audiorate",NULL);
    g_object_set(eB2, "tolerance", (120+10)*GST_MSECOND, NULL);

    GstElement* eB3 = gst_element_factory_make("audioresample",NULL);
    g_object_set(eB3, "quality", 4, NULL);
    g_object_set(eB3, "sinc-filter-mode", 2, NULL);

    GstElement* e_mixer = gst_element_factory_make("audiomixer",NULL);
    g_object_set(e_mixer, "latency", 512*GST_MSECOND, NULL);

    GstElement* e_sink = gst_element_factory_make("autoaudiosink",NULL);

    /* add ... */
    gst_bin_add_many(GST_BIN(p),live_audio_B.e,eB2,/*eB3,*/eB3,NULL);
    gst_bin_add_many(GST_BIN(p),e_mixer,e_sink,NULL);

    /* link ... */
    //gst_element_link_filtered(eA1, eA2, gst_caps_from_string(TESTCAPS));
    gst_element_link_many(live_audio_B.e, eB2, eB3, NULL);

    gst_pad_link (gst_element_get_static_pad (eB3,"src"),
                  gst_element_request_pad
(e_mixer,gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(e_mixer),"sink_%u"),
                                           NULL, NULL));
    gst_element_link_many(e_mixer, e_sink, NULL);

#if 1 /* Enable audioresample control loop, if disabled, the error does not
ocure  */
    {
        eB3_sink_pad = gst_element_get_static_pad (eB3, "sink");
        gst_pad_add_probe
(eB3_sink_pad,GST_PAD_PROBE_TYPE_BUFFER,(GstPadProbeCallback)
audioresample_pad_probe,NULL,NULL);

        eB3_src_pad = gst_element_get_static_pad (eB3, "src");
        gst_pad_add_probe
(eB3_src_pad,GST_PAD_PROBE_TYPE_BUFFER,(GstPadProbeCallback)
audioresample_pad_probe,NULL,NULL);
    }
#endif

    /* run ... */
    {
        static GMainLoop *loop;
        loop = g_main_loop_new(NULL, FALSE);
        gst_element_set_state(GST_ELEMENT(p), GST_STATE_PLAYING);
        g_main_loop_run(loop);
    }
    return 0;
}

/* timer based appsrc feed function.
 * 5 seconds sine + 5 seconds gap
 */
gboolean appsrc_feed_function (void* _me)
{
    AudioSrcDataType* me = (AudioSrcDataType*)_me;
    if( GST_BASE_SRC_IS_STARTED(me->e) )
    {
        GstClockTime t_now;
        while( ( t_now =
gst_clock_get_time(gst_element_get_clock(GST_ELEMENT(me->e)))-gst_element_get_base_time(GST_ELEMENT(me->e)))
> me->src_timestamp )
        {
            GstMapInfo buffer_info; guint i;
            guint buffer_size =
2*sizeof(gint16)*me->samplerate*me->period/1000;
            GstBuffer* buffer = gst_buffer_new_and_alloc(buffer_size);
            if( gst_buffer_map(buffer,&buffer_info,GST_MAP_WRITE) )
            {
                gst_buffer_ref(buffer);
                for(i=0;i<(buffer_size/sizeof(gint16));)
                {
                    static glong t=0;
                    gint16 v =
(gint16)(1000.0*sin(me->frequency*(t++)*2*3.14/me->samplerate));
                    ((gint16*)(buffer_info.data))[i++] = v;
                    ((gint16*)(buffer_info.data))[i++] = v;
                }
                GST_BUFFER_PTS(buffer) = t_now;
                GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
                //GST_BUFFER_DURATION (buffer) = me->period * GST_MSECOND;
                me->src_timestamp += me->period*GST_MSECOND;
                gst_buffer_unmap(buffer,&buffer_info);
            }

            if( (GST_TIME_AS_SECONDS(t_now)%20 ) < 10 )
            {
                /* 5 seconds push audio to pipeline */
                if(me->gap)
                {
                    me->gap = FALSE;
                    GST_BUFFER_FLAG_SET(buffer,GST_BUFFER_FLAG_RESYNC);
                }
                if( gst_app_src_push_buffer(GST_APP_SRC(me->e),buffer) !=
GST_FLOW_OK )
                {
                    gst_buffer_unref (buffer);
                }
            }
            else
            {
                /* 5 seconds GAP */
                gst_buffer_unref (buffer);

                if(!me->gap)
                {
                    me->gap = TRUE;
                }
               
gst_pad_push_event(GST_BASE_SRC_PAD(me->e),gst_event_new_gap(t_now,GST_CLOCK_TIME_NONE));
            }
        }
    }
    return TRUE;
}

/* audioresample PAD prob
 */
GstPadProbeReturn audioresample_pad_probe (GstPad          *pad,
                                           GstPadProbeInfo *info,
                                           gpointer         user_data)
{
    (void)user_data;
    if(((info->type&GST_PAD_PROBE_TYPE_BUFFER)!=0)&&(info->data != NULL))
    {
        if( pad == eB3_sink_pad )
        {
            eB3_sink_time = GST_BUFFER_TIMESTAMP(GST_BUFFER(info->data));
        }
        else if( pad == eB3_src_pad )
        {
            eB3_src_time = GST_BUFFER_TIMESTAMP(GST_BUFFER(info->data));
            if(( eB3_next_src_time < eB3_src_time
)&&(GST_PAD_STREAM_TRYLOCK(eB3_sink_pad)))
            {
                gint rate;
                GstCaps* caps = gst_pad_get_current_caps(eB3_sink_pad);
                GstStructure* structure;
                caps = gst_caps_make_writable(caps);
                structure = gst_caps_get_structure(caps,0);
                if (gst_structure_get_int (structure, "rate", &rate) )
                {
                    if( eB3_src_time > eB3_sink_time ) {
                        rate = 48000 + 8;
                    } else {
                        rate = 48000 - 8;
                    }
                    printf("src=%dms sink=%dms set audioresample input rate to
%d\n",
                           (gint)GST_TIME_AS_MSECONDS(eB3_src_time),
                           (gint)GST_TIME_AS_MSECONDS(eB3_sink_time),
                           rate);
                    gst_caps_set_simple(caps,"rate",G_TYPE_INT,rate,NULL);
                    gst_pad_set_caps(eB3_sink_pad,caps);
                    gst_pad_send_event (eB3_sink_pad, gst_event_new_caps
(caps));
                }
                eB3_next_src_time = eB3_src_time + 1000 * GST_MSECOND; /* next
adjustment in 5 seconds */
                GST_PAD_STREAM_UNLOCK(eB3_sink_pad);
            }
        }
    }
    return GST_PAD_PROBE_OK;
}

-- 
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