From ecadef9ee946e7d38439a3e680f87108887433a8 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Mon, 1 Aug 2011 12:21:14 +0000 Subject: [PATCH] emotion: use new ecore infrastructure and remove some race condition. SVN revision: 61949 --- .../emotion/src/modules/gstreamer/Makefile.am | 3 +- .../src/modules/gstreamer/emotion_gstreamer.h | 83 ++++++++++---- .../src/modules/gstreamer/emotion_sink.c | 102 +++++------------- 3 files changed, 91 insertions(+), 97 deletions(-) diff --git a/legacy/emotion/src/modules/gstreamer/Makefile.am b/legacy/emotion/src/modules/gstreamer/Makefile.am index ca95f13f0b..ac4b81c06a 100644 --- a/legacy/emotion/src/modules/gstreamer/Makefile.am +++ b/legacy/emotion/src/modules/gstreamer/Makefile.am @@ -19,7 +19,8 @@ pkgdir = $(libdir)/emotion pkg_LTLIBRARIES = gstreamer.la gstreamer_la_SOURCES = \ emotion_gstreamer.c \ -emotion_sink.c +emotion_sink.c \ +emotion_alloc.c gstreamer_la_LIBADD = @GSTREAMER_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 diff --git a/legacy/emotion/src/modules/gstreamer/emotion_gstreamer.h b/legacy/emotion/src/modules/gstreamer/emotion_gstreamer.h index 5281b220f4..edb34b4269 100644 --- a/legacy/emotion/src/modules/gstreamer/emotion_gstreamer.h +++ b/legacy/emotion/src/modules/gstreamer/emotion_gstreamer.h @@ -7,13 +7,21 @@ #define HTTP_STREAM 0 #define RTSP_STREAM 1 +#include #include #include #include +#include #include "emotion_private.h" - +typedef struct _EvasVideoSinkPrivate EvasVideoSinkPrivate; +typedef struct _EvasVideoSink EvasVideoSink; +typedef struct _EvasVideoSinkClass EvasVideoSinkClass; +typedef struct _Emotion_Gstreamer_Video Emotion_Gstreamer_Video; +typedef struct _Emotion_Audio_Stream Emotion_Audio_Stream; +typedef struct _Emotion_Gstreamer_Metadata Emotion_Gstreamer_Metadata; +typedef struct _Emotion_Gstreamer_Buffer Emotion_Gstreamer_Buffer; typedef struct _Emotion_Video_Stream Emotion_Video_Stream; struct _Emotion_Video_Stream @@ -27,8 +35,6 @@ struct _Emotion_Video_Stream int index; }; -typedef struct _Emotion_Audio_Stream Emotion_Audio_Stream; - struct _Emotion_Audio_Stream { gdouble length_time; @@ -36,8 +42,6 @@ struct _Emotion_Audio_Stream gint samplerate; }; -typedef struct _Emotion_Gstreamer_Metadata Emotion_Gstreamer_Metadata; - struct _Emotion_Gstreamer_Metadata { char *title; @@ -50,9 +54,6 @@ struct _Emotion_Gstreamer_Metadata char *disc_id; }; - -typedef struct _Emotion_Gstreamer_Video Emotion_Gstreamer_Video; - struct _Emotion_Gstreamer_Video { /* Gstreamer elements */ @@ -90,6 +91,53 @@ struct _Emotion_Gstreamer_Video unsigned char audio_mute : 1; }; +struct _EvasVideoSink { + /*< private >*/ + GstVideoSink parent; + EvasVideoSinkPrivate *priv; +}; + +struct _EvasVideoSinkClass { + /*< private >*/ + GstVideoSinkClass parent_class; +}; + +struct _EvasVideoSinkPrivate { + EINA_REFCOUNT; + + Evas_Object *o; + + int width; + int height; + Evas_Colorspace eformat; + GstVideoFormat gformat; + + GMutex* buffer_mutex; + GCond* data_cond; + + /* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */ + GstBuffer *last_buffer; + + // If this is TRUE all processing should finish ASAP + // This is necessary because there could be a race between + // unlock() and render(), where unlock() wins, signals the + // GCond, then render() tries to render a frame although + // everything else isn't running anymore. This will lead + // to deadlocks because render() holds the stream lock. + // + // Protected by the buffer mutex + Eina_Bool unlocked : 1; +}; + +struct _Emotion_Gstreamer_Buffer +{ + EvasVideoSinkPrivate *sink; + + GstBuffer *frame; + + Eina_Bool preroll : 1; +}; + extern int _emotion_gstreamer_log_domain; #define DBG(...) EINA_LOG_DOM_DBG(_emotion_gstreamer_log_domain, __VA_ARGS__) #define INF(...) EINA_LOG_DOM_INFO(_emotion_gstreamer_log_domain, __VA_ARGS__) @@ -119,25 +167,14 @@ extern int _emotion_gstreamer_log_domain; (G_TYPE_INSTANCE_GET_CLASS((obj), \ EVAS_TYPE_VIDEO_SINK, EvasVideoSinkClass)) -typedef struct _EvasVideoSink EvasVideoSink; -typedef struct _EvasVideoSinkClass EvasVideoSinkClass; -typedef struct _EvasVideoSinkPrivate EvasVideoSinkPrivate; - -struct _EvasVideoSink { - /*< private >*/ - GstVideoSink parent; - EvasVideoSinkPrivate *priv; -}; - -struct _EvasVideoSinkClass { - /*< private >*/ - GstVideoSinkClass parent_class; -}; - GstElement *gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev, Evas_Object *obj, const char *uri); gboolean gstreamer_plugin_init(GstPlugin *plugin); +Emotion_Gstreamer_Buffer *emotion_gstreamer_buffer_alloc(EvasVideoSinkPrivate *sink, + GstBuffer *buffer, + Eina_Bool preroll); +void emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send); #endif /* __EMOTION_GSTREAMER_H__ */ diff --git a/legacy/emotion/src/modules/gstreamer/emotion_sink.c b/legacy/emotion/src/modules/gstreamer/emotion_sink.c index 79ec2ee4c8..4033349dd3 100644 --- a/legacy/emotion/src/modules/gstreamer/emotion_sink.c +++ b/legacy/emotion/src/modules/gstreamer/emotion_sink.c @@ -1,8 +1,3 @@ -#include -#include -#include -#include - #include #include "emotion_gstreamer.h" @@ -30,32 +25,6 @@ enum { static guint evas_video_sink_signals[LAST_SIGNAL] = { 0, }; -struct _EvasVideoSinkPrivate { - Evas_Object *o; - Ecore_Pipe *p; - - int width; - int height; - Evas_Colorspace eformat; - GstVideoFormat gformat; - - GMutex* buffer_mutex; - GCond* data_cond; - - GstBuffer *last_buffer; /* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */ - - // If this is TRUE all processing should finish ASAP - // This is necessary because there could be a race between - // unlock() and render(), where unlock() wins, signals the - // GCond, then render() tries to render a frame although - // everything else isn't running anymore. This will lead - // to deadlocks because render() holds the stream lock. - // - // Protected by the buffer mutex - Eina_Bool unlocked : 1; - Eina_Bool preroll : 1; -}; - #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT(evas_video_sink_debug, \ "emotion-sink", \ @@ -71,7 +40,7 @@ GST_BOILERPLATE_FULL(EvasVideoSink, static void unlock_buffer_mutex(EvasVideoSinkPrivate* priv); -static void evas_video_sink_render_handler(void *data, void *buf, unsigned int len); +static void evas_video_sink_main_render(void *data); static void evas_video_sink_base_init(gpointer g_class) @@ -93,7 +62,6 @@ evas_video_sink_init(EvasVideoSink* sink, EvasVideoSinkClass* klass __UNUSED__) INF("sink init"); sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, EVAS_TYPE_VIDEO_SINK, EvasVideoSinkPrivate); priv->o = NULL; - priv->p = ecore_pipe_add(evas_video_sink_render_handler, sink); priv->last_buffer = NULL; priv->width = 0; priv->height = 0; @@ -101,7 +69,6 @@ evas_video_sink_init(EvasVideoSink* sink, EvasVideoSinkClass* klass __UNUSED__) priv->eformat = EVAS_COLORSPACE_ARGB8888; priv->data_cond = g_cond_new(); priv->buffer_mutex = g_mutex_new(); - priv->preroll = EINA_FALSE; priv->unlocked = EINA_FALSE; } @@ -183,11 +150,6 @@ evas_video_sink_dispose(GObject* object) priv->data_cond = 0; } - if (priv->p) { - ecore_pipe_del(priv->p); - priv->p = NULL; - } - if (priv->last_buffer) { gst_buffer_unref(priv->last_buffer); priv->last_buffer = NULL; @@ -259,14 +221,7 @@ evas_video_sink_start(GstBaseSink* base_sink) if (!priv->o) res = FALSE; else - { - if (!priv->p) - res = FALSE; - else - { - priv->unlocked = EINA_FALSE; - } - } + priv->unlocked = EINA_FALSE; g_mutex_unlock(priv->buffer_mutex); return res; } @@ -313,27 +268,27 @@ evas_video_sink_unlock_stop(GstBaseSink* object) static GstFlowReturn evas_video_sink_preroll(GstBaseSink* bsink, GstBuffer* buffer) { - GstBuffer *send; - EvasVideoSink* sink; - EvasVideoSinkPrivate* priv; + Emotion_Gstreamer_Buffer *send; + EvasVideoSinkPrivate *priv; + EvasVideoSink *sink; sink = EVAS_VIDEO_SINK(bsink); priv = sink->priv; - send = gst_buffer_ref(buffer); + send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_TRUE); - priv->preroll = EINA_TRUE; + if (send) + ecore_main_loop_thread_safe_call(evas_video_sink_main_render, send); - ecore_pipe_write(priv->p, &send, sizeof(buffer)); return GST_FLOW_OK; } static GstFlowReturn evas_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer) { - GstBuffer *send; - EvasVideoSink* sink; - EvasVideoSinkPrivate* priv; + Emotion_Gstreamer_Buffer *send; + EvasVideoSinkPrivate *priv; + EvasVideoSink *sink; Eina_Bool ret; sink = EVAS_VIDEO_SINK(bsink); @@ -347,12 +302,10 @@ evas_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer) return GST_FLOW_OK; } - priv->preroll = EINA_FALSE; + send = emotion_gstreamer_buffer_alloc(priv, buffer, EINA_FALSE); + if (!send) return GST_FLOW_ERROR; - send = gst_buffer_ref(buffer); - ret = ecore_pipe_write(priv->p, &send, sizeof(buffer)); - if (!ret) - return GST_FLOW_ERROR; + ecore_main_loop_thread_safe_call(evas_video_sink_main_render, send); g_cond_wait(priv->data_cond, priv->buffer_mutex); g_mutex_unlock(priv->buffer_mutex); @@ -360,13 +313,11 @@ evas_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer) return GST_FLOW_OK; } -static void evas_video_sink_render_handler(void *data, - void *buf, - unsigned int len) +static void evas_video_sink_main_render(void *data) { + Emotion_Gstreamer_Buffer *send; Emotion_Gstreamer_Video *ev; Emotion_Video_Stream *vstream; - EvasVideoSink* sink; EvasVideoSinkPrivate* priv; GstBuffer* buffer; unsigned char *evas_data; @@ -375,14 +326,17 @@ static void evas_video_sink_render_handler(void *data, GstFormat fmt = GST_FORMAT_TIME; Evas_Coord w, h; gint64 pos; + Eina_Bool preroll; - sink = (EvasVideoSink *)data; - priv = sink->priv; + send = data; - buffer = *((GstBuffer **)buf); + priv = send->sink; + if (!priv) goto exit_point; - if (priv->unlocked) - goto exit_point; + buffer = send->frame; + preroll = send->preroll; + + if (priv->unlocked) goto exit_point; gst_data = GST_BUFFER_DATA(buffer); if (!gst_data) goto exit_point; @@ -552,11 +506,13 @@ static void evas_video_sink_render_handler(void *data, _emotion_video_pos_update(ev->obj, ev->position, vstream->length_time); _emotion_frame_resize(ev->obj, priv->width, priv->height, ev->ratio); - exit_point: if (priv->last_buffer) gst_buffer_unref(priv->last_buffer); - priv->last_buffer = buffer; + priv->last_buffer = gst_buffer_ref(buffer); - if (priv->preroll) return ; + exit_point: + emotion_gstreamer_buffer_free(send); + + if (preroll) return ; g_mutex_lock(priv->buffer_mutex);