forked from enlightenment/efl
emotion: make Xv work.
NOTE: we need the help of the window manager to make this really work. So for the moment, it half work. As soon as I hack E17, the Xv fast path for Emotion will only work when used with E17 and it will fallback to canvas inlined rendering in other case. SVN revision: 63802
This commit is contained in:
parent
4376c4f995
commit
35c9a8f56c
|
@ -22,7 +22,8 @@ pkg_LTLIBRARIES = gstreamer.la
|
|||
gstreamer_la_SOURCES = \
|
||||
emotion_gstreamer.c \
|
||||
emotion_sink.c \
|
||||
emotion_alloc.c
|
||||
emotion_alloc.c \
|
||||
emotion_fakeeos.c
|
||||
gstreamer_la_LIBADD = @ECORE_X_LIBS@ @GSTREAMER_LIBS@ @GSTREAMER_INTERFACE_LIBS@ $(top_builddir)/src/lib/libemotion.la
|
||||
gstreamer_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
|
||||
gstreamer_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
|
|
@ -237,6 +237,8 @@ static Emotion_Video_Module em_module =
|
|||
NULL /* handle */
|
||||
};
|
||||
|
||||
static int priority_overide = 0;
|
||||
|
||||
static Emotion_Video_Stream *
|
||||
emotion_video_stream_new(Emotion_Gstreamer_Video *ev)
|
||||
{
|
||||
|
@ -404,6 +406,7 @@ em_cleanup(Emotion_Gstreamer_Video *ev)
|
|||
if (ev->xvpad) gst_object_unref(ev->xvpad);
|
||||
ev->xvpad = NULL;
|
||||
|
||||
fprintf(stderr, "destroying window: %i\n", ev->win);
|
||||
if (ev->win) ecore_x_window_free(ev->win);
|
||||
ev->win = 0;
|
||||
}
|
||||
|
@ -1226,6 +1229,7 @@ em_priority_set(void *video, Eina_Bool pri)
|
|||
Emotion_Gstreamer_Video *ev;
|
||||
|
||||
ev = video;
|
||||
if (priority_overide > 3) return ; /* If we failed to much to create that pipeline, let's don't wast our time anymore */
|
||||
ev->priority = pri;
|
||||
}
|
||||
|
||||
|
@ -1238,6 +1242,16 @@ em_priority_get(void *video)
|
|||
return ev->stream;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_ecore_event_x_destroy(void *data, int type, void *event)
|
||||
{
|
||||
Ecore_X_Event_Window_Destroy *ev = event;
|
||||
|
||||
fprintf(stderr, "killed window: %x (%x)\n", ev->win, ev->event_win);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
module_open(Evas_Object *obj,
|
||||
const Emotion_Video_Module **module,
|
||||
|
@ -1263,6 +1277,8 @@ module_open(Evas_Object *obj,
|
|||
if (!em_module.init(obj, video, opt))
|
||||
return EINA_FALSE;
|
||||
|
||||
ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _ecore_event_x_destroy, NULL);
|
||||
|
||||
eina_threads_init();
|
||||
|
||||
*module = &em_module;
|
||||
|
@ -1524,12 +1540,16 @@ _eos_main_fct(void *data)
|
|||
case GST_MESSAGE_STREAM_STATUS:
|
||||
break;
|
||||
case GST_MESSAGE_ERROR:
|
||||
ERR("Switching back to composited rendering.");
|
||||
em_cleanup(ev);
|
||||
|
||||
ev->priority = EINA_FALSE;
|
||||
if (ev->priority)
|
||||
{
|
||||
ERR("Switching back to canvas rendering.");
|
||||
ev->priority = EINA_FALSE;
|
||||
priority_overide++;
|
||||
|
||||
ecore_idler_add(_em_restart_stream, ev);
|
||||
ecore_idler_add(_em_restart_stream, ev);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERR("bus say: %s [%i - %s]",
|
||||
|
@ -1642,9 +1662,11 @@ _emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev,
|
|||
|
||||
res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
if (res == GST_STATE_CHANGE_NO_PREROLL)
|
||||
gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
|
||||
{
|
||||
gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
|
||||
|
||||
res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
}
|
||||
|
||||
/** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */
|
||||
/** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */
|
||||
|
|
|
@ -78,6 +78,7 @@ struct _Emotion_Gstreamer_Video
|
|||
GstElement *pipeline;
|
||||
GstElement *sink;
|
||||
GstElement *esink;
|
||||
GstElement *xvsink;
|
||||
GstElement *tee;
|
||||
GstPad *teepad;
|
||||
GstPad *xvpad;
|
||||
|
@ -138,7 +139,6 @@ struct _Emotion_Gstreamer_Video
|
|||
Eina_Bool delete_me : 1;
|
||||
Eina_Bool samsung : 1;
|
||||
Eina_Bool kill_buffer : 1;
|
||||
Eina_Bool linked : 1;
|
||||
Eina_Bool stream : 1;
|
||||
Eina_Bool priority : 1;
|
||||
};
|
||||
|
@ -210,6 +210,8 @@ extern int _emotion_gstreamer_log_domain;
|
|||
|
||||
#define EVAS_TYPE_VIDEO_SINK evas_video_sink_get_type()
|
||||
|
||||
GType fakeeos_bin_get_type(void);
|
||||
|
||||
#define EVAS_VIDEO_SINK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
|
||||
EVAS_TYPE_VIDEO_SINK, EvasVideoSink))
|
||||
|
@ -230,6 +232,8 @@ extern int _emotion_gstreamer_log_domain;
|
|||
(G_TYPE_INSTANCE_GET_CLASS((obj), \
|
||||
EVAS_TYPE_VIDEO_SINK, EvasVideoSinkClass))
|
||||
|
||||
#define GST_TYPE_FAKEEOS_BIN fakeeos_bin_get_type()
|
||||
|
||||
GstElement *gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
||||
Evas_Object *obj,
|
||||
const char *uri);
|
||||
|
|
|
@ -730,6 +730,12 @@ evas_video_sink_samsung_main_render(void *data)
|
|||
evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height);
|
||||
evas_object_image_pixels_dirty_set(priv->o, 0);
|
||||
|
||||
if (!preroll && send->ev->play_started)
|
||||
{
|
||||
_emotion_playback_started(send->ev->obj);
|
||||
send->ev->play_started = 0;
|
||||
}
|
||||
|
||||
_emotion_frame_new(send->ev->obj);
|
||||
|
||||
vstream = eina_list_nth(send->ev->video_streams, send->ev->video_stream_nbr - 1);
|
||||
|
@ -790,6 +796,7 @@ evas_video_sink_main_render(void *data)
|
|||
if (ev->send)
|
||||
emotion_gstreamer_buffer_free(ev->send);
|
||||
ev->send = send;
|
||||
evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height);
|
||||
goto exit_stream;
|
||||
}
|
||||
|
||||
|
@ -812,6 +819,12 @@ evas_video_sink_main_render(void *data)
|
|||
evas_object_image_data_update_add(priv->o, 0, 0, priv->width, priv->height);
|
||||
evas_object_image_pixels_dirty_set(priv->o, 0);
|
||||
|
||||
if (!preroll && ev->play_started)
|
||||
{
|
||||
_emotion_playback_started(ev->obj);
|
||||
ev->play_started = 0;
|
||||
}
|
||||
|
||||
_emotion_frame_new(ev->obj);
|
||||
|
||||
gst_element_query_position(ev->pipeline, &fmt, &pos);
|
||||
|
@ -944,10 +957,17 @@ static void
|
|||
_emotion_gstreamer_pause(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
Emotion_Gstreamer_Video *ev = data;
|
||||
gboolean res;
|
||||
|
||||
if (ecore_thread_check(thread) || !ev->pipeline) return ;
|
||||
|
||||
gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
|
||||
res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
if (res == GST_STATE_CHANGE_NO_PREROLL)
|
||||
{
|
||||
gst_element_set_state(ev->pipeline, GST_STATE_PLAYING);
|
||||
gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1009,19 +1029,51 @@ _video_move(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *s
|
|||
{
|
||||
Emotion_Gstreamer_Video *ev = data;
|
||||
|
||||
fprintf(stderr, "move: %i, %i\n", x, y);
|
||||
ecore_x_window_move(ev->win, x, y);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Much better idea to always feed the XvImageSink and let him handle optimizing the rendering as we do */
|
||||
static void
|
||||
_block_pad_unlink_cb(GstPad *pad, gboolean blocked, gpointer user_data)
|
||||
{
|
||||
if (blocked)
|
||||
{
|
||||
Emotion_Gstreamer_Video *ev = user_data;
|
||||
GstEvent *gev;
|
||||
|
||||
gst_pad_unlink(ev->teepad, ev->xvpad);
|
||||
gev = gst_event_new_eos();
|
||||
gst_pad_send_event(ev->xvpad, gev);
|
||||
gst_pad_set_blocked_async(pad, FALSE, _block_pad_unlink_cb, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_block_pad_link_cb(GstPad *pad, gboolean blocked, gpointer user_data)
|
||||
{
|
||||
if (blocked)
|
||||
{
|
||||
Emotion_Gstreamer_Video *ev = user_data;
|
||||
|
||||
gst_pad_link(ev->teepad, ev->xvpad);
|
||||
if (ev->play)
|
||||
gst_element_set_state(ev->xvsink, GST_STATE_PLAYING);
|
||||
else
|
||||
gst_element_set_state(ev->xvsink, GST_STATE_PAUSED);
|
||||
gst_pad_set_blocked_async(pad, FALSE, _block_pad_link_cb, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_video_show(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *surface __UNUSED__)
|
||||
{
|
||||
Emotion_Gstreamer_Video *ev = data;
|
||||
|
||||
fprintf(stderr, "show xwin %i\n", ev->win);
|
||||
|
||||
ecore_x_window_show(ev->win);
|
||||
gst_pad_link(ev->teepad, ev->xvpad);
|
||||
ev->linked = EINA_TRUE;
|
||||
/* gst_pad_set_blocked_async(ev->teepad, TRUE, _block_pad_link_cb, ev); */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1029,11 +1081,8 @@ _video_hide(void *data, Evas_Object *obj __UNUSED__, const Evas_Video_Surface *s
|
|||
{
|
||||
Emotion_Gstreamer_Video *ev = data;
|
||||
|
||||
fprintf(stderr, "hide xwin: %i\n", ev->win);
|
||||
|
||||
ecore_x_window_hide(ev->win);
|
||||
gst_pad_unlink(ev->teepad, ev->xvpad);
|
||||
ev->linked = EINA_FALSE;
|
||||
/* gst_pad_set_blocked_async(ev->teepad, TRUE, _block_pad_unlink_cb, ev); */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1101,8 +1150,6 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
|||
goto unref_pipeline;
|
||||
}
|
||||
|
||||
fprintf(stderr, "priority: %i\n", ev->priority);
|
||||
|
||||
#if defined HAVE_ECORE_X && defined HAVE_XOVERLAY_H
|
||||
engines = evas_render_method_list();
|
||||
|
||||
|
@ -1113,25 +1160,41 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
|||
Ecore_Evas *ee;
|
||||
Evas_Coord x, y, w, h;
|
||||
Ecore_X_Window win;
|
||||
Ecore_X_Window parent;
|
||||
|
||||
evas_object_geometry_get(obj, &x, &y, &w, &h);
|
||||
|
||||
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||
|
||||
if (w < 1) w = 1;
|
||||
if (h < 1) h = 1;
|
||||
if (w < 4) w = 4;
|
||||
if (h < 2) h = 2;
|
||||
|
||||
win = ecore_x_window_new((Ecore_X_Window) ecore_evas_window_get(ee), x, y, w, h);
|
||||
/* Here we really need to have the help of the window manager, this code will change when we update E17. */
|
||||
parent = (Ecore_X_Window) ecore_evas_window_get(ee);
|
||||
fprintf(stderr, "parent: %x\n", parent);
|
||||
|
||||
win = ecore_x_window_override_new(0, x, y, w, h);
|
||||
fprintf(stderr, "creating window: %x [%i, %i, %i, %i]\n", win, x, y, w, h);
|
||||
if (win)
|
||||
{
|
||||
ecore_x_window_show(win);
|
||||
xvsink = gst_element_factory_make("xvimagesink", NULL);
|
||||
if (xvsink)
|
||||
{
|
||||
Ecore_X_Atom atom;
|
||||
|
||||
gst_x_overlay_set_window_handle(GST_X_OVERLAY(xvsink), win);
|
||||
ev->win = win;
|
||||
|
||||
atom = ecore_x_atom_get("enlightenment.video");
|
||||
if (atom)
|
||||
{
|
||||
ecore_x_window_prop_card32_set(win, atom, &parent, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "destroying win: %x\n", win);
|
||||
ecore_x_window_free(win);
|
||||
}
|
||||
}
|
||||
|
@ -1161,7 +1224,7 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
|||
goto unref_pipeline;
|
||||
}
|
||||
|
||||
gst_bin_add_many(GST_BIN(bin), tee, queue, esink, xvsink, NULL);
|
||||
gst_bin_add_many(GST_BIN(bin), tee, queue, esink, NULL);
|
||||
gst_element_link_many(queue, esink, NULL);
|
||||
|
||||
/* link both sink to GstTee */
|
||||
|
@ -1173,23 +1236,36 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
|||
|
||||
if (xvsink)
|
||||
{
|
||||
GstElement *fakeeos;
|
||||
|
||||
queue = gst_element_factory_make("queue", NULL);
|
||||
if (queue)
|
||||
fakeeos = GST_ELEMENT(GST_BIN(g_object_new(GST_TYPE_FAKEEOS_BIN, "name", "eosbin", NULL)));
|
||||
if (queue && fakeeos)
|
||||
{
|
||||
gst_bin_add_many(GST_BIN(bin), queue, NULL);
|
||||
gst_element_link_many(queue, xvsink, NULL);
|
||||
GstPad *queue_pad;
|
||||
|
||||
pad = gst_element_get_pad(queue, "sink");
|
||||
teepad = gst_element_get_request_pad(tee, "src%d");
|
||||
gst_pad_link(teepad, pad);
|
||||
gst_bin_add_many(GST_BIN(bin), fakeeos, NULL);
|
||||
|
||||
ev->teepad = teepad;
|
||||
ev->xvpad = pad;
|
||||
gst_bin_add_many(GST_BIN(fakeeos), queue, xvsink, NULL);
|
||||
gst_element_link_many(queue, xvsink, NULL);
|
||||
queue_pad = gst_element_get_pad(queue, "sink");
|
||||
gst_element_add_pad(fakeeos, gst_ghost_pad_new("sink", queue_pad));
|
||||
|
||||
pad = gst_element_get_pad(fakeeos, "sink");
|
||||
teepad = gst_element_get_request_pad(tee, "src%d");
|
||||
gst_pad_link(teepad, pad);
|
||||
|
||||
xvsink = fakeeos;
|
||||
|
||||
ev->teepad = teepad;
|
||||
ev->xvpad = pad;
|
||||
}
|
||||
else
|
||||
{
|
||||
gst_object_unref(xvsink);
|
||||
xvsink = NULL;
|
||||
if (fakeeos) gst_object_unref(fakeeos);
|
||||
if (queue) gst_object_unref(queue);
|
||||
gst_object_unref(xvsink);
|
||||
xvsink = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1230,10 +1306,10 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
|||
}
|
||||
|
||||
eina_stringshare_replace(&ev->uri, uri);
|
||||
ev->linked = EINA_TRUE;
|
||||
ev->pipeline = playbin;
|
||||
ev->sink = bin;
|
||||
ev->esink = esink;
|
||||
ev->xvsink = xvsink;
|
||||
ev->tee = tee;
|
||||
ev->threads = eina_list_append(ev->threads,
|
||||
ecore_thread_run(_emotion_gstreamer_pause,
|
||||
|
|
Loading…
Reference in New Issue