[FFmpeg-devel] [PATCH] New p2p mode for showwaves filter

Paul B Mahol onemda at gmail.com
Sun Aug 3 10:00:00 CEST 2014


On Thu, Jul 31, 2014 at 2:50 PM, mrskman <mrskman at gmail.com> wrote:

> A few months ago I sent this patch and got some comments, which helped me
> to understand how this filter works. Thank you for that and I'm sorry it
> took me so long to reply. Here is a better version (atleast for me).
>
> Problem with the current mode=point is, you can get almost invisible wave
> when you set higher resolution output or when there are high amplitudes
> in audio stream.
>
> With this new mode additional points are drawn to make a line between
> points and output is readable regardless of the resolution or amplitudes.
>
> Please review and comment.
>
> ---
>  doc/filters.texi            |    3 +++
>  libavfilter/avf_showwaves.c |   38 +++++++++++++++++++++++++++++++++-----
>  2 files changed, 36 insertions(+), 5 deletions(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index a7919a3..145acbf 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -10698,6 +10698,9 @@ Draw a point for each sample.
>
>  @item line
>  Draw a vertical line for each sample.
> +
> + at item p2p
> +Draw a point for each sample and a line between them.
>  @end table
>
>  Default value is @code{point}.
> diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c
> index 0b45bd0..48e61d1 100644
> --- a/libavfilter/avf_showwaves.c
> +++ b/libavfilter/avf_showwaves.c
> @@ -35,6 +35,7 @@
>  enum ShowWavesMode {
>      MODE_POINT,
>      MODE_LINE,
> +    MODE_P2P,
>      MODE_NB,
>  };
>
> @@ -43,6 +44,8 @@ typedef struct {
>      int w, h;
>      AVRational rate;
>      int buf_idx;
> +    int *buf_idy;    /* y coordinate of previous sample for each channel
> */
> +    int nb_channels;
>

This change is not needed.


>      AVFrame *outpicref;
>      int req_fullfilled;
>      int n;
> @@ -59,6 +62,7 @@ static const AVOption showwaves_options[] = {
>      { "mode", "select display mode", OFFSET(mode), AV_OPT_TYPE_INT,
> {.i64=MODE_POINT}, 0, MODE_NB-1, FLAGS, "mode"},
>          { "point", "draw a point for each sample", 0, AV_OPT_TYPE_CONST,
> {.i64=MODE_POINT}, .flags=FLAGS, .unit="mode"},
>          { "line",  "draw a line for each sample",  0, AV_OPT_TYPE_CONST,
> {.i64=MODE_LINE},  .flags=FLAGS, .unit="mode"},
> +        { "p2p", "draw a line between samples", 0, AV_OPT_TYPE_CONST,
> {.i64=MODE_P2P}, .flags=FLAGS, .unit="mode"},
>      { "n",    "set how many samples to show in the same point",
> OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS },
>      { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE,
> {.str = "25"}, 0, 0, FLAGS },
>      { "r",    "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE,
> {.str = "25"}, 0, 0, FLAGS },
> @@ -72,6 +76,8 @@ static av_cold void uninit(AVFilterContext *ctx)
>      ShowWavesContext *showwaves = ctx->priv;
>
>      av_frame_free(&showwaves->outpicref);
> +    if (showwaves->buf_idy)
> +        av_freep(showwaves->buf_idy);
>  }
>
>  static int query_formats(AVFilterContext *ctx)
> @@ -110,6 +116,7 @@ static int query_formats(AVFilterContext *ctx)
>
>  static int config_output(AVFilterLink *outlink)
>  {
> +    int i;
>      AVFilterContext *ctx = outlink->src;
>      AVFilterLink *inlink = ctx->inputs[0];
>      ShowWavesContext *showwaves = ctx->priv;
> @@ -117,7 +124,14 @@ static int config_output(AVFilterLink *outlink)
>      if (!showwaves->n)
>          showwaves->n = FFMAX(1, ((double)inlink->sample_rate /
> (showwaves->w * av_q2d(showwaves->rate))) + 0.5);
>
> +    showwaves->nb_channels = inlink->channels;
>      showwaves->buf_idx = 0;
> +    if (!(showwaves->buf_idy = av_malloc_array(showwaves->nb_channels,
> 1))) {
> +        av_log(NULL, AV_LOG_ERROR, "Could not allocate showwaves
> buffer\n");
> +        return AVERROR(ENOMEM);
> +    }
> +    for (i = 0; i <= showwaves->nb_channels; i++)
> +        showwaves->buf_idy[i] = 0;
>      outlink->w = showwaves->w;
>      outlink->h = showwaves->h;
>      outlink->sample_aspect_ratio = (AVRational){1,1};
> @@ -133,12 +147,14 @@ static int config_output(AVFilterLink *outlink)
>  inline static int push_frame(AVFilterLink *outlink)
>  {
>      ShowWavesContext *showwaves = outlink->src->priv;
> -    int ret;
> +    int ret, i;
>
>      if ((ret = ff_filter_frame(outlink, showwaves->outpicref)) >= 0)
>          showwaves->req_fullfilled = 1;
>      showwaves->outpicref = NULL;
>      showwaves->buf_idx = 0;
> +    for (i = 0; i <= showwaves->nb_channels; i++)
> +        showwaves->buf_idy[i] = 0;
>      return ret;
>  }
>
> @@ -169,10 +185,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *insamples)
>      AVFrame *outpicref = showwaves->outpicref;
>      int linesize = outpicref ? outpicref->linesize[0] : 0;
>      int16_t *p = (int16_t *)insamples->data[0];
> -    int nb_channels = inlink->channels;
>      int i, j, k, h, ret = 0;
>      const int n = showwaves->n;
> -    const int x = 255 / (nb_channels * n); /* multiplication factor,
> pre-computed to avoid in-loop divisions */
> +    const int x = 255 / (showwaves->nb_channels * n); /* multiplication
> factor, pre-computed to avoid in-loop divisions */
>
>      /* draw data in the buffer */
>      for (i = 0; i < nb_samples; i++) {
> @@ -184,14 +199,14 @@ static int filter_frame(AVFilterLink *inlink,
> AVFrame *insamples)
>              outpicref->width  = outlink->w;
>              outpicref->height = outlink->h;
>              outpicref->pts = insamples->pts +
> -                             av_rescale_q((p - (int16_t
> *)insamples->data[0]) / nb_channels,
> +                             av_rescale_q((p - (int16_t
> *)insamples->data[0]) / showwaves->nb_channels,
>                                            (AVRational){ 1,
> inlink->sample_rate },
>                                            outlink->time_base);
>              linesize = outpicref->linesize[0];
>              for (j = 0; j < outlink->h; j++)
>                  memset(outpicref->data[0] + j * linesize, 0, outlink->w);
>          }
> -        for (j = 0; j < nb_channels; j++) {
> +        for (j = 0; j < showwaves->nb_channels; j++) {
>              h = showwaves->h/2 - av_rescale(*p++, showwaves->h/2,
> MAX_INT16);
>              switch (showwaves->mode) {
>              case MODE_POINT:
> @@ -207,7 +222,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *insamples)
>                      *(outpicref->data[0] + showwaves->buf_idx + k *
> linesize) += x;
>                  break;
>              }
> +            case MODE_P2P:
> +                if (h >= 0 && h < outlink->h) {
> +                    *(outpicref->data[0] + showwaves->buf_idx + h *
> linesize) += x;
> +                    if (showwaves->buf_idy[j] && h !=
> showwaves->buf_idy[j]) {
> +                        int start = showwaves->buf_idy[j], end =
> av_clip(h, 0, outlink->h-1);
> +                        if (start > end) FFSWAP(int16_t, start, end);
> +                        for (k = start + 1; k < end; k++)
> +                            *(outpicref->data[0] + showwaves->buf_idx + k
> * linesize) += x;
> +                    }
> +                }
> +                break;
>              }
> +            /* store current y coordinate for this channel */
> +            showwaves->buf_idy[j] = h;
>          }
>
>          showwaves->sample_count_mod++;
> --
> 1.7.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


More information about the ffmpeg-devel mailing list