Skip to content

Commit

Permalink
Manage get/set input and output
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagocoutinho committed Jul 12, 2024
1 parent c1ad0dc commit f052c8c
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 6 deletions.
31 changes: 31 additions & 0 deletions linuxpy/codegen/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,35 @@
{structs_body}
# STD macros are too complicated to auto generate
class StandardID(enum.IntFlag):
V4L2_STD_PAL_B = 0x00000001
V4L2_STD_PAL_B1 = 0x00000002
V4L2_STD_PAL_G = 0x00000004
V4L2_STD_PAL_H = 0x00000008
V4L2_STD_PAL_I = 0x00000010
V4L2_STD_PAL_D = 0x00000020
V4L2_STD_PAL_D1 = 0x00000040
V4L2_STD_PAL_K = 0x00000080
V4L2_STD_PAL_M = 0x00000100
V4L2_STD_PAL_N = 0x00000200
V4L2_STD_PAL_Nc = 0x00000400
V4L2_STD_PAL_60 = 0x00000800
V4L2_STD_NTSC_M = 0x00001000 # BTSC
V4L2_STD_NTSC_M_JP = 0x00002000 # EIA-J
V4L2_STD_NTSC_443 = 0x00004000
V4L2_STD_NTSC_M_KR = 0x00008000 # FM A2
V4L2_STD_SECAM_B = 0x00010000
V4L2_STD_SECAM_D = 0x00020000
V4L2_STD_SECAM_G = 0x00040000
V4L2_STD_SECAM_H = 0x00080000
V4L2_STD_SECAM_K = 0x00100000
V4L2_STD_SECAM_K1 = 0x00200000
V4L2_STD_SECAM_L = 0x00400000
V4L2_STD_SECAM_LC = 0x00800000
V4L2_STD_ATSC_8_VSB = 0x01000000
V4L2_STD_ATSC_16_VSB = 0x02000000
{iocs_body}"""

Expand All @@ -75,7 +104,9 @@
CEnum("ImageFormatFlag", "V4L2_FMT_FLAG_", "IntFlag"),
CEnum("InputStatus", "V4L2_IN_ST_", "IntFlag"),
CEnum("InputType", "V4L2_INPUT_TYPE_"),
CEnum("OutputType", "V4L2_OUTPUT_TYPE_"),
CEnum("InputCapabilities", "V4L2_IN_CAP_", "IntFlag"),
CEnum("OutputCapabilities", "V4L2_OUT_CAP_", "IntFlag"),
CEnum("ControlClass", "V4L2_CTRL_CLASS_"),
CEnum("ControlID", "V4L2_CID_"),
CEnum("ControlFlag", "V4L2_CTRL_FLAG_", "IntFlag"),
Expand Down
4 changes: 4 additions & 0 deletions linuxpy/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,7 @@ def tuple(self):
so `Version(3,2,1).tuple()` yields the tuple `(3, 2, 1)`
"""
return self.major, self.minor, self.patch


def bit_indexes(number):
return [i for i, c in enumerate(bin(number)[:1:-1]) if c == "1"]
63 changes: 58 additions & 5 deletions linuxpy/video/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from linuxpy.io import IO
from linuxpy.ioctl import ioctl
from linuxpy.types import AsyncIterator, Buffer, Callable, Iterable, Iterator, Optional, PathLike, Self
from linuxpy.util import add_reader_asyncio, make_find
from linuxpy.util import add_reader_asyncio, bit_indexes, make_find

from . import raw

Expand Down Expand Up @@ -69,12 +69,14 @@ def _enum(name, prefix, klass=enum.IntEnum):
FrameSizeType = raw.Frmsizetypes
Memory = raw.Memory
InputStatus = raw.InputStatus
InputType = raw.InputType
OutputType = raw.OutputType
InputCapabilities = raw.InputCapabilities
OutputCapabilities = raw.OutputCapabilities
Priority = raw.Priority
TimeCodeType = raw.TimeCodeType
TimeCodeFlag = raw.TimeCodeFlag
EventSubscriptionFlag = raw.EventSubscriptionFlag
StandardID = raw.StandardID


def V4L2_CTRL_ID2CLASS(id_):
Expand All @@ -91,7 +93,7 @@ def human_pixel_format(ifmt):
Info = collections.namedtuple(
"Info",
"driver card bus_info version capabilities device_capabilities "
"crop_capabilities buffers formats frame_sizes inputs controls",
"crop_capabilities buffers formats frame_sizes inputs outputs controls",
)

ImageFormat = collections.namedtuple("ImageFormat", "type description flags pixel_format")
Expand All @@ -108,6 +110,7 @@ def human_pixel_format(ifmt):

Input = collections.namedtuple("InputType", "index name type audioset tuner std status capabilities")

Output = collections.namedtuple("OutputType", "index name type audioset modulator std capabilities")

INFO_REPR = """\
driver = {info.driver}
Expand Down Expand Up @@ -286,15 +289,30 @@ def iter_read_inputs(fd):
index=inp.index,
name=inp.name.decode(),
type=InputType(inp.type),
audioset=inp.audioset,
audioset=bit_indexes(inp.audioset),
tuner=inp.tuner,
std=inp.std,
std=StandardID(inp.std),
status=InputStatus(inp.status),
capabilities=InputCapabilities(inp.capabilities),
)
yield input_type


def iter_read_outputs(fd):
output = raw.v4l2_output()
for out in iter_read(fd, IOC.ENUMOUTPUT, output):
output_type = Output(
index=out.index,
name=out.name.decode(),
type=OutputType(out.type),
audioset=bit_indexes(out.audioset),
modulator=out.modulator,
std=StandardID(out.std),
capabilities=OutputCapabilities(out.capabilities),
)
yield output_type


def iter_read_controls(fd):
ctrl = raw.v4l2_query_ext_ctrl()
nxt = ControlFlag.NEXT_CTRL | ControlFlag.NEXT_COMPOUND
Expand Down Expand Up @@ -374,6 +392,7 @@ def read_info(fd):
formats=image_formats,
frame_sizes=frame_sizes(fd, pixel_formats),
inputs=list(iter_read_inputs(fd)),
outputs=list(iter_read_outputs(fd)),
controls=list(iter_read_controls(fd)),
)

Expand Down Expand Up @@ -652,6 +671,28 @@ def get_edid(fd):
return string_at(edid_struct.edid, edid_len)


def get_input(fd):
inp = ctypes.c_uint()
ioctl(fd, IOC.G_INPUT, inp)
return inp.value


def set_input(fd, index: int):
index = ctypes.c_uint(index)
ioctl(fd, IOC.S_INPUT, index)


def get_output(fd):
out = ctypes.c_uint()
ioctl(fd, IOC.G_OUTPUT, out)
return out.value


def set_output(fd, index: int):
index = ctypes.c_uint(index)
ioctl(fd, IOC.S_OUTPUT, index)


# Helpers


Expand Down Expand Up @@ -792,6 +833,18 @@ def clear_edid(self):
def get_edid(self):
return get_edid(self.fileno())

def get_input(self):
return get_input(self.fileno())

def set_input(self, index: int):
return set_input(self.fileno(), index)

def get_output(self):
return get_output(self.fileno())

def set_output(self, index: int):
return set_output(self.fileno(), index)


class Controls(dict):
@classmethod
Expand Down
43 changes: 42 additions & 1 deletion linuxpy/video/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,13 +384,25 @@ class InputType(enum.IntEnum):
TOUCH = 0x3


class OutputType(enum.IntEnum):
MODULATOR = 0x1
ANALOG = 0x2
ANALOGVGAOVERLAY = 0x3


class InputCapabilities(enum.IntFlag):
DV_TIMINGS = 0x00000002 # Supports S_DV_TIMINGS
CUSTOM_TIMINGS = DV_TIMINGS # For compatibility
STD = 0x00000004 # Supports S_STD
NATIVE_SIZE = 0x00000008 # Supports setting native size


class OutputCapabilities(enum.IntFlag):
DV_TIMINGS = 0x00000002 # Supports S_DV_TIMINGS
STD = 0x00000004 # Supports S_STD
NATIVE_SIZE = 0x00000008 # Supports setting native size


class ControlClass(enum.IntEnum):
USER = 0x00980000 # Old-style 'user' controls
CODEC = 0x00990000 # Stateful codec controls
Expand Down Expand Up @@ -3969,7 +3981,36 @@ class v4l2_subdev_client_capability(Struct):
pass


v4l2_subdev_client_capability._fields_ = [("capabilities", culonglong)]
# STD macros are too complicated to auto generate


class StandardID(enum.IntFlag):
V4L2_STD_PAL_B = 0x00000001
V4L2_STD_PAL_B1 = 0x00000002
V4L2_STD_PAL_G = 0x00000004
V4L2_STD_PAL_H = 0x00000008
V4L2_STD_PAL_I = 0x00000010
V4L2_STD_PAL_D = 0x00000020
V4L2_STD_PAL_D1 = 0x00000040
V4L2_STD_PAL_K = 0x00000080
V4L2_STD_PAL_M = 0x00000100
V4L2_STD_PAL_N = 0x00000200
V4L2_STD_PAL_Nc = 0x00000400
V4L2_STD_PAL_60 = 0x00000800
V4L2_STD_NTSC_M = 0x00001000 # BTSC
V4L2_STD_NTSC_M_JP = 0x00002000 # EIA-J
V4L2_STD_NTSC_443 = 0x00004000
V4L2_STD_NTSC_M_KR = 0x00008000 # FM A2
V4L2_STD_SECAM_B = 0x00010000
V4L2_STD_SECAM_D = 0x00020000
V4L2_STD_SECAM_G = 0x00040000
V4L2_STD_SECAM_H = 0x00080000
V4L2_STD_SECAM_K = 0x00100000
V4L2_STD_SECAM_K1 = 0x00200000
V4L2_STD_SECAM_L = 0x00400000
V4L2_STD_SECAM_LC = 0x00800000
V4L2_STD_ATSC_8_VSB = 0x01000000
V4L2_STD_ATSC_16_VSB = 0x02000000


class IOC(enum.IntEnum):
Expand Down

0 comments on commit f052c8c

Please sign in to comment.