Added support to creating animated thumbnails from videos.

These thumbnails are generated using an edje template. Each thumbnail is
an edje file, that has a group called "movie/thumb"
The thumbnail can be animated by receiving a signal "animate" or "animate_loop"
(the last one being a loop animation that calls itself when finished), and
the animate_loop program can be stopped by receiving a signal "animate_stop".
The transition time is set based on the time of the animation (that is set
by the call ethumb_video_time_set()).



SVN revision: 41322
This commit is contained in:
Rafael Antognolli 2009-07-13 19:38:17 +00:00
parent 2dd7e38b96
commit 31fc2b0dfa
12 changed files with 681 additions and 29 deletions

View File

@ -31,7 +31,7 @@
#include <Ecore.h>
const char *aspect_opt[] = { "keep", "ignore", "crop", NULL };
const char *format_opt[] = { "png", "jpg", NULL };
const char *format_opt[] = { "png", "jpg", "eet", NULL };
struct frame
{
const char *file;
@ -182,7 +182,7 @@ main(int argc, char *argv[])
r = 0;
}
for (i = 0; i < 2; i++)
for (i = 0; i < 3; i++)
if (format_opt[i] == format_str)
{
format = i;

View File

@ -70,6 +70,10 @@ struct _Ethumb_Setup
Eina_Bool category : 1;
Eina_Bool frame : 1;
Eina_Bool video_time : 1;
Eina_Bool video_start : 1;
Eina_Bool video_interval : 1;
Eina_Bool video_ntimes : 1;
Eina_Bool video_fps : 1;
Eina_Bool document_page : 1;
} flags;
int fdo;
@ -85,6 +89,10 @@ struct _Ethumb_Setup
const char *group;
const char *swallow;
float video_time;
float video_start;
float video_interval;
int video_ntimes;
int video_fps;
int document_page;
};
@ -477,12 +485,16 @@ _ethumbd_pipe_write_setup(int fd, int type, const void *data)
case ETHUMBD_SIZE_W:
case ETHUMBD_SIZE_H:
case ETHUMBD_DOCUMENT_PAGE:
case ETHUMBD_VIDEO_NTIMES:
case ETHUMBD_VIDEO_FPS:
i_value = data;
_ethumbd_write_safe(fd, i_value, sizeof(*i_value));
break;
case ETHUMBD_CROP_X:
case ETHUMBD_CROP_Y:
case ETHUMBD_VIDEO_TIME:
case ETHUMBD_VIDEO_START:
case ETHUMBD_VIDEO_INTERVAL:
f_value = data;
_ethumbd_write_safe(fd, f_value, sizeof(*f_value));
break;
@ -544,6 +556,15 @@ _process_setup(struct _Ethumbd *ed)
}
if (setup->flags.video_time)
_ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_TIME, &setup->video_time);
if (setup->flags.video_start)
_ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_START, &setup->video_start);
if (setup->flags.video_interval)
_ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_INTERVAL,
&setup->video_interval);
if (setup->flags.video_ntimes)
_ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_NTIMES, &setup->video_ntimes);
if (setup->flags.video_fps)
_ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_FPS, &setup->video_fps);
if (setup->flags.document_page)
_ethumbd_pipe_write_setup(fd, ETHUMBD_DOCUMENT_PAGE,
&setup->document_page);
@ -1327,6 +1348,90 @@ _ethumb_dbus_video_time_set(struct _Ethumb_Object *eobject, DBusMessageIter *ite
return 1;
}
static int
_ethumb_dbus_video_start_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request)
{
int type;
double video_start;
type = dbus_message_iter_get_arg_type(iter);
if (type != DBUS_TYPE_DOUBLE)
{
ERR("invalid param for video_start_set.\n");
return 0;
}
dbus_message_iter_get_basic(iter, &video_start);
DBG("setting video_start to: %3.2f\n", video_start);
request->setup.flags.video_start = 1;
request->setup.video_start = video_start;
return 1;
}
static int
_ethumb_dbus_video_interval_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request)
{
int type;
double video_interval;
type = dbus_message_iter_get_arg_type(iter);
if (type != DBUS_TYPE_DOUBLE)
{
ERR("invalid param for video_interval_set.\n");
return 0;
}
dbus_message_iter_get_basic(iter, &video_interval);
DBG("setting video_interval to: %3.2f\n", video_interval);
request->setup.flags.video_interval = 1;
request->setup.video_interval = video_interval;
return 1;
}
static int
_ethumb_dbus_video_ntimes_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request)
{
int type;
int video_ntimes;
type = dbus_message_iter_get_arg_type(iter);
if (type != DBUS_TYPE_INT32)
{
ERR("invalid param for video_ntimes_set.\n");
return 0;
}
dbus_message_iter_get_basic(iter, &video_ntimes);
DBG("setting video_ntimes to: %3.2d\n", video_ntimes);
request->setup.flags.video_ntimes = 1;
request->setup.video_ntimes = video_ntimes;
return 1;
}
static int
_ethumb_dbus_video_fps_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request)
{
int type;
int video_fps;
type = dbus_message_iter_get_arg_type(iter);
if (type != DBUS_TYPE_INT32)
{
ERR("invalid param for video_fps_set.\n");
return 0;
}
dbus_message_iter_get_basic(iter, &video_fps);
DBG("setting video_fps to: %3.2d\n", video_fps);
request->setup.flags.video_fps = 1;
request->setup.video_fps = video_fps;
return 1;
}
static int
_ethumb_dbus_document_page_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request)
{
@ -1364,6 +1469,10 @@ static struct
{ "directory", _ethumb_dbus_directory_set },
{ "category", _ethumb_dbus_category_set },
{ "video_time", _ethumb_dbus_video_time_set },
{ "video_start", _ethumb_dbus_video_start_set },
{ "video_interval", _ethumb_dbus_video_interval_set },
{ "video_ntimes", _ethumb_dbus_video_ntimes_set },
{ "video_fps", _ethumb_dbus_video_fps_set },
{ "document_page", _ethumb_dbus_document_page_set },
{ NULL, NULL}
};

View File

@ -475,6 +475,66 @@ _ec_video_time_set(struct _Ethumbd_Child *ec, Ethumb *e)
return 1;
}
static int
_ec_video_start_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
int r;
float value;
r = _ec_read_safe(ec->pipein, &value, sizeof(value));
if (!r)
return 0;
ethumb_video_start_set(e, value);
DBG("video_start = %f\n", value);
return 1;
}
static int
_ec_video_interval_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
int r;
float value;
r = _ec_read_safe(ec->pipein, &value, sizeof(value));
if (!r)
return 0;
ethumb_video_interval_set(e, value);
DBG("video_interval = %f\n", value);
return 1;
}
static int
_ec_video_ntimes_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
int r;
int value;
r = _ec_read_safe(ec->pipein, &value, sizeof(value));
if (!r)
return 0;
ethumb_video_ntimes_set(e, value);
DBG("video_ntimes = %d\n", value);
return 1;
}
static int
_ec_video_fps_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
int r;
int value;
r = _ec_read_safe(ec->pipein, &value, sizeof(value));
if (!r)
return 0;
ethumb_video_fps_set(e, value);
DBG("video_fps = %d\n", value);
return 1;
}
static int
_ec_document_page_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
@ -532,6 +592,18 @@ _ec_setup_process(struct _Ethumbd_Child *ec, int index, int type)
case ETHUMBD_VIDEO_TIME:
_ec_video_time_set(ec, e);
break;
case ETHUMBD_VIDEO_START:
_ec_video_start_set(ec, e);
break;
case ETHUMBD_VIDEO_INTERVAL:
_ec_video_interval_set(ec, e);
break;
case ETHUMBD_VIDEO_NTIMES:
_ec_video_ntimes_set(ec, e);
break;
case ETHUMBD_VIDEO_FPS:
_ec_video_fps_set(ec, e);
break;
case ETHUMBD_DOCUMENT_PAGE:
_ec_document_page_set(ec, e);
break;

View File

@ -27,6 +27,10 @@ enum Ethubmd_Setup_Option
ETHUMBD_FRAME_GROUP,
ETHUMBD_FRAME_SWALLOW,
ETHUMBD_VIDEO_TIME,
ETHUMBD_VIDEO_START,
ETHUMBD_VIDEO_INTERVAL,
ETHUMBD_VIDEO_NTIMES,
ETHUMBD_VIDEO_FPS,
ETHUMBD_DOCUMENT_PAGE,
ETHUMBD_SETUP_FINISHED
};

View File

@ -190,6 +190,11 @@ ethumb_new(void)
ethumb->crop_y = 0.5;
ethumb->quality = 80;
ethumb->compress = 9;
ethumb->video.start = 0.1;
ethumb->video.time = 3;
ethumb->video.interval = 0.05;
ethumb->video.ntimes = 3;
ethumb->video.fps = 10;
ee = ecore_evas_buffer_new(1, 1);
e = ecore_evas_get(ee);
@ -562,6 +567,22 @@ ethumb_thumb_category_get(const Ethumb *e)
return e->category;
}
EAPI void
ethumb_video_start_set(Ethumb *e, float start)
{
EINA_SAFETY_ON_NULL_RETURN(e);
e->video.start = start;
}
EAPI float
ethumb_video_start_get(const Ethumb *e)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
return e->video.start;
}
EAPI void
ethumb_video_time_set(Ethumb *e, float time)
{
@ -578,6 +599,54 @@ ethumb_video_time_get(const Ethumb *e)
return e->video.time;
}
EAPI void
ethumb_video_interval_set(Ethumb *e, float interval)
{
EINA_SAFETY_ON_NULL_RETURN(e);
e->video.interval = interval;
}
EAPI float
ethumb_video_interval_get(const Ethumb *e)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
return e->video.interval;
}
EAPI void
ethumb_video_ntimes_set(Ethumb *e, int ntimes)
{
EINA_SAFETY_ON_NULL_RETURN(e);
e->video.ntimes = ntimes;
}
EAPI int
ethumb_video_ntimes_get(const Ethumb *e)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
return e->video.ntimes;
}
EAPI void
ethumb_video_fps_set(Ethumb *e, int fps)
{
EINA_SAFETY_ON_NULL_RETURN(e);
e->video.fps = fps;
}
EAPI int
ethumb_video_fps_get(const Ethumb *e)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
return e->video.fps;
}
EAPI void
ethumb_document_page_set(Ethumb *e, int page)
{

View File

@ -105,8 +105,18 @@ EAPI const char * ethumb_thumb_dir_path_get(const Ethumb *e) EINA_WARN_UNUSED_RE
EAPI void ethumb_thumb_category_set(Ethumb *e, const char *category) EINA_ARG_NONNULL(1);
EAPI const char * ethumb_thumb_category_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void ethumb_video_start_set(Ethumb *e, float start) EINA_ARG_NONNULL(1);
EAPI float ethumb_video_start_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void ethumb_video_time_set(Ethumb *e, float time) EINA_ARG_NONNULL(1);
EAPI float ethumb_video_time_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void ethumb_video_interval_set(Ethumb *e, float interval) EINA_ARG_NONNULL(1);
EAPI float ethumb_video_interval_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void ethumb_video_ntimes_set(Ethumb *e, int ntimes) EINA_ARG_NONNULL(1);
EAPI int ethumb_video_ntimes_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void ethumb_video_fps_set(Ethumb *e, int fps) EINA_ARG_NONNULL(1);
EAPI int ethumb_video_fps_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void ethumb_document_page_set(Ethumb *e, int page) EINA_ARG_NONNULL(1);
EAPI int ethumb_document_page_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;

View File

@ -604,8 +604,8 @@ ethumb_client_ethumb_setup(Ethumb_Client *client)
double t;
const char *theme_file, *group, *swallow;
const char *directory, *category;
double video_time;
dbus_int32_t document_page;
double video_time, video_start, video_interval;
dbus_int32_t video_ntimes, video_fps, document_page;
EINA_SAFETY_ON_NULL_RETURN(client);
client->ethumb_dirty = 0;
@ -692,6 +692,26 @@ ethumb_client_ethumb_setup(Ethumb_Client *client)
dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_time);
_close_variant_iter(viter);
_open_variant_iter("video_start", "d", viter);
video_start = ethumb_video_start_get(e);
dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_start);
_close_variant_iter(viter);
_open_variant_iter("video_interval", "d", viter);
video_interval = ethumb_video_interval_get(e);
dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_interval);
_close_variant_iter(viter);
_open_variant_iter("video_ntimes", "i", viter);
video_ntimes = ethumb_video_ntimes_get(e);
dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &video_ntimes);
_close_variant_iter(viter);
_open_variant_iter("video_fps", "i", viter);
video_fps = ethumb_video_fps_get(e);
dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &video_fps);
_close_variant_iter(viter);
_open_variant_iter("document_page", "i", viter);
document_page = ethumb_document_page_get(e);
dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &document_page);
@ -1147,6 +1167,42 @@ ethumb_client_video_time_set(Ethumb_Client *client, float time)
ethumb_video_time_set(client->ethumb, time);
}
EAPI void
ethumb_client_video_start_set(Ethumb_Client *client, float start)
{
EINA_SAFETY_ON_NULL_RETURN(client);
client->ethumb_dirty = 1;
ethumb_video_start_set(client->ethumb, start);
}
EAPI void
ethumb_client_video_interval_set(Ethumb_Client *client, float interval)
{
EINA_SAFETY_ON_NULL_RETURN(client);
client->ethumb_dirty = 1;
ethumb_video_interval_set(client->ethumb, interval);
}
EAPI void
ethumb_client_video_ntimes_set(Ethumb_Client *client, int ntimes)
{
EINA_SAFETY_ON_NULL_RETURN(client);
client->ethumb_dirty = 1;
ethumb_video_ntimes_set(client->ethumb, ntimes);
}
EAPI void
ethumb_client_video_fps_set(Ethumb_Client *client, int fps)
{
EINA_SAFETY_ON_NULL_RETURN(client);
client->ethumb_dirty = 1;
ethumb_video_fps_set(client->ethumb, fps);
}
EAPI void
ethumb_client_document_page_set(Ethumb_Client *client, int page)
{

View File

@ -72,6 +72,10 @@ EAPI const char * ethumb_client_dir_path_get(const Ethumb_Client *client);
EAPI void ethumb_client_category_set(Ethumb_Client *client, const char *category);
EAPI const char * ethumb_client_category_get(const Ethumb_Client *client);
EAPI void ethumb_client_video_time_set(Ethumb_Client *client, float time);
EAPI void ethumb_client_video_start_set(Ethumb_Client *client, float start);
EAPI void ethumb_client_video_interval_set(Ethumb_Client *client, float interval);
EAPI void ethumb_client_video_ntimes_set(Ethumb_Client *client, int ntimes);
EAPI void ethumb_client_video_fps_set(Ethumb_Client *client, int fps);
EAPI void ethumb_client_document_page_set(Ethumb_Client *client, int page);
EAPI void ethumb_client_ethumb_setup(Ethumb_Client *client);

View File

@ -28,7 +28,8 @@ struct _Ethumb
int rw, rh;
struct
{
double time;
double start, time, interval;
int ntimes, fps;
} video;
struct
{

View File

@ -1,12 +1,28 @@
MAINTAINERCLEANFILES = Makefile.in
EDJE_CC = edje_cc
EDJE_FLAGS = -v
filesdir = $(pluginsdir)/data
files_DATA = emotion_template.edj
EXTRA_DIST= \
template.edc
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/emotion \
@EVAS_CFLAGS@ @EINA_CFLAGS@ @EMOTION_CFLAGS@ @ECORE_CFLAGS@
@EVAS_CFLAGS@ @EINA_CFLAGS@ @EMOTION_CFLAGS@ @ECORE_CFLAGS@ \
@EDJE_CFLAGS@
pkgdir = $(pluginsdir)
pkg_LTLIBRARIES = emotion.la
emotion_la_SOURCES = emotion.c
emotion_la_DEPENDENCIES = $(top_builddir)/config.h
emotion_la_LIBADD = $(top_builddir)/src/lib/libethumb.la \
@EVAS_LIBS@ @EINA_LIBS@ @EMOTION_LIBS@ @ECORE_LIBS@
@EVAS_LIBS@ @EINA_LIBS@ @EMOTION_LIBS@ @ECORE_LIBS@ @EDJE_LIBS@
emotion_la_LDFLAGS = -module -avoid-version
emotion_template.edj: Makefile $(EXTRADIST)
$(EDJE_CC) $(EDJE_FLAGS) \
$(top_srcdir)/src/plugins/emotion/template.edc \
$(top_builddir)/src/plugins/emotion/emotion_template.edj

View File

@ -5,31 +5,280 @@
#include <stdio.h>
#include <stdlib.h>
#include <Eina.h>
#include <Eet.h>
#include <Ecore_File.h>
#include <Evas.h>
#include <Edje.h>
#include <Edje_Edit.h>
#include <Emotion.h>
static Evas_Object *_emotion = NULL;
struct _emotion_plugin
{
int fps;
double ptotal, len, pi;
double total_time, tmp_time;
int pcount;
int frnum;
int first;
Eet_File *ef;
Evas_Object *video;
Ethumb *e;
int w, h;
};
static void
_resize_movie(struct _emotion_plugin *_plugin)
{
Ethumb *e = _plugin->e;
double ratio;
int w, h;
int fx, fy, fw, fh;
ratio = emotion_object_ratio_get(_plugin->video);
ethumb_calculate_aspect_from_ratio(e, ratio, &w, &h);
ethumb_calculate_fill_from_ratio(e, ratio, &fx, &fy, &fw, &fh);
_plugin->w = w;
_plugin->h = h;
ethumb_plugin_image_resize(e, _plugin->w, _plugin->h);
evas_object_resize(_plugin->video, fw, fh);
evas_object_move(_plugin->video, fx, fy);
emotion_object_audio_mute_set(_plugin->video, 1);
}
static void
_frame_resized_cb(void *data, Evas_Object *o, void *event_info)
{
Ethumb *e = data;
Evas_Coord ww, hh;
Evas_Coord mw, mh;
_resize_movie(data);
}
emotion_object_size_get(o, &mw, &mh);
ethumb_calculate_aspect(e, mw, mh, &ww, &hh);
ethumb_plugin_image_resize(e, ww, hh);
static void
_video_stopped_cb(void *data, Evas_Object *o, void *event_info)
{
struct _emotion_plugin *_plugin = data;
evas_object_resize(o, ww, hh);
evas_object_move(o, 0, 0);
_plugin->pi = 0;
_plugin->ptotal = 0;
_plugin->first = 0;
_plugin->total_time = _plugin->tmp_time;
}
static void
_video_pos_set(struct _emotion_plugin *_plugin)
{
double pos;
double interval;
pos = ethumb_video_start_get(_plugin->e);
interval = ethumb_video_interval_get(_plugin->e);
_plugin->len = emotion_object_play_length_get(_plugin->video);
if (_plugin->len > 0)
_plugin->first = 1;
if (pos <=0 || pos >= 1)
_plugin->pi = 0.2 * _plugin->len + _plugin->pcount *
_plugin->len * interval;
else
_plugin->pi = pos * _plugin->len + _plugin->pcount *
_plugin->len * interval;
emotion_object_position_set(_plugin->video, _plugin->pi);
}
static int
_setup_thumbnail(struct _emotion_plugin *_plugin)
{
char buf[4096];
Evas *evas;
Evas_Object *edje;
int i;
const char *thumb_path;
ethumb_thumb_path_get(_plugin->e, &thumb_path, NULL);
evas = ethumb_evas_get(_plugin->e);
if (!edje_file_group_exists(thumb_path, "movie/thumb"))
{
fprintf(stderr, "ERROR: no group 'movie/thumb' found.\n");
goto exit_error;
}
edje = edje_object_add(evas);
edje_object_file_set(edje, thumb_path, "movie/thumb");
if (!edje_object_part_exists(edje, "image"))
{
fprintf(stderr, "ERROR: no 'image' part found.\n");
evas_object_del(edje);
goto exit_error;
}
if (!edje_edit_program_exist(edje, "animate"))
{
fprintf(stderr, "ERROR: no 'animate' program found.\n");
evas_object_del(edje);
goto exit_error;
}
for (i = 0; i < _plugin->frnum; i++)
{
snprintf(buf, sizeof(buf), "images/%d", i);
edje_edit_image_data_add(edje, buf, i);
if (i == 0)
edje_edit_state_image_set(edje, "image", "default 0.00", buf);
else
edje_edit_state_tween_add(edje, "image", "default 0.00", buf);
}
edje_edit_program_transition_time_set(edje, "animate",
_plugin->total_time);
edje_edit_program_transition_time_set(edje, "animate_loop",
_plugin->total_time);
edje_edit_group_min_w_set(edje, _plugin->w);
edje_edit_group_max_w_set(edje, _plugin->w);
edje_edit_group_min_h_set(edje, _plugin->h);
edje_edit_group_max_h_set(edje, _plugin->h);
edje_edit_save(edje);
evas_object_del(edje);
return 1;
exit_error:
return 0;
}
static void
_finish_thumb_generation(struct _emotion_plugin *_plugin, int success)
{
int r = 0;
evas_object_smart_callback_del(_plugin->video, "frame_resize",
_frame_resized_cb);
emotion_object_play_set(_plugin->video, 0);
evas_object_del(_plugin->video);
if (_plugin->ef)
eet_close(_plugin->ef);
if (success)
r = _setup_thumbnail(_plugin);
free(_plugin);
ethumb_finished_callback_call(_plugin->e, r);
}
static int
_frame_grab_single(void *data)
{
struct _emotion_plugin *_plugin = data;
Ethumb *e = _plugin->e;
double p;
if (_plugin->len <= 0)
{
_video_pos_set(_plugin);
return EINA_TRUE;
}
p = emotion_object_position_get(_plugin->video);
if (p < _plugin->pi)
return EINA_TRUE;
ethumb_image_save(e);
evas_object_smart_callback_del(o, "frame_resize", _frame_resized_cb);
emotion_object_play_set(o, 0);
evas_object_del(o);
evas_object_smart_callback_del(_plugin->video, "frame_resize",
_frame_resized_cb);
emotion_object_play_set(_plugin->video, 0);
evas_object_del(_plugin->video);
free(_plugin);
ethumb_finished_callback_call(e, 1);
return EINA_FALSE;
}
static int
_frame_grab(void *data)
{
struct _emotion_plugin *_plugin = data;
Ethumb *e = _plugin->e;
char buf[4096];
const void *pixels;
double p;
if (_plugin->len <= 0)
{
_video_pos_set(_plugin);
return EINA_TRUE;
}
p = emotion_object_position_get(_plugin->video);
if (p < _plugin->pi)
return EINA_TRUE;
if (_plugin->first)
{
_plugin->pi = p;
_plugin->first = 0;
}
if (p > _plugin->pi + _plugin->ptotal)
{
_plugin->total_time += _plugin->tmp_time;
if (_plugin->pcount >= ethumb_video_ntimes_get(e))
{
_finish_thumb_generation(_plugin, EINA_TRUE);
return EINA_FALSE;
}
else
{
_plugin->pcount++;
_video_pos_set(_plugin);
return EINA_TRUE;
}
}
_plugin->tmp_time = p - _plugin->pi;
if (_plugin->ef)
{
Ecore_Evas *ee = ethumb_ecore_evas_get(e);
int quality, compress;
quality = ethumb_thumb_quality_get(e);
compress = ethumb_thumb_compress_get(e);
pixels = ecore_evas_buffer_pixels_get(ee);
snprintf(buf, sizeof(buf), "images/%d", _plugin->frnum);
eet_data_image_write(_plugin->ef, buf, pixels, _plugin->w, _plugin->h,
0, compress, quality, quality);
_plugin->frnum++;
}
return EINA_TRUE;
}
static void
_generate_animated_thumb(struct _emotion_plugin *_plugin)
{
const char *thumb_path;
char *thumb_dir;
char buf[4096];
Ethumb *e = _plugin->e;
snprintf(buf, sizeof(buf), "%s/data/emotion_template.edj", PLUGINSDIR);
ethumb_thumb_path_get(e, &thumb_path, NULL);
thumb_dir = ecore_file_dir_get(thumb_path);
ecore_file_mkpath(thumb_dir);
free(thumb_dir);
ecore_file_cp(buf, thumb_path);
_plugin->ef = eet_open(thumb_path, EET_FILE_MODE_READ_WRITE);
if (!_plugin->ef)
{
fprintf(stderr, "ERROR: could not open '%s'\n", thumb_path);
_finish_thumb_generation(_plugin, 0);
}
ecore_timer_add(1.0 / ethumb_video_fps_get(e), _frame_grab, _plugin);
}
static void
@ -38,7 +287,9 @@ _generate_thumb(Ethumb *e)
Evas_Object *o;
int r;
const char *file;
float time;
float start;
Ethumb_Thumb_Format f;
struct _emotion_plugin *_plugin = calloc(sizeof(struct _emotion_plugin), 1);
o = emotion_object_add(ethumb_evas_get(e));
r = emotion_object_init(o, "xine");
@ -48,28 +299,48 @@ _generate_thumb(Ethumb *e)
" plugin.\n");
evas_object_del(o);
ethumb_finished_callback_call(e, 0);
free(_plugin);
return;
}
_plugin->video = o;
ethumb_file_get(e, &file, NULL);
time = ethumb_video_time_get(e);
start = ethumb_video_start_get(e);
f = ethumb_thumb_format_get(e);
emotion_object_file_set(o, file);
emotion_object_position_set(o, time);
_plugin->video = o;
_plugin->e = e;
_plugin->ptotal = ethumb_video_time_get(e) / ethumb_video_ntimes_get(e);
_plugin->pcount = 1;
_resize_movie(_plugin);
evas_object_smart_callback_add(o, "frame_resize",
_frame_resized_cb, _plugin);
evas_object_smart_callback_add(o, "decode_stop",
_video_stopped_cb, _plugin);
if (f == ETHUMB_THUMB_EET)
{
_generate_animated_thumb(_plugin);
}
else
{
ecore_timer_add(0.1, _frame_grab_single, _plugin);
}
_video_pos_set(_plugin);
emotion_object_play_set(o, 1);
evas_object_smart_callback_add(o, "frame_resize", _frame_resized_cb, e);
evas_object_show(o);
_emotion = o;
}
EAPI Ethumb_Plugin *
ethumb_plugin_get(void)
{
static const char *extensions[] = { "avi", NULL };
static const char *extensions[] = { "avi", "mp4", "ogv", NULL };
static Ethumb_Plugin plugin =
{
extensions,

View File

@ -0,0 +1,40 @@
collections {
group {
name: "movie/thumb";
parts {
part {
name: "image";
type: IMAGE;
description {
state: "default" 0.0;
}
}
}
programs {
program {
name: "animate";
signal: "animate";
action: STATE_SET "default" 0.0;
transition: LINEAR 3.0;
target: "image";
}
program {
name: "animate_loop";
signal: "animate_loop";
action: STATE_SET "default" 0.0;
transition: LINEAR 3.0;
target: "image";
after: "animate_loop";
}
program {
name: "animate_stop";
signal: "animate_stop";
action: ACTION_STOP;
target: "animate_loop";
}
}
}
}