#!/usr/bin/python3 import time import threading import os import stat import sys import gi import paho.mqtt.client as mqtt gi.require_version('Gst', '1.0') gi.require_version('GstNet', '1.0') from gi.repository import Gst, GstNet WIDTH = 1280 HEIGHT = 720 SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 zoom = 1 not_exited = True # def bus_call(bus, msg, *args): # if msg.type == Gst.MessageType.EOS: # print("End-of-stream") # loop.quit() # return # elif msg.type == Gst.MessageType.ERROR: # print("GST ERROR", msg.parse_error()) # loop.quit() # return # return True def set_preview(val): if val == 0: videosrc.set_property("preview-x", SCREEN_WIDTH) videosrc.set_property("preview-y", SCREEN_HEIGHT) else: videosrc.set_property("preview-x", 0) videosrc.set_property("preview-y", 0) def set_zoom(target): global zoom if target < zoom: direction = -1 else: direction = 1 target = min(target, 1) target = max(target, 0.40) while abs(target-zoom) > 0.01: # fuck IEEE floats zoom = zoom + direction*0.015 zoom = min(zoom, 1) zoom = max(zoom, 0.4) videosrc.set_property("roi-x", (1-zoom)/2) videosrc.set_property("roi-y", (1-zoom)/2) videosrc.set_property("roi-w", zoom) videosrc.set_property("roi-h", zoom) time.sleep(0.03) # The callback for when the client receives a CONNACK response from the server. def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) # Subscribing in on_connect() means that if we lose the connection and # reconnect then subscriptions will be renewed. client.subscribe("video/cam1/#") # The callback for when a PUBLISH message is received from the server. def on_message(client, userdata, msg): global not_exited print(msg.topic+" "+str(msg.payload)) if msg.topic == "video/cam1/preview": set_preview(int(msg.payload)) elif msg.topic == "video/cam1/zoom": set_zoom(float(msg.payload)) elif msg.topic == "video/cam1/restart": print("Restarting!") not_exited = False client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect("192.168.2.123", 1883, 60) if __name__ == "__main__": if 'LD_LIBRARY_PATH' not in os.environ: os.environ['LD_LIBRARY_PATH'] = '/usr/local/lib' os.execv(sys.argv[0], sys.argv) # initialization Gst.init(None) videocodec = "video/x-h264, width=%d, height=%d, framerate=25/1, profile=high ! h264parse" % (WIDTH, HEIGHT) p = "rpicamsrc sensor-mode=4 bitrate=0 quantisation-parameter=12 do-timestamp=true keyframe-interval=5 name=src ! "+videocodec+" ! matroskamux streamable=true ! tcpserversink host=0.0.0.0 port=5000 sync-method=next-keyframe blocksize=16384" print(p) pipeline = Gst.parse_launch(p) if pipeline is None: print("Failed to create pipeline") sys.exit(0) clock = GstNet.NetClientClock.new('CamVoctoClock', '192.168.2.123', 9998, 0) # FIXME: add clock support # print("Waiting for clock sync") # clock.wait_for_sync(Gst.CLOCK_TIME_NONE) # clock.do_wait(Gst.CLOCK_TIME_NONE) # print("Clock synced") pipeline.set_start_time(Gst.CLOCK_TIME_NONE) if clock is not None: pass # pipeline.use_clock(clock) videosrc = pipeline.get_by_name("src") videosrc.set_property("preview", 1) videosrc.set_property("preview-w", SCREEN_WIDTH) videosrc.set_property("preview-h", SCREEN_HEIGHT) videosrc.set_property("fullscreen", False) # videosrc.set_property("bitrate", 25000000) videosrc.set_property("rotation", 180) set_preview(0) pipeline.set_state(Gst.State.PLAYING) t = threading.Thread(target=client.loop_forever, daemon=True) t.start() counter = 0 while not_exited: time.sleep(1) counter += 1 if counter >= 10: client.publish("video/heartbeat", "cam1") counter = 0 pipeline.set_state(Gst.State.NULL) print("Pipeline dead. Bye")