gtk 应用程序中的 RTSP 视频

发布于 2024-11-16 13:23:17 字数 278 浏览 2 评论 0原文

我开发了一个 gtk 应用程序,用于播放来自 IP 摄像机的 RTSP 流。

pipeline=gst_parse_launch(“rtspsrc位置=rtsp://192.168.127.100:554/mo​​xa-cgi/udpStreamer延迟=0!decodebin!xvimagesink”,NULL); gst_element_set_state(管道,GST_STATE_PLAYING);

我将此代码粘贴到我的程序中,它工作正常,但另一个窗口。 如何在我的绘图区域或其他小部件上显示视频?

I develop an gtk-application for playing RTSP stream from IP cameras.

pipeline=gst_parse_launch("rtspsrc location=rtsp://192.168.127.100:554/moxa-cgi/udpStreamer latency=0 ! decodebin ! xvimagesink",NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);

I paste this code to my program, and it work fine, but another window.
How can I display the video on my drawing_area or other widget?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吃颗糖壮壮胆 2024-11-23 13:23:17

我做了几乎相同的事情,并在 Gtk3 中为其创建了一个类。希望有帮助。

class Camera(Gtk.DrawingArea):
def __init__(self, type, filepath, ui_table, callback):
    self.ui_table = ui_table
    self.type = type
    self.callback = callback

    # create GStreamer pipeline
    pipeline = Gst.Pipeline()

    # create bus to get events from GStreamer pipeline
    bus_camera = pipeline.get_bus()
    bus_camera.add_signal_watch()
    bus_camera.connect('message::eos', self.on_eos_Camera)
    bus_camera.connect('message::error', self.on_error_Camera)


    source = Gst.ElementFactory.make("rtspsrc", "source")
    source.set_property("location", filepath)
    source.set_property("latency", 0)
    source.connect("pad-added", self.on_pad)
    pipeline.add(source)

    depay = Gst.ElementFactory.make("rtph264depay", "depay")
    pipeline.add(depay)
    source.link(depay)

    dec = Gst.ElementFactory.make("fluh264dec", "dec")
    pipeline.add(dec)
    depay.link(dec)

    sink = Gst.ElementFactory.make("xvimagesink", "sink")
    sink.set_property("sync", False)
    pipeline.add(sink)
    dec.link(sink)


    Gtk.DrawingArea.__init__(self)
    # main drawingarea
    self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
    self.connect("button-press-event", self.drawingarea_methode)

    # get screen size
    screen = Gdk.Screen.get_default()
    screen_size_x = screen.get_width()
    screen_size_y = screen.get_height()

    self.set_size_request(screen_size_x, screen_size_y)

    # This is needed to make the video output in our DrawingArea:
    bus_camera.enable_sync_message_emission()
    bus_camera.connect('message', self.on_message_Camera)
    bus_camera.connect('sync-message::element', self.on_sync_message_Camera)

    self.source = source
    self.depay = depay
    self.pipeline = pipeline


def on_pad(self, rtspsrc, pad):
    depaySinkPad = self.depay.get_static_pad('sink')
    pad.link(depaySinkPad)

# clicked event onto drawingarea results in hiding the buttons
def drawingarea_methode(self, widget, event):
    #print "Mouse clicked... at ", event.x, ", ", event.y
    self.callback(self.type[-1])

def on_eos_Camera(self, bus, msg):
    self.player_camera.seek_simple(
        Gst.Format.TIME,
        Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
        0
    )

def on_error_Camera(self, bus, msg):
    print('on_error():', msg.parse_error())

def on_message_Camera(self, bus, message):
    t = message.type
    #print(t)

def on_sync_message_Camera(self, bus, msg):
    if msg.get_structure().get_name() == 'prepare-window-handle':
        msg.src.set_window_handle(self.xid_Camera)

I´ve done nearly the same and created a class for it in Gtk3. Hope it helps.

class Camera(Gtk.DrawingArea):
def __init__(self, type, filepath, ui_table, callback):
    self.ui_table = ui_table
    self.type = type
    self.callback = callback

    # create GStreamer pipeline
    pipeline = Gst.Pipeline()

    # create bus to get events from GStreamer pipeline
    bus_camera = pipeline.get_bus()
    bus_camera.add_signal_watch()
    bus_camera.connect('message::eos', self.on_eos_Camera)
    bus_camera.connect('message::error', self.on_error_Camera)


    source = Gst.ElementFactory.make("rtspsrc", "source")
    source.set_property("location", filepath)
    source.set_property("latency", 0)
    source.connect("pad-added", self.on_pad)
    pipeline.add(source)

    depay = Gst.ElementFactory.make("rtph264depay", "depay")
    pipeline.add(depay)
    source.link(depay)

    dec = Gst.ElementFactory.make("fluh264dec", "dec")
    pipeline.add(dec)
    depay.link(dec)

    sink = Gst.ElementFactory.make("xvimagesink", "sink")
    sink.set_property("sync", False)
    pipeline.add(sink)
    dec.link(sink)


    Gtk.DrawingArea.__init__(self)
    # main drawingarea
    self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
    self.connect("button-press-event", self.drawingarea_methode)

    # get screen size
    screen = Gdk.Screen.get_default()
    screen_size_x = screen.get_width()
    screen_size_y = screen.get_height()

    self.set_size_request(screen_size_x, screen_size_y)

    # This is needed to make the video output in our DrawingArea:
    bus_camera.enable_sync_message_emission()
    bus_camera.connect('message', self.on_message_Camera)
    bus_camera.connect('sync-message::element', self.on_sync_message_Camera)

    self.source = source
    self.depay = depay
    self.pipeline = pipeline


def on_pad(self, rtspsrc, pad):
    depaySinkPad = self.depay.get_static_pad('sink')
    pad.link(depaySinkPad)

# clicked event onto drawingarea results in hiding the buttons
def drawingarea_methode(self, widget, event):
    #print "Mouse clicked... at ", event.x, ", ", event.y
    self.callback(self.type[-1])

def on_eos_Camera(self, bus, msg):
    self.player_camera.seek_simple(
        Gst.Format.TIME,
        Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
        0
    )

def on_error_Camera(self, bus, msg):
    print('on_error():', msg.parse_error())

def on_message_Camera(self, bus, message):
    t = message.type
    #print(t)

def on_sync_message_Camera(self, bus, msg):
    if msg.get_structure().get_name() == 'prepare-window-handle':
        msg.src.set_window_handle(self.xid_Camera)
神妖 2024-11-23 13:23:17

Tristan 在他的博客上有一篇关于嵌入视频和全屏视频的好文章
http://tristanswork.blogspot.com/2008 /09/fullscreen-video-in-gstreamer-with-gtk.html

Tristan 的更新示例在这里:
http://code.sat.qc.ca /miville/inhouse/prototypes/gstreamer/cpp/fullscreen/test.c

#include <gst/gst.h>
#include <gtk/gtk.h>
#include <gst/interfaces/xoverlay.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>


gboolean handleBusMsg(GstMessage * message, GtkWidget *window)
{
    // ignore anything but 'prepare-xwindow-id' element messages
    if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
    return FALSE;

    if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
    return FALSE;

    g_print("Got prepare-xwindow-id msg\n");
    // FIXME: see https://bugzilla.gnome.org/show_bug.cgi?id=599885
    gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), GDK_WINDOW_XWINDOW(window->window));

    return TRUE;
}

gboolean bus_call(GstBus * bus, GstMessage *msg, gpointer data)
{
    GtkWidget *window = (GtkWidget*) data;
    switch(GST_MESSAGE_TYPE(msg))
    {
    case GST_MESSAGE_ELEMENT:
        {
            handleBusMsg(msg, window);
            break;
        }

    default:
        break;
    }

    return TRUE;
}

static void makeWindowBlack(GtkWidget * window)
{
    GdkColor color;
    gdk_color_parse ("black", &color);
    gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);    // needed to ensure black background
}


static gboolean
key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
    if (event->keyval != 'f')
    return TRUE;
    else 
    g_print("you hit f\n");

    gboolean isFullscreen = (gdk_window_get_state(GDK_WINDOW(widget->window)) == GDK_WINDOW_STATE_FULLSCREEN);

    if (isFullscreen) 
    gtk_window_unfullscreen(GTK_WINDOW(widget));
    else
    gtk_window_fullscreen(GTK_WINDOW(widget));

    return TRUE;
}

void destroy_cb(GtkWidget * widget, gpointer data)
{
    GMainLoop *loop = (GMainLoop*) data;
    g_print("Window destroyed\n");
    g_main_loop_quit(loop);
}


gint main (gint argc, gchar *argv[])
{
    GstStateChangeReturn ret;
    GstElement *pipeline, *src, *sink;
    GMainLoop *loop;
    GtkWidget *window;

    /* initialization */
    gst_init (&argc, &argv);
    gtk_init (&argc, &argv);

    loop = g_main_loop_new (NULL, FALSE);

    // build window and attach expose event to expose callback
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    /* create elements */
    pipeline = gst_pipeline_new ("my_pipeline");
    gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline)), 
            (GstBusFunc)bus_call, window);

    src = gst_element_factory_make ("videotestsrc", NULL);

    sink = gst_element_factory_make("xvimagesink", "videosink");

    if (!sink)
    g_print ("output could not be found - check your install\n");

    gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
    g_object_set(G_OBJECT(sink), "force-aspect-ratio", TRUE, NULL);

    /* link everything together */
    if (!gst_element_link(src, sink)) {
    g_print ("Failed to link one or more elements!\n");
    return -1;
    }

    // attach key press signal to key press callback
    gtk_widget_set_events(window, GDK_KEY_PRESS_MASK);
    g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press_event_cb), sink);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy_cb), loop);

    /* run */
    makeWindowBlack(window);
    gtk_widget_show_all(window);

    ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);

    if (ret == GST_STATE_CHANGE_FAILURE) 
    {
    g_print ("Failed to start up pipeline!\n");
    return 1;
    }

    g_main_loop_run (loop);

    /* clean up */
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);

    return 0;
}

Tristan has a nice article on his blog for embedding video and full screen video
http://tristanswork.blogspot.com/2008/09/fullscreen-video-in-gstreamer-with-gtk.html

Tristan's updated example is here:
http://code.sat.qc.ca/miville/inhouse/prototypes/gstreamer/cpp/fullscreen/test.c

#include <gst/gst.h>
#include <gtk/gtk.h>
#include <gst/interfaces/xoverlay.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>


gboolean handleBusMsg(GstMessage * message, GtkWidget *window)
{
    // ignore anything but 'prepare-xwindow-id' element messages
    if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
    return FALSE;

    if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
    return FALSE;

    g_print("Got prepare-xwindow-id msg\n");
    // FIXME: see https://bugzilla.gnome.org/show_bug.cgi?id=599885
    gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), GDK_WINDOW_XWINDOW(window->window));

    return TRUE;
}

gboolean bus_call(GstBus * bus, GstMessage *msg, gpointer data)
{
    GtkWidget *window = (GtkWidget*) data;
    switch(GST_MESSAGE_TYPE(msg))
    {
    case GST_MESSAGE_ELEMENT:
        {
            handleBusMsg(msg, window);
            break;
        }

    default:
        break;
    }

    return TRUE;
}

static void makeWindowBlack(GtkWidget * window)
{
    GdkColor color;
    gdk_color_parse ("black", &color);
    gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);    // needed to ensure black background
}


static gboolean
key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
    if (event->keyval != 'f')
    return TRUE;
    else 
    g_print("you hit f\n");

    gboolean isFullscreen = (gdk_window_get_state(GDK_WINDOW(widget->window)) == GDK_WINDOW_STATE_FULLSCREEN);

    if (isFullscreen) 
    gtk_window_unfullscreen(GTK_WINDOW(widget));
    else
    gtk_window_fullscreen(GTK_WINDOW(widget));

    return TRUE;
}

void destroy_cb(GtkWidget * widget, gpointer data)
{
    GMainLoop *loop = (GMainLoop*) data;
    g_print("Window destroyed\n");
    g_main_loop_quit(loop);
}


gint main (gint argc, gchar *argv[])
{
    GstStateChangeReturn ret;
    GstElement *pipeline, *src, *sink;
    GMainLoop *loop;
    GtkWidget *window;

    /* initialization */
    gst_init (&argc, &argv);
    gtk_init (&argc, &argv);

    loop = g_main_loop_new (NULL, FALSE);

    // build window and attach expose event to expose callback
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    /* create elements */
    pipeline = gst_pipeline_new ("my_pipeline");
    gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline)), 
            (GstBusFunc)bus_call, window);

    src = gst_element_factory_make ("videotestsrc", NULL);

    sink = gst_element_factory_make("xvimagesink", "videosink");

    if (!sink)
    g_print ("output could not be found - check your install\n");

    gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
    g_object_set(G_OBJECT(sink), "force-aspect-ratio", TRUE, NULL);

    /* link everything together */
    if (!gst_element_link(src, sink)) {
    g_print ("Failed to link one or more elements!\n");
    return -1;
    }

    // attach key press signal to key press callback
    gtk_widget_set_events(window, GDK_KEY_PRESS_MASK);
    g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press_event_cb), sink);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy_cb), loop);

    /* run */
    makeWindowBlack(window);
    gtk_widget_show_all(window);

    ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);

    if (ret == GST_STATE_CHANGE_FAILURE) 
    {
    g_print ("Failed to start up pipeline!\n");
    return 1;
    }

    g_main_loop_run (loop);

    /* clean up */
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文