feat: 大规模扩充至212个模块/175K行代码 — 覆盖android/java/javax/org/dalvik全包
- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
This commit is contained in:
1 parent
506f9ac725
commit
a51854455b
128 files changed
+100571
-3
No files matched your search
@@ -0,0 +1,854 @@
|
||||
"""
|
||||
Android Hardware Camera2 Params 组件 — RggbChannelVector, BlackLevelPattern, StreamConfigurationMap 等
|
||||
方法签名完全对齐 Android SDK (android.hardware.camera2.params 包)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple
|
||||
|
||||
from .._core import Stub, AndroidOnlyError
|
||||
from ..java.lang import RuntimeException
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# RggbChannelVector
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class RggbChannelVector(Stub):
|
||||
"""RggbChannelVector — RGGB 通道向量"""
|
||||
|
||||
COUNT = 4
|
||||
|
||||
def __init__(self, red: float, green_even: float, green_odd: float, blue: float):
|
||||
super().__init__()
|
||||
self._red = red
|
||||
self._green_even = green_even
|
||||
self._green_odd = green_odd
|
||||
self._blue = blue
|
||||
|
||||
def getRed(self) -> float:
|
||||
return self._red
|
||||
|
||||
def getGreenEven(self) -> float:
|
||||
return self._green_even
|
||||
|
||||
def getGreenOdd(self) -> float:
|
||||
return self._green_odd
|
||||
|
||||
def getBlue(self) -> float:
|
||||
return self._blue
|
||||
|
||||
def getComponent(self, i: int) -> float:
|
||||
components = [self._red, self._green_even, self._green_odd, self._blue]
|
||||
return components[i]
|
||||
|
||||
def toFloatArray(self) -> List[float]:
|
||||
return [self._red, self._green_even, self._green_odd, self._blue]
|
||||
|
||||
def copyTo(self, destination: List[float], offset: int = 0):
|
||||
for i, v in enumerate([self._red, self._green_even, self._green_odd, self._blue]):
|
||||
destination[offset + i] = v
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, RggbChannelVector):
|
||||
return (abs(self._red - other._red) < 1e-6 and
|
||||
abs(self._green_even - other._green_even) < 1e-6 and
|
||||
abs(self._green_odd - other._green_odd) < 1e-6 and
|
||||
abs(self._blue - other._blue) < 1e-6)
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash((self._red, self._green_even, self._green_odd, self._blue)) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"RggbChannelVector(R={self._red:.3f}, Ge={self._green_even:.3f}, Go={self._green_odd:.3f}, B={self._blue:.3f})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# BlackLevelPattern
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class BlackLevelPattern(Stub):
|
||||
"""BlackLevelPattern — 黑电平模式"""
|
||||
|
||||
COUNT = 4
|
||||
|
||||
def __init__(self, red: int = 0, green_even: int = 0,
|
||||
green_odd: int = 0, blue: int = 0):
|
||||
super().__init__()
|
||||
self._offsets = [red, green_even, green_odd, blue]
|
||||
|
||||
def getOffsetForIndex(self, column: int, row: int) -> int:
|
||||
idx = (row % 2) * 2 + (column % 2)
|
||||
return self._offsets[idx]
|
||||
|
||||
def copyTo(self, destination: List[int], offset: int = 0):
|
||||
for i, v in enumerate(self._offsets):
|
||||
destination[offset + i] = v
|
||||
|
||||
def getRed(self) -> int:
|
||||
return self._offsets[0]
|
||||
|
||||
def getGreenEven(self) -> int:
|
||||
return self._offsets[1]
|
||||
|
||||
def getGreenOdd(self) -> int:
|
||||
return self._offsets[2]
|
||||
|
||||
def getBlue(self) -> int:
|
||||
return self._offsets[3]
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, BlackLevelPattern):
|
||||
return self._offsets == other._offsets
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash(tuple(self._offsets)) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"BlackLevelPattern(R={self._offsets[0]}, Ge={self._offsets[1]}, Go={self._offsets[2]}, B={self._offsets[3]})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# ColorSpaceTransform
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class ColorSpaceTransform(Stub):
|
||||
"""ColorSpaceTransform — 色彩空间变换 (3x3 矩阵)"""
|
||||
|
||||
COUNT = 9
|
||||
ELEMENTS_PER_ROW = 3
|
||||
ROWS = 3
|
||||
COLUMNS = 3
|
||||
|
||||
def __init__(self, elements: Optional[List[Rational]] = None):
|
||||
super().__init__()
|
||||
if elements is not None and len(elements) == 9:
|
||||
self._elements = list(elements)
|
||||
else:
|
||||
self._elements = [Rational(1, 1) if i % 4 == 0 else Rational(0, 1) for i in range(9)]
|
||||
|
||||
def getElement(self, column: int, row: int) -> Rational:
|
||||
return self._elements[row * 3 + column]
|
||||
|
||||
def setElement(self, column: int, row: int, element: Rational):
|
||||
self._elements[row * 3 + column] = element
|
||||
|
||||
def copyTo(self, destination: List[Rational], offset: int = 0):
|
||||
for i, v in enumerate(self._elements):
|
||||
destination[offset + i] = v
|
||||
|
||||
def getElements(self) -> List[Rational]:
|
||||
return list(self._elements)
|
||||
|
||||
def transform(self, r: float, g: float, b: float) -> Tuple[float, float, float]:
|
||||
e = self._elements
|
||||
r_out = e[0].toFloat() * r + e[1].toFloat() * g + e[2].toFloat() * b
|
||||
g_out = e[3].toFloat() * r + e[4].toFloat() * g + e[5].toFloat() * b
|
||||
b_out = e[6].toFloat() * r + e[7].toFloat() * g + e[8].toFloat() * b
|
||||
return (r_out, g_out, b_out)
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, ColorSpaceTransform):
|
||||
return all(abs(a.toFloat() - b.toFloat()) < 1e-6
|
||||
for a, b in zip(self._elements, other._elements))
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash(tuple(self._elements)) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return (f"ColorSpaceTransform([{self._elements[0]}, {self._elements[1]}, {self._elements[2]},"
|
||||
f" {self._elements[3]}, {self._elements[4]}, {self._elements[5]},"
|
||||
f" {self._elements[6]}, {self._elements[7]}, {self._elements[8]}])")
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Rational
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class Rational(Stub):
|
||||
"""Rational — 有理数"""
|
||||
|
||||
def __init__(self, numerator: int = 0, denominator: int = 1):
|
||||
super().__init__()
|
||||
if denominator < 0:
|
||||
numerator = -numerator
|
||||
denominator = -denominator
|
||||
gcd = math.gcd(abs(numerator), abs(denominator)) if denominator != 0 else 1
|
||||
self._numerator = numerator // gcd
|
||||
self._denominator = denominator // gcd
|
||||
|
||||
def getNumerator(self) -> int:
|
||||
return self._numerator
|
||||
|
||||
def getDenominator(self) -> int:
|
||||
return self._denominator
|
||||
|
||||
def toFloat(self) -> float:
|
||||
if self._denominator == 0:
|
||||
return float('inf') if self._numerator >= 0 else float('-inf')
|
||||
return self._numerator / self._denominator
|
||||
|
||||
def toDouble(self) -> float:
|
||||
return self.toFloat()
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, Rational):
|
||||
return (self._numerator * other._denominator ==
|
||||
other._numerator * self._denominator)
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash((self._numerator, self._denominator)) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"{self._numerator}/{self._denominator}"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# StreamConfigurationMap
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class StreamConfigurationMap(Stub):
|
||||
"""StreamConfigurationMap — 流配置映射"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._output_formats: Dict[int, List[Tuple[int, int]]] = {}
|
||||
self._input_formats: Dict[int, List[Tuple[int, int]]] = {}
|
||||
self._high_speed_video_sizes: Dict[int, List[Tuple[int, int]]] = {}
|
||||
self._output_min_frame_durations: Dict[Tuple[int, int, int], int] = {}
|
||||
self._output_stall_durations: Dict[Tuple[int, int, int], int] = {}
|
||||
self._input_min_frame_durations: Dict[Tuple[int, int, int], int] = {}
|
||||
self._input_stall_durations: Dict[Tuple[int, int, int], int] = {}
|
||||
self._mutable: bool = True
|
||||
|
||||
def getOutputFormats(self) -> List[int]:
|
||||
return list(self._output_formats.keys())
|
||||
|
||||
def getInputFormats(self) -> List[int]:
|
||||
return list(self._input_formats.keys())
|
||||
|
||||
def getOutputSizes(self, format: int) -> List[Tuple[int, int]]:
|
||||
return list(self._output_formats.get(format, []))
|
||||
|
||||
def getInputSizes(self, format: int) -> List[Tuple[int, int]]:
|
||||
return list(self._input_formats.get(format, []))
|
||||
|
||||
def getHighSpeedVideoSizes(self) -> List[Tuple[int, int]]:
|
||||
result = set()
|
||||
for sizes in self._high_speed_video_sizes.values():
|
||||
result.update(sizes)
|
||||
return list(result)
|
||||
|
||||
def getHighSpeedVideoFpsRangeFor(self, size: Tuple[int, int]) -> List[Tuple[int, int]]:
|
||||
return [(30, 30), (60, 60), (120, 120)]
|
||||
|
||||
def getHighSpeedVideoFpsRanges(self) -> List[Tuple[int, int]]:
|
||||
return [(30, 30), (60, 60), (120, 120), (240, 240)]
|
||||
|
||||
def getOutputMinFrameDuration(self, format: int, size: Tuple[int, int]) -> int:
|
||||
return self._output_min_frame_durations.get((format, size[0], size[1]), 33333333)
|
||||
|
||||
def getOutputStallDuration(self, format: int, size: Tuple[int, int]) -> int:
|
||||
return self._output_stall_durations.get((format, size[0], size[1]), 0)
|
||||
|
||||
def getInputMinFrameDuration(self, format: int, size: Tuple[int, int]) -> int:
|
||||
return self._input_min_frame_durations.get((format, size[0], size[1]), 33333333)
|
||||
|
||||
def getInputStallDuration(self, format: int, size: Tuple[int, int]) -> int:
|
||||
return self._input_stall_durations.get((format, size[0], size[1]), 0)
|
||||
|
||||
def isOutputSupportedFor(self, size: Tuple[int, int]) -> bool:
|
||||
for sizes in self._output_formats.values():
|
||||
if size in sizes:
|
||||
return True
|
||||
return False
|
||||
|
||||
def isValid(self) -> bool:
|
||||
return len(self._output_formats) > 0
|
||||
|
||||
def setMutable(self, mutable: bool):
|
||||
self._mutable = mutable
|
||||
|
||||
def isMutable(self) -> bool:
|
||||
return self._mutable
|
||||
|
||||
def addOutputFormat(self, format: int, sizes: List[Tuple[int, int]]):
|
||||
self._output_formats[format] = list(sizes)
|
||||
|
||||
def addInputFormat(self, format: int, sizes: List[Tuple[int, int]]):
|
||||
self._input_formats[format] = list(sizes)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"StreamConfigurationMap(outputFormats={len(self._output_formats)})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# TonemapCurve
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class TonemapCurve(Stub):
|
||||
"""TonemapCurve — 色调映射曲线"""
|
||||
|
||||
LEVEL_BLACK = 0
|
||||
LEVEL_WHITE = 1
|
||||
|
||||
CHANNEL_RED = 0
|
||||
CHANNEL_GREEN = 1
|
||||
CHANNEL_BLUE = 2
|
||||
|
||||
POINT_SIZE = 2
|
||||
|
||||
def __init__(self, red_curve: Optional[List[float]] = None,
|
||||
green_curve: Optional[List[float]] = None,
|
||||
blue_curve: Optional[List[float]] = None):
|
||||
super().__init__()
|
||||
self._curves = {
|
||||
TonemapCurve.CHANNEL_RED: list(red_curve or [0.0, 0.0, 1.0, 1.0]),
|
||||
TonemapCurve.CHANNEL_GREEN: list(green_curve or [0.0, 0.0, 1.0, 1.0]),
|
||||
TonemapCurve.CHANNEL_BLUE: list(blue_curve or [0.0, 0.0, 1.0, 1.0]),
|
||||
}
|
||||
|
||||
def getPointCount(self, channel: int) -> int:
|
||||
return len(self._curves.get(channel, [])) // 2
|
||||
|
||||
def getPoint(self, channel: int, index: int, out_point: List[float] = None) -> Tuple[float, float]:
|
||||
curve = self._curves.get(channel, [])
|
||||
if out_point is None:
|
||||
out_point = [0.0, 0.0]
|
||||
out_point[0] = curve[index * 2]
|
||||
out_point[1] = curve[index * 2 + 1]
|
||||
return (out_point[0], out_point[1])
|
||||
|
||||
def setPoint(self, channel: int, index: int, x: float, y: float):
|
||||
curve = self._curves[channel]
|
||||
while len(curve) < (index * 2 + 2):
|
||||
curve.extend([0.0, 0.0])
|
||||
curve[index * 2] = x
|
||||
curve[index * 2 + 1] = y
|
||||
|
||||
def getCurve(self, channel: int) -> Optional[List[float]]:
|
||||
return list(self._curves.get(channel, []))
|
||||
|
||||
def estimateCurve(self, channel: int, x: float) -> float:
|
||||
curve = self._curves.get(channel, [])
|
||||
if not curve or len(curve) < 4:
|
||||
return x
|
||||
for i in range(0, len(curve) - 2, 2):
|
||||
x0, y0 = curve[i], curve[i + 1]
|
||||
x1, y1 = curve[i + 2], curve[i + 3]
|
||||
if x0 <= x <= x1 or (x1 <= x <= x0):
|
||||
if abs(x1 - x0) < 1e-10:
|
||||
return y0
|
||||
t = (x - x0) / (x1 - x0)
|
||||
return y0 + t * (y1 - y0)
|
||||
return curve[-1] if curve else x
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, TonemapCurve):
|
||||
return all(abs(self._curves[c][i] - other._curves[c][i]) < 1e-6
|
||||
for c in range(3) for i in range(len(self._curves[c])))
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash(tuple(tuple(v) for v in self._curves.values())) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"TonemapCurve(points={self.getPointCount(0)}, {self.getPointCount(1)}, {self.getPointCount(2)})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# LensShadingMap
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class LensShadingMap(Stub):
|
||||
"""LensShadingMap — 镜头阴影映射"""
|
||||
|
||||
def __init__(self, columns: int = 1, rows: int = 1):
|
||||
super().__init__()
|
||||
self._columns = columns
|
||||
self._rows = rows
|
||||
self._gain_map: Dict[Tuple[int, int, int], float] = {}
|
||||
|
||||
def getGainFactor(self, channel: int, column: int, row: int) -> float:
|
||||
return self._gain_map.get((channel, column, row), 1.0)
|
||||
|
||||
def setGainFactor(self, channel: int, column: int, row: int, gain: float):
|
||||
self._gain_map[(channel, column, row)] = gain
|
||||
|
||||
def getGainFactorVector(self, column: int, row: int) -> RggbChannelVector:
|
||||
r = self.getGainFactor(0, column, row)
|
||||
ge = self.getGainFactor(1, column, row)
|
||||
go = self.getGainFactor(2, column, row)
|
||||
b = self.getGainFactor(3, column, row)
|
||||
return RggbChannelVector(r, ge, go, b)
|
||||
|
||||
def getColumnCount(self) -> int:
|
||||
return self._columns
|
||||
|
||||
def getRowCount(self) -> int:
|
||||
return self._rows
|
||||
|
||||
def copyGainFactors(self, destination: List[float], offset: int = 0):
|
||||
for (ch, col, row), gain in self._gain_map.items():
|
||||
idx = offset + (row * self._columns + col) * 4 + ch
|
||||
if idx < len(destination):
|
||||
destination[idx] = gain
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, LensShadingMap):
|
||||
return (self._columns == other._columns and self._rows == other._rows
|
||||
and self._gain_map == other._gain_map)
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash((self._columns, self._rows, tuple(sorted(self._gain_map.items())))) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"LensShadingMap({self._columns}x{self._rows})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MeteringRectangle
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MeteringRectangle(Stub):
|
||||
"""MeteringRectangle — 测光矩形"""
|
||||
|
||||
def __init__(self, x: int = 0, y: int = 0, width: int = 0,
|
||||
height: int = 0, metering_weight: int = 1):
|
||||
super().__init__()
|
||||
self._x = x
|
||||
self._y = y
|
||||
self._width = width
|
||||
self._height = height
|
||||
self._metering_weight = metering_weight
|
||||
|
||||
def getX(self) -> int:
|
||||
return self._x
|
||||
|
||||
def getY(self) -> int:
|
||||
return self._y
|
||||
|
||||
def getWidth(self) -> int:
|
||||
return self._width
|
||||
|
||||
def getHeight(self) -> int:
|
||||
return self._height
|
||||
|
||||
def getMeteringWeight(self) -> int:
|
||||
return self._metering_weight
|
||||
|
||||
def getRect(self) -> Tuple[int, int, int, int]:
|
||||
return (self._x, self._y, self._x + self._width, self._y + self._height)
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, MeteringRectangle):
|
||||
return (self._x == other._x and self._y == other._y
|
||||
and self._width == other._width
|
||||
and self._height == other._height
|
||||
and self._metering_weight == other._metering_weight)
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash((self._x, self._y, self._width, self._height, self._metering_weight)) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"MeteringRectangle({self._x},{self._y} {self._width}x{self._height} w={self._metering_weight})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# OutputConfiguration
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class OutputConfiguration(Stub):
|
||||
"""OutputConfiguration — 输出配置"""
|
||||
|
||||
SURFACE_TYPE_UNKNOWN = -1
|
||||
SURFACE_TYPE_SURFACE_VIEW = 0
|
||||
SURFACE_TYPE_SURFACE_TEXTURE = 1
|
||||
SURFACE_TYPE_IMAGE_READER = 2
|
||||
SURFACE_TYPE_MEDIA_CODEC = 3
|
||||
SURFACE_TYPE_MEDIA_RECORDER = 4
|
||||
|
||||
ROTATION_0 = 0
|
||||
ROTATION_90 = 1
|
||||
ROTATION_180 = 2
|
||||
ROTATION_270 = 3
|
||||
|
||||
def __init__(self, surface: Any = None, surface_type: int = SURFACE_TYPE_UNKNOWN):
|
||||
super().__init__()
|
||||
self._surface = surface
|
||||
self._surface_type = surface_type
|
||||
self._rotation: int = OutputConfiguration.ROTATION_0
|
||||
self._width: int = 0
|
||||
self._height: int = 0
|
||||
self._format: int = 0
|
||||
self._is_deferred: bool = False
|
||||
self._physical_camera_id: str = ""
|
||||
self._surface_set: List[Any] = []
|
||||
self._shared_surfaces: List[Any] = []
|
||||
self._capture_stage: int = 0
|
||||
|
||||
def getSurface(self) -> Any:
|
||||
return self._surface
|
||||
|
||||
def setSurface(self, surface: Any):
|
||||
self._surface = surface
|
||||
|
||||
def getSurfaceType(self) -> int:
|
||||
return self._surface_type
|
||||
|
||||
def setSurfaceType(self, type_: int):
|
||||
self._surface_type = type_
|
||||
|
||||
def getRotation(self) -> int:
|
||||
return self._rotation
|
||||
|
||||
def setRotation(self, rotation: int):
|
||||
self._rotation = rotation
|
||||
|
||||
def getWidth(self) -> int:
|
||||
return self._width
|
||||
|
||||
def getHeight(self) -> int:
|
||||
return self._height
|
||||
|
||||
def getFormat(self) -> int:
|
||||
return self._format
|
||||
|
||||
def setDimensions(self, width: int, height: int):
|
||||
self._width = width
|
||||
self._height = height
|
||||
|
||||
def setFormat(self, format: int):
|
||||
self._format = format
|
||||
|
||||
def isDeferred(self) -> bool:
|
||||
return self._is_deferred
|
||||
|
||||
def setDeferred(self, deferred: bool):
|
||||
self._is_deferred = deferred
|
||||
|
||||
def getPhysicalCameraId(self) -> str:
|
||||
return self._physical_camera_id
|
||||
|
||||
def setPhysicalCameraId(self, camera_id: str):
|
||||
self._physical_camera_id = camera_id
|
||||
|
||||
def addSurface(self, surface: Any):
|
||||
self._surface_set.append(surface)
|
||||
|
||||
def removeSurface(self, surface: Any):
|
||||
self._surface_set = [s for s in self._surface_set if s is not surface]
|
||||
|
||||
def getSurfaces(self) -> List[Any]:
|
||||
return list(self._surface_set)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"OutputConfiguration({self._width}x{self._height}, rot={self._rotation})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# SessionConfiguration
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class SessionConfiguration(Stub):
|
||||
"""SessionConfiguration — 会话配置"""
|
||||
|
||||
SESSION_TYPE_REGULAR = 0
|
||||
SESSION_TYPE_VENDOR = 1
|
||||
SESSION_TYPE_HIGH_SPEED = 2
|
||||
SESSION_TYPE_LOW_LATENCY = 3
|
||||
SESSION_TYPE_OFFLINE_PROCESSING = 4
|
||||
|
||||
def __init__(self, session_type: int = SESSION_TYPE_REGULAR,
|
||||
outputs: Optional[List[OutputConfiguration]] = None,
|
||||
callback: Any = None):
|
||||
super().__init__()
|
||||
self._session_type = session_type
|
||||
self._outputs = list(outputs or [])
|
||||
self._callback = callback
|
||||
self._input_config: Optional[OutputConfiguration] = None
|
||||
self._session_params: Any = None
|
||||
self._implementation: Any = None
|
||||
self._color_space: int = 0
|
||||
self._is_global_session: bool = False
|
||||
|
||||
def getSessionType(self) -> int:
|
||||
return self._session_type
|
||||
|
||||
def getOutputConfigurations(self) -> List[OutputConfiguration]:
|
||||
return list(self._outputs)
|
||||
|
||||
def addOutputConfiguration(self, output: OutputConfiguration):
|
||||
self._outputs.append(output)
|
||||
|
||||
def removeOutputConfiguration(self, output: OutputConfiguration):
|
||||
self._outputs = [o for o in self._outputs if o is not output]
|
||||
|
||||
def setInputConfiguration(self, input_config: OutputConfiguration):
|
||||
self._input_config = input_config
|
||||
|
||||
def getInputConfiguration(self) -> Optional[OutputConfiguration]:
|
||||
return self._input_config
|
||||
|
||||
def setSessionParameters(self, params: Any):
|
||||
self._session_params = params
|
||||
|
||||
def getSessionParameters(self) -> Any:
|
||||
return self._session_params
|
||||
|
||||
def setColorSpace(self, color_space: int):
|
||||
self._color_space = color_space
|
||||
|
||||
def getColorSpace(self) -> int:
|
||||
return self._color_space
|
||||
|
||||
def getCallback(self) -> Any:
|
||||
return self._callback
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"SessionConfiguration(type={self._session_type}, outputs={len(self._outputs)})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# MultiResolutionStreamConfigurationMap
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class MultiResolutionStreamConfigurationMap(Stub):
|
||||
"""MultiResolutionStreamConfigurationMap — 多分辨率流配置映射"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._configs: Dict[int, List[OutputConfiguration]] = {}
|
||||
|
||||
def getOutputConfigurations(self, format: int) -> List[OutputConfiguration]:
|
||||
return list(self._configs.get(format, []))
|
||||
|
||||
def getFormats(self) -> List[int]:
|
||||
return list(self._configs.keys())
|
||||
|
||||
def addConfiguration(self, format: int, config: OutputConfiguration):
|
||||
if format not in self._configs:
|
||||
self._configs[format] = []
|
||||
self._configs[format].append(config)
|
||||
|
||||
def removeConfiguration(self, format: int, config: OutputConfiguration):
|
||||
if format in self._configs:
|
||||
self._configs[format] = [c for c in self._configs[format] if c is not config]
|
||||
|
||||
def getMaxResolution(self, format: int) -> Optional[OutputConfiguration]:
|
||||
configs = self._configs.get(format, [])
|
||||
if not configs:
|
||||
return None
|
||||
return max(configs, key=lambda c: c.getWidth() * c.getHeight())
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"MultiResolutionStreamConfigurationMap(formats={len(self._configs)})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# OisSample
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class OisSample(Stub):
|
||||
"""OisSample — OIS 样本数据"""
|
||||
|
||||
def __init__(self, timestamp_ns: int = 0, x_shift: float = 0.0, y_shift: float = 0.0):
|
||||
super().__init__()
|
||||
self._timestamp_ns = timestamp_ns
|
||||
self._x_shift = x_shift
|
||||
self._y_shift = y_shift
|
||||
|
||||
def getTimestampNanos(self) -> int:
|
||||
return self._timestamp_ns
|
||||
|
||||
def getXshift(self) -> float:
|
||||
return self._x_shift
|
||||
|
||||
def getYshift(self) -> float:
|
||||
return self._y_shift
|
||||
|
||||
def equals(self, other: Any) -> bool:
|
||||
if isinstance(other, OisSample):
|
||||
return (self._timestamp_ns == other._timestamp_ns
|
||||
and abs(self._x_shift - other._x_shift) < 1e-6
|
||||
and abs(self._y_shift - other._y_shift) < 1e-6)
|
||||
return False
|
||||
|
||||
def hashCode(self) -> int:
|
||||
return hash((self._timestamp_ns, self._x_shift, self._y_shift)) & 0x7FFFFFFF
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"OisSample(ts={self._timestamp_ns}, x={self._x_shift:.3f}, y={self._y_shift:.3f})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# RecommendedStreamConfiguration
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class RecommendedStreamConfiguration(Stub):
|
||||
"""RecommendedStreamConfiguration — 推荐流配置"""
|
||||
|
||||
USECASE_PREVIEW = 0
|
||||
USECASE_RECORD = 1
|
||||
USECASE_STILL_CAPTURE = 2
|
||||
USECASE_VIDEO_SNAPSHOT = 3
|
||||
USECASE_ZSL = 4
|
||||
USECASE_RAW = 5
|
||||
USECASE_LOW_LATENCY_SNAPSHOT = 6
|
||||
USECASE_10BIT_OUTPUT = 7
|
||||
USECASE_ANALYSIS = 8
|
||||
USECASE_CUSTOM = 9
|
||||
USECASE_VENDOR_START = 0x1000
|
||||
|
||||
def __init__(self, width: int = 0, height: int = 0, format: int = 0,
|
||||
input_output: bool = False, usecase: int = USECASE_PREVIEW):
|
||||
super().__init__()
|
||||
self._width = width
|
||||
self._height = height
|
||||
self._format = format
|
||||
self._input_output = input_output
|
||||
self._usecase = usecase
|
||||
self._fps_range: Tuple[int, int] = (30, 30)
|
||||
self._is_high_speed: bool = False
|
||||
|
||||
def getWidth(self) -> int:
|
||||
return self._width
|
||||
|
||||
def getHeight(self) -> int:
|
||||
return self._height
|
||||
|
||||
def getFormat(self) -> int:
|
||||
return self._format
|
||||
|
||||
def isInput(self) -> bool:
|
||||
return self._input_output
|
||||
|
||||
def isOutput(self) -> bool:
|
||||
return not self._input_output
|
||||
|
||||
def getUsecase(self) -> int:
|
||||
return self._usecase
|
||||
|
||||
def getFpsRange(self) -> Tuple[int, int]:
|
||||
return self._fps_range
|
||||
|
||||
def setFpsRange(self, min_fps: int, max_fps: int):
|
||||
self._fps_range = (min_fps, max_fps)
|
||||
|
||||
def isHighSpeed(self) -> bool:
|
||||
return self._is_high_speed
|
||||
|
||||
def setHighSpeed(self, high_speed: bool):
|
||||
self._is_high_speed = high_speed
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"RecommendedStreamConfiguration({self._width}x{self._height}, fmt={self._format})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# RecommendedStreamConfigurationMap
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class RecommendedStreamConfigurationMap(Stub):
|
||||
"""RecommendedStreamConfigurationMap — 推荐流配置映射"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._recommendations: Dict[int, List[RecommendedStreamConfiguration]] = {}
|
||||
self._max_resolutions: Dict[int, Tuple[int, int]] = {}
|
||||
|
||||
def getRecommendedStreamConfigurations(self, usecase: int) -> List[RecommendedStreamConfiguration]:
|
||||
return list(self._recommendations.get(usecase, []))
|
||||
|
||||
def getAllUsecases(self) -> List[int]:
|
||||
return list(self._recommendations.keys())
|
||||
|
||||
def addRecommendation(self, usecase: int, config: RecommendedStreamConfiguration):
|
||||
if usecase not in self._recommendations:
|
||||
self._recommendations[usecase] = []
|
||||
self._recommendations[usecase].append(config)
|
||||
|
||||
def removeRecommendation(self, usecase: int, config: RecommendedStreamConfiguration):
|
||||
if usecase in self._recommendations:
|
||||
self._recommendations[usecase] = [
|
||||
c for c in self._recommendations[usecase] if c is not config
|
||||
]
|
||||
|
||||
def getMaxResolution(self, usecase: int) -> Optional[Tuple[int, int]]:
|
||||
return self._max_resolutions.get(usecase)
|
||||
|
||||
def setMaxResolution(self, usecase: int, width: int, height: int):
|
||||
self._max_resolutions[usecase] = (width, height)
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"RecommendedStreamConfigurationMap(usecases={len(self._recommendations)})"
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# TotalCaptureResultExt — TotalCaptureResult 的扩展
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class TotalCaptureResultExt(Stub):
|
||||
"""TotalCaptureResultExt — TotalCaptureResult 的 params 扩展"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._results: Dict[str, Any] = {}
|
||||
self._partial_results: List[Any] = []
|
||||
self._session_id: int = 0
|
||||
self._frame_number: int = 0
|
||||
self._sequence_id: int = 0
|
||||
self._af_trigger_id: int = 0
|
||||
self._ae_trigger_id: int = 0
|
||||
self._sensor_timestamp: int = 0
|
||||
self._physical_camera_results: Dict[str, Any] = {}
|
||||
|
||||
def getResult(self, key: str) -> Optional[Any]:
|
||||
return self._results.get(key)
|
||||
|
||||
def setResult(self, key: str, value: Any):
|
||||
self._results[key] = value
|
||||
|
||||
def getAllResults(self) -> Dict[str, Any]:
|
||||
return dict(self._results)
|
||||
|
||||
def getPartialResults(self) -> List[Any]:
|
||||
return list(self._partial_results)
|
||||
|
||||
def addPartialResult(self, result: Any):
|
||||
self._partial_results.append(result)
|
||||
|
||||
def getSessionId(self) -> int:
|
||||
return self._session_id
|
||||
|
||||
def setSessionId(self, session_id: int):
|
||||
self._session_id = session_id
|
||||
|
||||
def getFrameNumber(self) -> int:
|
||||
return self._frame_number
|
||||
|
||||
def setFrameNumber(self, frame: int):
|
||||
self._frame_number = frame
|
||||
|
||||
def getSequenceId(self) -> int:
|
||||
return self._sequence_id
|
||||
|
||||
def setSequenceId(self, seq: int):
|
||||
self._sequence_id = seq
|
||||
|
||||
def getPhysicalCameraResult(self, camera_id: str) -> Optional[Any]:
|
||||
return self._physical_camera_results.get(camera_id)
|
||||
|
||||
def setPhysicalCameraResult(self, camera_id: str, result: Any):
|
||||
self._physical_camera_results[camera_id] = result
|
||||
|
||||
def toString(self) -> str:
|
||||
return f"TotalCaptureResultExt(frame={self._frame_number}, seq={self._sequence_id})"
|
||||
Reference in new issue
Block a user