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 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 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
def _getcaps(self, pad): otherpad = self._get_otherpad(pad) res = otherpad.peer_get_caps() if res == None: res = gst.caps_new_any() return res
def __init__(self, caps=None, uri=None, *args, **kwargs): gst.Bin.__init__(self, *args, **kwargs) if not caps: caps = gst.caps_new_any() self.caps = caps self.typefind = gst.element_factory_make("typefind", "internal-typefind") self.add(self.typefind) self.uri = uri if self.uri and gst.uri_is_valid(self.uri): self.urisrc = gst.element_make_from_uri(gst.URI_SRC, uri, "urisrc") self.log("created urisrc %s / %r" % (self.urisrc.get_name(), self.urisrc)) self.add(self.urisrc) self.urisrc.link(self.typefind) else: self._sinkpad = gst.GhostPad("sink", self.typefind.get_pad("sink")) self._sinkpad.set_active(True) self.add_pad(self._sinkpad) self.typefind.connect("have_type", self._typefindHaveTypeCb) self._srcpad = None self._dynamics = [] self._validelements = [] #added elements self._factories = self._getSortedFactoryList()
def __init__(self, caps=None, uri=None, stream=None, *args, **kwargs): gst.Bin.__init__(self, *args, **kwargs) if not caps: caps = gst.caps_new_any() self.caps = caps self.stream = stream self.typefind = gst.element_factory_make("typefind", "internal-typefind") self.add(self.typefind) self.uri = uri if self.uri and gst.uri_is_valid(self.uri): self.urisrc = gst.element_make_from_uri(gst.URI_SRC, uri, "urisrc") self.log("created urisrc %s / %r" % (self.urisrc.get_name(), self.urisrc)) self.add(self.urisrc) self.urisrc.link(self.typefind) else: self._sinkpad = gst.GhostPad("sink", self.typefind.get_pad("sink")) self._sinkpad.set_active(True) self.add_pad(self._sinkpad) self.typefind.connect("have_type", self._typefindHaveTypeCb) self._srcpad = None self._dynamics = [] self._validelements = [] #added elements self._factories = self._getSortedFactoryList()
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 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 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 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 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
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())
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 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 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 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
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 PyIdentity(gst.Element): _sinkpadtemplate = gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()) _srcpadtemplate = gst.PadTemplate("src", 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.sinkpad.set_chain_function(self.chainfunc) self.sinkpad.set_event_function(self.eventfunc) self.sinkpad.set_getcaps_function(gst.Pad.proxy_getcaps) self.sinkpad.set_setcaps_function(gst.Pad.proxy_setcaps) self.add_pad(self.sinkpad) self.srcpad = gst.Pad(self._srcpadtemplate, "src") self.srcpad.set_event_function(self.srceventfunc) self.srcpad.set_query_function(self.srcqueryfunc) self.srcpad.set_getcaps_function(gst.Pad.proxy_getcaps) self.srcpad.set_setcaps_function(gst.Pad.proxy_setcaps) self.add_pad(self.srcpad) def chainfunc(self, pad, buffer): gst.log("Passing buffer with ts %d" % (buffer.timestamp)) return self.srcpad.push(buffer) def eventfunc(self, pad, event): return self.srcpad.push_event(event) def srcqueryfunc(self, pad, query): return self.sinkpad.query(query) def srceventfunc(self, pad, event): return self.sinkpad.push_event(event)
class IcySrc(gst.Bin, gst.URIHandler): __gstdetails__ = ('IcySrc', 'Src', 'HTTP src wrapper for icy:// support.', 'Mopidy') srcpad_template = gst.PadTemplate( 'src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) __gsttemplates__ = (srcpad_template,) def __init__(self): super(IcySrc, self).__init__() self._httpsrc = gst.element_make_from_uri(gst.URI_SRC, 'http://') try: self._httpsrc.set_property('iradio-mode', True) except TypeError: pass self.add(self._httpsrc) self._srcpad = gst.GhostPad('src', self._httpsrc.get_pad('src')) self.add_pad(self._srcpad) @classmethod def do_get_type_full(cls): return gst.URI_SRC @classmethod def do_get_protocols_full(cls): return [b'icy', b'icyx'] def do_set_uri(self, uri): if uri.startswith('icy://'): return self._httpsrc.set_uri(b'http://' + uri[len('icy://'):]) elif uri.startswith('icyx://'): return self._httpsrc.set_uri(b'https://' + uri[len('icyx://'):]) else: return False def do_get_uri(self): uri = self._httpsrc.get_uri() if uri.startswith('http://'): return b'icy://' + uri[len('http://'):] else: return b'icyx://' + uri[len('https://'):]
class GridFSSource(Base, gst.BaseSrc): __metaclass__ = classmaker() __gsttemplates__ = ( gst.PadTemplate( "src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any() # gst.caps_from_string("application/ogg") # gst.caps_from_string("audio/x-raw-int, channels=2, endianness=1234, rate=44100, width=16, depth=16, signed=true") ), ) blocksize = 4096 fd = None def __init__(self, file_id): super(GridFSSource, self).__init__() self.__gobject_init__() self.curoffset = 0 self.file_id = file_id # doc = self.db.conn.files.File() fs = gridfs.GridFS(self.db) self.fd = fs.get(ObjectId(file_id)) # @asynchronous def do_create(self, offset, size): if offset != self.curoffset: self.fd.seek(offset, 0) # data = yield task(self.query, self.fd.read, self.blocksize) data = self.fd.read(self.blocksize) if data: self.curoffset += len(data) # respond(gst.FLOW_OK, gst.Buffer(data)) return gst.FLOW_OK, gst.Buffer(data) else: # respond(gst.FLOW_UNEXPECTED, None) return gst.FLOW_UNEXPECTED, None def __del__(self): self.fd.close()
class KaicongAudioSource(gst.BaseSrc): __gstdetails__ = ( "Kaicong Audio src plugin", "KaicongAudioGst.py", "Source element that rips sound from a Kaicong IP camera", "Scott Martin (github: smartin015)") _src_template = gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) __gsignals__ = { 'packet_received': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } __gsttemplates__ = (_src_template, ) def __init__(self, *args, **kwargs): self.caps = gst.caps_from_string( 'audio/x-raw-int, rate=7600, endianness=1234, channels=1, width=16, depth=16, signed=true' ) gst.BaseSrc.__init__(self) gst.info("Creating Kaicong src pad") self.src_pad = gst.Pad(self._src_template) self.src_pad.use_fixed_caps() def set_property(self, name, value): if name == 'ip': self.ip = value elif name == 'user': self.user = value elif name == "pwd": self.pwd = value elif name == "on" and value: self.audio = KaicongAudio(self.ip, user=self.user, pwd=self.pwd) self.audio.connect() gst.info("Connected audio") def do_create(self, offset, size): self.emit("packet_received") assert self.audio data = self.audio.read() buf = gst.Buffer(data) buf.set_caps(self.caps) print "do_create", len(buf) return gst.FLOW_OK, buf
class OverlayImageSource(gst.BaseSrc): __gstdetails__ = ('FluOverlaySrc', 'Source', 'Overlay Image source for flumotion', 'Zaheer Merali') __gsttemplates__ = (gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any())) imgBuf = "" capsStr = "" duration = 1.0 / 25 def __init__(self): gst.BaseSrc.__init__(self) self.set_format(gst.FORMAT_TIME) def do_create(self, offset, length): self.debug("Pushing buffer") gstBuf = gst.Buffer(self.imgBuf) padcaps = gst.caps_from_string(self.capsStr) gstBuf.set_caps(padcaps) gstBuf.timestamp = 0 gstBuf.duration = self.duration * gst.SECOND return gst.FLOW_OK, gstBuf
class QuietSource(gst.BaseSrc): __gsttemplates__ = ( gst.PadTemplate("src", gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()), ) def __init__(self, caps): self.__gobject_init__() self.caps = caps values = [0 for a in numpy.arange(0.0, 12*math.pi, 0.06)] data = struct.pack('<' + 'h'*len(values), *values) self.buf = gst.Buffer(data) caps = gst.caps_from_string('audio/x-raw-int, rate=8000, endianness=1234, channels=1, width=16, depth=16, signed=true') self.buf.set_caps(caps) def do_create(self, offset, size): return gst.FLOW_OK, self.buf
class VideoSink(gst.BaseSink): __gtype_name__ = 'VideoSink' __gstdetails__ = ("Video Sink", "Sink/Network", "Receive data over a CCNx network", "Derek Kulinski <*****@*****.**>") __gsttemplates__ = (gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()), ) def do_start(self): print "Starting!" self.of = open("video.bin", "wb") return True def do_stop(self): print "Stopping!" self.of.close() return True def do_set_caps(self, caps): print "Caps: %s" % caps self.of.write("%s\n" % caps) return True def do_render(self, buffer): print "Buffer timestamp %d %d %d" % (buffer.timestamp, buffer.duration, buffer.flags) hdr = struct.pack(hdr_fmt, len(buffer), buffer.timestamp, buffer.duration, buffer.flags) self.of.write(hdr) self.of.write(buffer.data) return gst.FLOW_OK def do_preroll(self, buf): print "Preroll" return gst.FLOW_OK def do_event(self, ev): print "Got event of type %s" % ev.type return gst.FLOW_OK
class ReStamp(gst.Element): """ Helper element to resets timestamps for buffers except for keyframes """ _src_padtemplate = gst.PadTemplate('src', gst.PAD_SRC, gst.PAD_ALWAYS, gst.caps_new_any()) def __init__(self, sink_templ): gst.Element.__init__(self) self.bytestream = True # Sinkpad should have the same template and caps as the wrapped decoder self.sinkpad = gst.Pad(sink_templ, 'sink') self.add_pad(self.sinkpad) self.sinkpad.set_chain_function(self._chain) self.sinkpad.set_setcaps_function(self._setcaps) self.sinkpad.set_getcaps_function(self._getcaps) # Srcpad is only internal -> any caps self.srcpad = gst.Pad(self._src_padtemplate, 'src') self.add_pad(self.srcpad) def _setcaps(self, pad, caps): # We don't need to delete timestamps in avc streams. At least with mkv they are correct if not "byte-stream" in caps.to_string(): self.bytestream = False # We simulate a decoder, so just pass on all caps negotiation return self.srcpad.get_peer().set_caps(caps) def _getcaps(self, pad): # We simulate a decoder, so just pass on all caps negotiation return self.srcpad.peer_get_caps() def _chain(self, pad, buf): # If we have byte-stream and no keyframe, delete the timestamp # print "Got buffer with timestamp %u, duration %u, offset %u, offset_end %u, Keyframe %r and caps: %s" % (buf.timestamp, buf.duration, buf.offset, buf.offset_end, not buf.flag_is_set(gst.BUFFER_FLAG_DELTA_UNIT), buf.caps) if self.bytestream and buf.flag_is_set(gst.BUFFER_FLAG_DELTA_UNIT): buf.timestamp = gst.CLOCK_TIME_NONE # print "Buffer timestamp set to gst.CLOCK_TIME_NONE" return self.srcpad.push(buf)
def __init__(self, caps=None, uri=None, stream=None, *args, **kwargs): gst.Bin.__init__(self, *args, **kwargs) if not caps: caps = gst.caps_new_any() self.caps = caps self.stream = stream self.typefind = gst.element_factory_make("typefind", "internal-typefind") self.add(self.typefind) self.uri = uri if self.uri and gst.uri_is_valid(self.uri): self.urisrc = gst.element_make_from_uri(gst.URI_SRC, uri, "urisrc") self.log("created urisrc %s / %r" % (self.urisrc.get_name(), self.urisrc)) self.add(self.urisrc) # Set the blocksize to 512kbytes, this will only matter for push-based sources if hasattr(self.urisrc.props, "blocksize"): self.urisrc.props.blocksize = 524288 self.urisrc.link_pads_full("src", self.typefind, "sink", gst.PAD_LINK_CHECK_NOTHING) else: self._sinkpad = gst.GhostPad("sink", self.typefind.get_pad("sink")) self._sinkpad.set_active(True) self.add_pad(self._sinkpad) self.typefind.connect("have_type", self._typefindHaveTypeCb) self._srcpad = None self._dynamics = [] self._validelements = [] # added elements self.debug("stream:%r" % self.stream) self.pending_newsegment = None self.eventProbeId = None
class VideoSink(gst.BaseSink): __gtype_name__ = 'VideoSink' __gstdetails__ = ("Video Sink", "Sink/Network", "Catch video stream as jpeg frames", "Dennis Liu <*****@*****.**>") __gsttemplates__ = ( gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()), ) _index = 0 _Signal_Buffer = SignalObject() def getSignal(self): return self._Signal_Buffer.signal def do_start(self): self.of = open("video.bin", "wb") return True def do_stop(self): self.of.close() return True def do_set_caps(self, caps): self.of.write("%s\n" % caps) return True def do_render(self, get_buffer): #gst.Buffer self._Signal_Buffer.signal.emit(get_buffer, self._index) return gst.FLOW_OK def do_preroll(self, buf): return gst.FLOW_OK def do_event(self, ev): return gst.FLOW_OK
class MultiMemSink(gst.BaseSink): """A GStreamer Sink writing buffers to a list in memory """ __gsttemplates__ = ( gst.PadTemplate("sink", gst.PAD_SINK, gst.PAD_ALWAYS, gst.caps_new_any()), ) def __init__(self, name): self.__gobject_init__() self._data_list = [] self.set_name(name) def get_property(self, name): if name == 'data_list': return self._data_list def do_render(self, bfr): self._data_list.append(bfr) return gst.FLOW_OK
def __init__(self, caps=None, uri=None, stream=None, *args, **kwargs): gst.Bin.__init__(self, *args, **kwargs) if not caps: caps = gst.caps_new_any() self.caps = caps self.stream = stream self.typefind = gst.element_factory_make("typefind", "internal-typefind") self.add(self.typefind) self.uri = uri if self.uri and gst.uri_is_valid(self.uri): self.urisrc = gst.element_make_from_uri(gst.URI_SRC, uri, "urisrc") self.log("created urisrc %s / %r" % (self.urisrc.get_name(), self.urisrc)) self.add(self.urisrc) # Set the blocksize to 512kbytes, this will only matter for push-based sources if hasattr(self.urisrc.props, "blocksize"): self.urisrc.props.blocksize = 524288 self.urisrc.link_pads_full("src", self.typefind, "sink", gst.PAD_LINK_CHECK_NOTHING) else: self._sinkpad = gst.GhostPad("sink", self.typefind.get_pad("sink")) self._sinkpad.set_active(True) self.add_pad(self._sinkpad) self.typefind.connect("have_type", self._typefindHaveTypeCb) self._srcpad = None self._dynamics = [] self._validelements = [] #added elements self.debug("stream:%r" % self.stream) self.pending_newsegment = None self.eventProbeId = None
def _computeAndSetValues(self): """ Calculate the new values to set on capsfilter and videobox. """ if (self.widthin == -1 or self.heightin == -1 or self.widthout == -1 or self.heightout == -1): # FIXME : should we reset videobox/capsfilter properties here ? self.error( "We don't have input and output caps, " "we can't calculate videobox values") return self.log("incoming width/height/PAR/DAR : %d/%d/%r/%r" % ( self.widthin, self.heightin, self.parin, self.darin)) self.log("outgoing width/height/PAR/DAR : %d/%d/%r/%r" % ( self.widthout, self.heightout, self.parout, self.darout)) if self.darin == self.darout: self.log( "We have same input and output caps, " "resetting capsfilter and videobox settings") # same DAR, set inputcaps on capsfilter, reset videobox values caps = gst.caps_new_any() left = 0 right = 0 top = 0 bottom = 0 else: par = self.parout dar = self.darin fdarin = float(self.darin.num) / float(self.darin.denom) fdarout = float(self.darout.num) / float(self.darout.denom) if fdarin > fdarout: self.log("incoming DAR is greater that ougoing DAR. " "Adding top/bottom borders") # width, PAR stays the same as output # calculate newheight = (PAR * widthout) / DAR newheight = ((par.num * self.widthout * dar.denom) / (par.denom * dar.num)) self.log("newheight should be %d" % newheight) extra = self.heightout - newheight top = extra / 2 bottom = extra - top # compensate for odd extra left = right = 0 # calculate filter caps astr = "width=%d,height=%d" % (self.widthout, newheight) else: self.log("incoming DAR is smaller than outgoing DAR. " "Adding left/right borders") # height, PAR stays the same as output # calculate newwidth = (DAR * heightout) / PAR newwidth = ((dar.num * self.heightout * par.denom) / (dar.denom * par.num)) self.log("newwidth should be %d" % newwidth) extra = self.widthout - newwidth left = extra / 2 right = extra - left # compensate for odd extra top = bottom = 0 # calculate filter caps astr = "width=%d,height=%d" % (newwidth, self.heightout) caps = gst.caps_from_string( "video/x-raw-yuv,%s;video/x-raw-rgb,%s" % (astr, astr)) # set properties on elements self.debug( "About to set left/right/top/bottom : %d/%d/%d/%d" % ( -left, -right, -top, -bottom)) self.videobox.props.left = -left self.videobox.props.right = -right self.videobox.props.top = -top self.videobox.props.bottom = -bottom self.debug("Settings filter caps %s" % caps.to_string()) self.capsfilter.props.caps = caps self.debug("done")
def __init__(self): QtCore.QThread.__init__(self) self.loop = gobject.MainLoop() self.filepath = None self.pipelineactive = False self.recording = False self.srcrate = "44100" self.recordrate = None self.settings = Settings() self.utils = Utils() self.pipeline = gst.Pipeline("Recording Pipeline") if sys.platform == 'darwin': self.audiosrc = gst.element_factory_make("osxaudiosrc", "audiosrc") self.srcratecap = gst.Caps("audio/x-raw-float, rate=" + self.srcrate) elif os.name == 'nt': self.audiosrc = gst.element_factory_make("dshowaudiosrc", "audiosrc") self.srcratecap = gst.caps_new_any() else: self.audiosrc = gst.element_factory_make("autoaudiosrc", "audiosrc") self.srcratecap = gst.caps_new_any() self.srcratefilter = gst.element_factory_make("capsfilter", "srcratefilter") self.srcratefilter.set_property("caps", self.srcratecap) self.audioconvert = gst.element_factory_make("audioconvert", "audioconvert") self.audioresample = gst.element_factory_make("audioresample", "audioresample") self.level = gst.element_factory_make("level", "level") self.recordingratecap = gst.caps_new_any() self.recordingratefilter = gst.element_factory_make("capsfilter", "recordingratefilter") self.recordingratefilter.set_property("caps", self.recordingratecap) self.valve = gst.element_factory_make("valve", "valve") self.sink = gst.Bin("Sink") self.audiorate = gst.element_factory_make("audiorate", "audiorate") self.audiorate.set_property("skip-to-first", True) self.wavenc = gst.element_factory_make("wavenc", "wavenc") self.filesink = gst.element_factory_make("filesink", "filesink") self.sink.add_many(self.audiorate, self.wavenc) self.audiorate.link(self.wavenc) self.sinkpad = self.audiorate.get_static_pad("sink") self.sinkghostpad = gst.GhostPad("sink", self.sinkpad) self.sinkghostpad.set_active(True) self.sink.add_pad(self.sinkghostpad) if not (self.pipeline and self.audiosrc and self.srcratecap and self.srcratefilter and self.audioconvert and self.audioresample and self.level and self.recordingratecap and self.recordingratefilter and self.valve): print("Not all elements could be loaded", sys.stderr) exit(-1) self.pipeline.add(self.audiosrc, self.srcratefilter, self.audioconvert, self.audioresample, self.level, self.recordingratefilter, self.valve, self.sink) if not gst.element_link_many(self.audiosrc, self.srcratefilter, self.audioconvert, self.audioresample, self.level, self.recordingratefilter, self.valve, self.sink): print("Elements could not be linked", sys.stderr) exit(-1) self.valve.set_property("drop", True) self.pipeline.set_state(gst.STATE_PLAYING) self.pipelineactive = True self.bus = self.pipeline.get_bus() self.bus.add_signal_watch() self.bus.connect('message', self.on_message) Registry().register('recorder', self)
def __init__(self, uri, *args, **kwargs): self.uri = uri SinkFactory.__init__(self, *args, **kwargs) self.addInputStream(MultimediaStream(caps=gst.caps_new_any()))
def __init__(self, FILECHOSEN, FILENAME, DESTDIR, CONTAINERCHOICE, AUDIOCODECVALUE, VIDEOCODECVALUE, PRESET, OHEIGHT, OWIDTH, FRATENUM, FRATEDEN, ACHANNELS, MULTIPASS, PASSCOUNTER, OUTPUTNAME, TIMESTAMP, ROTATIONVALUE, AUDIOPASSTOGGLE, VIDEOPASSTOGGLE, INTERLACED, INPUTVIDEOCAPS): gobject.GObject.__init__(self) # Choose plugin based on Container name self.container = CONTAINERCHOICE self.audiocaps = AUDIOCODECVALUE if self.container != False: self.containercaps = gst.Caps(codecfinder.containermap[CONTAINERCHOICE]) # special case mp3 which is a no-container format with a container (id3mux) else: if self.audiocaps.intersect(gst.Caps("audio/mpeg, mpegversion=1, layer=3")): self.containercaps=gst.Caps("application/x-id3") self.container=gst.Caps("application/x-id3") # Choose plugin based on Codec Name # or switch to remuxing mode if any of the values are set to 'pastr' self.stoptoggle=False self.videocaps = VIDEOCODECVALUE # "novid" means we have a video file input, but do not want it # while False means we don't have any video self.audiopasstoggle = AUDIOPASSTOGGLE self.interlaced = INTERLACED self.videopasstoggle = VIDEOPASSTOGGLE self.inputvideocaps = INPUTVIDEOCAPS self.doaudio= False self.preset = PRESET self.oheight = OHEIGHT self.owidth = OWIDTH self.fratenum = FRATENUM self.frateden = FRATEDEN self.achannels = ACHANNELS self.blackborderflag = False self.multipass = MULTIPASS self.passcounter = PASSCOUNTER self.outputfilename = OUTPUTNAME self.timestamp = TIMESTAMP self.rotationvalue = int(ROTATIONVALUE) self.vbox = {} # switching width and height around for rotationchoices where it makes sense if self.rotationvalue == 1 or self.rotationvalue == 3: nwidth = self.oheight nheight = self.owidth self.oheight = nheight self.owidth = nwidth # if needed create a variable to store the filename of the multipass \ # statistics file if self.multipass != False: self.cachefile = (str (glib.get_user_cache_dir()) + "/" + \ "multipass-cache-file" + self.timestamp + ".log") # gather preset data if relevant if self.preset != "nopreset": height, width, num, denom, pixelaspectratio = self.provide_presets() for acap in self.audiocaps: acap["channels"] = self.channels for vcap in self.videocaps: vcap["height"] = int(height) vcap["width"] = int(width) vcap["framerate"] = gst.Fraction(num, denom) if pixelaspectratio != gst.Fraction(0, 0): vcap["pixel-aspect-ratio"] = pixelaspectratio # Create transcoding pipeline self.pipeline = gst.Pipeline("TranscodingPipeline") self.pipeline.set_state(gst.STATE_PAUSED) self.uridecoder = gst.element_factory_make("uridecodebin", "uridecoder") self.uridecoder.set_property("uri", FILECHOSEN) self.uridecoder.connect("pad-added", self.OnDynamicPad) # first check if we have a container format, if not set up output for possible outputs # should not be hardcoded audiopreset=None videopreset=None if self.preset != "nopreset": # print "got preset and will use Quality Normal" # these values should not be hardcoded, but gotten from profile XML file audiopreset="Quality Normal" videopreset="Quality Normal" if self.container==False: if self.audiocaps.intersect(gst.Caps("audio/mpeg, mpegversion=4")): self.audiocaps=gst.Caps("audio/mpeg, mpegversion=4, stream-format=adts") elif self.audiocaps.intersect(gst.Caps("audio/x-flac")): self.audiocaps=gst.Caps("audio/x-flac") else: self.encodebinprofile = gst.pbutils.EncodingContainerProfile ("containerformat", None , self.containercaps, None) if self.audiocaps != False: if self.container==False: self.encodebinprofile = gst.pbutils.EncodingAudioProfile (gst.Caps(self.audiocaps), audiopreset, gst.caps_new_any(), 0) else: self.audioprofile = gst.pbutils.EncodingAudioProfile (gst.Caps(self.audiocaps), audiopreset, gst.caps_new_any(), 0) self.encodebinprofile.add_profile(self.audioprofile) if self.videocaps != "novid": if (self.videocaps != False): self.videoprofile = gst.pbutils.EncodingVideoProfile (gst.Caps(self.videocaps), videopreset, gst.caps_new_any(), 0) self.encodebinprofile.add_profile(self.videoprofile) self.encodebin = gst.element_factory_make ("encodebin", None) self.encodebin.set_property("profile", self.encodebinprofile) self.encodebin.set_property("avoid-reencoding", True) self.pipeline.add(self.encodebin) self.encodebin.set_state(gst.STATE_PAUSED) if self.videopasstoggle==False: if self.container != False: self.videoflipper = gst.element_factory_make("videoflip") self.videoflipper.set_property("method", self.rotationvalue) self.pipeline.add(self.videoflipper) self.deinterlacer = gst.element_factory_make("deinterlace") self.pipeline.add(self.deinterlacer) self.colorspaceconversion = gst.element_factory_make("ffmpegcolorspace") self.pipeline.add(self.colorspaceconversion) self.deinterlacer.link(self.colorspaceconversion) self.colorspaceconversion.link(self.videoflipper) self.deinterlacer.set_state(gst.STATE_PAUSED) self.colorspaceconversion.set_state(gst.STATE_PAUSED) self.videoflipper.set_state(gst.STATE_PAUSED) self.remuxcaps = gst.Caps() if self.audiopasstoggle: self.remuxcaps.append(self.audiocaps) if self.videopasstoggle: self.remuxcaps.append(self.videocaps) if self.audiopasstoggle and not self.videopasstoggle: self.remuxcaps.append_structure(gst.Structure("video/x-raw-rgb")) self.remuxcaps.append_structure(gst.Structure("video/x-raw-yuv")) if self.videopasstoggle and not self.audiopasstoggle: self.remuxcaps.append_structure(gst.Structure("audio/x-raw-float")) self.remuxcaps.append_structure(gst.Structure("audio/x-raw-int")) if self.videocaps=="novid": if self.inputvideocaps != None: self.remuxcaps.append(self.inputvideocaps) self.remuxcaps.append_structure(gst.Structure("audio/x-raw-float")) self.remuxcaps.append_structure(gst.Structure("audio/x-raw-int")) if (self.audiopasstoggle) or (self.videopasstoggle) or (self.videocaps=="novid"): self.uridecoder.set_property("caps", self.remuxcaps) self.pipeline.add(self.uridecoder) self.transcodefileoutput = gst.element_factory_make("filesink", \ "transcodefileoutput") self.transcodefileoutput.set_property("location", \ (DESTDIR+"/"+self.outputfilename)) self.pipeline.add(self.transcodefileoutput) self.encodebin.link(self.transcodefileoutput) self.uridecoder.set_state(gst.STATE_PAUSED) # print "setting uridcodebin to paused" self.BusMessages = self.BusWatcher() # we need to wait on this one before going further self.uridecoder.connect("no-more-pads", self.noMorePads)
def testTimelinePipeline(self): stgs = gst.pbutils.EncodingAudioProfile(gst.Caps("video/x-dirac"), "test", gst.caps_new_any(), 0) ppln = ges.TimelinePipeline() tl = ges.Timeline() assert (ppln.add_timeline (tl) == True) assert (ppln.set_mode("TIMELINE_MODE_PREVIEW_AUDIO") == True)