59 lines
1.6 KiB
Python
59 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
from PySide6.QtCore import QObject, Signal
|
|
from PySide6.QtMultimedia import (
|
|
QCamera,
|
|
QCameraDevice,
|
|
QCameraFormat,
|
|
QMediaCaptureSession,
|
|
QMediaDevices,
|
|
QVideoSink,
|
|
)
|
|
|
|
|
|
class CameraService(QObject):
|
|
error_occurred = Signal(str)
|
|
|
|
def __init__(self, parent: QObject | None = None) -> None:
|
|
super().__init__(parent)
|
|
self._session = QMediaCaptureSession()
|
|
self._sink = QVideoSink()
|
|
self._session.setVideoOutput(self._sink)
|
|
self._camera: QCamera | None = None
|
|
|
|
@property
|
|
def sink(self) -> QVideoSink:
|
|
return self._sink
|
|
|
|
@property
|
|
def session(self) -> QMediaCaptureSession:
|
|
return self._session
|
|
|
|
@staticmethod
|
|
def available_cameras() -> list[QCameraDevice]:
|
|
return QMediaDevices.videoInputs()
|
|
|
|
def is_active(self) -> bool:
|
|
return self._camera is not None and self._camera.isActive()
|
|
|
|
def start(self, device: QCameraDevice) -> None:
|
|
self.stop()
|
|
self._camera = QCamera(device, self)
|
|
self._camera.errorOccurred.connect(self._on_error)
|
|
self._session.setCamera(self._camera)
|
|
self._camera.start()
|
|
|
|
def stop(self) -> None:
|
|
if self._camera is not None:
|
|
self._camera.stop()
|
|
self._session.setCamera(None)
|
|
self._camera.deleteLater()
|
|
self._camera = None
|
|
|
|
def set_camera_format(self, fmt: QCameraFormat) -> None:
|
|
if self._camera is not None:
|
|
self._camera.setCameraFormat(fmt)
|
|
|
|
def _on_error(self, error: QCamera.Error, error_string: str) -> None:
|
|
self.error_occurred.emit(error_string)
|