avfilter/vf_waveform: implement tint options

pull/331/head
Paul B Mahol 5 years ago
parent b3216f13ce
commit 6399eed48a
  1. 6
      doc/filters.texi
  2. 156
      libavfilter/vf_waveform.c
  3. 100
      tests/ref/fate/filter-waveform_uv

@ -19689,6 +19689,12 @@ Default is digital.
@item bgopacity, b
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
@section weave, doubleweave

@ -112,6 +112,8 @@ typedef struct WaveformContext {
GraticuleLines *glines;
int nb_glines;
int rgb;
float ftint[2];
int tint[2];
int (*waveform_slice)(AVFilterContext *ctx, void *arg,
int jobnr, int nb_jobs);
@ -179,6 +181,10 @@ static const AVOption waveform_options[] = {
{ "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 },
{ "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 }
};
@ -678,10 +684,11 @@ static av_always_inline void lowpass16(WaveformContext *s,
int jobnr, int nb_jobs)
{
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_h = s->shift_h[component];
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 limit = s->max - 1;
const int max = limit - intensity;
@ -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 step = column ? 1 << shift_w : 1 << shift_h;
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_line = (mirror ? dst_bottom_line : dst_data);
const uint16_t *p;
@ -730,6 +737,56 @@ static av_always_inline void lowpass16(WaveformContext *s,
src_data += src_linesize;
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) \
@ -765,10 +822,11 @@ static av_always_inline void lowpass(WaveformContext *s,
int jobnr, int nb_jobs)
{
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_h = s->shift_h[component];
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 max = 255 - intensity;
const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
@ -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 step = column ? 1 << shift_w : 1 << shift_h;
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_line = (mirror ? dst_bottom_line : dst_data);
const uint8_t *p;
@ -794,48 +852,76 @@ static av_always_inline void lowpass(WaveformContext *s,
for (p = src_data + slicew_start; p < src_data_end; p++) {
uint8_t *target;
int i = 0;
if (column) {
target = dst + dst_signed_linesize * *p;
dst += step;
update(target, max, intensity);
do {
target = dst++ + dst_signed_linesize * *p;
update(target, max, intensity);
} while (++i < step);
} else {
uint8_t *row = dst_data;
if (mirror)
target = row - *p - 1;
else
target = row + *p;
update(target, max, intensity);
row += dst_linesize;
do {
if (mirror)
target = row - *p - 1;
else
target = row + *p;
update(target, max, intensity);
row += dst_linesize;
} while (++i < step);
}
}
src_data += src_linesize;
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;
uint8_t *dst;
int x, z;
dst = out->data[plane] + offset_y * dst_linesize + offset_x;
const int t0 = s->tint[0];
const int t1 = s->tint[1];
uint8_t *dst0, *dst1;
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 (x = slicew_start * step; x < slicew_end * step; x+=step) {
for (z = 1; z < step; z++) {
dst[x + z] = dst[x];
for (x = slicew_start * step; x < slicew_end * step; x++) {
if (src[x] != bg) {
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;
uint8_t *dst;
int z;
const int t0 = s->tint[0];
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;
for (y = sliceh_start * step; y < sliceh_end * step; y+=step) {
for (z = 1; z < step; z++)
memcpy(dst + dst_linesize * z, dst, dst_w);
dst += dst_linesize * step;
src += dst_linesize;
dst0 += dst_linesize;
dst1 += dst_linesize;
}
}
}
@ -3198,6 +3284,9 @@ static int config_input(AVFilterLink *inlink)
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) {
case AV_PIX_FMT_GBRAP:
case AV_PIX_FMT_GBRP:
@ -3334,10 +3423,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
td.offset_x = offset_x;
ctx->internal->execute(ctx, s->waveform_slice, &td, NULL, ff_filter_get_nb_threads(ctx));
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 CHROMA:
case COLOR:
case LOWPASS:
if (s->bits <= 8)
envelope(s, out, plane, plane, s->mode ? offset_x : offset_y);
else

@ -3,53 +3,53 @@
#codec_id 0: rawvideo
#dimensions 0: 352x512
#sar 0: 1/1
0, 0, 0, 1, 540672, 0x8a2521d6
0, 1, 1, 1, 540672, 0xb9a321d6
0, 2, 2, 1, 540672, 0x325421d6
0, 3, 3, 1, 540672, 0xafee21d2
0, 4, 4, 1, 540672, 0x172121d6
0, 5, 5, 1, 540672, 0x24d121d6
0, 6, 6, 1, 540672, 0x7fec21d6
0, 7, 7, 1, 540672, 0xa8a021d6
0, 8, 8, 1, 540672, 0x29fd21d6
0, 9, 9, 1, 540672, 0x6dfe21d6
0, 10, 10, 1, 540672, 0xe39821d6
0, 11, 11, 1, 540672, 0x83f521d6
0, 12, 12, 1, 540672, 0x57aa21d6
0, 13, 13, 1, 540672, 0x67b221d6
0, 14, 14, 1, 540672, 0x535821d6
0, 15, 15, 1, 540672, 0xb8ac21d6
0, 16, 16, 1, 540672, 0x27f621d6
0, 17, 17, 1, 540672, 0x775221d6
0, 18, 18, 1, 540672, 0x8e6621d6
0, 19, 19, 1, 540672, 0x74c921d6
0, 20, 20, 1, 540672, 0x04cd21d6
0, 21, 21, 1, 540672, 0xccd421d6
0, 22, 22, 1, 540672, 0x317221d6
0, 23, 23, 1, 540672, 0xd79321d6
0, 24, 24, 1, 540672, 0xa2ac21d6
0, 25, 25, 1, 540672, 0x7f0a21d6
0, 26, 26, 1, 540672, 0x483521d6
0, 27, 27, 1, 540672, 0xb65721d6
0, 28, 28, 1, 540672, 0xb77021d6
0, 29, 29, 1, 540672, 0x9fd521d6
0, 30, 30, 1, 540672, 0xb72121d6
0, 31, 31, 1, 540672, 0x540221d6
0, 32, 32, 1, 540672, 0xa34121d6
0, 33, 33, 1, 540672, 0xe01421d6
0, 34, 34, 1, 540672, 0x6fc721d6
0, 35, 35, 1, 540672, 0x7fa621d6
0, 36, 36, 1, 540672, 0xc48c21d6
0, 37, 37, 1, 540672, 0x40f021d6
0, 38, 38, 1, 540672, 0xdf3f21d6
0, 39, 39, 1, 540672, 0xb04321d6
0, 40, 40, 1, 540672, 0x222821d6
0, 41, 41, 1, 540672, 0x2a5521d6
0, 42, 42, 1, 540672, 0x6a4621be
0, 43, 43, 1, 540672, 0xed7f21d6
0, 44, 44, 1, 540672, 0xb16521d6
0, 45, 45, 1, 540672, 0x9f5621d6
0, 46, 46, 1, 540672, 0x204321d6
0, 47, 47, 1, 540672, 0xc26e21d6
0, 48, 48, 1, 540672, 0x3e8321d6
0, 49, 49, 1, 540672, 0xaaee21d6
0, 0, 0, 1, 540672, 0xe33821d6
0, 1, 1, 1, 540672, 0x12c521d6
0, 2, 2, 1, 540672, 0x8b6721d6
0, 3, 3, 1, 540672, 0x6fd321d6
0, 4, 4, 1, 540672, 0x703421d6
0, 5, 5, 1, 540672, 0x7de421d6
0, 6, 6, 1, 540672, 0xd8ff21d6
0, 7, 7, 1, 540672, 0x01c221d6
0, 8, 8, 1, 540672, 0x831021d6
0, 9, 9, 1, 540672, 0xc71121d6
0, 10, 10, 1, 540672, 0x3cba21d6
0, 11, 11, 1, 540672, 0xdd0821d6
0, 12, 12, 1, 540672, 0xb0bd21d6
0, 13, 13, 1, 540672, 0xc0c521d6
0, 14, 14, 1, 540672, 0xac6b21d6
0, 15, 15, 1, 540672, 0x11ce21d6
0, 16, 16, 1, 540672, 0x810921d6
0, 17, 17, 1, 540672, 0xd06521d6
0, 18, 18, 1, 540672, 0xe77921d6
0, 19, 19, 1, 540672, 0xcddc21d6
0, 20, 20, 1, 540672, 0x5de021d6
0, 21, 21, 1, 540672, 0x25f621d6
0, 22, 22, 1, 540672, 0x8a8521d6
0, 23, 23, 1, 540672, 0x30b521d6
0, 24, 24, 1, 540672, 0xfbbf21d6
0, 25, 25, 1, 540672, 0xd81d21d6
0, 26, 26, 1, 540672, 0xa14821d6
0, 27, 27, 1, 540672, 0x0f7921d6
0, 28, 28, 1, 540672, 0x109221d6
0, 29, 29, 1, 540672, 0xf8e821d6
0, 30, 30, 1, 540672, 0x104321d6
0, 31, 31, 1, 540672, 0xad1521d6
0, 32, 32, 1, 540672, 0xfc5421d6
0, 33, 33, 1, 540672, 0x393621d6
0, 34, 34, 1, 540672, 0xc8da21d6
0, 35, 35, 1, 540672, 0xd8b921d6
0, 36, 36, 1, 540672, 0x1dae21d6
0, 37, 37, 1, 540672, 0x9a0321d6
0, 38, 38, 1, 540672, 0x386121d6
0, 39, 39, 1, 540672, 0x096521d6
0, 40, 40, 1, 540672, 0x7b3b21d6
0, 41, 41, 1, 540672, 0x836821d6
0, 42, 42, 1, 540672, 0x97bd21d6
0, 43, 43, 1, 540672, 0x46a121d6
0, 44, 44, 1, 540672, 0x0a8721d6
0, 45, 45, 1, 540672, 0xf86921d6
0, 46, 46, 1, 540672, 0x795621d6
0, 47, 47, 1, 540672, 0x1b9021d6
0, 48, 48, 1, 540672, 0x979621d6
0, 49, 49, 1, 540672, 0x041021d6

Loading…
Cancel
Save