Commit 6399eed4 authored by Paul B Mahol's avatar Paul B Mahol

avfilter/vf_waveform: implement tint options

parent b3216f13
...@@ -19689,6 +19689,12 @@ Default is digital. ...@@ -19689,6 +19689,12 @@ Default is digital.
@item bgopacity, b @item bgopacity, b
Set background opacity. Set background opacity.
@item tint0, t0
@item tint1, t1
Set tint for output.
Only used with lowpass filter and when display is not overlay and input
pixel formats are not RGB.
@end table @end table
@section weave, doubleweave @section weave, doubleweave
......
...@@ -112,6 +112,8 @@ typedef struct WaveformContext { ...@@ -112,6 +112,8 @@ typedef struct WaveformContext {
GraticuleLines *glines; GraticuleLines *glines;
int nb_glines; int nb_glines;
int rgb; int rgb;
float ftint[2];
int tint[2];
int (*waveform_slice)(AVFilterContext *ctx, void *arg, int (*waveform_slice)(AVFilterContext *ctx, void *arg,
int jobnr, int nb_jobs); int jobnr, int nb_jobs);
...@@ -179,6 +181,10 @@ static const AVOption waveform_options[] = { ...@@ -179,6 +181,10 @@ static const AVOption waveform_options[] = {
{ "ire", NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE}, 0, 0, FLAGS, "scale" }, { "ire", NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE}, 0, 0, FLAGS, "scale" },
{ "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
{ "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
{ "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
{ "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
{ "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
{ "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
{ NULL } { NULL }
}; };
...@@ -678,10 +684,11 @@ static av_always_inline void lowpass16(WaveformContext *s, ...@@ -678,10 +684,11 @@ static av_always_inline void lowpass16(WaveformContext *s,
int jobnr, int nb_jobs) int jobnr, int nb_jobs)
{ {
const int plane = s->desc->comp[component].plane; const int plane = s->desc->comp[component].plane;
const int dplane = (s->rgb || s->display == OVERLAY) ? plane : 0;
const int shift_w = s->shift_w[component]; const int shift_w = s->shift_w[component];
const int shift_h = s->shift_h[component]; const int shift_h = s->shift_h[component];
const int src_linesize = in->linesize[plane] / 2; const int src_linesize = in->linesize[plane] / 2;
const int dst_linesize = out->linesize[plane] / 2; const int dst_linesize = out->linesize[dplane] / 2;
const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
const int limit = s->max - 1; const int limit = s->max - 1;
const int max = limit - intensity; const int max = limit - intensity;
...@@ -693,7 +700,7 @@ static av_always_inline void lowpass16(WaveformContext *s, ...@@ -693,7 +700,7 @@ static av_always_inline void lowpass16(WaveformContext *s,
const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
const int step = column ? 1 << shift_w : 1 << shift_h; const int step = column ? 1 << shift_w : 1 << shift_h;
const uint16_t *src_data = (const uint16_t *)in->data[plane] + sliceh_start * src_linesize; const uint16_t *src_data = (const uint16_t *)in->data[plane] + sliceh_start * src_linesize;
uint16_t *dst_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; uint16_t *dst_data = (uint16_t *)out->data[dplane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data); uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
const uint16_t *p; const uint16_t *p;
...@@ -730,6 +737,56 @@ static av_always_inline void lowpass16(WaveformContext *s, ...@@ -730,6 +737,56 @@ static av_always_inline void lowpass16(WaveformContext *s,
src_data += src_linesize; src_data += src_linesize;
dst_data += dst_linesize * step; dst_data += dst_linesize * step;
} }
if (s->display != OVERLAY && column && !s->rgb) {
const int mult = s->max / 256;
const int bg = s->bg_color[0] * mult;
const int t0 = s->tint[0];
const int t1 = s->tint[1];
uint16_t *dst0, *dst1;
const uint16_t *src;
int x;
src = (const uint16_t *)(out->data[0]) + offset_y * dst_linesize + offset_x;
dst0 = (uint16_t *)(out->data[1]) + offset_y * dst_linesize + offset_x;
dst1 = (uint16_t *)(out->data[2]) + offset_y * dst_linesize + offset_x;
for (y = 0; y < s->max; y++) {
for (x = slicew_start * step; x < slicew_end * step; x++) {
if (src[x] != bg) {
dst0[x] = t0;
dst1[x] = t1;
}
}
src += dst_linesize;
dst0 += dst_linesize;
dst1 += dst_linesize;
}
} else if (s->display != OVERLAY && !s->rgb) {
const int mult = s->max / 256;
const int bg = s->bg_color[0] * mult;
const int t0 = s->tint[0];
const int t1 = s->tint[1];
uint16_t *dst0, *dst1;
const uint16_t *src;
int x;
src = (const uint16_t *)out->data[0] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
dst0 = (uint16_t *)(out->data[1]) + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
dst1 = (uint16_t *)(out->data[2]) + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
for (y = sliceh_start * step; y < sliceh_end * step; y++) {
for (x = 0; x < s->max; x++) {
if (src[x] != bg) {
dst0[x] = t0;
dst1[x] = t1;
}
}
src += dst_linesize;
dst0 += dst_linesize;
dst1 += dst_linesize;
}
}
} }
#define LOWPASS16_FUNC(name, column, mirror) \ #define LOWPASS16_FUNC(name, column, mirror) \
...@@ -765,10 +822,11 @@ static av_always_inline void lowpass(WaveformContext *s, ...@@ -765,10 +822,11 @@ static av_always_inline void lowpass(WaveformContext *s,
int jobnr, int nb_jobs) int jobnr, int nb_jobs)
{ {
const int plane = s->desc->comp[component].plane; const int plane = s->desc->comp[component].plane;
const int dplane = (s->rgb || s->display == OVERLAY) ? plane : 0;
const int shift_w = s->shift_w[component]; const int shift_w = s->shift_w[component];
const int shift_h = s->shift_h[component]; const int shift_h = s->shift_h[component];
const int src_linesize = in->linesize[plane]; const int src_linesize = in->linesize[plane];
const int dst_linesize = out->linesize[plane]; const int dst_linesize = out->linesize[dplane];
const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
const int max = 255 - intensity; const int max = 255 - intensity;
const int src_h = AV_CEIL_RSHIFT(in->height, shift_h); const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
...@@ -779,7 +837,7 @@ static av_always_inline void lowpass(WaveformContext *s, ...@@ -779,7 +837,7 @@ static av_always_inline void lowpass(WaveformContext *s,
const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
const int step = column ? 1 << shift_w : 1 << shift_h; const int step = column ? 1 << shift_w : 1 << shift_h;
const uint8_t *src_data = in->data[plane] + sliceh_start * src_linesize; const uint8_t *src_data = in->data[plane] + sliceh_start * src_linesize;
uint8_t *dst_data = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; uint8_t *dst_data = out->data[dplane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data); uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
const uint8_t *p; const uint8_t *p;
...@@ -794,48 +852,76 @@ static av_always_inline void lowpass(WaveformContext *s, ...@@ -794,48 +852,76 @@ static av_always_inline void lowpass(WaveformContext *s,
for (p = src_data + slicew_start; p < src_data_end; p++) { for (p = src_data + slicew_start; p < src_data_end; p++) {
uint8_t *target; uint8_t *target;
int i = 0;
if (column) { if (column) {
target = dst + dst_signed_linesize * *p; do {
dst += step; target = dst++ + dst_signed_linesize * *p;
update(target, max, intensity); update(target, max, intensity);
} while (++i < step);
} else { } else {
uint8_t *row = dst_data; uint8_t *row = dst_data;
if (mirror) do {
target = row - *p - 1; if (mirror)
else target = row - *p - 1;
target = row + *p; else
update(target, max, intensity); target = row + *p;
row += dst_linesize; update(target, max, intensity);
row += dst_linesize;
} while (++i < step);
} }
} }
src_data += src_linesize; src_data += src_linesize;
dst_data += dst_linesize * step; dst_data += dst_linesize * step;
} }
if (column && step > 1) { if (s->display != OVERLAY && column && !s->rgb) {
const int bg = s->bg_color[0];
const int dst_h = 256; const int dst_h = 256;
uint8_t *dst; const int t0 = s->tint[0];
int x, z; const int t1 = s->tint[1];
uint8_t *dst0, *dst1;
dst = out->data[plane] + offset_y * dst_linesize + offset_x; const uint8_t *src;
int x;
src = out->data[0] + offset_y * dst_linesize + offset_x;
dst0 = out->data[1] + offset_y * dst_linesize + offset_x;
dst1 = out->data[2] + offset_y * dst_linesize + offset_x;
for (y = 0; y < dst_h; y++) { for (y = 0; y < dst_h; y++) {
for (x = slicew_start * step; x < slicew_end * step; x+=step) { for (x = slicew_start * step; x < slicew_end * step; x++) {
for (z = 1; z < step; z++) { if (src[x] != bg) {
dst[x + z] = dst[x]; dst0[x] = t0;
dst1[x] = t1;
} }
} }
dst += dst_linesize;
src += dst_linesize;
dst0 += dst_linesize;
dst1 += dst_linesize;
} }
} else if (step > 1) { } else if (s->display != OVERLAY && !s->rgb) {
const int bg = s->bg_color[0];
const int dst_w = 256; const int dst_w = 256;
uint8_t *dst; const int t0 = s->tint[0];
int z; const int t1 = s->tint[1];
uint8_t *dst0, *dst1;
const uint8_t *src;
int x;
src = out->data[0] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
dst0 = out->data[1] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
dst1 = out->data[2] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
for (y = sliceh_start * step; y < sliceh_end * step; y++) {
for (x = 0; x < dst_w; x++) {
if (src[x] != bg) {
dst0[x] = t0;
dst1[x] = t1;
}
}
dst = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; src += dst_linesize;
for (y = sliceh_start * step; y < sliceh_end * step; y+=step) { dst0 += dst_linesize;
for (z = 1; z < step; z++) dst1 += dst_linesize;
memcpy(dst + dst_linesize * z, dst, dst_w);
dst += dst_linesize * step;
} }
} }
} }
...@@ -3198,6 +3284,9 @@ static int config_input(AVFilterLink *inlink) ...@@ -3198,6 +3284,9 @@ static int config_input(AVFilterLink *inlink)
s->size = s->size << (s->bits - 8); s->size = s->size << (s->bits - 8);
s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1);
s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1);
switch (inlink->format) { switch (inlink->format) {
case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GBRAP:
case AV_PIX_FMT_GBRP: case AV_PIX_FMT_GBRP:
...@@ -3334,10 +3423,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ...@@ -3334,10 +3423,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
td.offset_x = offset_x; td.offset_x = offset_x;
ctx->internal->execute(ctx, s->waveform_slice, &td, NULL, ff_filter_get_nb_threads(ctx)); ctx->internal->execute(ctx, s->waveform_slice, &td, NULL, ff_filter_get_nb_threads(ctx));
switch (s->filter) { switch (s->filter) {
case LOWPASS:
if (s->bits <= 8)
envelope(s, out, plane, s->rgb || s->display == OVERLAY ? plane : 0, s->mode ? offset_x : offset_y);
else
envelope16(s, out, plane, s->rgb || s->display == OVERLAY ? plane : 0, s->mode ? offset_x : offset_y);
break;
case ACOLOR: case ACOLOR:
case CHROMA: case CHROMA:
case COLOR: case COLOR:
case LOWPASS:
if (s->bits <= 8) if (s->bits <= 8)
envelope(s, out, plane, plane, s->mode ? offset_x : offset_y); envelope(s, out, plane, plane, s->mode ? offset_x : offset_y);
else else
......
...@@ -3,53 +3,53 @@ ...@@ -3,53 +3,53 @@
#codec_id 0: rawvideo #codec_id 0: rawvideo
#dimensions 0: 352x512 #dimensions 0: 352x512
#sar 0: 1/1 #sar 0: 1/1
0, 0, 0, 1, 540672, 0x8a2521d6 0, 0, 0, 1, 540672, 0xe33821d6
0, 1, 1, 1, 540672, 0xb9a321d6 0, 1, 1, 1, 540672, 0x12c521d6
0, 2, 2, 1, 540672, 0x325421d6 0, 2, 2, 1, 540672, 0x8b6721d6
0, 3, 3, 1, 540672, 0xafee21d2 0, 3, 3, 1, 540672, 0x6fd321d6
0, 4, 4, 1, 540672, 0x172121d6 0, 4, 4, 1, 540672, 0x703421d6
0, 5, 5, 1, 540672, 0x24d121d6 0, 5, 5, 1, 540672, 0x7de421d6
0, 6, 6, 1, 540672, 0x7fec21d6 0, 6, 6, 1, 540672, 0xd8ff21d6
0, 7, 7, 1, 540672, 0xa8a021d6 0, 7, 7, 1, 540672, 0x01c221d6
0, 8, 8, 1, 540672, 0x29fd21d6 0, 8, 8, 1, 540672, 0x831021d6
0, 9, 9, 1, 540672, 0x6dfe21d6 0, 9, 9, 1, 540672, 0xc71121d6
0, 10, 10, 1, 540672, 0xe39821d6 0, 10, 10, 1, 540672, 0x3cba21d6
0, 11, 11, 1, 540672, 0x83f521d6 0, 11, 11, 1, 540672, 0xdd0821d6
0, 12, 12, 1, 540672, 0x57aa21d6 0, 12, 12, 1, 540672, 0xb0bd21d6
0, 13, 13, 1, 540672, 0x67b221d6 0, 13, 13, 1, 540672, 0xc0c521d6
0, 14, 14, 1, 540672, 0x535821d6 0, 14, 14, 1, 540672, 0xac6b21d6
0, 15, 15, 1, 540672, 0xb8ac21d6 0, 15, 15, 1, 540672, 0x11ce21d6
0, 16, 16, 1, 540672, 0x27f621d6 0, 16, 16, 1, 540672, 0x810921d6
0, 17, 17, 1, 540672, 0x775221d6 0, 17, 17, 1, 540672, 0xd06521d6
0, 18, 18, 1, 540672, 0x8e6621d6 0, 18, 18, 1, 540672, 0xe77921d6
0, 19, 19, 1, 540672, 0x74c921d6 0, 19, 19, 1, 540672, 0xcddc21d6
0, 20, 20, 1, 540672, 0x04cd21d6 0, 20, 20, 1, 540672, 0x5de021d6
0, 21, 21, 1, 540672, 0xccd421d6 0, 21, 21, 1, 540672, 0x25f621d6
0, 22, 22, 1, 540672, 0x317221d6 0, 22, 22, 1, 540672, 0x8a8521d6
0, 23, 23, 1, 540672, 0xd79321d6 0, 23, 23, 1, 540672, 0x30b521d6
0, 24, 24, 1, 540672, 0xa2ac21d6 0, 24, 24, 1, 540672, 0xfbbf21d6
0, 25, 25, 1, 540672, 0x7f0a21d6 0, 25, 25, 1, 540672, 0xd81d21d6
0, 26, 26, 1, 540672, 0x483521d6 0, 26, 26, 1, 540672, 0xa14821d6
0, 27, 27, 1, 540672, 0xb65721d6 0, 27, 27, 1, 540672, 0x0f7921d6
0, 28, 28, 1, 540672, 0xb77021d6 0, 28, 28, 1, 540672, 0x109221d6
0, 29, 29, 1, 540672, 0x9fd521d6 0, 29, 29, 1, 540672, 0xf8e821d6
0, 30, 30, 1, 540672, 0xb72121d6 0, 30, 30, 1, 540672, 0x104321d6
0, 31, 31, 1, 540672, 0x540221d6 0, 31, 31, 1, 540672, 0xad1521d6
0, 32, 32, 1, 540672, 0xa34121d6 0, 32, 32, 1, 540672, 0xfc5421d6
0, 33, 33, 1, 540672, 0xe01421d6 0, 33, 33, 1, 540672, 0x393621d6
0, 34, 34, 1, 540672, 0x6fc721d6 0, 34, 34, 1, 540672, 0xc8da21d6
0, 35, 35, 1, 540672, 0x7fa621d6 0, 35, 35, 1, 540672, 0xd8b921d6
0, 36, 36, 1, 540672, 0xc48c21d6 0, 36, 36, 1, 540672, 0x1dae21d6
0, 37, 37, 1, 540672, 0x40f021d6 0, 37, 37, 1, 540672, 0x9a0321d6
0, 38, 38, 1, 540672, 0xdf3f21d6 0, 38, 38, 1, 540672, 0x386121d6
0, 39, 39, 1, 540672, 0xb04321d6 0, 39, 39, 1, 540672, 0x096521d6
0, 40, 40, 1, 540672, 0x222821d6 0, 40, 40, 1, 540672, 0x7b3b21d6
0, 41, 41, 1, 540672, 0x2a5521d6 0, 41, 41, 1, 540672, 0x836821d6
0, 42, 42, 1, 540672, 0x6a4621be 0, 42, 42, 1, 540672, 0x97bd21d6
0, 43, 43, 1, 540672, 0xed7f21d6 0, 43, 43, 1, 540672, 0x46a121d6
0, 44, 44, 1, 540672, 0xb16521d6 0, 44, 44, 1, 540672, 0x0a8721d6
0, 45, 45, 1, 540672, 0x9f5621d6 0, 45, 45, 1, 540672, 0xf86921d6
0, 46, 46, 1, 540672, 0x204321d6 0, 46, 46, 1, 540672, 0x795621d6
0, 47, 47, 1, 540672, 0xc26e21d6 0, 47, 47, 1, 540672, 0x1b9021d6
0, 48, 48, 1, 540672, 0x3e8321d6 0, 48, 48, 1, 540672, 0x979621d6
0, 49, 49, 1, 540672, 0xaaee21d6 0, 49, 49, 1, 540672, 0x041021d6
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment