Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- import gi
- gi.require_version('Gst', '1.0')
- from gi.repository import GObject, Gst, Gtk, Gdk
- import socket
- import sys
- import _thread as thread
- from time import sleep
- # Needed for window.get_xid(), xvimagesink.set_window_handle(), respectively:
- from gi.repository import GdkX11, GstVideo
- GObject.threads_init()
- Gst.init(None)
- # Connect the socket to the port where the server is listening
- server_address = '/tmp/uds_dnvff'
- window_width = 800
- window_height = 480
- video_width = 320
- video_height = 240
- class Buttons:
- blink_left = 1
- blink_right = 1
- dead_mans1 = 1
- dead_mans2 = 1
- horn = 1
- joy_sw = 1
- lights_far = 1
- lights_near = 1
- phone = 1
- wiper = 1
- joy_y = 0
- volume = 0
- fans = 0
- class Webcam:
- def __init__(self):
- self.window = Gtk.Window()
- self.window.set_title("Hello")
- self.window.connect('destroy', self.quit)
- self.window.set_default_size(window_width, window_height)
- self.geometry = Gdk.Geometry()
- self.geometry.max_width = window_width
- self.geometry.max_height = window_height
- self.geometry.min_width = 0
- self.geometry.min_height = 0
- self.hints = Gdk.WindowHints(Gdk.WindowHints.MAX_SIZE)
- self.window.set_geometry_hints(self.window,
- self.geometry,
- self.hints)
- self.window.set_position(Gtk.WindowPosition.CENTER)
- self.window.fullscreen()
- self.drawingarea = Gtk.DrawingArea()
- #self.drawingarea.set_size_request(video_width, video_height)
- self.buttons = Buttons()
- self.counter = 0
- self.outer_grid = Gtk.Grid()
- self.outer_grid.set_column_spacing(5)
- self.outer_grid.set_row_spacing(5)
- self.window.add(self.outer_grid)
- number_of_buttons = 5
- button_height = int((480 - (5*(number_of_buttons-1)))/number_of_buttons)
- button_width = 80
- # stuff that goes in outer grid: (MAIN MENU)
- info_button = Gtk.Button(label="Info")
- info_button.set_size_request(button_width, button_height)
- info_button.connect("clicked", self.info_button_on_click)
- video_button = Gtk.Button(label="Video")
- video_button.set_size_request(button_width, button_height)
- video_button.connect("clicked", self.video_button_on_click)
- map_button = Gtk.Button(label="Map")
- map_button.set_size_request(button_width, button_height)
- #video_button.connect("clicked", self.map_button_on_click)
- phone_button = Gtk.Button(label="Extra")
- phone_button.set_size_request(button_width, button_height)
- phone_button.connect("clicked", self.phone_button_on_click)
- race_button = Gtk.Button(label="Race")
- race_button.set_size_request(button_width, button_height)
- race_button.connect("clicked", self.race_button_on_click)
- self.race_grid = Gtk.Grid()
- self.video_grid = Gtk.Grid()
- self.map_grid = Gtk.Grid()
- self.phone_grid = Gtk.Grid()
- self.info_grid = Gtk.Grid()
- ######################################## info grid ##############################################
- self.info_grid.set_column_spacing(5)
- self.info_grid.set_row_spacing(5)
- info_header = Gtk.Label()
- info_header.set_markup('<big>Information/diagnostics</big>')
- self.button_blink_label = Gtk.Label('Blink: -')
- self.button_dead_label = Gtk.Label('Dead-mans: -')
- self.button_horn_label = Gtk.Label('Horn: -')
- self.button_joy_sw_label = Gtk.Label('Joy sw: -')
- self.button_lights_label = Gtk.Label('Lights: -')
- self.button_phone_label = Gtk.Label('Phone: -')
- self.button_wiper_label = Gtk.Label('Wiper: -')
- self.button_volume_label = Gtk.Label('Volume: -')
- self.button_fans_label = Gtk.Label('Fans: -')
- self.button_joy_y_label = Gtk.Label('Joystick: -')
- self.info_grid.attach(info_header, 0, 0, 1, 1)
- self.info_grid.attach(self.button_blink_label, 0, 1, 1, 1)
- self.info_grid.attach(self.button_dead_label, 0, 2, 1, 1)
- self.info_grid.attach(self.button_horn_label, 0, 3, 1, 1)
- self.info_grid.attach(self.button_joy_sw_label, 0, 4, 1, 1)
- self.info_grid.attach(self.button_lights_label, 0, 5, 1, 1)
- self.info_grid.attach(self.button_phone_label, 0, 6, 1, 1)
- self.info_grid.attach(self.button_wiper_label, 0, 7, 1, 1)
- self.info_grid.attach(self.button_volume_label, 0, 8, 1, 1)
- self.info_grid.attach(self.button_fans_label, 0, 9, 1, 1)
- self.info_grid.attach(self.button_joy_y_label, 0, 10, 1, 1)
- ######################################## race grid ##############################################
- race_header = Gtk.Label()
- race_header.set_text('race')
- self.race_grid.attach(race_header, 0,0,1,1)
- self.race_grid.attach(self.drawingarea, 1, 0, 1, 1)
- self.drawingarea.set_size_request(video_width, video_height)
- #button4 = Gtk.Button(label="Button 4")
- #button5 = Gtk.Button(label="Button 5")
- #button6 = Gtk.Button(label="Button 6")
- #grid.add(button1)
- #put stuff in outer grid:
- self.outer_grid.attach(race_button, 0, 0, 1, 1)
- self.outer_grid.attach(video_button, 0, 1, 1, 1)
- self.outer_grid.attach(map_button, 0, 2, 1, 1)
- self.outer_grid.attach(phone_button, 0, 3, 1, 1)
- self.outer_grid.attach(info_button, 0, 4, 1, 1)
- self.outer_grid.attach(self.race_grid, 1, 0, 1, number_of_buttons)
- #grid.insert_row(1)
- #grid.attach(button2, 0, 2, 2, 2)
- #grid.attach(button3, 0, 4, 2, 2)
- #grid.attach(button4, 0, 6, 2, 2)
- #grid.attach(button5, 0, 8, 2, 2)
- #grid.attach_next_to(button4, button3, Gtk.PositionType.RIGHT, 2, 1)
- #grid.attach(self.drawingarea, 1, 2, 1, 1)
- #grid.attach_next_to(button6, button5, Gtk.PositionType.RIGHT, 1, 1)
- # Create GStreamer pipeline
- self.pipeline = Gst.Pipeline()
- #################################### local stuff: #############################################################
- #source:
- self.rpi_cam_src = Gst.ElementFactory.make('rpicamsrc', None)
- self.rpi_cam_src.set_property('bitrate', 1000000)
- self.rpi_cam_src.set_property('preview', False)
- self.rpi_cam_src.set_property('image-effect', 'none')
- #caps
- gst_caps = Gst.caps_from_string('video/x-h264,width=' + str(video_width) + ',height=' + str(video_height))
- #capsfilter
- gst_capsfilter = Gst.ElementFactory.make('capsfilter', None)
- gst_capsfilter.set_property('caps', gst_caps)
- #decodebin
- gst_decodebin = Gst.ElementFactory.make('decodebin', None)
- #queue
- gst_queue_local = Gst.ElementFactory.make('queue', None)
- self.gst_queue_local_2 = Gst.ElementFactory.make('queue', None)
- #videoconvert
- gst_videoconvert = Gst.ElementFactory.make('videoconvert', None)
- #sink
- gst_localsink = Gst.ElementFactory.make("ximagesink", None)
- ####################################################################################################################
- #gst-launch-1.0 rpicamsrc bitrate=1000000 ! video/x-h264,width=640,height=480! h264parse ! flvmux ! rtmpsink location='rtmp://live.twitch.tv/app/'
- ############################################## udp stuff ###########################################################
- #tee (split)
- gst_tee = Gst.ElementFactory.make('tee', None)
- #udp queue
- gst_queue_udp = Gst.ElementFactory.make('queue', None)
- #h264parser
- gst_h264parse = Gst.ElementFactory.make('h264parse', None)
- #flvmux
- gst_flvmux = Gst.ElementFactory.make('flvmux', None)
- #rtmpsink
- gst_rtmpsink = Gst.ElementFactory.make('rtmpsink', None)
- temp_file = open('twitch.key', 'r')
- twitch_key = temp_file.readline().rstrip()
- print(twitch_key)
- temp_file.close()
- gst_rtmpsink.set_property('location', 'rtmp://live.twitch.tv/app/' + twitch_key)
- self.pipeline.add(self.rpi_cam_src)
- self.pipeline.add(gst_capsfilter)
- self.pipeline.add(gst_tee)
- self.pipeline.add(gst_queue_local)
- self.pipeline.add(gst_decodebin)
- self.pipeline.add(self.gst_queue_local_2)
- self.pipeline.add(gst_videoconvert)
- self.pipeline.add(gst_localsink)
- self.pipeline.add(gst_queue_udp)
- self.pipeline.add(gst_h264parse)
- self.pipeline.add(gst_flvmux)
- self.pipeline.add(gst_rtmpsink)
- #link local stuff:
- print('linking..')
- print(self.rpi_cam_src.link(gst_capsfilter))
- print(gst_capsfilter.link(gst_tee))
- gst_tee_pad1 = gst_tee.get_request_pad('src_%u')
- print(gst_tee_pad1.link(gst_queue_local.get_static_pad('sink')))
- #print(gst_tee.link(gst_queue_local))
- print(gst_queue_local.link(gst_decodebin))
- #print(gst_decodebin.link(gst_queue_local_2)) # dont link it here, do it with a callback:
- gst_decodebin.connect("pad-added", self.decodebin_pad_added)
- print(self.gst_queue_local_2.link(gst_videoconvert))
- print(gst_videoconvert.link(gst_localsink))
- #link udp stuff:
- gst_tee_pad2 = gst_tee.get_request_pad('src_%u')
- print(gst_tee_pad2.link(gst_queue_udp.get_static_pad('sink')))
- #print(gst_tee.link(gst_queue_udp))
- print(gst_queue_udp.link(gst_h264parse))
- print(gst_h264parse.link(gst_flvmux))
- print(gst_flvmux.link(gst_rtmpsink))
- self.video_playing = False
- self.bus = self.pipeline.get_bus()
- self.bus.add_signal_watch()
- self.bus.connect('message::error', self.on_error)
- # This is needed to make the video output in our DrawingArea:
- self.bus.enable_sync_message_emission()
- self.bus.connect('sync-message::element', self.on_sync_message)
- self.ximage_sink = None
- ################################################################## SOCKET STUFF ########################################################################
- self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- try:
- thread.start_new_thread( self.update_button_info, () )
- thread.start_new_thread( self.listen_on_TCP, () )
- except Exception as inst:
- print(type(inst))
- def decodebin_pad_added(self, decodebin, pad):
- print('linking decodebin')
- pad.link(self.gst_queue_local_2.get_static_pad('sink'))
- def info_button_on_click(self, button):
- for wid in self.outer_grid.get_children():
- if wid.get_name() == 'GtkGrid':
- print('found grid. removing')
- self.outer_grid.remove(wid)
- if self.video_playing:
- self.pipeline.set_state(Gst.State.NULL)
- self.rpi_cam_src.set_property('preview', False)
- self.pipeline.set_state(Gst.State.PLAYING)
- self.video_playing = False
- self.outer_grid.attach(self.info_grid, 1, 0, 1, 5)
- self.window.show_all()
- def video_button_on_click(self, button):
- #self.rpi_cam_src.set_property('image-effect', 'cartoon')
- if not self.video_playing:
- print('attempting to go to fullscreen')
- print(self.pipeline.set_state(Gst.State.READY))
- print(self.rpi_cam_src.set_property('preview', True))
- print(self.pipeline.set_state(Gst.State.PLAYING))
- self.video_playing = True
- #video_pipeline = 'rpicamsrc bitrate=1000000 preview=false ! video/x-h264,width=' + str(video_width) + ',height=' + str(video_height) +' ! decodebin ! queue ! videoconvert ! autovideosink'
- #video_pipeline = 'v4l2src ! autovideosink'
- #video_pipeline = 'rpicamsrc bitrate=1000000 ! decodebin ! queue ! videoconvert ! autovideosink'
- #print ('pipeline :' + video_pipeline)
- #self.pipeline = Gst.parse_launch(video_pipeline)
- # Create bus to get events from GStreamer pipeline
- pass
- def phone_button_on_click(self, button):
- #wiringpi.digitalWrite(7, 0)
- sys.exit(1)
- pass
- def race_button_on_click(self, button):
- #wiringpi.digitalWrite(7, 0)
- for wid in self.outer_grid.get_children():
- if wid.get_name() == 'GtkGrid':
- print('found grid. removing')
- self.outer_grid.remove(wid)
- if self.video_playing:
- self.pipeline.set_state(Gst.State.READY)
- self.rpi_cam_src.set_property('preview', False)
- self.pipeline.set_state(Gst.State.PLAYING)
- self.video_playing = False
- #if self.video_playing:
- # self.pipeline.set_state(Gst.State.PAUSED)
- self.outer_grid.attach(self.race_grid, 1, 0, 1, 5)
- self.window.show_all()
- self.xid = self.drawingarea.get_property('window').get_xid()
- print (self.xid)
- self.ximage_sink.set_window_handle(self.xid)
- def update_button_info(self):
- print('starting update')
- while 1:
- #print('woop woop')
- self.button_joy_y_label.set_text('Joystick: %d' % (self.buttons.joy_y))
- if self.buttons.blink_left == 0:
- self.button_blink_label.set_text('Blink: %s' % ('Left'))
- elif self.buttons.blink_right == 0:
- self.button_blink_label.set_text('Blink: %s' % ('Right'))
- else:
- self.button_blink_label.set_text('Blink: %s' % ('Off'))
- if self.buttons.dead_mans1 == 0 or self.buttons.dead_mans2 == 0:
- self.button_dead_label.set_text('Dead-mans: %s' % ('Ok'))
- else:
- self.button_dead_label.set_text('Dead-mans: %s' % ('NOT Ok'))
- if self.buttons.horn == 0:
- self.button_horn_label.set_text('Horn: %s' % ('On'))
- else:
- self.button_horn_label.set_text('Horn: %s' % ('Off'))
- if self.buttons.horn == 0:
- self.button_joy_sw_label.set_text('Joy sw: %s' % ('On'))
- else:
- self.button_joy_sw_label.set_text('Joy sw: %s' % ('Off'))
- if self.buttons.lights_far == 0:
- self.button_lights_label.set_text('Lights: %s' % ('Far'))
- elif self.buttons.lights_near == 0:
- self.button_lights_label.set_text('Lights: %s' % ('Near'))
- else:
- self.button_lights_label.set_text('Lights: %s' % ('Off'))
- self.button_phone_label.set_text('Phone: %d' % (self.buttons.phone))
- self.button_wiper_label.set_text('Wiper: %d' % (self.buttons.wiper))
- self.button_volume_label.set_text('Volume: %d' % (self.buttons.volume))
- self.button_fans_label.set_text('Fans: %d' % (self.buttons.fans))
- self.button_joy_y_label.set_text('Joystick: %d' % (self.buttons.joy_y))
- #self.window.show_all()
- sleep(0.1) # sleep 100 ms
- def parse_data(self, data):
- #print('parsing')
- if len(data)<13:
- print('too short')
- return
- if data[0] == 254 and data[1] == 1 and data[2] == 254 and data[11] == 255:
- self.buttons.blink_left = (data[3] & (1<<7)) >> 7
- self.buttons.blink_right = (data[3] & (1<<6)) >> 6
- self.buttons.dead_mans1 = (data[3] & (1<<5)) >> 5
- self.buttons.dead_mans2 = (data[3] & (1<<4)) >> 4
- self.buttons.horn = (data[3] & (1<<3)) >> 3
- self.buttons.joy_sw = (data[3] & (1<<2)) >> 2
- self.buttons.lights_far = (data[3] & (1<<1)) >> 1
- self.buttons.lights_near = (data[3] & (1<<0)) >> 0
- self.buttons.phone = (data[4] & (1<<7)) >> 7
- self.buttons.wiper = (data[4] & (1<<6)) >> 6
- self.buttons.joy_y = (data[5] << 2)
- self.buttons.joy_y = self.buttons.joy_y | (data[6])
- self.buttons.volume = (data[7] << 2)
- self.buttons.volume = self.buttons.volume | (data[8])
- self.buttons.fans = (data[9] << 2)
- self.buttons.fans = self.buttons.fans | (data[10])
- #print('updated buttons')
- #self.update_button_info()
- def run(self):
- 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.
- #self.xid = self.drawingarea.get_property('window').get_xid()
- #print (self.xid)
- #self.pipeline.set_state(Gst.State.PLAYING)
- #Gdk.threads_init()
- self.xid = self.drawingarea.get_property('window').get_xid()
- print (self.xid)
- print(self.pipeline.set_state(Gst.State.PLAYING))
- Gtk.main()
- def quit(self, window):
- self.pipeline.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)
- self.ximage_sink = msg.src
- def on_error(self, bus, msg):
- print('on_error():', msg.parse_error())
- def listen_on_TCP(self):
- while True:
- # Create a UDS socket
- try:
- self.sock.connect(server_address)
- except socket.error as msg:
- #print(msg)
- sleep(10)
- continue
- #try again in 10 seconds
- print('Listening..')
- while True:
- try:
- data = self.sock.recv(16)
- if data:
- #print(data[1])
- self.parse_data(data)
- #self.sock.send(data)
- else:
- self.sock.close()
- break
- except:
- print('something went wrong. closing socket')
- print ('Unexpected error:')
- print(sys.exc_info()[0])
- self.sock.close()
- break
- webcam = Webcam()
- webcam.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement