48 lines
1.6 KiB
Python
48 lines
1.6 KiB
Python
import logging
|
|
import subprocess
|
|
import threading
|
|
|
|
from platypush.plugins.camera.model.writer.image import MJPEGStreamWriter
|
|
from platypush.plugins.camera.model.writer.preview import PreviewWriter
|
|
|
|
logger = logging.getLogger('cam-preview')
|
|
|
|
|
|
class FFplayPreviewWriter(PreviewWriter, MJPEGStreamWriter):
|
|
"""
|
|
General class for managing previews from camera devices or generic sources of images over ffplay.
|
|
"""
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.ffplay = subprocess.Popen(['ffplay', '-'], stdin=subprocess.PIPE)
|
|
self._preview_thread = threading.Thread(target=self._ffplay_thread)
|
|
self._preview_thread.start()
|
|
|
|
def _ffplay_thread(self):
|
|
while not self.closed and self.ffplay.poll() is None:
|
|
with self.ready:
|
|
self.ready.wait(1.)
|
|
if not self.frame:
|
|
continue
|
|
|
|
try:
|
|
self.ffplay.stdin.write(self.frame)
|
|
except Exception as e:
|
|
logger.warning('ffplay write error: {}'.format(str(e)))
|
|
self.close()
|
|
break
|
|
|
|
def close(self):
|
|
if self.ffplay and self.ffplay.poll() is None:
|
|
self.ffplay.terminate()
|
|
|
|
self.camera = None
|
|
super().close()
|
|
if self._preview_thread and self._preview_thread.is_alive() and \
|
|
threading.get_ident() != self._preview_thread.ident:
|
|
self._preview_thread.join(timeout=5.0)
|
|
self._preview_thread = None
|
|
|
|
|
|
# vim:sw=4:ts=4:et:
|