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

View File

@ -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[] = {
{ "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,
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,
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,
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,
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,
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,
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;
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 (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;
}
} 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; 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; } 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->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)
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

View File

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