[FFmpeg-devel] [PATCH] lavfi audio framework
Stefano Sabatini
stefano.sabatini-lala
Fri Jul 30 10:29:51 CEST 2010
On date Thursday 2010-07-22 01:18:36 -0700, S.N. Hemanth Meenakshisundaram encoded:
>
> This is the lavfi audio framework patch minus the AVFilterBuffer
> resizing. The resizing + its fix for video buffer is in the patch sent
> out earlier and it precedes this one. Once both are applied, this patch
> also passes make lavfitest and make test now.
>
> ---
> libavfilter/avfilter.c | 70 +++++++++++++++++++++++++
> libavfilter/avfilter.h | 136 +++++++++++++++++++++++++++++++++++++++++++----
> libavfilter/defaults.c | 94 +++++++++++++++++++++++++++++++++
> libavfilter/formats.c | 3 +-
> 4 files changed, 290 insertions(+), 13 deletions(-)
>
>
>
> diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
> index 3787ba2..c6c59c9 100644
> --- a/libavfilter/avfilter.c
> +++ b/libavfilter/avfilter.c
> @@ -53,6 +53,15 @@ AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask)
> return ret;
> }
>
> +AVFilterSamplesRef *avfilter_ref_samples(AVFilterSamplesRef *ref, int pmask)
> +{
> + AVFilterSamplesRef *ret = av_malloc(sizeof(AVFilterSamplesRef));
> + *ret = *ref;
> + ret->perms &= pmask;
> + ret->samples->refcount++;
> + return ret;
> +}
> +
> void avfilter_unref_pic(AVFilterPicRef *ref)
> {
> if(!(--ref->pic->refcount))
> @@ -60,6 +69,13 @@ void avfilter_unref_pic(AVFilterPicRef *ref)
> av_free(ref);
> }
>
> +void avfilter_unref_samples(AVFilterSamplesRef *ref)
> +{
> + if(!(--ref->samples->refcount))
> + ref->samples->free(ref->samples);
> + av_free(ref);
> +}
nit: if_(, here and below.
> +
> void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off,
> AVFilterPad **pads, AVFilterLink ***links,
> AVFilterPad *newpad)
> @@ -212,6 +228,20 @@ AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w,
> return ret;
> }
>
> +AVFilterSamplesRef *avfilter_get_samples_ref(AVFilterLink *link, int perms, int size,
> + int64_t channel_layout, enum SampleFormat sample_fmt, int planar)
> +{
> + AVFilterSamplesRef *ret = NULL;
> +
> + if(link_dpad(link).get_samples_ref)
> + ret = link_dpad(link).get_samples_ref(link, perms, size, channel_layout, sample_fmt, planar);
> +
> + if(!ret)
> + ret = avfilter_default_get_samples_ref(link, perms, size, channel_layout, sample_fmt, planar);
> +
> + return ret;
> +}
> +
> int avfilter_request_frame(AVFilterLink *link)
> {
> DPRINTF_START(NULL, request_frame); dprintf_link(NULL, link, 1);
> @@ -332,6 +362,46 @@ void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
> draw_slice(link, y, h, slice_dir);
> }
>
> +void avfilter_filter_samples(AVFilterLink *link, AVFilterSamplesRef *samplesref)
> +{
> + void (*filter_samples)(AVFilterLink *, AVFilterSamplesRef *);
> + AVFilterPad *dst = &link_dpad(link);
> +
> + if (!(filter_samples = dst->filter_samples))
> + filter_samples = avfilter_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) {
> + unsigned int i, num_channels, copy_size;
> +
> + av_log(link->dst, AV_LOG_INFO,
> + "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n",
> + samplesref->perms, link_dpad(link).min_perms, link_dpad(link).rej_perms);
> +
> + link->cur_samples = avfilter_default_get_samples_ref(link, dst->min_perms,
> + samplesref->size, samplesref->channel_layout,
> + samplesref->sample_fmt, samplesref->planar);
> + link->cur_samples->pts = samplesref->pts;
> + link->cur_samples->sample_rate = samplesref->sample_rate;
> +
> + /* Copy actual data into new samples buffer */
> +
> + /* FIXME: Need to use hamming weight count function instead once libavutil has the required function */
> + num_channels = avcodec_channel_layout_num_channels(samplesref->channel_layout);
> + copy_size = samplesref->size/num_channels;
> +
> + for (i = 0; i < num_channels; i++)
> + memcpy(link->cur_samples->data[i], samplesref->data[i], copy_size);
> +
> + avfilter_unref_samples(samplesref);
> + }
> + else
> + link->cur_samples = samplesref;
> +
> + filter_samples(link, link->cur_samples);
> +}
> +
> #define MAX_REGISTERED_AVFILTERS_NB 64
>
> static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1];
> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
> index a9bec02..faeb3b6 100644
> --- a/libavfilter/avfilter.h
> +++ b/libavfilter/avfilter.h
> @@ -38,6 +38,7 @@
>
> #include <stddef.h>
> #include "libavcodec/avcodec.h"
> +#include "libavcodec/audioconvert.h"
>
> /**
> * Return the LIBAVFILTER_VERSION_INT constant.
> @@ -66,7 +67,7 @@ typedef struct AVFilterPad AVFilterPad;
> */
> typedef struct AVFilterBuffer
> {
> - uint8_t *data[8]; ///< buffer data for each plane
> + uint8_t *data[8]; ///< buffer data for each plane/channel
> int linesize[8]; ///< number of bytes per line
> int format; ///< media format
>
> @@ -130,6 +131,32 @@ static inline void avfilter_copy_picref_props(AVFilterPicRef *dst, AVFilterPicRe
> }
>
> /**
> + * A reference to an AVFilterBuffer for audio. Since filters can manipulate the
> + * origin of an audio buffer to, for example, reduce precision without any memcpy,
> + * sample format and channel_layout are per-reference properties. Sample step is
> + * also useful when reducing the number of channels, etc, and so is also per-reference.
> + */
> +typedef struct AVFilterSamplesRef
> +{
> + AVFilterBuffer *samples; ///< the audio buffer that this is a reference to
> + uint8_t *data[8]; ///< audio data for each channel
> + int linesize[8]; ///< number of bytes to next sample
> + int64_t pts; ///< presentation timestamp in units of 1/AV_TIME_BASE
> +
> + int64_t channel_layout; ///< channel layout of current buffer
> + int64_t sample_rate; ///< samples per second
> + enum SampleFormat sample_fmt; ///< sample format
> +
> + int samples_nb; ///< number of samples in this buffer
> + /* Should this go here or in the AVFilterBuffer struct? */
> + int size; ///< size of buffer
> +
> + int perms; ///< permissions
> +
> + int planar; ///< is buffer planar or packed
> +} AVFilterSamplesRef;
The alternative here if we don't want to duplicate the generic fields:
AVFilterBuffer -> actually contains the data
AVFilterBufferRef[erence] in place of AVFilterSamplesRef and
AVFilterSamplesPic.
Then we may share the common fields (perms, size, pts, buffer, data,
linesize), use a media type field and put the media specific stuff in
an union.
This requires more work to re-adapt the patch, but will avoid evil
code duplication.
Michael?
Same technique may be used for AVFilterLink.
[...]
Regards.
--
FFmpeg = Fundamental Fanciful Mysterious Plastic Erroneous Governor
More information about the ffmpeg-devel
mailing list