#!/usr/bin/env python3.4 # This file is part of Libre-Streamer. # # Libre-Streamer is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Libre-Streamer is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Libre-Streamer. If not, see . # # Copyright (c) 2016 David Testé import gi from gi.repository import Gst from gi.repository import GstVideo class New_user_pipeline(): def __init__(self): self.user_pipeline = self.create_gstreamer_pipeline() def create_video_sources(self): """Create video inputs from various sources.""" self.videosrc = Gst.ElementFactory.make('rtspsrc', 'videosrc') self.videosrc.set_property('location', 'rtsp://192.168.48.2:554') self.videosrc.set_property('latency', 0) def create_audio_sources(self): """Create audio inputs from various sources.""" self.audiosrc = Gst.ElementFactory.make('pulsesrc', 'audiosrc') ## self.videosrc.set_property('latency', 0) def create_pipeline_callbacks(self): """Callbacks to connect dynamically created pads.""" self.videosrc.connect("pad-added", self.on_pad_added_to_rtspsrc) def on_pad_added_to_rtspsrc(self, rtspsrc, pad): """Connect the dynamic 'src'pad of an RTSP source.""" sinkpad = self.queuev_1.get_static_pad('sink') pad.link(sinkpad) def create_filesink(self): """Create storable output elements.""" self.disksink_rawvideo = Gst.ElementFactory.make('filesink') #[TO DO]: File location has to be defined self.disksink_rawvideo.set_property('location', 'popo_rawvideo') self.disksink_audio = Gst.ElementFactory.make('filesink') self.disksink_audio.set_property('location', 'popo_audio') self.disksink_stream = Gst.ElementFactory.make('filesink') self.disksink_stream.set_property('location', 'popo_stream') def create_streamsink(self): """Create streamable output elements.""" # To local screen: self.screensink = Gst.ElementFactory.make('xvimagesink', 'screensink') # To icecast server: self.icecastsink_audio = Gst.ElementFactory.make('shout2send', 'icecastsink_audio') ## Configuration should be written on a file locally to keep safe private addresses self.icecastsink_audio.set_property('ip', 'live2.fsf.org') self.icecastsink_audio.set_property('port', 80) self.icecastsink_audio.set_property('mount', 'testaudio.ogv') self.icecastsink_audio.set_property('password', 'thahw3Wiez') self.icecastsink_stream = Gst.ElementFactory.make('shout2send', 'icecastsink_stream') self.icecastsink_stream.set_property('ip', 'live2.fsf.org') self.icecastsink_stream.set_property('port', 80) self.icecastsink_stream.set_property('mount', 'teststream.ogv') self.icecastsink_stream.set_property('password', 'thahw3Wiez') def create_payloader_elements(self): pass def create_depayloader_elements(self): self.rtpjpegdepay = Gst.ElementFactory.make('rtpjpegdepay', 'rtpjpegdepay') def create_encoder_elements(self): # Audio encoders: self.vorbisenc = Gst.ElementFactory.make('vorbisenc', 'vorbisenc') # Video encoders: self.vp8enc = Gst.ElementFactory.make('vp8enc', 'vp8enc') self.vp8enc.set_property('min_quantizer', 1) self.vp8enc.set_property('max_quantizer', 13) self.vp8enc.set_property('cpu-used', 5) self.vp8enc.set_property('deadline', 42000) self.vp8enc.set_property('threads', 2) self.vp8enc.set_property('sharpness', 7) def create_decoder_elements(self): self.jpegdec = Gst.ElementFactory.make('jpegdec', 'jpegdec') self.jpegdec.set_property('max-errors', -1) def create_muxer_elements(self): self.oggmux = Gst.ElementFactory.make('oggmux', 'oggmux') self.mkvmux = Gst.ElementFactory.make('matroskamux', 'mkvmux') self.webmmux = Gst.ElementFactory.make('webmmux', 'webmmux') self.webmmux.set_property('streamable', True) def create_demuxer_elements(self): pass def create_filtering_elements(self): self.scaling = Gst.ElementFactory.make('videoscale', 'scaling') caps = Gst.caps_from_string('video/x-raw, width=(int)640, height=(int)360') self.capsfilter = Gst.ElementFactory.make('capsfilter', 'capsfilter') self.capsfilter.set_property('caps', caps) def create_tee_elements(self): """Create tee elements to divide feeds.""" self.tee_rawvideo = Gst.ElementFactory.make('tee', 'tee_rawvideo') self.tee_videodecoded = Gst.ElementFactory.make('tee', 'tee_videodecoded') self.tee_streamfull = Gst.ElementFactory.make('tee', 'tee_streamfull') self.tee_rawaudio = Gst.ElementFactory.make('tee', 'tee_rawaudio') self.tee_streamaudio = Gst.ElementFactory.make('tee', 'tee_streamaudio') def connect_tee(self, tee_element, input_element, output_element_1, output_element_2,): """Links input and outputs of a given tee element.""" # Find a way to check if the element given are in the pipeline # then pass the result to the 'if' statement. ## argcheck = [True for arg in locals() if arg in 'the_list_of_elements_added'] ## print('[DEBUG] ArgList check: ', argcheck) ## if False not in argcheck if True: input_element.link(tee_element) tee_element.link(output_element_1) tee_element.link(output_element_2) else: print('[ERROR] Couldn\'t link the tee. Element(s) probably not in the pipeline ') def create_queues(self): # For video feed: self.queuev_1 = Gst.ElementFactory.make('queue', 'queuev_1') self.queuev_2 = Gst.ElementFactory.make('queue', 'queuev_2') self.queuev_3 = Gst.ElementFactory.make('queue', 'queuev_3') self.queuev_4 = Gst.ElementFactory.make('queue', 'queuev_4') self.queuev_5 = Gst.ElementFactory.make('queue', 'queuev_5') self.queuev_6 = Gst.ElementFactory.make('queue', 'queuev_6') # For audio feed: self.queuea_1 = Gst.ElementFactory.make('queue', 'queuea_1') self.queuea_2 = Gst.ElementFactory.make('queue', 'queuea_2') self.queuea_3 = Gst.ElementFactory.make('queue', 'queuea_3') self.queuea_4 = Gst.ElementFactory.make('queue', 'queuea_4') self.queuea_5 = Gst.ElementFactory.make('queue', 'queuea_5') # For audio+video muxer: self.queuem_1 = Gst.ElementFactory.make('queue', 'queuem_1') self.queuem_2 = Gst.ElementFactory.make('queue', 'queuem_2') def create_pipeline_elements(self): print('Pipeline creation state: creating elements... ', end='') # Inputs elements: self.create_video_sources() self.create_audio_sources() # Middle elements: self.create_payloader_elements() self.create_depayloader_elements() self.create_encoder_elements() self.create_decoder_elements() self.create_muxer_elements() self.create_filtering_elements() self.create_tee_elements() self.create_queues() # Output elements: self.create_filesink() self.create_streamsink() print('created') def add_elements_to_pipeline(self): print('Pipeline creation state: adding elements... ', end='') # Inputs elements: self.streampipe.add(self.videosrc) self.streampipe.add(self.audiosrc) # Middle elements: self.streampipe.add(self.rtpjpegdepay) self.streampipe.add(self.jpegdec) self.streampipe.add(self.tee_rawvideo) self.streampipe.add(self.mkvmux) self.streampipe.add(self.vorbisenc) self.streampipe.add(self.oggmux) self.streampipe.add(self.scaling) self.streampipe.add(self.capsfilter) self.streampipe.add(self.vp8enc) self.streampipe.add(self.webmmux) self.streampipe.add(self.tee_rawaudio) self.streampipe.add(self.tee_streamaudio) self.streampipe.add(self.tee_videodecoded) self.streampipe.add(self.tee_streamfull) self.streampipe.add(self.queuev_1) self.streampipe.add(self.queuev_2) self.streampipe.add(self.queuev_3) self.streampipe.add(self.queuev_4) self.streampipe.add(self.queuev_5) self.streampipe.add(self.queuev_6) self.streampipe.add(self.queuea_1) self.streampipe.add(self.queuea_2) self.streampipe.add(self.queuea_3) self.streampipe.add(self.queuea_4) self.streampipe.add(self.queuea_5) self.streampipe.add(self.queuem_1) self.streampipe.add(self.queuem_2) # Outputs elements: self.streampipe.add(self.screensink) self.streampipe.add(self.disksink_rawvideo) self.streampipe.add(self.disksink_audio) self.streampipe.add(self.disksink_stream) self.streampipe.add(self.icecastsink_audio) self.streampipe.add(self.icecastsink_stream) print('added') def link_pipeline_elements(self): """Link all elements with static pads.""" print('Pipeline creation state: linking elements... ', end='') # Video feed: self.queuev_1.link(self.rtpjpegdepay) self.connect_tee(self.tee_rawvideo, self.rtpjpegdepay, self.queuev_2, self.jpegdec,) self.queuev_2.link(self.mkvmux) self.mkvmux.link(self.queuev_4) self.queuev_4.link(self.disksink_rawvideo) self.connect_tee(self.tee_videodecoded, self.jpegdec, self.queuev_3, self.scaling,) self.queuev_3.link(self.screensink) # Audio feed: self.audiosrc.link(self.queuea_1) self.queuea_1.link(self.vorbisenc) self.connect_tee(self.tee_rawaudio, self.vorbisenc, self.queuea_2, self.queuea_5,) self.queuea_2.link(self.oggmux) self.connect_tee(self.tee_streamaudio, self.oggmux, self.queuea_3, self.queuea_4,) self.queuea_3.link(self.disksink_audio) self.queuea_4.link(self.icecastsink_audio) self.queuea_5.link(self.webmmux) # Stream (audio+video) feed: self.scaling.link(self.capsfilter) self.capsfilter.link(self.vp8enc) self.vp8enc.link(self.queuev_6) self.queuev_6.link(self.webmmux) self.connect_tee(self.tee_streamfull, self.webmmux, self.queuem_1, self.queuem_2,) self.queuem_1.link(self.disksink_stream) self.queuem_2.link(self.icecastsink_stream) print('linked') def create_gstreamer_pipeline(self): # New empty pipeline: self.streampipe = Gst.Pipeline() # Setting-up: self.create_pipeline_elements() self.add_elements_to_pipeline() self.link_pipeline_elements() self.create_pipeline_callbacks() global bus bus = self.streampipe.get_bus() bus.add_signal_watch() bus.enable_sync_message_emission() # Used to get messages that GStreamer emits. bus.connect("message", self.on_message) print('Pipeline creation state: successfully done.') return self.streampipe def on_message(self, bus, message): t = message.type if t == Gst.MessageType.EOS: self.pipeol.set_state(Gst.State.NULL) self.stream_button.set_label('Stream') elif t == Gst.MessageType.ERROR: err, debug = message.parse_error() print ("Error: %s" % err, debug) self.pipel.set_state(Gst.State.NULL) self.stream_button.set_label('Stream') def stream_play(self): self.streampipe.set_state(Gst.State.PLAYING) def stream_stop(self): self.streampipe.set_state(Gst.State.NULL) def get_stream_state(self): print(self.streampipe.get_state(self)) ## return self.streampipe.get_state() def get_gstreamer_bus(): return bus