我正在使用 PyQt 并尝试从网络摄像头获取视频以在 QT 小部件中播放。我已经找到了 C 和 Qt 的教程,以及 python 和 gtk 的教程,但是对于这个 pyQt 和 gstreamer 的组合没有任何教程。有人让这个工作吗?
这可以很好地播放视频,但在一个单独的窗口中:
self.gcam = gst.parse_launch('v4l2src device=/dev/video0 ! autovideosink')
self.gcam.set_state(gst.STATE_PLAYING)
我需要的是让叠加层正常工作,以便它显示在我的 GUI 上的一个小部件中。谢谢,互联网大师!
好的,我已经取得了很大进展,但仍然需要一些帮助。我实际上是为 Maemo 编写的,但以下代码在我的 Linux 笔记本电脑上运行良好:
class Vid:
def __init__(self, windowId):
self.player = gst.Pipeline("player")
self.source = gst.element_factory_make("v4l2src", "vsource")
self.sink = gst.element_factory_make("autovideosink", "outsink")
self.source.set_property("device", "/dev/video0")
self.scaler = gst.element_factory_make("videoscale", "vscale")
self.window_id = None
self.windowId = windowId
self.player.add(self.source, self.scaler, self.sink)
gst.element_link_many(self.source,self.scaler, self.sink)
bus = self.player.get_bus()
bus.add_signal_watch()
bus.enable_sync_message_emission()
bus.connect("message", self.on_message)
bus.connect("sync-message::element", self.on_sync_message)
def on_message(self, bus, message):
t = message.type
if t == gst.MESSAGE_EOS:
self.player.set_state(gst.STATE_NULL)
elif t == gst.MESSAGE_ERROR:
err, debug = message.parse_error()
print "Error: %s" % err, debug
self.player.set_state(gst.STATE_NULL)
def on_sync_message(self, bus, message):
if message.structure is None:
return
message_name = message.structure.get_name()
if message_name == "prepare-xwindow-id":
win_id = self.windowId
assert win_id
imagesink = message.src
imagesink.set_property("force-aspect-ratio", True)
imagesink.set_xwindow_id(win_id)
def startPrev(self):
self.player.set_state(gst.STATE_PLAYING)
print "should be playing"
vidStream = Vid(wId)
vidStream.startPrev()
其中 wId 是我试图在其中显示输出的小部件的窗口 ID。当我在 N900 上运行它时,屏幕变黑并闪烁。有任何想法吗?我快死在这里了!
编辑:我被要求发布完整的代码,虽然我仍然需要稍微清理一下,但这里是相关部分:
self.cameraWindow = QtGui.QWidget(self)
self.cameraWindow.setGeometry(QtCore.QRect(530, 20, 256, 192))
self.cameraWindow.setObjectName("cameraWindow")
self.cameraWindow.setAttribute(0, 1); # AA_ImmediateWidgetCreation == 0
self.cameraWindow.setAttribute(3, 1); # AA_NativeWindow == 3
global wId
wId = self.cameraWindow.winId()
self.camera = Vid(wId)
self.camera.startPrev()
class Vid:
def __init__(self, windowId):
self.player = gst.Pipeline("player")
self.source = gst.element_factory_make("v4l2src", "vsource")
self.sink = gst.element_factory_make("autovideosink", "outsink")
self.source.set_property("device", "/dev/video0")
#self.scaler = gst.element_factory_make("videoscale", "vscale")
self.fvidscale = gst.element_factory_make("videoscale", "fvidscale")
self.fvidscale_cap = gst.element_factory_make("capsfilter", "fvidscale_cap")
self.fvidscale_cap.set_property('caps', gst.caps_from_string('video/x-raw-yuv, width=256, height=192'))
self.window_id = None
self.windowId = windowId
print windowId
self.player.add(self.source, self.fvidscale, self.fvidscale_cap, self.sink)
gst.element_link_many(self.source,self.fvidscale, self.fvidscale_cap, self.sink)
bus = self.player.get_bus()
bus.add_signal_watch()
bus.enable_sync_message_emission()
bus.connect("message", self.on_message)
bus.connect("sync-message::element", self.on_sync_message)
def on_message(self, bus, message):
t = message.type
if t == gst.MESSAGE_EOS:
self.player.set_state(gst.STATE_NULL)
elif t == gst.MESSAGE_ERROR:
err, debug = message.parse_error()
print "Error: %s" % err, debug
self.player.set_state(gst.STATE_NULL)
def on_sync_message(self, bus, message):
if message.structure is None:
return
message_name = message.structure.get_name()
if message_name == "prepare-xwindow-id":
win_id = self.windowId
assert win_id
imagesink = message.src
imagesink.set_property("force-aspect-ratio", True)
imagesink.set_xwindow_id(win_id)
def startPrev(self):
self.player.set_state(gst.STATE_PLAYING)
def pausePrev(self):
self.player.set_state(gst.STATE_NULL)
这是拼凑的一些内容,我现在无法测试,但也许会对某些人有所帮助。祝你好运!
最佳答案
如果您碰巧在 Linux 以外的平台上使用 PySide 而不是 PyQt,则 winId() 返回一个 PyCObject can't be used directly with native functions or other modules .就我而言,在 Microsoft Windows 上将 GStreamer (pygst) 与 PySide 结合使用时,这会派上用场:
from ctypes import pythonapi, c_void_p, py_object
...
if message_name == 'prepare-xwindow-id':
# convert winId from PyCObject to void pointer
pythonapi.PyCObject_AsVoidPtr.restype = c_void_p
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]
hWnd = pythonapi.PyCObject_AsVoidPtr(self.videoWidget.winId())
# set window handle to video sink
self.videoSink.set_xwindow_id(hWnd)
关于Python + QT + Gstreamer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2398958/