Python + QT + Gstreamer

gstreamer, maemo, pyqt4, python, qt-maemo

Solution

Got it! It appears I needed to force the resolution of the pipeline to match the resolution of the widget where I was pumping the video to:

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

Then just add those to the pipeline like the other elements, and it works great. Man, it seems so easy looking at it now, but when I was pounding my head against the wall for a few days it wasn't so obvious...

Problem

I'm working with PyQt and trying to get video from a webcam to play within a QT widget. I've found tutorials for C and Qt, and for python and gtk, but NOTHING for this combo of pyQt and gstreamer. Anybody get this working? This plays the video fine, but in a separate window: ``` self.gcam = gst.parse_launch('v4l2src device=/dev/video0 ! autovideosink') self.gcam.set_state(gst.STATE_PLAYING) ``` what I need is to get the overlay working so it's displayed within a widget on my GUI. Thanks, Gurus of the internet! ok, so I've gotten a lot farther, but still in need of some help. I'm actually writing this for Maemo, but the following code works fine on my linux laptop: ``` 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() ``` where wId is the window id of the widget im trying to get to display the output in. When I run this on the N900, the screen goes black and blinks. Any ideas? I'm dying here! EDIT: I've been asked to post the full code, and though I still need to clean it up a bit, here's the relevant part: ``` 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) ``` This is piecing together a few bits, and I can't test it right now, but maybe it will be helpful to someone. Good luck!

Original source