git-svn-id: http://svn.enlightenment.org/svn/e/trunk/emotion@62514
7cbeb6ba-43b4-40fd-8cce-
4c39aea84d33
{
Emotion_Gstreamer_Buffer *send;
{
Emotion_Gstreamer_Buffer *send;
+ if (!sink->ev) return NULL;
+
send = malloc(sizeof (Emotion_Gstreamer_Buffer));
if (!send) return NULL;
send->sink = sink;
send->frame = gst_buffer_ref(buffer);
send->preroll = preroll;
send = malloc(sizeof (Emotion_Gstreamer_Buffer));
if (!send) return NULL;
send->sink = sink;
send->frame = gst_buffer_ref(buffer);
send->preroll = preroll;
+ sink->ev->out++;
+ send->ev = sink->ev;
void
emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send)
{
void
emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send)
{
+ send->ev->in++;
+
+ if (send->ev->in == send->ev->out
+ && send->ev->threads == NULL
+ && send->ev->delete_me)
+ em_shutdown(send->ev);
+
gst_buffer_unref(send->frame);
free(send);
}
gst_buffer_unref(send->frame);
free(send);
}
{
Emotion_Gstreamer_Message *send;
{
Emotion_Gstreamer_Message *send;
+ if (!ev) return NULL;
+
send = malloc(sizeof (Emotion_Gstreamer_Message));
if (!send) return NULL;
send = malloc(sizeof (Emotion_Gstreamer_Message));
if (!send) return NULL;
- if (send->ev->in == send->ev->out && send->ev->delete_me)
+ if (send->ev->in == send->ev->out
+ && send->ev->threads == NULL
+ && send->ev->delete_me)
em_shutdown(send->ev);
gst_message_unref(send->msg);
em_shutdown(send->ev);
gst_message_unref(send->msg);
ev->volume = 0.8;
ev->play_started = 0;
ev->delete_me = EINA_FALSE;
ev->volume = 0.8;
ev->play_started = 0;
ev->delete_me = EINA_FALSE;
- ecore_thread_cancel(ev->thread);
- ev->thread = NULL;
+ Ecore_Thread *t;
+
+ EINA_LIST_FREE(ev->threads, t)
+ ecore_thread_cancel(t);
+
+ ev->delete_me = EINA_TRUE;
+ return 1;
+ g_object_set(G_OBJECT(ev->sink), "ev", NULL, NULL);
+ g_object_set(G_OBJECT(ev->sink), "evas-object", NULL, NULL);
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
gst_object_unref(ev->pipeline);
ev->pipeline = NULL;
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
gst_object_unref(ev->pipeline);
ev->pipeline = NULL;
}
EINA_LIST_FREE(ev->audio_streams, astream)
}
EINA_LIST_FREE(ev->audio_streams, astream)
- ecore_thread_cancel(ev->thread);
- ev->thread = NULL;
+ Ecore_Thread *t;
+
+ EINA_LIST_FREE(ev->threads, t)
+ ecore_thread_cancel(t);
+ g_object_set(G_OBJECT(ev->sink), "ev", NULL, NULL);
+ g_object_set(G_OBJECT(ev->sink), "evas-object", NULL, NULL);
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
gst_object_unref(ev->pipeline);
ev->pipeline = NULL;
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
gst_object_unref(ev->pipeline);
ev->pipeline = NULL;
}
/* we clear the stream lists */
}
/* we clear the stream lists */
ev = (Emotion_Gstreamer_Video *)video;
if (!ev->pipeline) return ;
ev = (Emotion_Gstreamer_Video *)video;
if (!ev->pipeline) return ;
gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
ev->play = 0;
}
gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
ev->play = 0;
}
case GST_MESSAGE_ASYNC_DONE:
send = emotion_gstreamer_message_alloc(ev, msg);
case GST_MESSAGE_ASYNC_DONE:
send = emotion_gstreamer_message_alloc(ev, msg);
- if (send) ecore_main_loop_thread_safe_call(_eos_main_fct, send);
+ if (send) ecore_main_loop_thread_safe_call_async(_eos_main_fct, send);
if (ev->pipeline_parsed)
return EINA_TRUE;
if (ev->pipeline_parsed)
return EINA_TRUE;
- if (force && ev->thread)
+ if (force && ev->threads)
- ecore_thread_cancel(ev->thread);
- ev->thread = NULL;
+ Ecore_Thread *t;
+
+ EINA_LIST_FREE(ev->threads, t)
+ ecore_thread_cancel(t);
return EINA_FALSE;
res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
return EINA_FALSE;
res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
{
/* Gstreamer elements */
GstElement *pipeline;
{
/* Gstreamer elements */
GstElement *pipeline;
+ GstElement *sink;
+ Eina_List *threads;
/* eos */
GstBus *eos_bus;
/* eos */
GstBus *eos_bus;
+ Emotion_Gstreamer_Video *ev;
+
int width;
int height;
Evas_Colorspace eformat;
GstVideoFormat gformat;
int width;
int height;
Evas_Colorspace eformat;
GstVideoFormat gformat;
- GMutex* buffer_mutex;
- GCond* data_cond;
+ Eina_Lock m;
+ Eina_Condition c;
/* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */
GstBuffer *last_buffer;
/* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */
GstBuffer *last_buffer;
struct _Emotion_Gstreamer_Buffer
{
struct _Emotion_Gstreamer_Buffer
{
+ Emotion_Gstreamer_Video *ev;
EvasVideoSinkPrivate *sink;
GstBuffer *frame;
EvasVideoSinkPrivate *sink;
GstBuffer *frame;
PROP_EVAS_OBJECT,
PROP_WIDTH,
PROP_HEIGHT,
PROP_EVAS_OBJECT,
PROP_WIDTH,
PROP_HEIGHT,
};
static guint evas_video_sink_signals[LAST_SIGNAL] = { 0, };
};
static guint evas_video_sink_signals[LAST_SIGNAL] = { 0, };
priv->height = 0;
priv->gformat = GST_VIDEO_FORMAT_UNKNOWN;
priv->eformat = EVAS_COLORSPACE_ARGB8888;
priv->height = 0;
priv->gformat = GST_VIDEO_FORMAT_UNKNOWN;
priv->eformat = EVAS_COLORSPACE_ARGB8888;
- priv->data_cond = g_cond_new();
- priv->buffer_mutex = g_mutex_new();
+ eina_lock_new(&priv->m);
+ eina_condition_new(&priv->c, &priv->m);
priv->unlocked = EINA_FALSE;
}
/**** Object methods ****/
priv->unlocked = EINA_FALSE;
}
/**** Object methods ****/
+static void
+_cleanup_priv(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+ EvasVideoSinkPrivate* priv;
+
+ priv = data;
+
+ eina_lock_take(&priv->m);
+ if (priv->o == obj)
+ priv->o = NULL;
+ eina_lock_release(&priv->m);
+}
static void
evas_video_sink_set_property(GObject * object, guint prop_id,
static void
evas_video_sink_set_property(GObject * object, guint prop_id,
switch (prop_id) {
case PROP_EVAS_OBJECT:
switch (prop_id) {
case PROP_EVAS_OBJECT:
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
+ evas_object_event_callback_del(priv->o, EVAS_CALLBACK_FREE, _cleanup_priv);
priv->o = g_value_get_pointer (value);
priv->o = g_value_get_pointer (value);
- g_mutex_unlock(priv->buffer_mutex);
+ evas_object_event_callback_add(priv->o, EVAS_CALLBACK_FREE, _cleanup_priv, priv);
+ eina_lock_release(&priv->m);
+ break;
+ case PROP_EV:
+ eina_lock_take(&priv->m);
+ priv->ev = g_value_get_pointer (value);
+ eina_lock_release(&priv->m);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
switch (prop_id) {
case PROP_EVAS_OBJECT:
switch (prop_id) {
case PROP_EVAS_OBJECT:
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
g_value_set_pointer (value, priv->o);
g_value_set_pointer (value, priv->o);
- g_mutex_unlock(priv->buffer_mutex);
+ eina_lock_release(&priv->m);
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
g_value_set_int(value, priv->width);
g_value_set_int(value, priv->width);
- g_mutex_unlock(priv->buffer_mutex);
+ eina_lock_release(&priv->m);
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
g_value_set_int (value, priv->height);
g_value_set_int (value, priv->height);
- g_mutex_unlock(priv->buffer_mutex);
+ eina_lock_release(&priv->m);
+ break;
+ case PROP_EV:
+ eina_lock_take(&priv->m);
+ g_value_set_pointer (value, priv->ev);
+ eina_lock_release(&priv->m);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
sink = EVAS_VIDEO_SINK(object);
priv = sink->priv;
sink = EVAS_VIDEO_SINK(object);
priv = sink->priv;
- if (priv->buffer_mutex) {
- g_mutex_free(priv->buffer_mutex);
- priv->buffer_mutex = 0;
- }
-
- if (priv->data_cond) {
- g_cond_free(priv->data_cond);
- priv->data_cond = 0;
- }
+ eina_lock_free(&priv->m);
+ eina_condition_free(&priv->c);
if (priv->last_buffer) {
gst_buffer_unref(priv->last_buffer);
if (priv->last_buffer) {
gst_buffer_unref(priv->last_buffer);
gboolean res = TRUE;
priv = EVAS_VIDEO_SINK(base_sink)->priv;
gboolean res = TRUE;
priv = EVAS_VIDEO_SINK(base_sink)->priv;
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
if (!priv->o)
res = FALSE;
else
priv->unlocked = EINA_FALSE;
if (!priv->o)
res = FALSE;
else
priv->unlocked = EINA_FALSE;
- g_mutex_unlock(priv->buffer_mutex);
+ eina_lock_release(&priv->m);
sink = EVAS_VIDEO_SINK(object);
priv = sink->priv;
sink = EVAS_VIDEO_SINK(object);
priv = sink->priv;
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
- g_mutex_unlock(priv->buffer_mutex);
+ eina_lock_release(&priv->m);
return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock_stop,
(object), TRUE);
return GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock_stop,
(object), TRUE);
send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_TRUE);
if (send)
send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_TRUE);
if (send)
- ecore_main_loop_thread_safe_call(evas_video_sink_main_render, send);
+ ecore_main_loop_thread_safe_call_async(evas_video_sink_main_render, send);
Emotion_Gstreamer_Buffer *send;
EvasVideoSinkPrivate *priv;
EvasVideoSink *sink;
Emotion_Gstreamer_Buffer *send;
EvasVideoSinkPrivate *priv;
EvasVideoSink *sink;
sink = EVAS_VIDEO_SINK(bsink);
priv = sink->priv;
sink = EVAS_VIDEO_SINK(bsink);
priv = sink->priv;
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
if (priv->unlocked) {
ERR("LOCKED");
if (priv->unlocked) {
ERR("LOCKED");
- g_mutex_unlock(priv->buffer_mutex);
+ eina_lock_release(&priv->m);
return GST_FLOW_OK;
}
send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_FALSE);
return GST_FLOW_OK;
}
send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_FALSE);
- if (!send) return GST_FLOW_ERROR;
+ if (!send) {
+ eina_lock_release(&priv->m);
+ return GST_FLOW_ERROR;
+ }
- ecore_main_loop_thread_safe_call(evas_video_sink_main_render, send);
+ ecore_main_loop_thread_safe_call_async(evas_video_sink_main_render, send);
- g_cond_wait(priv->data_cond, priv->buffer_mutex);
- g_mutex_unlock(priv->buffer_mutex);
+ eina_condition_wait(&priv->c);
+ eina_lock_release(&priv->m);
-static void evas_video_sink_main_render(void *data)
+static void
+evas_video_sink_main_render(void *data)
{
Emotion_Gstreamer_Buffer *send;
{
Emotion_Gstreamer_Buffer *send;
- Emotion_Gstreamer_Video *ev;
+ Emotion_Gstreamer_Video *ev = NULL;
Emotion_Video_Stream *vstream;
EvasVideoSinkPrivate* priv;
GstBuffer* buffer;
unsigned char *evas_data;
const guint8 *gst_data;
Emotion_Video_Stream *vstream;
EvasVideoSinkPrivate* priv;
GstBuffer* buffer;
unsigned char *evas_data;
const guint8 *gst_data;
GstFormat fmt = GST_FORMAT_TIME;
Evas_Coord w, h;
gint64 pos;
GstFormat fmt = GST_FORMAT_TIME;
Evas_Coord w, h;
gint64 pos;
priv = send->sink;
if (!priv) goto exit_point;
priv = send->sink;
if (!priv) goto exit_point;
+ if (!priv->o) goto exit_point;
buffer = send->frame;
preroll = send->preroll;
buffer = send->frame;
preroll = send->preroll;
gst_data = GST_BUFFER_DATA(buffer);
if (!gst_data) goto exit_point;
gst_data = GST_BUFFER_DATA(buffer);
if (!gst_data) goto exit_point;
- ev = evas_object_data_get(priv->o, "_emotion_gstreamer_video");
if (!ev) goto exit_point;
_emotion_gstreamer_video_pipeline_parse(ev, EINA_TRUE);
if (!ev) goto exit_point;
_emotion_gstreamer_video_pipeline_parse(ev, EINA_TRUE);
exit_point:
emotion_gstreamer_buffer_free(send);
exit_point:
emotion_gstreamer_buffer_free(send);
+ if (preroll || !priv->o || !ev) return ;
- g_mutex_lock(priv->buffer_mutex);
+ eina_lock_take(&priv->m);
+ if (!priv->unlocked)
+ eina_condition_signal(&priv->c);
- if (priv->unlocked) {
- g_mutex_unlock(priv->buffer_mutex);
- return;
- }
-
- g_cond_signal(priv->data_cond);
- g_mutex_unlock(priv->buffer_mutex);
+ eina_lock_release(&priv->m);
}
static void
unlock_buffer_mutex(EvasVideoSinkPrivate* priv)
{
}
static void
unlock_buffer_mutex(EvasVideoSinkPrivate* priv)
{
- g_mutex_lock(priv->buffer_mutex);
-
+ eina_lock_take(&priv->m);
priv->unlocked = EINA_TRUE;
priv->unlocked = EINA_TRUE;
- g_cond_signal(priv->data_cond);
- g_mutex_unlock(priv->buffer_mutex);
+
+ eina_condition_signal(&priv->c);
+ eina_lock_release(&priv->m);
g_param_spec_int ("height", "Height",
"The height of the video",
0, 65536, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_param_spec_int ("height", "Height",
"The height of the video",
0, 65536, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_EV,
+ g_param_spec_pointer ("ev", "Emotion_Gstreamer_Video",
+ "THe internal data of the emotion object",
+ G_PARAM_READWRITE));
gobject_class->dispose = evas_video_sink_dispose;
gobject_class->dispose = evas_video_sink_dispose;
-_emotion_gstreamer_pause(void *data, Ecore_Thread *thread __UNUSED__)
+_emotion_gstreamer_pause(void *data, Ecore_Thread *thread)
{
Emotion_Gstreamer_Video *ev = data;
{
Emotion_Gstreamer_Video *ev = data;
+ if (ecore_thread_check(thread) || !ev->pipeline) return ;
+
gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
}
static void
gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
}
static void
-_emotion_gstreamer_cancel(void *data, Ecore_Thread *thread __UNUSED__)
+_emotion_gstreamer_cancel(void *data, Ecore_Thread *thread)
{
Emotion_Gstreamer_Video *ev = data;
{
Emotion_Gstreamer_Video *ev = data;
+ ev->threads = eina_list_remove(ev->threads, thread);
+
+ if (ev->in == ev->out && ev->threads == NULL && ev->delete_me)
+ em_shutdown(ev);
GstElement *playbin;
GstElement *sink;
Evas_Object *obj;
GstElement *playbin;
GstElement *sink;
Evas_Object *obj;
- GstStateChangeReturn res;
obj = emotion_object_image_get(o);
if (!obj)
obj = emotion_object_image_get(o);
if (!obj)
+ g_object_set(G_OBJECT(sink), "evas-object", obj, NULL);
+ g_object_set(G_OBJECT(sink), "ev", ev, NULL);
+
g_object_set(G_OBJECT(playbin), "video-sink", sink, NULL);
g_object_set(G_OBJECT(playbin), "uri", uri, NULL);
g_object_set(G_OBJECT(playbin), "video-sink", sink, NULL);
g_object_set(G_OBJECT(playbin), "uri", uri, NULL);
- g_object_set(G_OBJECT(sink), "evas-object", obj, NULL);
- ev->thread = ecore_thread_run(_emotion_gstreamer_pause,
- _emotion_gstreamer_end,
- _emotion_gstreamer_cancel,
- ev);
+ ev->sink = sink;
+ ev->threads = eina_list_append(ev->threads,
+ ecore_thread_run(_emotion_gstreamer_pause,
+ _emotion_gstreamer_end,
+ _emotion_gstreamer_cancel,
+ ev));
/** 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 */
if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(playbin), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT"));
/** 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 */
if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(playbin), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT"));
- evas_object_data_set(obj, "_emotion_gstreamer_video", ev);
-
return playbin;
unref_pipeline:
return playbin;
unref_pipeline: