emotion: remove (broken) X11 integration from the GStreamer 1.x backend.

This code was disabled and did not work properly. If this should be
re-added it will have to be rewritten anyway and currently it only
clutters the existing code.

Reviewers: cedric

CC: cedric

Differential Revision: https://phab.enlightenment.org/D414

Signed-off-by: Cedric BAIL <cedric.bail@samsung.com>
This commit is contained in:
Sebastian Dröge 2013-12-27 09:56:11 +09:00 committed by Cedric BAIL
parent 922fe6c109
commit 1875e4725f
5 changed files with 10 additions and 555 deletions

View File

@ -91,7 +91,6 @@ modules/emotion/gstreamer1/emotion_gstreamer.h \
modules/emotion/gstreamer1/emotion_gstreamer.c \
modules/emotion/gstreamer1/emotion_alloc.c \
modules/emotion/gstreamer1/emotion_convert.c \
modules/emotion/gstreamer1/emotion_fakeeos.c \
modules/emotion/gstreamer1/emotion_sink.c
if EMOTION_STATIC_BUILD_GSTREAMER1
@ -110,11 +109,6 @@ modules_emotion_gstreamer1_module_la_LIBADD = \
modules_emotion_gstreamer1_module_la_DEPENDENCIES = @USE_EMOTION_INTERNAL_LIBS@
modules_emotion_gstreamer1_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
modules_emotion_gstreamer1_module_la_LIBTOOLFLAGS = --tag=disable-static
if HAVE_ECORE_X
modules_emotion_gstreamer1_module_la_CPPFLAGS += @ECORE_X_CFLAGS@ @ECORE_EVAS_CFLAGS@
modules_emotion_gstreamer1_module_la_LIBADD += @USE_ECORE_X_LIBS@ @USE_ECORE_EVAS_LIBS@
modules_emotion_gstreamer1_module_la_DEPENDENCIES += @USE_ECORE_X_INTERNAL_LIBS@ @USE_ECORE_EVAS_INTERNAL_LIBS@
endif
endif
endif

View File

@ -1,47 +0,0 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "emotion_gstreamer.h"
typedef struct _FakeEOSBin
{
GstBin parent;
} FakeEOSBin;
typedef struct _FakeEOSBinClass
{
GstBinClass parent;
} FakeEOSBinClass;
G_DEFINE_TYPE (FakeEOSBin, fakeeos_bin, GST_TYPE_BIN);
static void
fakeeos_bin_handle_message(GstBin * bin, GstMessage * message)
{
/* FakeEOSBin *fakeeos = (FakeEOSBin *)(bin); */
switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_EOS:
/* what to do here ? just returning at the moment */
return;
default:
break;
}
GST_BIN_CLASS(fakeeos_bin_parent_class)->handle_message(bin, message);
}
static void
fakeeos_bin_class_init(FakeEOSBinClass * klass)
{
GstBinClass *gstbin_class = GST_BIN_CLASS(klass);
gstbin_class->handle_message =
GST_DEBUG_FUNCPTR (fakeeos_bin_handle_message);
}
static void
fakeeos_bin_init(FakeEOSBin *src EINA_UNUSED)
{
}

View File

@ -4,12 +4,9 @@
#include "emotion_gstreamer.h"
Eina_Bool window_manager_video = EINA_FALSE;
int _emotion_gstreamer_log_domain = -1;
Eina_Bool debug_fps = EINA_FALSE;
Eina_Bool _ecore_x_available = EINA_FALSE;
static Ecore_Idler *restart_idler;
static int _emotion_init_count = 0;
/* Callbacks to get the eos */
@ -20,13 +17,8 @@ static GstBusSyncReply _eos_sync_fct(GstBus *bus,
GstMessage *message,
gpointer data);
static Eina_Bool _em_restart_stream(void *data);
/* Module interface */
static int priority_overide = 0;
static Emotion_Video_Stream *
emotion_video_stream_new(Emotion_Gstreamer_Video *ev)
{
@ -137,27 +129,8 @@ em_cleanup(Emotion_Gstreamer_Video *ev)
ev->pipeline = NULL;
ev->sink = NULL;
if (ev->eteepad) gst_object_unref(ev->eteepad);
ev->eteepad = NULL;
if (ev->xvteepad) gst_object_unref(ev->xvteepad);
ev->xvteepad = NULL;
if (ev->xvpad) gst_object_unref(ev->xvpad);
ev->xvpad = NULL;
ev->src_width = 0;
ev->src_height = 0;
#ifdef HAVE_ECORE_X
INF("destroying window: %i", ev->win);
if (ev->win) ecore_x_window_free(ev->win);
ev->win = 0;
#endif
}
if (restart_idler)
{
ecore_idler_del(restart_idler);
restart_idler = NULL;
}
EINA_LIST_FREE(ev->audio_streams, astream)
@ -1065,106 +1038,6 @@ em_meta_get(void *video, int meta)
return str;
}
static void
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 */
if (ev->priority != pri && ev->pipeline)
{
if (ev->threads)
{
Ecore_Thread *t;
EINA_LIST_FREE(ev->threads, t)
ecore_thread_cancel(t);
}
em_cleanup(ev);
restart_idler = ecore_idler_add(_em_restart_stream, ev);
}
ev->priority = pri;
}
static Eina_Bool
em_priority_get(void *video)
{
Emotion_Gstreamer_Video *ev;
ev = video;
return !ev->stream;
}
#ifdef HAVE_ECORE_X
static Eina_Bool
_ecore_event_x_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
{
Ecore_X_Event_Window_Destroy *ev = event;
INF("killed window: %x (%x).", ev->win, ev->event_win);
return EINA_TRUE;
}
static void
gstreamer_ecore_x_check(void)
{
Ecore_X_Window *roots;
int num;
ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _ecore_event_x_destroy, NULL);
/* Check if the window manager is able to handle our special Xv window. */
roots = ecore_x_window_root_list(&num);
if (roots && num > 0)
{
Ecore_X_Window win, twin;
int nwins;
nwins = ecore_x_window_prop_window_get(roots[0],
ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
&win, 1);
if (nwins > 0)
{
nwins = ecore_x_window_prop_window_get(win,
ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
&twin, 1);
if (nwins > 0 && twin == win)
{
Ecore_X_Atom *supported;
int supported_num;
int i;
if (ecore_x_netwm_supported_get(roots[0], &supported, &supported_num))
{
Eina_Bool parent = EINA_FALSE;
Eina_Bool video_position = EINA_FALSE;
for (i = 0; i < supported_num; ++i)
{
if (supported[i] == ECORE_X_ATOM_E_VIDEO_PARENT)
parent = EINA_TRUE;
else if (supported[i] == ECORE_X_ATOM_E_VIDEO_POSITION)
video_position = EINA_TRUE;
if (parent && video_position)
break;
}
if (parent && video_position)
{
window_manager_video = EINA_TRUE;
}
}
free(supported);
}
}
}
free(roots);
}
#endif
static void *
em_add(const Emotion_Engine *api,
Evas_Object *obj,
@ -1253,8 +1126,8 @@ static const Emotion_Engine em_engine =
em_speed_get, /* speed_get */
em_eject, /* eject */
em_meta_get, /* meta_get */
em_priority_set, /* priority_set */
em_priority_get /* priority_get */
NULL, /* priority_set */
NULL /* priority_get */
};
Eina_Bool
@ -1286,14 +1159,6 @@ gstreamer_module_init(void)
goto error_gst_init;
}
#ifdef HAVE_ECORE_X
if (ecore_x_init(NULL) > 0)
{
_ecore_x_available = EINA_TRUE;
gstreamer_ecore_x_check();
}
#endif
if (gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
"emotion-sink",
"video sink plugin for Emotion",
@ -1319,14 +1184,6 @@ gstreamer_module_init(void)
error_register:
error_gst_plugin:
#ifdef HAVE_ECORE_X
if (_ecore_x_available)
{
ecore_x_shutdown();
_ecore_x_available = EINA_FALSE;
window_manager_video = EINA_FALSE;
}
#endif
gst_deinit();
@ -1354,15 +1211,6 @@ gstreamer_module_shutdown(void)
_emotion_module_unregister(&em_engine);
#ifdef HAVE_ECORE_X
if (_ecore_x_available)
{
ecore_x_shutdown();
_ecore_x_available = EINA_FALSE;
window_manager_video = EINA_FALSE;
}
#endif
eina_log_domain_unregister(_emotion_gstreamer_log_domain);
_emotion_gstreamer_log_domain = -1;
@ -1507,32 +1355,6 @@ _free_metadata(Emotion_Gstreamer_Metadata *m)
free(m);
}
static Eina_Bool
_em_restart_stream(void *data)
{
Emotion_Gstreamer_Video *ev;
ev = data;
ev->pipeline = gstreamer_video_sink_new(ev, ev->obj, ev->uri);
if (ev->pipeline)
{
ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline));
if (!ev->eos_bus)
{
ERR("could not get the bus");
return EINA_FALSE;
}
gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev, NULL);
}
restart_idler = NULL;
return ECORE_CALLBACK_CANCEL;
}
static Eina_Bool
_video_size_get(GstElement *elem, int *width, int *height)
{
@ -1687,15 +1509,6 @@ _eos_main_fct(void *data)
break;
case GST_MESSAGE_ERROR:
em_cleanup(ev);
if (ev->priority)
{
ERR("Switching back to canvas rendering.");
ev->priority = EINA_FALSE;
priority_overide++;
restart_idler = ecore_idler_add(_em_restart_stream, ev);
}
break;
default:
ERR("bus say: %s [%i - %s]",
@ -1769,16 +1582,12 @@ _eos_sync_fct(GstBus *bus EINA_UNUSED, GstMessage *msg, gpointer data)
g_error_free(error);
g_free(debug);
/* FIXME: This is broken */
if (strncmp(GST_OBJECT_NAME(msg->src), "xvimagesink", 11) == 0)
{
send = emotion_gstreamer_message_alloc(ev, msg);
send = emotion_gstreamer_message_alloc(ev, msg);
if (send)
{
_emotion_pending_ecore_begin();
ecore_main_loop_thread_safe_call_async(_eos_main_fct, send);
}
if (send)
{
_emotion_pending_ecore_begin();
ecore_main_loop_thread_safe_call_async(_eos_main_fct, send);
}
break;
}

View File

@ -18,14 +18,6 @@
#include <gst/audio/audio.h>
#include <gst/tag/tag.h>
// forcibly disable x overlay window.. broken badly.
#undef HAVE_ECORE_X
#ifdef HAVE_ECORE_X
# include <Ecore_X.h>
# include <gst/video/videooverlay.h>
#endif
typedef void (*Evas_Video_Convert_Cb)(unsigned char *evas_data,
const unsigned char *gst_data,
unsigned int w,
@ -75,13 +67,8 @@ struct _Emotion_Gstreamer_Video
GstElement *pipeline;
GstElement *sink;
GstElement *esink;
GstElement *xvsink;
GstElement *tee;
GstElement *convert;
GstPad *eteepad;
GstPad *xvteepad;
GstPad *xvpad;
Eina_List *threads;
/* eos */
@ -110,10 +97,6 @@ struct _Emotion_Gstreamer_Video
Emotion_Gstreamer_Metadata *metadata;
#ifdef HAVE_ECORE_X
Ecore_X_Window win;
#endif
const char *uri;
Emotion_Gstreamer_Buffer *send;
@ -144,7 +127,6 @@ struct _Emotion_Gstreamer_Video
Eina_Bool delete_me : 1;
Eina_Bool kill_buffer : 1;
Eina_Bool stream : 1;
Eina_Bool priority : 1;
int src_width;
int src_height;
@ -162,8 +144,6 @@ struct _EvasVideoSinkClass {
};
struct _EvasVideoSinkPrivate {
EINA_REFCOUNT;
Evas_Object *o;
Emotion_Gstreamer_Video *ev;
@ -206,10 +186,8 @@ struct _Emotion_Gstreamer_Message
GstMessage *msg;
};
extern Eina_Bool window_manager_video;
extern Eina_Bool debug_fps;
extern int _emotion_gstreamer_log_domain;
extern Eina_Bool _ecore_x_available;
extern Eina_Bool debug_fps;
#ifdef DBG
#undef DBG
@ -238,8 +216,6 @@ extern Eina_Bool _ecore_x_available;
#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))
@ -260,8 +236,6 @@ GType fakeeos_bin_get_type(void);
(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);

View File

@ -599,132 +599,6 @@ _emotion_gstreamer_end(void *data, Ecore_Thread *thread)
_emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE);
}
static void
_video_resize(void *data, Evas_Object *obj EINA_UNUSED, const Evas_Video_Surface *surface EINA_UNUSED,
Evas_Coord w, Evas_Coord h)
{
#ifdef HAVE_ECORE_X
Emotion_Gstreamer_Video *ev = data;
ecore_x_window_resize(ev->win, w, h);
DBG("resize: %i, %i", w, h);
#else
if (data)
{
DBG("resize: %i, %i (fake)", w, h);
}
#endif
}
static void
_video_move(void *data, Evas_Object *obj EINA_UNUSED, const Evas_Video_Surface *surface EINA_UNUSED,
Evas_Coord x, Evas_Coord y)
{
#ifdef HAVE_ECORE_X
Emotion_Gstreamer_Video *ev = data;
unsigned int pos[2];
DBG("move: %i, %i", x, y);
pos[0] = x; pos[1] = y;
ecore_x_window_prop_card32_set(ev->win, ECORE_X_ATOM_E_VIDEO_POSITION, pos, 2);
#else
if (data)
{
DBG("move: %i, %i (fake)", x, y);
}
#endif
}
#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->xvteepad, 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->xvteepad, 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 EINA_UNUSED, const Evas_Video_Surface *surface EINA_UNUSED)
{
#ifdef HAVE_ECORE_X
Emotion_Gstreamer_Video *ev = data;
DBG("show xv");
ecore_x_window_show(ev->win);
#else
if (data)
{
DBG("show xv (fake)");
}
#endif
/* gst_pad_set_blocked_async(ev->xvteepad, TRUE, _block_pad_link_cb, ev); */
}
static void
_video_hide(void *data, Evas_Object *obj EINA_UNUSED, const Evas_Video_Surface *surface EINA_UNUSED)
{
#ifdef HAVE_ECORE_X
Emotion_Gstreamer_Video *ev = data;
DBG("hide xv");
ecore_x_window_hide(ev->win);
#else
if (data)
{
DBG("hide xv (fake)");
}
#endif
/* gst_pad_set_blocked_async(ev->xvteepad, TRUE, _block_pad_unlink_cb, ev); */
}
static void
_video_update_pixels(void *data, Evas_Object *obj EINA_UNUSED, const Evas_Video_Surface *surface EINA_UNUSED)
{
Emotion_Gstreamer_Video *ev = data;
Emotion_Gstreamer_Buffer *send;
if (!ev->send) return;
send = ev->send;
send->force = EINA_TRUE;
ev->send = NULL;
_emotion_pending_ecore_begin();
evas_video_sink_main_render(send);
}
static void
_image_resize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
}
GstElement *
gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
Evas_Object *o,
@ -733,18 +607,11 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
GstElement *playbin;
GstElement *bin = NULL;
GstElement *esink = NULL;
GstElement *xvsink = NULL;
GstElement *tee = NULL;
GstElement *queue = NULL;
Evas_Object *obj;
GstPad *pad;
GstPad *teepad;
int flags;
const char *launch;
#if defined HAVE_ECORE_X
const char *engine = NULL;
Eina_List *engines;
#endif
obj = emotion_object_image_get(o);
if (!obj)
@ -791,83 +658,6 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
goto unref_pipeline;
}
tee = gst_element_factory_make("tee", NULL);
if (!tee)
{
ERR("Unable to create 'tee' GstElement.");
goto unref_pipeline;
}
#if defined HAVE_ECORE_X
if (window_manager_video)
{
Eina_List *l;
const char *ename;
engines = evas_render_method_list();
EINA_LIST_FOREACH(engines, l, ename)
{
if (evas_render_method_lookup(ename) ==
evas_output_method_get(evas_object_evas_get(obj)))
{
engine = ename;
break;
}
}
if (ev->priority && engine && strstr(engine, "_x11") != NULL)
{
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 < 4) w = 4;
if (h < 2) h = 2;
/* 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);
DBG("parent: %x", parent);
win = ecore_x_window_new(0, x, y, w, h);
DBG("creating window: %x [%i, %i, %i, %i]", win, x, y, w, h);
if (win)
{
Ecore_X_Window_State state[] = { ECORE_X_WINDOW_STATE_SKIP_TASKBAR, ECORE_X_WINDOW_STATE_SKIP_PAGER };
ecore_x_netwm_window_state_set(win, state, 2);
ecore_x_window_hide(win);
xvsink = gst_element_factory_make("xvimagesink", NULL);
if (xvsink)
{
unsigned int pos[2];
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(xvsink), win);
ev->win = win;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_VIDEO_PARENT, &parent, 1);
pos[0] = x; pos[1] = y;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_VIDEO_POSITION, pos, 2);
}
else
{
DBG("destroying win: %x", win);
ecore_x_window_free(win);
}
}
}
evas_render_method_list_free(engines);
}
#else
//# warning "missing: ecore_x"
#endif
esink = gst_element_factory_make("emotion-sink", "sink");
if (!esink)
{
@ -879,7 +669,6 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
g_object_set(G_OBJECT(esink), "ev", ev, NULL);
evas_object_image_pixels_get_callback_set(obj, NULL, NULL);
evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _image_resize, ev);
/* We need queue to force each video sink to be in its own thread */
queue = gst_element_factory_make("queue", "equeue");
@ -889,57 +678,14 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
goto unref_pipeline;
}
gst_bin_add_many(GST_BIN(bin), tee, queue, esink, NULL);
gst_bin_add_many(GST_BIN(bin), queue, esink, NULL);
gst_element_link_many(queue, esink, NULL);
/* link both sink to GstTee */
pad = gst_element_get_static_pad(queue, "sink");
teepad = gst_element_get_request_pad(tee, "src_%u");
gst_pad_link(teepad, pad);
gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
gst_object_unref(pad);
ev->eteepad = teepad;
/* FIXME: Why a bin that drops the EOS message?! */
if (xvsink)
{
GstElement *fakeeos;
queue = gst_element_factory_make("queue", "xvqueue");
fakeeos = GST_ELEMENT(GST_BIN(g_object_new(GST_TYPE_FAKEEOS_BIN, "name", "eosbin", NULL)));
if (queue && fakeeos)
{
GstPad *queue_pad;
gst_bin_add_many(GST_BIN(bin), fakeeos, NULL);
gst_bin_add_many(GST_BIN(fakeeos), queue, xvsink, NULL);
gst_element_link_many(queue, xvsink, NULL);
queue_pad = gst_element_get_static_pad(queue, "sink");
gst_element_add_pad(fakeeos, gst_ghost_pad_new("sink", queue_pad));
pad = gst_element_get_static_pad(fakeeos, "sink");
teepad = gst_element_get_request_pad(tee, "src_%u");
gst_pad_link(teepad, pad);
xvsink = fakeeos;
ev->xvteepad = teepad;
ev->xvpad = pad;
}
else
{
if (fakeeos) gst_object_unref(fakeeos);
if (queue) gst_object_unref(queue);
gst_object_unref(xvsink);
xvsink = NULL;
}
}
teepad = gst_element_get_static_pad(tee, "sink");
gst_element_add_pad(bin, gst_ghost_pad_new("sink", teepad));
gst_object_unref(teepad);
#define GST_PLAY_FLAG_NATIVE_VIDEO (1 << 6)
#define GST_PLAY_FLAG_DOWNLOAD (1 << 7)
#define GST_PLAY_FLAG_AUDIO (1 << 1)
@ -961,29 +707,10 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
ev->stream = EINA_TRUE;
if (xvsink)
{
Evas_Video_Surface video;
video.version = EVAS_VIDEO_SURFACE_VERSION;
video.data = ev;
video.parent = NULL;
video.move = _video_move;
video.resize = _video_resize;
video.show = _video_show;
video.hide = _video_hide;
video.update_pixels = _video_update_pixels;
evas_object_image_video_surface_set(obj, &video);
ev->stream = EINA_FALSE;
}
eina_stringshare_replace(&ev->uri, uri);
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,
_emotion_gstreamer_end,
@ -997,9 +724,7 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
return playbin;
unref_pipeline:
gst_object_unref(xvsink);
gst_object_unref(esink);
gst_object_unref(tee);
gst_object_unref(bin);
gst_object_unref(playbin);
return NULL;