Hello all,<br><br>I still have some questions about gstreamer.<br><br>Actually I&#39;d like to change the way my program work, in order to display a frame from the camera only once the image processing has been done, and with a rectangle over the face of the person.<br>
<br>So I changed my pipeline (removed the screen_sink element), and I&#39;d like to send a buffer from my image processing function to the gtk drawing area where the camera image was displayed before. I tried to do it with gtk drawing area (and with gtk image too with no sucess), but I can&#39;t find the way to change the image contained in the drawing area.<br>
<br>Here is my code :<br><br><br><br>///// IMAGE PROCESSING CALLBACK<br><br>/* Callback to be called when data goes through the pad */<br>static gboolean process_frame(GstElement *video_sink,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GstBuffer *buffer, GstPad *pad, AppData *appdata)<br>
{<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int x, y;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // getting the pointer to camera buffer<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned char *data_photo = (unsigned char *) GST_BUFFER_DATA(buffer);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br><br>// REMOVED PART WHERE THE COORDINATES OF THE POSITION OF THE FACE IS CALCULATED //<br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>// THIS PART IS WHAT I TRIED, BUT I HAVE A SEGMENTATION FAULT WHEN CREATING PIXBUF //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GdkPixbuf *newscreen;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //newscreen = gdk_pixbuf_new_from_data(data_photo,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //GDK_COLORSPACE_RGB, /* RGB-colorspace */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //FALSE, /* No alpha-channel */<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //8, /* Bits per RGB-component */<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //IMAGE_WIDTH, IMAGE_HEIGHT, /* Dimensions */<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //3*IMAGE_WIDTH, /* Number of bytes between lines (ie stride) */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //NULL, NULL); /* Callbacks */<br><br><br>gdk_draw_pixmap(GDK_DRAWABLE(appdata-&gt;screen), appdata-&gt;screen-&gt;style-&gt;black_gc, GDK_DRAWABLE(newscreen), 0, 0, 0, 0, -1, -1);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return TRUE;<br>}<br><br><br><br><br><br>/////// PIPELINE<br><br><br>/* Initialize the the Gstreamer pipeline. Below is a diagram<br>&nbsp;* of the pipeline that will be created:<br>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;* |Camera|&nbsp; |CSP&nbsp;&nbsp; |&nbsp; |Screen|&nbsp; |Screen|&nbsp;&nbsp; |Image&nbsp;&nbsp;&nbsp;&nbsp; |<br>
&nbsp;* |src&nbsp;&nbsp; |-&gt;|Filter|-&gt;|queue |-&gt;|sink&nbsp; |-&gt; |processing|-&gt;&nbsp; Display<br>&nbsp;*/<br>static gboolean initialize_pipeline(AppData *appdata,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int *argc, char ***argv)<br>{<br>&nbsp;&nbsp;&nbsp; GstElement *pipeline, *camera_src, *screen_sink;<br>
&nbsp;&nbsp;&nbsp; GstElement *screen_queue;<br>&nbsp;&nbsp;&nbsp; GstElement *csp_filter;<br>&nbsp;&nbsp;&nbsp; GstCaps *caps;<br>&nbsp;&nbsp;&nbsp; GstBus *bus;<br>&nbsp;&nbsp;&nbsp; GstPad *sinkpad;<br><br>&nbsp;&nbsp;&nbsp; /* Initialize Gstreamer */<br>&nbsp;&nbsp;&nbsp; gst_init(argc, argv);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /* Create pipeline and attach a callback to it&#39;s<br>
&nbsp;&nbsp;&nbsp; &nbsp;* message bus */<br>&nbsp;&nbsp;&nbsp; pipeline = gst_pipeline_new(&quot;test-camera&quot;);<br><br>&nbsp;&nbsp;&nbsp; bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));<br>&nbsp;&nbsp;&nbsp; gst_bus_add_watch(bus, (GstBusFunc)bus_callback, appdata);<br>&nbsp;&nbsp;&nbsp; gst_object_unref(GST_OBJECT(bus));<br>
&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /* Save pipeline to the AppData structure */<br>&nbsp;&nbsp;&nbsp; appdata-&gt;pipeline = pipeline;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /* Create elements */<br>&nbsp;&nbsp;&nbsp; /* Camera video stream comes from a Video4Linux driver */<br>&nbsp;&nbsp;&nbsp; camera_src = gst_element_factory_make(VIDEO_SRC, &quot;camera_src&quot;);<br>
&nbsp;&nbsp;&nbsp; /* Colorspace filter is needed to make sure that sinks understands<br>&nbsp;&nbsp;&nbsp; &nbsp;* the stream coming from the camera */<br>&nbsp;&nbsp;&nbsp; csp_filter = gst_element_factory_make(&quot;ffmpegcolorspace&quot;, &quot;csp_filter&quot;);<br>
&nbsp;&nbsp;&nbsp; /* Queue creates new thread for the stream */<br>&nbsp;&nbsp;&nbsp; screen_queue = gst_element_factory_make(&quot;queue&quot;, &quot;screen_queue&quot;);<br>&nbsp;&nbsp;&nbsp; /* Sink that shows the image on screen. Xephyr doesn&#39;t support XVideo<br>
&nbsp;&nbsp;&nbsp; &nbsp;* extension, so it needs to use ximagesink, but the device uses<br>&nbsp;&nbsp;&nbsp; &nbsp;* xvimagesink */<br>&nbsp;&nbsp;&nbsp; //screen_sink = gst_element_factory_make(VIDEO_SINK, &quot;screen_sink&quot;);<br><br>&nbsp;&nbsp;&nbsp; sinkpad = gst_element_get_static_pad(screen_queue,&quot;sink&quot;);<br>
&nbsp;&nbsp;&nbsp; gst_pad_add_buffer_probe(sinkpad,G_CALLBACK(process_frame), appdata);<br><br><br>&nbsp;&nbsp;&nbsp; /* Check that elements are correctly initialized */<br>&nbsp;&nbsp;&nbsp; if(!(pipeline &amp;&amp; camera_src /*&amp;&amp; screen_sink*/ &amp;&amp; csp_filter &amp;&amp; screen_queue))<br>
&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; g_critical(&quot;Couldn&#39;t create pipeline elements&quot;);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return FALSE;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /* Add elements to the pipeline. This has to be done prior to<br>&nbsp;&nbsp;&nbsp; &nbsp;* linking them */<br>
&nbsp;&nbsp;&nbsp; gst_bin_add_many(GST_BIN(pipeline), camera_src, csp_filter,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; screen_queue, /*screen_sink,*/ NULL);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /* Specify what kind of video is wanted from the camera */<br>&nbsp;&nbsp;&nbsp; caps = gst_caps_new_simple(&quot;video/x-raw-rgb&quot;,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;width&quot;, G_TYPE_INT, IMAGE_WIDTH,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;height&quot;, G_TYPE_INT, IMAGE_HEIGHT,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;framerate&quot;, GST_TYPE_FRACTION, FRAMERATE, 1,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; NULL);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
<br>&nbsp;&nbsp;&nbsp; /* Link the camera source and colorspace filter using capabilities<br>&nbsp;&nbsp;&nbsp; &nbsp;* specified */<br>&nbsp;&nbsp;&nbsp; if(!gst_element_link_filtered(camera_src, csp_filter, caps))<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return FALSE;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; gst_caps_unref(caps);<br>
&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /* Connect Colorspace Filter -&gt; Screen Queue -&gt; Screen Sink<br>&nbsp;&nbsp;&nbsp; &nbsp;* This finalizes the initialization of the screen-part of the pipeline */<br>&nbsp;&nbsp;&nbsp; if(!gst_element_link_many(csp_filter, screen_queue, /*screen_sink, */NULL))<br>
&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return FALSE;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; gst_element_set_state(pipeline, GST_STATE_PAUSED);&nbsp;&nbsp;&nbsp; <br><br>&nbsp;&nbsp;&nbsp; return TRUE;<br>}<br><br><br><br><br><br><br><br>/////// MAIN FUNCTION<br><br><br>int main(int argc, char **argv)<br>
{<br>// variables for face detection<br>&nbsp;&nbsp;&nbsp; // main structure for vjdetect<br><br>&nbsp;&nbsp;&nbsp; pdata = (mainstruct*) calloc(1, sizeof(mainstruct));<br>&nbsp;&nbsp;&nbsp; // Allocate memory for array of face detections returned by facedetector (VjDetect).<br>
&nbsp;&nbsp;&nbsp; pdata-&gt;pFaceDetections = (FLY_Rect *)calloc(MAX_NUMBER_OF_FACE_DETECTIONS, sizeof(FLY_Rect));<br>&nbsp;&nbsp;&nbsp; init(pdata);<br><br>&nbsp;&nbsp;&nbsp; AppData appdata;<br>&nbsp;&nbsp;&nbsp; appdata.expression = 0;<br>&nbsp;&nbsp;&nbsp; GtkWidget *hbox, *vbox_button, *vbox, *button1, *button2;<br>
<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /* Initialize and create the GUI */<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; example_gui_initialize(<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &amp;appdata.program, &amp;appdata.window,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &amp;argc, &amp;argv, &quot;Expression Detector&quot;);<br><br>&nbsp;&nbsp;&nbsp; vbox = gtk_vbox_new(FALSE, 0);<br>
&nbsp;&nbsp;&nbsp; hbox = gtk_hbox_new(FALSE, 0);<br>&nbsp;&nbsp;&nbsp; vbox_button = gtk_vbox_new(FALSE, 0);<br><br>&nbsp;&nbsp;&nbsp; gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);<br>&nbsp;&nbsp;&nbsp; gtk_box_pack_start(GTK_BOX(hbox), vbox_button, FALSE, FALSE, 0);<br>
<br>&nbsp;&nbsp;&nbsp; appdata.screen = gtk_drawing_area_new();<br>&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.screen, 500, 380);<br>&nbsp;&nbsp;&nbsp; gtk_box_pack_start(GTK_BOX(vbox), appdata.screen, FALSE, FALSE, 0);<br><br>&nbsp;&nbsp;&nbsp; button1 = gtk_toggle_button_new_with_label(&quot;Run/Stop&quot;);<br>
&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(button1, 170, 75);<br>&nbsp;&nbsp;&nbsp; gtk_box_pack_start(GTK_BOX(vbox_button), button1, FALSE, FALSE, 0);<br><br>&nbsp;&nbsp;&nbsp; button2 = gtk_toggle_button_new_with_label(&quot;Expressions ON/OFF&quot;);<br>&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(button2, 170, 75);<br>
&nbsp;&nbsp;&nbsp; gtk_box_pack_start(GTK_BOX(vbox_button), button2, FALSE, FALSE, 0);<br><br><br>&nbsp;&nbsp;&nbsp; appdata.anger = gtk_image_new_from_file(&quot;./smileys/anger.jpg&quot;);<br>&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.anger, 160, 180);<br>
&nbsp;&nbsp;&nbsp; appdata.disgust = gtk_image_new_from_file(&quot;./smileys/disgust.jpg&quot;);<br>&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.disgust, 160, 180);<br>&nbsp;&nbsp;&nbsp; appdata.fear = gtk_image_new_from_file(&quot;./smileys/fear.jpg&quot;);<br>
&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.fear, 160, 180);<br>&nbsp;&nbsp;&nbsp; appdata.happy = gtk_image_new_from_file(&quot;./smileys/happy.jpg&quot;);<br>&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.happy, 160, 180);<br>&nbsp;&nbsp;&nbsp; appdata.neutral = gtk_image_new_from_file(&quot;./smileys/neutral.jpg&quot;); <br>
&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.neutral, 160, 180);<br>&nbsp;&nbsp;&nbsp; appdata.sad = gtk_image_new_from_file(&quot;./smileys/sad.jpg&quot;);<br>&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.sad, 160, 180);<br>&nbsp;&nbsp;&nbsp; appdata.surprise = gtk_image_new_from_file(&quot;./smileys/surprise.jpg&quot;); <br>
&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.surprise, 160, 180);<br>&nbsp;&nbsp;&nbsp; appdata.unknown = gtk_image_new_from_file(&quot;./smileys/unknown.jpg&quot;);<br>&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.unknown, 160, 180);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; appdata.smiley = gtk_image_new_from_file(&quot;./smileys/unknown.jpg&quot;);<br>
&nbsp;&nbsp;&nbsp; gtk_widget_set_size_request(appdata.smiley, 160, 180);<br>&nbsp;&nbsp;&nbsp; gtk_box_pack_start(GTK_BOX(vbox_button), appdata.smiley, FALSE, FALSE, 0);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; g_signal_connect(G_OBJECT(button1), &quot;clicked&quot;,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;G_CALLBACK(button1_pressed), &amp;appdata);<br>
<br>&nbsp;&nbsp;&nbsp; g_signal_connect(G_OBJECT(button2), &quot;clicked&quot;,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;G_CALLBACK(button2_pressed), &amp;appdata);<br><br><br>&nbsp;&nbsp;&nbsp; gtk_container_add(GTK_CONTAINER(appdata.window), hbox);<br><br>&nbsp;&nbsp;&nbsp; /* Initialize the GTK pipeline */<br>
&nbsp;&nbsp;&nbsp; if(!initialize_pipeline(&amp;appdata, &amp;argc, &amp;argv))<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hildon_banner_show_information(<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GTK_WIDGET(appdata.window),<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;gtk-dialog-error&quot;,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &quot;Failed to initialize pipeline&quot;);<br>
&nbsp;&nbsp;&nbsp; }<br><br><br><br>&nbsp;&nbsp;&nbsp; g_signal_connect(G_OBJECT(appdata.window), &quot;destroy&quot;,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; G_CALLBACK(destroy_pipeline), &amp;appdata);<br><br><br>&nbsp;&nbsp;&nbsp; /* Begin the main application */<br>&nbsp;&nbsp;&nbsp; example_gui_run(appdata.program, appdata.window);<br>
<br>&nbsp;&nbsp;&nbsp; /* Free the gstreamer resources. Elements added<br>&nbsp;&nbsp;&nbsp; &nbsp;* to the pipeline will be freed automatically */<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br><br>What I&#39;d like to do is to modify the data_photo buffer to draw a rectangle in it (in the process_frame function), and draw the content in the appdata.screen GtkWidget. (by the way screen is declared as a GtkWidget * in the appdata structure).<br>
<br>Thanks in advance for your help !<br>Bruno<br><br>