2010-03-08 3 views
6

Я работаю с PyQt и пытаюсь получить видео с веб-камеры, чтобы играть в виджет QT. Я нашел учебники для C и Qt, а также для python и gtk, но НИЧЕГО для этой комбинации pyQt и gstreamer. Кто-нибудь получает эту работу?Python + QT + 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 это окно идентификатор виджета им пытаются получить для вывода в Когда я запускаю это. на N900 экран становится черным и мигает. Есть идеи? Я умираю здесь!

EDIT: Я попросил, чтобы отправить полный код, и хотя мне еще нужно, чтобы очистить его немного, вот соответствующая часть:

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) 

Это склеиванием несколько битов, и Я не могу проверить это прямо сейчас, но, возможно, это будет полезно кому-то. Удачи!

+0

где вы нашли для C++ и QT? im ищет способ потоковой передачи rstp с QT – user63898

+0

Просто выполнив поиск на этом сайте и в google, я нашел информацию для C++ и QT. Также проверьте форумы Maemo.org. Удачи! – Ptterb

ответ

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

Затем просто добавьте их в конвейер, как и другие элементы, и отлично работает , Мужчина, кажется, так легко смотреть на это сейчас, но когда я несколько раз стучал головой о стену, это было не так очевидно ...

1

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 конструктора.
Виджет начинает загрузку, но падает.

Выход говорит:
должен играть
Сегментация неисправностей

+0

Попробуйте новый код, который я только что положил. Дайте мне знать, если у вас все еще есть проблемы! – Ptterb

+0

ZolaKt, вы решили проблему выше? –

+0

@ БернардоКиотоку: Нет, извините. Я отказался от этого проекта, когда Nokia решила пойти в дерьмо и переключиться на Windows – ZolaKt

3

Если вы случается использовать PySide вместо PyQt на платформе, отличной от Linux, WinID() возвращает какой can't be used directly with native functions or other modules в PyCObject. В моем случае это пригодилось при использовании GStreamer (pygst) с PySide на Microsoft Windows:

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

Вставляемый код не показывает 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_())