Skip to content

Commit

Permalink
devices: imx708: Add a new IMX708 helper class
Browse files Browse the repository at this point in the history
This class provides a convenient helper function set enable/disable
sensor HDR mode without relying on external tools. Usage example:

-----
from picamera2.devices.imx708 import IMX708
from picamera2 import Picamera2

camera_num = 0
c = IMX708(camera_num)
c.set_hdr_mode(True)
picam2 = Picamera2(camera_num)
-----

Note that after calling IMX708.set_hdr_mode(), you must re-initialise
the Picamera2 instance.

A change to the CameraManager class is also needed to allow it to be
reset as it caches sensor modes internally in libcamera.

Signed-off-by: Naushir Patuck <[email protected]>
  • Loading branch information
naushir committed Aug 12, 2024
1 parent ddd2ca3 commit 475f818
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions picamera2/devices/imx708/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .imx708 import IMX708
54 changes: 54 additions & 0 deletions picamera2/devices/imx708/imx708.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import fcntl
import libcamera
import os

from picamera2 import Picamera2
from v4l2 import *

HDR_CTRL_ID = 0x009a0915


class IMX708:
def __init__(self, camera_num: int):
self.device_fd = None

camera_id = None
for c in Picamera2.global_camera_info():
if c['Num'] == camera_num:
camera_id = c['Id']

if camera_id is None:
raise RuntimeError('IMX708: Requested camera number {camera_num} cound not be found')

for i in range(16):
test_dir = f'/sys/class/video4linux/v4l-subdev{i}/device'
module_dir = f'{test_dir}/driver/module'
id_dir = f'{test_dir}/of_node'
if os.path.exists(module_dir) and os.path.islink(module_dir) and 'imx708' in os.readlink(module_dir):
if os.path.islink(id_dir) and camera_id in os.readlink(id_dir):
self.device_fd = open(f'/dev/v4l-subdev{i}', 'rb+', buffering=0)
break

if self.device_fd is None:
raise RuntimeError('IMX708: Requested camera device node not found')

def __del__(self):
if self.device_fd:
self.device_fd.close()

def set_hdr_mode(self, enable: bool):
"""
Set the HDR mode (True/False) on the IMX708 device. Note that after changing the HDR mode, you must re-initialise
the Picamera2 object to cache the updated sensor modes.
"""
ctrl = v4l2_control()
ctrl.id = HDR_CTRL_ID
ctrl.value = int(enable)

try:
fcntl.ioctl(self.device_fd, VIDIOC_S_CTRL, ctrl)
except OSError as err:
print(f'IMX708: Unable to set HDR control in the device node: {err}')

# Re-initialise the camera manager as it (also) caches sensor modes.
Picamera2._cm.reset()
5 changes: 5 additions & 0 deletions picamera2/picamera2.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ def cms(self):
self._cms = libcamera.CameraManager.singleton()
return self._cms

def reset(self):
with self._lock:
self._cms = None
self._cms = libcamera.CameraManager.singleton()

def add(self, index, camera):
with self._lock:
self.cameras[index] = camera
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"Programming Language :: Python :: 3.9",
"Topic :: Multimedia :: Graphics :: Capture :: Digital Camera",
],
packages=['picamera2', 'picamera2.encoders', 'picamera2.outputs', 'picamera2.previews', 'picamera2.allocators'],
packages=['picamera2', 'picamera2.devices.imx708', 'picamera2.encoders', 'picamera2.outputs', 'picamera2.previews',
'picamera2.allocators'],
python_requires='>=3.9',
licence='BSD 2-Clause License',
install_requires=['numpy', 'PiDNG', 'piexif', 'pillow', 'simplejpeg', 'v4l2-python3', 'python-prctl', 'av'],
Expand Down

0 comments on commit 475f818

Please sign in to comment.