Created
January 31, 2013 12:49
-
-
Save anonymous/4682630 to your computer and use it in GitHub Desktop.
stdin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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