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 *_buid_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)
{
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 handoff (GstElement* object,
GstBuffer* arg0,
GstPad* arg1,
gpointer user_data)
{
Ecore_Pipe *pipe;
pipe = (Ecore_Pipe *)user_data;
printf ("handoff : %p\n", arg0);
gst_buffer_ref (arg0);
ecore_pipe_write(pipe, &arg0, sizeof(arg0));
}
int
main (int argc, char *argv[])
{
GstElement *pipeline;
char *filename;
Ecore_Pipe *pipe;
gst_init (&argc, &argv);
if (!ecore_init ())
{
gst_deinit ();
return 0;
}
pipe = ecore_pipe_add (handler);
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 = _buid_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
new_decoded_pad_cb (GstElement *demuxer,
GstPad *new_pad,
gpointer user_data)
{
GstElement *decoder;
GstPad *pad;
GstCaps *caps;
gchar *str;
caps = gst_pad_get_caps (new_pad);
str = gst_caps_to_string (caps);
if (g_str_has_prefix (str, "video/")) {
decoder = GST_ELEMENT (user_data);
pad = gst_element_get_pad (decoder, "sink");
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));
}
}
g_free (str);
gst_caps_unref (caps);
}
static GstElement
_buid_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;
}