LINUX.ORG.RU

Видеозахват + GTK

 , ,


0

2

Пытаюсь написать программку для захвата видео (v4l2 + GTK). Осилил этот пример. Теперь борюсь с GTK. Не могу уяснить, как подружить 2 цикла: захвата видео и gtk main? Где запускать цикл чтения с камеры и какой магией проводить отрисовку? Подскажите волшебные слова для гуглежа хотябы!

Предлагаю пройти творческий путь от gtk_idle_add со стопроцентной нагрузкой процессора и тормозами, через gtk_timeout_add с плохим временнем отзыва и, наконец, прийти в райские кущи многопоточных программ, пуская захват видео в одном потоке, GTK в другом и передавая из одного потока в другой лишь готовые данные, может даже и по указателю.

quiet_readonly ★★★★ ()

завалялось тут :)

#include <gst/interfaces/xoverlay.h>
#include <gtk/gtk.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h> // for GDK_WINDOW_XID
#endif
gint
destroy(GtkWidget *widget,GdkEvent *event,gpointer data) {
    g_print("destroy\n");
    gtk_main_quit();
    return TRUE;
}
gboolean
bus_call(GstBus * bus, GstMessage *msg, gpointer data) {
    GtkWidget *window = (GtkWidget*) data;
    gchar *debug;
    GError *error;
    g_debug("bus_call %d",GST_MESSAGE_TYPE(msg));
    switch(GST_MESSAGE_TYPE(msg)) {
        case GST_MESSAGE_EOS:
            g_debug("end of stream");
            break;
        case GST_MESSAGE_ELEMENT:
            if (gst_structure_has_name(msg->structure, "prepare-xwindow-id")) {
                g_debug("prepare-xwindow-xid");
                gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), GDK_WINDOW_XID(gtk_widget_get_window(window)));
                return TRUE;
            }
            return FALSE;
            break;
        case GST_MESSAGE_ERROR :
            gst_message_parse_error(msg,&error,&debug);
            g_debug("error:%s debug:%s",error->message,debug);
            g_free(debug);
            g_error_free(error);
            gtk_main_quit();
            break;    
        default:
            break;
}
    return TRUE;
}
GstElement *
create_pipeline(GtkWidget *area,gint width,gint height) {
    GstElement *pipeline,*source,*flip,*sink;
    GstCaps *caps;
    g_debug("create_pipeline");
    
    pipeline=gst_pipeline_new("test");
    
    source=gst_element_factory_make("v4l2src","play");
    
    flip=gst_element_factory_make("videoflip","flip");
    g_object_set(G_OBJECT(flip),"method",4,NULL);
    
    sink=gst_element_factory_make("xvimagesink","sink");
    
    if (!pipeline || !source || !sink ) {
        g_critical("Internal error\n");
        return NULL;
    }
gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline)),(GstBusFunc) bus_call, area);    
    gst_bin_add_many(GST_BIN(pipeline),source,flip,sink,NULL);
    caps=gst_caps_new_simple("video/x-raw-yuv",
        "width",G_TYPE_INT,width,
        "height",G_TYPE_INT,height,
        "framerate",GST_TYPE_FRACTION,30,1,
        NULL);
    gst_element_link_filtered(source,flip,caps);
    gst_element_link(flip,sink);
    gst_caps_unref(caps);
    return pipeline;
}
int
main(int argc,char *argv[]) {
    GError *error=NULL;
    GtkWidget *window;
    GtkWidget *area;
    GstElement *pipeline;
    gint width,height;
    
    gst_init(&argc,&argv);
    gtk_init(&argc,&argv);
    width=800;
    height=600;
    if (argc==3) {
        width=atoi(argv[1]);
        height=atoi(argv[2]);
    }
    if (width<100 || height<100 || width>1920 || height>1080) {
        g_error("args");
        exit(1);
    }    
    window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    
    area=gtk_drawing_area_new();
    gtk_widget_set_size_request(area,width,height);
    
    gtk_container_add(GTK_CONTAINER(window),area);
    g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);
    pipeline=create_pipeline(area,width,height);
    gtk_widget_show_all(window);
    gst_element_set_state(pipeline, GST_STATE_PLAYING);
    gtk_main();
    return(0);
}

MKuznetsov ★★★★★ ()
Ответ на: комментарий от MKuznetsov

Как-то все короче с гстримером. Но наш путь - в гамаке стоя. Так что я пошел указаным путем. :) Спасибо!

Devider ()

как подружить 2 цикла: захвата видео и gtk main?

погугли на тему многопоточности и узнаешь, что можно запустить эти циклы параллельно так, чтобы они друг другу не мешали

EugeneBas ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.