<div dir="ltr"><div style>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 style><br></div><div style>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 style><br></div>
<div style>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 style>Thanks a lot!</div>
<div><br></div><div>refbuf_t * ffmpegFetchDecodeResampleNext(myFFmpegContext * ff, source_t *source){</div><div><span class="" style="white-space:pre">   </span></div><div>    refbuf_t * retRefBuff = NULL;<br></div><div><span style="white-space:pre">    </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">      </span>int localbuffering = 1;<br></div>
<div><span style="white-space:pre">      </span>while(global.running == ICE_RUNNING && source->running && localbuffering)</div><div><span class="" style="white-space:pre">        </span>{</div><div><span class="" style="white-space:pre">          </span>ff->timeout = time(NULL);</div>
<div><span class="" style="white-space:pre">            </span>ret= av_read_frame(ff->pInputFormatCtx, &pPacket);</div><div><span class="" style="white-space:pre">  </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 class="" style="white-space:pre">            </span>av_free_packet(&pPacket);</div><div>            continue;</div>
<div>        }</div><div><span class="" style="white-space:pre">            </span>if(ret == EOF){</div><div><span class="" style="white-space:pre">                    </span>source->running = 0;</div><div><span class="" style="white-space:pre">                    </span>ERROR1("av_read_frame error, EOF, exiting %s",ff->localMount);</div>
<div><span class="" style="white-space:pre">                    </span>av_free_packet(&pPacket);</div><div><span class="" style="white-space:pre">                      </span>break;</div><div><span class="" style="white-space:pre">             </span>}</div><div>        if (ret < 0) {</div>
<div><span class="" style="white-space:pre">                    </span>WARN1("av_read_frame error, error reading frame, breaking %s",ff->localMount);</div><div><span class="" style="white-space:pre">                        </span>av_free_packet(&pPacket);</div>
<div><span class="" style="white-space:pre">                    </span>ff->failedReads++;</div><div><span class="" style="white-space:pre">                      </span>if(ff->failedReads >= 10)</div><div><span class="" style="white-space:pre">                            </span>source->running = 0;</div>
<div>            return NULL;</div><div>        }</div><div><br></div><div><span class="" style="white-space:pre">    </span>ff->failedReads = 0;</div><div><br></div><div><span class="" style="white-space:pre">   </span>time_t current = time (NULL);</div>
<div><span class="" style="white-space:pre">    </span>source->last_read = current;</div><div>    <span class="" style="white-space:pre">        </span>int got_frame = 0;<br></div><div><span class="" style="white-space:pre">       </span>avcodec_get_frame_defaults(frame);</div>
<div><span class="" style="white-space:pre">    </span>ret = avcodec_decode_audio4(ff->pInputCodecCtx, frame, &got_frame, &pPacket);</div><div>                </div><div><span class="" style="white-space:pre">    </span>if(ret < 0 ){</div>
<div><span class="" style="white-space:pre">                    </span>WARN1("avcodec_decode_audio3 unable to decode %s",ff->localMount);</div><div><span class="" style="white-space:pre">                    </span>ff->failedDecodes++;</div>
<div><span class="" style="white-space:pre">                    </span>if(ff->failedDecodes >= 500){</div><div><span class="" style="white-space:pre">                                </span>source->running = 0;</div><div><span class="" style="white-space:pre">                            </span>ERROR1("avcodec_decode_audio3 unable to decode %s error limit reached, closing stream",ff->localMount);</div>
<div><span class="" style="white-space:pre">                            </span>av_free_packet(&pPacket);</div><div>        <span class="" style="white-space:pre">                      </span>return NULL;</div><div><span class="" style="white-space:pre">                       </span>}</div>
<div><span class="" style="white-space:pre">    </span>}</div><div>     <span class="" style="white-space:pre">     </span>  </div><div><span class="" style="white-space:pre">         </span>else if(got_frame == 0){</div><div><span class="" style="white-space:pre">           </span> <span class="" style="white-space:pre"> </span>thread_sleep (delay*1000);</div>
<div><span class="" style="white-space:pre">            </span>}</div><div>      </div><div><span class="" style="white-space:pre">             </span>else{  </div><div>            </div><div><span class="" style="white-space:pre">                 </span>ff->failedDecodes = 0;</div>
<div><span class="" style="white-space:pre">                    </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 class="" style="white-space:pre">                             </span>if (resample_changed)   {</div><div><span class="" style="white-space:pre">                                  </span>ff->resample_sample_fmt  = ff->pInputCodecCtx->sample_fmt;</div>
<div><span class="" style="white-space:pre">    </span>            <span class="" style="white-space:pre">                      </span>ff->resample_channels    = ff->pInputCodecCtx->channels;</div><div><span class="" style="white-space:pre">  </span>            <span class="" style="white-space:pre">                      </span>ff->resample_sample_rate = ff->pInputCodecCtx->sample_rate;</div>
<div><span class="" style="white-space:pre">                                    </span></div><div><span class="" style="white-space:pre">                           </span>}</div><div><span class="" style="white-space:pre">                          </span>/*RESAMPLING parameters */<br></div><div><span class="" style="white-space:pre">                               </span>INFO3("resampling context ch:%d spl:%d %s",ff->pInputCodecCtx->channels, ff->pInputCodecCtx->sample_rate, ff->localMount);</div>
<div><span class="" style="white-space:pre">                            </span>INFO2("volume for %s :%d",ff->localMount, ff->volume);</div><div><span class="" style="white-space:pre">                             </span>if ((ret = init_filters(ff,source)) < 0) {</div>
<div><span class="" style="white-space:pre">                    </span>   <span class="" style="white-space:pre">               </span>ERROR1( "Error while init_filters %s",ff->localMount);</div><div><span class="" style="white-space:pre">                                        </span>av_free_packet(&pPacket);</div>
<div><span class="" style="white-space:pre">                                    </span>source->running = 0;</div><div><span class="" style="white-space:pre">                                    </span>return NULL;</div><div><span class="" style="white-space:pre">                               </span>}</div>
<div>                </div><div>               </div><div><span class="" style="white-space:pre">                       </span>}</div><div>           </div><div style>            //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 class="" style="white-space:pre">                                       </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 style><span class="" style="white-space:pre">             </span></div><div style>
<span class="" style="white-space:pre">// This is where the crash happens - initially it was something like:</span></div><div style><span class="" style="white-space:pre">                //    AVFilterBufferRef *samplesref;
                //     ret = av_buffersink_get_buffer_ref(ff->buffersink_ctx, &samplesref, 0);</span></div><div style><span class="" style="white-space:pre">               //
                                        </span> </div><div>                </div><div>                ret = av_buffersink_get_frame(ff->buffersink_ctx, filt_frame);</div><div><br></div><div style>// 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 style>              </div><div>                if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)</div><div><span class="" style="white-space:pre">                                          </span>break;</div><div>                if(ret < 0)</div><div>
<span class="" style="white-space:pre">                                               </span>WARN1("error av_buffersink_get_frame, %s",ff->localMount);</div><div>                if (ret>=0) {</div><div><span class="" style="white-space:pre">                                             </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 style>                   //process the frame and put it in a circular buffer to be returned at exit</div><div style>................................................</div><div style><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 class="" style="white-space:pre">                     </span>if(ret < 0) {</div><div><span class="" style="white-space:pre">                           </span>av_free_packet(&pPacket);</div><div>
<span class="" style="white-space:pre">                               </span>break;</div><div><span class="" style="white-space:pre">                     </span>}</div><div><span class="" style="white-space:pre">                                  </span></div><div><span class="" style="white-space:pre">           </span>}</div>
<div><span class="" style="white-space:pre">            </span>av_free_packet(&pPacket);</div><div><span class="" style="white-space:pre">      </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">    </span></div><div>    return nextPreBuffer(source);</div><div>}</div><div><br></div><div><br></div><div style>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 style><br></div><div style><br></div><div style><div>static int init_filters(myFFmpegContext * ff, source_t *source)</div><div>{</div><div><span class="" style="white-space:pre">       </span>AVFormatContext *fmt_ctx = ff->pInputFormatCtx;</div>
<div><span class="" style="white-space:pre">    </span>AVCodecContext *dec_ctx = ff->pInputCodecCtx; </div><div><span class="" style="white-space:pre">  </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 class="" style="white-space:pre">   </span>if(ff->filter_graph)</div><div><span class="" style="white-space:pre">            </span>avfilter_graph_free(&ff->filter_graph);</div><div><span class="" style="white-space:pre">     </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 class="" style="white-space:pre">      </span>char *filter_descr = default_filter_descr;</div><div>       </div><div><span class="" style="white-space:pre">   </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 class="" style="white-space:pre"> </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 class="" style="white-space:pre">    </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">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>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Le tridi 13 floréal, an CCXXI, Radu Robotin a écrit :<br>
<div class="im">> 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 class="im"><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 class="im"><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 class="HOEnZb"><font color="#888888"><br>
--<br>
  Nicolas George<br>
</font></span><br>-----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">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>