integrate camera

This commit is contained in:
petrucci4prez 2017-05-30 01:43:09 -04:00
parent 9d49a0ce06
commit 6f91aa0465
2 changed files with 51 additions and 43 deletions

View File

@ -12,6 +12,7 @@ from listeners import KeypadListener, PipeListener
from blinkenLights import Blinkenlights from blinkenLights import Blinkenlights
from soundLib import SoundLib from soundLib import SoundLib
from webInterface import initWebInterface from webInterface import initWebInterface
from stream import initCamera
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -133,6 +134,8 @@ class StateMachine:
self.LED = Blinkenlights(17) self.LED = Blinkenlights(17)
initCamera()
def action(): def action():
if self.currentState == self.states.armed: if self.currentState == self.states.armed:
self.selectState(SIGNALS.TRIGGER) self.selectState(SIGNALS.TRIGGER)

View File

@ -9,10 +9,14 @@
# - will not require SIGINT (this entire program won't understand them anyways) # - will not require SIGINT (this entire program won't understand them anyways)
# - no tags or TOCs # - no tags or TOCs
from auxilary import async from auxilary import async, waitForPath
from threading import Thread from threading import Thread
import gi, time import gi, time, logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
gi.require_version('Gst', '1.0') gi.require_version('Gst', '1.0')
gi.require_version('GObject', '2.0') gi.require_version('GObject', '2.0')
@ -21,18 +25,18 @@ from gi.repository import Gst, GObject
class GstException(Exception): class GstException(Exception):
pass pass
def gstPrintMsg(pName, frmt, *args, sName=None): def gstPrintMsg(pName, frmt, *args, level=logging.DEBUG, sName=None):
if sName: if sName:
print('[{}] [{}] '.format(pName, sName) + frmt.format(*args)) logger.log(level, '[{}] [{}] '.format(pName, sName) + frmt.format(*args))
else: else:
print('[{}] '.format(pName) + frmt.format(*args)) logger.log(level, '[{}] '.format(pName) + frmt.format(*args))
def processErrorMessage(pName, sName, msg): def processErrorMessage(pName, sName, msg, level=logging.DEBUG):
error, debug = msg.parse_error() error, debug = msg.parse_error()
if debug: if debug:
gstPrintMsg(pName, '{} - Additional debug info: {}', error.message, debug, sName=sName) gstPrintMsg(pName, '{} - Additional debug info: {}', error.message, debug, level=level, sName=sName)
else: else:
gstPrintMsg(pName, error.message, sName=sName) gstPrintMsg(pName, error.message, level=level, sName=sName)
raise GstException(error) raise GstException(error)
def linkElements(e1, e2, caps=None): def linkElements(e1, e2, caps=None):
@ -76,15 +80,13 @@ def eventLoop(pipeline, block=True, doProgress=False, targetState=Gst.State.PLAY
if msgType == Gst.MessageType.REQUEST_STATE: if msgType == Gst.MessageType.REQUEST_STATE:
state = msg.parse_request_state() state = msg.parse_request_state()
print('Setting state to {} as requested by {}'.format( logger.info('Setting state to %s as requested by %s',
Gst.Element.get_state_name(state), Gst.Element.get_state_name(state), msgSrcName)
msgSrcName)
)
pipeline.set_state(state) pipeline.set_state(state)
elif msgType == Gst.MessageType.CLOCK_LOST: elif msgType == Gst.MessageType.CLOCK_LOST:
print('Clock lost. Getting new one.') logger.debug('Clock lost. Getting new one.')
pipeline.set_state(Gst.State.PAUSED) pipeline.set_state(Gst.State.PAUSED)
pipeline.set_state(Gst.State.PLAYING) pipeline.set_state(Gst.State.PLAYING)
@ -105,18 +107,19 @@ def eventLoop(pipeline, block=True, doProgress=False, targetState=Gst.State.PLAY
error, debug = msg.parse_info() error, debug = msg.parse_info()
if debug: if debug:
gstPrintMsg(pName, debug, sName=msgSrcName) gstPrintMsg(pName, debug, level=logging.INFO, sName=msgSrcName)
elif msgType == Gst.MessageType.WARNING: elif msgType == Gst.MessageType.WARNING:
error, debug = msg.parse_warning() error, debug = msg.parse_warning()
if debug: if debug:
gstPrintMsg(pName, '{} - Additional debug info: {}', error.message, debug, sName=msgSrcName) gstPrintMsg(pName, '{} - Additional debug info: {}', error.message,
debug, level=logging.INFO, sName=msgSrcName)
else: else:
gstPrintMsg(pName, error.message, sName=msgSrcName) gstPrintMsg(pName, error.message, level=logging.INFO, sName=msgSrcName)
elif msgType == Gst.MessageType.ERROR: elif msgType == Gst.MessageType.ERROR:
processErrorMessage(pName, msgSrcName, msg) processErrorMessage(pName, msgSrcName, msg, logging.ERROR)
elif msgType == Gst.MessageType.STATE_CHANGED: elif msgType == Gst.MessageType.STATE_CHANGED:
# we only care about pipeline level state changes # we only care about pipeline level state changes
@ -128,11 +131,13 @@ def eventLoop(pipeline, block=True, doProgress=False, targetState=Gst.State.PLAY
prerolled = True prerolled = True
if buffering: if buffering:
gstPrintMsg(pName, 'Prerolled, waiting for buffering to finish') gstPrintMsg(pName, 'Prerolled, waiting for buffering to finish',
level=logging.INFO)
continue continue
if inProgress: if inProgress:
gstPrintMsg(pName, 'Prerolled, waiting for progress to finish') gstPrintMsg(pName, 'Prerolled, waiting for progress to finish',
level=logging.INFO)
continue continue
return return
@ -185,19 +190,19 @@ def eventLoop(pipeline, block=True, doProgress=False, targetState=Gst.State.PLAY
# these are things I might not need... # these are things I might not need...
elif msgType == Gst.MessageType.STREAM_START: elif msgType == Gst.MessageType.STREAM_START:
if msgSrc == pipeline: if msgSrc == pipeline:
gstPrintMsg(pName, 'Started stream') gstPrintMsg(pName, 'Started stream', level=logging.INFO)
#~ elif msgType == Gst.MessageType.QOS: elif msgType == Gst.MessageType.QOS:
#~ frmt, processed, dropped = msg.parse_qos_stats() frmt, processed, dropped = msg.parse_qos_stats()
#~ jitter, proportion, quality = msg.parse_qos_values() jitter, proportion, quality = msg.parse_qos_values()
#~ gstPrintMsg( gstPrintMsg(
#~ pName, pName,
#~ 'QOS stats: jitter={} dropped={}', 'QOS stats: jitter={} dropped={}',
#~ jitter, jitter,
#~ '-' if frmt == Gst.Format.UNDEFINED else dropped, '-' if frmt == Gst.Format.UNDEFINED else dropped,
#~ sName = msgSrcName sName = msgSrcName
#~ ) )
elif msgType == Gst.MessageType.ELEMENT: elif msgType == Gst.MessageType.ELEMENT:
gstPrintMsg(pName, 'Unknown message ELEMENT', sName=msgSrcName) gstPrintMsg(pName, 'Unknown message ELEMENT', sName=msgSrcName)
@ -209,10 +214,10 @@ def eventLoop(pipeline, block=True, doProgress=False, targetState=Gst.State.PLAY
def startPipeline(pipeline, play=True): def startPipeline(pipeline, play=True):
pName = pipeline.get_name() pName = pipeline.get_name()
stateChange = pipeline.set_state(Gst.State.PAUSED) stateChange = pipeline.set_state(Gst.State.PAUSED)
gstPrintMsg(pName, 'Setting to PAUSED') gstPrintMsg(pName, 'Setting to PAUSED', level=logging.INFO)
if stateChange == Gst.StateChangeReturn.FAILURE: if stateChange == Gst.StateChangeReturn.FAILURE:
gstPrintMsg(pName, 'Cannot set to PAUSE') gstPrintMsg(pName, 'Cannot set to PAUSE', level=logging.INFO)
eventLoop(pipeline, block=False, doProgress=False, targetState=Gst.State.VOID_PENDING) eventLoop(pipeline, block=False, doProgress=False, targetState=Gst.State.VOID_PENDING)
# we should always end up here because live # we should always end up here because live
elif stateChange == Gst.StateChangeReturn.NO_PREROLL: elif stateChange == Gst.StateChangeReturn.NO_PREROLL:
@ -222,7 +227,7 @@ def startPipeline(pipeline, play=True):
try: try:
eventLoop(pipeline, block=True, doProgress=True, targetState=Gst.State.PAUSED) eventLoop(pipeline, block=True, doProgress=True, targetState=Gst.State.PAUSED)
except GstException: except GstException:
gstPrintMsg(pName, 'Does not want to preroll') gstPrintMsg(pName, 'Does not want to preroll', level=logging.ERROR)
# some cleanup here? # some cleanup here?
raise raise
elif stateChange == Gst.StateChangeReturn.SUCCESS: elif stateChange == Gst.StateChangeReturn.SUCCESS:
@ -232,19 +237,19 @@ def startPipeline(pipeline, play=True):
try: try:
eventLoop(pipeline, block=False, doProgress=True, targetState=Gst.State.PLAYING) eventLoop(pipeline, block=False, doProgress=True, targetState=Gst.State.PLAYING)
except GstException: except GstException:
gstPrintMsg(pName, 'Does not want to preroll') gstPrintMsg(pName, 'Does not want to preroll', level=logging.ERROR)
# some cleanup here? # some cleanup here?
raise raise
# ...and end up here # ...and end up here
else: else:
if play: if play:
gstPrintMsg(pName, 'Setting to PLAYING') gstPrintMsg(pName, 'Setting to PLAYING', level=logging.INFO)
# and since this will ALWAYS be successful (maybe)... # and since this will ALWAYS be successful (maybe)...
if pipeline.set_state(Gst.State.PLAYING) == Gst.StateChangeReturn.FAILURE: if pipeline.set_state(Gst.State.PLAYING) == Gst.StateChangeReturn.FAILURE:
gstPrintMsg(pName, 'Cannot set to PLAYING') gstPrintMsg(pName, 'Cannot set to PLAYING', level=logging.ERROR)
err = pipeline.get_bus().pop_filtered(Gst.MessageType.Error) err = pipeline.get_bus().pop_filtered(Gst.MessageType.Error)
processErrorMessage(pName, msgSrcName, err) processErrorMessage(pName, msgSrcName, err, logging.ERROR)
# ...we and end up here and loop until Tool releases their next album # ...we and end up here and loop until Tool releases their next album
try: try:
@ -253,9 +258,11 @@ def startPipeline(pipeline, play=True):
# cleanup or recover # cleanup or recover
raise raise
def Camera(video=True, audio=True): def initCamera(video=True, audio=True):
pipeline = Gst.Pipeline.new("camera") pipeline = Gst.Pipeline.new("camera")
vPath = '/dev/video0'
if video: if video:
vSource = Gst.ElementFactory.make("v4l2src", "videoSource") vSource = Gst.ElementFactory.make("v4l2src", "videoSource")
vConvert = Gst.ElementFactory.make("videoconvert", "videoConvert") vConvert = Gst.ElementFactory.make("videoconvert", "videoConvert")
@ -265,7 +272,7 @@ def Camera(video=True, audio=True):
vRTPPay = Gst.ElementFactory.make("rtph264pay", "videoRTPPayload") vRTPPay = Gst.ElementFactory.make("rtph264pay", "videoRTPPayload")
vRTPSink = Gst.ElementFactory.make("multiudpsink", "videoRTPSink") vRTPSink = Gst.ElementFactory.make("multiudpsink", "videoRTPSink")
vSource.set_property('device', '/dev/video0') vSource.set_property('device', vPath)
vRTPPay.set_property('config-interval', 1) vRTPPay.set_property('config-interval', 1)
vRTPPay.set_property('pt', 96) vRTPPay.set_property('pt', 96)
vRTPSink.set_property('clients', '127.0.0.1:9001,127.0.0.1:9002') vRTPSink.set_property('clients', '127.0.0.1:9001,127.0.0.1:9002')
@ -302,6 +309,8 @@ def Camera(video=True, audio=True):
linkElements(aEncode, aRTPPay) linkElements(aEncode, aRTPPay)
linkElements(aRTPPay, aRTPSink) linkElements(aRTPPay, aRTPSink)
waitForPath(vPath) # video is on usb, so wait until it comes back after we hard reset the bus
startPipeline(pipeline) startPipeline(pipeline)
class FileDump: class FileDump:
@ -348,10 +357,6 @@ class FileDump:
self.pipeline.set_state(Gst.State.PAUSED) self.pipeline.set_state(Gst.State.PAUSED)
Gst.init(None) Gst.init(None)
Camera()
while 1:
time.sleep(3600)
# this works for file dump # this works for file dump
# gst-launch-1.0 -v udpsrc port=8001 ! application/x-rtp,encoding-name=OPUS,payload=96 ! # gst-launch-1.0 -v udpsrc port=8001 ! application/x-rtp,encoding-name=OPUS,payload=96 !