194 lines
4.4 KiB
C
194 lines
4.4 KiB
C
//Compile with:
|
|
// gcc -o ecore_pipe_gstreamer_example ecore_pipe_gstreamer_example.c `pkg-config --libs --cflags ecore gstreamer-0.10`
|
|
|
|
#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)
|
|
{
|
|
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, NULL);
|
|
if (!pipe)
|
|
{
|
|
ecore_shutdown();
|
|
gst_deinit();
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 2)
|
|
{
|
|
g_print("usage: %s file.avi\n", argv[0]);
|
|
ecore_pipe_del(pipe);
|
|
ecore_shutdown();
|
|
gst_deinit();
|
|
return 0;
|
|
}
|
|
filename = argv[1];
|
|
|
|
pipeline = _build_pipeline(filename, pipe);
|
|
if (!pipeline)
|
|
{
|
|
g_print("Error during the pipeline building\n");
|
|
ecore_pipe_del(pipe);
|
|
ecore_shutdown();
|
|
gst_deinit();
|
|
return -1;
|
|
}
|
|
|
|
gst_element_set_state(pipeline, GST_STATE_PLAYING);
|
|
|
|
ecore_main_loop_begin();
|
|
|
|
ecore_pipe_del(pipe);
|
|
ecore_shutdown();
|
|
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 *
|
|
_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;
|
|
}
|
|
|