class NewsegmentEater(gst.BaseTransform): __gstdetails__ = ( "Description", "Klass", "Description", "Author") sink_template = gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.Caps('ANY')) src_template = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.Caps('ANY')) __gsttemplates__ = (sink_template, src_template) def __init__(self): gst.BaseTransform.__init__(self) def do_event(self, event): res = gst.BaseTransform.do_event(self, event) if event.type == gst.EVENT_NEWSEGMENT: # don't forward the event downstream return False return res
class FixSeekStart(gst.BaseTransform): __gstdetails__ = ("Description", "Klass", "Description", "Author") sink_template = gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.Caps('ANY')) src_template = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.Caps('ANY')) __gsttemplates__ = (sink_template, src_template) def __init__(self, track): gst.BaseTransform.__init__(self) self.track = track def do_src_event(self, event): if event.type == gst.EVENT_SEEK: rate, format, flags, cur_type, cur, stop_type, stop = \ event.parse_seek() if cur_type == gst.SEEK_TYPE_SET and cur >= self.track.duration: cur = self.track.duration - 1 * gst.NSECOND new_event = gst.event_new_seek(rate, format, flags, cur_type, cur, stop_type, stop) event = new_event return gst.BaseTransform.do_src_event(self, event)
class NoDataBinUnlinker(gst.Element): #source pad (template): we send buffers forward through here _srctemplate = gst.PadTemplate ('src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) #sink pad (template): we recieve buffers from our sink pad _sinktemplate = gst.PadTemplate ('sink', gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) #register our pad templates __gsttemplates__ = (_srctemplate, _sinktemplate) def __init__(self, unlink, tolerance=1): #initialise parent class gst.Element.__init__(self) self.datawatcher = DataWatcher(unlink, tolerance) self.playing = False #source pad, outgoing data self.srcpad = gst.Pad(self._srctemplate) #sink pad, incoming data self.sinkpad = gst.Pad(self._sinktemplate) self.sinkpad.set_setcaps_function(self._sink_setcaps) self.sinkpad.set_chain_function(self._sink_chain) #make pads available self.add_pad(self.srcpad) self.add_pad(self.sinkpad) def _sink_setcaps(self, pad, caps): #we negotiate our capabilities here, this function is called #as autovideosink accepts anything, we just say yes we can handle the #incoming data return True def _sink_chain(self, pad, buf): #this is where we do filtering #and then push a buffer to the next element, returning a value saying # it was either successful or not. if not self.playing: self.playing = True self.datawatcher.start() secs = float(buf.duration) / gst.SECOND # print "NEW BUFFER "+str(secs) if (len(buf)>0): self.datawatcher.touch(secs) return self.srcpad.push(buf)
class EOSSir(gst.Element): __gstdetails__ = ("EOSSir", "Generic", "pushes EOS after the first buffer", "Alessandro Decina <*****@*****.**>") srctemplate = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.Caps("ANY")) sinktemplate = gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.Caps("ANY")) __gsttemplates__ = (srctemplate, sinktemplate) def __init__(self): gst.Element.__init__(self) self.sinkpad = gst.Pad(self.sinktemplate, "sink") self.sinkpad.set_chain_function(self.chain) self.add_pad(self.sinkpad) self.srcpad = gst.Pad(self.srctemplate, "src") self.add_pad(self.srcpad) def chain(self, pad, buf): ret = self.srcpad.push(buf) if ret == gst.FLOW_OK: self.info("pushed, doing EOS") self.srcpad.push_event(gst.event_new_eos()) return ret
def testNewDecodedPadNotFixed(self): video_template = gst.PadTemplate( 'video_00', gst.PAD_SRC, gst.PAD_ALWAYS, gst.Caps('video/x-raw-rgb, ' 'framerate=[0/1, %d/1]' % ((2**31) - 1))) audio_template = gst.PadTemplate( 'audio_00', gst.PAD_SRC, gst.PAD_ALWAYS, gst.Caps('audio/x-raw-int, ' 'rate=[1, %d]' % ((2**31) - 1))) video = gst.Pad(video_template) audio = gst.Pad(audio_template) video_ghost = gst.GhostPad("video", video) audio_ghost = gst.GhostPad("audio", audio) self.failUnlessEqual(self.discoverer.current_streams, []) self.discoverer._newDecodedPadCb(None, video_ghost, False) self.failUnlessEqual(len(self.discoverer.current_streams), 0) self.failUnlessEqual(self.discoverer.new_video_pad_cb, 1) self.discoverer._newDecodedPadCb(None, audio_ghost, False) self.failUnlessEqual(len(self.discoverer.current_streams), 0) self.failUnlessEqual(self.discoverer.new_video_pad_cb, 1) # fix the caps video.set_caps(gst.Caps('video/x-raw-rgb, framerate=25/1')) self.failUnlessEqual(len(self.discoverer.current_streams), 1) self.failUnlessEqual(self.discoverer.new_video_pad_cb, 1) audio.set_caps(gst.Caps('audio/x-raw-int, rate=44100')) self.failUnlessEqual(len(self.discoverer.current_streams), 2) self.failUnlessEqual(self.discoverer.new_video_pad_cb, 1)
class NewElement(gst.Element): """ A basic, buffer forwarding gstreamer element """ #here we register our plugin details __gstdetails__ = ( "NewElement plugin", "newelement.py", "gst.Element, that passes a buffer from source to sink (a filter)", "Stephen Griffiths <*****@*****.**>") #source pad (template): we send buffers forward through here _srctemplate = gst.PadTemplate ('src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) #sink pad (template): we recieve buffers from our sink pad _sinktemplate = gst.PadTemplate ('sink', gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) #register our pad templates __gsttemplates__ = (_srctemplate, _sinktemplate) def __init__(self, *args, **kwargs): print 'sinit' #initialise parent class gst.Element.__init__(self, *args, **kwargs) #source pad, outgoing data self.srcpad = gst.Pad(self._srctemplate) #sink pad, incoming data self.sinkpad = gst.Pad(self._sinktemplate) self.sinkpad.set_setcaps_function(self._sink_setcaps) self.sinkpad.set_chain_function(self._sink_chain) #make pads available self.add_pad(self.srcpad) self.add_pad(self.sinkpad) print 'einit' def _sink_setcaps(self, pad, caps): #we negotiate our capabilities here, this function is called #as autovideosink accepts anything, we just say yes we can handle the #incoming data print 'setcaps' return True def _sink_chain(self, pad, buf): #this is where we do filtering #and then push a buffer to the next element, returning a value saying # it was either successful or not. print 'schain' ret = self.srcpad.push(buf) print 'echain' return ret
class LapseElement(gst.Element): _srcpadtemplate = gst.PadTemplate("srcpadtemplate", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) _sinkpadtemplate = gst.PadTemplate("sinkpadtemplate", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) def info(self, m): print m def __init__(self): gst.Element.__init__(self) gst.info('creating pads') self.srcpad = gst.Pad(self._srcpadtemplate, "src") self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") gst.info('adding pads to self') self.add_pad(self.srcpad) self.add_pad(self.sinkpad) gst.info('setting chain/event functions') #self.srcpad.set_chain_function(self.src_chainfunc) #self.srcpad.set_event_function(self.src_eventfunc) self.sinkpad.set_chain_function(self.sink_chainfunc) self.sinkpad.set_event_function(self.sink_eventfunc) self.time_cb = None self.interval = 60 self._calc_next() def _calc_next(self): """Given the configured interval, calculate when the next frame should be added to the output""" d = self.interval self.next = d + int(time.time() / d) * d def set_property(self, name, value): if name == "interval": self.interval = value self._calc_next() elif name == "time_cb": self.time_cb = value def sink_chainfunc(self, pad, buffer): #self.info("%s timestamp(buffer):%d" % (pad, buffer.timestamp)) self.time_cb and self.time_cb(time.ctime(self.next)) if time.time() > self.next: self._calc_next() self.srcpad.push(buffer) self.info("pushed buffer at " + time.ctime()) return gst.FLOW_OK def sink_eventfunc(self, pad, event): self.info("%s event:%r" % (pad, event.type)) self.srcpad.push_event(event) return True
class ResizeSink(gst.Element): # Above didn't have this but seems its not optional __gstdetails__ = ('ResizeSink','Sink', \ 'Resize source to get around X11 memory limitations', 'John McMaster') _sinkpadtemplate = gst.PadTemplate ("sinkpadtemplate", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) _srcpadtemplate = gst.PadTemplate ("srcpadtemplate", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) def __init__(self): gst.Element.__init__(self) self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") self.srcpad = gst.Pad(self._srcpadtemplate, "src") self.add_pad(self.sinkpad) self.add_pad(self.srcpad) self.sinkpad.set_chain_function(self.chainfunc) self.sinkpad.set_event_function(self.eventfunc) def chainfunc(self, pad, buffer): try: print 'Got resize buffer' # Simplest: just propagate the data # self.srcpad.push(buffer) # Import into PIL and downsize it # Raw jpeg to pr0n PIL wrapper object print 'resize chain', len(buffer.data), len(buffer.data) / 3264.0 #open('temp.jpg', 'w').write(buffer.data) #io = StringIO.StringIO(buffer.data) io = StringIO.StringIO(str(buffer)) try: image = Image.open(io) except: print 'failed to create image' return gst.FLOW_OK # Use a fast filter since this is realtime image = get_scaled(image, 0.5, Image.NEAREST) output = StringIO.StringIO() image.save(output, 'jpeg') self.srcpad.push(gst.Buffer(output.getvalue())) except: traceback.print_exc() os._exit(1) return gst.FLOW_OK def eventfunc(self, pad, event): return True
class Equalizer(gst.Element): _sinkpadtemplate = gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.Caps("audio/x-raw-spectrum")) _srcpadtemplate = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.Caps("audio/x-raw-spectrum")) __gstdetails__ = ("spectrum_equalizer", "Audio/Filter", "equalizer that deals with spectrum data", "Leberwurscht") __gproperties__ = { "transmission": (gobject.TYPE_PYOBJECT, "transmission", "transmission for each spectral band", gobject.PARAM_READWRITE) } def __init__(self, *args, **kwargs): self.frequencies = Math.get_frq(2049, 44100) self.transmission = None gst.Element.__init__(self, *args, **kwargs) if not self.transmission: self.transmission = numpy.ones(2049) self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") self.sinkpad.use_fixed_caps() self.srcpad = gst.Pad(self._srcpadtemplate, "src") self.srcpad.use_fixed_caps() self.sinkpad.set_chain_function(self.chainfunc) self.sinkpad.set_event_function(self.eventfunc) self.add_pad(self.sinkpad) self.srcpad.set_event_function(self.srceventfunc) self.add_pad(self.srcpad) # custom property def do_get_property(self, pspec): return getattr(self, pspec.name) def do_set_property(self, pspec, value): setattr(self, pspec.name, value) def chainfunc(self, pad, buffer): gst.log("Passing buffer with ts %d" % (buffer.timestamp)) fft = numpy.frombuffer(buffer, numpy.complex128) fft = fft * self.transmission b = gst.Buffer(fft) b.set_caps(self.srcpad.get_caps()) b.timestamp = buffer.timestamp return self.srcpad.push(b) def eventfunc(self, pad, event): return self.srcpad.push_event(event) def srceventfunc(self, pad, event): return self.sinkpad.push_event(event)
class AudioResyncer(gst.Element): ''' I retimestamp incomming buffers adding a fixed delay. ''' __gproperties__ = { 'delay': (float, 'delay (in ms)', 'Resynchronisation delay in milliseconds', -1000000, 1000000, 0, gobject.PARAM_READWRITE)} _sinkpadtemplate = gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_from_string( "audio/x-raw-float;" "audio/x-raw-int")) _srcpadtemplate = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_from_string( "audio/x-raw-float;" "audio/x-raw-int")) def __init__(self, delay=0): gst.Element.__init__(self) self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") self.sinkpad.set_chain_function(self.chainfunc) self.add_pad(self.sinkpad) self.srcpad = gst.Pad(self._srcpadtemplate, "src") self.add_pad(self.srcpad) self._delay = long(delay * gst.MSECOND) print self._delay def do_get_property(self, property): if property.name == "delay": return self._delay else: raise AttributeError('unknown property %s' % property.name) def do_set_property(self, property, value): if property.name == "delay": self._delay = long(value * gst.MSECOND) else: raise AttributeError('unknown property %s' % property.name) def chainfunc(self, pad, buffer): if self._delay != 0: buffer.make_metadata_writable buffer.timestamp = buffer.timestamp + self._delay self.srcpad.push(buffer) return gst.FLOW_OK
class FFT(gst.Element): _sinkpadtemplate = gst.PadTemplate( "sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.Caps( "audio/x-raw-float, rate=44100, channels=1, width=64, endianness=1234" )) _srcpadtemplate = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.Caps("audio/x-raw-spectrum")) __gstdetails__ = ("fft", "Audio/Filter", "fft element", "Leberwurscht") # __gproperties__ = {"":(gobject.TYPE_INT, "mode", "editing mode", 0, MODES_NUM-1, MODE_DEFAULT, gobject.PARAM_READWRITE)} def __init__(self): gst.Element.__init__(self) self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") self.sinkpad.use_fixed_caps() self.srcpad = gst.Pad(self._srcpadtemplate, "src") self.srcpad.use_fixed_caps() self.sinkpad.set_chain_function(self.chainfunc) self.sinkpad.set_event_function(self.eventfunc) self.add_pad(self.sinkpad) self.srcpad.set_event_function(self.srceventfunc) self.add_pad(self.srcpad) self.adapter = gst.Adapter() def chainfunc(self, pad, buffer): # fixme: need to reset adapter when starting - see gstspectrum.c self.adapter.push(buffer) end_time = buffer.timestamp + buffer.duration gst.log("Got buffer with ts %d and length %d" % (buffer.timestamp, len(buffer))) l = 4096 bytes_num = l * 8 while self.adapter.available() >= bytes_num: time_till_end = int(self.adapter.available() / 8. / 44100 * gst.SECOND) data = numpy.frombuffer(self.adapter.peek(bytes_num)) fft = numpy.fft.rfft(data) # length of this array is l/2 + 1 b = gst.Buffer(fft) b.timestamp = end_time - time_till_end b.set_caps(self.srcpad.get_caps()) self.srcpad.push(b) self.adapter.flush(bytes_num) return gst.FLOW_OK def eventfunc(self, pad, event): return self.srcpad.push_event(event) def srceventfunc(self, pad, event): return self.sinkpad.push_event(event)
class FakeTransformer(gst.Element, log.Loggable): logCategory = 'faker_datasink' _sinkpadtemplate = gst.PadTemplate("sinkpadtemplate", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) _srcpadtemplate = gst.PadTemplate("srcpadtemplate", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) def __init__(self, destination=None, request=None): gst.Element.__init__(self) log.Loggable.__init__(self) self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") self.srcpad = gst.Pad(self._srcpadtemplate, "src") self.add_pad(self.sinkpad) self.add_pad(self.srcpad) self.sinkpad.set_chain_function(self.chainfunc) self.buffer = '' self.buffer_size = 0 self.proxy = False self.got_new_segment = False self.closed = False def get_fake_header(self): return struct.pack(">L4s", 32, 'ftyp') + \ "mp42\x00\x00\x00\x00mp42mp41isomiso2" def chainfunc(self, pad, buffer): if self.proxy: # we are in proxy mode already self.srcpad.push(buffer) return gst.FLOW_OK self.buffer = self.buffer + buffer.data if not self.buffer_size: try: self.buffer_size, a_type = struct.unpack( ">L4s", self.buffer[:8]) except: return gst.FLOW_OK if len(self.buffer) < self.buffer_size: # we need to buffer more return gst.FLOW_OK buffer = self.buffer[self.buffer_size:] fake_header = self.get_fake_header() n_buf = gst.Buffer(fake_header + buffer) self.proxy = True self.srcpad.push(n_buf) return gst.FLOW_OK
class UriListElement(BasePlaylistElement): __gstdetails__ = ('URIListDemuxer', 'Demuxer', 'Convert a text/uri-list to a stream', 'Mopidy') sinkpad_template = gst.PadTemplate( 'sink', gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_from_string('text/uri-list')) srcpad_template = gst.PadTemplate( 'src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) ghost_srcpad = True # We need to hook this up to our internal decodebin __gsttemplates__ = (sinkpad_template, srcpad_template) def __init__(self): super(UriListElement, self).__init__() self.uridecodebin = gst.element_factory_make('uridecodebin') self.uridecodebin.connect('pad-added', self.pad_added) # Limit to anycaps so we get a single stream out, letting other # elements downstream figure out actual muxing self.uridecodebin.set_property('caps', gst.caps_new_any()) def pad_added(self, src, pad): self.srcpad.set_target(pad) pad.add_event_probe(self.pad_event) def pad_event(self, pad, event): if event.has_name('urilist-played'): error = gst.GError(gst.RESOURCE_ERROR, gst.RESOURCE_ERROR_FAILED, b'Nested playlists not supported.') message = b'Playlists pointing to other playlists is not supported' self.post_message(gst.message_new_error(self, error, message)) return 1 # GST_PAD_PROBE_OK def handle(self, uris): struct = gst.Structure('urilist-played') event = gst.event_new_custom(gst.EVENT_CUSTOM_UPSTREAM, struct) self.sinkpad.push_event(event) # TODO: hookup about to finish and errors to rest of URIs so we # round robin, only giving up once all have been tried. # TODO: uris could be empty. self.add(self.uridecodebin) self.uridecodebin.set_state(gst.STATE_READY) self.uridecodebin.set_property('uri', uris[0]) self.uridecodebin.sync_state_with_parent() return True # Make sure we consume the EOS that triggered us. def convert(self, data): return parse_urilist(data)
class AsxDecoder(BasePlaylistElement): __gstdetails__ = ('ASX Decoder', 'Decoder', 'Convert .asx to text/uri-list', 'Mopidy') sinkpad_template = gst.PadTemplate('sink', gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_from_string('audio/x-ms-asx')) srcpad_template = gst.PadTemplate('src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_from_string('text/uri-list')) __gsttemplates__ = (sinkpad_template, srcpad_template) def convert(self, data): return parse_asx(data)
class XspfDecoder(BasePlaylistElement): __gstdetails__ = ('XSPF Decoder', 'Decoder', 'Convert .pls to text/uri-list', 'Mopidy') sinkpad_template = gst.PadTemplate( 'sink', gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_from_string('application/xspf+xml')) srcpad_template = gst.PadTemplate('src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_from_string('text/uri-list')) __gsttemplates__ = (sinkpad_template, srcpad_template) def convert(self, data): return parse_xspf(data)
class LedVideoSink(gst.BaseSink): __gsttemplates__ = (gst.PadTemplate( "sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_from_string( "video/x-raw-rgb,width=16,height=15,bpp=24,framerate=40/1")), ) sinkpad = property(lambda self: self.get_pad("sink")) def __init__(self, matrix): gst.BaseSink.__init__(self) self.matrix = matrix self.set_sync(True) gst.info('setting chain/event functions') # will break seeking #self.sinkpad.set_event_function(self.eventfunc) def do_render(self, buffer): self.matrix.send_raw_image(buffer) return gst.FLOW_OK def eventfunc(self, pad, event): self.info("%s event:%r" % (pad, event.type)) return True
class ArraySink(gst.BaseSink): """ Stores audio samples in a numeric array of floats. """ caps = gst.Caps("audio/x-raw-float, width=(int) 32, " "endianness = (int) LITTLE_ENDIAN, " "channels = (int) 1, " "rate = (int) [1, 96000]") __gsttemplates__ = (gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, caps), ) def __init__(self): gst.BaseSink.__init__(self) self.props.sync = False self.rate = 0 self.duration = 0L self.reset() def reset(self): self.samples = array.array('f') def do_set_caps(self, caps): if not caps[0].get_name() == "audio/x-raw-float": return False self.rate = caps[0]["rate"] return True def do_render(self, buf): self.samples.fromstring(buf) self.duration += buf.duration return gst.FLOW_OK def do_preroll(self, buf): return self.do_render(buf)
class FileSource(gst.BaseSrc): __gsttemplates__ = ( gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()), ) blocksize = 4096 fd = None def __init__(self, name): self.__gobject_init__() self.curoffset = 0 self.set_name(name) def set_property(self, name, value): if name == 'location': self.fd = open(value, 'r') def do_create(self, offset, size): if offset != self.curoffset: self.fd.seek(offset, 0) data = self.fd.read(self.blocksize) if data: self.curoffset += len(data) return gst.FLOW_OK, gst.Buffer(data) else: return gst.FLOW_UNEXPECTED, None
class MidiNoteSource(gst.BaseSrc): __gsttemplates__ = ( gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()), ) blocksize = 4096 fd = None def __init__(self, name=None, note=None): self.__gobject_init__() self.curoffset = 0 if name is not None: self.set_name(name) if note is not None: self.set_note(note) def set_note(self, note): self.fd = StringIO.StringIO(binascii.unhexlify("4d546864000000060000000101e04d54726b0000002600ff510307a12000ff5902000000ff58040402300800c0180090%x69816f80%x00820aff2f00" % (note+69, note+69))) def set_property(self, name, value): if name == 'note': self.set_note(value) def do_create(self, offset, size): if offset != self.curoffset: self.fd.seek(offset, 0) data = self.fd.read(self.blocksize) if data: self.curoffset += len(data) return gst.FLOW_OK, gst.Buffer(data) else: return gst.FLOW_UNEXPECTED, None
class CaptureSink(gst.Element): __gstdetails__ = ('CaptureSink','Sink', \ 'Captures images for the CNC', 'John McMaster') _sinkpadtemplate = gst.PadTemplate("sinkpadtemplate", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) def __init__(self): gst.Element.__init__(self) self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") self.add_pad(self.sinkpad) self.sinkpad.set_chain_function(self.chainfunc) self.sinkpad.set_event_function(self.eventfunc) self.img_cb = lambda buffer: None ''' gstreamer plugin core methods ''' def chainfunc(self, pad, buffer): #print 'Capture sink buffer in' try: self.img_cb(buffer) except: traceback.print_exc() os._exit(1) return gst.FLOW_OK def eventfunc(self, pad, event): return True
class BridgeSink(gst.Element): _sinkpadtemplate = gst.PadTemplate ("sinkpadtemplate", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) def __init__(self, queue): gst.Element.__init__(self) self.queue = queue gst.info('creating sinkpad') self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") gst.info('adding sinkpad to self') self.add_pad(self.sinkpad) gst.info('setting chain/event functions') self.sinkpad.set_chain_function(self.chainfunc) self.sinkpad.set_event_function(self.eventfunc) def chainfunc(self, pad, buffer): self.info("%s timestamp(buffer):%d" % (pad, buffer.timestamp)) self.queue.put(buffer) return gst.FLOW_OK def eventfunc(self, pad, event): self.info("%s event:%r" % (pad, event.type)) return True
class MemSrc(gst.BaseSrc): """A GStreamer Source reading from memory """ __gsttemplates__ = ( gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()), ) def __init__(self, name): self.__gobject_init__() self._data = None self.set_name(name) def set_property(self, name, value): if name == 'data': self._data = value self._data_len = len(value) def do_create(self, offset, size): size = 4096 * 2**4 if self._data and offset < self._data_len: blob = self._data[offset:offset+size] return gst.FLOW_OK, gst.Buffer(blob) else: return gst.FLOW_UNEXPECTED, None
class KinectDepthSrc(gst.BaseSrc): """ Depth """ #here we register our plugin details __gstdetails__ = ( "Kinect depth source", "kinectdepthsrc.py", "Source element for Kinect depth", "Oleksandr Lavrushchenko <*****@*****.**>") _src_template = gst.PadTemplate ("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_from_string ("video/x-raw-gray,bpp=(int)16,depth=(int)16,width=[ 1, 2147483647 ],height=[ 1, 2147483647 ],framerate=[ 0/1, 2147483647/1 ]")) __gsttemplates__ = (_src_template,) def __init__ (self, *args, **kwargs): gst.BaseSrc.__init__(self) gst.info('creating srcpad') self.src_pad = gst.Pad (self._src_template) self.src_pad.use_fixed_caps() def do_create(self, offset, length): depth, timestamp = freenect.sync_get_depth() databuf = numpy.getbuffer(depth) self.buf = gst.Buffer(databuf) self.buf.timestamp = 0 self.buf.duration = pow(2, 63) -1 return gst.FLOW_OK, self.buf
class VideoSrc(ElementBase.CCNElementSrc): __gtype_name__ = 'VideoSrc' __gstdetails__ = ("CCN Video Source", "Source/Network", "Receives video data over a CCNx network", "Derek Kulinski <*****@*****.**>") __gsttemplates__ = ( gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()), ) __gproperties__ = { 'location' : (gobject.TYPE_STRING, 'CCNx location', 'location of the stream in CCNx network', '', gobject.PARAM_READWRITE) } def do_set_property(self, property, value): if property.name == 'location': self.depacketizer = CCNVideoDepacketizer(value, 18) else: raise AttributeError, 'unknown property %s' % property.name def do_set_state(self, state): print "CHANGING STATE %s" % state
class AudioSrc(gst.BaseSrc): __gtype_name__ = 'AudioSrc' __gstdetails__ = ("Audio Source", "Source/Network", "Receive data over a CCNx network", "Derek Kulinski <*****@*****.**>") __gsttemplates__ = (gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()), ) caps = None of = None def do_get_caps(self): print "Get caps" if not self.caps: if self.of: caps_str = self.of.readline() self.caps = gst.caps_from_string(caps_str.rstrip('\n')) else: return None return self.caps def do_set_caps(self, caps): print "Caps: %s" % caps return True def do_start(self): print "Starting!" self.of = open("audio.bin", "rb") return True def do_stop(self): print "Stopping!" self.of.close() return True def do_is_seekable(self): print "Is seekable?" return False def do_event(self, ev): print "Got event of type %s" % ev.type return gst.FLOW_OK def do_create(self, offset, size): hdr = self.of.read(hdr_len) size, timestamp, duration, flags = struct.unpack(hdr_fmt, hdr) buffer = gst.Buffer(self.of.read(size)) buffer.timestamp = timestamp buffer.duration = duration #buffer.flags = flags print "buffer timestamp %d %d %d" % (buffer.timestamp, buffer.duration, buffer.flags) return gst.FLOW_OK, buffer def do_check_get_range(self): return False
class SnapshotSource(gst.Element): __gstdetails__ = ("SnapshotSource plugin", "convert.py", "A source of screenshot video frames", "Rodney Lorrimar <*****@*****.**>") _src_template = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) __gsttemplates__ = (_src_template, ) def __init__(self, framerate=None): gst.Element.__init__(self) self.framerate = framerate self.src_pad = gst.Pad(self._src_template) self.src_pad.use_fixed_caps() self.add_pad(self.src_pad) def add_snapshot(self, pixbuf, time_ms): self.width = pixbuf.get_width() self.height = pixbuf.get_height() #print "Pushing %dx%d snapshot to source" % (self.width, self.height) buf = gst.Buffer(pixbuf.get_pixels()) buf.timestamp = int(round(time_ms * gst.MSECOND)) # Don't forget to set the right caps on the buffer self.set_caps_on(buf) src = self.get_static_pad("src") status = src.push(buf) if status != gst.FLOW_OK: raise RuntimeError, "Error while pushing buffer : " + str(status) def set_caps_on(self, dest): """Set the current frame caps on the specified object""" framerate = ("framerate=%s," % self.framerate) if self.framerate else "" # The data is always native-endian xRGB; ffmpegcolorspace # doesn't support little-endian xRGB, but does support # big-endian BGRx. caps = gst.caps_from_string("video/x-raw-rgb,bpp=24,depth=24,\ red_mask=0xff0000,\ green_mask=0x00ff00,\ blue_mask=0x0000ff,\ endianness=4321,\ %swidth=%d,height=%d" \ % (framerate, self.width, self.height)) if dest: dest.set_caps(caps) def _src_setcaps(self, pad, caps): #we negotiate our capabilities here, this function is called #as autovideosink accepts anything, we just say yes we can handle the #incoming data return True def _src_chain(self, pad, buf): #this is where we do filtering #and then push a buffer to the next element, returning a value saying # it was either successful or not. return self.srcpad.push(buf)
class lal_fixodc(gst.BaseTransform): __gstdetails__ = ("Fix ODC sample format", "Generic", "Type-casts float to int", __author__) __gproperties__ = {} __gsttemplates__ = ( gst.PadTemplate( "sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_from_string("audio/x-raw-float, " + "rate = (int) [1, MAX], " + "channels = (int) 1, " + "endianness = (int) BYTE_ORDER, " + "width = (int) 32")), gst.PadTemplate( "src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_from_string("audio/x-raw-int, " + "rate = (int) [1, MAX], " + "channels = (int) 1, " + "endianness = (int) BYTE_ORDER, " + "width = (int) 32," + "depth = (int) 32," + "signed = (bool) false"))) def __init__(self): super(lal_fixodc, self).__init__() self.set_gap_aware(True) def do_transform_caps(self, direction, caps): if direction == gst.PAD_SRC: tmpltcaps = self.get_pad("sink").get_pad_template_caps() elif direction == gst.PAD_SINK: tmpltcaps = self.get_pad("src").get_pad_template_caps() else: raise AssertionError rate, = [s["rate"] for s in caps] result = gst.Caps() for s in tmpltcaps: s = s.copy() s["rate"] = rate result.append_structure(s) return result def do_transform(self, ibuf, obuf): pipeio.array_from_audio_buffer( obuf)[:] = pipeio.array_from_audio_buffer(ibuf) return gst.FLOW_OK
class CapsRemover(gst.Element): #source pad (template): we send buffers forward through here _srctemplate = gst.PadTemplate ('src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) #sink pad (template): we recieve buffers from our sink pad _sinktemplate = gst.PadTemplate ('sink', gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) #register our pad templates __gsttemplates__ = (_srctemplate, _sinktemplate) def __init__(self, *args, **kwargs): #initialise parent class gst.Element.__init__(self, *args, **kwargs) #source pad, outgoing data self.srcpad = gst.Pad(self._srctemplate) #sink pad, incoming data self.sinkpad = gst.Pad(self._sinktemplate) self.sinkpad.set_setcaps_function(self._sink_setcaps) self.sinkpad.set_chain_function(self._sink_chain) #make pads available self.add_pad(self.srcpad) self.add_pad(self.sinkpad) def _sink_setcaps(self, pad, caps): #we negotiate our capabilities here, this function is called #as autovideosink accepts anything, we just say yes we can handle the #incoming data return True def _sink_chain(self, pad, buf): #this is where we do filtering #and then push a buffer to the next element, returning a value saying # it was either successful or not. # buf.set_caps(gst.caps_new_any()) return self.srcpad.push(gst.Buffer(str(buf)))
class CairoSurfaceThumbnailSink(gst.BaseSink): """ GStreamer thumbnailing sink element. Can be used in pipelines to generates gtk.gdk.Pixbuf automatically. """ __gsignals__ = { "thumbnail": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ([gobject.TYPE_UINT64])) } __gsttemplates__ = ( gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.Caps("video/x-raw-rgb," "bpp = (int) 32, depth = (int) 32," "endianness = (int) BIG_ENDIAN," "alpha_mask = (int) %i, " "red_mask = (int) %i, " "green_mask = (int) %i, " "blue_mask = (int) %i, " "width = (int) [ 1, max ], " "height = (int) [ 1, max ], " "framerate = (fraction) [ 0, 25 ]" % (big_to_cairo_alpha_mask, big_to_cairo_red_mask, big_to_cairo_green_mask, big_to_cairo_blue_mask))) ) def __init__(self): gst.BaseSink.__init__(self) self.width = 1 self.height = 1 self.set_sync(True) self.data = None def do_set_caps(self, caps): self.log("caps %s" % caps.to_string()) self.log("padcaps %s" % self.get_pad("sink").get_caps().to_string()) self.width = caps[0]["width"] self.height = caps[0]["height"] if not caps[0].get_name() == "video/x-raw-rgb": return False return True def do_render(self, buf): self.data = str(buf.data) self.emit('thumbnail', buf.timestamp) return gst.FLOW_OK def do_preroll(self, buf): return self.do_render(buf)
class DataSink(gst.Element, log.Loggable): logCategory = 'transcoder_datasink' _sinkpadtemplate = gst.PadTemplate("sinkpadtemplate", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) def __init__(self, destination=None, request=None): gst.Element.__init__(self) log.Loggable.__init__(self) self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink") self.add_pad(self.sinkpad) self.sinkpad.set_chain_function(self.chainfunc) self.sinkpad.set_event_function(self.eventfunc) self.destination = destination self.request = request if self.destination is not None: self.destination = open(self.destination, 'wb') self.buffer = '' self.data_size = 0 self.got_new_segment = False self.closed = False def chainfunc(self, pad, buffer): if self.closed: return gst.FLOW_OK if self.destination is not None: self.destination.write(buffer.data) elif self.request is not None: self.buffer += buffer.data if len(self.buffer) > 200000: self.request.write(self.buffer) self.buffer = '' else: self.buffer += buffer.data self.data_size += buffer.size return gst.FLOW_OK def eventfunc(self, pad, event): if event.type == gst.EVENT_NEWSEGMENT: if not self.got_new_segment: self.got_new_segment = True else: self.closed = True elif event.type == gst.EVENT_EOS: if self.destination is not None: self.destination.close() elif self.request is not None: if len(self.buffer) > 0: self.request.write(self.buffer) self.request.finish() return True