[gegl] gcut: add support for timed global filters chains
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] gcut: add support for timed global filters chains
- Date: Wed, 9 Aug 2017 21:32:43 +0000 (UTC)
commit ec1b62481a9e0ca8f495feac481be9b7f0c69e06
Author: Øyvind Kolås <pippin gimp org>
Date: Wed Aug 9 19:04:40 2017 +0200
gcut: add support for timed global filters chains
This adds support for chains that apply on top of the cut and spliced/faded
video track. For now only chains with global time offstes preceding the clips
is supported.
Adding for instance:
-- 10.2s 20s gegl:pixelize x-size=0.1rel y-size=0.1rel
before all the clips in a video project will blur the sequence between 10.2s
and 20s.
If multiple filters apply they are applied in the order they occur in the
timeline/file.
gcut/default.edl | 7 +--
gcut/default.edl.inc | 7 +--
gcut/gcut.c | 126 +++++++++++++++++++++++++++++++++++++++-----------
gcut/gcut.h | 6 ++-
4 files changed, 108 insertions(+), 38 deletions(-)
---
diff --git a/gcut/default.edl b/gcut/default.edl
index 6646a93..b6d83a1 100644
--- a/gcut/default.edl
+++ b/gcut/default.edl
@@ -4,15 +4,14 @@ output-path=gcut.mp4
video-width=800
video-height=600
fps=25.000000
-selection-start=291
-selection-end=291
+selection-start=291.000
+selection-end=291.000
frame-scale=0.398424
t0=56.702866
frame-pos=0.000
gegl:color value=black gegl:crop width=400 height=400 1.240s 2.000s --
gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 2.000s -- [fade=1.040s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='note: this is a gcut video\nproject for testing features\nit relies
on synthetic GEGL\npatterns instead of\nvideo footage\nto be to minimie size\nfor inclusion in gcut
sources\nbeing able to create this project \nfrom scratch in the gcut ui\nis a current goal.'
size=0.071811296045780182rel color='rgb(1.0000, 1.0000, 1.0000)' width=3 height=1 gegl:translate opi=0:0
x=0.10000000000000001rel y=0.051874876022338867rel ]
--- #annotations
gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 reset-origin=true 0.000s 3.200s -- svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='gcut' font='sans' size=0.20000000000000001rel color='rgb(1.0000,
1.0000, 1.0000)' width=1 height=1 gegl:gaussian-blur opi=0:0 std-dev-x={ 0.000000=0.400000rel
2.560000=0.000084rel } std-dev-y={ 0.000000=0.200000rel } clip-extent=false gegl:translate opi=0:0
x=0.10000000000000001rel y=0.3304142951965332rel ] gegl:lens-flare opi=0:0 pos-x={ 0.000000=-2.000000
2.400000=0.293004 4.000000=2.000000 } pos-y={ 0.000000=0.100000 2.400000=0.360697 25.000000=0.910000 }
gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 2.000s -- [fade=2.560s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='video editing\nfileformat+render / ui' size=0.10000000000000001rel
color='rgb(1.0000, 1.0000, 1.0000)' width=1 height=1 gegl:translate opi=0:0 x=0.10000000000000001rel
y=0.55924856662750244rel ]
gegl:cell-noise opi=0:0 shape={ 0.000000=1.000000 1.600000=1.850000 } palettize=true gegl:translate
opi=0:0 x={ 20.000000=50.000000 } y={ 20.000000=500.000000 } gegl:crop opi=0:0 width=400 height=400
0.000s 1.600s -- [fade=0.920s]
@@ -28,6 +27,6 @@ gegl:noise-solid opi=0:0 y-size=4.6258320808410645 seed=668093247 gegl:crop opi=
gegl:noise-solid opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 1.000s -- [fade=1.440s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='crash recovery by default' size=0.081632360816001892rel
color='rgb(1.0000, 1.0000, 0.0000)' width=1 height=1 gegl:translate opi=0:0 x=0.10000000000000001rel
y=0.42925620079040527rel ]
gegl:noise-solid opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 1.000s -- [fade=1.360s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='overlays:audio filter' size=0.10000000000000001rel
color='rgb(1.0000, 1.0000, 0.0000)' width=1 height=1 gegl:translate opi=0:0 x=0.10000000000000001rel
y=0.48208630084991455rel ]
gegl:noise-solid gegl:crop width=400 height=400 0.000s 1.000s -- [fade=1.360s] over aux=[ text size=0.1rel
string='network rendering' color=yellow translate x=0.1rel y=0.8rel ]
---#end titles
+-- #end titles
gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 18.960s -- svg:src-over opi=0:0 aux=[
gegl:text opi=0:0 string='end titles\n\nfull of newlines\n\nand some images and more\n\nmost of the
time\n\n\nthough\n\nusing an image that one pans\nwill provide better typographic control\nperhaps based on a
pdf/svg\n\nthis is is also where I should stick misc info' size=0.040000000000000001rel color='rgb(1.0000,
1.0000, 1.0000)' width=1 height=8 gegl:translate opi=0:0 x=0.10000000000000001rel y={ 0.000000=1.000000rel
32.000000=-2.000000rel } ]
-----
diff --git a/gcut/default.edl.inc b/gcut/default.edl.inc
index aeeee6d..3179c6d 100644
--- a/gcut/default.edl.inc
+++ b/gcut/default.edl.inc
@@ -4,15 +4,14 @@
"video-width=800\n"
"video-height=600\n"
"fps=25.000000\n"
-"selection-start=291\n"
-"selection-end=291\n"
+"selection-start=291.000\n"
+"selection-end=291.000\n"
"frame-scale=0.398424\n"
"t0=56.702866\n"
"frame-pos=0.000\n"
"\n"
"gegl:color value=black gegl:crop width=400 height=400 1.240s 2.000s -- \n"
"gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 2.000s -- [fade=1.040s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='note: this is a gcut video\\nproject for testing features\\nit
relies on synthetic GEGL\\npatterns instead of\\nvideo footage\\nto be to minimie size\\nfor inclusion in
gcut sources\\nbeing able to create this project \\nfrom scratch in the gcut ui\\nis a current goal.'
size=0.071811296045780182rel color='rgb(1.0000, 1.0000, 1.0000)' width=3 height=1 gegl:translate opi=0:0
x=0.10000000000000001rel y=0.051874876022338867rel ]\n"
-"-- #annotations\n"
"gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 reset-origin=true 0.000s 3.200s -- svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='gcut' font='sans' size=0.20000000000000001rel color='rgb(1.0000,
1.0000, 1.0000)' width=1 height=1 gegl:gaussian-blur opi=0:0 std-dev-x={ 0.000000=0.400000rel
2.560000=0.000084rel } std-dev-y={ 0.000000=0.200000rel } clip-extent=false gegl:translate opi=0:0
x=0.10000000000000001rel y=0.3304142951965332rel ] gegl:lens-flare opi=0:0 pos-x={ 0.000000=-2.000000
2.400000=0.293004 4.000000=2.000000 } pos-y={ 0.000000=0.100000 2.400000=0.360697 25.000000=0.910000
}\n"
"gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 2.000s -- [fade=2.560s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='video editing\\nfileformat+render / ui' size=0.10000000000000001rel
color='rgb(1.0000, 1.0000, 1.0000)' width=1 height=1 gegl:translate opi=0:0 x=0.10000000000000001rel
y=0.55924856662750244rel ]\n"
"gegl:cell-noise opi=0:0 shape={ 0.000000=1.000000 1.600000=1.850000 } palettize=true gegl:translate
opi=0:0 x={ 20.000000=50.000000 } y={ 20.000000=500.000000 } gegl:crop opi=0:0 width=400 height=400
0.000s 1.600s -- [fade=0.920s] \n"
@@ -28,6 +27,6 @@
"gegl:noise-solid opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 1.000s -- [fade=1.440s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='crash recovery by default' size=0.081632360816001892rel
color='rgb(1.0000, 1.0000, 0.0000)' width=1 height=1 gegl:translate opi=0:0 x=0.10000000000000001rel
y=0.42925620079040527rel ]\n"
"gegl:noise-solid opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 1.000s -- [fade=1.360s] svg:src-over
opi=0:0 aux=[ gegl:text opi=0:0 string='overlays:audio filter' size=0.10000000000000001rel
color='rgb(1.0000, 1.0000, 0.0000)' width=1 height=1 gegl:translate opi=0:0 x=0.10000000000000001rel
y=0.48208630084991455rel ]\n"
"gegl:noise-solid gegl:crop width=400 height=400 0.000s 1.000s -- [fade=1.360s] over aux=[ text size=0.1rel
string='network rendering' color=yellow translate x=0.1rel y=0.8rel ]\n"
-"--#end titles\n"
+"-- #end titles\n"
"gegl:color opi=0:0 gegl:crop opi=0:0 width=400 height=400 0.000s 18.960s -- svg:src-over opi=0:0 aux=[
gegl:text opi=0:0 string='end titles\\n\\nfull of newlines\\n\\nand some images and more\\n\\nmost of the
time\\n\\n\\nthough\\n\\nusing an image that one pans\\nwill provide better typographic control\\nperhaps
based on a pdf/svg\\n\\nthis is is also where I should stick misc info' size=0.040000000000000001rel
color='rgb(1.0000, 1.0000, 1.0000)' width=1 height=8 gegl:translate opi=0:0 x=0.10000000000000001rel y={
0.000000=1.000000rel 32.000000=-2.000000rel } ]\n"
"-----\n"
diff --git a/gcut/gcut.c b/gcut/gcut.c
index 390f9a2..1b917bc 100644
--- a/gcut/gcut.c
+++ b/gcut/gcut.c
@@ -233,6 +233,7 @@ gchar *gcut_get_pos_hash_full (GeglEDL *edl, double pos,
Clip **clip1, double *clip1_pos,
double *mix)
{
+ GString *str = g_string_new ("");
GList *l;
double clip_start = 0;
double prev_clip_start = 0;
@@ -298,22 +299,16 @@ gchar *gcut_get_pos_hash_full (GeglEDL *edl, double pos,
char *clip0_hash = clip_get_pos_hash (clip, clip_frame_pos);
char *clip1_hash = clip_get_pos_hash (prev, pos - prev_clip_start + clip_get_start (prev));
double ratio = 0.5 + ((pos -clip_start) * 1.0 / prev_fade_len)/2;
- char *str = g_strdup_printf ("%s %s %f", clip1_hash, clip0_hash, ratio);
- GChecksum *hash = g_checksum_new (G_CHECKSUM_MD5);
- char *ret;
+ g_string_append_printf (str, "%s %s %f", clip1_hash, clip0_hash, ratio);
g_free (clip0_hash);
g_free (clip1_hash);
- g_checksum_update (hash, (void*)str, -1);
- g_free (str);
- ret = g_strdup (g_checksum_get_string(hash));
- g_checksum_free (hash);
if (clip0) *clip0 = prev;
if (clip0_pos) *clip0_pos = pos - prev_clip_start + clip_get_start (prev);
if (clip1) *clip1 = clip;
if (clip1_pos) *clip1_pos = clip_frame_pos;
if (mix) *mix = ratio;
- return ret;
+ goto done;
}
if (next && pos - clip_start > clip_duration - next_fade_len)/* out*/
@@ -321,29 +316,27 @@ gchar *gcut_get_pos_hash_full (GeglEDL *edl, double pos,
char *clip0_hash = clip_get_pos_hash (clip, clip_frame_pos);
char *clip1_hash = clip_get_pos_hash (next, pos - (clip_start + clip_duration) + clip_get_start
(next));
double ratio = (1.0-(clip_duration -(pos -clip_start)) * 1.0 / next_fade_len)/2;
- GChecksum *hash = g_checksum_new (G_CHECKSUM_MD5);
- char *str = g_strdup_printf ("%s %s %f", clip0_hash, clip1_hash, ratio);
- char *ret;
+ g_string_append_printf (str, "%s %s %f", clip0_hash, clip1_hash, ratio);
g_free (clip0_hash);
g_free (clip1_hash);
- g_checksum_update (hash, (void*)str, -1);
- g_free (str);
- ret = g_strdup (g_checksum_get_string(hash));
- g_checksum_free (hash);
if (clip0) *clip0 = clip;
if (clip0_pos) *clip0_pos = clip_frame_pos;
if (clip1_pos) *clip1_pos = pos - (clip_start +clip_duration) + clip_get_start (next);
if (clip1) *clip1 = next;
if (mix) *mix = ratio;
- return ret;
+ goto done;
}
else
{
+ char *clip0_hash = clip_get_pos_hash (clip, clip_frame_pos);
+ g_string_append_printf (str, "%s ", clip0_hash);
+ g_free (clip0_hash);
+
if (clip0) *clip0 = clip;
if (clip0_pos) *clip0_pos = clip_frame_pos;
if (clip1) *clip1 = NULL;
if (mix) *mix = 0.0;
- return clip_get_pos_hash (clip, clip_frame_pos);
+ goto done;
}
}
prev_clip_start = clip_start;
@@ -356,6 +349,29 @@ gchar *gcut_get_pos_hash_full (GeglEDL *edl, double pos,
if (clip1) *clip1 = NULL;
if (mix) *mix = 0.0;
return NULL;
+done:
+
+ {
+ GList *l;
+ for (l = edl->clips; l; l = l->next)
+ {
+ Clip *c = l->data;
+ if (c->is_meta)
+ {
+ if (pos >= c->start && pos < c->end)
+ g_string_append_printf (str, "[%s]\n", c->filter_graph);
+ }
+ }
+ }
+
+ {
+ GChecksum *hash = g_checksum_new (G_CHECKSUM_MD5);
+ char *ret;
+ g_checksum_update (hash, (void*)str->str, -1);
+ ret = g_strdup (g_checksum_get_string(hash));
+ g_checksum_free (hash);
+ return ret;
+ }
}
gchar *gcut_get_pos_hash (GeglEDL *edl, double pos)
@@ -404,7 +420,7 @@ void gcut_set_pos (GeglEDL *edl, double pos)
{
Clip *clip = NULL;
gegl_node_set (edl->cache_loader, "path", cache_path, NULL);
- gegl_node_link_many (edl->cache_loader, edl->result, NULL);
+ gegl_node_link_many (edl->cache_loader, edl->final_result, NULL);
clip = edl_get_clip_for_pos (edl, pos);
if (clip)
{
@@ -417,7 +433,7 @@ void gcut_set_pos (GeglEDL *edl, double pos)
gegl_meta_get_audio (cache_path, clip->audio);
}
{
- GeglRectangle ext = gegl_node_get_bounding_box (edl->result);
+ GeglRectangle ext = gegl_node_get_bounding_box (edl->final_result);
gegl_buffer_set_extent (edl->buffer, &ext);
}
gegl_node_process (edl->store_final_buf);
@@ -436,16 +452,36 @@ void gcut_set_pos (GeglEDL *edl, double pos)
if (clip1 == NULL)
{
clip_render_pos (clip0, clip0_pos);
- gegl_node_link_many (clip0->nop_crop, edl->result, NULL);
+ gegl_node_link_many (clip0->nop_crop, edl->video_result, NULL);
}
else
{
gegl_node_set (edl->mix, "ratio", mix, NULL);
clip_render_pos (clip0, clip0_pos);
clip_render_pos (clip1, clip1_pos);
- gegl_node_link_many (clip0->nop_crop, edl->mix, edl->result, NULL);
+ gegl_node_link_many (clip0->nop_crop, edl->mix, edl->video_result, NULL);
gegl_node_connect_to (clip1->nop_crop, "output", edl->mix, "aux");
}
+ gegl_node_link_many (edl->video_result, edl->final_result, NULL);
+
+ {
+ GList *l;
+ for (l = edl->clips; l; l = l->next)
+ {
+ Clip *c = l->data;
+ if (c->is_meta)
+ {
+ if (pos >= c->start && pos < c->end)
+ {
+ GeglNode *prev = gegl_node_get_producer (edl->final_result, "input", NULL);
+ gegl_create_chain (c->filter_graph, prev, edl->final_result,
+ pos - c->start,
+ edl->height, NULL, NULL);
+ }
+ }
+ }
+ }
+
gegl_node_process (edl->store_final_buf);
gcut_update_buffer (edl);
@@ -468,7 +504,7 @@ void gcut_set_pos (GeglEDL *edl, double pos)
{
gegl_node_set (save, "bitdepth", 8, NULL);
}
- gegl_node_link_many (edl->result, save, NULL);
+ gegl_node_link_many (edl->final_result, save, NULL);
gegl_node_process (save);
if (clip1 && clip1->audio && mix > 0.5)
gegl_meta_set_audio (cache_path, clip1->audio);
@@ -696,7 +732,31 @@ void gcut_parse_line (GeglEDL *edl, const char *line)
else if (start == 0 && end == 0 && rest)
{
Clip *clip = clip_new_full (edl, NULL, 0, 0);
+ const char *first = NULL;
+ const char *second = NULL;
+ const char *p = rest;
+ while (*p == ' ') p++;
+ if (isdigit(*p))
+ {
+ first = p;
+ while (isdigit(*p) || (*p == '.') || (*p == 's')) p++;
+ while (*p == ' ') p++;
+ if (isdigit(*p))
+ {
+ second = p;
+ while (isdigit(*p) || (*p == '.') || (*p == 's')) p++;
+ }
+ while (*p == ' ') p++;
+ rest = p;
+ }
clip->filter_graph = g_strdup (rest);
+ if (first)
+ clip->start = g_strtod (first, NULL);
+ if (second)
+ clip->end = g_strtod (second, NULL);
+ else
+ clip->end = clip->start;
+
edl->clips = g_list_append (edl->clips, clip);
}
}
@@ -990,7 +1050,8 @@ GeglEDL *gcut_new_from_path (const char *path)
static void setup (GeglEDL *edl)
{
- edl->result = gegl_node_new_child (edl->gegl, "operation", "gegl:nop", NULL);
+ edl->video_result = gegl_node_new_child (edl->gegl, "operation", "gegl:nop", NULL);
+ edl->final_result = gegl_node_new_child (edl->gegl, "operation", "gegl:nop", NULL);
edl->mix = gegl_node_new_child (edl->gegl, "operation", "gegl:mix", NULL);
edl->encode = gegl_node_new_child (edl->gegl, "operation", "gegl:ff-save",
"path", edl->output_path,
@@ -1004,7 +1065,8 @@ static void setup (GeglEDL *edl)
edl->cached_result = gegl_node_new_child (edl->gegl, "operation", "gegl:buffer-source", "buffer",
edl->buffer, NULL);
edl->store_final_buf = gegl_node_new_child (edl->gegl, "operation", "gegl:write-buffer", "buffer",
edl->buffer, NULL);
- gegl_node_link_many (edl->result, edl->store_final_buf, NULL);
+ gegl_node_link_many (edl->video_result, edl->final_result, NULL);
+ gegl_node_link_many (edl->final_result, edl->store_final_buf, NULL);
gegl_node_link_many (edl->cached_result, edl->encode, NULL);
}
@@ -1478,10 +1540,18 @@ char *gcut_serialize (GeglEDL *edl)
if (!strncmp (path, edl->parent_path, strlen(edl->parent_path)))
path += strlen (edl->parent_path);
- if (strlen(path)== 0 &&
- clip->start == 0 &&
- clip->end == 0 &&
- clip->filter_graph)
+ if (clip->is_meta)
+ {
+ if (clip->start == 0 && clip->end == 0)
+ g_string_append_printf (ser, "-- ");
+ else
+ g_string_append_printf (ser, "-- %.3fs %.3fs ", clip->start, clip->end);
+ g_string_append_printf (ser, "%s\n", clip->filter_graph);
+ }
+ else if (strlen(path)== 0 &&
+ clip->start == 0 &&
+ clip->end == 0 &&
+ clip->filter_graph)
{
g_string_append_printf (ser, "--%s\n", clip->filter_graph);
}
diff --git a/gcut/gcut.h b/gcut/gcut.h
index bcc58f0..9528a13 100644
--- a/gcut/gcut.h
+++ b/gcut/gcut.h
@@ -179,6 +179,7 @@ struct _GeglEDL
char *parent_path;
GList *clip_db;
GList *clips;
+
int frame; /* render thread, frame_no_ui is ui side */
double pos; /* render thread, frame_pos_ui is ui side */
double fps;
@@ -216,9 +217,10 @@ struct _GeglEDL
int framedrop;
int ui_mode;
- GeglNode *result;
- GeglNode *store_final_buf;
GeglNode *mix;
+ GeglNode *video_result;
+ GeglNode *final_result;
+ GeglNode *store_final_buf;
GeglNode *encode;
double scale;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]