From: David Testé Date: Wed, 17 Feb 2016 21:41:04 +0000 (+0100) Subject: New GUI for 2016 edition X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=6fdd41d93c6ac8b9aa08496a77660c8436a4f763;p=libre-streamer.git New GUI for 2016 edition Python implementation using GTK3.0 and Gst1.0 (still in debugging) --- diff --git a/stream_2016/gstpipeline.py b/stream_2016/gstpipeline.py new file mode 100755 index 0000000..d789548 --- /dev/null +++ b/stream_2016/gstpipeline.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3.4 + +from gi.repository import Gst + + +def constructpipeline (self): + + + """Add and link elements in a GStreamer pipeline""" + + # Create the pipelines instance. + self.streampipe = Gst.Pipeline() + self.storepipe_hi = Gst.Pipeline() + self.storepipe_lo = Gst.Pipeline() + + # Define pipeline elements. +## The next line will NOT display the camera's video feed +## self.videosrc = Gst.ElementFactory.make('location', 'rtsp://192.168.48.2:554') + self.videosrc = Gst.ElementFactory.make('videotestsrc', 'source') + + self.queue = Gst.ElementFactory.make('queue') + +## self.oggstreamsink = Gst.ElementFactory.make() +## self.oggdisksink = Gst.ElementFactory.make() + +## self.jpegdisksink = Gst.ElementFactory.make() + + self.screensink = Gst.ElementFactory.make('sink', 'xvimagesink') + +## self.webmdisksink = Gst.ElementFactory.make() +## self.webmstreamsink = Gst.ElementFactory.make() + + # Add the elements to the pipeline. + self.streampipe.add(self.videosrc, + self.queue, + self.screensink,) + + # Link the elements in the pipeline. + +constructpipeline() +streampipe.set_state(Gst.State.PLAYING) \ No newline at end of file diff --git a/stream_2016/gstream_pipeline_by_quidam b/stream_2016/gstream_pipeline_by_quidam new file mode 100644 index 0000000..d0655be --- /dev/null +++ b/stream_2016/gstream_pipeline_by_quidam @@ -0,0 +1,25 @@ +Primary command (need to be enhanced): +-------------------------------------- +One line = one pipeline + +gst-launch-1.0 -e rtspsrc location=rtsp://192.168.48.2:554 latency=100 ! queue ! rtpjpegdepay ! tee name=rawjpeg ! queue ! jpegdec max-errors=-1 ! tee name=rawvideo ! queue ! xvimagesink +rawjpeg. ! queue ! matroskamux name=mux +pulsesrc ! queue ! vorbisenc quality=0.3 ! tee name=oggaudio +pulsesrc ! queue ! flacenc ! queue ! queue ! mux. mux. ! queue ! filesink location=popo +rawvideo. ! videoscale ! video/x-raw, width=640, height=360 ! vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=2 sharpness=7 ! queue ! webmmux name=mux2 +oggaudio. ! queue ! queue ! mux2. mux2. ! queue ! tee name=streamlo ! queue ! filesink location=popo2 +oggaudio. ! queue ! oggmux ! queue ! tee name=streamaudio ! queue ! filesink location=popo4 +streamlo. ! queue ! shout2send ip=live.fsf.org port=80 mount=testlo.ogv password=icecastfsf1 +streamaudio. ! queue ! shout2send ip=live.fsf.org port=80 mount=testaudio.ogv password=icecastfsf1 + +## +## TODO: Investigate double queues and double mux. +## + +Lightened command (to do CPU load benchmarking): +Do changes here and merge it with the primary command +----------------------------------------------------- +gst-launch-1.0 -e rtspsrc location=rtsp://192.168.48.2:554 latency=100 ! queue ! rtpjpegdepay ! queue ! jpegdec max-errors=-1 ! tee name=rawvideo ! queue ! xvimagesink +pulsesrc ! queue ! vorbisenc quality=0.3 ! tee name=oggaudio +rawvideo. ! vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=2 sharpness=7 ! queue ! webmmux name=mux2 +oggaudio. ! queue ! queue ! mux2. mux2. ! queue ! tee name=streamlo ! queue ! filesink location=popo2 diff --git a/stream_2016/libre-streamer.py b/stream_2016/libre-streamer.py new file mode 100755 index 0000000..1ac1bc1 --- /dev/null +++ b/stream_2016/libre-streamer.py @@ -0,0 +1,161 @@ +#!/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é + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TODO list: +# ---------- +# - Create a module for the pipeline construction section to clarify the code +# - Create a module for the network configuration (ifconfig, stream server,etc) +# - Generate a log file during runtime. (e.g. this will let you know if the network configuration +# and the pipeline construction went well (or not)) +# - Add an input source choice for the user (camera on IP or webcam) +# - Add a VU-meter to check if audio feed is emitting signal +# - Investigate this error (at stream launching during prototyping phase): +# (libre-streamer.py:7856): Gdk-ERROR **: The program 'libre-streamer.py' received an X Window System error. +# This probably reflects a bug in the program. +# The error was 'BadIDChoice (invalid resource ID chosen for this connection)'. +# (Details: serial 592 error_code 14 request_code 1 (core protocol) minor_code 0) +# - Add the FSF logo (need to do some pixel art) as an application icon +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import sys + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +from gi.repository import Gst +from gi.repository import GdkX11 +from gi.repository import GstVideo + +##import networkinit +##import gstpipeline + + +class Streamgui(object): + + + def __init__(self): + + self.multimedia_file="" + # Create the global pipeline (might wanna use a general bin instead) + self.pipel = self.constructpipeline() + # Create the GUI + self.win = Gtk.Window() + self.win.set_title("Libre-Streamer") + self.win.connect("delete_event", + lambda w,e: Gtk.main_quit()) + vbox = Gtk.VBox(False, 0) + hbox = Gtk.HBox(False, 0) + self.load_file = Gtk.FileChooserButton("Choose Audio File") + self.stream_button = Gtk.Button("Stream") + self.videowidget = Gtk.DrawingArea() + self.videowidget.set_size_request(600, 400) + self.load_file.connect("selection-changed", self.on_file_selected) + self.stream_button.connect("clicked", self.on_stream_clicked) + + hbox.pack_start(self.stream_button, False, True, 0) + vbox.pack_start(self.load_file, False, True, 0) + vbox.pack_start(self.videowidget, True, True, 0) + vbox.pack_start(hbox, False, True, 0) + self.win.add(vbox) + self.win.set_position(Gtk.WindowPosition.CENTER) + self.win.show_all() + + bus = self.pipel.get_bus() + bus.add_signal_watch() + bus.enable_sync_message_emission() + # Used to get messages that GStreamer emits. + bus.connect("message", self.on_message) + # Used for connecting video to your application. + bus.connect("sync-message::element", self.on_sync_message) + + def constructpipeline (self): + + """Add and link elements in a GStreamer pipeline""" + + # Create the pipelines instance. + self.streampipe = Gst.Pipeline() +## self.storepipe_hi = Gst.Pipeline() +## self.storepipe_lo = Gst.Pipeline() + + # Define pipeline elements. + ## The next line WILL NOT display the camera's video feed + ## self.videosrc = Gst.ElementFactory.make('location', 'rtsp://192.168.48.2:554') + self.videosrc = Gst.ElementFactory.make('videotestsrc', 'source') + self.queue = Gst.ElementFactory.make('queue') + ## self.oggstreamsink = Gst.ElementFactory.make() + ## self.oggdisksink = Gst.ElementFactory.make() + + ## self.jpegdisksink = Gst.ElementFactory.make() + + self.screensink = Gst.ElementFactory.make('xvimagesink', 'rawfeed') + + ## self.webmdisksink = Gst.ElementFactory.make() + ## self.webmstreamsink = Gst.ElementFactory.make() + + # Add the elements to the pipeline. + self.streampipe.add(self.videosrc) + self.streampipe.add(self.queue) + self.streampipe.add(self.screensink) + # Link the elements in the pipeline. + self.videosrc.link(self.queue) + self.queue.link(self.screensink) + + return self.streampipe + + def on_message(self, bus, message): + + t = message.type + if t == Gst.MessageType.EOS: + self.player.set_state(Gst.State.NULL) + elif t == Gst.MessageType.ERROR: + self.player.set_state(Gst.State.NULL) + err, debug = message.parse_error() + print ("Error: %s" % err, debug) + + def on_sync_message(self, bus, message): + + if message.get_structure().get_name() == 'prepare-window-handle': + imagesink = message.src + imagesink.set_property('force-aspect-ratio', True) + imagesink.set_window_handle(self.videowidget.get_property('window').get_xid()) + + + # USE THAT FUNCTION TO GET THE SOURCE CHOICE (ELPHEL OR WEBCAM) + def on_file_selected(self, widget): + + self.multimedia_file = self.load_file.get_filename() + + def on_stream_clicked(self, widget): + + # Put here the script to launch streaming and start recording +## self.streampipe.uri_construct('rtsp', '://192.168.48.2:554') + labelname = self.stream_button.get_label() + if labelname == 'Stream': + self.pipel.set_state(Gst.State.PLAYING) + self.stream_button.set_label('ON AIR') + elif labelname == 'ON AIR': + self.pipel.set_state(Gst.State.NULL) + self.stream_button.set_label('Stream') + + +if __name__ == "__main__": + Gst.init() + Streamgui() + Gtk.main() \ No newline at end of file