how to save a screenshot (or a frame) from a camera stream

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

how to save a screenshot (or a frame) from a camera stream

arzo
Hello,
I am trying to save jpeg (or bmp), while displaying the screen simultaneously.

I have written following code:
(can be compiled after getting 
yes|sudo apt-get install libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev
yes|sudo apt-get install libgtk2.0
compilation:
#g++ -Wall `pkg-config gtk+-2.0 --cflags` `pkg-config gstreamer-0.10 --cflags` -c example.cpp -o example.o 
#OR directly
g++ -Wall -Wall \
-pthread \
-I/usr/include/gtk-2.0 \
-I/usr/lib/i386-linux-gnu/gtk-2.0/include \
-I/usr/include/atk-1.0 \
-I/usr/include/cairo \
-I/usr/include/gdk-pixbuf-2.0 \
-I/usr/include/pango-1.0 \
-I/usr/include/gio-unix-2.0/ \
-I/usr/include/glib-2.0 \
-I/usr/lib/i386-linux-gnu/glib-2.0/include \
-I/usr/include/pixman-1 \
-I/usr/include/freetype2 \
-I/usr/include/libpng12 \
-I/usr/include/glib-2.0 \
-I/usr/lib/i386-linux-gnu/glib-2.0/include \
-I/usr/include/gstreamer-0.10 \
-I/usr/include/libxml2 \
-I/usr/include/glib-2.0 \
-I/usr/lib/i386-linux-gnu/glib-2.0/include \
-I/usr/include/gstreamer-0.10 \
-I/usr/include/libxml2  \
-g     -c example.cpp -o example.o
linker: 
 #g++ `pkg-config gtk+-2.0 --libs` `pkg-config gstreamer-0.10 --libs` -lgstinterfaces-0.10 example.o -o example 
#OR directly
g++ example.o -o example \
-pthread -lgstreamer-0.10 \
-lgdk_pixbuf-2.0 
application code:
#include <string.h> /* for memset () */
#include <gst/gst.h>

//the base of the code https://vcs.maemo.org/svn/maemoexamples/tags/maemo_4.1/maemo-examples/example_camera.c
#include <gtk/gtk.h>
#include <gst/gst.h>
//#include <gst/interfaces/xoverlay.h>
#include <gdk/gdkx.h>

#define SAVE_FOLDER_DEFAULT  	 "./"
#define PHOTO_NAME_DEFAULT	 "Picture"
#define PHOTO_NAME_SUFFIX_DEFAULT ".bmp"
#define EXTENSION "bmp"
/* Creates a jpeg file from the buffer's raw image data */

bool takePhoto=false;

static gboolean create_jpeg(unsigned char *data)
{
    printf(".");
    GdkPixbuf *pixbuf = NULL;
    GError *error = NULL;
    guint height, width, bpp;
    const gchar *directory;
    GString *filename;
    guint base_len, i;
    struct stat statbuf;

    width = 640;
    height = 480;
    bpp = 24;

    /* Define the save folder */
    directory = SAVE_FOLDER_DEFAULT;
    if(directory == NULL)
    {
        directory = g_get_tmp_dir();
    }


    /* Create an unique file name */
    filename = g_string_new(g_build_filename(directory, PHOTO_NAME_DEFAULT, NULL));
    base_len = filename->len;
    g_string_append(filename, PHOTO_NAME_SUFFIX_DEFAULT);
    for(i = 1; !stat(filename->str, &statbuf); ++i)
    {
        g_string_truncate(filename, base_len);
        g_string_append_printf(filename, "%d%s", i, PHOTO_NAME_SUFFIX_DEFAULT);
    }


    /* Create a pixbuf object from the data */
    pixbuf = gdk_pixbuf_new_from_data(data,
                                      GDK_COLORSPACE_RGB, /* RGB-colorspace */
                                      FALSE, /* No alpha-channel */
                                      bpp/3, /* Bits per RGB-component */
                                      width, height, /* Dimensions */
                                      3*width, /* Number of bytes between lines (ie stride) */
                                      NULL, NULL); /* Callbacks */

    /* Save the pixbuf content's in to a jpeg file and check for
    * errors */
    if(!gdk_pixbuf_save(pixbuf, filename->str, EXTENSION, &error, NULL))
    {
        g_warning("%s\n", error->message);
        g_error_free(error);
        gdk_pixbuf_unref(pixbuf);
        g_string_free(filename, TRUE);
        return FALSE;
    }

    /* Free allocated resources and return TRUE which means
    * that the operation was succesful */
    g_string_free(filename, TRUE);
    gdk_pixbuf_unref(pixbuf);
    return TRUE;
}

GstElement *pipeline;
static gboolean
cb_handoff2 (GstElement *src,
             GstBuffer  *buffer,
             GstPad     *pad,
             gpointer    user_data)
{
    static gboolean white = FALSE;
    static int cnt=0;
    char *ptr=0;
    printf("got photo %d from %s, user_data=%p, buffer size=%d dur=%d\n", cnt++, ptr=gst_pad_get_name(pad), user_data, (int)buffer->size, (int)buffer->duration);
    if(takePhoto) printf("and yes! taking a photo\n");
    g_free(ptr);
    ptr=0;

    if(takePhoto)
    {
        //gst_element_change_state (pipeline, GST_STATE_CHANGE_READY_TO_PAUSED);
        create_jpeg((unsigned char *) GST_BUFFER_DATA(buffer));
        //gst_element_change_state (pipeline, GST_STATE_CHANGE_PAUSED_TO_PLAYING);
    }
    takePhoto=0;
    return TRUE;
}

gint ButtonPressed(GtkWidget* widget, gpointer data)
{
    g_print("You pressed the button.\n");
    takePhoto=1;
    return FALSE;
}
gint main(gint argc , gchar *argv[])
{

    GtkWidget *window;
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    //make_window_black(window);
    gtk_widget_show_all(window);
    GMainLoop *loop;
    loop = g_main_loop_new (NULL, FALSE);
    GtkWidget *button=gtk_button_new_with_label("photo");

    gtk_container_add(GTK_CONTAINER(window), button);
    gtk_widget_show_all(button);

    //gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(Delete), NULL);

    g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(ButtonPressed), NULL);


    GstElement *src
    , *tee
    , *queue1
    , *queue2
    , *videosink1
    , *videosink2
    ;
    gst_init (&argc, &argv);
    pipeline = gst_pipeline_new ("pipeline");
    src = gst_element_factory_make ("v4l2src", "source");
    tee = gst_element_factory_make ("tee", "t");
    queue1 = gst_element_factory_make ("queue", "q1");
    queue2 = gst_element_factory_make ("queue", "q2");
    videosink1 = gst_element_factory_make ("xvimagesink", "videosink");
    videosink2 = gst_element_factory_make ("fakesink", "videosink2");

    GstElement *flt = gst_element_factory_make ("capsfilter", "flt");
    GstElement *conv = gst_element_factory_make ("ffmpegcolorspace", "conv");
    GstCaps *caps=gst_caps_new_simple ("video/x-raw-rgb",
                                       "width", G_TYPE_INT, 3,
                                       "height", G_TYPE_INT, 2,
                                       NULL);
    g_object_set (G_OBJECT (flt), "caps",caps, NULL);
    g_object_set(G_OBJECT(videosink2),"signal-handoffs", TRUE,NULL);
    g_signal_connect(videosink2, "handoff", G_CALLBACK (cb_handoff2), NULL);

    gst_bin_add_many(GST_BIN (pipeline), src, tee,  queue1, videosink1, NULL);
    gst_bin_add_many(GST_BIN (pipeline),            queue2, videosink2, NULL);
    //gst_bin_add_many(GST_BIN (pipeline), flt, conv, NULL);

    gst_element_link_many (src, tee, queue1, videosink1, NULL);
    gst_element_link_many (     tee, queue2, videosink2, NULL);

    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    g_main_loop_run (loop);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(GST_OBJECT (pipeline));
    return 0;
}

The problem is i get triple repeated images in result (after pressing gtk button).
I attach example photo here: http://img854.imageshack.us/img854/4541/picture1dkz.png 

Do you have any ideas can I deal with this problem?
Reply | Threaded
Open this post in threaded view
|

Re: how to save a screenshot (or a frame) from a camera stream

Tim-Philipp Müller-2
On Thu, 2012-11-22 at 09:37 -0800, arzo wrote:

> I am trying to save jpeg (or bmp), while displaying the screen
> simultaneously.
>
> I have written following code:
> (can be compiled after *getting*
> *compilation: *
>
> *linker:*
>
> *application code: *
>
>
> The problem is i get triple repeated images in result (after pressing gtk
> button).
> I attach example photo here:
> http://img854.imageshack.us/img854/4541/picture1dkz.png 
>
> Do you have any ideas can I deal with this problem?

The easiest would be to use the camerabin element (if you are using
GStreamer 1.0), or camerabin2 if you are using the old 0.10 version.

It allows you to take snapshot images or record a video while showing
the video stream at the same time.

Cheers
 -Tim

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: how to save a screenshot (or a frame) from a camera stream

arzo
Thank you very much Tim!
I did not even know about existence of such a solution.

My problem needs video stream and screen shot to be threated separately (I would like screen shots to be in higher quality than video, and also screen shots (photos) should, in my case, have better quality than preview and there should be included time of taking the photo).

Unfortunately, I am afraid that camerabin2 can't handle those problems.
I hope there is at least small hope it all can be done,

greetings,
Artur
Reply | Threaded
Open this post in threaded view
|

Re: how to save a screenshot (or a frame) from a camera stream

Nicolas Dufresne
Le mardi 27 novembre 2012 à 01:13 -0800, arzo a écrit :

> Thank you very much Tim!
> I did not even know about existence of such a solution.
>
> My problem needs video stream and screen shot to be threated
> separately (I
> would like screen shots to be in higher quality than video, and also
> screen
> shots (photos) should, in my case, have better quality than preview
> and
> there should be included time of taking the photo).
>
> Unfortunately, I am afraid that camerabin2 can't handle those
> problems.
> I hope there is at least small hope it all can be done,

Camerabin does that. See the properties video-capture-caps,
image-capture-caps and preview-capture-caps. These are use to choose the
quality for each of them. Note that capture is not gapless.

Nicolas

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel