#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "avfilter.h"
+#include "filters.h"
#include "formats.h"
#include "audio.h"
#include "video.h"
DRAW_NB,
};
+enum ShowWavesFilterMode {
+ FILTER_AVERAGE,
+ FILTER_PEAK,
+ FILTER_NB,
+};
+
struct frame_node {
AVFrame *frame;
struct frame_node *next;
int scale; ///< ShowWavesScale
int draw_mode; ///< ShowWavesDrawMode
int split_channels;
+ int filter_mode;
uint8_t *fg;
int (*get_h)(int16_t sample, int height);
/* set input audio formats */
formats = ff_make_format_list(sample_fmts);
- if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0)
+ if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0)
return ret;
layouts = ff_all_channel_layouts();
- if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0)
+ if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0)
return ret;
formats = ff_all_samplerates();
- if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0)
+ if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0)
return ret;
/* set output video format */
formats = ff_make_format_list(pix_fmts);
- if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0)
+ if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0)
return ret;
return 0;
showwaves->n = 1;
if (!showwaves->n)
- showwaves->n = FFMAX(1, ((double)inlink->sample_rate / (showwaves->w * av_q2d(showwaves->rate))) + 0.5);
+ showwaves->n = FFMAX(1, av_rescale_q(inlink->sample_rate, av_make_q(1, showwaves->w), showwaves->rate));
showwaves->buf_idx = 0;
if (!(showwaves->buf_idy = av_mallocz_array(nb_channels, sizeof(*showwaves->buf_idy)))) {
int64_t max_samples = col == outlink->w - 1 ? last_column_samples: column_max_samples;
int ch;
- for (ch = 0; ch < nb_channels; ch++)
- sum[ch] += abs(p[ch + i*nb_channels]) << 1;
+ switch (showwaves->filter_mode) {
+ case FILTER_AVERAGE:
+ for (ch = 0; ch < nb_channels; ch++)
+ sum[ch] += abs(p[ch + i*nb_channels]) << 1;
+ break;
+ case FILTER_PEAK:
+ for (ch = 0; ch < nb_channels; ch++)
+ sum[ch] = FFMAX(sum[ch], abs(p[ch + i*nb_channels]));
+ break;
+ }
+
n++;
if (n == max_samples) {
for (ch = 0; ch < nb_channels; ch++) {
- int16_t sample = sum[ch] / max_samples;
+ int16_t sample = sum[ch] / (showwaves->filter_mode == FILTER_AVERAGE ? max_samples : 1);
uint8_t *buf = out->data[0] + col * pixstep;
int h;
showwaves->sample_count_mod = 0;
showwaves->buf_idx++;
}
- if (showwaves->buf_idx == showwaves->w)
+ if (showwaves->buf_idx == showwaves->w ||
+ (ff_outlink_get_status(inlink) && i == nb_samples - 1))
if ((ret = push_frame(outlink)) < 0)
break;
outpicref = showwaves->outpicref;
return ret;
}
+static int activate(AVFilterContext *ctx)
+{
+ AVFilterLink *inlink = ctx->inputs[0];
+ AVFilterLink *outlink = ctx->outputs[0];
+ ShowWavesContext *showwaves = ctx->priv;
+ AVFrame *in;
+ const int nb_samples = showwaves->n * outlink->w;
+ int ret;
+
+ FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+ ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ return showwaves_filter_frame(inlink, in);
+
+ FF_FILTER_FORWARD_STATUS(inlink, outlink);
+ FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
+ return FFERROR_NOT_READY;
+}
+
static const AVFilterPad showwaves_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_frame = showwaves_filter_frame,
},
{ NULL }
};
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_output,
- .request_frame = request_frame,
},
{ NULL }
};
-AVFilter ff_avf_showwaves = {
+const AVFilter ff_avf_showwaves = {
.name = "showwaves",
.description = NULL_IF_CONFIG_SMALL("Convert input audio to a video output."),
.init = init,
.query_formats = query_formats,
.priv_size = sizeof(ShowWavesContext),
.inputs = showwaves_inputs,
+ .activate = activate,
.outputs = showwaves_outputs,
.priv_class = &showwaves_class,
};
{ "draw", "set draw mode", OFFSET(draw_mode), AV_OPT_TYPE_INT, {.i64 = DRAW_SCALE}, 0, DRAW_NB-1, FLAGS, .unit="draw" },
{ "scale", "scale pixel values for each drawn sample", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_SCALE}, .flags=FLAGS, .unit="draw"},
{ "full", "draw every pixel for sample directly", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_FULL}, .flags=FLAGS, .unit="draw"},
+ { "filter", "set filter mode", OFFSET(filter_mode), AV_OPT_TYPE_INT, {.i64 = FILTER_AVERAGE}, 0, FILTER_NB-1, FLAGS, .unit="filter" },
+ { "average", "use average samples", 0, AV_OPT_TYPE_CONST, {.i64=FILTER_AVERAGE}, .flags=FLAGS, .unit="filter"},
+ { "peak", "use peak samples", 0, AV_OPT_TYPE_CONST, {.i64=FILTER_PEAK}, .flags=FLAGS, .unit="filter"},
{ NULL }
};
{ NULL }
};
-AVFilter ff_avf_showwavespic = {
+const AVFilter ff_avf_showwavespic = {
.name = "showwavespic",
.description = NULL_IF_CONFIG_SMALL("Convert input audio to a video output single picture."),
.init = init,