audioresample assertion failed: (out_len >= out_processed)
Maik Scholz
Scholz.Maik at t-online.de
Mon Jul 11 12:23:03 UTC 2016
Hi Sebastian,
>Please try to create a (as simple as possible) testcase for reproducing
this problem.
the attached code shows the same problem compiled with gstreamer 1.8.1.
It implements a pipeline with a test noise source, a switched (5 seconds on
+ 5 seconds off) appsrc sine noise,
combined with a audiomixer.
If i run that code, then i see the exception after 10 seconds.
If I disable the "#if 1", the the code runs without exception.
My current understanding is, that the "(out_len >= out_processed)" exception
happens
when i change the caps/samplerate within a gap.
Maik
#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 (AudioSrcDataType* 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");
GstElement* eA1 = gst_element_factory_make("audiotestsrc",NULL);
g_object_set(eA1, "volume", 0.01, NULL);
g_object_set(eA1, "wave", 5, NULL);
g_object_set(eA1, "samplesperbuffer", 48000*32/1000, NULL);
GstElement* eA2 = gst_element_factory_make("audioconvert",NULL);
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),eA1,eA2,NULL);
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 (eA2,"src"),
gst_element_request_pad
(e_mixer,gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(e_mixer),"sink_%u"),
NULL, 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 (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)%10 ) < 5 )
{
/* 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 + 50;
} else {
rate = 48000 - 50;
}
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;
}
--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/audioresample-assertion-failed-out-len-out-processed-tp4678533p4678595.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
More information about the gstreamer-devel
mailing list