From 49e455f481387d2d6ad24c8b318276fcb2f41b24 Mon Sep 17 00:00:00 2001 From: Daniel Zaoui Date: Sun, 10 Jun 2018 11:58:40 +0300 Subject: [PATCH] Player: try to stabilize screenshotting Buffer evas cannot be used when the application is shown on the screen. It means the _sync_shot_get function cannot work always. That is a problem when the stabilization feature is used. That's why we need to use snapshot no matter the case. The problem is that snapshot seems to sit on the canvas and therefore doesn't forward the events, such as mouse down... So we need to create a snapshot only when needed. Additionally, stabilization feature needed to be finished. The threshold to guarantee the stabilization was not implemented. --- src/bin/player.c | 201 ++++++++++++++++++++++++----------------------- 1 file changed, 102 insertions(+), 99 deletions(-) diff --git a/src/bin/player.c b/src/bin/player.c index 0fd10b9..de1977e 100644 --- a/src/bin/player.c +++ b/src/bin/player.c @@ -145,28 +145,100 @@ _printf(int verbose, const char *fmt, ...) va_end(ap); } +static Exactness_Image * +_snapshot_shot_get(Evas *e) +{ + Exactness_Image *ex_img; + Evas_Object *snapshot; + void *pixels; + int w, h, nb_bytes; + + if (!e) return NULL; + + evas_output_size_get(e, &w, &h); + if ((w < 1) || (h < 1)) return NULL; + + snapshot = efl_key_data_get(e, "_snapshot"); + if (!snapshot) + { + snapshot = evas_object_image_filled_add(e); + if (snapshot) + { + evas_object_image_snapshot_set(snapshot, EINA_TRUE); + evas_object_geometry_set(snapshot, 0, 0, w, h); + efl_gfx_entity_visible_set(snapshot, EINA_TRUE); + efl_key_data_set(e, "_snapshot", snapshot); + } + return NULL; + } + + pixels = evas_object_image_data_get(snapshot, EINA_FALSE); + if (!pixels) return NULL; + + ex_img = malloc(sizeof(*ex_img)); + nb_bytes = w * h * 4; + ex_img->w = w; + ex_img->h = h; + ex_img->pixels = malloc(nb_bytes); + memcpy(ex_img->pixels, pixels, nb_bytes); + return ex_img; +} + +static void +_evas_render_post_cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + if (_shot_needed) + { + Evas_Event_Render_Post *post = event->info; + void *e_data = efl_key_data_get(event->object, "_shot"); + + // Nothing was updated, so let's not bother sending nothingness + if (post && !post->updated_area) return; + Exactness_Image *ex_shot = efl_key_data_get(event->object, "_last_shot"); + if (!ex_shot) ex_shot = _snapshot_shot_get(event->object); + if (!ex_shot) return; + + efl_key_data_set(event->object, "_last_shot", NULL); + + if (_dest_type == FTYPE_DIR) + { + char *filename = e_data; + Eo *o = evas_object_image_add(event->object); + evas_object_image_size_set(o, ex_shot->w, ex_shot->h); + evas_object_image_data_set(o, ex_shot->pixels); + _printf(1, "Shot taken (%s).\n", filename); + if (!evas_object_image_save(o, filename, NULL, NULL)) + { + printf("Cannot save widget to <%s>\n", filename); + } + free(filename); + } + else if (_dest_type == FTYPE_EXU) + { + Exactness_Image *ex_img = e_data; + memcpy(ex_img, ex_shot, sizeof(Exactness_Image)); + ex_shot->pixels = NULL; + _printf(1, "Shot taken (in %s).\n", _dest); + } + exactness_image_free(ex_shot); + efl_key_data_set(event->object, "_shot", NULL); + evas_object_del(efl_key_data_get(event->object, "_snapshot")); + efl_key_data_set(event->object, "_snapshot", NULL); + /* This part is needed when the shot is needed at the end of the scenario. + * As it is async, we need to wait for the shot termination. */ + _shot_needed = EINA_FALSE; + if (_exit_required) ecore_main_loop_quit(); + } +} + static void _shot_do(Evas *e) { - Ecore_Evas *ee_orig; - int w, h; - if (!e) return; - ee_orig = ecore_evas_ecore_evas_get(e); - - ecore_evas_geometry_get(ee_orig, NULL, NULL, &w, &h); - if ((w < 1) || (h < 1)) return; - if (!_disable_shots) { void *e_data = NULL; - Evas_Object *snapshot = evas_object_image_filled_add(e); - if (!snapshot) return; - evas_object_image_snapshot_set(snapshot, EINA_TRUE); - - evas_object_geometry_set(snapshot, 0, 0, w, h); - efl_gfx_entity_visible_set(snapshot, EINA_TRUE); if (_dest_type == FTYPE_DIR) { @@ -184,15 +256,16 @@ _shot_do(Evas *e) else if (_dest_type == FTYPE_EXU) { Exactness_Image *ex_img = malloc(sizeof(*ex_img)); - ex_img->w = w; - ex_img->h = h; _dest_unit->imgs = eina_list_append(_dest_unit->imgs, ex_img); _dest_unit->nb_shots++; e_data = ex_img; } efl_key_data_set(e, "_shot", e_data); - efl_key_data_set(e, "_snapshot", snapshot); _shot_needed = EINA_TRUE; + Efl_Event ev; + ev.info = NULL; + ev.object = e; + _evas_render_post_cb(NULL, &ev); } if (_scan_objects && _dest_type == FTYPE_EXU) @@ -234,34 +307,6 @@ _shot_do(Evas *e) } } -static Exactness_Image * -_sync_shot_get(Evas *e) -{ - Exactness_Image *ex_img; - Ecore_Evas *ee_orig; - unsigned int *pixels; - int w, h, nb_bytes; - - if (!e) return NULL; - - ee_orig = ecore_evas_ecore_evas_get(e); - - ecore_evas_manual_render(ee_orig); - pixels = (void *)ecore_evas_buffer_pixels_get(ee_orig); - if (!pixels) return NULL; - - ecore_evas_geometry_get(ee_orig, NULL, NULL, &w, &h); - if ((w < 1) || (h < 1)) return NULL; - - ex_img = malloc(sizeof(*ex_img)); - nb_bytes = w * h * 4; - ex_img->w = w; - ex_img->h = h; - ex_img->pixels = malloc(nb_bytes); - memcpy(ex_img->pixels, pixels, nb_bytes); - return ex_img; -} - static void _feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data) { @@ -490,12 +535,15 @@ _stabilization_timer_cb(void *data EINA_UNUSED) { Eina_List *itr; Evas *e; - Eina_Bool need_more = EINA_FALSE; +#define STAB_MAX 5 + static int need_more = STAB_MAX; EINA_LIST_FOREACH(_evas_list, itr, e) { Exactness_Image *last_img = efl_key_data_get(e, "_last_shot"); - Exactness_Image *cur_img = _sync_shot_get(e); - if (!last_img || exactness_image_compare(last_img, cur_img, NULL)) need_more = EINA_TRUE; + Exactness_Image *cur_img = _snapshot_shot_get(e); + if (!last_img || exactness_image_compare(last_img, cur_img, NULL)) need_more = STAB_MAX; + if (need_more != STAB_MAX) printf("cur == last\n"); + else printf("cur != last\n"); exactness_image_free(last_img); efl_key_data_set(e, "_last_shot", cur_img); } @@ -503,9 +551,8 @@ _stabilization_timer_cb(void *data EINA_UNUSED) { if (!need_more) { - Exactness_Image *last_img = efl_key_data_get(e, "_last_shot"); - exactness_image_free(last_img); - efl_key_data_set(e, "_last_shot", NULL); + evas_object_del(efl_key_data_get(e, "_snapshot")); + efl_key_data_set(e, "_snapshot", NULL); } } if (!need_more) @@ -516,56 +563,12 @@ _stabilization_timer_cb(void *data EINA_UNUSED) _printf(2, " %s timer_time=<%f>\n", __func__, act->delay_ms / 1000.0); ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL); } + need_more = STAB_MAX; + printf("end stab\n"); return ECORE_CALLBACK_CANCEL; } - else return ECORE_CALLBACK_RENEW; -} - -static void -_evas_render_post_cb(void *data EINA_UNUSED, const Efl_Event *event) -{ - if (_shot_needed) - { - Evas_Event_Render_Post *post = event->info; - void *e_data = efl_key_data_get(event->object, "_shot"); - Evas_Object *snapshot = efl_key_data_get(event->object, "_snapshot"); - void *pixels; - int w, h; - - // Nothing was updated, so let's not bother sending nothingness - if (!post->updated_area) return; - pixels = evas_object_image_data_get(snapshot, EINA_FALSE); - if (!pixels) return; - evas_object_geometry_get(snapshot, NULL, NULL, &w, &h); - - if (_dest_type == FTYPE_DIR) - { - char *filename = e_data; - Eo *o = evas_object_image_add(event->object); - evas_object_image_size_set(o, w, h); - evas_object_image_data_set(o, pixels); - _printf(1, "Shot taken (%s).\n", filename); - if (!evas_object_image_save(o, filename, NULL, NULL)) - { - printf("Cannot save widget to <%s>\n", filename); - } - free(filename); - } - else if (_dest_type == FTYPE_EXU) - { - int nb_bytes = w * h * 4; - Exactness_Image *ex_img = e_data; - ex_img->pixels = malloc(nb_bytes); - memcpy(ex_img->pixels, pixels, nb_bytes); - _printf(1, "Shot taken (in %s).\n", _dest); - } - efl_key_data_set(event->object, "_shot", NULL); - evas_object_del(snapshot); - /* This part is needed when the shot is needed at the end of the scenario. - * As it is async, we need to wait for the shot termination. */ - _shot_needed = EINA_FALSE; - if (_exit_required) ecore_main_loop_quit(); - } + need_more--; + return ECORE_CALLBACK_RENEW; } static void