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.
This commit is contained in:
Daniel Zaoui 2018-06-10 11:58:40 +03:00
parent e59cca6fce
commit 49e455f481
1 changed files with 102 additions and 99 deletions

View File

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