X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Faudio.c;h=f3eebbfdaebb46328b628cc8dc2af47dffe45d89;hb=7d1918affee4bc70fb8ac139ba9235e7fed2979b;hp=a6fef9d2739ab9eebc75bc317ea942b651fa05f8;hpb=9cdf74f904f76b2a1da474a2290c7e9ed34dd431;p=ffmpeg diff --git a/libavfilter/audio.c b/libavfilter/audio.c index a6fef9d2739..f3eebbfdaeb 100644 --- a/libavfilter/audio.c +++ b/libavfilter/audio.c @@ -1,21 +1,25 @@ /* - * This file is part of Libav. + * Copyright (c) Stefano Sabatini | stefasab at gmail.com + * Copyright (c) S.N. Hemanth Meenakshisundaram | smeenaks at ucsd.edu * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/audioconvert.h" #include "audio.h" @@ -96,9 +100,9 @@ AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays(uint8_t **data, samplesref->audio->nb_samples = nb_samples; samplesref->audio->channel_layout = channel_layout; - samplesref->audio->planar = av_sample_fmt_is_planar(sample_fmt); - planes = samplesref->audio->planar ? av_get_channel_layout_nb_channels(channel_layout) : 1; + planes = av_sample_fmt_is_planar(sample_fmt) ? + av_get_channel_layout_nb_channels(channel_layout) : 1; /* make sure the buffer gets read permission or it's useless for output */ samplesref->perms = perms | AV_PERM_READ; @@ -146,41 +150,24 @@ fail: return NULL; } -void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) -{ - ff_filter_samples(link->dst->outputs[0], samplesref); -} - -/* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */ -void ff_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) +static int default_filter_samples(AVFilterLink *link, + AVFilterBufferRef *samplesref) { - AVFilterLink *outlink = NULL; - - if (inlink->dst->nb_outputs) - outlink = inlink->dst->outputs[0]; - - if (outlink) { - outlink->out_buf = ff_default_get_audio_buffer(inlink, AV_PERM_WRITE, - samplesref->audio->nb_samples); - outlink->out_buf->pts = samplesref->pts; - outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate; - ff_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0)); - avfilter_unref_buffer(outlink->out_buf); - outlink->out_buf = NULL; - } - avfilter_unref_buffer(samplesref); - inlink->cur_buf = NULL; + return ff_filter_samples(link->dst->outputs[0], samplesref); } -void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) +int ff_filter_samples_framed(AVFilterLink *link, AVFilterBufferRef *samplesref) { - void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); + int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *dst = link->dstpad; + int64_t pts; + AVFilterBufferRef *buf_out; + int ret; - FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); + FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1); if (!(filter_samples = dst->filter_samples)) - filter_samples = ff_default_filter_samples; + filter_samples = default_filter_samples; /* prepare to copy the samples if the buffer has insufficient permissions */ if ((dst->min_perms & samplesref->perms) != dst->min_perms || @@ -189,21 +176,70 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n", samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms); - link->cur_buf = ff_default_get_audio_buffer(link, dst->min_perms, - samplesref->audio->nb_samples); - link->cur_buf->pts = samplesref->pts; - link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; + buf_out = ff_default_get_audio_buffer(link, dst->min_perms, + samplesref->audio->nb_samples); + buf_out->pts = samplesref->pts; + buf_out->audio->sample_rate = samplesref->audio->sample_rate; /* Copy actual data into new samples buffer */ - av_samples_copy(link->cur_buf->extended_data, samplesref->extended_data, + av_samples_copy(buf_out->extended_data, samplesref->extended_data, 0, 0, samplesref->audio->nb_samples, av_get_channel_layout_nb_channels(link->channel_layout), link->format); avfilter_unref_buffer(samplesref); } else - link->cur_buf = samplesref; + buf_out = samplesref; - filter_samples(link, link->cur_buf); + link->cur_buf = buf_out; + pts = buf_out->pts; + ret = filter_samples(link, buf_out); + ff_update_link_current_pts(link, pts); + return ret; } +int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) +{ + int insamples = samplesref->audio->nb_samples, inpos = 0, nb_samples; + AVFilterBufferRef *pbuf = link->partial_buf; + int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); + int ret = 0; + + if (!link->min_samples || + (!pbuf && + insamples >= link->min_samples && insamples <= link->max_samples)) { + return ff_filter_samples_framed(link, samplesref); + } + /* Handle framing (min_samples, max_samples) */ + while (insamples) { + if (!pbuf) { + AVRational samples_tb = { 1, link->sample_rate }; + int perms = link->dstpad->min_perms | AV_PERM_WRITE; + pbuf = ff_get_audio_buffer(link, perms, link->partial_buf_size); + if (!pbuf) { + av_log(link->dst, AV_LOG_WARNING, + "Samples dropped due to memory allocation failure.\n"); + return 0; + } + avfilter_copy_buffer_ref_props(pbuf, samplesref); + pbuf->pts = samplesref->pts + + av_rescale_q(inpos, samples_tb, link->time_base); + pbuf->audio->nb_samples = 0; + } + nb_samples = FFMIN(insamples, + link->partial_buf_size - pbuf->audio->nb_samples); + av_samples_copy(pbuf->extended_data, samplesref->extended_data, + pbuf->audio->nb_samples, inpos, + nb_samples, nb_channels, link->format); + inpos += nb_samples; + insamples -= nb_samples; + pbuf->audio->nb_samples += nb_samples; + if (pbuf->audio->nb_samples >= link->min_samples) { + ret = ff_filter_samples_framed(link, pbuf); + pbuf = NULL; + } + } + avfilter_unref_buffer(samplesref); + link->partial_buf = pbuf; + return ret; +}