mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-10-24 02:09:03 +03:00
avfilter/vf_drawvg: values from the p() function can be used as colors.
To be able to reuse colors from the original frame, the last value returned by
`p()` is tracked in the eval state, and if it is assigned to a variable, the
original color components are copied to `color_vars`. Thus, commands like
`setcolor` and `colorstop` can use those variables:
setvar pixel (p(0, 0))
...
setcolor pixel
`fate-filter-drawvg-video` now also verifies the `p()` function.
Signed-off-by: Ayose <ayosec@gmail.com>
This commit is contained in:
@@ -1443,6 +1443,12 @@ struct VGSEvalState {
|
||||
/// Colors stored in variables.
|
||||
cairo_color color_vars[USER_VAR_COUNT];
|
||||
|
||||
/// Track last color read by the `p()` function.
|
||||
struct {
|
||||
double numeric;
|
||||
uint8_t components[4];
|
||||
} last_fn_p_color;
|
||||
|
||||
/// State for each index available for the `randomg` function.
|
||||
FFSFC64 random_state[RANDOM_STATES];
|
||||
|
||||
@@ -1555,7 +1561,7 @@ static double vgs_fn_randomg(void *data, double arg) {
|
||||
///
|
||||
/// If the coordinates are outside the frame, return NAN.
|
||||
static double vgs_fn_p(void* data, double x0, double y0) {
|
||||
const struct VGSEvalState *state = (struct VGSEvalState *)data;
|
||||
struct VGSEvalState *state = (struct VGSEvalState *)data;
|
||||
const AVFrame *frame = state->frame;
|
||||
|
||||
if (frame == NULL || !isfinite(x0) || !isfinite(y0))
|
||||
@@ -1575,8 +1581,6 @@ static double vgs_fn_p(void* data, double x0, double y0) {
|
||||
|
||||
for (int c = 0; c < desc->nb_components; c++) {
|
||||
uint32_t pixel;
|
||||
const int depth = desc->comp[c].depth;
|
||||
|
||||
av_read_image_line2(
|
||||
&pixel,
|
||||
(void*)frame->data,
|
||||
@@ -1589,14 +1593,35 @@ static double vgs_fn_p(void* data, double x0, double y0) {
|
||||
4 // dst_element_size
|
||||
);
|
||||
|
||||
if (depth != 8) {
|
||||
const int depth = desc->comp[c].depth;
|
||||
if (depth != 8)
|
||||
pixel = pixel * 255 / ((1 << depth) - 1);
|
||||
}
|
||||
|
||||
color[c] = pixel;
|
||||
}
|
||||
|
||||
return color[0] << 24 | color[1] << 16 | color[2] << 8 | color[3];
|
||||
// A common use-case of `p()` is to store its result in a variable, so it
|
||||
// can be used later with commands like `setcolor` or `colorstop`:
|
||||
//
|
||||
// setvar pixel (p(0, 0))
|
||||
// ...
|
||||
// setcolor pixel
|
||||
//
|
||||
// Since we can't pass custom values through `av_expr_eval`, we store the
|
||||
// color in the `VGSEvalState` instance. Then, when a variable is assigned
|
||||
// in `setvar`, it checks if the value is the same as the output of `p()`.
|
||||
// In such case, it copies the color components to the slot in `color_vars`.
|
||||
//
|
||||
// This solution is far from perfect, but it works in all the documented
|
||||
// use-cases.
|
||||
|
||||
const double num = color[0] << 24 | color[1] << 16 | color[2] << 8 | color[3];
|
||||
|
||||
state->last_fn_p_color.numeric = num;
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(color); i++)
|
||||
state->last_fn_p_color.components[i] = (uint8_t)color[i];
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static int vgs_eval_state_init(
|
||||
@@ -1609,7 +1634,9 @@ static int vgs_eval_state_init(
|
||||
|
||||
state->log_ctx = log_ctx;
|
||||
state->frame = frame;
|
||||
|
||||
state->rcp.status = RCP_NONE;
|
||||
state->last_fn_p_color.numeric = NAN;
|
||||
|
||||
if (program->proc_names != NULL) {
|
||||
state->procedures = av_calloc(sizeof(struct VGSProcedure), program->proc_names_count);
|
||||
@@ -2476,9 +2503,17 @@ static int vgs_eval(
|
||||
const int user_var = statement->args[0].constant;
|
||||
av_assert0(user_var >= VAR_U0 && user_var < (VAR_U0 + USER_VAR_COUNT));
|
||||
|
||||
color_copy(&state->color_vars[user_var - VAR_U0], &colors[1]);
|
||||
state->vars[user_var] = numerics[1];
|
||||
|
||||
// Take the color from `p()`, if any.
|
||||
cairo_color *color = &state->color_vars[user_var - VAR_U0];
|
||||
if (state->last_fn_p_color.numeric == numerics[1]) {
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(*color); i++)
|
||||
(*color)[i] = state->last_fn_p_color.components[i] / 255.0;
|
||||
} else {
|
||||
color_copy(color, &colors[1]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -617,13 +617,14 @@ fate-filter-tiltandshift-410: CMD = framecrc -c:v pgmyuv -i $(SRC) -flags +bitex
|
||||
fate-filter-tiltandshift-422: CMD = framecrc -c:v pgmyuv -i $(SRC) -flags +bitexact -vf scale=sws_flags=+accurate_rnd+bitexact,format=yuv422p,tiltandshift
|
||||
fate-filter-tiltandshift-444: CMD = framecrc -c:v pgmyuv -i $(SRC) -flags +bitexact -vf scale=sws_flags=+accurate_rnd+bitexact,format=yuv444p,tiltandshift
|
||||
|
||||
DRAWVG_SCRIPT_LINES = tests/data/fate/drawvg.lines
|
||||
$(DRAWVG_SCRIPT_LINES): $(SRC_PATH)/tests/ref/lavf/drawvg.lines
|
||||
DRAWVG_SCRIPT_VIDEO = tests/data/fate/drawvg.video
|
||||
$(DRAWVG_SCRIPT_VIDEO): TAG = COPY
|
||||
$(DRAWVG_SCRIPT_VIDEO): $(SRC_PATH)/tests/ref/lavf/drawvg.video
|
||||
$(M)cp $< $@
|
||||
|
||||
FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_DRAWVG_FILTER) += fate-filter-drawvg-video
|
||||
fate-filter-drawvg-video: $(DRAWVG_SCRIPT_LINES)
|
||||
fate-filter-drawvg-video: CMD = video_filter scale,format=bgr0,drawvg=file=$(DRAWVG_SCRIPT_LINES)
|
||||
fate-filter-drawvg-video: $(DRAWVG_SCRIPT_VIDEO)
|
||||
fate-filter-drawvg-video: CMD = video_filter scale,format=bgr0,drawvg=file=$(DRAWVG_SCRIPT_VIDEO)
|
||||
|
||||
tests/pixfmts.mak: TAG = GEN
|
||||
tests/pixfmts.mak: ffmpeg$(PROGSSUF)$(EXESUF) | tests
|
||||
|
||||
@@ -1 +1 @@
|
||||
drawvg-video caa7642950ab2fb1367bd28c287f31bd
|
||||
drawvg-video 0f73962365b69779a604c5d41a4b7ae3
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
// Render a square, for `make fate-filter-drawvg-video`.
|
||||
|
||||
M 10 10
|
||||
l 0 10
|
||||
h 10
|
||||
v -10
|
||||
h -10
|
||||
z
|
||||
setcolor blue
|
||||
stroke
|
||||
13
tests/ref/lavf/drawvg.video
Normal file
13
tests/ref/lavf/drawvg.video
Normal file
@@ -0,0 +1,13 @@
|
||||
// Render a square, for `make fate-filter-drawvg-video`.
|
||||
|
||||
setvar pixel (p(10, 10))
|
||||
|
||||
M 10 10
|
||||
l 0 100
|
||||
h 100
|
||||
v -100
|
||||
h -100
|
||||
z
|
||||
|
||||
setcolor pixel
|
||||
fill
|
||||
Reference in New Issue
Block a user