From 7ad0d9864ee4a25dcace903c0b5860cbe43e535b Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Fri, 27 Apr 2012 19:19:45 +0200 Subject: [PATCH] lavfi: merge asrc_abuffer into vsrc_buffer. --- libavfilter/Makefile | 1 - libavfilter/asrc_abuffer.c | 369 --------------------------------------------- libavfilter/vsrc_buffer.c | 349 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 338 insertions(+), 381 deletions(-) delete mode 100644 libavfilter/asrc_abuffer.c diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ce4fc48354..e5da239dcd 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -42,7 +42,6 @@ OBJS-$(CONFIG_PAN_FILTER) += af_pan.o OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o -OBJS-$(CONFIG_ABUFFER_FILTER) += asrc_abuffer.o OBJS-$(CONFIG_AEVALSRC_FILTER) += asrc_aevalsrc.o OBJS-$(CONFIG_AMOVIE_FILTER) += src_movie.o OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o diff --git a/libavfilter/asrc_abuffer.c b/libavfilter/asrc_abuffer.c deleted file mode 100644 index eab83e2b3d..0000000000 --- a/libavfilter/asrc_abuffer.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram - * Copyright (c) 2011 Mina Nagy Zaki - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * memory buffer source for audio - */ - -#include "libavutil/audioconvert.h" -#include "libavutil/avstring.h" -#include "libavutil/fifo.h" -#include "asrc_abuffer.h" -#include "internal.h" - -typedef struct { - // Audio format of incoming buffers - int sample_rate; - unsigned int sample_format; - int64_t channel_layout; - int packing_format; - - // FIFO buffer of audio buffer ref pointers - AVFifoBuffer *fifo; - - // Normalization filters - AVFilterContext *aconvert; - AVFilterContext *aresample; -} ABufferSourceContext; - -#define FIFO_SIZE 8 - -static void buf_free(AVFilterBuffer *ptr) -{ - av_free(ptr); - return; -} - -static void set_link_source(AVFilterContext *src, AVFilterLink *link) -{ - link->src = src; - link->srcpad = &(src->output_pads[0]); - src->outputs[0] = link; -} - -static int reconfigure_filter(ABufferSourceContext *abuffer, AVFilterContext *filt_ctx) -{ - int ret; - AVFilterLink * const inlink = filt_ctx->inputs[0]; - AVFilterLink * const outlink = filt_ctx->outputs[0]; - - inlink->format = abuffer->sample_format; - inlink->channel_layout = abuffer->channel_layout; - inlink->planar = abuffer->packing_format; - inlink->sample_rate = abuffer->sample_rate; - - filt_ctx->filter->uninit(filt_ctx); - memset(filt_ctx->priv, 0, filt_ctx->filter->priv_size); - if ((ret = filt_ctx->filter->init(filt_ctx, NULL , NULL)) < 0) - return ret; - if ((ret = inlink->srcpad->config_props(inlink)) < 0) - return ret; - return outlink->srcpad->config_props(outlink); -} - -static int insert_filter(ABufferSourceContext *abuffer, - AVFilterLink *link, AVFilterContext **filt_ctx, - const char *filt_name) -{ - int ret; - - if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0) - return ret; - - link->src->outputs[0] = NULL; - if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) { - link->src->outputs[0] = link; - return ret; - } - - set_link_source(*filt_ctx, link); - - if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) { - avfilter_free(*filt_ctx); - return ret; - } - - return 0; -} - -static void remove_filter(AVFilterContext **filt_ctx) -{ - AVFilterLink *outlink = (*filt_ctx)->outputs[0]; - AVFilterContext *src = (*filt_ctx)->inputs[0]->src; - - (*filt_ctx)->outputs[0] = NULL; - avfilter_free(*filt_ctx); - *filt_ctx = NULL; - - set_link_source(src, outlink); -} - -static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref) -{ - char old_layout_str[16], new_layout_str[16]; - av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str), - -1, link->channel_layout); - av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str), - -1, ref->audio->channel_layout); - av_log(ctx, AV_LOG_INFO, - "Audio input format changed: " - "%s:%s:%d -> %s:%s:%d, normalizing\n", - av_get_sample_fmt_name(link->format), - old_layout_str, (int)link->sample_rate, - av_get_sample_fmt_name(ref->format), - new_layout_str, ref->audio->sample_rate); -} - -int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *ctx, - AVFilterBufferRef *samplesref, - int av_unused flags) -{ - ABufferSourceContext *abuffer = ctx->priv; - AVFilterLink *link; - int ret, logged = 0; - - if (av_fifo_space(abuffer->fifo) < sizeof(samplesref)) { - av_log(ctx, AV_LOG_ERROR, - "Buffering limit reached. Please consume some available frames " - "before adding new ones.\n"); - return AVERROR(EINVAL); - } - - // Normalize input - - link = ctx->outputs[0]; - if (samplesref->audio->sample_rate != link->sample_rate) { - - log_input_change(ctx, link, samplesref); - logged = 1; - - abuffer->sample_rate = samplesref->audio->sample_rate; - - if (!abuffer->aresample) { - ret = insert_filter(abuffer, link, &abuffer->aresample, "aresample"); - if (ret < 0) return ret; - } else { - link = abuffer->aresample->outputs[0]; - if (samplesref->audio->sample_rate == link->sample_rate) - remove_filter(&abuffer->aresample); - else - if ((ret = reconfigure_filter(abuffer, abuffer->aresample)) < 0) - return ret; - } - } - - link = ctx->outputs[0]; - if (samplesref->format != link->format || - samplesref->audio->channel_layout != link->channel_layout || - samplesref->audio->planar != link->planar) { - - if (!logged) log_input_change(ctx, link, samplesref); - - abuffer->sample_format = samplesref->format; - abuffer->channel_layout = samplesref->audio->channel_layout; - abuffer->packing_format = samplesref->audio->planar; - - if (!abuffer->aconvert) { - ret = insert_filter(abuffer, link, &abuffer->aconvert, "aconvert"); - if (ret < 0) return ret; - } else { - link = abuffer->aconvert->outputs[0]; - if (samplesref->format == link->format && - samplesref->audio->channel_layout == link->channel_layout && - samplesref->audio->planar == link->planar - ) - remove_filter(&abuffer->aconvert); - else - if ((ret = reconfigure_filter(abuffer, abuffer->aconvert)) < 0) - return ret; - } - } - - if (sizeof(samplesref) != av_fifo_generic_write(abuffer->fifo, &samplesref, - sizeof(samplesref), NULL)) { - av_log(ctx, AV_LOG_ERROR, "Error while writing to FIFO\n"); - return AVERROR(EINVAL); - } - - return 0; -} - -int av_asrc_buffer_add_samples(AVFilterContext *ctx, - uint8_t *data[8], int linesize[8], - int nb_samples, int sample_rate, - int sample_fmt, int64_t channel_layout, int planar, - int64_t pts, int av_unused flags) -{ - AVFilterBufferRef *samplesref; - - samplesref = avfilter_get_audio_buffer_ref_from_arrays( - data, linesize, AV_PERM_WRITE, - nb_samples, - sample_fmt, channel_layout, planar); - if (!samplesref) - return AVERROR(ENOMEM); - - samplesref->buf->free = buf_free; - samplesref->pts = pts; - samplesref->audio->sample_rate = sample_rate; - - return av_asrc_buffer_add_audio_buffer_ref(ctx, samplesref, 0); -} - -int av_asrc_buffer_add_buffer(AVFilterContext *ctx, - uint8_t *buf, int buf_size, int sample_rate, - int sample_fmt, int64_t channel_layout, int planar, - int64_t pts, int av_unused flags) -{ - uint8_t *data[8] = {0}; - int linesize[8]; - int nb_channels = av_get_channel_layout_nb_channels(channel_layout), - nb_samples = buf_size / nb_channels / av_get_bytes_per_sample(sample_fmt); - - av_samples_fill_arrays(data, linesize, - buf, nb_channels, nb_samples, - sample_fmt, 16); - - return av_asrc_buffer_add_samples(ctx, - data, linesize, nb_samples, - sample_rate, - sample_fmt, channel_layout, planar, - pts, flags); -} - -static av_cold int init(AVFilterContext *ctx, const char *args0, void *opaque) -{ - ABufferSourceContext *abuffer = ctx->priv; - char *arg = NULL, *ptr, chlayout_str[16]; - char *args = av_strdup(args0); - int ret; - - arg = av_strtok(args, ":", &ptr); - -#define ADD_FORMAT(fmt_name) \ - if (!arg) \ - goto arg_fail; \ - if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) { \ - av_freep(&args); \ - return ret; \ - } \ - if (*args) \ - arg = av_strtok(NULL, ":", &ptr) - - ADD_FORMAT(sample_rate); - ADD_FORMAT(sample_format); - ADD_FORMAT(channel_layout); - ADD_FORMAT(packing_format); - - abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*)); - if (!abuffer->fifo) { - av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n"); - return AVERROR(ENOMEM); - } - - av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), - -1, abuffer->channel_layout); - av_log(ctx, AV_LOG_INFO, "format:%s layout:%s rate:%d\n", - av_get_sample_fmt_name(abuffer->sample_format), chlayout_str, - abuffer->sample_rate); - av_freep(&args); - - return 0; - -arg_fail: - av_log(ctx, AV_LOG_ERROR, "Invalid arguments, must be of the form " - "sample_rate:sample_fmt:channel_layout:packing\n"); - av_freep(&args); - return AVERROR(EINVAL); -} - -static av_cold void uninit(AVFilterContext *ctx) -{ - ABufferSourceContext *abuffer = ctx->priv; - av_fifo_free(abuffer->fifo); -} - -static int query_formats(AVFilterContext *ctx) -{ - ABufferSourceContext *abuffer = ctx->priv; - AVFilterFormats *formats; - - formats = NULL; - avfilter_add_format(&formats, abuffer->sample_format); - avfilter_set_common_sample_formats(ctx, formats); - - formats = NULL; - avfilter_add_format(&formats, abuffer->channel_layout); - avfilter_set_common_channel_layouts(ctx, formats); - - formats = NULL; - avfilter_add_format(&formats, abuffer->packing_format); - avfilter_set_common_packing_formats(ctx, formats); - - return 0; -} - -static int config_output(AVFilterLink *outlink) -{ - ABufferSourceContext *abuffer = outlink->src->priv; - outlink->sample_rate = abuffer->sample_rate; - return 0; -} - -static int request_frame(AVFilterLink *outlink) -{ - ABufferSourceContext *abuffer = outlink->src->priv; - AVFilterBufferRef *samplesref; - - if (!av_fifo_size(abuffer->fifo)) - return AVERROR(EAGAIN); - - av_fifo_generic_read(abuffer->fifo, &samplesref, sizeof(samplesref), NULL); - avfilter_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0)); - avfilter_unref_buffer(samplesref); - - return 0; -} - -static int poll_frame(AVFilterLink *outlink) -{ - ABufferSourceContext *abuffer = outlink->src->priv; - return av_fifo_size(abuffer->fifo)/sizeof(AVFilterBufferRef*); -} - -AVFilter avfilter_asrc_abuffer = { - .name = "abuffer", - .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."), - .priv_size = sizeof(ABufferSourceContext), - .query_formats = query_formats, - - .init = init, - .uninit = uninit, - - .inputs = (const AVFilterPad[]) {{ .name = NULL }}, - .outputs = (const AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_AUDIO, - .request_frame = request_frame, - .poll_frame = poll_frame, - .config_props = config_output, }, - { .name = NULL}}, -}; diff --git a/libavfilter/vsrc_buffer.c b/libavfilter/vsrc_buffer.c index b3d1ef583a..e3060344fb 100644 --- a/libavfilter/vsrc_buffer.c +++ b/libavfilter/vsrc_buffer.c @@ -1,5 +1,7 @@ /* * Copyright (c) 2008 Vitor Sessak + * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram + * Copyright (c) 2011 Mina Nagy Zaki * * This file is part of FFmpeg. * @@ -28,21 +30,39 @@ #include "avcodec.h" #include "buffersrc.h" #include "vsrc_buffer.h" +#include "asrc_abuffer.h" +#include "libavutil/audioconvert.h" +#include "libavutil/avstring.h" #include "libavutil/fifo.h" #include "libavutil/imgutils.h" typedef struct { - AVFilterContext *scale; AVFifoBuffer *fifo; + AVRational time_base; ///< time_base to set in the output link + int eof; + unsigned nb_failed_requests; + + /* Video only */ + AVFilterContext *scale; int h, w; enum PixelFormat pix_fmt; - AVRational time_base; ///< time_base to set in the output link AVRational sample_aspect_ratio; char sws_param[256]; - int eof; - unsigned nb_failed_requests; + + /* Audio only */ + // Audio format of incoming buffers + int sample_rate; + unsigned int sample_format; + int64_t channel_layout; + int packing_format; + + // Normalization filters + AVFilterContext *aconvert; + AVFilterContext *aresample; } BufferSourceContext; +#define FIFO_SIZE 8 + #define CHECK_PARAM_CHANGE(s, c, width, height, format)\ if (c->w != width || c->h != height || c->pix_fmt != format) {\ av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\ @@ -186,7 +206,7 @@ unsigned av_vsrc_buffer_get_nb_failed_requests(AVFilterContext *buffer_src) return ((BufferSourceContext *)buffer_src->priv)->nb_failed_requests; } -static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +static av_cold int init_video(AVFilterContext *ctx, const char *args, void *opaque) { BufferSourceContext *c = ctx->priv; char pix_fmt_str[128]; @@ -214,6 +234,52 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) return 0; } +static av_cold int init_audio(AVFilterContext *ctx, const char *args0, void *opaque) +{ + BufferSourceContext *abuffer = ctx->priv; + char *arg = NULL, *ptr, chlayout_str[16]; + char *args = av_strdup(args0); + int ret; + + arg = av_strtok(args, ":", &ptr); + +#define ADD_FORMAT(fmt_name) \ + if (!arg) \ + goto arg_fail; \ + if ((ret = ff_parse_##fmt_name(&abuffer->fmt_name, arg, ctx)) < 0) { \ + av_freep(&args); \ + return ret; \ + } \ + if (*args) \ + arg = av_strtok(NULL, ":", &ptr) + + ADD_FORMAT(sample_rate); + ADD_FORMAT(sample_format); + ADD_FORMAT(channel_layout); + ADD_FORMAT(packing_format); + + abuffer->fifo = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*)); + if (!abuffer->fifo) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo, filter init failed.\n"); + return AVERROR(ENOMEM); + } + + av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), + -1, abuffer->channel_layout); + av_log(ctx, AV_LOG_INFO, "format:%s layout:%s rate:%d\n", + av_get_sample_fmt_name(abuffer->sample_format), chlayout_str, + abuffer->sample_rate); + av_freep(&args); + + return 0; + +arg_fail: + av_log(ctx, AV_LOG_ERROR, "Invalid arguments, must be of the form " + "sample_rate:sample_fmt:channel_layout:packing\n"); + av_freep(&args); + return AVERROR(EINVAL); +} + static av_cold void uninit(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; @@ -228,7 +294,7 @@ static av_cold void uninit(AVFilterContext *ctx) s->scale = NULL; } -static int query_formats(AVFilterContext *ctx) +static int query_formats_video(AVFilterContext *ctx) { BufferSourceContext *c = ctx->priv; enum PixelFormat pix_fmts[] = { c->pix_fmt, PIX_FMT_NONE }; @@ -237,7 +303,27 @@ static int query_formats(AVFilterContext *ctx) return 0; } -static int config_props(AVFilterLink *link) +static int query_formats_audio(AVFilterContext *ctx) +{ + BufferSourceContext *abuffer = ctx->priv; + AVFilterFormats *formats; + + formats = NULL; + avfilter_add_format(&formats, abuffer->sample_format); + avfilter_set_common_sample_formats(ctx, formats); + + formats = NULL; + avfilter_add_format(&formats, abuffer->channel_layout); + avfilter_set_common_channel_layouts(ctx, formats); + + formats = NULL; + avfilter_add_format(&formats, abuffer->packing_format); + avfilter_set_common_packing_formats(ctx, formats); + + return 0; +} + +static int config_output_video(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; @@ -249,6 +335,13 @@ static int config_props(AVFilterLink *link) return 0; } +static int config_output_audio(AVFilterLink *outlink) +{ + BufferSourceContext *abuffer = outlink->src->priv; + outlink->sample_rate = abuffer->sample_rate; + return 0; +} + static int request_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; @@ -262,11 +355,20 @@ static int request_frame(AVFilterLink *link) } av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL); + switch (link->type) { + case AVMEDIA_TYPE_VIDEO: + /* TODO reindent */ avfilter_start_frame(link, avfilter_ref_buffer(buf, ~0)); avfilter_draw_slice(link, 0, link->h, 1); avfilter_end_frame(link); avfilter_unref_buffer(buf); - + break; + case AVMEDIA_TYPE_AUDIO: + avfilter_filter_samples(link, avfilter_ref_buffer(buf, ~0)); + break; + default: + return AVERROR(ENOSYS); + } return 0; } @@ -279,13 +381,216 @@ static int poll_frame(AVFilterLink *link) return size/sizeof(AVFilterBufferRef*); } +static void buf_free(AVFilterBuffer *ptr) +{ + av_free(ptr); + return; +} + +static void set_link_source(AVFilterContext *src, AVFilterLink *link) +{ + link->src = src; + link->srcpad = &(src->output_pads[0]); + src->outputs[0] = link; +} + +static int reconfigure_filter(BufferSourceContext *abuffer, AVFilterContext *filt_ctx) +{ + int ret; + AVFilterLink * const inlink = filt_ctx->inputs[0]; + AVFilterLink * const outlink = filt_ctx->outputs[0]; + + inlink->format = abuffer->sample_format; + inlink->channel_layout = abuffer->channel_layout; + inlink->planar = abuffer->packing_format; + inlink->sample_rate = abuffer->sample_rate; + + filt_ctx->filter->uninit(filt_ctx); + memset(filt_ctx->priv, 0, filt_ctx->filter->priv_size); + if ((ret = filt_ctx->filter->init(filt_ctx, NULL , NULL)) < 0) + return ret; + if ((ret = inlink->srcpad->config_props(inlink)) < 0) + return ret; + return outlink->srcpad->config_props(outlink); +} + +static int insert_filter(BufferSourceContext *abuffer, + AVFilterLink *link, AVFilterContext **filt_ctx, + const char *filt_name) +{ + int ret; + + if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0) + return ret; + + link->src->outputs[0] = NULL; + if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) { + link->src->outputs[0] = link; + return ret; + } + + set_link_source(*filt_ctx, link); + + if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) { + avfilter_free(*filt_ctx); + return ret; + } + + return 0; +} + +static void remove_filter(AVFilterContext **filt_ctx) +{ + AVFilterLink *outlink = (*filt_ctx)->outputs[0]; + AVFilterContext *src = (*filt_ctx)->inputs[0]->src; + + (*filt_ctx)->outputs[0] = NULL; + avfilter_free(*filt_ctx); + *filt_ctx = NULL; + + set_link_source(src, outlink); +} + +static inline void log_input_change(void *ctx, AVFilterLink *link, AVFilterBufferRef *ref) +{ + char old_layout_str[16], new_layout_str[16]; + av_get_channel_layout_string(old_layout_str, sizeof(old_layout_str), + -1, link->channel_layout); + av_get_channel_layout_string(new_layout_str, sizeof(new_layout_str), + -1, ref->audio->channel_layout); + av_log(ctx, AV_LOG_INFO, + "Audio input format changed: " + "%s:%s:%d -> %s:%s:%d, normalizing\n", + av_get_sample_fmt_name(link->format), + old_layout_str, (int)link->sample_rate, + av_get_sample_fmt_name(ref->format), + new_layout_str, ref->audio->sample_rate); +} + +int av_asrc_buffer_add_audio_buffer_ref(AVFilterContext *ctx, + AVFilterBufferRef *samplesref, + int av_unused flags) +{ + BufferSourceContext *abuffer = ctx->priv; + AVFilterLink *link; + int ret, logged = 0; + + if (av_fifo_space(abuffer->fifo) < sizeof(samplesref)) { + av_log(ctx, AV_LOG_ERROR, + "Buffering limit reached. Please consume some available frames " + "before adding new ones.\n"); + return AVERROR(EINVAL); + } + + // Normalize input + + link = ctx->outputs[0]; + if (samplesref->audio->sample_rate != link->sample_rate) { + + log_input_change(ctx, link, samplesref); + logged = 1; + + abuffer->sample_rate = samplesref->audio->sample_rate; + + if (!abuffer->aresample) { + ret = insert_filter(abuffer, link, &abuffer->aresample, "aresample"); + if (ret < 0) return ret; + } else { + link = abuffer->aresample->outputs[0]; + if (samplesref->audio->sample_rate == link->sample_rate) + remove_filter(&abuffer->aresample); + else + if ((ret = reconfigure_filter(abuffer, abuffer->aresample)) < 0) + return ret; + } + } + + link = ctx->outputs[0]; + if (samplesref->format != link->format || + samplesref->audio->channel_layout != link->channel_layout || + samplesref->audio->planar != link->planar) { + + if (!logged) log_input_change(ctx, link, samplesref); + + abuffer->sample_format = samplesref->format; + abuffer->channel_layout = samplesref->audio->channel_layout; + abuffer->packing_format = samplesref->audio->planar; + + if (!abuffer->aconvert) { + ret = insert_filter(abuffer, link, &abuffer->aconvert, "aconvert"); + if (ret < 0) return ret; + } else { + link = abuffer->aconvert->outputs[0]; + if (samplesref->format == link->format && + samplesref->audio->channel_layout == link->channel_layout && + samplesref->audio->planar == link->planar + ) + remove_filter(&abuffer->aconvert); + else + if ((ret = reconfigure_filter(abuffer, abuffer->aconvert)) < 0) + return ret; + } + } + + if (sizeof(samplesref) != av_fifo_generic_write(abuffer->fifo, &samplesref, + sizeof(samplesref), NULL)) { + av_log(ctx, AV_LOG_ERROR, "Error while writing to FIFO\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +int av_asrc_buffer_add_samples(AVFilterContext *ctx, + uint8_t *data[8], int linesize[8], + int nb_samples, int sample_rate, + int sample_fmt, int64_t channel_layout, int planar, + int64_t pts, int av_unused flags) +{ + AVFilterBufferRef *samplesref; + + samplesref = avfilter_get_audio_buffer_ref_from_arrays( + data, linesize, AV_PERM_WRITE, + nb_samples, + sample_fmt, channel_layout, planar); + if (!samplesref) + return AVERROR(ENOMEM); + + samplesref->buf->free = buf_free; + samplesref->pts = pts; + samplesref->audio->sample_rate = sample_rate; + + return av_asrc_buffer_add_audio_buffer_ref(ctx, samplesref, 0); +} + +int av_asrc_buffer_add_buffer(AVFilterContext *ctx, + uint8_t *buf, int buf_size, int sample_rate, + int sample_fmt, int64_t channel_layout, int planar, + int64_t pts, int av_unused flags) +{ + uint8_t *data[8] = {0}; + int linesize[8]; + int nb_channels = av_get_channel_layout_nb_channels(channel_layout), + nb_samples = buf_size / nb_channels / av_get_bytes_per_sample(sample_fmt); + + av_samples_fill_arrays(data, linesize, + buf, nb_channels, nb_samples, + sample_fmt, 16); + + return av_asrc_buffer_add_samples(ctx, + data, linesize, nb_samples, + sample_rate, + sample_fmt, channel_layout, planar, + pts, flags); +} + AVFilter avfilter_vsrc_buffer = { .name = "buffer", .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."), .priv_size = sizeof(BufferSourceContext), - .query_formats = query_formats, + .query_formats = query_formats_video, - .init = init, + .init = init_video, .uninit = uninit, .inputs = (const AVFilterPad[]) {{ .name = NULL }}, @@ -293,6 +598,28 @@ AVFilter avfilter_vsrc_buffer = { .type = AVMEDIA_TYPE_VIDEO, .request_frame = request_frame, .poll_frame = poll_frame, - .config_props = config_props, }, + .config_props = config_output_video, }, { .name = NULL}}, }; + +#ifdef CONFIG_ABUFFER_FILTER + +AVFilter avfilter_asrc_abuffer = { + .name = "abuffer", + .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."), + .priv_size = sizeof(BufferSourceContext), + .query_formats = query_formats_audio, + + .init = init_audio, + .uninit = uninit, + + .inputs = (const AVFilterPad[]) {{ .name = NULL }}, + .outputs = (const AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .request_frame = request_frame, + .poll_frame = poll_frame, + .config_props = config_output_audio, }, + { .name = NULL}}, +}; + +#endif -- 2.11.0