[gegl] bin: always use nearest neighbor blitting during playback
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] bin: always use nearest neighbor blitting during playback
- Date: Sat, 18 May 2019 01:26:22 +0000 (UTC)
commit 8f7f0581780dab2e3a996e88d99cd5de6575111a
Author: Øyvind Kolås <pippin gimp org>
Date: Sat May 18 03:20:55 2019 +0200
bin: always use nearest neighbor blitting during playback
Also add start of support for using different image file formats for
frame cache.
bin/ui-core.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++---------
bin/ui.h | 1 -
2 files changed, 113 insertions(+), 20 deletions(-)
---
diff --git a/bin/ui-core.c b/bin/ui-core.c
index c148980a4..cbc5f72b8 100644
--- a/bin/ui-core.c
+++ b/bin/ui-core.c
@@ -813,6 +813,71 @@ static gchar *pos_hash (GeState *o)
return ret;
}
+/* .ppm, .exr, .tif, .jpg, .png, .geglbuffer
+ *
+ */
+//static char *frame_ext = ".png";
+//static char *frame_ext = ".jpg";
+//static char *frame_ext = ".exr";
+//static char *frame_ext = ".tif";
+//static char *frame_ext = ".ppm";
+static char *frame_ext = ".geglbuffer";
+
+static GeglBuffer *_gegl_buffer_load (const char *path)
+{
+ GeglBuffer *buffer = NULL;
+ GeglNode *gegl, *load, *sink;
+ if (!strcmp (frame_ext, ".geglbuffer"))
+ {
+ buffer = gegl_buffer_load (path);
+ }
+ else
+ {
+ gegl = gegl_node_new ();
+ load = gegl_node_new_child (gegl, "operation", "gegl:load",
+ "path", path,
+ NULL);
+ sink = gegl_node_new_child (gegl, "operation", "gegl:buffer-sink",
+ "buffer", &buffer,
+ NULL);
+ gegl_node_link_many (load, sink, NULL);
+ gegl_node_process (sink);
+ g_object_unref (gegl);
+ }
+ return buffer;
+}
+
+static void _gegl_buffer_save (GeglBuffer *buffer,
+ const char *path)
+{
+ if (!strcmp (frame_ext, ".geglbuffer"))
+ {
+ gegl_buffer_save (buffer, path, NULL);
+ }
+ else
+ {
+ GeglNode *gegl, *load, *sink;
+ gegl = gegl_node_new ();
+ load = gegl_node_new_child (gegl, "operation", "gegl:buffer-source",
+ "buffer", buffer,
+ NULL);
+ if (!strcmp (frame_ext, ".png"))
+ sink = gegl_node_new_child (gegl, "operation", "gegl:png-save",
+ "compression", 2,
+ "bitdepth", 8,
+ "path", path,
+ NULL);
+ else
+ sink = gegl_node_new_child (gegl, "operation", "gegl:save",
+ "path", path,
+ NULL);
+ gegl_node_link_many (load, sink, NULL);
+ gegl_node_process (sink);
+ g_object_unref (gegl);
+ }
+}
+
+
static int has_quit = 0;
static GeglAudioFragment *cached_audio = NULL;
@@ -893,7 +958,7 @@ static int frame_cache_check (GeState *o, const char *hash)
{
char *dir = get_item_dir (o);
- path = g_strdup_printf ("%s/.gegl/frame_cache/%s", dir, hash);
+ path = g_strdup_printf ("%s/.gegl/frame_cache/%s%s", dir, hash, frame_ext);
g_free (dir);
}
@@ -901,7 +966,8 @@ static int frame_cache_check (GeState *o, const char *hash)
{
if (o->cached_buffer)
g_object_unref (o->cached_buffer);
- o->cached_buffer = gegl_buffer_open (path);
+ //o->cached_buffer = gegl_buffer_open (path);
+ o->cached_buffer = _gegl_buffer_load (path);
ret = 1;
}
g_free (path);
@@ -914,12 +980,13 @@ static void frame_cache_store (GeState *o, const char *hash)
{
char *path = NULL;
char *dir = get_item_dir (o);
- path = g_strdup_printf ("%s/.gegl/frame_cache/%s", dir, hash);
+ path = g_strdup_printf ("%s/.gegl/frame_cache/%s%s", dir, hash, frame_ext);
g_free (dir);
if (!g_file_test (path, G_FILE_TEST_EXISTS))
{
- gegl_buffer_save (o->processor_buffer, path, NULL);
+ //gegl_buffer_save (o->processor_buffer, path, NULL);
+ _gegl_buffer_save (o->processor_buffer, path);
}
else
{
@@ -928,6 +995,7 @@ static void frame_cache_store (GeState *o, const char *hash)
g_free (path);
}
+static uint32_t prev_complete_ms = 0;
static gboolean renderer_task (gpointer data)
{
@@ -936,7 +1004,7 @@ static gboolean renderer_task (gpointer data)
void *old_processor = o->processor;
GeglBuffer *old_buffer = o->processor_buffer;
static char *hash = NULL;
-
+ static guint32 render_start = 0;
#define TASK_BASE 0
#define TASK_RENDER 1
@@ -944,6 +1012,10 @@ static gboolean renderer_task (gpointer data)
#define TASK_THUMB 3
#define TASK_PCM_FRAME_CACHE 4
+ if (prev_complete_ms == 0)
+ prev_complete_ms = mrg_ms (o->mrg);
+
+
switch (o->renderer_state)
{
case TASK_BASE:
@@ -957,6 +1029,7 @@ static gboolean renderer_task (gpointer data)
if (renderer_dirty)
{
renderer_dirty = 0;
+ render_start = mrg_ms (o->mrg);
g_clear_object (&o->cached_buffer);
if (o->processor_node != o->sink)
@@ -982,7 +1055,7 @@ static gboolean renderer_task (gpointer data)
//if (o->frame_cache)
/* we always check for cache - this makes the cache kick-in when turned off but cached entries are
valid */
-
+ hash = pos_hash (o);
if (frame_cache_check (o, hash))
{
o->renderer_state = TASK_RENDER_DONE;
@@ -997,7 +1070,7 @@ static gboolean renderer_task (gpointer data)
}
else
{
- g_usleep (4000);
+ g_usleep (500);
o->renderer_state = TASK_BASE;
}
}
@@ -1034,6 +1107,19 @@ static gboolean renderer_task (gpointer data)
break;
case TASK_RENDER_DONE:
mrg_gegl_dirty ();
+ {
+ guint32 ms = mrg_ms (o->mrg);
+ float fps = 1.0/((ms-prev_complete_ms)/1000.0);
+ static float avgfps = 0.0;
+ float dt = 0.9;
+ avgfps = avgfps * dt + fps * (1.0-dt);
+
+ fprintf (stderr, "frame delta: %ims %.3ffps render time:%ims \r", ms-prev_complete_ms,
+ avgfps, ms-render_start);
+ prev_complete_ms = ms;
+ }
+
+
switch (renderer)
{
case GEGL_RENDERER_IDLE:
@@ -1041,7 +1127,7 @@ static gboolean renderer_task (gpointer data)
break;
case GEGL_RENDERER_THREAD:
mrg_queue_draw (o->mrg, NULL);
- g_usleep (4000);
+ g_usleep (500);
break;
}
@@ -1094,7 +1180,7 @@ static gboolean renderer_task (gpointer data)
thumb_queue_item_free (item);
}
}
- g_usleep (1000);
+ g_usleep (500);
}
o->renderer_state = TASK_BASE;
@@ -1143,8 +1229,8 @@ static gboolean renderer_task (gpointer data)
wait until the pcm buffer is nearly ready to play
back our content
*/
- while (mrg_pcm_get_queued_length (o->mrg) > (1.0/o->fps) * 1.25 )
- g_usleep (100);
+ while (mrg_pcm_get_queued_length (o->mrg) > (1.0/o->fps) * 1.5 )
+ g_usleep (10);
}
}
@@ -1156,7 +1242,7 @@ static gboolean renderer_task (gpointer data)
int channels = gegl_audio_fragment_get_channels (audio);
char *path = NULL;
char *dir = get_item_dir (o);
- path = g_strdup_printf ("%s/.gegl/frame_cache/%s.png", dir, hash);
+ path = g_strdup_printf ("%s/.gegl/frame_cache/%s.pcm", dir, hash);
g_free (dir);
g_string_append_printf (str, "%i %i %i %i",
@@ -5368,6 +5454,12 @@ static void gegl_ui (Mrg *mrg, void *data)
cairo_paint (mrg_cr (mrg));
}
else
+ {
+ int nearest = 0;
+ if (o->playing != 0 ||
+ o->nearest_neighbor)
+ nearest = 1;
+
switch (renderer)
{
case GEGL_RENDERER_BLIT:
@@ -5379,7 +5471,7 @@ static void gegl_ui (Mrg *mrg, void *data)
o->u, o->v,
o->scale,
o->render_quality,
- o->nearest_neighbor,
+ nearest,
o->color_managed_display);
break;
case GEGL_RENDERER_THREAD:
@@ -5392,6 +5484,7 @@ static void gegl_ui (Mrg *mrg, void *data)
buffer = g_object_ref (o->cached_buffer);
else
buffer = g_object_ref (o->processor_buffer);
+
mrg_gegl_buffer_blit (mrg,
0, 0,
mrg_width (mrg), mrg_height (mrg),
@@ -5399,14 +5492,17 @@ static void gegl_ui (Mrg *mrg, void *data)
o->u, o->v,
o->scale,
o->render_quality,
- o->nearest_neighbor,
+ nearest,
o->color_managed_display);
+
+
g_object_unref (buffer);
} else {
fprintf (stderr, "lacking buffer\n");
}
break;
}
+ }
if (o->show_controls && 0)
@@ -5674,10 +5770,6 @@ static void gegl_ui (Mrg *mrg, void *data)
ui_show_bindings (mrg, o);
}
- /* iterate frame, and queue pcm last - since this might cause
- waiting with presenting the video frame until the pcm data
- of the frame is about to be played
- */
if (o->playing)
{
iterate_frame (o);
@@ -5910,7 +6002,10 @@ static void load_path_inner (GeState *o,
gegl_node_process (o->source);
+ {
+
gegl_node_get (o->source, "frame-rate", &fps, "frames", &frames, NULL);
+ }
o->fps = fps;
if (o->duration < 0)
@@ -6446,7 +6541,6 @@ photos_gegl_buffer_apply_orientation (GeglBuffer *buffer_original, Orientation o
}
-
static void load_into_buffer (GeState *o, const char *path)
{
GeglNode *gegl, *load, *sink;
diff --git a/bin/ui.h b/bin/ui.h
index fbc31b13f..6759c2de3 100644
--- a/bin/ui.h
+++ b/bin/ui.h
@@ -54,7 +54,6 @@ enum _SortOrder
SORT_ORDER_CUSTOM = 512, /* gets or'ed with - other selection */
};
-
struct _GeState {
GObject parent;
void (*ui) (Mrg *mrg, void *state);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]