【问题标题】:RTSP video in gtk-applicationgtk 应用程序中的 RTSP 视频
【发布时间】:2017-03-13 17:52:30
【问题描述】:

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

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

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

【问题讨论】:

    标签: gtk rtsp gstreamer


    【解决方案1】:

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

    特里斯坦的更新示例在这里: 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;
    }
    

    【讨论】:

      【解决方案2】:

      我做了几乎相同的工作,并在 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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-14
        • 2012-09-15
        • 1970-01-01
        • 2012-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多