[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