Hello all
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">My name is Corentin and I'm working on
a web multimedia project based on Django frameworkand Gstreamer, and
I want to add a scene change detection fonctionality to my project.
</p>
<p style="margin-bottom: 0cm;">To do this i need to acces to the video
data so I take a (long..) look at Gstreamer manual and made this
code. It's made with the Hello world code to read a ogg audio file
(Chapter 10 in the manual), I easily turned to play ogg video file
and with the code from the example of data probing (Chapter 18 in the
manual)</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> so here is my code :</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">#include <gst/gst.h><br><br>
</p>
<p style="margin-bottom: 0cm;">/*<br>* Global objects are usually a bad
thing. For the purpose of this<br>* example, we will use them, however.<br>*/</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">GstElement *pipeline, *source, *parser,
*decoder, *csp, *filter, *sink;<br>
</p>
<p style="margin-bottom: 0cm;">static gboolean<br>bus_call (GstBus *bus,<br>GstMessage *msg,<br>gpointer data)<br>{</p>
<p style="margin-bottom: 0cm;"> GMainLoop *loop = (GMainLoop *) data;<br>
</p>
<p style="margin-bottom: 0cm;"> switch (GST_MESSAGE_TYPE (msg)) {<br>case GST_MESSAGE_EOS:<br>g_print ("End-of-stream\n");<br>g_main_loop_quit (loop);<br>break;<br>case GST_MESSAGE_ERROR: {<br>gchar *debug;<br>
GError *err;</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> gst_message_parse_error (msg,
&err, &debug);<br>g_free (debug);<br>g_print ("Error: %s\n",
err->message);<br>g_error_free (err);<br>
</p>
<p style="margin-bottom: 0cm;"> g_main_loop_quit (loop);<br>break;<br>}<br>default:<br>break;<br>}</p>
<p style="margin-bottom: 0cm;"> return TRUE;<br>}</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">// this fonction deals with the pixels
(it should invert the video)<br>static gboolean<br>cb_have_data (GstPad *pad,<br>GstBuffer *buffer,<br>gpointer u_data)<br>{</p>
<p style="margin-bottom: 0cm;">        g_print ("Youpi, you are in the
loop of the frame \n");<br>gint x, y;<br>guint16 *data = (guint16 *)
GST_BUFFER_DATA (buffer), t;</p>
<p style="margin-bottom: 0cm;"> // invert data<br>for (y = 0; y < 288; y++) {<br>for (x = 0; x < 384 / 2; x++) {<br>t = data[384 - 1 - x];<br>data[384 - 1 - x] = data[x];<br>data[x] = t;<br>}<br>data += 384;<br>}</p>
<p style="margin-bottom: 0cm;"> return TRUE;<br>}</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">// add a pad<br>static void<br>new_pad (GstElement *element,<br>GstPad *pad,<br>gpointer data)<br>{</p>
<p style="margin-bottom: 0cm;"> GstPad *sinkpad;</p><p style="margin-bottom: 0cm;">/* We can now link this pad with the
audio decoder */<br>g_print ("Dynamic pad created,
linking parser/decoder\n");<br>sinkpad = gst_element_get_pad
(decoder, "sink");<br>gst_pad_link (pad, sinkpad);<br>gst_object_unref (sinkpad);</p>
<p style="margin-bottom: 0cm;">}</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">int<br>main (int argc,<br>char *argv[])<br>{</p>
<p style="margin-bottom: 0cm;"> GMainLoop *loop;<br>GstBus *bus;<br>GstCaps *filtercaps;<br>GstPad *pad2;</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> /* initialize GStreamer */<br>gst_init (&argc, &argv);<br>loop = g_main_loop_new (NULL, FALSE);<br><br>
</p>
<p style="margin-bottom: 0cm;"> /* check input arguments */<br>if (argc != 2) {<br>g_print ("Usage: %s
<Ogg/Vorbis filename>\n", argv[0]);<br>return -1;</p>
<p style="margin-bottom: 0cm;"> }</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> /* create elements */<br>pipeline = gst_pipeline_new
("player");<br>source = gst_element_factory_make
("filesrc", "file-source");<br>parser = gst_element_factory_make
("oggdemux", "ogg-parser");<br>decoder = gst_element_factory_make
("theoradec", "theora-decoder");<br>filter = gst_element_factory_make
("capsfilter", "filter");<br>csp = gst_element_factory_make
("ffmpegcolorspace", "csp");<br>g_assert (filter != NULL); /* should
always exist */<br>
</p>
<p style="margin-bottom: 0cm;"> sink = gst_element_factory_make
("ximagesink", "sink");<br>if (!pipeline || !source || !parser
|| !decoder || !csp || !filter ||!sink) {<br>g_print ("One element could
not be created\n");</p>
<p style="margin-bottom: 0cm;"> return -1;<br>}</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> /* set filename property on the file
source. Also add a message<br>* handler. */<br>g_object_set (G_OBJECT (source),
"location", argv[1], NULL);<br>
</p>
<p style="margin-bottom: 0cm;"> bus = gst_pipeline_get_bus
(GST_PIPELINE (pipeline));<br>gst_bus_add_watch (bus, bus_call,
loop);<br>gst_object_unref (bus);<br><br>
</p>
<p style="margin-bottom: 0cm;"> /* put all elements in a bin */<br>gst_bin_add_many (GST_BIN (pipeline),<br>source, parser, decoder,
csp,filter, sink, NULL);<br><br>
</p>
<p style="margin-bottom: 0cm;"> /* link together - note that we
cannot link the parser and<br>* decoder yet, becuse the parser
uses dynamic pads. For that,<br>* we set a pad-added signal handler.
*/<br>gst_element_link (source, parser);<br>gst_element_link_many (decoder, csp ,
filter, sink, NULL);<br>g_signal_connect (parser,
"pad-added", G_CALLBACK (new_pad), NULL);</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> // create the filter caps vvith the video caracteristics<br></p>
<p style="margin-bottom: 0cm;"> filtercaps = gst_caps_new_simple
("video/x-raw-rgb",<br>"width", G_TYPE_INT,
288,<br>"height", G_TYPE_INT,
208,<br>"framerate",
GST_TYPE_FRACTION, 30, 1,<br>//"bpp", G_TYPE_INT,
16,<br>//"depth", G_TYPE_INT,
16,<br>// "endianness",
G_TYPE_INT, G_BYTE_ORDER,<br>NULL);</p>
<p style="margin-bottom: 0cm;"> g_print ("try to set the caps on
the filter\n");<br>g_object_set (G_OBJECT (filter),
"caps", filtercaps, NULL);<br>gst_caps_unref (filtercaps);</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> g_print ("try to get the
pad\n");<br>pad2 = gst_element_get_pad
(csp,"csp");<br>if ( pad2 == NULL )<br>{<br>g_print ("could not get the
pad\n");<br>}<br><br>
</p>
<p style="margin-bottom: 0cm;"> //pad2 = gst_element_get_pad (csp,
"csp");<br><br>
</p>
<p style="margin-bottom: 0cm;"> //add the probe<br>g_print ("\n setting the probe");<br>gst_pad_add_buffer_probe (pad2,
G_CALLBACK (cb_have_data), NULL);<br>g_print ("\nprobe added\n");<br>gst_object_unref (pad2);</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> /* Now set to playing and iterate. */<br>g_print ("Setting to
PLAYING\n");<br>gst_element_set_state (pipeline,
GST_STATE_PLAYING);<br>g_print ("Running\n");<br>g_main_loop_run (loop);</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;"> /* clean up nicely */<br>g_print ("Returned, stopping
playback\n");<br>gst_element_set_state (pipeline,
GST_STATE_NULL);<br>g_print ("Deleting pipeline\n");<br>gst_object_unref (GST_OBJECT
(pipeline));</p><p style="margin-bottom: 0cm;"> return 0;</p>
<p style="margin-bottom: 0cm;">}</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">To my mind the error comes from getting
the pad. I take a look about this and I tried all the functions :</p>
<p style="margin-bottom: 0cm;">gst_element_get_static_pad() &
gst_element_get_request_pad().<br>
</p>
<p style="margin-bottom: 0cm;">The fact is I set the filter after the
csp (ffmpegcolorspace) because it think this is here I will find the video data.<br>I tried to set the filter before but
nothing changed.<br>I can't find my error.</p>
<p style="margin-bottom: 0cm;">If anyone of you knows where I'm wrong
it would be very nice to tell me because i'm getting mad.</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">You 'll find the little video I use to
test my code at :<br><a href="http://corentino.fr/dl/vid.ogg" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">http://corentino.fr/dl/vid.ogg</a><br>you'll need it, because some video properties are set in hard, if you try my code ! : )
<br>
</p>
<p style="margin-bottom: 0cm;">Thank you by advance,<br>Sincerly<br></p><span class="sg"><span>
<p style="margin-bottom: 0cm;"><br>Corentin</p>
<p style="margin-bottom: 0cm;"><br>
</p>
<p style="margin-bottom: 0cm;">
</p>
</span>
</span>