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