Here is an example that uses the pipe wrapper with a Gstreamer pipeline.
For each decoded frame in the Gstreamer thread, a handle is called in the ecore thread.
 
#include <gst/gst.h>
#include <Ecore.h>
 
static int nbr = 0;
 
static GstElement *_build_pipeline(gchar *filename, 
Ecore_Pipe *pipe);
 
 
static void        new_decoded_pad_cb(GstElement *demuxer,
                                      GstPad *new_pad,
                                      gpointer user_data);
 
static void
handler(
void *data, 
void *buf, 
unsigned int len 
EINA_UNUSED)
{
   GstBuffer *buffer = *((GstBuffer **)buf);
 
   printf("handler : %p\n", buffer);
   printf("frame  : %d %p %lld %p\n", nbr++, data, (long long)GST_BUFFER_DURATION(buffer), buffer);
   gst_buffer_unref(buffer);
}
 
static void
        GstBuffer *arg0,
        gpointer user_data)
{
 
   printf("handoff : %p\n", arg0);
   gst_buffer_ref(arg0);
}
 
int
main(int argc, char *argv[])
{
   GstElement *pipeline;
   char *filename;
 
   gst_init(&argc, &argv);
 
     {
        gst_deinit();
        return 0;
     }
 
   if (!pipe)
     {
        gst_deinit();
        return 0;
     }
 
   if (argc < 2)
     {
        g_print("usage: %s file.avi\n", argv[0]);
        gst_deinit();
        return 0;
     }
   filename = argv[1];
 
   pipeline = _build_pipeline(filename, pipe);
   if (!pipeline)
     {
        g_print("Error during the pipeline building\n");
        gst_deinit();
        return -1;
     }
 
   gst_element_set_state(pipeline, GST_STATE_PLAYING);
 
 
   gst_deinit();
 
   return 0;
}
 
static void
                   GstPad *new_pad,
                   gpointer user_data)
{
   GstElement *decoder;
   GstPad *pad;
   GstCaps *caps;
   GstStructure *s;
   const gchar *str;
 
#if GST_CHECK_VERSION(1,0,0)
   caps = gst_pad_get_current_caps(new_pad);
#else
   caps = gst_pad_get_caps(new_pad);
#endif
   s = gst_caps_get_structure(caps, 0);
   str = gst_structure_get_name(s);
 
   if (g_str_has_prefix(str, "video/"))
     {
        decoder = GST_ELEMENT(user_data);
 
#if GST_CHECK_VERSION(1,0,0)
        pad = gst_element_get_static_pad(decoder, "sink");
#else
        pad = gst_element_get_pad(decoder, "sink");
#endif
        if (GST_PAD_LINK_FAILED(gst_pad_link(new_pad, pad)))
          {
             g_warning("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME(new_pad),
                       GST_DEBUG_PAD_NAME(pad));
          }
        gst_object_unref(pad);
     }
   gst_caps_unref(caps);
}
 
static GstElement *
_build_pipeline(gchar *filename, 
Ecore_Pipe *pipe)
{
   GstElement *pipeline;
   GstElement *filesrc;
   GstElement *demuxer;
   GstElement *decoder;
   GstElement *sink;
   GstStateChangeReturn res;
 
   pipeline = gst_pipeline_new("pipeline");
   if (!pipeline)
     return NULL;
 
   filesrc = gst_element_factory_make("filesrc", "filesrc");
   if (!filesrc)
     {
        printf("no filesrc");
        goto failure;
     }
   g_object_set(G_OBJECT(filesrc), "location", filename, NULL);
 
   demuxer = gst_element_factory_make("oggdemux", "demuxer");
   if (!demuxer)
     {
        printf("no demux");
        goto failure;
     }
 
   decoder = gst_element_factory_make("theoradec", "decoder");
   if (!decoder)
     {
        printf("no dec");
        goto failure;
     }
 
   g_signal_connect(demuxer, "pad-added",
                    G_CALLBACK(new_decoded_pad_cb), decoder);
 
   sink = gst_element_factory_make("fakesink", "sink");
   if (!sink)
     {
        printf("no sink");
        goto failure;
     }
   g_object_set(G_OBJECT(sink), 
"sync", 
EINA_TRUE, NULL);
   g_object_set(G_OBJECT(sink), 
"signal-handoffs", 
EINA_TRUE, NULL);
   g_signal_connect(sink, "handoff",
                    G_CALLBACK(handoff), pipe);
 
   gst_bin_add_many(GST_BIN(pipeline),
                    filesrc, demuxer, decoder, sink, NULL);
 
   if (!gst_element_link(filesrc, demuxer))
     goto failure;
   if (!gst_element_link(decoder, sink))
     goto failure;
 
   res = gst_element_set_state(pipeline, GST_STATE_PAUSED);
   if (res == GST_STATE_CHANGE_FAILURE)
     goto failure;
 
   res = gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
   if (res != GST_STATE_CHANGE_SUCCESS)
     goto failure;
 
   return pipeline;
 
failure:
   gst_object_unref(GST_OBJECT(pipeline));
   return NULL;
}
 
EAPI int ecore_shutdown(void)
Shuts down connections, signal handlers sockets etc.
Definition: ecore.c:366
EAPI int ecore_init(void)
Sets up connections, signal handlers, sockets etc.
Definition: ecore.c:225
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition: ecore_main.c:1298
struct _Ecore_Pipe Ecore_Pipe
A handle for pipes.
Definition: Ecore_Common.h:2402
Ecore_Pipe * ecore_pipe_add(Ecore_Pipe_Cb handler, const void *data)
Creates two file descriptors (sockets on Windows).
Definition: ecore_pipe.c:93
Eina_Bool ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes)
Writes on the file descriptor the data passed as parameter.
Definition: ecore_pipe.c:199
void * ecore_pipe_del(Ecore_Pipe *p)
Frees an Ecore_Pipe object created with ecore_pipe_add().
Definition: ecore_pipe.c:100
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339