我开发了一个gtk应用程序,用于从IP摄像机播放RTSP流。
pipeline = gst_parse_launch(“rtspsrc location = rtsp://192.168.127.100:554 / moxa-cgi / udpStreamer latency = 0!decodebin!xvimagesink”,NULL); gst_element_set_state(管道,GST_STATE_PLAYING);
我将此代码粘贴到我的程序中,它工作正常,但另一个窗口。 如何在drawing_area或其他小部件上显示视频?
答案 0 :(得分:0)
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;
}
答案 1 :(得分:0)
我做的几乎一样,并在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)