""" Android Camera2 组件 — CameraManager, CameraDevice, CaptureRequest 等 方法签名完全对齐 Android SDK """ import time from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union from .._core import Stub, AndroidOnlyError, android_context, HAS_PIL # ═══════════════════════════════════════════════════════════════ # CameraMetadata # ═══════════════════════════════════════════════════════════════ class CameraMetadata(Stub): """CameraMetadata — 相机元数据基类""" # CONTROL_AE modes CONTROL_AE_MODE_OFF = 0 CONTROL_AE_MODE_ON = 1 CONTROL_AE_MODE_ON_AUTO_FLASH = 2 CONTROL_AE_MODE_ON_ALWAYS_FLASH = 3 CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4 CONTROL_AE_MODE_EXTERNAL_FLASH = 5 # CONTROL_AF modes CONTROL_AF_MODE_OFF = 0 CONTROL_AF_MODE_AUTO = 1 CONTROL_AF_MODE_MACRO = 2 CONTROL_AF_MODE_CONTINUOUS_VIDEO = 3 CONTROL_AF_MODE_CONTINUOUS_PICTURE = 4 CONTROL_AF_MODE_EDOF = 5 # CONTROL_AWB modes CONTROL_AWB_MODE_OFF = 0 CONTROL_AWB_MODE_AUTO = 1 CONTROL_AWB_MODE_INCANDESCENT = 2 CONTROL_AWB_MODE_FLUORESCENT = 3 CONTROL_AWB_MODE_WARM_FLUORESCENT = 4 CONTROL_AWB_MODE_DAYLIGHT = 5 CONTROL_AWB_MODE_CLOUDY_DAYLIGHT = 6 CONTROL_AWB_MODE_TWILIGHT = 7 CONTROL_AWB_MODE_SHADE = 8 # CONTROL modes CONTROL_MODE_OFF = 0 CONTROL_MODE_AUTO = 1 CONTROL_MODE_USE_SCENE_MODE = 2 CONTROL_MODE_OFF_KEEP_STATE = 3 # FLASH modes FLASH_MODE_OFF = 0 FLASH_MODE_SINGLE = 1 FLASH_MODE_TORCH = 2 # STATISTICS_FACE_DETECT modes STATISTICS_FACE_DETECT_MODE_OFF = 0 STATISTICS_FACE_DETECT_MODE_SIMPLE = 1 STATISTICS_FACE_DETECT_MODE_FULL = 2 # EDGE modes EDGE_MODE_OFF = 0 EDGE_MODE_FAST = 1 EDGE_MODE_HIGH_QUALITY = 2 EDGE_MODE_ZERO_SHUTTER_LAG = 3 # NOISE_REDUCTION modes NOISE_REDUCTION_MODE_OFF = 0 NOISE_REDUCTION_MODE_FAST = 1 NOISE_REDUCTION_MODE_HIGH_QUALITY = 2 NOISE_REDUCTION_MODE_MINIMAL = 3 NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG = 4 # TONEMAP modes TONEMAP_MODE_CONTRAST_CURVE = 0 TONEMAP_MODE_FAST = 1 TONEMAP_MODE_HIGH_QUALITY = 2 TONEMAP_MODE_GAMMA_VALUE = 3 TONEMAP_MODE_PRESET_CURVE = 4 # COLOR_CORRECTION modes COLOR_CORRECTION_MODE_TRANSFORM_MATRIX = 0 COLOR_CORRECTION_MODE_FAST = 1 COLOR_CORRECTION_MODE_HIGH_QUALITY = 2 # COLOR_CORRECTION_ABERRATION modes COLOR_CORRECTION_ABERRATION_MODE_OFF = 0 COLOR_CORRECTION_ABERRATION_MODE_FAST = 1 COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2 # CONTROL_AE_PRECAPTURE_TRIGGER CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0 CONTROL_AE_PRECAPTURE_TRIGGER_START = 1 CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2 # CONTROL_EFFECT modes CONTROL_EFFECT_MODE_OFF = 0 CONTROL_EFFECT_MODE_MONO = 1 CONTROL_EFFECT_MODE_NEGATIVE = 2 CONTROL_EFFECT_MODE_SOLARIZE = 3 CONTROL_EFFECT_MODE_SEPIA = 4 CONTROL_EFFECT_MODE_POSTERIZE = 5 CONTROL_EFFECT_MODE_WHITEBOARD = 6 CONTROL_EFFECT_MODE_BLACKBOARD = 7 CONTROL_EFFECT_MODE_AQUA = 8 # CONTROL_SCENE modes CONTROL_SCENE_MODE_DISABLED = 0 CONTROL_SCENE_MODE_FACE_PRIORITY = 1 CONTROL_SCENE_MODE_ACTION = 2 CONTROL_SCENE_MODE_PORTRAIT = 3 CONTROL_SCENE_MODE_LANDSCAPE = 4 CONTROL_SCENE_MODE_NIGHT = 5 CONTROL_SCENE_MODE_NIGHT_PORTRAIT = 6 CONTROL_SCENE_MODE_THEATRE = 7 CONTROL_SCENE_MODE_BEACH = 8 CONTROL_SCENE_MODE_SNOW = 9 CONTROL_SCENE_MODE_SUNSET = 10 CONTROL_SCENE_MODE_STEADYPHOTO = 11 CONTROL_SCENE_MODE_FIREWORKS = 12 CONTROL_SCENE_MODE_SPORTS = 13 CONTROL_SCENE_MODE_PARTY = 14 CONTROL_SCENE_MODE_CANDLELIGHT = 15 CONTROL_SCENE_MODE_BARCODE = 16 CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17 CONTROL_SCENE_MODE_HDR = 18 # CONTROL_VIDEO_STABILIZATION modes CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0 CONTROL_VIDEO_STABILIZATION_MODE_ON = 1 # DISTORTION_CORRECTION modes DISTORTION_CORRECTION_MODE_OFF = 0 DISTORTION_CORRECTION_MODE_FAST = 1 DISTORTION_CORRECTION_MODE_HIGH_QUALITY = 2 # HOT_PIXEL modes HOT_PIXEL_MODE_OFF = 0 HOT_PIXEL_MODE_FAST = 1 HOT_PIXEL_MODE_HIGH_QUALITY = 2 # LENS_OPTICAL_STABILIZATION modes LENS_OPTICAL_STABILIZATION_MODE_OFF = 0 LENS_OPTICAL_STABILIZATION_MODE_ON = 1 # LENS_FACING LENS_FACING_FRONT = 0 LENS_FACING_BACK = 1 LENS_FACING_EXTERNAL = 2 # INFO_SUPPORTED_HARDWARE_LEVEL INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0 INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1 INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2 INFO_SUPPORTED_HARDWARE_LEVEL_3 = 3 INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL = 4 # ═══════════════════════════════════════════════════════════════ # CameraCharacteristics # ═══════════════════════════════════════════════════════════════ class CameraCharacteristics(CameraMetadata): """CameraCharacteristics — 相机特性""" LENS_FACING = "android.lens.facing" SENSOR_ORIENTATION = "android.sensor.orientation" FLASH_INFO_AVAILABLE = "android.flash.info.available" INFO_SUPPORTED_HARDWARE_LEVEL = "android.info.supportedHardwareLevel" SCALER_STREAM_CONFIGURATION_MAP = "android.scaler.streamConfigurationMap" CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES = "android.control.aeAvailableTargetFpsRanges" CONTROL_AE_AVAILABLE_MODES = "android.control.aeAvailableModes" CONTROL_AF_AVAILABLE_MODES = "android.control.afAvailableModes" CONTROL_AVAILABLE_EFFECTS = "android.control.availableEffects" CONTROL_AVAILABLE_SCENE_MODES = "android.control.availableSceneModes" CONTROL_MAX_REGIONS_AE = "android.control.maxRegionsAe" CONTROL_MAX_REGIONS_AF = "android.control.maxRegionsAf" CONTROL_MAX_REGIONS_AWB = "android.control.maxRegionsAwb" JPEG_AVAILABLE_THUMBNAIL_SIZES = "android.jpeg.availableThumbnailSizes" JPEG_MAX_SIZE = "android.jpeg.maxSize" SENSOR_INFO_PIXEL_ARRAY_SIZE = "android.sensor.info.pixelArraySize" SENSOR_INFO_ACTIVE_ARRAY_SIZE = "android.sensor.info.activeArraySize" FLASH_MODE = "android.flash.mode" def __init__(self, camera_id: str = "0"): super().__init__() self._properties: Dict[str, Any] = { CameraCharacteristics.LENS_FACING: CameraCharacteristics.LENS_FACING_BACK, CameraCharacteristics.SENSOR_ORIENTATION: 90, CameraCharacteristics.FLASH_INFO_AVAILABLE: True, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL: CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP: { "output_sizes": [(1920, 1080), (1280, 720), (640, 480)], "input_sizes": [(1920, 1080)], }, CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES: [(15, 30), (30, 30)], CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES: [0, 1, 2, 3, 4], CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES: [0, 1, 2, 3, 4, 5], CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS: list(range(9)), CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES: list(range(19)), CameraCharacteristics.CONTROL_MAX_REGIONS_AE: 1, CameraCharacteristics.CONTROL_MAX_REGIONS_AF: 1, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB: 0, CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES: [(320, 240), (160, 120)], CameraCharacteristics.JPEG_MAX_SIZE: 5000000, CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE: (4032, 3024), CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE: (4032, 3024), } def get(self, key: str) -> Any: return self._properties.get(key) def keys(self) -> Set[str]: return set(self._properties.keys()) def query(self, key: str) -> Any: return self._properties.get(key) # ═══════════════════════════════════════════════════════════════ # CameraId # ═══════════════════════════════════════════════════════════════ class CameraId(Stub): """CameraId — 相机ID封装""" def __init__(self, id_string: str): super().__init__() self._id = id_string def getId(self) -> str: return self._id def toString(self) -> str: return self._id def equals(self, other) -> bool: if isinstance(other, CameraId): return self._id == other._id if isinstance(other, str): return self._id == other return False def hashCode(self) -> int: return hash(self._id) # ═══════════════════════════════════════════════════════════════ # CameraCharacteristicsKey # ═══════════════════════════════════════════════════════════════ class CameraCharacteristicsKey(Stub): """CameraCharacteristicsKey — 相机特性键""" def __init__(self, name: str, native_type: type = object): super().__init__() self._name = name self._native_type = native_type def getName(self) -> str: return self._name def getNativeType(self) -> type: return self._native_type def equals(self, other) -> bool: if isinstance(other, CameraCharacteristicsKey): return self._name == other._name return False def hashCode(self) -> int: return hash(self._name) def toString(self) -> str: return f"CameraCharacteristicsKey({self._name})" # ═══════════════════════════════════════════════════════════════ # CaptureRequest # ═══════════════════════════════════════════════════════════════ class CaptureRequest(CameraMetadata): """CaptureRequest — 捕获请求""" CONTROL_AE_MODE = "android.control.aeMode" CONTROL_AF_MODE = "android.control.afMode" CONTROL_AWB_MODE = "android.control.awbMode" CONTROL_MODE = "android.control.mode" FLASH_MODE = "android.flash.mode" SENSOR_EXPOSURE_TIME = "android.sensor.exposureTime" SENSOR_SENSITIVITY = "android.sensor.sensitivity" LENS_FOCUS_DISTANCE = "android.lens.focusDistance" STATISTICS_FACE_DETECT_MODE = "android.statistics.faceDetectMode" JPEG_QUALITY = "android.jpeg.quality" JPEG_ORIENTATION = "android.jpeg.orientation" JPEG_THUMBNAIL_QUALITY = "android.jpeg.thumbnailQuality" JPEG_THUMBNAIL_SIZE = "android.jpeg.thumbnailSize" SCALER_CROP_REGION = "android.scaler.cropRegion" EDGE_MODE = "android.edge.mode" NOISE_REDUCTION_MODE = "android.noiseReduction.mode" TONEMAP_MODE = "android.tonemap.mode" BLACK_LEVEL_LOCK = "android.blackLevel.lock" CONTROL_AE_TARGET_FPS_RANGE = "android.control.aeTargetFpsRange" CONTROL_AE_EXPOSURE_COMPENSATION = "android.control.aeExposureCompensation" CONTROL_AE_LOCK = "android.control.aeLock" CONTROL_AE_PRECAPTURE_TRIGGER = "android.control.aePrecaptureTrigger" CONTROL_AWB_LOCK = "android.control.awbLock" CONTROL_EFFECT_MODE = "android.control.effectMode" CONTROL_SCENE_MODE = "android.control.sceneMode" CONTROL_VIDEO_STABILIZATION_MODE = "android.control.videoStabilizationMode" COLOR_CORRECTION_MODE = "android.colorCorrection.mode" COLOR_CORRECTION_GAINS = "android.colorCorrection.gains" COLOR_CORRECTION_TRANSFORM = "android.colorCorrection.transform" COLOR_CORRECTION_ABERRATION_MODE = "android.colorCorrection.aberrationMode" CONTROL_POST_RAW_SENSITIVITY_BOOST = "android.control.postRawSensitivityBoost" DISTORTION_CORRECTION_MODE = "android.distortionCorrection.mode" HOT_PIXEL_MODE = "android.hotPixel.mode" LENS_OPTICAL_STABILIZATION_MODE = "android.lens.opticalStabilizationMode" REQUEST_PIPELINE_MAX_DEPTH = "android.request.pipelineMaxDepth" SENSOR_TIMESTAMP = "android.sensor.timestamp" STATISTICS_LENS_SHADING_MAP_MODE = "android.statistics.lensShadingMapMode" STATISTICS_OIS_DATA_MODE = "android.statistics.oisDataMode" STATISTICS_SECTION = "android.statistics.section" TONEMAP_CURVE = "android.tonemap.curve" TONEMAP_GAMMA = "android.tonemap.gamma" class Builder(Stub): """CaptureRequest.Builder — 捕获请求构建器""" def __init__(self, camera_device: "CameraDevice"): super().__init__() self._parameters: Dict[str, Any] = {} self._tag = None self._camera_device = camera_device def set(self, key: str, value: Any): self._parameters[key] = value def get(self, key: str) -> Any: return self._parameters.get(key) def setTag(self, tag: Any): self._tag = tag def build(self) -> "CaptureRequest": req = CaptureRequest() req._parameters = dict(self._parameters) req._tag = self._tag return req def addTarget(self, surface): pass def removeTarget(self, surface): pass def __init__(self): super().__init__() self._parameters: Dict[str, Any] = { CaptureRequest.CONTROL_AE_MODE: CameraMetadata.CONTROL_AE_MODE_ON, CaptureRequest.CONTROL_AF_MODE: CameraMetadata.CONTROL_AF_MODE_AUTO, CaptureRequest.CONTROL_AWB_MODE: CameraMetadata.CONTROL_AWB_MODE_AUTO, CaptureRequest.CONTROL_MODE: CameraMetadata.CONTROL_MODE_AUTO, CaptureRequest.FLASH_MODE: CameraMetadata.FLASH_MODE_OFF, CaptureRequest.JPEG_QUALITY: 95, CaptureRequest.JPEG_ORIENTATION: 0, } self._tag = None self._targets: List[Any] = [] def get(self, key: str) -> Any: return self._parameters.get(key) def keys(self) -> Set[str]: return set(self._parameters.keys()) def getTag(self) -> Any: return self._tag # ═══════════════════════════════════════════════════════════════ # CaptureResult # ═══════════════════════════════════════════════════════════════ class CaptureResult(CameraMetadata): """CaptureResult — 捕获结果""" # Same keys as CaptureRequest CONTROL_AE_MODE = CaptureRequest.CONTROL_AE_MODE CONTROL_AF_MODE = CaptureRequest.CONTROL_AF_MODE CONTROL_AWB_MODE = CaptureRequest.CONTROL_AWB_MODE CONTROL_MODE = CaptureRequest.CONTROL_MODE FLASH_MODE = CaptureRequest.FLASH_MODE SENSOR_EXPOSURE_TIME = CaptureRequest.SENSOR_EXPOSURE_TIME SENSOR_SENSITIVITY = CaptureRequest.SENSOR_SENSITIVITY LENS_FOCUS_DISTANCE = CaptureRequest.LENS_FOCUS_DISTANCE STATISTICS_FACE_DETECT_MODE = CaptureRequest.STATISTICS_FACE_DETECT_MODE JPEG_QUALITY = CaptureRequest.JPEG_QUALITY JPEG_ORIENTATION = CaptureRequest.JPEG_ORIENTATION JPEG_THUMBNAIL_QUALITY = CaptureRequest.JPEG_THUMBNAIL_QUALITY JPEG_THUMBNAIL_SIZE = CaptureRequest.JPEG_THUMBNAIL_SIZE SCALER_CROP_REGION = CaptureRequest.SCALER_CROP_REGION EDGE_MODE = CaptureRequest.EDGE_MODE NOISE_REDUCTION_MODE = CaptureRequest.NOISE_REDUCTION_MODE TONEMAP_MODE = CaptureRequest.TONEMAP_MODE BLACK_LEVEL_LOCK = CaptureRequest.BLACK_LEVEL_LOCK CONTROL_AE_TARGET_FPS_RANGE = CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE CONTROL_AE_EXPOSURE_COMPENSATION = CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION CONTROL_AE_LOCK = CaptureRequest.CONTROL_AE_LOCK CONTROL_AE_PRECAPTURE_TRIGGER = CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER CONTROL_AWB_LOCK = CaptureRequest.CONTROL_AWB_LOCK CONTROL_EFFECT_MODE = CaptureRequest.CONTROL_EFFECT_MODE CONTROL_SCENE_MODE = CaptureRequest.CONTROL_SCENE_MODE CONTROL_VIDEO_STABILIZATION_MODE = CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE COLOR_CORRECTION_MODE = CaptureRequest.COLOR_CORRECTION_MODE COLOR_CORRECTION_GAINS = CaptureRequest.COLOR_CORRECTION_GAINS COLOR_CORRECTION_TRANSFORM = CaptureRequest.COLOR_CORRECTION_TRANSFORM COLOR_CORRECTION_ABERRATION_MODE = CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE CONTROL_POST_RAW_SENSITIVITY_BOOST = CaptureRequest.CONTROL_POST_RAW_SENSITIVITY_BOOST DISTORTION_CORRECTION_MODE = CaptureRequest.DISTORTION_CORRECTION_MODE HOT_PIXEL_MODE = CaptureRequest.HOT_PIXEL_MODE LENS_OPTICAL_STABILIZATION_MODE = CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE REQUEST_PIPELINE_MAX_DEPTH = CaptureRequest.REQUEST_PIPELINE_MAX_DEPTH SENSOR_TIMESTAMP = CaptureRequest.SENSOR_TIMESTAMP STATISTICS_LENS_SHADING_MAP_MODE = CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE STATISTICS_OIS_DATA_MODE = CaptureRequest.STATISTICS_OIS_DATA_MODE STATISTICS_SECTION = CaptureRequest.STATISTICS_SECTION TONEMAP_CURVE = CaptureRequest.TONEMAP_CURVE TONEMAP_GAMMA = CaptureRequest.TONEMAP_GAMMA def __init__(self, request: CaptureRequest = None): super().__init__() self._results: Dict[str, Any] = { CaptureResult.CONTROL_AE_MODE: CameraMetadata.CONTROL_AE_MODE_ON, CaptureResult.CONTROL_AF_MODE: CameraMetadata.CONTROL_AF_MODE_AUTO, CaptureResult.CONTROL_AWB_MODE: CameraMetadata.CONTROL_AWB_MODE_AUTO, CaptureResult.CONTROL_MODE: CameraMetadata.CONTROL_MODE_AUTO, CaptureResult.FLASH_MODE: CameraMetadata.FLASH_MODE_OFF, CaptureResult.SENSOR_EXPOSURE_TIME: 33333333, CaptureResult.SENSOR_SENSITIVITY: 100, CaptureResult.SENSOR_TIMESTAMP: int(time.time() * 1e9), } self._request = request self._sequence_id = -1 self._frame_number = -1 def get(self, key: str) -> Any: return self._results.get(key) def keys(self) -> Set[str]: return set(self._results.keys()) def getRequest(self) -> Optional[CaptureRequest]: return self._request def getSequenceId(self) -> int: return self._sequence_id def getFrameNumber(self) -> int: return self._frame_number # ═══════════════════════════════════════════════════════════════ # TotalCaptureResult # ═══════════════════════════════════════════════════════════════ class TotalCaptureResult(CaptureResult): """TotalCaptureResult — 完整捕获结果""" def __init__(self, request: CaptureRequest = None, partial_results: List[CaptureResult] = None): super().__init__(request) self._partial_results = partial_results or [] def getPartialResults(self) -> List[CaptureResult]: return list(self._partial_results) # ═══════════════════════════════════════════════════════════════ # CameraCaptureSession # ═══════════════════════════════════════════════════════════════ class CameraCaptureSession(Stub): """CameraCaptureSession — 捕获会话""" class StateCallback(Stub): """CameraCaptureSession.StateCallback — 会话状态回调""" def onConfigured(self, session: "CameraCaptureSession"): pass def onConfigureFailed(self, session: "CameraCaptureSession"): pass def onReady(self, session: "CameraCaptureSession"): pass def onActive(self, session: "CameraCaptureSession"): pass def onClosed(self, session: "CameraCaptureSession"): pass def onSurfacePrepared(self, session: "CameraCaptureSession", surface): pass class CaptureCallback(Stub): """CameraCaptureSession.CaptureCallback — 捕获回调""" def onCaptureStarted(self, session: "CameraCaptureSession", request: CaptureRequest, timestamp: int, frameNumber: int): pass def onCaptureCompleted(self, session: "CameraCaptureSession", request: CaptureRequest, result: TotalCaptureResult): pass def onCaptureFailed(self, session: "CameraCaptureSession", request: CaptureRequest, failure): pass def onCaptureProgressed(self, session: "CameraCaptureSession", request: CaptureRequest, result: CaptureResult): pass def onCaptureSequenceCompleted(self, session: "CameraCaptureSession", sequenceId: int, frameNumber: int): pass def onCaptureSequenceAborted(self, session: "CameraCaptureSession", sequenceId: int): pass def onCaptureBufferLost(self, session: "CameraCaptureSession", request: CaptureRequest, target, frameNumber: int): pass def __init__(self, device: "CameraDevice"): super().__init__() self._device = device self._closed = False self._repeating_request = None self._state_callback = None self._session_id = int(time.time() * 1000) def capture(self, request: CaptureRequest, callback: CaptureCallback = None, handler=None) -> int: seq_id = int(time.time() * 1000) result = TotalCaptureResult(request) if callback: callback.onCaptureStarted(self, request, int(time.time() * 1e9), 0) callback.onCaptureCompleted(self, request, result) callback.onCaptureSequenceCompleted(self, seq_id, 0) return seq_id def setRepeatingRequest(self, request: CaptureRequest, callback: CaptureCallback = None, handler=None) -> int: self._repeating_request = request seq_id = int(time.time() * 1000) result = TotalCaptureResult(request) if callback: callback.onCaptureStarted(self, request, int(time.time() * 1e9), 0) callback.onCaptureCompleted(self, request, result) return seq_id def stopRepeatingRequest(self) -> None: self._repeating_request = None def abortCaptures(self) -> None: pass def close(self): self._closed = True def getDevice(self) -> "CameraDevice": return self._device def isClosed(self) -> bool: return self._closed # ═══════════════════════════════════════════════════════════════ # CameraDevice # ═══════════════════════════════════════════════════════════════ class CameraDevice(Stub): """CameraDevice — 相机设备""" STATE_OPENED = 0 STATE_CLOSED = 3 STATE_DISCONNECTED = 1 STATE_ERROR = 2 class StateCallback(Stub): """CameraDevice.StateCallback — 设备状态回调""" def onOpened(self, device: "CameraDevice"): pass def onClosed(self, device: "CameraDevice"): pass def onDisconnected(self, device: "CameraDevice"): pass def onError(self, device: "CameraDevice", error: int): pass def __init__(self, camera_id: str = "0"): super().__init__() self._id = camera_id self._state = CameraDevice.STATE_OPENED self._state_callback = None self._sessions: List[CameraCaptureSession] = [] def getId(self) -> str: return self._id def createCaptureRequest(self, templateType: int) -> CaptureRequest.Builder: return CaptureRequest.Builder(self) def createCaptureSession(self, outputs: List[Any], callback: CameraCaptureSession.StateCallback, handler=None): session = CameraCaptureSession(self) session._state_callback = callback self._sessions.append(session) if callback: callback.onConfigured(session) return session def close(self): self._state = CameraDevice.STATE_CLOSED for session in self._sessions: session.close() def getState(self) -> int: return self._state def toString(self) -> str: return f"CameraDevice@{self._id}" # ═══════════════════════════════════════════════════════════════ # CameraManager # ═══════════════════════════════════════════════════════════════ class CameraManager(Stub): """CameraManager — 相机管理器""" def __init__(self): super().__init__() self._cameras: Dict[str, CameraCharacteristics] = { "0": CameraCharacteristics("0"), } self._open_devices: Dict[str, CameraDevice] = {} self._availability_callbacks: List[Any] = [] self._torch_callbacks: List[Any] = [] def getCameraIdList(self) -> List[str]: return list(self._cameras.keys()) def getCameraCharacteristics(self, cameraId: str) -> CameraCharacteristics: if cameraId not in self._cameras: raise AndroidOnlyError(f"Camera {cameraId} not available") return self._cameras[cameraId] def openCamera(self, cameraId: str, callback: CameraDevice.StateCallback, handler=None): if cameraId not in self._cameras: if callback: callback.onError(None, CameraDevice.STATE_ERROR) return device = CameraDevice(cameraId) self._open_devices[cameraId] = device if callback: callback.onOpened(device) def registerAvailabilityCallback(self, callback): self._availability_callbacks.append(callback) def unregisterAvailabilityCallback(self, callback): if callback in self._availability_callbacks: self._availability_callbacks.remove(callback) def registerTorchCallback(self, callback, handler=None): self._torch_callbacks.append(callback) def unregisterTorchCallback(self, callback): if callback in self._torch_callbacks: self._torch_callbacks.remove(callback) def setTorchMode(self, cameraId: str, enabled: bool): pass # ═══════════════════════════════════════════════════════════════ # CameraOfflineSession # ═══════════════════════════════════════════════════════════════ class CameraOfflineSession(CameraCaptureSession): """CameraOfflineSession — 离线会话 (API 30+)""" def __init__(self, device: CameraDevice): super().__init__(device) def switchToOffline(self): pass # ═══════════════════════════════════════════════════════════════ # CameraExtensionSession # ═══════════════════════════════════════════════════════════════ class CameraExtensionSession(Stub): """CameraExtensionSession — 扩展会话 (API 31+)""" class StateCallback(Stub): def onConfigured(self, session: "CameraExtensionSession"): pass def onConfigureFailed(self, session: "CameraExtensionSession"): pass def onClosed(self, session: "CameraExtensionSession"): pass class ExtensionCaptureCallback(Stub): def onCaptureStarted(self, session: "CameraExtensionSession", request: CaptureRequest, timestamp: int): pass def onCaptureProcessStarted(self, session: "CameraExtensionSession", request: CaptureRequest): pass def onCaptureFailed(self, session: "CameraExtensionSession", request: CaptureRequest): pass def onCaptureResultAvailable(self, session: "CameraExtensionSession", request: CaptureRequest, result: TotalCaptureResult): pass def __init__(self): super().__init__() self._closed = False def close(self): self._closed = True # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "CameraManager", "CameraDevice", "CameraCaptureSession", "CaptureRequest", "CaptureResult", "CameraCharacteristics", "CameraMetadata", "CameraId", "CameraCharacteristicsKey", "TotalCaptureResult", "CameraOfflineSession", "CameraExtensionSession", ]