[Libav-user] av_buffersink_get_frame() crashes
Radu Robotin
radu.robotin at gmail.com
Mon May 13 18:48:32 CEST 2013
Here is a little update: I haven't found the problem yet :)
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.
The strangest thing is that under valgrind everything works fine. Tested
several times, under valgrind it just works.
What am I missing here? Why is it working under valgrind and crashes during
normal running? I really need help with this one!!
Thank you guys, for any suggestions and help!
Best,
Radu
On Fri, May 3, 2013 at 5:38 PM, Radu Robotin <radu.robotin at gmail.com> wrote:
> 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.
>
> The first call to ffmpegFetchDecodeResampleNext() works as expected,. the
> second one fails (with coredump) when trying to get the filtered frame from
> the filtergraph.
>
> 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?
>
>
> Thanks a lot!
>
> refbuf_t * ffmpegFetchDecodeResampleNext(myFFmpegContext * ff, source_t
> *source){
> refbuf_t * retRefBuff = NULL;
> AVPacket pPacket;
> AVFrame *frame = av_frame_alloc();
> AVFrame *filt_frame = av_frame_alloc();
> AVFrame *enc_frame = av_frame_alloc();
>
> if (!frame || !filt_frame || !enc_frame) {
> ERROR0("Could not allocate frame(s)");
> return NULL;
> }
> int ret;
> int localbuffering = 1;
> while(global.running == ICE_RUNNING && source->running &&
> localbuffering)
> {
> ff->timeout = time(NULL);
> ret= av_read_frame(ff->pInputFormatCtx, &pPacket);
> if(ret == AVERROR(EAGAIN)){
> WARN1("av_read_frame error EAGAIN, error reading frame,
> continuing %s",ff->localMount);
> av_free_packet(&pPacket);
> continue;
> }
> if(ret == EOF){
> source->running = 0;
> ERROR1("av_read_frame error, EOF, exiting %s",ff->localMount);
> av_free_packet(&pPacket);
> break;
> }
> if (ret < 0) {
> WARN1("av_read_frame error, error reading frame, breaking
> %s",ff->localMount);
> av_free_packet(&pPacket);
> ff->failedReads++;
> if(ff->failedReads >= 10)
> source->running = 0;
> return NULL;
> }
>
> ff->failedReads = 0;
>
> time_t current = time (NULL);
> source->last_read = current;
> int got_frame = 0;
> avcodec_get_frame_defaults(frame);
> ret = avcodec_decode_audio4(ff->pInputCodecCtx, frame, &got_frame,
> &pPacket);
>
> if(ret < 0 ){
> WARN1("avcodec_decode_audio3 unable to decode %s",ff->localMount);
> ff->failedDecodes++;
> if(ff->failedDecodes >= 500){
> source->running = 0;
> ERROR1("avcodec_decode_audio3 unable to decode %s error limit reached,
> closing stream",ff->localMount);
> av_free_packet(&pPacket);
> return NULL;
> }
> }
>
> else if(got_frame == 0){
> thread_sleep (delay*1000);
> }
>
> else{
>
> ff->failedDecodes = 0;
> 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;
> if (resample_changed) {
> if (resample_changed) {
> ff->resample_sample_fmt = ff->pInputCodecCtx->sample_fmt;
> ff->resample_channels = ff->pInputCodecCtx->channels;
> ff->resample_sample_rate = ff->pInputCodecCtx->sample_rate;
> }
> /*RESAMPLING parameters */
> INFO3("resampling context ch:%d spl:%d %s",ff->pInputCodecCtx->channels,
> ff->pInputCodecCtx->sample_rate, ff->localMount);
> INFO2("volume for %s :%d",ff->localMount, ff->volume);
> if ((ret = init_filters(ff,source)) < 0) {
> ERROR1( "Error while init_filters %s",ff->localMount);
> av_free_packet(&pPacket);
> source->running = 0;
> return NULL;
> }
>
>
> }
>
> //feed the filter graph with the new frame
>
> if (av_buffersrc_add_frame_flags(ff->buffersrc_ctx, frame,0)
> < 0) {
> ERROR1( "Error while feeding the audio filtergraph %s",ff->localMount);
> }
>
> /* pull filtered audio from the filtergraph */
> while (1) {
>
> // This is where the crash happens - initially it was something like:
> // AVFilterBufferRef *samplesref; // ret =
> av_buffersink_get_buffer_ref(ff->buffersink_ctx, &samplesref, 0);
> //
>
> ret = av_buffersink_get_frame(ff->buffersink_ctx,
> filt_frame);
>
> // 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
>
> if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
> break;
> if(ret < 0)
> WARN1("error av_buffersink_get_frame, %s",ff->localMount);
> if (ret>=0) {
> //print_samplesref(samplesref);
> char * resampleBuff = (char *)filt_frame->data[0];
> size_out = filt_frame->nb_samples *
> av_get_channel_layout_nb_channels(av_frame_get_channel_layout(filt_frame));
>
> //process the frame and put it in a circular buffer to
> be returned at exit
> ................................................
>
> av_frame_unref(filt_frame);
> av_frame_unref(frame);
> }
>
> }
> av_frame_unref(filt_frame);
> av_frame_unref(frame);
> if(ret < 0) {
> av_free_packet(&pPacket);
> break;
> }
> }
> av_free_packet(&pPacket);
> }
> av_frame_free(&filt_frame);
> av_frame_free(&frame);
> av_frame_free(&enc_frame);
>
> return nextPreBuffer(source);
> }
>
>
> 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
>
>
> static int init_filters(myFFmpegContext * ff, source_t *source)
> {
> AVFormatContext *fmt_ctx = ff->pInputFormatCtx;
> AVCodecContext *dec_ctx = ff->pInputCodecCtx;
> int audio_stream_index = ff->audioStreamIndex;
>
> char args[512];
> int ret;
> char *pcTemp_string1, *pcTemp_string2;
> char buffer[10];
>
> AVFilter *abuffersrc = avfilter_get_by_name("abuffer");
> AVFilter *abuffersink = avfilter_get_by_name("abuffersink");
> AVFilterInOut *outputs = avfilter_inout_alloc();
> AVFilterInOut *inputs = avfilter_inout_alloc();
> const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16,
> AV_SAMPLE_FMT_NONE };
> AVABufferSinkParams *abuffersink_params;
>
>
> const AVFilterLink *outlink;
> AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base;
>
> if(ff->filter_graph)
> avfilter_graph_free(&ff->filter_graph);
> ff->filter_graph = avfilter_graph_alloc();
>
> /* buffer audio source: the decoded frames from the decoder will be
> inserted here. */
> if (!dec_ctx->channel_layout)
> dec_ctx->channel_layout =
> av_get_default_channel_layout(dec_ctx->channels);
> 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);
> ret = avfilter_graph_create_filter(&ff->buffersrc_ctx, abuffersrc,
> "in", args, NULL, ff->filter_graph);
> if (ret < 0) {
> av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");
> return ret;
> }
>
> /* buffer audio sink: to terminate the filter chain. */
> //abuffersink_params = av_abuffersink_params_alloc();
> //abuffersink_params->sample_fmts = sample_fmts;
> ret = avfilter_graph_create_filter(&ff->buffersink_ctx, abuffersink,
> "out", NULL, NULL, ff->filter_graph);
> //av_free(abuffersink_params);
> if (ret < 0) {
> av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");
> return ret;
> }
>
>
>
> /* Endpoints for the filter graph. */
> outputs->name = av_strdup("in");
> outputs->filter_ctx = ff->buffersrc_ctx;
> outputs->pad_idx = 0;
> outputs->next = NULL;
>
> inputs->name = av_strdup("out");
> inputs->filter_ctx = ff->buffersink_ctx;
> inputs->pad_idx = 0;
> inputs->next = NULL;
>
> char *filter_descr = default_filter_descr;
>
> snprintf(args,sizeof(args), "%s,volume=%.2f",filter_descr , volume);
> INFO1("Filter string: %s",filter_descr);
>
> if ((ret = avfilter_graph_parse(ff->filter_graph, args, &inputs,
> &outputs, NULL)) < 0)
> return ret;
>
> if ((ret = avfilter_graph_config(ff->filter_graph, NULL)) < 0)
> return ret;
>
> av_log(NULL, AV_LOG_INFO, "%s\n", args);
> /* Print summary of the sink buffer
> * Note: args buffer is reused to store channel layout string */
> outlink = ff->buffersink_ctx->inputs[0];
> av_get_channel_layout_string(args, sizeof(args), -1,
> outlink->channel_layout);
> 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);
>
> return 0;
> }
>
>
>
> On Fri, May 3, 2013 at 1:36 PM, Nicolas George <
> nicolas.george at normalesup.org> wrote:
>
>> Le tridi 13 floréal, an CCXXI, Radu Robotin a écrit :
>> > I'm using ffmpeg with libavcodec and libavfilters for a custom project.
>> > I've recently upgraded to the latest version available from git and
>> noticed
>> > that my previous code has stopped working. I'm processing several
>> streams,
>> > each in his own thread in the following way:
>> >
>> > next sample is taken from the stream, decoded and then inserted in
>> the
>> > buffer source of the filtergraph using av_buffersrc_add_frame()
>> > a frame is extracted from the buffer sink of the filtergraph using
>> > av_buffersink_get_frame()
>> > the filtered frame is copied in a buffer for further processing
>> >
>> > before upgrading to the latest version of ffmpeg I've been using ffmpeg
>> 1.2
>> > and everything worked flawlessly. The filtered buffer was pulled from
>> the
>> > filtergraph using the av_buffersink_get_buffer_ref().
>>
>> The change from buffer ref to frames was accompanied with a change in the
>> lifetime of the frames. What you describe looks like a problem with that,
>> but without seeing the code it is impossible to tell for sure.
>>
>> > The problem I'm encountering: at the first pass everything works fine,
>> > however when I call the processing function for the second time (for
>> > processing the next frame), it coredumps when I call
>> > av_buffersink_get_frame() with the message " corrupted double-linked
>> list ".
>> > I tried further investigating the problem and have several
>> > frames processed during the same call of this function: everything works
>> > until the second call, then it coredumps at the same point.
>>
>> The "corrupted double-linked list" message seems to indicate corrupted
>> memory: either you write to an invalid location, or you write to a
>> location
>> that was previously freed, but you do not get the error immediately. I
>> suggest you use valgrind to get an error at the exact time of the problem.
>>
>> > To me it seems that something changes the structure of the filtergraph
>> > between the calls to the processing function.
>>
>> I am rather sure that the structure of the filter graph is not supposed to
>> change after it has been configured.
>>
>> Regards,
>>
>> --
>> Nicolas George
>>
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v1.4.12 (GNU/Linux)
>>
>> iEYEARECAAYFAlGDkyQACgkQsGPZlzblTJO/swCgkvXLQfnrP65ERswa1evJZSlp
>> jBgAoKLHeBMgtGqB9oAsjmpKL0eDVv5G
>> =0vJ2
>> -----END PGP SIGNATURE-----
>>
>> _______________________________________________
>> Libav-user mailing list
>> Libav-user at ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/libav-user
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20130513/f1470538/attachment.html>
More information about the Libav-user
mailing list