Python Gstreamer, Webcam, and Pil

Andrey Nechypurenko andreynech at googlemail.com
Sat Aug 24 02:15:24 PDT 2013


On 24 August 2013 10:14, Jason (spot) Brower <encompass at gmail.com> wrote:
> I can take the picture and save the image to a file using just Gstreamer.
> But I need to work with the image before I save it anyway, so how can I
> convert it to PIL after I take the picture.
> A code example would be handy. I have googled and no found it as far as I
> have searched.

One possible way would be to create the pipeline which ends with
fakesink element and use it's handoff mechanism to get access to raw
frame. For example:

videotestsrc is-live=true !
video/x-raw-yuv,width=640,height=480,framerate=30/1 ! ffmpegcolorspace
! video/x-raw-rgb, bpp=32, depth=32 ! fakesink sync=1

The following code illustrates how to update OpenGL texture with it.
Here on_gst_buffer(self, fakesink, buff, pad, data=None) will be
invoked by gstreamer for each new frame and data contains raw decoded
frame in format specified by the caps filter in front of fakesink.

import ctypes

import gobject
import gst

class Receiver(object):

    def __init__(self, video_tex_id, pipeline_string):
        self.tex_updated = True
        self.texdata = (ctypes.c_ubyte * 640 * 480 * 4)()
        self.video_tex_id = video_tex_id

        # Create GStreamer pipeline
        self.pipeline = gst.parse_launch(pipeline_string)

        # Create bus to get events from GStreamer pipeline
        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect('message::eos', self.on_eos)
        self.bus.connect('message::error', self.on_error)

        self.fakesink = self.pipeline.get_by_name('fakesink0')
        self.fakesink.props.signal_handoffs = True
        self.fakesink.connect("handoff", self.on_gst_buffer)

        self.pipeline.set_state(gst.STATE_PLAYING)


    def on_gst_buffer(self, fakesink, buff, pad, data=None):
        self.tex_updated = False
        ctypes.memmove(self.texdata, buff.data, buff.size)
        return gst.FLOW_OK


    def updateTexture(self):
        if not self.tex_updated and not self.texdata == None:
            glBindTexture(GL_TEXTURE_2D, self.video_tex_id)
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 640, 480, GL_RGBA,
GL_UNSIGNED_BYTE, self.texdata)
            self.tex_updated = True


    def on_eos(self, bus, msg):
        print('on_eos(): seeking to start of video')
        self.pipeline.seek_simple(
            gst.FORMAT_TIME,
            gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT,
            0L
        )


    def on_error(self, bus, msg):
        print('on_error():', msg.parse_error())


HTH,
Andrey.


More information about the gstreamer-devel mailing list