From 3984ad2214058c27b2dd74d2fd029e0a627e36a5 Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Sat, 13 Jun 2015 21:56:22 +0200 Subject: [PATCH] Python gstreamer pipeline works --- .gitignore | 1 + ini/.base.ini.swp | Bin 12288 -> 0 bytes ini/.test720p.ini.swp | Bin 12288 -> 0 bytes ini/base.ini | 2 +- python/camerafeed.py | 79 ++++++++++++++++++++++++++++++++++++++++++ python/config.py | 23 ++++++++++++ python/runfeeds.py | 38 ++++++++++++++++++++ 7 files changed, 142 insertions(+), 1 deletion(-) delete mode 100644 ini/.base.ini.swp delete mode 100644 ini/.test720p.ini.swp create mode 100644 python/camerafeed.py create mode 100644 python/config.py create mode 100644 python/runfeeds.py 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 924d3bf79d236087200bcecc9c5836875742dae3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 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 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()