Advertisement
pootle

python 3.4 v4l2 mmap and selectors

Apr 12th, 2016
3,366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.60 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. import logging
  4. import os
  5. import v4l2
  6. import fcntl
  7. import mmap
  8. import multiprocessing as mp
  9. import time
  10. #import asyncore
  11. import selectors
  12.  
  13. import bufferman
  14. import numpy
  15. from PIL import Image
  16.  
  17. logging.basicConfig(format='%(asctime)s %(levelname)s %(name)s: %(message)s'
  18.             ,datefmt='%I:%M:%S'
  19. #           ,filename="aalog.log"
  20.             ,level=logging.DEBUG)
  21.  
  22. def opendev(vfn):
  23.     dfile = os.open(vfn, os.O_RDWR | os.O_NONBLOCK, 0)
  24.     return dfile
  25.    
  26. def closedev(dfile):
  27.     os.close(dfile)
  28.  
  29. class asyncamtest():
  30.     def __init__(self,cq,rq,vdev):
  31.         self.vdev = vdev
  32.         self.cq = cq
  33.         self.rq = rq
  34.         self.lgr = logging.getLogger('selectorscamtest')
  35.         self._buffers = []
  36.         self._mmaps = []
  37.         self.asel = selectors.DefaultSelector()
  38.         self.asel.register(self.vdev, selectors.EVENT_READ | selectors.EVENT_WRITE, self.vfileio)
  39.         self.lgr.info("__init__ completes")
  40.  
  41.     def runloop(self):
  42.         self.lgr.info("runloop starts")
  43.         self.running = True
  44.         while self.running:
  45.             if not self.cq.empty():
  46.                 self.msgin(self.cq.get())
  47. #           asyncore.loop(0.2, map = self.cmap, count = 3)
  48.             events = self.asel.select(.2)
  49.             self.lgr.info("runloop select returns %d events" % len(events))
  50.             for key, mask in events:
  51.                 callback = key.data
  52.                 callback(mask)     
  53.         self.releaseBuffs()
  54.         self.lgr.info("runloop finishes")
  55.  
  56.     def vfileio(self, mask):
  57.         ma = "" if selectors.EVENT_READ & mask == 0 else "have read "
  58.         mb = "" if selectors.EVENT_WRITE & mask == 0 else "have write "
  59.         self.lgr.info("fileio " + ma + mb)
  60.         if ma != "":
  61.             self.handle_read()
  62.  
  63.     def msgin(self, msgin):
  64.         cmd = msgin['cmd']
  65.         self.lgr.info("msgin gets %s" % cmd)
  66.         if cmd == 'done':
  67.             self.running = False
  68.             self.lgr.info("msgin running unset")
  69.             msgin['resu'] = 'closing'
  70.             self.rq.put(msgin)
  71.         elif cmd == 'takepics':
  72.             self.takepics(msgin)
  73.         else:
  74.             self.lgr.info("msgin What> - %s" % cmd)
  75.             qi['resu'] = 'What? - %s' % cms
  76.             self.rq.put(msgin)
  77.  
  78.     def takepics(self, msgin):
  79.         self.lgr.info("prepare to take piccy ")
  80.         self._bufferMode = v4l2.V4L2_MEMORY_MMAP
  81.         self.fpixformat = v4l2.V4L2_PIX_FMT_YUYV
  82.         rbuffcount = msgin['buffcount']
  83.         vformat = self.getFormat()
  84.         self.allocBuffs(rbuffcount, vformat)
  85.         procparams={}
  86.         procparams['rotact'] = 0
  87. #       procparams['basefilename'] = "%s%s%%04d" % ('zz', camsettings['sequnamef'])
  88.         procparams['basefilename'] = "fred%04d"
  89.         procparams['savetype'] = "JPEG"
  90.         self._buffman = bufferman.bufferman(self, vformat, vformat.fmt.pix.pixelformat, procparams)
  91.         self.stype = v4l2.v4l2_buf_type(v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE)
  92.         fcntl.ioctl(self.vdev, v4l2.VIDIOC_STREAMON, self.stype)
  93.         self.lgr.info("takepiccy rolling")
  94.        
  95.     def handle_read(self):
  96.                 #but first check we've not closed it recently....
  97.         if self.vdev is None:
  98.             self.lgr.debug("camera ready to read but file is None")
  99.             return
  100.        
  101.         self.lgr.debug("camera ready to read....")
  102.         self._dqbuf.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
  103.         self._dqbuf.memory = v4l2.V4L2_MEMORY_MMAP
  104.         self._dqbuf.reserved = 0
  105.         fcntl.ioctl(self.vdev, v4l2.VIDIOC_DQBUF, self._dqbuf)
  106. #       self.lgr.debug(v4camSupport.expandBufferFlags(self._dqbuf.flags))
  107.         tstamp = time.strftime("%Y:%m:%d %H:%M:%S")
  108.         self._buffman.makeSmartImage(self._dqbuf.index, 5, tstamp)
  109.         fcntl.ioctl(self.vdev, v4l2.VIDIOC_STREAMOFF, self.stype)
  110.         self._buffman.releaseSmartImageBuff()
  111.         self.releaseBuffs()
  112.         self.lgr.info("camera read finishes")
  113.  
  114.     def getFormat(self):
  115.         vFormat = v4l2.v4l2_format()
  116.         vFormat.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
  117.         fcntl.ioctl(self.vdev, v4l2.VIDIOC_G_FMT, vFormat) # lets just see what we get.....
  118.         self.lgr.info("video frame format before: - linestride " + str(vFormat.fmt.pix.bytesperline)
  119.             + ", imageInfo:" + str(vFormat.fmt.pix.width) + "/" + str(vFormat.fmt.pix.height))
  120.         vFormat.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
  121.         vFormat.fmt.pix.width = 640
  122.         vFormat.fmt.pix.height = 480
  123.         vFormat.fmt.pix.pixelformat = self.fpixformat
  124.         vFormat.fmt.pix.field = v4l2.V4L2_FIELD_NONE
  125.         vFormat.fmt.pix.bytesperline = 0
  126.         fcntl.ioctl(self.vdev, v4l2.VIDIOC_S_FMT, vFormat)
  127.         self.lgr.info("video frame format now set - linestride " + str(vFormat.fmt.pix.bytesperline)
  128.             + ", imageInfo:" + str(vFormat.fmt.pix.width) + "/" + str(vFormat.fmt.pix.height) + " is " + str(vFormat.fmt.pix.sizeimage)
  129.             + " from " + str(vFormat.fmt.pix.width * vFormat.fmt.pix.height))
  130.         fcntl.ioctl(self.vdev, v4l2.VIDIOC_G_FMT, vFormat)
  131.         self.lgr.info("video frame format REALLY set - linestride " + str(vFormat.fmt.pix.bytesperline)
  132.             + ", imageInfo:" + str(vFormat.fmt.pix.width) + "/" + str(vFormat.fmt.pix.height) + " is " + str(vFormat.fmt.pix.sizeimage)
  133.             + " from " + str(vFormat.fmt.pix.width * vFormat.fmt.pix.height))
  134. #           + ", colour space: " + colorSpaces.get(vFormat.fmt.pix.colorspace)
  135. #           + ", pixel format: " + pixelFormats[ vFormat.fmt.pix.pixelformat])
  136.    
  137.         return vFormat
  138.  
  139.     def allocBuffs(self, buffcount, vformat):
  140.         buffRequ = v4l2.v4l2_requestbuffers()
  141.         buffRequ.count = buffcount
  142.         buffRequ.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
  143.         buffRequ.memory = self._bufferMode
  144.         fcntl.ioctl(self.vdev, v4l2.VIDIOC_REQBUFS, buffRequ)
  145.         self.lgr.info("agent::allocBuffs requested " + str(buffcount) + ", got " + str(buffRequ.count))
  146.  
  147.         self._buffers = []
  148.         self._mmaps = []
  149.         for bi in range(0, buffRequ.count):
  150.             abuf = v4l2.v4l2_buffer()
  151.             self._buffers.append(abuf)
  152.             abuf.type = v4l2.V4L2_BUF_TYPE_VIDEO_CAPTURE
  153.             abuf.memory = self._bufferMode
  154.             abuf.index = bi
  155.             fcntl.ioctl(self.vdev, v4l2.VIDIOC_QUERYBUF, abuf)
  156.             abuf.length = vformat.fmt.pix.sizeimage
  157.             if self._bufferMode == v4l2.V4L2_MEMORY_MMAP:
  158.                 fcntl.ioctl(self.vdev, v4l2.VIDIOC_QBUF, abuf)
  159.                 self._mmaps.append(mmap.mmap(self.vdev, abuf.length, mmap.MAP_SHARED,  
  160.                     mmap.PROT_READ | mmap.PROT_WRITE, offset=abuf.m.offset))
  161.             else:
  162.                 abufarea = ctypes.c_int(55)
  163.                 abuf.m.userptr = ctypes.byref(abufarea)
  164.                 fcntl.ioctl(self.vdev, v4l2.VIDIOC_QBUF, abuf)
  165.  
  166.         self._dqbuf = v4l2.v4l2_buffer()
  167.  
  168.     def releaseBuffs(self):
  169.         if self._bufferMode == v4l2.V4L2_MEMORY_MMAP:
  170.             for bi in range(0, len(self._mmaps)):
  171.                 self._mmaps[bi].close()
  172.             self._mmaps = []
  173.         self._buffers = []
  174.    
  175.        
  176. def runCamera(cq, rq, vfile):
  177.     lgr = logging.getLogger('runCamera')
  178.     lgr.info("camera process started")
  179.     cdev = opendev(vfile)
  180.     lgr.info('camera file opened')
  181.     ct = asyncamtest(cq,rq,cdev)
  182.     ct.runloop()
  183.     if not cdev is None:
  184.         closedev(cdev)
  185.         lgr.info('camera closed')
  186.     time.sleep(0.5)
  187.     lgr.info("camera process finished")
  188.  
  189. if __name__=="__main__":
  190.     logging.info("now attempting to run usb camera using multiple processes and memory mapped IO.......")
  191.     import argparse
  192.     parser = argparse.ArgumentParser(description="test app for multi processing with memory mapped IO")
  193.     parser.add_argument( "-v", "--video"
  194.         , type=int
  195.         , help="number of the video device to be tested (from /dev/videox) default is video0")
  196.     args = parser.parse_args()
  197.     vnum = args.video if args.video else 0
  198.     vfilename = '/dev/video%d' % vnum
  199.     try:
  200.         dfile = opendev(vfilename)
  201.     except IOError:
  202.         logging.critical("Unable to open device - IOError" + vfilename)
  203.         quit()
  204.     except:
  205.         logging.critical("Device open failed for " + vfilename)
  206.         quit()
  207.  
  208.     logging.info("device %s opened OK - start camera process" % vfilename)
  209.     closedev(dfile)
  210.     comq = mp.Queue()
  211.     respq = mp. Queue()
  212.     camproc = mp.Process(target=runCamera, name = "camtest video%d" % vnum
  213.                 , args= (comq, respq, vfilename))
  214.     camproc.start()
  215.     comq.put({'cmd': 'takepics', 'buffcount':4})
  216.     time.sleep(4)
  217.     comq.put({'cmd':'done'})
  218.     resp = respq.get()
  219.     print("->" + str(resp))
  220.    
  221.     camproc.join()
  222.     logging.info("byeeee")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement