Python + QT + Gstreamer
質問
私は PyQt を使用して、Web カメラからビデオを取得して 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)
これはいくつかの部分をつなぎ合わせたもので、今はテストできませんが、もしかしたら誰かの役に立つかもしれません。幸運を!
解決 2
は、それを手に入れました!
:私が私がビデオをポンピングされたウィジェットの解像度に合わせてパイプラインの解像度を強制するために必要な表示されますself.fvidscale_cap = gst.element_factory_make( "capsfilter"、 "fvidscale_cap") self.fvidscale_cap.set_property(gst.caps_from_string 'キャップ'、( 'ビデオ/ X-RAW-YUV、幅= 256、高さ= 192'))
それからちょうど他の要素のようなパイプラインにそれらを追加し、それは素晴らしい作品。男は、それはそう簡単に今それを見ているようだが、私はそれはとても明らかではなかった数日間、壁に頭を叩いたとき...
他のヒント
Linux 以外のプラットフォームで PyQt の代わりに PySide を使用している場合、winId() は PyCObject を返します。 ネイティブ関数や他のモジュールでは直接使用できません. 。私の場合、これは Microsoft Windows 上の PySide で GStreamer (pygst) を使用するときに便利でした。
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)
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を()に渡します。
ロードが、クラッシュを開始ウィジェットます。
出力は述べています。
をプレイする必要があります
セグメンテーションフォールト
貼り付けたコードが却下することができないGObjectの負荷を、表示されません。 欠けていたかを把握する一方、それは私にいいました。 6月を持ってくれてありがとう 作業オーディオ例ます。
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_())