【问题标题】:Python + QT + GstreamerPython + QT + Gstreamer
【发布时间】:2011-01-24 19:58:14
【问题描述】:

我正在使用 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)

这是拼凑起来的,我现在无法测试它,但也许它会对某人有所帮助。祝你好运!

【问题讨论】:

  • 你在哪里找到 c++ 和 QT 的?我正在寻找使用 QT 流式传输 rstp 的方法
  • 只是搜索这个网站和谷歌我找到了 c++ 和 QT 的信息。另外,请查看 Maemo.org 论坛。祝你好运!
  • 代码中的问题似乎是缩进问题。您的函数 startPrev 和 pausePrev 是空的,就像您发布它们一样

标签: python pyqt4 gstreamer maemo qt-maemo


【解决方案1】:

知道了!看来我需要强制管道的分辨率与我将视频抽到的小部件的分辨率相匹配:

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'))

然后像其他元素一样将它们添加到管道中,效果很好。伙计,现在看起来很容易,但是当我把头撞在墙上几天时,它就不那么明显了......

【讨论】:

    【解决方案2】:

    Ptterb 你能发布你的完整代码吗?

    我复制了你的代码。
    将 fvidscale_cap 添加到管道中,其中:

    self.player.add(self.source, self.scaler, self.fvidscale_cap, self.sink)
    gst.element_link_many(self.source,self.scaler, self.fvidscale_cap, self.sink)
    

    我从主程序创建了一个新的 QWidget,并将其 winId() 传递给 Vid 构造函数。
    小部件开始加载,但崩溃。

    输出显示:
    应该玩
    分段错误

    【讨论】:

    • 试试我刚刚提出的新代码。如果您仍有问题,请告诉我!
    • @BernardoKyotoku:不,抱歉。当诺基亚决定去废话并切换到 Windows 时,我放弃了那个项目
    【解决方案3】:

    如果你碰巧在 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)
    

    【讨论】:

      【解决方案4】:

      粘贴的代码未显示 gobject 加载,无法关闭。 我花了很长时间才弄清楚缺少什么。感谢Jun 拥有 一个有效的音频示例。

      import gobject, pygst
      pygst.require('0.10')
      import gst
      from PyQt4.QtGui import QMainWindow, QWidget, QApplication 
      import sys
      
      class Video(QMainWindow):
          def __init__(self):
              QMainWindow.__init__(self)
              container = QWidget()
              self.setCentralWidget(container)
              self.windowId = container.winId()
              self.setGeometry(300,300,640,480)
              self.show()
      
          def setUpGst(self):
              self.player = gst.Pipeline("player")
              source = gst.element_factory_make("v4l2src", "vsource")
              sink = gst.element_factory_make("xvimagesink", "sink")
              fvidscale_cap = gst.element_factory_make("capsfilter", "fvidscale_cap")
              fvidscale = gst.element_factory_make("videoscale", "fvidscale")
              caps = gst.caps_from_string('video/x-raw-yuv')
              fvidscale_cap.set_property('caps', caps)
              source.set_property("device", "/dev/video0")
      
              self.player.add(source, fvidscale, fvidscale_cap, sink)
              gst.element_link_many(source,fvidscale, fvidscale_cap, 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)
                  print "end of message"
              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_xwindow_id(win_id)
      
          def startPrev(self):
              self.player.set_state(gst.STATE_PLAYING)
              print "should be playing"
      
      if __name__ == "__main__":
          gobject.threads_init()
          app = QApplication(sys.argv)
          video = Video()
          video.setUpGst()
          video.startPrev()
          sys.exit(app.exec_())
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-16
        • 2018-03-26
        • 2021-08-03
        • 2018-06-30
        • 1970-01-01
        • 1970-01-01
        • 2017-06-04
        • 1970-01-01
        相关资源
        最近更新 更多