Created
September 10, 2014 12:20
-
-
Save spscream/4df7195a50b0e35ba63e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import gi | |
import os | |
from datetime import datetime | |
gi.require_version('Gst', '1.0') | |
from gi.repository import GObject, Gst, Gtk | |
from gi.repository import GdkX11, GstVideo | |
from gi.repository.Gtk import Window, VBox, HBox, DrawingArea, ToggleButton, Button, Statusbar | |
GObject.threads_init() | |
Gst.init(None) | |
""" | |
gst-launch-0.10 -ev \ | |
udpsrc uri="udp://192.168.100.100:20000" ! tee name=source0 \ | |
source0. ! queue ! tsdemux name=demuxer \ | |
demuxer. ! "audio/mpeg" ! queue max-size-buffers=1200 max-size-time=0 max-size-bytes=0 ! tee name=audio0 \ | |
demuxer. ! "video/x-h264" ! queue max-size-buffers=1200 max-size-time=0 max-size-bytes=0 ! tee name=video0 \ | |
qtmux name=mp4muxer moov-recovery-file=/home/dvruser/gstreamer/records/cam0_rec_$DATE.moov dts-method=0 \ | |
video0. ! queue ! h264parse ! mp4muxer. \ | |
audio0. ! queue ! mpegaudioparse ! mp4muxer. \ | |
mp4muxer. ! filesink location=/home/dvruser/gstreamer/records/cam0_rec_$DATE.mp4 \ | |
video0. ! queue ! h264parse ! ffdec_h264 ! ffmpegcolorspace ! deinterlace ! xvimagesink \ | |
#audio0. ! queue ! mpegaudioparse ! mad ! pulsesink device=$ADEVICE \ | |
""" | |
SOURCE="rtmp://192.168.100.100:1935/cameras/cam0" | |
#SOURCE="rtmp://itv08.digizuite.dk/tv2b/ch1" | |
class YayMan: | |
def __init__(self): | |
self.make_gui() | |
self.src_bin = Gst.Bin.new("sourcebin") | |
self.source = Gst.ElementFactory.make("rtmpsrc", "rtmpsource") | |
self.source.set_property("location", SOURCE) | |
self.demux = Gst.ElementFactory.make("flvdemux", "demux") | |
self.demux.connect("pad-added", self.demuxer_callback) | |
self.atee = Gst.ElementFactory.make("tee", "atee") | |
self.vtee = Gst.ElementFactory.make("tee", "vtee") | |
# Audio | |
self.vq = Gst.ElementFactory.make("queue", "vq") | |
self.h264parse = Gst.ElementFactory.make("h264parse", "h264parse") | |
self.ffdec_h264 = Gst.ElementFactory.make("avdec_h264", "avdec_h264") | |
# Video | |
self.aq = Gst.ElementFactory.make("queue", "aq") | |
self.mpegaudioparse = Gst.ElementFactory.make("mpegaudioparse", "mpparse") | |
self.mad = Gst.ElementFactory.make("mad", "mad") | |
# Add to src_bin | |
self.src_bin.add(self.source) | |
self.src_bin.add(self.demux) | |
self.src_bin.add(self.atee) | |
self.src_bin.add(self.vtee) | |
self.src_bin.add(self.vq) | |
self.src_bin.add(self.h264parse) | |
self.src_bin.add(self.ffdec_h264) | |
self.src_bin.add(self.aq) | |
self.src_bin.add(self.mpegaudioparse) | |
self.src_bin.add(self.mad) | |
self.source.link(self.demux) | |
self.vtee.link(self.vq) | |
self.atee.link(self.aq) | |
self.vq.link(self.h264parse) | |
self.h264parse.link(self.ffdec_h264) | |
self.aq.link(self.mpegaudioparse) | |
self.mpegaudioparse.link(self.mad) | |
src_v_pad = Gst.GhostPad.new("video", self.ffdec_h264.get_static_pad("src")) | |
src_a_pad = Gst.GhostPad.new("audio", self.mad.get_static_pad("src")) | |
self.src_bin.add_pad(src_v_pad) | |
self.src_bin.add_pad(src_a_pad) | |
self.record = Gst.ElementFactory.make("camerabin","camera") | |
self.record_source = Gst.ElementFactory.make("rtmpsrc","recordsrc") | |
self.record_source.set_property("location", "rtmp://192.168.100.100:1935/cameras/cam0") | |
self.src_wrap = Gst.ElementFactory.make("wrappercamerabinsrc","wrap") | |
self.src_wrap.set_property("video-source", self.src_bin) | |
src_wrap_a_pad = Gst.GhostPad.new("audio", self.src_bin.get_static_pad("audio")) | |
self.src_wrap.add_pad(src_wrap_a_pad) | |
self.record.set_property("mode", 2) | |
self.record.set_property("location", self.record_location()) | |
self.record.set_property("camera-source", self.src_wrap) | |
#self.record.set_property("audio-source", self.src_bin) | |
self.bus = self.record.get_bus() | |
self.bus.add_signal_watch() | |
self.bus.connect('message::error', self.on_error) | |
self.bus.enable_sync_message_emission() | |
self.bus.connect('sync-message::element', self.on_sync_message) | |
def demuxer_callback(self, demuxer, pad): | |
print (pad.get_property("template").name_template) | |
if pad.get_property("template").name_template == "audio": | |
atee_pad = self.atee.get_static_pad("sink") | |
pad.link(atee_pad) | |
elif pad.get_property("template").name_template == "video": | |
vtee_pad = self.vtee.get_static_pad("sink") | |
pad.link(vtee_pad) | |
def record_location(self): | |
today = datetime.today() | |
directory = "/home/dvruser/gstreamer/records/"+today.strftime("%d-%m-%y") | |
if not os.path.exists(directory): | |
os.makedirs(directory) | |
return directory + today.strftime("/%H:%M:%S") + "_rus_%d.flv" | |
def make_gui(self): | |
self.window = Window() | |
self.window.connect('destroy', self.quit) | |
self.window.set_default_size(640, 450) | |
self.vbox = VBox() | |
self.video_area = DrawingArea() | |
self.controls_box = HBox() | |
self.record_button = ToggleButton(label="Запись") | |
self.record_button.connect("toggled", self.toggle_record_cb) | |
self.translator_button = ToggleButton(label="Запись переводчика") | |
self.translator_button.connect("toggled", self.toggle_translator_cb) | |
self.statusbar = Statusbar() | |
self.vbox.pack_start(self.video_area, True, True, 0) | |
self.controls_box.pack_start(self.record_button, False, False, 0) | |
self.controls_box.pack_start(self.translator_button, False, False, 0) | |
self.controls_box.pack_start(self.statusbar, True, True, 0) | |
self.vbox.pack_start(self.controls_box, False, False, 0) | |
self.window.add(self.vbox) | |
def run(self): | |
self.window.show_all() | |
self.xid = self.video_area.get_property('window').get_xid() | |
self.record.set_state(Gst.State.PLAYING) | |
def quit(self, window): | |
self.record.set_state(Gst.State.NULL) | |
Gtk.main_quit() | |
def on_sync_message(self, bus, msg): | |
if msg.get_structure().get_name() == 'prepare-window-handle': | |
print('prepare-window-handle') | |
msg.src.set_property('force-aspect-ratio', True) | |
msg.src.set_window_handle(self.xid) | |
def on_error(self, bus, msg): | |
print('on_error():', msg.parse_error()) | |
def toggle_record_cb(self, widget, data=None): | |
if (widget.get_active()): | |
self.record.set_property("location", self.record_location()) | |
self.record.emit("start-capture") | |
else: | |
self.record.emit("stop-capture") | |
print (widget.get_active()) | |
def toggle_translator_cb(self, widget, data=None): | |
print (widget.get_active()) | |
if __name__ == "__main__": | |
yayman = YayMan() | |
yayman.run() | |
try: | |
Gtk.main() | |
except KeyboardInterrupt: | |
print("Ctrl^C. Exiting...") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment