diff --git a/.gitignore b/.gitignore index 6594be4..29b7a48 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ images/logo.* python/virtenv videos *.pyc +*.swp diff --git a/ini/.base.ini.swp b/ini/.base.ini.swp deleted file mode 100644 index 924d3bf..0000000 Binary files a/ini/.base.ini.swp and /dev/null differ diff --git a/ini/.test720p.ini.swp b/ini/.test720p.ini.swp deleted file mode 100644 index 3cee7af..0000000 Binary files a/ini/.test720p.ini.swp and /dev/null differ diff --git a/ini/base.ini b/ini/base.ini index 3952b50..c6060b0 100644 --- a/ini/base.ini +++ b/ini/base.ini @@ -78,7 +78,7 @@ vfeed source feed 5 2 vfeed place rect 5 645 2 1280 720 0 0 0 0.492 0.492 1.0 vfeed add 6 SmallCam1 -vfeed source feed 6 2 +vfeed source feed 6 3 vfeed place rect 6 645 363 1280 720 0 0 0 0.492 0.492 1.0 diff --git a/python/camerafeed.py b/python/camerafeed.py new file mode 100644 index 0000000..7ef5676 --- /dev/null +++ b/python/camerafeed.py @@ -0,0 +1,79 @@ +#!/bin/env python2 +import os +import threading +from time import sleep + +import pygst +pygst.require('0.10') +import gst + +from config import * + +WIDTH = 1280 +HEIGHT = 720 +FRAMERATE = 25 +SHM_SIZE = 10000000 + +class CameraFeed(object): + def __init__(self, feed_pipe, camera_ip): + self._feed_pipe = feed_pipe + self._camera_ip = camera_ip + self._running = False + self._pipeline = None + self._thead = None + + def start(self): + if self._running: + return + + if not os.path.exists(MIXER_PIPE): + print '[%s] not starting because mixer is not running (pipe is missing)' % self._feed_pipe + return + + if os.path.exists(self._feed_pipe): + print '[%s] not starting because feed pipe already exists' % self._feed_pipe + return + + print '[%s] is starting' % self._feed_pipe + self._running = True + self._thread = threading.Thread(target=self._run) + self._thread.start() + + + def is_running(self): + return self._running + + + def stop(self): + + if not self._running: + return + + if self._pipeline <> None: + print "[%s] pipeline stopped" % self._feed_pipe + self._pipeline.set_state(gst.STATE_NULL) + + if self._thread <> None: + print "[%s] waiting for thread to terminate" % self._feed_pipe + self._thread.join(2.0) + + + def _run(self): + src = FEED_SOURCE % {'ip': self._camera_ip} + mixer_format = MIXER_FORMAT % {'width' : MIXER_WIDTH, 'height' : MIXER_HEIGHT, 'framerate' : MIXER_FRAMERATE} + sink = FEED_SINK % {'feed_pipe' : self._feed_pipe, 'shm_size' : SHM_SIZE} + + self._pipeline = gst.parse_launch('%s ! %s ! %s ! %s' % (src, SCALE, mixer_format, sink)) + + self._pipeline.set_state(gst.STATE_PLAYING) + print "[%s] is playing" % self._feed_pipe + + bus = self._pipeline.get_bus() + msg = bus.timed_pop_filtered(gst.CLOCK_TIME_NONE, gst.MESSAGE_ERROR | gst.MESSAGE_EOS) + print "[%s] %s" % (self._feed_pipe, msg.parse_error()[1]) + + self._pipeline.set_state(gst.STATE_NULL) + + self._running = False + + print "[%s] has stopped" % self._feed_pipe diff --git a/python/config.py b/python/config.py new file mode 100644 index 0000000..c51d386 --- /dev/null +++ b/python/config.py @@ -0,0 +1,23 @@ +#!/bin/env python2 + +CAMERA_FEEDS = { + '/tmp/feed1' : '192.168.1.100', + '/tmp/feed2' : '192.168.1.101', + '/tmp/feed3' : '192.168.1.102', +} + +MIXER_PIPE = '/tmp/mixer1' + +MIXER_WIDTH = 1280 +MIXER_HEIGHT = 720 +MIXER_FRAMERATE = 25 +SHM_SIZE = 10000000 + +FEED_SOURCE = 'rtspsrc location=rtsp://%(ip)s ! rtph264depay ! h264parse ! ffdec_h264' +MIXER_FORMAT = 'video/x-raw-rgb, bpp=(int)32, endianness=(int)4321, format=(fourcc)BGRA,'\ + + ' red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216,'\ + + ' width=(int)%(width)d, height=(int)%(height)d, framerate=(fraction)%(framerate)d/1,'\ + + 'pixel-aspect-ratio=(fraction)1/1, interlaced=(boolean)false' +SCALE = 'ffmpegcolorspace ! videorate ! videoscale ! ffmpegcolorspace' +FEED_SINK = 'shmsink socket-path=%(feed_pipe)s shm-size=%(shm_size)d wait-for-connection=0' + diff --git a/python/runfeeds.py b/python/runfeeds.py new file mode 100644 index 0000000..057f6e9 --- /dev/null +++ b/python/runfeeds.py @@ -0,0 +1,38 @@ +#!/bin/env python2 +import os +import sys +import signal +import time +import gobject + +from camerafeed import CameraFeed + +from config import * + +feeds = [] + +def teardown(): + print "[main] Stopping all remaining feeds" + for feed in feeds: + feed.stop() + +def handle_sigint(signum, frame): + print "[main] caught sigint" + teardown() + sys.exit(0) + + +gobject.threads_init() +signal.signal(signal.SIGINT, handle_sigint) + +for pipe, ip in CAMERA_FEEDS.items(): + feeds.append(CameraFeed(pipe, ip)) + +while os.path.exists(MIXER_PIPE): + for feed in feeds: + if not feed.is_running(): + feed.start() + + time.sleep(5) + +teardown()