def remove_bin(port): log.info("Removing RTP-Bin for Port %d to the Pipeline" % port) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "remove_bin_%u_before" % port) log.info("Selecting Bin") txbin = pipeline.get_by_name("tx-bin-%d" % port) log.debug(txbin) log.info("Selecting Ghost-Pad") ghostpad = txbin.get_static_pad("sink") log.debug(ghostpad) log.info("Selecting Tee-Pad (Peer of Ghost-Pad)") teepad = ghostpad.get_peer() log.debug(teepad) def blocking_pad_probe(pad, info): log.info("Stopping Bin") log.debug(txbin.set_state(Gst.State.NULL)) log.info("Removing Bin from Pipeline") log.debug(pipeline.remove(txbin)) log.info("Releasing Tee-Pad") log.debug(tee.release_request_pad(teepad)) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "remove_bin_%u_after" % port) log.info("Removed RTP-Bin for Port %d to the Pipeline" % port) return Gst.PadProbeReturn.REMOVE log.info("Configuring Blocking Probe on teepad") teepad.add_probe(Gst.PadProbeType.BLOCK, blocking_pad_probe) # (5)
def render(self, dialog): """Renders pipeline from @dialog.""" from pitivi.render import RenderingProgressDialog with tempfile.TemporaryDirectory() as temp_dir: # Start rendering with mock.patch.object(dialog.filebutton, "get_uri", return_value=Gst.filename_to_uri(temp_dir)): with mock.patch.object(dialog.fileentry, "get_text", return_value="outfile"): with mock.patch.object(RenderingProgressDialog, "__new__"): dialog._renderButtonClickedCb(None) message = dialog._pipeline.get_bus().timed_pop_filtered( Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS | Gst.MessageType.ERROR) self.assertIsNotNone(message) Gst.debug_bin_to_dot_file_with_ts( dialog._pipeline, Gst.DebugGraphDetails.ALL, "test_rendering_with_profile.dot") result_file = Gst.filename_to_uri(os.path.join( temp_dir, "outfile")) struct = message.get_structure() self.assertEqual(message.type, Gst.MessageType.EOS, struct.to_string() if struct else message) asset = GES.UriClipAsset.request_sync(result_file) self.assertIsNotNone(asset) if message: dialog._pipeline.get_bus().post(message)
def get_frame(self, timeout_secs=10, since=None): import time t = time.time() end_time = t + timeout_secs if since is None: # If you want to wait 10s for a frame you're probably not interested # in a frame from 10s ago. since = t - timeout_secs with self._condition: while True: if (isinstance(self.last_frame, Frame) and self.last_frame.time > since): self.last_used_frame = self.last_frame return self.last_frame elif isinstance(self.last_frame, Exception): raise RuntimeError(str(self.last_frame)) t = time.time() if t > end_time: break self._condition.wait(end_time - t) pipeline = self.source_pipeline if pipeline: Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "NoVideo") raise NoVideo("No video")
def _busMessageCb(self, bus, message): if message.type == Gst.MessageType.EOS: self._prepareSamples() self._startRendering() self.stop_generation() elif message.type == Gst.MessageType.ERROR: if self.adapter: self.adapter.stop() self.adapter = None # Something went wrong TODO : recover self.stop_generation() self._num_failures += 1 if self._num_failures < 2: self.warning( "Issue during waveforms generation: %s" " for the %ith time, trying again with no rate " " modulation", message.parse_error(), self._num_failures) bus.disconnect_by_func(self._busMessageCb) self._launchPipeline() self.become_controlled() else: if self.pipeline: Gst.debug_bin_to_dot_file_with_ts( self.pipeline, Gst.DebugGraphDetails.ALL, "error-generating-waveforms") self.error("Aborting due to waveforms generation issue: %s", message.parse_error())
def _busMessageCb(self, bus, message): if message.type == Gst.MessageType.EOS: self._prepareSamples() self._startRendering() self.stopGeneration() elif message.type == Gst.MessageType.ERROR: if self.adapter: self.adapter.stop() self.adapter = None # Something went wrong TODO : recover self.stopGeneration() self._num_failures += 1 if self._num_failures < 2: self.warning("Issue during waveforms generation: %s" " for the %ith time, trying again with no rate " " modulation", message.parse_error(), self._num_failures) bus.disconnect_by_func(self._busMessageCb) self._launchPipeline() self.becomeControlled() else: Gst.debug_bin_to_dot_file_with_ts(self.pipeline, Gst.DebugGraphDetails.ALL, "error-generating-waveforms") self.error("Aborting due to waveforms generation issue: %s", message.parse_error())
def relinkPipeline(pad, probeInfo, userData): self = userData #if (probeInfo.type != Gst.EventType.EOS): if self.cnt < 2: self.cnt += 1 self.log.debug("Event received, not EOS but {0}".format( probeInfo.type)) return Gst.PadProbeReturn.OK self.log.debug("EOS received, change file location") # remove padProbe pad.remove_probe(probeInfo.id) self.padProbes += [[pad, probeInfo]] self.elements["filesink1"].set_state(Gst.State.NULL) self.elements["filesink1"].set_property( "location", "/run/media/peter/home/tmp/webcam/test3.mp4") self.elements["filesink1"].set_state(Gst.State.PLAYING) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main_blocked") return Gst.PadProbeReturn.OK
def _on_warning(self, _bus, message): assert message.type == Gst.MessageType.WARNING if self.sink_pipeline is not None: Gst.debug_bin_to_dot_file_with_ts( self.sink_pipeline, Gst.DebugGraphDetails.ALL, "WARNING") err, dbg = message.parse_warning() warn("%s: %s\n%s\n" % (err, err.message, dbg))
def remove_bin(port): log.info("Removing RTP-Bin for Port %d to the Pipeline" % port) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "remove_bin_%u_before" % port) log.info("Selecting Bin") rxbin = pipeline.get_by_name("rx-bin-%d" % port) # (1) log.debug(rxbin) log.info("Selecting Ghost-Pad") ghostpad = rxbin.get_static_pad("src") log.debug(ghostpad) log.info("Selecting Mixerpad (Peer of Ghost-Pad)") mixerpad = ghostpad.get_peer() # (4) log.debug(mixerpad) log.info("Stopping Bin") log.debug(rxbin.set_state(Gst.State.NULL)) # (5) ff. log.info("Removing Bin from Pipeline") log.debug(pipeline.remove(rxbin)) log.info("Releasing mixerpad") log.debug(mixer.release_request_pad(mixerpad)) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "remove_bin_%u_after" % port) log.info("Removed RTP-Bin for Port %d to the Pipeline" % port)
def get_frame(self, timeout_secs=10, since=None): import time t = time.time() end_time = t + timeout_secs if since is None: # If you want to wait 10s for a frame you're probably not interested # in a frame from 10s ago. since = t - timeout_secs with self._condition: while True: if (isinstance(self.last_frame, Frame) and self.last_frame.time > since): self.last_used_frame = self.last_frame return self.last_frame elif isinstance(self.last_frame, Exception): raise RuntimeError(str(self.last_frame)) t = time.time() if t > end_time: break self._condition.wait(end_time - t) pipeline = self.source_pipeline if pipeline: Gst.debug_bin_to_dot_file_with_ts( pipeline, Gst.DebugGraphDetails.ALL, "NoVideo") raise NoVideo("No video")
def __bus_watch(self, bus, message): if message.type == Gst.MessageType.STATE_CHANGED: old_state, new_state, pending_state = message.parse_state_changed() if message.src == self.pulsesrc: # The pulsesrc element's "device" property only has any effect # after pulsesrc's state has been set to READY. Therefore, we # set that property's value here, so that pulsesrc captures # PCM data from the specified source. if (old_state == Gst.State.NULL) and (new_state == Gst.State.READY): msg('Setting pulsesrc device') self.pulsesrc.set_property('device', self.source_name) elif message.src == self.pipeline: old_state_name = Gst.Element.state_get_name(old_state) new_state_name = Gst.Element.state_get_name(new_state) pending_state_name = Gst.Element.state_get_name(pending_state) # Dump the pipeline's topology as a Graphviz .dot file after # the whole pipeline completed a state change. This is useful # for debugging and diagnostics. The dumps will be done only # if the GST_DEBUG_DUMP_DOT_DIR environment variable is set. # Otherwise, debug_bin_to_dot_file_with_ts() is a no-op. dot_filename = 'statechange_old-{}_new-{}_pending-{}'.format( old_state_name, new_state_name, pending_state_name) Gst.debug_bin_to_dot_file_with_ts(self.pipeline, Gst.DebugGraphDetails.ALL, dot_filename) msg('Completed state change from {} to {}; pending: {}'.format( old_state_name, new_state_name, pending_state_name)) elif message.type == Gst.MessageType.INFO: err, debug = message.parse_info() msg( 'GStreamer info: {} (debug details: {})'.format( err, debug or 'none'), 2) elif message.type == Gst.MessageType.WARNING: err, debug = message.parse_warning() msg( 'GStreamer warning: {} (debug details: {})'.format( err, debug or 'none'), 2) elif message.type == Gst.MessageType.ERROR: err, debug = message.parse_error() error('GStreamer error: {} (debug details: {})'.format( err, debug or 'none')) self.mainloop.quit() elif message.type == Gst.MessageType.LATENCY: # As the GStreamer documentation states, it is recommended # to call recalculate_latency() once this message arrives. msg('Recalculatinge pipeline latency', 2) self.pipeline.recalculate_latency() elif message.type == Gst.MessageType.EOS: msg('End of stream detected', 2) self.mainloop.quit() return True
def render(self, dialog): """Renders pipeline from @dialog.""" from pitivi.render import RenderingProgressDialog with tempfile.TemporaryDirectory() as temp_dir: # Start rendering with mock.patch.object(dialog.filebutton, "get_uri", return_value=Gst.filename_to_uri(temp_dir)): with mock.patch.object(dialog.fileentry, "get_text", return_value="outfile"): with mock.patch.object(RenderingProgressDialog, "__new__"): dialog._renderButtonClickedCb(None) message = dialog._pipeline.get_bus().timed_pop_filtered( 10 * Gst.SECOND, Gst.MessageType.EOS | Gst.MessageType.ERROR) Gst.debug_bin_to_dot_file_with_ts( dialog._pipeline, Gst.DebugGraphDetails.ALL, "test_rendering_with_profile.dot") result_file = Gst.filename_to_uri(os.path.join(temp_dir, "outfile")) struct = message.get_structure() if message else None self.assertEqual(message.type, Gst.MessageType.EOS, struct.to_string() if struct else message) asset = GES.UriClipAsset.request_sync(result_file) # FIXME Check more things? self.assertIsNotNone(asset)
def _on_error(self, _bus, message): assert message.type == Gst.MessageType.ERROR if self.sink_pipeline is not None: Gst.debug_bin_to_dot_file_with_ts( self.sink_pipeline, Gst.DebugGraphDetails.ALL, "ERROR") err, dbg = message.parse_error() self._raise_in_user_thread( RuntimeError("%s: %s\n%s\n" % (err, err.message, dbg)))
def on_error(self, _bus, message): assert message.type == Gst.MessageType.ERROR pipeline = self.source_pipeline if pipeline is not None: Gst.debug_bin_to_dot_file_with_ts( pipeline, Gst.DebugGraphDetails.ALL, "ERROR") err, dbg = message.parse_error() self.tell_user_thread(NoVideo( "Error from source pipeline: %s: %s\n%s" % (err, err.message, dbg)))
def preview(self): logger.debug("recorder preview") for bin in self.bins.values(): bin.changeValve(True) self.__valves_status = True self.__set_state(Gst.State.PLAYING) Gst.debug_bin_to_dot_file_with_ts(self.pipeline, Gst.DebugGraphDetails.ALL, 'galicaster-pipeline')
def preview(self): logger.debug("recorder preview") for bin in list(self.bins.values()): bin.changeValve(True) self.__valves_status = True self.__set_state(Gst.State.PLAYING) Gst.debug_bin_to_dot_file_with_ts(self.pipeline, Gst.DebugGraphDetails.ALL, 'galicaster-pipeline')
def connect_audiosink(pipe): Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "audiosink0") audiosink = Gst.ElementFactory.make("autoaudiosink", None) audiosink.set_state(Gst.State.PLAYING) pipe.add(audiosink) agnostic = pipe.get_by_name("agnostic") agnostic.link(audiosink) Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "audiosink1") return False
def disconnect_videosink(pipe, name): Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "removevideosink0") videosink = pipe.get_by_name(name) if videosink == None: return remove_element(videosink) Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "removevideosink1") return False
def __on_bus_error(self, bus, message): """On error signal.""" self.stop_generation() self._num_failures += 1 if self._num_failures < 2: self.__disconnect_bus() self._launch_pipeline() elif self.pipeline: Gst.debug_bin_to_dot_file_with_ts(self.pipeline, Gst.DebugGraphDetails.ALL, "error-generating-waveforms")
def pipeline2Null(self, pipeline): self.log.debug("send EOS") pipeline.send_event(Gst.Event.new_eos()) bus = pipeline.get_bus() msg = bus.timed_pop_filtered (Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS | Gst.MessageType.ERROR) if msg.type == Gst.MessageType.ERROR: self.log.debug("bus message {0}".format(msg.parse_error())) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main" ) self.log.debug("null pipeline") pipeline.set_state(Gst.State.NULL)
def bus_call(bus, message, loop): t = message.type Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "test") if t == Gst.MessageType.EOS: sys.stdout.write("End-of-stream\n") loop.quit() elif t == Gst.MessageType.ERROR: err, debug = message.parse_error() sys.stderr.write("Error: %s: %s\n" % (err, debug)) loop.quit() return True
def run(self): self.log.debug("start pipeline") self.cnt = 0 self.window.show_all() # You need to get the XID after window.show_all(). You shouldn't get it # in the on_sync_message() handler because threading issues will cause # segfaults there. Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main_before" ) self.xid = self.drawingarea.get_property('window').get_xid() self.pipelines["main"].set_state(Gst.State.PLAYING) # self.pipelines["catch"].set_state(Gst.State.PLAYING) Gtk.main()
def connect_videosink(pipe, name, timeout): Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "videosink0") videosink = Gst.ElementFactory.make("xvimagesink", name) videosink.set_state(Gst.State.PLAYING) pipe.add(videosink) agnostic = pipe.get_by_name("agnostic") agnostic.link(videosink) if timeout != 0: GLib.timeout_add_seconds(timeout, disconnect_videosink, pipe, name) Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "videosink1") return False
def add_bin(port): Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "add_bin_%u_before" % port) bin = create_bin(port) log.info("Adding RTP-Bin for Port %d to the Pipeline" % port) pipeline.add(bin) output_element: Gst.Element = pipeline.get_by_name("out-%d" % port) # (9) output_element.link_filtered(mixer, caps_audio) bin.sync_state_with_parent() # (10) log.info("Added RTP-Bin for Port %d to the Pipeline" % port) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "add_bin_%u_after" % port)
def __start(self, notuse): self['bus'].add_signal_watch() self['bus'].connect("message", EngineGST.__bus_call, (self['mainloop'], self['pipeline'])) self['pipeline'].set_state(Gst.State.PLAYING) Gst.debug_bin_to_dot_file_with_ts(self['pipeline'], Gst.DebugGraphDetails.ALL, self['id']) #GObject.timeout_add(5*1000, switch_file, loop) try: self['mainloop'].run() except Exception as e: print("streamer except exit by", e.message) self['pipeline'].set_state(Gst.State.NULL)
def close_pipeline(self): """Stop gstreamer pipeline.""" log.info("Closing pipeline") # If pipeline is running, then export pipeline graph before closing # To use this, set GST_DEBUG_DUMP_DOT_DIR environnement variable if self.pipe is not None: Gst.debug_bin_to_dot_file_with_ts(self.pipe, Gst.DebugGraphDetails.ALL, "pipeline") self.pipe.set_state(Gst.State.NULL) self.pipe = None self.webrtc = None
def bus_call(bus, message, loop): t = message.type Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "test") if t == Gst.MessageType.EOS: logging.info("End-of-stream") loop.quit() elif t == Gst.MessageType.ERROR: err, debug = message.parse_error() logging.error(f" {err}: {debug}") stopSignal.set() sleep(2) loop.quit() return True
def preparePipeline(pad, probeInfo, userData): self = userData self.log.debug("pad blocked") # remove padProbe pad.remove_probe(probeInfo.id) self.padProbes = [[pad, probeInfo]] ################################################################################ self.cnt += 1 # get pad of current recBin pC = pad.get_peer() # get current recBin (the one that is currently doing the recording) binC = pC.get_parent() # get next recBin (the one that will be linked to the video stream next) binN = None if binC == self.elements["recBin1"]: self.log.debug("replace recBin1 by recBin2") binN = self.elements["recBin2"] else: self.log.debug("replace recBin2 by recBin1") binN = self.elements["recBin1"] self.log.debug("remove current recBin from main and prepare catch") self.pipelines["main"].remove(binC) # self.pipelines["catch"].set_state(Gst.State.PAUSED) # # self.pipelines["catch"].remove(self.elements["fakesink"]) # # self.log.debug("add/link current recBin to catch") # self.pipelines["catch"].add(self.elements["recBin1"]) # assert(self.elements["fakesrc"].link(self.elements["recBin1"])) # # self.log.debug("set catch PLAYING") # self.pipelines["catch"].set_state(Gst.State.PLAYING) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["catch"], Gst.DebugGraphDetails.ALL, "catch" ) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main" ) self.log.debug("send EOS to current recBin") binC.send_event(Gst.Event.new_eos()) # self.log.debug("prepare next recBin") binN.set_state(Gst.State.NULL) self.log.debug("add and link next recBin to main") self.pipelines["main"].add(binN) self.elements["srcQueue"].link(binN) self.log.debug("change file location of next recBin") fs = binN.get_by_name("filesink") fs.set_property("location", "/run/media/peter/home/tmp/webcam/test{0}.mp4".format(self.cnt)) binN.set_state(Gst.State.PLAYING) ################################################################################ Gst.debug_bin_to_dot_file_with_ts(self.pipelines["catch"], Gst.DebugGraphDetails.ALL, "catch" ) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main" ) return Gst.PadProbeReturn.OK
def blocking_pad_probe(pad, info): log.info("Stopping Bin") log.debug(txbin.set_state(Gst.State.NULL)) log.info("Removing Bin from Pipeline") log.debug(pipeline.remove(txbin)) log.info("Releasing Tee-Pad") log.debug(tee.release_request_pad(teepad)) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "remove_bin_%u_after" % port) log.info("Removed RTP-Bin for Port %d to the Pipeline" % port) return Gst.PadProbeReturn.REMOVE
def connect_enc_videosink(pipe): Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "encvideosink0") encoder = Gst.ElementFactory.make("theoradec", None) videosink = Gst.ElementFactory.make("xvimagesink", None) videosink.set_state(Gst.State.PLAYING) encoder.set_state(Gst.State.PLAYING) pipe.add(videosink) pipe.add(encoder) agnostic = pipe.get_by_name("agnostic") encoder.link(videosink) agnostic.link(encoder) Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "encvideosink1") return False
def run(self): self.log.debug("start pipeline") self.cnt = 0 self.window.show_all() # You need to get the XID after window.show_all(). You shouldn't get it # in the on_sync_message() handler because threading issues will cause # segfaults there. Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main_before") self.xid = self.drawingarea.get_property('window').get_xid() self.pipelines["main"].set_state(Gst.State.PLAYING) # self.pipelines["catch"].set_state(Gst.State.PLAYING) Gtk.main()
def blockActiveQueuePad(pad, probeInfo, userData): self = userData buffer = probeInfo.get_buffer() #if not buffer.flag_is_set(Gst.BufferFlags.DELTA_UNIT): if True:#not (buffer.mini_object.flags & Gst.BufferFlags.DELTA_UNIT): pad.remove_probe(probeInfo.id) self.log.debug("found keyframe start blocking process") # tee pad to active recording bin Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main_before" ) tp = self.elements["srcQueue"].get_static_pad("src") tp.add_probe(Gst.PadProbeType.BLOCK_DOWNSTREAM, preparePipeline, self) return Gst.PadProbeReturn.OK else: self.log.debug("no keyframe yet") return Gst.PadProbeReturn.OK
def _busMessageCb(self, bus, message): if message.type == Gst.MessageType.EOS: self._prepareSamples() self._startRendering() self.stopGeneration() elif message.type == Gst.MessageType.ERROR: if self.adapter: self.adapter.stop() self.adapter = None # Something went wrong TODO : recover self.stopGeneration() self._num_failures += 1 if self._num_failures < 2: self.warning( "Issue during waveforms generation: %s" " for the %ith time, trying again with no rate " " modulation", message.parse_error(), self._num_failures) bus.disconnect_by_func(self._busMessageCb) self._launchPipeline() self.becomeControlled() else: Gst.debug_bin_to_dot_file_with_ts( self.pipeline, Gst.DebugGraphDetails.ALL, "error-generating-waveforms") self.error("Aborting due to waveforms generation issue: %s", message.parse_error()) elif message.type == Gst.MessageType.STATE_CHANGED: prev, new, unused_pending_state = message.parse_state_changed() if message.src == self.pipeline: if prev == Gst.State.READY and new == Gst.State.PAUSED: self.pipeline.seek( 1.0, Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE, Gst.SeekType.SET, 0, Gst.SeekType.NONE, -1) # In case we failed previously, we won't modulate next time elif not self.adapter and prev == Gst.State.PAUSED and \ new == Gst.State.PLAYING and self._num_failures == 0: # This line is necessary so we can instantiate GstTranscoder's # GstCpuThrottlingClock below. Gst.ElementFactory.make("uritranscodebin", None) clock = GObject.new( GObject.type_from_name("GstCpuThrottlingClock")) clock.props.cpu_usage = self.app.settings.previewers_max_cpu self.pipeline.use_clock(clock)
def link_element(): Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "link_element_before") log.info("Requesting Tee-Pad") tee_pad_templ = tee.get_pad_template("src_%u") tee_pad = tee.request_pad(tee_pad_templ) log.debug(tee_pad) log.info("Requesting Mixer-Pad") mixer_pad_templ = mixer.get_pad_template("sink_%u") mixer_pad = mixer.request_pad(mixer_pad_templ) log.debug(mixer_pad) log.info("Linking Tee-Pad to Mixer-Pad") log.debug(tee_pad.link(mixer_pad)) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "link_element_after")
def main(argv): Gst.init(argv) pipe = Gst.Pipeline() bus = pipe.get_bus() bus.add_watch(GLib.PRIORITY_DEFAULT, bus_callback, None) videotest = Gst.ElementFactory.make("videotestsrc", None) encoder = Gst.ElementFactory.make("vp8enc", None) agnostic = Gst.ElementFactory.make("agnosticbin", "agnostic") decoder = Gst.ElementFactory.make("vp8dec", None) videosink2 = Gst.ElementFactory.make("xvimagesink", None) videosink = Gst.ElementFactory.make("xvimagesink", "videosink0") videotest.set_property("pattern", "ball") videotest.set_property("is-live", True) pipe.add(videotest) pipe.add(encoder) pipe.add(agnostic) pipe.add(videosink) pipe.add(decoder) pipe.add(videosink2) videotest.link(encoder) encoder.link(agnostic) agnostic.link(videosink) agnostic.link(decoder) decoder.link(videosink2) pipe.set_state(Gst.State.PLAYING) Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "playing") GLib.timeout_add_seconds(2, connect_videosink, pipe, "videosink1", 4) GLib.timeout_add_seconds(2, connect_enc_videosink, pipe) GLib.timeout_add_seconds(4, connect_audiosink, pipe) GLib.timeout_add_seconds(10, disconnect_videosink, pipe, "videosink0") GLib.timeout_add_seconds(16, connect_videosink, pipe, "videosink3", 0) GLib.timeout_add_seconds(18, connect_enc_videosink, pipe) try: loop.run() except: pass Gst.debug_bin_to_dot_file_with_ts(pipe, Gst.DebugGraphDetails.ALL, "end") pipe.set_state(Gst.State.NULL)
def unlink_element(): Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "link_element_before") log.info("Unlinking tee from mixer") for tee_pad in tee.srcpads: mixer_pad = tee_pad.get_peer() log.info("Unlinking pads %s and %s" % (tee_pad, mixer_pad)) log.debug(tee_pad.unlink(mixer_pad)) log.info("Releasing pad %s" % tee_pad) log.debug(tee.release_request_pad(tee_pad)) log.info("Releasing pad %s" % mixer_pad) log.debug(mixer.release_request_pad(mixer_pad)) Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "link_element_after")
def _busMessageCb(self, bus, message): if message.type == Gst.MessageType.EOS: self._prepareSamples() self._startRendering() self.stopGeneration() elif message.type == Gst.MessageType.ERROR: if self.adapter: self.adapter.stop() self.adapter = None # Something went wrong TODO : recover self.stopGeneration() self._num_failures += 1 if self._num_failures < 2: self.warning("Issue during waveforms generation: %s" " for the %ith time, trying again with no rate " " modulation", message.parse_error(), self._num_failures) bus.disconnect_by_func(self._busMessageCb) self._launchPipeline() self.becomeControlled() else: Gst.debug_bin_to_dot_file_with_ts(self.pipeline, Gst.DebugGraphDetails.ALL, "error-generating-waveforms") self.error("Aborting due to waveforms generation issue: %s", message.parse_error()) elif message.type == Gst.MessageType.STATE_CHANGED: prev, new, unused_pending_state = message.parse_state_changed() if message.src == self.pipeline: if prev == Gst.State.READY and new == Gst.State.PAUSED: self.pipeline.seek(1.0, Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE, Gst.SeekType.SET, 0, Gst.SeekType.NONE, -1) # In case we failed previously, we won't modulate next time elif not self.adapter and prev == Gst.State.PAUSED and \ new == Gst.State.PLAYING and self._num_failures == 0: self.adapter = PipelineCpuAdapter(self.pipeline) self.adapter.start()
def blockActiveQueuePad(pad, probeInfo, userData): self = userData buffer = probeInfo.get_buffer() #if not buffer.flag_is_set(Gst.BufferFlags.DELTA_UNIT): if True: #not (buffer.mini_object.flags & Gst.BufferFlags.DELTA_UNIT): pad.remove_probe(probeInfo.id) self.log.debug("found keyframe start blocking process") # tee pad to active recording bin Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main_before") tp = self.elements["srcQueue"].get_static_pad("src") tp.add_probe(Gst.PadProbeType.BLOCK_DOWNSTREAM, preparePipeline, self) return Gst.PadProbeReturn.OK else: self.log.debug("no keyframe yet") return Gst.PadProbeReturn.OK
def add_new_src(): global testsrc2, capsfilter2, mixerpad Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "adding-testsrc2-before") log.info("Adding testsrc2") log.info("Creating testsrc2") testsrc2 = Gst.ElementFactory.make("audiotestsrc", "testsrc2") testsrc2.set_property("freq", 440) testsrc2.set_property("is-live", True) # attach probe for logging timestamps testsrc2.get_static_pad("src").add_probe(Gst.PadProbeType.BUFFER, logging_pad_probe, "testsrc2-output") log.info("Adding testsrc2") log.debug(pipeline.add(testsrc2)) log.info("Creating capsfilter") capsfilter2 = Gst.ElementFactory.make("capsfilter", "capsfilter2") # (3) capsfilter2.set_property("caps", caps) log.info("Adding capsfilter") log.debug(pipeline.add(capsfilter2)) log.info("Linking testsrc2 to capsfilter2") log.debug(testsrc2.link(capsfilter2)) log.info("Requesting Pad from Mixer") mixerpad = mixer.get_request_pad("sink_%u") log.debug(mixerpad) log.info("Linking capsfilter2 to mixerpad") log.debug(capsfilter2.get_static_pad("src").link(mixerpad)) log.info("Syncing Element-States with Pipeline") log.debug(capsfilter2.sync_state_with_parent()) log.debug(testsrc2.sync_state_with_parent()) log.info("Adding testsrc2 done") Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "adding-testsrc2-after") # (4)
def relinkPipeline(pad, probeInfo, userData): self = userData #if (probeInfo.type != Gst.EventType.EOS): if self.cnt < 2: self.cnt += 1 self.log.debug("Event received, not EOS but {0}".format(probeInfo.type)) return Gst.PadProbeReturn.OK; self.log.debug("EOS received, change file location") # remove padProbe pad.remove_probe(probeInfo.id) self.padProbes += [[pad, probeInfo]] self.elements["filesink1"].set_state(Gst.State.NULL) self.elements["filesink1"].set_property("location", "/run/media/peter/home/tmp/webcam/test3.mp4") self.elements["filesink1"].set_state(Gst.State.PLAYING) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main_blocked" ) return Gst.PadProbeReturn.OK
def __ctrl_c_handling(signal, frame): Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, '-pad') sys.exit(0)
def on_warning(self, _bus, message): assert message.type == Gst.MessageType.WARNING Gst.debug_bin_to_dot_file_with_ts( self.source_pipeline, Gst.DebugGraphDetails.ALL, "WARNING") err, dbg = message.parse_warning() warn("%s: %s\n%s\n" % (err, err.message, dbg))
def preparePipeline(pad, probeInfo, userData): self = userData self.log.debug("pad blocked") # remove padProbe pad.remove_probe(probeInfo.id) self.padProbes = [[pad, probeInfo]] ################################################################################ self.cnt += 1 # get pad of current recBin pC = pad.get_peer() # get current recBin (the one that is currently doing the recording) binC = pC.get_parent() # get next recBin (the one that will be linked to the video stream next) binN = None fs = None if binC == self.elements["recBin1"]: self.log.debug("replace recBin1 by recBin2") self.log.debug("prepare next recBin") self.resetBin(self.elements["recBin2"]) binN = self.elements["recBin2"] fs = self.elements["filesink2"] mux = self.elements["mux_2"] fqN = self.elements["fileQueue2"] fqC = self.elements["fileQueue1"] else: self.log.debug("replace recBin2 by recBin1") self.log.debug("ref of recBin1: {0}".format(gc.get_referrers(self.elements["recBin1"]))) self.log.debug("prepare next recBin") self.resetBin(self.elements["recBin1"]) binN = self.elements["recBin1"] fs = self.elements["filesink1"] mux = self.elements["mux_1"] fqN = self.elements["fileQueue1"] fqC = self.elements["fileQueue2"] self.updateFilesinkLocation(fs, mux) self.log.debug("remove current recBin from main and prepare catch") self.elements["srcQueue"].unlink(fqC) self.pipelines["main"].remove(binC) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main-1" ) self.log.debug("send EOS to current recBin") binC.send_event(Gst.Event.new_eos()) self.log.debug("prepare next recBin") binN.set_state(Gst.State.NULL) self.log.debug("add and link next recBin to main") self.pipelines["main"].add(binN) assert(self.elements["srcQueue"].link(binN)) self.log.debug("change file location of next recBin") for pad in mux.pads: if pad.get_name().startswith("video"): pad.push_event(Gst.Event.new_reconfigure()) binN.set_state(Gst.State.PLAYING) ################################################################################ Gst.debug_bin_to_dot_file_with_ts(self.pipelines["catch"], Gst.DebugGraphDetails.ALL, "catch-2" ) Gst.debug_bin_to_dot_file_with_ts(self.pipelines["main"], Gst.DebugGraphDetails.ALL, "main-2" ) return Gst.PadProbeReturn.OK
def _busMessageCb(self, unused_bus, message): if message.type == Gst.MessageType.EOS: self.pause() self.emit('eos') elif message.type == Gst.MessageType.STATE_CHANGED: prev, new, pending = message.parse_state_changed() if message.src == self._pipeline: self.debug( "Pipeline change state prev: %r, new: %r, pending: %r", prev, new, pending) emit_state_change = pending == Gst.State.VOID_PENDING if prev == Gst.State.READY and new == Gst.State.PAUSED: # trigger duration-changed try: self.getDuration() except PipelineError as e: self.warning("Could not get duration because: %s", e) # no sinks?? pass if self._recovery_state == self.RecoveryState.STARTED_RECOVERING: if self._attempted_recoveries == MAX_RECOVERIES: self._recovery_state = self.RecoveryState.NOT_RECOVERING self._attempted_recoveries = 0 self.error("Too many tries to seek back to right position" "not trying again, and going back to 0 instead") else: self._recovery_state = self.RecoveryState.SEEKED_AFTER_RECOVERING self.simple_seek(self._last_position) self.info( "Seeked back to the last position after pipeline recovery") self._listenToPosition(self._force_position_listener) elif prev == Gst.State.PAUSED and new == Gst.State.PLAYING: self._listenToPosition(True) elif prev == Gst.State.PLAYING and new == Gst.State.PAUSED: self._listenToPosition(self._force_position_listener) if emit_state_change: self.emit('state-change', new, prev) elif message.type == Gst.MessageType.ERROR: error, detail = message.parse_error() self._handleErrorMessage(error, detail, message.src) Gst.debug_bin_to_dot_file_with_ts(self._pipeline, Gst.DebugGraphDetails.ALL, "pitivi.error") if not self._rendering(): self._recover() elif message.type == Gst.MessageType.DURATION_CHANGED: self.debug("Duration might have changed, querying it") GLib.idle_add(self._queryDurationAsync) elif message.type == Gst.MessageType.ASYNC_DONE: if self._recovery_state == self.RecoveryState.SEEKED_AFTER_RECOVERING: self._recovery_state = self.RecoveryState.NOT_RECOVERING self._attempted_recoveries = 0 self._waiting_for_async_done = False self.__emitPosition() if self._next_seek is not None: self.simple_seek(self._next_seek) self._next_seek = None self._removeWaitingForAsyncDoneTimeout() else: self.log("%s [%r]", message.type, message.src)