forked from platypush/platypush
parent
4bf9c01ac9
commit
4fffabd82a
5 changed files with 126 additions and 0 deletions
5
docs/source/platypush/plugins/camera.gstreamer.rst
Normal file
5
docs/source/platypush/plugins/camera.gstreamer.rst
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
``camera.gstreamer``
|
||||||
|
======================================
|
||||||
|
|
||||||
|
.. automodule:: platypush.plugins.camera.gstreamer
|
||||||
|
:members:
|
|
@ -19,6 +19,7 @@ Plugins
|
||||||
platypush/plugins/camera.android.ipcam.rst
|
platypush/plugins/camera.android.ipcam.rst
|
||||||
platypush/plugins/camera.cv.rst
|
platypush/plugins/camera.cv.rst
|
||||||
platypush/plugins/camera.ffmpeg.rst
|
platypush/plugins/camera.ffmpeg.rst
|
||||||
|
platypush/plugins/camera.gstreamer.rst
|
||||||
platypush/plugins/camera.ir.mlx90640.rst
|
platypush/plugins/camera.ir.mlx90640.rst
|
||||||
platypush/plugins/camera.pi.rst
|
platypush/plugins/camera.pi.rst
|
||||||
platypush/plugins/chat.irc.rst
|
platypush/plugins/chat.irc.rst
|
||||||
|
|
94
platypush/plugins/camera/gstreamer/__init__.py
Normal file
94
platypush/plugins/camera/gstreamer/__init__.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
from PIL.Image import Image as ImageType
|
||||||
|
|
||||||
|
from platypush.plugins.camera import CameraPlugin
|
||||||
|
from platypush.plugins.camera.gstreamer.model import GStreamerCamera
|
||||||
|
from platypush.common.gstreamer import Pipeline
|
||||||
|
|
||||||
|
|
||||||
|
class CameraGstreamerPlugin(CameraPlugin):
|
||||||
|
"""
|
||||||
|
Plugin to interact with a camera over GStreamer.
|
||||||
|
|
||||||
|
Requires:
|
||||||
|
|
||||||
|
* **gst-python**
|
||||||
|
* **pygobject**
|
||||||
|
|
||||||
|
On Debian and derived systems:
|
||||||
|
|
||||||
|
* ``[sudo] apt-get install python3-gi python3-gst-1.0``
|
||||||
|
|
||||||
|
On Arch and derived systems:
|
||||||
|
|
||||||
|
* ``[sudo] pacman -S gst-python``
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
_camera_class = GStreamerCamera
|
||||||
|
|
||||||
|
def __init__(self, device: Optional[str] = '/dev/video0', **opts):
|
||||||
|
"""
|
||||||
|
:param device: Path to the camera device (default ``/dev/video0``).
|
||||||
|
:param opts: Camera options - see constructor of :class:`platypush.plugins.camera.CameraPlugin`.
|
||||||
|
"""
|
||||||
|
super().__init__(device=device, **opts)
|
||||||
|
|
||||||
|
def prepare_device(self, camera: GStreamerCamera) -> Pipeline:
|
||||||
|
pipeline = Pipeline()
|
||||||
|
src = pipeline.add_source('v4l2src', device=camera.info.device)
|
||||||
|
convert = pipeline.add('videoconvert')
|
||||||
|
assert camera.info and camera.info.resolution
|
||||||
|
|
||||||
|
video_filter = pipeline.add(
|
||||||
|
'capsfilter',
|
||||||
|
caps='video/x-raw,format=RGB,width={width},height={height},framerate={fps}/1'.format(
|
||||||
|
width=camera.info.resolution[0],
|
||||||
|
height=camera.info.resolution[1],
|
||||||
|
fps=camera.info.fps,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
sink = pipeline.add_sink('appsink', name='appsink', sync=False)
|
||||||
|
pipeline.link(src, convert, video_filter, sink)
|
||||||
|
return pipeline
|
||||||
|
|
||||||
|
def start_camera(
|
||||||
|
self, camera: GStreamerCamera, preview: bool = False, *args, **kwargs
|
||||||
|
):
|
||||||
|
super().start_camera(*args, camera=camera, preview=preview, **kwargs)
|
||||||
|
if camera.object:
|
||||||
|
camera.object.play()
|
||||||
|
|
||||||
|
def release_device(self, camera: GStreamerCamera):
|
||||||
|
if camera.object:
|
||||||
|
camera.object.stop()
|
||||||
|
|
||||||
|
def capture_frame(self, camera: GStreamerCamera, *_, **__) -> Optional[ImageType]:
|
||||||
|
if not (camera.info and camera.info.fps and camera.info.resolution):
|
||||||
|
return None
|
||||||
|
|
||||||
|
timed_out = not camera.object.data_ready.wait(
|
||||||
|
timeout=5 + (1.0 / camera.info.fps)
|
||||||
|
)
|
||||||
|
if timed_out:
|
||||||
|
self.logger.warning('Frame capture timeout')
|
||||||
|
return None
|
||||||
|
|
||||||
|
data = camera.object.data
|
||||||
|
if data is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
camera.object.data_ready.clear()
|
||||||
|
if (
|
||||||
|
not data
|
||||||
|
and len(data) != camera.info.resolution[0] * camera.info.resolution[1] * 3
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return Image.frombytes('RGB', camera.info.resolution, data)
|
||||||
|
|
||||||
|
|
||||||
|
# vim:sw=4:ts=4:et:
|
16
platypush/plugins/camera/gstreamer/manifest.yaml
Normal file
16
platypush/plugins/camera/gstreamer/manifest.yaml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
manifest:
|
||||||
|
events: {}
|
||||||
|
install:
|
||||||
|
pip:
|
||||||
|
- numpy
|
||||||
|
- Pillow
|
||||||
|
- pygobject
|
||||||
|
apt:
|
||||||
|
- python3-gi
|
||||||
|
- python3-gst-1.0
|
||||||
|
pacman:
|
||||||
|
- gst-python
|
||||||
|
- python-gobject
|
||||||
|
|
||||||
|
package: platypush.plugins.camera.gstreamer
|
||||||
|
type: plugin
|
10
platypush/plugins/camera/gstreamer/model.py
Normal file
10
platypush/plugins/camera/gstreamer/model.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from platypush.common.gstreamer import Pipeline
|
||||||
|
from platypush.plugins.camera import CameraInfo, Camera
|
||||||
|
|
||||||
|
|
||||||
|
class GStreamerCamera(Camera):
|
||||||
|
info: CameraInfo
|
||||||
|
object: Pipeline
|
||||||
|
|
||||||
|
|
||||||
|
# vim:sw=4:ts=4:et:
|
Loading…
Reference in a new issue