<div dir="ltr">Here is a little update: I haven't found the problem yet :)<div>To summaries the issue: I'm trying to migrate from ffmpeg 1.2 to the latest build. With version 1.2 everything is working. I am decoding and filtering several streams, each stream is processed in it's own thread, a frame is taken and decoded, inserted in a filtergraph for filtering, pulled out the filtered frame and inserted into a local buffer. This process loops as long as the input stream is valid. The issue is, with the new API I have av_buffersink_get_frame() that I'd like to use to get the filtered frame out of buffersink. At the first run of this decode-filter loop, everything works fine, but at the second pass (i.e. for the second frame) it crashes - most of the time is segfault, sometimes I get a glibc message detecting a corrupted double linked list. Gdb points me inside of av_buffersink_get_frame() where some pointers are zero when trying to read a fifo buffer.</div>
<div><br></div><div style>The strangest thing is that under valgrind everything works fine. Tested several times, under valgrind it just works. </div><div style><br></div><div style>What am I missing here? Why is it working under valgrind and crashes during normal running? I really need help with this one!!</div>
<div style>Thank you guys, for any suggestions and help!</div><div style>Best,</div><div style>Radu</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, May 3, 2013 at 5:38 PM, Radu Robotin <span dir="ltr"><<a href="mailto:radu.robotin@gmail.com" target="_blank">radu.robotin@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Here is the some parts of the code that's causing trouble: the ffmpegFetchDecodeResampleNext() is called for fetching a frame form a stream, decoding and then filtering and putting the filtered frame in an internal buffer - then the process repeats. Before any call to ffmpegFetchDecodeResampleNext, the codec and the context for decoding are initialized, as well as the filtergraph.</div>
<div><br></div><div>The first call to ffmpegFetchDecodeResampleNext() works as expected,. the second one fails (with coredump) when trying to get the filtered frame from the filtergraph.</div><div><br></div>
<div>What has changed in the way filterghraph is handled? I had no issues working with version 1.2. Can you please help me and tell me what I'm doing wrong?</div><div><br></div><div><br></div><div>Thanks a lot!</div>
<div><br></div><div>refbuf_t * ffmpegFetchDecodeResampleNext(myFFmpegContext * ff, source_t *source){</div><div><span style="white-space:pre-wrap"> </span></div><div> refbuf_t * retRefBuff = NULL;<br></div><div><span style="white-space:pre-wrap"> </span>AVPacket pPacket;</div>
<div> AVFrame *frame = av_frame_alloc();</div><div> AVFrame *filt_frame = av_frame_alloc();</div><div> AVFrame *enc_frame = av_frame_alloc();</div><div> </div><div> if (!frame || !filt_frame || !enc_frame) {</div>
<div> ERROR0("Could not allocate frame(s)");</div><div> return NULL;</div><div> }</div><div> int ret;<br></div><div><span style="white-space:pre-wrap"> </span>int localbuffering = 1;<br>
</div>
<div><span style="white-space:pre-wrap"> </span>while(global.running == ICE_RUNNING && source->running && localbuffering)</div><div><span style="white-space:pre-wrap"> </span>{</div><div><span style="white-space:pre-wrap"> </span>ff->timeout = time(NULL);</div>
<div><span style="white-space:pre-wrap"> </span>ret= av_read_frame(ff->pInputFormatCtx, &pPacket);</div><div><span style="white-space:pre-wrap"> </span></div><div> if(ret == AVERROR(EAGAIN)){</div><div>
WARN1("av_read_frame error EAGAIN, error reading frame, continuing %s",ff->localMount);</div><div><span style="white-space:pre-wrap"> </span>av_free_packet(&pPacket);</div><div> continue;</div>
<div> }</div><div><span style="white-space:pre-wrap"> </span>if(ret == EOF){</div><div><span style="white-space:pre-wrap"> </span>source->running = 0;</div><div><span style="white-space:pre-wrap"> </span>ERROR1("av_read_frame error, EOF, exiting %s",ff->localMount);</div>
<div><span style="white-space:pre-wrap"> </span>av_free_packet(&pPacket);</div><div><span style="white-space:pre-wrap"> </span>break;</div><div><span style="white-space:pre-wrap"> </span>}</div><div> if (ret < 0) {</div>
<div><span style="white-space:pre-wrap"> </span>WARN1("av_read_frame error, error reading frame, breaking %s",ff->localMount);</div><div><span style="white-space:pre-wrap"> </span>av_free_packet(&pPacket);</div>
<div><span style="white-space:pre-wrap"> </span>ff->failedReads++;</div><div><span style="white-space:pre-wrap"> </span>if(ff->failedReads >= 10)</div><div><span style="white-space:pre-wrap"> </span>source->running = 0;</div>
<div> return NULL;</div><div> }</div><div><br></div><div><span style="white-space:pre-wrap"> </span>ff->failedReads = 0;</div><div><br></div><div><span style="white-space:pre-wrap"> </span>time_t current = time (NULL);</div>
<div><span style="white-space:pre-wrap"> </span>source->last_read = current;</div><div> <span style="white-space:pre-wrap"> </span>int got_frame = 0;<br></div><div><span style="white-space:pre-wrap"> </span>avcodec_get_frame_defaults(frame);</div>
<div><span style="white-space:pre-wrap"> </span>ret = avcodec_decode_audio4(ff->pInputCodecCtx, frame, &got_frame, &pPacket);</div><div> </div><div><span style="white-space:pre-wrap"> </span>if(ret < 0 ){</div>
<div><span style="white-space:pre-wrap"> </span>WARN1("avcodec_decode_audio3 unable to decode %s",ff->localMount);</div><div><span style="white-space:pre-wrap"> </span>ff->failedDecodes++;</div>
<div><span style="white-space:pre-wrap"> </span>if(ff->failedDecodes >= 500){</div><div><span style="white-space:pre-wrap"> </span>source->running = 0;</div><div><span style="white-space:pre-wrap"> </span>ERROR1("avcodec_decode_audio3 unable to decode %s error limit reached, closing stream",ff->localMount);</div>
<div><span style="white-space:pre-wrap"> </span>av_free_packet(&pPacket);</div><div> <span style="white-space:pre-wrap"> </span>return NULL;</div><div><span style="white-space:pre-wrap"> </span>}</div>
<div><span style="white-space:pre-wrap"> </span>}</div><div> <span style="white-space:pre-wrap"> </span> </div><div><span style="white-space:pre-wrap"> </span>else if(got_frame == 0){</div><div><span style="white-space:pre-wrap"> </span> <span style="white-space:pre-wrap"> </span>thread_sleep (delay*1000);</div>
<div><span style="white-space:pre-wrap"> </span>}</div><div> </div><div><span style="white-space:pre-wrap"> </span>else{ </div><div> </div><div><span style="white-space:pre-wrap"> </span>ff->failedDecodes = 0;</div>
<div><span style="white-space:pre-wrap"> </span>int resample_changed = ff->resample_sample_fmt != ff->pInputCodecCtx->sample_fmt || ff->resample_channels != ff->pInputCodecCtx->channels || ff->resample_sample_rate != ff->pInputCodecCtx->sample_rate;</div>
<div> if (resample_changed) {</div><div><span style="white-space:pre-wrap"> </span>if (resample_changed) {</div><div><span style="white-space:pre-wrap"> </span>ff->resample_sample_fmt = ff->pInputCodecCtx->sample_fmt;</div>
<div><span style="white-space:pre-wrap"> </span> <span style="white-space:pre-wrap"> </span>ff->resample_channels = ff->pInputCodecCtx->channels;</div><div><span style="white-space:pre-wrap"> </span> <span style="white-space:pre-wrap"> </span>ff->resample_sample_rate = ff->pInputCodecCtx->sample_rate;</div>
<div><span style="white-space:pre-wrap"> </span></div><div><span style="white-space:pre-wrap"> </span>}</div><div><span style="white-space:pre-wrap"> </span>/*RESAMPLING parameters */<br></div><div><span style="white-space:pre-wrap"> </span>INFO3("resampling context ch:%d spl:%d %s",ff->pInputCodecCtx->channels, ff->pInputCodecCtx->sample_rate, ff->localMount);</div>
<div><span style="white-space:pre-wrap"> </span>INFO2("volume for %s :%d",ff->localMount, ff->volume);</div><div><span style="white-space:pre-wrap"> </span>if ((ret = init_filters(ff,source)) < 0) {</div>
<div><span style="white-space:pre-wrap"> </span> <span style="white-space:pre-wrap"> </span>ERROR1( "Error while init_filters %s",ff->localMount);</div><div><span style="white-space:pre-wrap"> </span>av_free_packet(&pPacket);</div>
<div><span style="white-space:pre-wrap"> </span>source->running = 0;</div><div><span style="white-space:pre-wrap"> </span>return NULL;</div><div><span style="white-space:pre-wrap"> </span>}</div>
<div> </div><div> </div><div><span style="white-space:pre-wrap"> </span>}</div><div> </div><div> //feed the filter graph with the new frame</div><div><br></div>
<div> if (av_buffersrc_add_frame_flags(ff->buffersrc_ctx, frame,0) < 0) {</div><div><span style="white-space:pre-wrap"> </span>ERROR1( "Error while feeding the audio filtergraph %s",ff->localMount);</div>
<div> }</div><div> </div><div> /* pull filtered audio from the filtergraph */</div><div> while (1) {</div><div><span style="white-space:pre-wrap"> </span></div><div>
<span style="white-space:pre-wrap">// This is where the crash happens - initially it was something like:</span></div><div><span style="white-space:pre-wrap"> // AVFilterBufferRef *samplesref;
// ret = av_buffersink_get_buffer_ref(ff->buffersink_ctx, &samplesref, 0);</span></div><div><span style="white-space:pre-wrap"> //
</span> </div><div> </div><div> ret = av_buffersink_get_frame(ff->buffersink_ctx, filt_frame);</div><div><br></div><div>// At the second call of this function, we don't get to this point, as it crashes when trying to extract the frame from the filtergraph</div>
<div> </div><div> if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)</div><div><span style="white-space:pre-wrap"> </span>break;</div><div> if(ret < 0)</div><div>
<span style="white-space:pre-wrap"> </span>WARN1("error av_buffersink_get_frame, %s",ff->localMount);</div><div> if (ret>=0) {</div><div><span style="white-space:pre-wrap"> </span>//print_samplesref(samplesref);</div>
<div> char * resampleBuff = (char *)filt_frame->data[0];</div><div> size_out = filt_frame->nb_samples * av_get_channel_layout_nb_channels(av_frame_get_channel_layout(filt_frame));</div>
<div> </div><div> //process the frame and put it in a circular buffer to be returned at exit</div><div>................................................</div><div><br></div>
<div> av_frame_unref(filt_frame);</div><div> av_frame_unref(frame); </div><div> }</div><div> </div><div> }</div><div> av_frame_unref(filt_frame);</div>
<div> av_frame_unref(frame); </div><div><span style="white-space:pre-wrap"> </span>if(ret < 0) {</div><div><span style="white-space:pre-wrap"> </span>av_free_packet(&pPacket);</div><div>
<span style="white-space:pre-wrap"> </span>break;</div><div><span style="white-space:pre-wrap"> </span>}</div><div><span style="white-space:pre-wrap"> </span></div><div><span style="white-space:pre-wrap"> </span>}</div>
<div><span style="white-space:pre-wrap"> </span>av_free_packet(&pPacket);</div><div><span style="white-space:pre-wrap"> </span>}</div><div> av_frame_free(&filt_frame);</div><div> av_frame_free(&frame);</div>
<div> av_frame_free(&enc_frame);</div><div><span style="white-space:pre-wrap"> </span></div><div> return nextPreBuffer(source);</div><div>}</div><div><br></div><div><br></div><div>the decoder and the filtergraph are initialized prior calling this function. Here is a snippet with the function used for filter_init. It's pretty much standard as in the example file</div>
<div><br></div><div><br></div><div><div>static int init_filters(myFFmpegContext * ff, source_t *source)</div><div>{</div><div><span style="white-space:pre-wrap"> </span>AVFormatContext *fmt_ctx = ff->pInputFormatCtx;</div>
<div><span style="white-space:pre-wrap"> </span>AVCodecContext *dec_ctx = ff->pInputCodecCtx; </div><div><span style="white-space:pre-wrap"> </span>int audio_stream_index = ff->audioStreamIndex;</div><div><br>
</div><div> char args[512];</div><div> int ret;</div><div> char *pcTemp_string1, *pcTemp_string2;</div><div> char buffer[10];</div><div> </div><div> AVFilter *abuffersrc = avfilter_get_by_name("abuffer");</div>
<div> AVFilter *abuffersink = avfilter_get_by_name("abuffersink");</div><div> AVFilterInOut *outputs = avfilter_inout_alloc();</div><div> AVFilterInOut *inputs = avfilter_inout_alloc();</div><div> const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };</div>
<div> AVABufferSinkParams *abuffersink_params;</div><div> </div><div> </div><div> const AVFilterLink *outlink;</div><div> AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base;</div>
<div><br></div><div><span style="white-space:pre-wrap"> </span>if(ff->filter_graph)</div><div><span style="white-space:pre-wrap"> </span>avfilter_graph_free(&ff->filter_graph);</div><div><span style="white-space:pre-wrap"> </span>ff->filter_graph = avfilter_graph_alloc();</div>
<div><br></div><div> /* buffer audio source: the decoded frames from the decoder will be inserted here. */</div><div> if (!dec_ctx->channel_layout)</div><div> dec_ctx->channel_layout = av_get_default_channel_layout(dec_ctx->channels);</div>
<div> snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, time_base.num, time_base.den, dec_ctx->sample_rate, av_get_sample_fmt_name(dec_ctx->sample_fmt), dec_ctx->channel_layout);</div>
<div> ret = avfilter_graph_create_filter(&ff->buffersrc_ctx, abuffersrc, "in", args, NULL, ff->filter_graph);</div><div> if (ret < 0) {</div><div> av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");</div>
<div> return ret;</div><div> }</div><div><br></div><div> /* buffer audio sink: to terminate the filter chain. */</div><div> //abuffersink_params = av_abuffersink_params_alloc();</div><div> //abuffersink_params->sample_fmts = sample_fmts;</div>
<div> ret = avfilter_graph_create_filter(&ff->buffersink_ctx, abuffersink, "out", NULL, NULL, ff->filter_graph);</div><div> //av_free(abuffersink_params);</div><div> if (ret < 0) {</div><div>
av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");</div><div> return ret;</div><div> }</div><div> </div><div> </div><div><br></div><div> /* Endpoints for the filter graph. */</div>
<div> outputs->name = av_strdup("in");</div><div> outputs->filter_ctx = ff->buffersrc_ctx;</div><div> outputs->pad_idx = 0;</div><div> outputs->next = NULL;</div><div><br>
</div><div> inputs->name = av_strdup("out");</div><div> inputs->filter_ctx = ff->buffersink_ctx;</div><div> inputs->pad_idx = 0;</div><div> inputs->next = NULL;</div><div>
<br></div><div><span style="white-space:pre-wrap"> </span>char *filter_descr = default_filter_descr;</div><div> </div><div><span style="white-space:pre-wrap"> </span>snprintf(args,sizeof(args), "%s,volume=%.2f",filter_descr , volume);<br>
</div><div> INFO1("Filter string: %s",filter_descr);</div><div> </div><div> if ((ret = avfilter_graph_parse(ff->filter_graph, args, &inputs, &outputs, NULL)) < 0)</div><div> return ret;</div>
<div><br></div><div> if ((ret = avfilter_graph_config(ff->filter_graph, NULL)) < 0)</div><div> return ret;</div><div><br></div><div><span style="white-space:pre-wrap"> </span>av_log(NULL, AV_LOG_INFO, "%s\n", args);</div>
<div> /* Print summary of the sink buffer</div><div> * Note: args buffer is reused to store channel layout string */</div><div> outlink = ff->buffersink_ctx->inputs[0];</div><div> av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout);</div>
<div><span style="white-space:pre-wrap"> </span></div><div> av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n", (int)outlink->sample_rate, (char *)av_x_if_null(av_get_sample_fmt_name((AVSampleFormat)outlink->format), "?"), args);</div>
<div><br></div><div> return 0;</div><div>}</div><div><br></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote"><div><div class="h5">On Fri, May 3, 2013 at 1:36 PM, Nicolas George <span dir="ltr"><<a href="mailto:nicolas.george@normalesup.org" target="_blank">nicolas.george@normalesup.org</a>></span> wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">Le tridi 13 floréal, an CCXXI, Radu Robotin a écrit :<br>
<div>> I'm using ffmpeg with libavcodec and libavfilters for a custom project.<br>
> I've recently upgraded to the latest version available from git and noticed<br>
> that my previous code has stopped working. I'm processing several streams,<br>
> each in his own thread in the following way:<br>
><br>
> next sample is taken from the stream, decoded and then inserted in the<br>
> buffer source of the filtergraph using av_buffersrc_add_frame()<br>
> a frame is extracted from the buffer sink of the filtergraph using<br>
> av_buffersink_get_frame()<br>
> the filtered frame is copied in a buffer for further processing<br>
><br>
> before upgrading to the latest version of ffmpeg I've been using ffmpeg 1.2<br>
> and everything worked flawlessly. The filtered buffer was pulled from the<br>
> filtergraph using the av_buffersink_get_buffer_ref().<br>
<br>
</div>The change from buffer ref to frames was accompanied with a change in the<br>
lifetime of the frames. What you describe looks like a problem with that,<br>
but without seeing the code it is impossible to tell for sure.<br>
<div><br>
> The problem I'm encountering: at the first pass everything works fine,<br>
> however when I call the processing function for the second time (for<br>
> processing the next frame), it coredumps when I call<br>
> av_buffersink_get_frame() with the message " corrupted double-linked list ".<br>
> I tried further investigating the problem and have several<br>
> frames processed during the same call of this function: everything works<br>
> until the second call, then it coredumps at the same point.<br>
<br>
</div>The "corrupted double-linked list" message seems to indicate corrupted<br>
memory: either you write to an invalid location, or you write to a location<br>
that was previously freed, but you do not get the error immediately. I<br>
suggest you use valgrind to get an error at the exact time of the problem.<br>
<div><br>
> To me it seems that something changes the structure of the filtergraph<br>
> between the calls to the processing function.<br>
<br>
</div>I am rather sure that the structure of the filter graph is not supposed to<br>
change after it has been configured.<br>
<br>
Regards,<br>
<span><font color="#888888"><br>
--<br>
Nicolas George<br>
</font></span><br></div></div>-----BEGIN PGP SIGNATURE-----<br>
Version: GnuPG v1.4.12 (GNU/Linux)<br>
<br>
iEYEARECAAYFAlGDkyQACgkQsGPZlzblTJO/swCgkvXLQfnrP65ERswa1evJZSlp<br>
jBgAoKLHeBMgtGqB9oAsjmpKL0eDVv5G<br>
=0vJ2<br>
-----END PGP SIGNATURE-----<br>
<br>_______________________________________________<br>
Libav-user mailing list<br>
<a href="mailto:Libav-user@ffmpeg.org" target="_blank">Libav-user@ffmpeg.org</a><br>
<a href="http://ffmpeg.org/mailman/listinfo/libav-user" target="_blank">http://ffmpeg.org/mailman/listinfo/libav-user</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div>