avfilter/vf_waveform: implement tint options

This commit is contained in:
Paul B Mahol 2019-12-28 19:50:33 +01:00
parent b3216f13ce
commit 6399eed48a
3 changed files with 182 additions and 82 deletions

View File

@ -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

View File

@ -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;
const int t0 = s->tint[0];
const int t1 = s->tint[1];
uint8_t *dst0, *dst1;
const uint8_t *src;
int x;
dst = out->data[plane] + offset_y * dst_linesize + offset_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;
}
} else if (step > 1) {
const int dst_w = 256;
uint8_t *dst;
int z;
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;
}
} else if (s->display != OVERLAY && !s->rgb) {
const int bg = s->bg_color[0];
const int dst_w = 256;
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;
}
}
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

View File

@ -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