forked from enlightenment/efl
emotion: remove g stuff and make it safer.
SVN revision: 62514
This commit is contained in:
parent
1ca5e18738
commit
6245940483
|
@ -14,12 +14,16 @@ emotion_gstreamer_buffer_alloc(EvasVideoSinkPrivate *sink,
|
|||
{
|
||||
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;
|
||||
sink->ev->out++;
|
||||
send->ev = sink->ev;
|
||||
|
||||
return send;
|
||||
}
|
||||
|
@ -27,6 +31,13 @@ emotion_gstreamer_buffer_alloc(EvasVideoSinkPrivate *sink,
|
|||
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);
|
||||
}
|
||||
|
@ -37,6 +48,8 @@ emotion_gstreamer_message_alloc(Emotion_Gstreamer_Video *ev,
|
|||
{
|
||||
Emotion_Gstreamer_Message *send;
|
||||
|
||||
if (!ev) return NULL;
|
||||
|
||||
send = malloc(sizeof (Emotion_Gstreamer_Message));
|
||||
if (!send) return NULL;
|
||||
|
||||
|
@ -52,7 +65,9 @@ emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send)
|
|||
{
|
||||
send->ev->in++;
|
||||
|
||||
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);
|
||||
|
|
|
@ -333,6 +333,7 @@ em_init(Evas_Object *obj,
|
|||
ev->volume = 0.8;
|
||||
ev->play_started = 0;
|
||||
ev->delete_me = EINA_FALSE;
|
||||
ev->threads = NULL;
|
||||
|
||||
*emotion_video = ev;
|
||||
|
||||
|
@ -355,10 +356,15 @@ em_shutdown(void *video)
|
|||
if (!ev)
|
||||
return 0;
|
||||
|
||||
if (ev->thread)
|
||||
if (ev->threads)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (ev->in != ev->out)
|
||||
|
@ -375,9 +381,12 @@ em_shutdown(void *video)
|
|||
|
||||
if (ev->pipeline)
|
||||
{
|
||||
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;
|
||||
ev->sink = NULL;
|
||||
}
|
||||
|
||||
EINA_LIST_FREE(ev->audio_streams, astream)
|
||||
|
@ -470,17 +479,22 @@ em_file_close(void *video)
|
|||
ev->eos_bus = NULL;
|
||||
}
|
||||
|
||||
if (ev->thread)
|
||||
if (ev->threads)
|
||||
{
|
||||
ecore_thread_cancel(ev->thread);
|
||||
ev->thread = NULL;
|
||||
Ecore_Thread *t;
|
||||
|
||||
EINA_LIST_FREE(ev->threads, t)
|
||||
ecore_thread_cancel(t);
|
||||
}
|
||||
|
||||
if (ev->pipeline)
|
||||
{
|
||||
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;
|
||||
ev->sink = NULL;
|
||||
}
|
||||
|
||||
/* we clear the stream lists */
|
||||
|
@ -521,7 +535,7 @@ em_stop(void *video)
|
|||
ev = (Emotion_Gstreamer_Video *)video;
|
||||
|
||||
if (!ev->pipeline) return ;
|
||||
|
||||
|
||||
gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
|
||||
ev->play = 0;
|
||||
}
|
||||
|
@ -1478,7 +1492,7 @@ _eos_sync_fct(GstBus *bus, GstMessage *msg, gpointer data)
|
|||
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);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -1504,13 +1518,15 @@ _emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev,
|
|||
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);
|
||||
}
|
||||
|
||||
if (ev->thread)
|
||||
if (ev->threads)
|
||||
return EINA_FALSE;
|
||||
|
||||
res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
|
|
|
@ -59,7 +59,8 @@ struct _Emotion_Gstreamer_Video
|
|||
{
|
||||
/* Gstreamer elements */
|
||||
GstElement *pipeline;
|
||||
Ecore_Thread *thread;
|
||||
GstElement *sink;
|
||||
Eina_List *threads;
|
||||
|
||||
/* eos */
|
||||
GstBus *eos_bus;
|
||||
|
@ -113,13 +114,15 @@ struct _EvasVideoSinkPrivate {
|
|||
|
||||
Evas_Object *o;
|
||||
|
||||
Emotion_Gstreamer_Video *ev;
|
||||
|
||||
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;
|
||||
|
@ -137,6 +140,7 @@ struct _EvasVideoSinkPrivate {
|
|||
|
||||
struct _Emotion_Gstreamer_Buffer
|
||||
{
|
||||
Emotion_Gstreamer_Video *ev;
|
||||
EvasVideoSinkPrivate *sink;
|
||||
|
||||
GstBuffer *frame;
|
||||
|
|
|
@ -20,7 +20,8 @@ enum {
|
|||
PROP_EVAS_OBJECT,
|
||||
PROP_WIDTH,
|
||||
PROP_HEIGHT,
|
||||
PROP_LAST,
|
||||
PROP_EV,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static guint evas_video_sink_signals[LAST_SIGNAL] = { 0, };
|
||||
|
@ -67,13 +68,25 @@ evas_video_sink_init(EvasVideoSink* sink, EvasVideoSinkClass* klass __UNUSED__)
|
|||
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 ****/
|
||||
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,
|
||||
|
@ -87,9 +100,16 @@ evas_video_sink_set_property(GObject * object, guint prop_id,
|
|||
|
||||
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);
|
||||
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);
|
||||
|
@ -110,19 +130,24 @@ evas_video_sink_get_property(GObject * object, guint prop_id,
|
|||
|
||||
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_mutex_unlock(priv->buffer_mutex);
|
||||
eina_lock_release(&priv->m);
|
||||
break;
|
||||
case PROP_WIDTH:
|
||||
g_mutex_lock(priv->buffer_mutex);
|
||||
eina_lock_take(&priv->m);
|
||||
g_value_set_int(value, priv->width);
|
||||
g_mutex_unlock(priv->buffer_mutex);
|
||||
eina_lock_release(&priv->m);
|
||||
break;
|
||||
case PROP_HEIGHT:
|
||||
g_mutex_lock(priv->buffer_mutex);
|
||||
eina_lock_take(&priv->m);
|
||||
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);
|
||||
|
@ -140,15 +165,8 @@ evas_video_sink_dispose(GObject* object)
|
|||
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);
|
||||
|
@ -217,12 +235,12 @@ evas_video_sink_start(GstBaseSink* base_sink)
|
|||
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;
|
||||
g_mutex_unlock(priv->buffer_mutex);
|
||||
eina_lock_release(&priv->m);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -257,9 +275,9 @@ evas_video_sink_unlock_stop(GstBaseSink* object)
|
|||
sink = EVAS_VIDEO_SINK(object);
|
||||
priv = sink->priv;
|
||||
|
||||
g_mutex_lock(priv->buffer_mutex);
|
||||
eina_lock_take(&priv->m);
|
||||
priv->unlocked = FALSE;
|
||||
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);
|
||||
|
@ -278,7 +296,7 @@ evas_video_sink_preroll(GstBaseSink* bsink, GstBuffer* buffer)
|
|||
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);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
@ -289,40 +307,42 @@ evas_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer)
|
|||
Emotion_Gstreamer_Buffer *send;
|
||||
EvasVideoSinkPrivate *priv;
|
||||
EvasVideoSink *sink;
|
||||
Eina_Bool ret;
|
||||
|
||||
sink = EVAS_VIDEO_SINK(bsink);
|
||||
priv = sink->priv;
|
||||
|
||||
g_mutex_lock(priv->buffer_mutex);
|
||||
eina_lock_take(&priv->m);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void evas_video_sink_main_render(void *data)
|
||||
static void
|
||||
evas_video_sink_main_render(void *data)
|
||||
{
|
||||
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;
|
||||
GstQuery *query;
|
||||
GstFormat fmt = GST_FORMAT_TIME;
|
||||
Evas_Coord w, h;
|
||||
gint64 pos;
|
||||
|
@ -332,6 +352,7 @@ static void evas_video_sink_main_render(void *data)
|
|||
|
||||
priv = send->sink;
|
||||
if (!priv) goto exit_point;
|
||||
if (!priv->o) goto exit_point;
|
||||
|
||||
buffer = send->frame;
|
||||
preroll = send->preroll;
|
||||
|
@ -341,7 +362,7 @@ static void evas_video_sink_main_render(void *data)
|
|||
gst_data = GST_BUFFER_DATA(buffer);
|
||||
if (!gst_data) goto exit_point;
|
||||
|
||||
ev = evas_object_data_get(priv->o, "_emotion_gstreamer_video");
|
||||
ev = send->ev;
|
||||
if (!ev) goto exit_point;
|
||||
|
||||
_emotion_gstreamer_video_pipeline_parse(ev, EINA_TRUE);
|
||||
|
@ -514,27 +535,23 @@ static void evas_video_sink_main_render(void *data)
|
|||
exit_point:
|
||||
emotion_gstreamer_buffer_free(send);
|
||||
|
||||
if (preroll) return ;
|
||||
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)
|
||||
{
|
||||
g_mutex_lock(priv->buffer_mutex);
|
||||
|
||||
eina_lock_take(&priv->m);
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -591,6 +608,10 @@ evas_video_sink_class_init(EvasVideoSinkClass* klass)
|
|||
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;
|
||||
|
||||
|
@ -622,19 +643,24 @@ gstreamer_plugin_init (GstPlugin * plugin)
|
|||
}
|
||||
|
||||
static void
|
||||
_emotion_gstreamer_pause(void *data, Ecore_Thread *thread __UNUSED__)
|
||||
_emotion_gstreamer_pause(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
Emotion_Gstreamer_Video *ev = data;
|
||||
|
||||
if (ecore_thread_check(thread) || !ev->pipeline) return ;
|
||||
|
||||
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;
|
||||
|
||||
ev->thread = NULL;
|
||||
ev->threads = eina_list_remove(ev->threads, thread);
|
||||
|
||||
if (ev->in == ev->out && ev->threads == NULL && ev->delete_me)
|
||||
em_shutdown(ev);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -652,7 +678,6 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
|||
GstElement *playbin;
|
||||
GstElement *sink;
|
||||
Evas_Object *obj;
|
||||
GstStateChangeReturn res;
|
||||
|
||||
obj = emotion_object_image_get(o);
|
||||
if (!obj)
|
||||
|
@ -675,22 +700,24 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
|||
goto unref_pipeline;
|
||||
}
|
||||
|
||||
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(sink), "evas-object", obj, NULL);
|
||||
|
||||
ev->pipeline = playbin;
|
||||
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"));
|
||||
|
||||
evas_object_data_set(obj, "_emotion_gstreamer_video", ev);
|
||||
|
||||
return playbin;
|
||||
|
||||
unref_pipeline:
|
||||
|
|
Loading…
Reference in New Issue