Created
August 2, 2011 13:56
-
-
Save joshdoe/1120231 to your computer and use it in GitHub Desktop.
PySide (Qt) + PyGst (GStreamer) on Microsoft Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
# needed for casting PyCObject to void pointer | |
from ctypes import pythonapi, c_void_p, py_object | |
from PySide.QtCore import * | |
from PySide.QtGui import * | |
import gobject | |
import pygst | |
pygst.require('0.10') | |
import gst | |
class Form(QDialog): | |
def __init__(self, parent=None): | |
super(Form, self).__init__(parent) | |
self.setWindowTitle('PySide+GStreamer on Microsoft Windows') | |
# create widgets and set properties | |
self.videoWidget = QWidget(self) | |
self.videoWidget.setMinimumSize(640, 480) | |
self.numBuffersSpinBox = QSpinBox() | |
self.numBuffersSpinBox.setMinimum(-1) | |
self.numBuffersSpinBox.setValue(-1) | |
self.button = QPushButton('Start') | |
# build layout | |
layout = QVBoxLayout() | |
layout.addWidget(self.videoWidget) | |
layout.addWidget(QLabel('num-buffers')) | |
layout.addWidget(self.numBuffersSpinBox) | |
layout.addWidget(self.button) | |
self.setLayout(layout) | |
# connect signals | |
self.button.clicked.connect(self.on_start_stop) | |
# build pipeline | |
self.pipeline = gst.Pipeline() | |
self.source = gst.element_factory_make('videotestsrc') | |
self.sink = gst.element_factory_make('dshowvideosink') | |
self.pipeline.add(self.source, self.sink) | |
gst.element_link_many(self.source, self.sink) | |
# connect sync-message from gst.Bus | |
self.bus = self.pipeline.get_bus() | |
self.bus.add_signal_watch() | |
self.bus.enable_sync_message_emission() | |
self.bus.connect('sync-message::element', self.on_sync_message) | |
# create timer for checking gst.Bus messages | |
self.timer = QTimer() | |
self.timer.timeout.connect(self.on_timer) | |
# we can't call winId() within the streaming thread (on_sync_message) | |
# so we must do it here | |
winid = self.videoWidget.winId() | |
# convert winId from PyCObject to void pointer (only for PySide on | |
# Windows) | |
pythonapi.PyCObject_AsVoidPtr.restype = c_void_p | |
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object] | |
self.hWnd = pythonapi.PyCObject_AsVoidPtr(self.videoWidget.winId()) | |
def on_start_stop(self): | |
if self.button.text() == 'Stop': | |
self.pipeline.set_state(gst.STATE_NULL) | |
self.button.setText('Start') | |
else: | |
self.source.props.num_buffers = self.numBuffersSpinBox.value() | |
self.pipeline.set_state(gst.STATE_PLAYING) | |
self.button.setText('Stop') | |
self.timer.start(30) | |
def on_sync_message(self, bus, message): | |
if message.structure is None: | |
return | |
if message.structure.get_name() == 'prepare-xwindow-id': | |
# enables video to play in QWidget | |
self.sink.set_xwindow_id(self.hWnd) | |
def on_timer(self): | |
message = self.bus.pop() | |
if message == None: | |
return | |
t = message.type | |
if t == gst.MESSAGE_EOS: | |
self.on_start_stop() | |
elif t == gst.MESSAGE_ERROR: | |
err, debug = message.parse_error() | |
QMessageBox.critical(self, self.tr('Pipeline error'), | |
str(err) + '\n' + debug) | |
self.on_start_stop() | |
if __name__ == '__main__': | |
gobject.threads_init() | |
app = QApplication(sys.argv) | |
form = Form() | |
form.show() | |
sys.exit(app.exec_()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment