mirror of https://git.ffmpeg.org/ffmpeg.git
avfilter/avf_showcwt: add bar display support
This commit is contained in:
parent
ca9ec4e7ed
commit
422bfdc4ae
|
@ -96,6 +96,7 @@ typedef struct ShowCWTContext {
|
||||||
AVFrame *ifft_in;
|
AVFrame *ifft_in;
|
||||||
AVFrame *ifft_out;
|
AVFrame *ifft_out;
|
||||||
AVFrame *ch_out;
|
AVFrame *ch_out;
|
||||||
|
AVFrame *bh_out;
|
||||||
int nb_threads;
|
int nb_threads;
|
||||||
int nb_channels;
|
int nb_channels;
|
||||||
int nb_consumed_samples;
|
int nb_consumed_samples;
|
||||||
|
@ -118,6 +119,8 @@ typedef struct ShowCWTContext {
|
||||||
float minimum_frequency;
|
float minimum_frequency;
|
||||||
float maximum_frequency;
|
float maximum_frequency;
|
||||||
float deviation;
|
float deviation;
|
||||||
|
float bar_ratio;
|
||||||
|
int bar_size;
|
||||||
|
|
||||||
AVFloatDSPContext *fdsp;
|
AVFloatDSPContext *fdsp;
|
||||||
} ShowCWTContext;
|
} ShowCWTContext;
|
||||||
|
@ -159,6 +162,7 @@ static const AVOption showcwt_options[] = {
|
||||||
{ "rl", "right to left", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_RL}, 0, 0, FLAGS, "direction" },
|
{ "rl", "right to left", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_RL}, 0, 0, FLAGS, "direction" },
|
||||||
{ "ud", "up to down", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_UD}, 0, 0, FLAGS, "direction" },
|
{ "ud", "up to down", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_UD}, 0, 0, FLAGS, "direction" },
|
||||||
{ "du", "down to up", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_DU}, 0, 0, FLAGS, "direction" },
|
{ "du", "down to up", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_DU}, 0, 0, FLAGS, "direction" },
|
||||||
|
{ "bar", "set bar ratio", OFFSET(bar_ratio), AV_OPT_TYPE_FLOAT, {.dbl = 0.}, 0, 1, FLAGS },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -184,6 +188,7 @@ static av_cold void uninit(AVFilterContext *ctx)
|
||||||
av_frame_free(&s->ifft_in);
|
av_frame_free(&s->ifft_in);
|
||||||
av_frame_free(&s->ifft_out);
|
av_frame_free(&s->ifft_out);
|
||||||
av_frame_free(&s->ch_out);
|
av_frame_free(&s->ch_out);
|
||||||
|
av_frame_free(&s->bh_out);
|
||||||
|
|
||||||
if (s->fft) {
|
if (s->fft) {
|
||||||
for (int n = 0; n < s->nb_threads; n++)
|
for (int n = 0; n < s->nb_threads; n++)
|
||||||
|
@ -315,6 +320,80 @@ static int run_channel_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr, i
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DRAW_BAR_COLOR(x) \
|
||||||
|
do { \
|
||||||
|
if (Y <= ht) { \
|
||||||
|
dstY[x] = 0; \
|
||||||
|
dstU[x] = 128; \
|
||||||
|
dstV[x] = 128; \
|
||||||
|
} else { \
|
||||||
|
float mul = (Y - ht) * bh[0]; \
|
||||||
|
dstY[x] = av_clip_uint8(lrintf(Y * mul * 255.f)); \
|
||||||
|
dstU[x] = av_clip_uint8(lrintf((U-0.5f) * 128.f + 128)); \
|
||||||
|
dstV[x] = av_clip_uint8(lrintf((V-0.5f) * 128.f + 128)); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static void draw_bar(ShowCWTContext *s, int y,
|
||||||
|
float Y, float U, float V)
|
||||||
|
{
|
||||||
|
float *bh = ((float *)s->bh_out->extended_data[0]) + y;
|
||||||
|
const ptrdiff_t ylinesize = s->outpicref->linesize[0];
|
||||||
|
const ptrdiff_t ulinesize = s->outpicref->linesize[1];
|
||||||
|
const ptrdiff_t vlinesize = s->outpicref->linesize[2];
|
||||||
|
const int direction = s->direction;
|
||||||
|
const int bar_size = s->bar_size;
|
||||||
|
const float rcp_bar_h = 1.f / bar_size;
|
||||||
|
uint8_t *dstY, *dstU, *dstV;
|
||||||
|
const int w_1 = s->w - 1;
|
||||||
|
|
||||||
|
bh[0] = 1.f / (Y + 0.0001f);
|
||||||
|
switch (direction) {
|
||||||
|
case DIRECTION_LR:
|
||||||
|
dstY = s->outpicref->data[0] + y * ylinesize;
|
||||||
|
dstU = s->outpicref->data[1] + y * ulinesize;
|
||||||
|
dstV = s->outpicref->data[2] + y * vlinesize;
|
||||||
|
for (int x = 0; x < bar_size; x++) {
|
||||||
|
float ht = (bar_size - x) * rcp_bar_h;
|
||||||
|
DRAW_BAR_COLOR(x);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIRECTION_RL:
|
||||||
|
dstY = s->outpicref->data[0] + y * ylinesize;
|
||||||
|
dstU = s->outpicref->data[1] + y * ulinesize;
|
||||||
|
dstV = s->outpicref->data[2] + y * vlinesize;
|
||||||
|
for (int x = 0; x < bar_size; x++) {
|
||||||
|
float ht = x * rcp_bar_h;
|
||||||
|
DRAW_BAR_COLOR(w_1 - bar_size + x);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIRECTION_UD:
|
||||||
|
dstY = s->outpicref->data[0] + w_1 - y;
|
||||||
|
dstU = s->outpicref->data[1] + w_1 - y;
|
||||||
|
dstV = s->outpicref->data[2] + w_1 - y;
|
||||||
|
for (int x = 0; x < bar_size; x++) {
|
||||||
|
float ht = (bar_size - x) * rcp_bar_h;
|
||||||
|
DRAW_BAR_COLOR(0);
|
||||||
|
dstY += ylinesize;
|
||||||
|
dstU += ulinesize;
|
||||||
|
dstV += vlinesize;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIRECTION_DU:
|
||||||
|
dstY = s->outpicref->data[0] + w_1 - y + ylinesize * (s->h - 1 - bar_size);
|
||||||
|
dstU = s->outpicref->data[1] + w_1 - y + ulinesize * (s->h - 1 - bar_size);
|
||||||
|
dstV = s->outpicref->data[2] + w_1 - y + vlinesize * (s->h - 1 - bar_size);
|
||||||
|
for (int x = 0; x < bar_size; x++) {
|
||||||
|
float ht = x * rcp_bar_h;
|
||||||
|
DRAW_BAR_COLOR(0);
|
||||||
|
dstY += ylinesize;
|
||||||
|
dstU += ulinesize;
|
||||||
|
dstV += vlinesize;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
{
|
{
|
||||||
ShowCWTContext *s = ctx->priv;
|
ShowCWTContext *s = ctx->priv;
|
||||||
|
@ -330,6 +409,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
const int ihop_size = s->ihop_size;
|
const int ihop_size = s->ihop_size;
|
||||||
const int direction = s->direction;
|
const int direction = s->direction;
|
||||||
uint8_t *dstY, *dstU, *dstV, *dstA;
|
uint8_t *dstY, *dstU, *dstV, *dstA;
|
||||||
|
const int bar_size = s->bar_size;
|
||||||
const int mode = s->mode;
|
const int mode = s->mode;
|
||||||
const int w_1 = s->w - 1;
|
const int w_1 = s->w - 1;
|
||||||
const int x = s->pos;
|
const int x = s->pos;
|
||||||
|
@ -414,6 +494,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
dstV[0] = av_clip_uint8(lrintf(V * 255.f));
|
dstV[0] = av_clip_uint8(lrintf(V * 255.f));
|
||||||
if (dstA)
|
if (dstA)
|
||||||
dstA[0] = dstY[0];
|
dstA[0] = dstY[0];
|
||||||
|
|
||||||
|
if (bar_size > 0)
|
||||||
|
draw_bar(s, y, Y, U, V);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -441,6 +524,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
dstV[0] = av_clip_uint8(lrintf(V * 255.f));
|
dstV[0] = av_clip_uint8(lrintf(V * 255.f));
|
||||||
if (dstA)
|
if (dstA)
|
||||||
dstA[0] = dstY[0];
|
dstA[0] = dstY[0];
|
||||||
|
|
||||||
|
if (bar_size > 0)
|
||||||
|
draw_bar(s, y, Y, U, V);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -455,6 +541,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
dstV[0] = av_clip_uint8(lrintf(V * 255.f));
|
dstV[0] = av_clip_uint8(lrintf(V * 255.f));
|
||||||
if (dstA)
|
if (dstA)
|
||||||
dstA[0] = dstY[0];
|
dstA[0] = dstY[0];
|
||||||
|
if (bar_size > 0)
|
||||||
|
draw_bar(s, y, Y, U, V);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
Y = atan2f(src[0].im, src[0].re);
|
Y = atan2f(src[0].im, src[0].re);
|
||||||
|
@ -463,6 +551,8 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
dstY[0] = av_clip_uint8(lrintf(Y * 255.f));
|
dstY[0] = av_clip_uint8(lrintf(Y * 255.f));
|
||||||
if (dstA)
|
if (dstA)
|
||||||
dstA[0] = dstY[0];
|
dstA[0] = dstY[0];
|
||||||
|
if (bar_size > 0)
|
||||||
|
draw_bar(s, y, Y, 0.5f, 0.5f);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
Y = hypotf(src[0].re, src[0].im);
|
Y = hypotf(src[0].re, src[0].im);
|
||||||
|
@ -471,6 +561,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||||
dstY[0] = av_clip_uint8(lrintf(Y * 255.f));
|
dstY[0] = av_clip_uint8(lrintf(Y * 255.f));
|
||||||
if (dstA)
|
if (dstA)
|
||||||
dstA[0] = dstY[0];
|
dstA[0] = dstY[0];
|
||||||
|
|
||||||
|
if (bar_size > 0)
|
||||||
|
draw_bar(s, y, Y, 0.5f, 0.5f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,10 +682,12 @@ static int config_output(AVFilterLink *outlink)
|
||||||
switch (s->direction) {
|
switch (s->direction) {
|
||||||
case DIRECTION_LR:
|
case DIRECTION_LR:
|
||||||
case DIRECTION_RL:
|
case DIRECTION_RL:
|
||||||
|
s->bar_size = s->w * s->bar_ratio;
|
||||||
s->frequency_band_count = s->h;
|
s->frequency_band_count = s->h;
|
||||||
break;
|
break;
|
||||||
case DIRECTION_UD:
|
case DIRECTION_UD:
|
||||||
case DIRECTION_DU:
|
case DIRECTION_DU:
|
||||||
|
s->bar_size = s->h * s->bar_ratio;
|
||||||
s->frequency_band_count = s->w;
|
s->frequency_band_count = s->w;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -651,6 +746,7 @@ static int config_output(AVFilterLink *outlink)
|
||||||
s->kernel_x = av_frame_alloc();
|
s->kernel_x = av_frame_alloc();
|
||||||
s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2);
|
s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2);
|
||||||
s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);
|
s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);
|
||||||
|
s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count);
|
||||||
s->ifft_in = av_frame_alloc();
|
s->ifft_in = av_frame_alloc();
|
||||||
s->ifft_out = av_frame_alloc();
|
s->ifft_out = av_frame_alloc();
|
||||||
s->kernel = av_frame_alloc();
|
s->kernel = av_frame_alloc();
|
||||||
|
@ -658,8 +754,8 @@ static int config_output(AVFilterLink *outlink)
|
||||||
s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));
|
s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));
|
||||||
s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));
|
s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));
|
||||||
if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x ||
|
if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->kernel_x ||
|
||||||
!s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop ||
|
!s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out ||
|
||||||
!s->frequency_band || !s->kernel || !s->cache || !s->index)
|
!s->frequency_band || !s->kernel || !s->cache || !s->index || !s->bh_out)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
s->ifft_in->format = inlink->format;
|
s->ifft_in->format = inlink->format;
|
||||||
|
@ -760,16 +856,16 @@ static int config_output(AVFilterLink *outlink)
|
||||||
|
|
||||||
switch (s->direction) {
|
switch (s->direction) {
|
||||||
case DIRECTION_LR:
|
case DIRECTION_LR:
|
||||||
s->pos = 0;
|
s->pos = s->bar_size;
|
||||||
break;
|
break;
|
||||||
case DIRECTION_RL:
|
case DIRECTION_RL:
|
||||||
s->pos = s->w - 1;
|
s->pos = FFMAX(0, s->w - 2 - s->bar_size);
|
||||||
break;
|
break;
|
||||||
case DIRECTION_UD:
|
case DIRECTION_UD:
|
||||||
s->pos = 0;
|
s->pos = s->bar_size;
|
||||||
break;
|
break;
|
||||||
case DIRECTION_DU:
|
case DIRECTION_DU:
|
||||||
s->pos = s->h - 1;
|
s->pos = FFMAX(0, s->h - 2 - s->bar_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,7 +898,7 @@ static int output_frame(AVFilterContext *ctx)
|
||||||
for (int p = 0; p < nb_planes; p++) {
|
for (int p = 0; p < nb_planes; p++) {
|
||||||
ptrdiff_t linesize = s->outpicref->linesize[p];
|
ptrdiff_t linesize = s->outpicref->linesize[p];
|
||||||
|
|
||||||
for (int y = s->h - 1; y > 0; y--) {
|
for (int y = s->h - 1; y > s->bar_size; y--) {
|
||||||
uint8_t *dst = s->outpicref->data[p] + y * linesize;
|
uint8_t *dst = s->outpicref->data[p] + y * linesize;
|
||||||
|
|
||||||
memmove(dst, dst - linesize, s->w);
|
memmove(dst, dst - linesize, s->w);
|
||||||
|
@ -813,7 +909,7 @@ static int output_frame(AVFilterContext *ctx)
|
||||||
for (int p = 0; p < nb_planes; p++) {
|
for (int p = 0; p < nb_planes; p++) {
|
||||||
ptrdiff_t linesize = s->outpicref->linesize[p];
|
ptrdiff_t linesize = s->outpicref->linesize[p];
|
||||||
|
|
||||||
for (int y = 0; y < s->h - 1; y++) {
|
for (int y = 0; y < s->h - 2 - s->bar_size; y++) {
|
||||||
uint8_t *dst = s->outpicref->data[p] + y * linesize;
|
uint8_t *dst = s->outpicref->data[p] + y * linesize;
|
||||||
|
|
||||||
memmove(dst, dst + linesize, s->w);
|
memmove(dst, dst + linesize, s->w);
|
||||||
|
@ -833,28 +929,28 @@ static int output_frame(AVFilterContext *ctx)
|
||||||
case DIRECTION_LR:
|
case DIRECTION_LR:
|
||||||
s->pos++;
|
s->pos++;
|
||||||
if (s->pos >= s->w) {
|
if (s->pos >= s->w) {
|
||||||
s->pos = 0;
|
s->pos = s->bar_size;
|
||||||
s->new_frame = 1;
|
s->new_frame = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIRECTION_RL:
|
case DIRECTION_RL:
|
||||||
s->pos--;
|
s->pos--;
|
||||||
if (s->pos < 0) {
|
if (s->pos < 0) {
|
||||||
s->pos = s->w - 1;
|
s->pos = FFMAX(0, s->w - 2 - s->bar_size);
|
||||||
s->new_frame = 1;
|
s->new_frame = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIRECTION_UD:
|
case DIRECTION_UD:
|
||||||
s->pos++;
|
s->pos++;
|
||||||
if (s->pos >= s->h) {
|
if (s->pos >= s->h) {
|
||||||
s->pos = 0;
|
s->pos = s->bar_size;
|
||||||
s->new_frame = 1;
|
s->new_frame = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIRECTION_DU:
|
case DIRECTION_DU:
|
||||||
s->pos--;
|
s->pos--;
|
||||||
if (s->pos < 0) {
|
if (s->pos < 0) {
|
||||||
s->pos = s->h - 1;
|
s->pos = FFMAX(0, s->h - 2 - s->bar_size);
|
||||||
s->new_frame = 1;
|
s->new_frame = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -864,13 +960,13 @@ static int output_frame(AVFilterContext *ctx)
|
||||||
switch (s->direction) {
|
switch (s->direction) {
|
||||||
case DIRECTION_UD:
|
case DIRECTION_UD:
|
||||||
case DIRECTION_LR:
|
case DIRECTION_LR:
|
||||||
s->pos = 0;
|
s->pos = s->bar_size;
|
||||||
break;
|
break;
|
||||||
case DIRECTION_RL:
|
case DIRECTION_RL:
|
||||||
s->pos = s->w - 1;
|
s->pos = FFMAX(0, s->w - 2 - s->bar_size);
|
||||||
break;
|
break;
|
||||||
case DIRECTION_DU:
|
case DIRECTION_DU:
|
||||||
s->pos = s->h - 1;
|
s->pos = FFMAX(0, s->h - 2 - s->bar_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue