[FFmpeg-user] Delay filter reconfiguration
Paul B Mahol
onemda at gmail.com
Wed Jun 11 18:42:24 CEST 2014
On 6/11/14, androiddevmar11 <androiddevmar11 at gmail.com> wrote:
> Hello,
> Actually there can be more than two inputs. To be specific, in most typical
> scenario I will have one AAC file and more than one video files. I want to
> get some frames from specific time stamp of video file and add them to
> specific time stamp in AAC file. More than one pieces of audio can be taken
> from one video input and added to one or more places in AAC file. I am
> doing
> proof of concept based on this code:
> https://gist.github.com/MrArtichaut/11136813. My init_filter_graph function
> looks like this:
>
> static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src0,
> AVFilterContext **src1,
> AVFilterContext **sink)
> {
> AVFilterGraph *filter_graph;
> AVFilterContext *abuffer1_ctx;
> AVFilter *abuffer1;
> AVFilterContext *abuffer0_ctx;
> AVFilter *abuffer0;
> AVFilterContext *adelay_ctx;
> AVFilter *adelay;
> AVFilterContext *mix_ctx;
> AVFilter *mix_filter;
> AVFilterContext *abuffersink_ctx;
> AVFilter *abuffersink;
>
> char args[512];
>
> int err;
>
> /* Create a new filter graph, which will contain all the filters. */
> filter_graph = avfilter_graph_alloc();
> if (!filter_graph) {
> //av_log(NULL, AV_LOG_ERROR, "Unable to create filter graph.\n");
> LOGE("Unable to create filter graph.\n");
> return AVERROR(ENOMEM);
> }
>
> /****** abuffer 0 ********/
>
> /* Create the abuffer filter, it will be used for feeding the data into
> the graph. */
> abuffer0 = avfilter_get_by_name("abuffer");
> if (!abuffer0) {
> //av_log(NULL, AV_LOG_ERROR, "Could not find the abuffer
> filter.\n");
> LOGE("Could not find the abuffer filter.\n");
> return AVERROR_FILTER_NOT_FOUND;
> }
>
> /* buffer audio source: the decoded frames from the decoder will be
> inserted here. */
> if (!input_codec_context_0->channel_layout)
> input_codec_context_0->channel_layout =
> av_get_default_channel_layout(input_codec_context_0->channels);
> snprintf(args, sizeof(args),
> "sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
> input_codec_context_0->sample_rate,
> av_get_sample_fmt_name(input_codec_context_0->sample_fmt),
> input_codec_context_0->channel_layout);
>
>
> err = avfilter_graph_create_filter(&abuffer0_ctx, abuffer0, "src0",
> args, NULL, filter_graph);
> if (err < 0) {
> //av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer
> source\n");
> LOGE("Cannot create audio buffer source\n");
> return err;
> }
>
> /****** abuffer 1 ******* */
>
> /* Create the abuffer filter;
> * it will be used for feeding the data into the graph. */
> abuffer1 = avfilter_get_by_name("abuffer");
> if (!abuffer1) {
> //av_log(NULL, AV_LOG_ERROR, "Could not find the abuffer
> filter.\n");
> LOGE("Could not find the abuffer filter.\n");
> return AVERROR_FILTER_NOT_FOUND;
> }
>
> /* buffer audio source: the decoded frames from the decoder will be
> inserted here. */
> if (!input_codec_context_1->channel_layout)
> input_codec_context_1->channel_layout =
> av_get_default_channel_layout(input_codec_context_1->channels);
> snprintf(args,
> sizeof(args),"sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
> input_codec_context_1->sample_rate,
> av_get_sample_fmt_name(input_codec_context_1->sample_fmt),
> input_codec_context_1->channel_layout);
>
>
> err = avfilter_graph_create_filter(&abuffer1_ctx, abuffer1, "src1",
> args, NULL, filter_graph);
> if (err < 0) {
> //av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer
> source\n");
> LOGE("Cannot create audio buffer source\n");
> return err;
> }
>
> /****** adelay ******* */
> adelay = avfilter_get_by_name("adelay");
> if (!adelay) {
> LOGE("Could not find the adelay filter.\n");
> return AVERROR_FILTER_NOT_FOUND;
> }
> /* buffer audio source: the decoded frames from the decoder will be
> inserted here. */
> snprintf(args, sizeof(args),"delays=%d", 1000);
> err = avfilter_graph_create_filter(&adelay_ctx, adelay, "del1", args,
> NULL,
> filter_graph);
>
> /* ***** amix ******* */
> /* Create mix filter. */
> mix_filter = avfilter_get_by_name("amix");
> if (!mix_filter) {
> //av_log(NULL, AV_LOG_ERROR, "Could not find the mix filter.\n");
> LOGE("Could not find the mix filter.\n");
> return AVERROR_FILTER_NOT_FOUND;
> }
>
> snprintf(args, sizeof(args), "inputs=2:duration=shortest");
>
> err = avfilter_graph_create_filter(&mix_ctx, mix_filter, "amix",
> args, NULL, filter_graph);
>
> if (err < 0) {
> av_log(NULL, AV_LOG_ERROR, "Cannot create audio amix filter\n");
> LOGE("Cannot create audio amix filter\n");
> return err;
> }
>
> /* Finally create the abuffersink filter;
> * it will be used to get the filtered data out of the graph. */
> abuffersink = avfilter_get_by_name("abuffersink");
> if (!abuffersink) {
> //av_log(NULL, AV_LOG_ERROR, "Could not find the abuffersink
> filter.\n");
> LOGE("Could not find the abuffersink filter.\n");
> return AVERROR_FILTER_NOT_FOUND;
> }
>
> abuffersink_ctx = avfilter_graph_alloc_filter(filter_graph,
> abuffersink,
> "sink");
> if (!abuffersink_ctx) {
> //av_log(NULL, AV_LOG_ERROR, "Could not allocate the abuffersink
> instance.\n");
> LOGE("Could not allocate the abuffersink instance.\n");
> return AVERROR(ENOMEM);
> }
>
> /* Same sample fmts as the output file. */
> err = av_opt_set_int_list(abuffersink_ctx, "sample_fmts",
> ((int[]){ SAMPLE_FORMAT, AV_SAMPLE_FMT_NONE
> }),
> AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
>
> uint8_t ch_layout[64];
> av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0,
> OUTPUT_CHANNELS);
> av_opt_set (abuffersink_ctx, "channel_layout", ch_layout,
> AV_OPT_SEARCH_CHILDREN);
>
> if (err < 0) {
> //av_log(NULL, AV_LOG_ERROR, "Could set options to the abuffersink
> instance.\n");
> LOGE("Could set options to the abuffersink instance.\n");
> return err;
> }
>
> err = avfilter_init_str(abuffersink_ctx, NULL);
> if (err < 0) {
> //av_log(NULL, AV_LOG_ERROR, "Could not initialize the abuffersink
> instance.\n");
> LOGE("Could not initialize the abuffersink instance.\n");
> return err;
> }
>
>
> /* Connect the filters; */
> err = avfilter_link(abuffer0_ctx, 0, adelay_ctx, 0);
> err = avfilter_link(adelay_ctx, 0, mix_ctx, 0);
> if (err >= 0)
> err = avfilter_link(abuffer1_ctx, 0, mix_ctx, 1);
> if (err >= 0)
> err = avfilter_link(mix_ctx, 0, abuffersink_ctx, 0);
> if (err < 0) {
> av_log(NULL, AV_LOG_ERROR, "Error connecting filters\n");
> return err;
> }
>
> /* Configure the graph. */
> err = avfilter_graph_config(filter_graph, NULL);
> if (err < 0) {
> //av_log(NULL, AV_LOG_ERROR, "Error while configuring graph :
> %s\n",
> get_error_text(err));
> LOGE("Error while configuring graph : %s\n", get_error_text(err));
> return err;
> }
>
> // ------------------------------------------------
> // reconfigure delay filter:
> avfilter_free(adelay_ctx);
>
> snprintf(args, sizeof(args),"delays=%d", 2000);
> err = avfilter_graph_create_filter(&adelay_ctx, adelay, "del1", args,
> NULL,
> filter_graph);
>
> err = avfilter_link(abuffer0_ctx, 0, adelay_ctx, 0);
> err = avfilter_link(adelay_ctx, 0, mix_ctx, 0);
> err = avfilter_graph_config(filter_graph, NULL);
> // ------------------------------------------------
>
> char* dump = avfilter_graph_dump(filter_graph, NULL);
> //av_log(NULL, AV_LOG_ERROR, "Graph :\n%s\n", dump);
> LOGE("Graph :\n%s\n", dump);
>
> *graph = filter_graph;
> *src0 = abuffer0_ctx;
> *src1 = abuffer1_ctx;
> *sink = abuffersink_ctx;
>
> return 0;
> }
>
> Please have a look at "reconfigure delay filter" part. Program crashes at
> av_buffersink_get_frame (funciton process_all() from link) giving error:
>
> Execution stopped at: 0x6AEF0400
> In thread 1 (OS thread id 2758)
> In buffersink.c
>
> You mentioned that using adelay is not optimal. What is the better
> solution?
> Other filter? Thank you for help.
Perhaps only asetpts filter. It is not optimal to use adelay+amix
because of extra overhead with calculation of samples while you
basically only change frame timestamp.
Also be aware that adelay filter when used in your case need to delay
all available channels and not just first one, so something like
"delays=1000 | 1000" should be used for stereo.
>
>
>
>
>
> --
> View this message in context:
> http://ffmpeg-users.933282.n4.nabble.com/Delay-filter-reconfiguration-tp4665727p4665765.html
> Sent from the FFmpeg-users mailing list archive at Nabble.com.
> _______________________________________________
> ffmpeg-user mailing list
> ffmpeg-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-user
>
More information about the ffmpeg-user
mailing list