Skip to content

Instantly share code, notes, and snippets.

Created January 31, 2013 12:49
Show Gist options
  • Save anonymous/4682630 to your computer and use it in GitHub Desktop.
Save anonymous/4682630 to your computer and use it in GitHub Desktop.
stdin
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c
index 21c9561..58b544a 100644
--- a/libavfilter/avf_showspectrum.c
+++ b/libavfilter/avf_showspectrum.c
@@ -38,8 +38,9 @@ typedef struct {
AVFilterBufferRef *outpicref;
int req_fullfilled;
int nb_display_channels;
- int compat; ///< use old up to 2 channels display mode
int sliding; ///< 1 if sliding mode, 0 otherwise
+ int combined; ///< use old-style combined channel display mode
+ float saturation; ///< color saturation multiplier
int xpos; ///< x position (current column)
RDFTContext *rdft; ///< Real Discrete Fourier Transform context
int rdft_bits; ///< number of bits (RDFT window size = 1<<rdft_bits)
@@ -47,6 +48,7 @@ typedef struct {
int filled; ///< number of samples (per channel) filled in current rdft_buffer
int consumed; ///< number of samples (per channel) consumed from the input frame
float *window_func_lut; ///< Window function LUT
+ float *combine_buffer; ///< color combining buffer (3 * h items)
} ShowSpectrumContext;
#define OFFSET(x) offsetof(ShowSpectrumContext, x)
@@ -56,7 +58,8 @@ static const AVOption showspectrum_options[] = {
{ "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, FLAGS },
{ "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, FLAGS },
{ "slide", "set sliding mode", OFFSET(sliding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS },
- { "compat", "set compat mode", OFFSET(compat), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS },
+ { "combined", "set combined mode", OFFSET(combined), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS },
+ { "saturation", "color saturation multiplier", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1}, -10, 10, FLAGS },
{ NULL },
};
@@ -96,7 +99,7 @@ static int query_formats(AVFilterContext *ctx)
AVFilterLink *inlink = ctx->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE };
- static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE };
+ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE };
/* set input audio formats */
formats = ff_make_format_list(sample_fmts);
@@ -133,7 +136,7 @@ static int config_output(AVFilterLink *outlink)
outlink->w = showspectrum->w;
outlink->h = showspectrum->h;
- h = showspectrum->compat ? outlink->h: outlink->h / inlink->channels;
+ h = showspectrum->combined ? outlink->h : outlink->h / inlink->channels;
/* RDFT window size (precision) according to the requested output frame height */
for (rdft_bits = 1; 1 << rdft_bits < 2 * h; rdft_bits++);
@@ -154,10 +157,7 @@ static int config_output(AVFilterLink *outlink)
for (i = 0; i < showspectrum->nb_display_channels; i++)
av_freep(&showspectrum->rdft_data[i]);
av_freep(&showspectrum->rdft_data);
- if (showspectrum->compat)
- showspectrum->nb_display_channels = FFMIN(inlink->channels, 2);
- else
- showspectrum->nb_display_channels = inlink->channels;
+ showspectrum->nb_display_channels = inlink->channels;
if (av_size_mult(sizeof(*showspectrum->rdft_data),
showspectrum->nb_display_channels * win_size, &rdft_size) < 0)
@@ -196,6 +196,10 @@ static int config_output(AVFilterLink *outlink)
if (showspectrum->xpos >= outlink->w)
showspectrum->xpos = 0;
+ showspectrum->combine_buffer = av_realloc(showspectrum->combine_buffer,
+ outlink->h * 3 *
+ sizeof(*showspectrum->combine_buffer));
+
av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d RDFT window size:%d\n",
showspectrum->w, showspectrum->h, win_size);
return 0;
@@ -260,6 +264,9 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl
/* complete RDFT window size? */
if (showspectrum->filled == win_size) {
+ /* channel height */
+ int h = showspectrum->combined ? outlink->h : outlink->h / showspectrum->nb_display_channels;
+
/* run RDFT on each samples set */
for (ch = 0; ch < showspectrum->nb_display_channels; ch++)
av_rdft_calc(showspectrum->rdft, showspectrum->rdft_data[ch]);
@@ -269,47 +276,67 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl
#define IM(ch) showspectrum->rdft_data[ch][2*y + 1]
#define MAGNITUDE(re, im) sqrt((re)*(re) + (im)*(im))
- if (showspectrum->compat) {
+ /* initialize buffer for combining to black */
for (y = 0; y < outlink->h; y++) {
- // FIXME: bin[0] contains first and last bins
- uint8_t *p = outpicref->data[0] + (outlink->h - y - 1) * outpicref->linesize[0];
- int a = sqrt(w * MAGNITUDE(RE(0), IM(0)));
- int b = showspectrum->nb_display_channels > 1 ? sqrt(w * MAGNITUDE(RE(1), IM(1))) : a;
-
- if (showspectrum->sliding) {
- memmove(p, p + 3, (outlink->w - 1) * 3);
- p += (outlink->w - 1) * 3;
+ showspectrum->combine_buffer[3*y] = 0;
+ showspectrum->combine_buffer[3*y+1] = 127.5;
+ showspectrum->combine_buffer[3*y+2] = 127.5;
+ }
+
+ for (ch = 0; ch < showspectrum->nb_display_channels; ch++) {
+ float yf, uf, vf;
+
+ /* decide channel colors */
+ if (showspectrum->combined) {
+ yf = 1.0f / showspectrum->nb_display_channels;
+ uf = yf;
+ vf = yf;
} else {
- p += showspectrum->xpos * 3;
+ yf = 1.0f;
+ uf = 0.5f;
+ vf = 0.5f;
+ }
+ if (showspectrum->nb_display_channels >= 2) {
+ uf *= cos((2 * M_PI * ch) / showspectrum->nb_display_channels);
+ vf *= sin((2 * M_PI * ch) / showspectrum->nb_display_channels);
+ } else {
+ uf = 0.0f;
+ vf = 0.0f;
+ }
+ uf *= showspectrum->saturation;
+ vf *= showspectrum->saturation;
+
+ for (y = 0; y < h; y++) {
+ int row = showspectrum->combined ? y : ch * h + y;
+ float *out = &showspectrum->combine_buffer[3 * row];
+ float a = sqrt(w * MAGNITUDE(RE(ch), IM(ch)));
+ out[0] += a * yf;
+ out[1] += a * vf;
+ out[2] += a * uf;
}
-
- a = FFMIN(a, 255);
- b = FFMIN(b, 255);
- p[0] = a;
- p[1] = b;
- p[2] = (a + b) / 2;
}
- } else {
- int h = outlink->h / showspectrum->nb_display_channels;
-
- for (ch = 0; ch < showspectrum->nb_display_channels; ch++) {
- for (y = 0; y < h; y++) {
- uint8_t *p = outpicref->data[0] +
- (outlink->h - (ch * h + y) - 1) *
- outpicref->linesize[0];
- int a = sqrt(w * MAGNITUDE(RE(ch), IM(ch)));
-
- if (showspectrum->sliding) {
- memmove(p, p + 3, (outlink->w - 1) * 3);
- p += (outlink->w - 1) * 3;
- } else {
- p += showspectrum->xpos * 3;
- }
-
- p[0] = p[1] = p[2] = a;
+
+ /* copy to output */
+ if (showspectrum->sliding) {
+ for (ch = 0; ch < 3; ch++) {
+ for (y = 0; y < outlink->h; y++) {
+ uint8_t *p = outpicref->data[ch] +
+ y * outpicref->linesize[ch];
+ memmove(p, p + 1, outlink->w - 1);
}
}
+ showspectrum->xpos = outlink->w - 1;
}
+ for (ch = 0; ch < 3; ch++) {
+ uint8_t *p = outpicref->data[ch] +
+ (outlink->h - 1) * outpicref->linesize[ch] +
+ showspectrum->xpos;
+ for (y = 0; y < outlink->h; y++) {
+ *p = rint(FFMAX(0, FFMIN(showspectrum->combine_buffer[3*y + ch], 255)));
+ p -= outpicref->linesize[ch];
+ }
+ }
+
outpicref->pts = insamples->pts +
av_rescale_q(showspectrum->consumed,
(AVRational){ 1, inlink->sample_rate },
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment