1 //Compile with:
2 // gcc -o ecore_pipe_gstreamer_example ecore_pipe_gstreamer_example.c `pkg-config --libs --cflags ecore gstreamer-1.0`
3 // or
4 // gcc -o ecore_pipe_gstreamer_example ecore_pipe_gstreamer_example.c `pkg-config --libs --cflags ecore gstreamer-0.10`
5 
6 #include <gst/gst.h>
7 #include <Ecore.h>
8 
9 static int nbr = 0;
10 
11 static GstElement *_build_pipeline(gchar *filename, Ecore_Pipe *pipe);
12 
13 static void        new_decoded_pad_cb(GstElement *demuxer,
14                                       GstPad *new_pad,
15                                       gpointer user_data);
16 
17 static void
handler(void * data,void * buf,unsigned int len EINA_UNUSED)18 handler(void *data, void *buf, unsigned int len EINA_UNUSED)
19 {
20    GstBuffer *buffer = *((GstBuffer **)buf);
21 
22    printf("handler : %p\n", buffer);
23    printf("frame  : %d %p %lld %p\n", nbr++, data, (long long)GST_BUFFER_DURATION(buffer), buffer);
24    gst_buffer_unref(buffer);
25 }
26 
27 static void
handoff(GstElement * object EINA_UNUSED,GstBuffer * arg0,GstPad * arg1 EINA_UNUSED,gpointer user_data)28 handoff(GstElement *object EINA_UNUSED,
29         GstBuffer *arg0,
30         GstPad *arg1 EINA_UNUSED,
31         gpointer user_data)
32 {
33    Ecore_Pipe *pipe;
34 
35    pipe = (Ecore_Pipe *)user_data;
36    printf("handoff : %p\n", arg0);
37    gst_buffer_ref(arg0);
38    ecore_pipe_write(pipe, &arg0, sizeof(arg0));
39 }
40 
41 int
main(int argc,char * argv[])42 main(int argc, char *argv[])
43 {
44    GstElement *pipeline;
45    char *filename;
46    Ecore_Pipe *pipe;
47 
48    gst_init(&argc, &argv);
49 
50    if (!ecore_init())
51      {
52         gst_deinit();
53         return 0;
54      }
55 
56    pipe = ecore_pipe_add(handler, NULL);
57    if (!pipe)
58      {
59         ecore_shutdown();
60         gst_deinit();
61         return 0;
62      }
63 
64    if (argc < 2)
65      {
66         g_print("usage: %s file.avi\n", argv[0]);
67         ecore_pipe_del(pipe);
68         ecore_shutdown();
69         gst_deinit();
70         return 0;
71      }
72    filename = argv[1];
73 
74    pipeline = _build_pipeline(filename, pipe);
75    if (!pipeline)
76      {
77         g_print("Error during the pipeline building\n");
78         ecore_pipe_del(pipe);
79         ecore_shutdown();
80         gst_deinit();
81         return -1;
82      }
83 
84    gst_element_set_state(pipeline, GST_STATE_PLAYING);
85 
86    ecore_main_loop_begin();
87 
88    ecore_pipe_del(pipe);
89    ecore_shutdown();
90    gst_deinit();
91 
92    return 0;
93 }
94 
95 static void
new_decoded_pad_cb(GstElement * demuxer EINA_UNUSED,GstPad * new_pad,gpointer user_data)96 new_decoded_pad_cb(GstElement *demuxer EINA_UNUSED,
97                    GstPad *new_pad,
98                    gpointer user_data)
99 {
100    GstElement *decoder;
101    GstPad *pad;
102    GstCaps *caps;
103    GstStructure *s;
104    const gchar *str;
105 
106 #if GST_CHECK_VERSION(1,0,0)
107    caps = gst_pad_get_current_caps(new_pad);
108 #else
109    caps = gst_pad_get_caps(new_pad);
110 #endif
111    s = gst_caps_get_structure(caps, 0);
112    str = gst_structure_get_name(s);
113 
114    if (g_str_has_prefix(str, "video/"))
115      {
116         decoder = GST_ELEMENT(user_data);
117 
118 #if GST_CHECK_VERSION(1,0,0)
119         pad = gst_element_get_static_pad(decoder, "sink");
120 #else
121         pad = gst_element_get_pad(decoder, "sink");
122 #endif
123         if (GST_PAD_LINK_FAILED(gst_pad_link(new_pad, pad)))
124           {
125              g_warning("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME(new_pad),
126                        GST_DEBUG_PAD_NAME(pad));
127           }
128         gst_object_unref(pad);
129      }
130    gst_caps_unref(caps);
131 }
132 
133 static GstElement *
_build_pipeline(gchar * filename,Ecore_Pipe * pipe)134 _build_pipeline(gchar *filename, Ecore_Pipe *pipe)
135 {
136    GstElement *pipeline;
137    GstElement *filesrc;
138    GstElement *demuxer;
139    GstElement *decoder;
140    GstElement *sink;
141    GstStateChangeReturn res;
142 
143    pipeline = gst_pipeline_new("pipeline");
144    if (!pipeline)
145      return NULL;
146 
147    filesrc = gst_element_factory_make("filesrc", "filesrc");
148    if (!filesrc)
149      {
150         printf("no filesrc");
151         goto failure;
152      }
153    g_object_set(G_OBJECT(filesrc), "location", filename, NULL);
154 
155    demuxer = gst_element_factory_make("oggdemux", "demuxer");
156    if (!demuxer)
157      {
158         printf("no demux");
159         goto failure;
160      }
161 
162    decoder = gst_element_factory_make("theoradec", "decoder");
163    if (!decoder)
164      {
165         printf("no dec");
166         goto failure;
167      }
168 
169    g_signal_connect(demuxer, "pad-added",
170                     G_CALLBACK(new_decoded_pad_cb), decoder);
171 
172    sink = gst_element_factory_make("fakesink", "sink");
173    if (!sink)
174      {
175         printf("no sink");
176         goto failure;
177      }
178    g_object_set(G_OBJECT(sink), "sync", EINA_TRUE, NULL);
179    g_object_set(G_OBJECT(sink), "signal-handoffs", EINA_TRUE, NULL);
180    g_signal_connect(sink, "handoff",
181                     G_CALLBACK(handoff), pipe);
182 
183    gst_bin_add_many(GST_BIN(pipeline),
184                     filesrc, demuxer, decoder, sink, NULL);
185 
186    if (!gst_element_link(filesrc, demuxer))
187      goto failure;
188    if (!gst_element_link(decoder, sink))
189      goto failure;
190 
191    res = gst_element_set_state(pipeline, GST_STATE_PAUSED);
192    if (res == GST_STATE_CHANGE_FAILURE)
193      goto failure;
194 
195    res = gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
196    if (res != GST_STATE_CHANGE_SUCCESS)
197      goto failure;
198 
199    return pipeline;
200 
201 failure:
202    gst_object_unref(GST_OBJECT(pipeline));
203    return NULL;
204 }
205 
206