我有两个树莓派。并希望将视频从一个流式传输到另一个。为此,我在第一个 Raspberry Pi 上使用了以下命令来流式传输视频:
raspivid -t 999999 -w 1080 -h 720 -fps 25 -hf -b 2000000 -o - | \gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 \! gdppay ! tcpserversink host=serverIp port=5000
在第二个 Raspberry Pi 中,我使用以下 pyqt 代码来捕获流式视频:
import sys
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, GstVideo
GObject.threads_init()
Gst.init(None)
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Create GStreamer pipeline
self.Video_pipeline()
##############################################################################
#VIDEO Pipeline
#|
#|
#V
##############################################################################
def Video_pipeline(self):
self.pipeline = Gst.Pipeline()
self.tcpsrc = Gst.ElementFactory.make('tcpclientsrc','tcpsrc')
self.tcpsrc.set_property("host", '192.168.1.9')
self.tcpsrc.set_property("port", 5000)
self.gdepay = Gst.ElementFactory.make('gdpdepay', 'gdepay')
self.rdepay = Gst.ElementFactory.make('rtph264depay', 'rdepay')
self.avdec = Gst.ElementFactory.make('avdec_h264', 'avdec')
self.vidconvert = Gst.ElementFactory.make('videoconvert', 'vidconvert')
self.asink = Gst.ElementFactory.make('autovideosink', 'asink')
self.asink.set_property('sync', False)
self.pipeline.add(self.tcpsrc)
self.pipeline.add(self.gdepay)
self.pipeline.add(self.avdec)
self.pipeline.add(self.rdepay)
self.pipeline.add(self.vidconvert)
self.pipeline.add(self.asink)
self.tcpsrc.link(self.gdepay)
self.gdepay.link(self.rdepay)
self.rdepay.link(self.avdec)
self.avdec.link(self.vidconvert)
self.vidconvert.link(self.asink)
##############################################################################
#^
#|
#|
#VIDEO Pipeline
##############################################################################
def start(self):
self.pipeline.set_state(Gst.State.PLAYING)
self.pipeline_A.set_state(Gst.State.PLAYING)
#self.showMaximized()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.start()
sys.exit(app.exec_())
它工作得很好。现在我需要设计一个 GUI。我写了这段代码:
import sys
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, GstVideo
GObject.threads_init()
Gst.init(None)
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
#creat Simple Window
container = QtGui.QWidget(self)
container.setWindowTitle('Test1')
container.connect('destroy', self.quit)
self.setCentralWidget(container)
self.winId = container.winId()
self.resize(480, 320)
qbtn = QtGui.QPushButton('Quit', self)
qbtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
# Create GStreamer pipeline
self.Video_pipeline()
# Create bus to get events from GStreamer pipeline
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.enable_sync_message_emission()
self.bus.connect('message::error', self.on_error)
self.bus.connect('message::eos', self.on_eos)
self.bus.connect('sync-message::element', self.on_sync_message)
##############################################################################
#VIDEO Pipeline
#|
#|
#V
##############################################################################
def Video_pipeline(self):
self.pipeline = Gst.Pipeline()
self.tcpsrc = Gst.ElementFactory.make('tcpclientsrc','tcpsrc')
self.tcpsrc.set_property("host", '192.168.1.9')
self.tcpsrc.set_property("port", 5000)
self.gdepay = Gst.ElementFactory.make('gdpdepay', 'gdepay')
self.rdepay = Gst.ElementFactory.make('rtph264depay', 'rdepay')
self.avdec = Gst.ElementFactory.make('avdec_h264', 'avdec')
self.vidconvert = Gst.ElementFactory.make('videoconvert', 'vidconvert')
self.asink = Gst.ElementFactory.make('autovideosink', 'asink')
self.asink.set_property('sync', False)
#self.asink.set_property('emit-signals', True)
#self.set_property('drop', True)
self.pipeline.add(self.tcpsrc)
self.pipeline.add(self.gdepay)
self.pipeline.add(self.avdec)
self.pipeline.add(self.rdepay)
self.pipeline.add(self.vidconvert)
self.pipeline.add(self.asink)
self.tcpsrc.link(self.gdepay)
self.gdepay.link(self.rdepay)
self.rdepay.link(self.avdec)
self.avdec.link(self.vidconvert)
self.vidconvert.link(self.asink)
##############################################################################
#^
#|
#|
#VIDEO Pipeline
##############################################################################
def on_sync_message(self, bus, message):
if message.get_structure().get_name() == 'prepare-window-handle':
message.src.set_property('force-aspect-ratio', True)
message.src.set_window_handle(self.winId)
def quit(self, container):
self.pipeline.set_state(Gst.State.NULL)
self.pipeline_A.set_state(Gst.State.NULL)
Gtk.main_quit()
def on_eos(self, bus, msg):
print('on_eos(): seeking to start of video')
self.pipeline.seek_simple(
Gst.Format.TIME,
Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
0
)
def on_error(self, bus, msg):
print('on_error():', msg.parse_error())
def start(self):
self.pipeline.set_state(Gst.State.PLAYING)
self.pipeline_A.set_state(Gst.State.PLAYING)
self.showMaximized()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
window.start()
sys.exit(app.exec_())
这段代码在我的 ubuntu 系统中运行良好。它显示了流式视频和一个按钮。但是当我在 Raspberry Pi 上运行此代码时,会显示一个窗口片刻,然后它就消失了。
我在 Ubunu 上收到以下警告:
(DO2.py:7495): GStreamer-WARNING **: gstpad.c:4506:store_sticky_event: 粘性事件排序错误,在“caps”之前得到“segment”
(DO2.py:7495): GStreamer-WARNING **: gstpad.c:4506:store_sticky_event: 粘性事件排序错误,在“caps”之前得到“segment”
这些在覆盆子上:
qgtkstyle 无法检测到当前的 gtk (DO2.py:7495):
GStreamer-WARNING **:gstpad.c:4506:store_sticky_event:粘性事件排序错误,在“caps”之前得到“segment”
(DO2.py:7495): GStreamer-WARNING **: gstpad.c:4506:store_sticky_event: 粘性事件排序错误,在“caps”分段错误之前得到“段”
请帮助我解决问题或指导我如何设计一个在 Raspberry 中工作的 GUI。多谢