gstreamer视频进入python中的窗口
Posted
技术标签:
【中文标题】gstreamer视频进入python中的窗口【英文标题】:gstreamer video into a window in python 【发布时间】:2016-02-05 14:11:29 【问题描述】:我有以下管道来流式传输视频:
发件人:
gst-launch-1.0 rpicamsrc 预览=0 ! '视频/x-h264,宽度=1280,高度=720,帧率=15/1,配置文件=高'!队列 ! rtph264pay! udpsink 主机=192.168.0.8 端口=50000
接收者:
gst-launch-1.0 udpsrc port=50000 caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264" ! rtph264depay!解码器!自动视频接收器
这很好用,但我想在 python 中做接收器,并将视频流引导到一个窗口中,就像这样:
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst, Gtk, GdkX11,GstVideo
GObject.threads_init()
Gst.init(None)
class VideoReceiver:
def __init__(self):
self.window = Gtk.Window()
self.window.connect('destroy', self.stop)
self.window.set_default_size(320, 200)
self.drawingarea = Gtk.DrawingArea()
self.window.add(self.drawingarea)
self.window.show_all()
self.xid = self.drawingarea.get_property('window').get_xid()
self.pipeline = Gst.parse_launch ('udpsrc name=udpsrc port=50000'
' caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264" ! '
'rtph264depay ! decodebin ! autovideosink')
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message::error', self.on_error)
self.bus.enable_sync_message_emission()
self.bus.connect('sync-message::element', self.on_sync_message)
def start(self):
self.pipeline.set_state(Gst.State.PLAYING)
Gtk.main()
def stop(self, window):
self.pipeline.set_state(Gst.State.NULL)
Gtk.main_quit()
def on_sync_message(self, bus, msg):
if msg.get_structure().get_name() == 'prepare-window-handle':
print('prepare-window-handle')
msg.src.set_property('force-aspect-ratio', True)
msg.src.set_window_handle(self.xid)
def on_error(self, bus, msg):
print('on_error():', msg.parse_error())
vr1=VideoReceiver()
vr1.start()
但是当流媒体开始时,窗口只是简单地关闭,程序结束时没有错误。 有什么想法可能是错误的,我如何将视频输出定向到窗口中?
如果在没有 root 权限的情况下运行时输出:
$ GST_DEBUG=3 python3.2 test.py
** (test.py:3275): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
prepare-window-handle
0:00:04.134038733 3275 0x1c72260 ERROR egladaption gstegladaptation_egl.c:311:gst_egl_adaptation_create_surface:<autovideosink0-actual-sink-eglgles> Can't create surface
0:00:04.135032949 3275 0x1c72260 ERROR egladaption gstegladaptation.c:461:gst_egl_adaptation_init_surface:<autovideosink0-actual-sink-eglgles> Can't create surface
0:00:04.135378104 3275 0x1c72260 ERROR egladaption gstegladaptation.c:657:gst_egl_adaptation_init_surface:<autovideosink0-actual-sink-eglgles> Couldn't setup EGL surface
0:00:04.135678780 3275 0x1c72260 ERROR eglglessink gsteglglessink.c:2132:gst_eglglessink_configure_caps:<autovideosink0-actual-sink-eglgles> Couldn't init EGL surface from window
0:00:04.135971436 3275 0x1c72260 ERROR eglglessink gsteglglessink.c:2144:gst_eglglessink_configure_caps:<autovideosink0-actual-sink-eglgles> Configuring caps failed
0:00:04.137130443 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.137830336 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.138175544 3275 0x1c78a60 WARN GST_PADS gstpad.c:3620:gst_pad_peer_query:<sink:proxypad1> could not send sticky events
0:00:04.157868139 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.158217826 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.158321940 3275 0x1c78a60 WARN GST_PADS gstpad.c:3620:gst_pad_peer_query:<sink:proxypad1> could not send sticky events
0:00:04.184023215 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.184216600 3275 0x1c78a60 WARN GST_PADS gstpad.c:3620:gst_pad_peer_query:<sink:proxypad1> could not send sticky events
0:00:04.185187274 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.185499825 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.186118000 3275 0x1c78a60 WARN omxvideodec gstomxvideodec.c:2817:gst_omx_video_dec_loop:<omxh264dec-omxh264dec0> error: Internal data stream error.
0:00:04.186551488 3275 0x1c78a60 WARN omxvideodec gstomxvideodec.c:2817:gst_omx_video_dec_loop:<omxh264dec-omxh264dec0> error: stream stopped, reason not-negotiated
0:00:04.187462163 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
0:00:04.187758151 3275 0x1c78a60 ERROR eglglessink gsteglglessink.c:2167:gst_eglglessink_setcaps:<autovideosink0-actual-sink-eglgles> Failed to configure caps
on_error(): (GError('Internal data stream error.',), 'gstomxvideodec.c(2817): gst_omx_video_dec_loop (): /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstOMXH264Dec-omxh264dec:omxh264dec-omxh264dec0:\nstream stopped, reason not-negotiated'
作为根输出:
GST_DEBUG=3 sudo python3.2 test.py
** (test.py:3205): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
prepare-window-handle
所以 Gstreamer 没有错误,窗口在流启动时简单地关闭。
【问题讨论】:
使用 GST_DEBUG=3 运行 python 接收器并检查警告/错误.. 但是您是否在第二行之后没有错过 parse_launch 中的 + 号 - 大写...? 不,它适用于 + 和没有,但我更正了代码以使其保持一致。不幸的是,Gstreamer 没有警告或错误消息,窗口只是关闭,程序在流启动时结束。 如果我在没有 sudo 的情况下运行程序,那么我确实有错误消息,但是当我以 root 身份运行时,窗口只会关闭。我会在这两种情况下发布确切的输出。 @otopolsky:有什么想法可能有什么问题吗? 我不确定.. sudo 的事情可能是由于未传播 GST_DEBUG(或某些权限?).. 什么是操作系统?也许逃避双引号?尝试在变量中准备管道字符串并打印它以查看它的外观.. 也使用 ximagesink 而不是 auto.. 这是一些不错的tutorial - 第 3.2 章是你想要的.. 【参考方案1】:我没有将 gtk 用于此目的,仅 wxpython 所以只是一些想法。 尝试更改:
self.bus.connect('message::error', self.on_error)
到
self.bus.connect('message', self.on_error)
然后从那里的消息中挑选骨头,即
t = message.type
if t == Gst.MessageType.ERROR:
error_0 = Gst.Message.parse_error (message)[0]
error_1 = Gst.Message.parse_error (message)[1]
report errors here.......
elif t == Gst.MessageType.EOS:
print ("End of Audio")
return True
来自 on_error 和 on_sync_message 总是return True
最后,
尝试在窗口而非绘图区域触发set_window_handle
。
【讨论】:
以上是关于gstreamer视频进入python中的窗口的主要内容,如果未能解决你的问题,请参考以下文章
Python中的Gstreamer立即退出,但在命令行上很好