[Libav-user] av_buffersink_get_frame() crashes
Radu Robotin
radu.robotin at gmail.com
Fri May 3 16:38:02 CEST 2013
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/20130503/7d9a75b5/attachment.html>
More information about the Libav-user
mailing list