Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-05-11 00:41:29 +0400
committerMichael Niedermayer <michaelni@gmx.at>2012-05-11 01:30:42 +0400
commit015903294ca983f007ab5cae098a54013e77f2f6 (patch)
tree66838f53dca82964270a1938692489c36e1fb1b0 /libavfilter/audio.c
parent2a793ff2bf2197f36db3bf296668d44915142d03 (diff)
parent110d0cdc9d1ec414a658f841a3fbefbf6f796d61 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (25 commits) rv40dsp x86: MMX/MMX2/3DNow/SSE2/SSSE3 implementations of MC ape: Use unsigned integer maths arm: dsputil: fix overreads in put/avg_pixels functions h264: K&R formatting cosmetics for header files (part II/II) h264: K&R formatting cosmetics for header files (part I/II) rtmp: Implement check bandwidth notification. rtmp: Support 'rtmp_swfurl', an option which specifies the URL of the SWF player. rtmp: Support 'rtmp_flashver', an option which overrides the version of the Flash plugin. rtmp: Support 'rtmp_tcurl', an option which overrides the URL of the target stream. cmdutils: Add fallback case to switch in check_stream_specifier(). sctp: be consistent with socket option level configure: Add _XOPEN_SOURCE=600 to Solaris preprocessor flags. vcr1enc: drop pointless empty encode_init() wrapper function vcr1: drop pointless write-only AVCodecContext member from VCR1Context vcr1: group encoder code together to save #ifdefs vcr1: cosmetics: K&R prettyprinting, typos, parentheses, dead code, comments mov: make one comment slightly more specific lavr: replace the SSE version of ff_conv_fltp_to_flt_6ch() with SSE4 and AVX lavfi: move audio-related functions to a separate file. lavfi: remove some audio-related function from public API. ... Conflicts: cmdutils.c libavcodec/h264.h libavcodec/h264_mvpred.h libavcodec/vcr1.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/defaults.c libavfilter/internal.h Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavfilter/audio.c')
-rw-r--r--libavfilter/audio.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/libavfilter/audio.c b/libavfilter/audio.c
new file mode 100644
index 0000000000..31f6796437
--- /dev/null
+++ b/libavfilter/audio.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) Stefano Sabatini | stefasab at gmail.com
+ * Copyright (c) S.N. Hemanth Meenakshisundaram | smeenaks at ucsd.edu
+ *
+ * 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
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/audioconvert.h"
+
+#include "audio.h"
+#include "avfilter.h"
+#include "internal.h"
+
+AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms,
+ int nb_samples)
+{
+ return ff_get_audio_buffer(link->dst->outputs[0], perms, nb_samples);
+}
+
+AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms,
+ int nb_samples)
+{
+ AVFilterBufferRef *samplesref = NULL;
+ int linesize[8] = {0};
+ uint8_t *data[8] = {0};
+ int ch, nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+
+ /* right now we don't support more than 8 channels */
+ av_assert0(nb_channels <= 8);
+
+ /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */
+ if (av_samples_alloc(data, linesize,
+ nb_channels, nb_samples,
+ av_get_alt_sample_fmt(link->format, link->planar),
+ 16) < 0)
+ return NULL;
+
+ for (ch = 1; link->planar && ch < nb_channels; ch++)
+ linesize[ch] = linesize[0];
+ samplesref =
+ avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms,
+ nb_samples, link->format,
+ link->channel_layout, link->planar);
+ if (!samplesref) {
+ av_free(data[0]);
+ return NULL;
+ }
+
+ return samplesref;
+}
+
+static AVFilterBufferRef *ff_default_get_audio_buffer_alt(AVFilterLink *link, int perms,
+ int nb_samples)
+{
+ AVFilterBufferRef *samplesref = NULL;
+ uint8_t **data;
+ int planar = av_sample_fmt_is_planar(link->format);
+ int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ int planes = planar ? nb_channels : 1;
+ int linesize;
+
+ if (!(data = av_mallocz(sizeof(*data) * planes)))
+ goto fail;
+
+ if (av_samples_alloc(data, &linesize, nb_channels, nb_samples, link->format, 0) < 0)
+ goto fail;
+
+ samplesref = avfilter_get_audio_buffer_ref_from_arrays_alt(data, linesize, perms,
+ nb_samples, link->format,
+ link->channel_layout);
+ if (!samplesref)
+ goto fail;
+
+ av_freep(&data);
+
+fail:
+ if (data)
+ av_freep(&data[0]);
+ av_freep(&data);
+ return samplesref;
+}
+
+AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
+ int nb_samples)
+{
+ AVFilterBufferRef *ret = NULL;
+
+ if (link->dstpad->get_audio_buffer)
+ ret = link->dstpad->get_audio_buffer(link, perms, nb_samples);
+
+ if (!ret)
+ ret = ff_default_get_audio_buffer(link, perms, nb_samples);
+
+ if (ret)
+ ret->type = AVMEDIA_TYPE_AUDIO;
+
+ return ret;
+}
+
+AVFilterBufferRef *
+avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms,
+ int nb_samples, enum AVSampleFormat sample_fmt,
+ uint64_t channel_layout, int planar)
+{
+ AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer));
+ AVFilterBufferRef *samplesref = av_mallocz(sizeof(AVFilterBufferRef));
+
+ if (!samples || !samplesref)
+ goto fail;
+
+ samplesref->buf = samples;
+ samplesref->buf->free = ff_avfilter_default_free_buffer;
+ if (!(samplesref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps))))
+ goto fail;
+
+ samplesref->audio->nb_samples = nb_samples;
+ samplesref->audio->channel_layout = channel_layout;
+ samplesref->audio->planar = planar;
+
+ /* make sure the buffer gets read permission or it's useless for output */
+ samplesref->perms = perms | AV_PERM_READ;
+
+ samples->refcount = 1;
+ samplesref->type = AVMEDIA_TYPE_AUDIO;
+ samplesref->format = sample_fmt;
+
+ memcpy(samples->data, data, sizeof(samples->data));
+ memcpy(samples->linesize, linesize, sizeof(samples->linesize));
+ memcpy(samplesref->data, data, sizeof(samplesref->data));
+ memcpy(samplesref->linesize, linesize, sizeof(samplesref->linesize));
+
+ return samplesref;
+
+fail:
+ if (samplesref && samplesref->audio)
+ av_freep(&samplesref->audio);
+ av_freep(&samplesref);
+ av_freep(&samples);
+ return NULL;
+}
+
+AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays_alt(uint8_t **data,
+ int linesize,int perms,
+ int nb_samples,
+ enum AVSampleFormat sample_fmt,
+ uint64_t channel_layout)
+{
+ int planes;
+ AVFilterBuffer *samples = av_mallocz(sizeof(*samples));
+ AVFilterBufferRef *samplesref = av_mallocz(sizeof(*samplesref));
+
+ if (!samples || !samplesref)
+ goto fail;
+
+ samplesref->buf = samples;
+ samplesref->buf->free = ff_avfilter_default_free_buffer;
+ if (!(samplesref->audio = av_mallocz(sizeof(*samplesref->audio))))
+ goto fail;
+
+ 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;
+
+ /* make sure the buffer gets read permission or it's useless for output */
+ samplesref->perms = perms | AV_PERM_READ;
+
+ samples->refcount = 1;
+ samplesref->type = AVMEDIA_TYPE_AUDIO;
+ samplesref->format = sample_fmt;
+
+ memcpy(samples->data, data,
+ FFMIN(FF_ARRAY_ELEMS(samples->data), planes)*sizeof(samples->data[0]));
+ memcpy(samplesref->data, samples->data, sizeof(samples->data));
+
+ samples->linesize[0] = samplesref->linesize[0] = linesize;
+
+ if (planes > FF_ARRAY_ELEMS(samples->data)) {
+ samples-> extended_data = av_mallocz(sizeof(*samples->extended_data) *
+ planes);
+ samplesref->extended_data = av_mallocz(sizeof(*samplesref->extended_data) *
+ planes);
+
+ if (!samples->extended_data || !samplesref->extended_data)
+ goto fail;
+
+ memcpy(samples-> extended_data, data, sizeof(*data)*planes);
+ memcpy(samplesref->extended_data, data, sizeof(*data)*planes);
+ } else {
+ samples->extended_data = samples->data;
+ samplesref->extended_data = samplesref->data;
+ }
+
+ return samplesref;
+
+fail:
+ if (samples && samples->extended_data != samples->data)
+ av_freep(&samples->extended_data);
+ if (samplesref) {
+ av_freep(&samplesref->audio);
+ if (samplesref->extended_data != samplesref->data)
+ av_freep(&samplesref->extended_data);
+ }
+ av_freep(&samplesref);
+ av_freep(&samples);
+ 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)
+{
+ AVFilterLink *outlink = NULL;
+
+ if (inlink->dst->output_count)
+ 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;
+}
+
+void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
+{
+ void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
+ AVFilterPad *dst = link->dstpad;
+ int64_t pts;
+
+ FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1);
+
+ if (!(filter_samples = dst->filter_samples))
+ filter_samples = ff_default_filter_samples;
+
+ /* prepare to copy the samples if the buffer has insufficient permissions */
+ if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
+ dst->rej_perms & samplesref->perms) {
+ int i, planar = av_sample_fmt_is_planar(samplesref->format);
+ int planes = !planar ? 1:
+ av_get_channel_layout_nb_channels(samplesref->audio->channel_layout);
+
+ av_log(link->dst, AV_LOG_DEBUG,
+ "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;
+
+ /* Copy actual data into new samples buffer */
+ for (i = 0; samplesref->data[i] && i < 8; i++)
+ memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]);
+ for (i = 0; i < planes; i++)
+ memcpy(link->cur_buf->extended_data[i], samplesref->extended_data[i], samplesref->linesize[0]);
+
+ avfilter_unref_buffer(samplesref);
+ } else
+ link->cur_buf = samplesref;
+
+ pts = link->cur_buf->pts;
+ filter_samples(link, link->cur_buf);
+ ff_update_link_current_pts(link, pts);
+}