""" Android media.capture 组件 — CaptureSession, CaptureRequest, CaptureResult 等 方法签名完全对齐 Android SDK """ from __future__ import annotations import os import math import time import threading from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException # ═══════════════════════════════════════════════════════════════ # 捕获请求/结果常量 # ═══════════════════════════════════════════════════════════════ REQUEST_ID = "request-id" REQUEST_TYPE = "request-type" RESULT_STATUS = "result-status" RESULT_TIMESTAMP = "result-timestamp" RESULT_FRAME_NUMBER = "result-frame-number" ERROR_CAMERA_DEVICE = 1 ERROR_CAMERA_DISABLED = 2 ERROR_CAMERA_IN_USE = 3 ERROR_CAMERA_SERVICE = 4 ERROR_MAX_CAMERAS_IN_USE = 5 ERROR_CAMERA_UNAVAILABLE = 1001 ERROR_CAMERA_ACCESS_DENIED = 1002 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_ON_EXTERNAL_FLASH = 5 CONTROL_AE_LOCK_OFF = 0 CONTROL_AE_LOCK_ON = 1 CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0 CONTROL_AE_PRECAPTURE_TRIGGER_START = 1 CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2 CONTROL_AE_STATE_INACTIVE = 0 CONTROL_AE_STATE_SEARCHING = 1 CONTROL_AE_STATE_CONVERGED = 2 CONTROL_AE_STATE_LOCKED = 3 CONTROL_AE_STATE_FLASH_REQUIRED = 4 CONTROL_AE_STATE_PRECAPTURE = 5 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_AF_TRIGGER_IDLE = 0 CONTROL_AF_TRIGGER_START = 1 CONTROL_AF_TRIGGER_CANCEL = 2 CONTROL_AF_STATE_INACTIVE = 0 CONTROL_AF_STATE_PASSIVE_SCAN = 1 CONTROL_AF_STATE_PASSIVE_FOCUSED = 2 CONTROL_AF_STATE_ACTIVE_SCAN = 3 CONTROL_AF_STATE_FOCUSED_LOCKED = 4 CONTROL_AF_STATE_NOT_FOCUSED_LOCKED = 5 CONTROL_AF_STATE_PASSIVE_UNFOCUSED = 6 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_AWB_LOCK_OFF = 0 CONTROL_AWB_LOCK_ON = 1 CONTROL_AWB_STATE_INACTIVE = 0 CONTROL_AWB_STATE_SEARCHING = 1 CONTROL_AWB_STATE_CONVERGED = 2 CONTROL_AWB_STATE_LOCKED = 3 CONTROL_CAPTURE_INTENT_PREVIEW = 1 CONTROL_CAPTURE_INTENT_STILL_CAPTURE = 2 CONTROL_CAPTURE_INTENT_VIDEO_RECORD = 3 CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT = 4 CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG = 5 CONTROL_CAPTURE_INTENT_MANUAL = 6 CONTROL_CAPTURE_INTENT_MOTION_TRACKING = 7 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_MODE_AUTO = 1 CONTROL_MODE_OFF = 0 CONTROL_MODE_USE_SCENE_MODE = 2 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_MODE_OFF = 0 CONTROL_VIDEO_STABILIZATION_MODE_ON = 1 CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW = 2 STATISTICS_FACE_DETECT_MODE_OFF = 0 STATISTICS_FACE_DETECT_MODE_SIMPLE = 1 STATISTICS_FACE_DETECT_MODE_FULL = 2 STATISTICS_HOT_PIXEL_MAP_MODE_OFF = 0 STATISTICS_HOT_PIXEL_MAP_MODE_ON = 1 STATISTICS_LENS_SHADING_MAP_MODE_OFF = 0 STATISTICS_LENS_SHADING_MAP_MODE_ON = 1 STATISTICS_OIS_DATA_MODE_OFF = 0 STATISTICS_OIS_DATA_MODE_ON = 1 STATISTICS_SCENE_FLICKER_NONE = 0 STATISTICS_SCENE_FLICKER_50HZ = 1 STATISTICS_SCENE_FLICKER_60HZ = 2 FLASH_MODE_OFF = 0 FLASH_MODE_SINGLE = 1 FLASH_MODE_TORCH = 2 LENS_FACING_FRONT = 0 LENS_FACING_BACK = 1 LENS_FACING_EXTERNAL = 2 SENSOR_SENSITIVITY = "sensor-sensitivity" SENSOR_EXPOSURE_TIME = "sensor-exposure-time" SENSOR_FRAME_DURATION = "sensor-frame-duration" SENSOR_TIMESTAMP = "sensor-timestamp" JPEG_QUALITY = "jpeg-quality" JPEG_ORIENTATION = "jpeg-orientation" JPEG_GPS_LOCATION = "jpeg-gps-location" JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality" JPEG_THUMBNAIL_SIZE = "jpeg-thumbnail-size" 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 EDGE_MODE_OFF = 0 EDGE_MODE_FAST = 1 EDGE_MODE_HIGH_QUALITY = 2 EDGE_MODE_ZERO_SHUTTER_LAG = 3 TONEMAP_MODE_CONTRAST_CURVE = 0 TONEMAP_MODE_FAST = 1 TONEMAP_MODE_HIGH_QUALITY = 2 TONEMAP_MODE_GAMMA_VALUE = 3 TONEMAP_MODE_PRESET_CURVE = 4 TONEMAP_PRESET_CURVE_SRGB = 0 TONEMAP_PRESET_CURVE_REC709 = 1 REQUEST_AVAILABLE_CAPABILITIES = "request-available-capabilities" REQUEST_AVAILABLE_CHARACTERISTICS_KEYS = "request-available-characteristics-keys" REQUEST_AVAILABLE_RESULT_KEYS = "request-available-result-keys" REQUEST_AVAILABLE_SESSION_KEYS = "request-available-session-keys" REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES = "request-available-dynamic-range-profiles" REQUEST_AVAILABLE_RAW_MIN_DENOISE = "request-available-raw-min-denoise" REQUEST_AVAILABLE_TEST_PATTERN_MODES = "request-available-test-pattern-modes" REQUEST_PARTIAL_RESULT_COUNT = "request-partial-result-count" REQUEST_PIPELINE_MAX_DEPTH = "request-pipeline-max-depth" # ═══════════════════════════════════════════════════════════════ # CaptureRequest # ═══════════════════════════════════════════════════════════════ class CaptureRequest(Stub): """CaptureRequest — 捕获请求""" class Builder(Stub): """CaptureRequest.Builder — 捕获请求构建器""" def __init__(self): super().__init__() self._parameters: Dict[str, Any] = {} self._tags: Dict[str, Any] = {} self._surfaces: List[Any] = [] self._repeating = False def set(self, key: str, value: Any) -> "CaptureRequest.Builder": self._parameters[key] = value return self def get(self, key: str) -> Optional[Any]: return self._parameters.get(key) def setTag(self, key: str, value: Any) -> "CaptureRequest.Builder": self._tags[key] = value return self def getTag(self, key: str) -> Optional[Any]: return self._tags.get(key) def addTarget(self, surface: Any) -> "CaptureRequest.Builder": if surface not in self._surfaces: self._surfaces.append(surface) return self def removeTarget(self, surface: Any) -> "CaptureRequest.Builder": if surface in self._surfaces: self._surfaces.remove(surface) return self def getTargets(self) -> List[Any]: return list(self._surfaces) def isEmpty(self) -> bool: return len(self._parameters) == 0 def build(self) -> "CaptureRequest": req = CaptureRequest() req._parameters = dict(self._parameters) req._tags = dict(self._tags) req._surfaces = list(self._surfaces) req._repeating = self._repeating return req def toString(self) -> str: return (f"CaptureRequest.Builder(params={len(self._parameters)}, " f"targets={len(self._surfaces)})") def __init__(self): super().__init__() self._parameters: Dict[str, Any] = {} self._tags: Dict[str, Any] = {} self._surfaces: List[Any] = [] self._repeating = False self._frame_number: int = 0 self._request_id: int = 0 def get(self, key: str) -> Optional[Any]: return self._parameters.get(key) def set(self, key: str, value: Any) -> None: self._parameters[key] = value def getParameters(self) -> Dict[str, Any]: return dict(self._parameters) def getTags(self) -> Dict[str, Any]: return dict(self._tags) def getTargets(self) -> List[Any]: return list(self._surfaces) def isRepeating(self) -> bool: return self._repeating def setRepeating(self, repeating: bool) -> None: self._repeating = repeating def getFrameNumber(self) -> int: return self._frame_number def setFrameNumber(self, frame: int) -> None: self._frame_number = frame def getRequestId(self) -> int: return self._request_id def setRequestId(self, req_id: int) -> None: self._request_id = req_id def toString(self) -> str: return (f"CaptureRequest(id={self._request_id}, " f"frame={self._frame_number}, " f"params={len(self._parameters)})") # ═══════════════════════════════════════════════════════════════ # CaptureResult # ═══════════════════════════════════════════════════════════════ class CaptureResult(Stub): """CaptureResult — 捕获结果""" def __init__(self): super().__init__() self._results: Dict[str, Any] = {} self._request: Optional[CaptureRequest] = None self._sequence_id: int = 0 self._frame_number: int = 0 self._timestamp: int = 0 self._partial_count: int = 0 self._metadata: Dict[str, Any] = {} def get(self, key: str) -> Optional[Any]: return self._results.get(key) def put(self, key: str, value: Any) -> None: self._results[key] = value def getAll(self) -> Dict[str, Any]: return dict(self._results) def getRequest(self) -> Optional[CaptureRequest]: return self._request def setRequest(self, request: CaptureRequest) -> None: self._request = request def getSequenceId(self) -> int: return self._sequence_id def setSequenceId(self, seq_id: int) -> None: self._sequence_id = seq_id def getFrameNumber(self) -> int: return self._frame_number def setFrameNumber(self, frame: int) -> None: self._frame_number = frame def getTimestamp(self) -> int: return self._timestamp def setTimestamp(self, ts: int) -> None: self._timestamp = ts def getMetadata(self, key: str) -> Any: return self._metadata.get(key) def setMetadata(self, key: str, value: Any) -> None: self._metadata[key] = value def getPartialCount(self) -> int: return self._partial_count def setPartialCount(self, count: int) -> None: self._partial_count = count def toString(self) -> str: return (f"CaptureResult(frame={self._frame_number}, " f"seq={self._sequence_id}, " f"results={len(self._results)})") # ═══════════════════════════════════════════════════════════════ # TotalCaptureResult # ═══════════════════════════════════════════════════════════════ class TotalCaptureResult(CaptureResult): """TotalCaptureResult — 完整捕获结果(包含所有部分结果)""" def __init__(self): super().__init__() self._partial_results: List[CaptureResult] = [] self._sensor_timestamp: int = 0 self._physical_camera_results: Dict[str, CaptureResult] = {} def getPartialResults(self) -> List[CaptureResult]: return list(self._partial_results) def addPartialResult(self, result: CaptureResult) -> None: self._partial_results.append(result) def getPhysicalCameraResults(self) -> Dict[str, CaptureResult]: return dict(self._physical_camera_results) def setPhysicalCameraResult(self, camera_id: str, result: CaptureResult) -> None: self._physical_camera_results[camera_id] = result def toString(self) -> str: return (f"TotalCaptureResult(frame={self.getFrameNumber()}, " f"partials={len(self._partial_results)}, " f"physical={len(self._physical_camera_results)})") # ═══════════════════════════════════════════════════════════════ # CaptureFailure # ═══════════════════════════════════════════════════════════════ class CaptureFailure(Stub): """CaptureFailure — 捕获失败信息""" REASON_ERROR = 0 REASON_FLUSHED = 1 REASON_DROPPED = 2 def __init__(self, request: Optional[CaptureRequest] = None, reason: int = REASON_ERROR, frame_number: int = 0, sequence_id: int = 0, is_image_capture: bool = False): super().__init__() self._request = request self._reason = reason self._frame_number = frame_number self._sequence_id = sequence_id self._is_image_capture = is_image_capture self._physical_camera_id: Optional[str] = None def getRequest(self) -> Optional[CaptureRequest]: return self._request def getReason(self) -> int: return self._reason def getFrameNumber(self) -> int: return self._frame_number def getSequenceId(self) -> int: return self._sequence_id def isImageCapture(self) -> bool: return self._is_image_capture def getPhysicalCameraId(self) -> Optional[str]: return self._physical_camera_id def setPhysicalCameraId(self, camera_id: str) -> None: self._physical_camera_id = camera_id def toString(self) -> str: reasons = {0: "ERROR", 1: "FLUSHED", 2: "DROPPED"} return (f"CaptureFailure(reason={reasons.get(self._reason, 'UNKNOWN')}, " f"frame={self._frame_number})") # ═══════════════════════════════════════════════════════════════ # CaptureExtension # ═══════════════════════════════════════════════════════════════ class CaptureExtension(Stub): """CaptureExtension — 捕获扩展""" EXTENSION_NONE = 0 EXTENSION_AUTO = 1 EXTENSION_BEAUTY = 2 EXTENSION_BOKEH = 3 EXTENSION_HDR = 4 EXTENSION_NIGHT = 5 def __init__(self, extension_type: int = EXTENSION_NONE): super().__init__() self._extension_type = extension_type self._parameters: Dict[str, Any] = {} self._enabled = False def getExtensionType(self) -> int: return self._extension_type def setExtensionType(self, ext_type: int) -> None: self._extension_type = ext_type def isEnabled(self) -> bool: return self._enabled def setEnabled(self, enabled: bool) -> None: self._enabled = enabled def setParameter(self, key: str, value: Any) -> None: self._parameters[key] = value def getParameter(self, key: str) -> Optional[Any]: return self._parameters.get(key) def toString(self) -> str: types = {0: "NONE", 1: "AUTO", 2: "BEAUTY", 3: "BOKEH", 4: "HDR", 5: "NIGHT"} return f"CaptureExtension(type={types.get(self._extension_type, 'UNKNOWN')})" # ═══════════════════════════════════════════════════════════════ # CaptureSession # ═══════════════════════════════════════════════════════════════ class CaptureSession(Stub): """CaptureSession — 捕获会话""" SESSION_ID = "session-id" SESSION_CONFIGURATION = "session-configuration" SESSION_STATE = "session-state" SESSION_STATE_OPEN = 0 SESSION_STATE_READY = 1 SESSION_STATE_ACTIVE = 2 SESSION_STATE_CLOSED = 3 CAPTURE = "capture" CAPTURE_BURST = "capture-burst" SET_REPEATING_REQUEST = "set-repeating-request" SET_REPEATING_BURST = "set-repeating-burst" STOP_REPEATING = "stop-repeating" ABORT_CAPTURES = "abort-captures" # 回调接口 class CaptureCallback(Stub): """CaptureSession.CaptureCallback — 捕获回调""" def onCaptureStarted(self, session: "CaptureSession", request: CaptureRequest, timestamp: int, frame_number: int) -> None: pass def onCaptureProgressed(self, session: "CaptureSession", request: CaptureRequest, partial_result: CaptureResult) -> None: pass def onCaptureCompleted(self, session: "CaptureSession", request: CaptureRequest, result: TotalCaptureResult) -> None: pass def onCaptureFailed(self, session: "CaptureSession", request: CaptureRequest, failure: CaptureFailure) -> None: pass def onCaptureSequenceCompleted(self, session: "CaptureSession", sequence_id: int, frame_number: int) -> None: pass def onCaptureSequenceAborted(self, session: "CaptureSession", sequence_id: int) -> None: pass def onCaptureBufferLost(self, session: "CaptureSession", request: CaptureRequest, target: Any, frame_number: int) -> None: pass class StateCallback(Stub): """CaptureSession.StateCallback — 会话状态回调""" def onConfigured(self, session: "CaptureSession") -> None: pass def onConfigureFailed(self, session: "CaptureSession") -> None: pass def onReady(self, session: "CaptureSession") -> None: pass def onActive(self, session: "CaptureSession") -> None: pass def onClosed(self, session: "CaptureSession") -> None: pass def __init__(self): super().__init__() self._state = self.SESSION_STATE_CLOSED self._state_callback: Optional[CaptureSession.StateCallback] = None self._capture_callback: Optional[CaptureSession.CaptureCallback] = None self._repeating_request: Optional[CaptureRequest] = None self._output_config: Optional[Any] = None self._input_config: Optional[Any] = None self._session_id: int = 0 self._next_sequence_id: int = 1 self._lock = threading.Lock() def open(self, callback: StateCallback, handler: Any = None) -> None: self._state_callback = callback self._state = self.SESSION_STATE_OPEN if callback: callback.onConfigured(self) def capture(self, request: CaptureRequest, callback: Optional[CaptureCallback] = None, handler: Any = None) -> int: with self._lock: seq_id = self._next_sequence_id self._next_sequence_id += 1 if callback: callback.onCaptureStarted(self, request, int(time.time() * 1e9), 0) result = TotalCaptureResult() result.setRequest(request) result.setSequenceId(seq_id) callback.onCaptureCompleted(self, request, result) return seq_id def captureBurst(self, requests: List[CaptureRequest], callback: Optional[CaptureCallback] = None, handler: Any = None) -> int: with self._lock: seq_id = self._next_sequence_id self._next_sequence_id += 1 if callback: for req in requests: callback.onCaptureStarted(self, req, int(time.time() * 1e9), 0) result = TotalCaptureResult() result.setRequest(req) result.setSequenceId(seq_id) callback.onCaptureCompleted(self, req, result) return seq_id def setRepeatingRequest(self, request: CaptureRequest, callback: Optional[CaptureCallback] = None, handler: Any = None) -> int: with self._lock: self._repeating_request = request seq_id = self._next_sequence_id self._next_sequence_id += 1 return seq_id def setRepeatingBurst(self, requests: List[CaptureRequest], callback: Optional[CaptureCallback] = None, handler: Any = None) -> int: with self._lock: seq_id = self._next_sequence_id self._next_sequence_id += 1 return seq_id def stopRepeating(self) -> None: with self._lock: self._repeating_request = None def abortCaptures(self) -> None: with self._lock: self._repeating_request = None def close(self) -> None: with self._lock: self._state = self.SESSION_STATE_CLOSED if self._state_callback: self._state_callback.onClosed(self) def getState(self) -> int: return self._state def isClosed(self) -> bool: return self._state == self.SESSION_STATE_CLOSED def getSessionId(self) -> int: return self._session_id def toString(self) -> str: states = {0: "OPEN", 1: "READY", 2: "ACTIVE", 3: "CLOSED"} return f"CaptureSession(state={states.get(self._state, 'UNKNOWN')})" CaptureSession.CaptureCallback = CaptureSession.CaptureCallback CaptureSession.StateCallback = CaptureSession.StateCallback class CaptureSessionConfig(Stub): """CaptureSessionConfig — 捕获会话配置""" def __init__(self): super().__init__() self._output_surfaces: List[Any] = [] self._input_surface: Optional[Any] = None self._session_params: Dict[str, Any] = {} self._session_type: int = 0 def addOutputSurface(self, surface: Any) -> None: if surface not in self._output_surfaces: self._output_surfaces.append(surface) def removeOutputSurface(self, surface: Any) -> None: if surface in self._output_surfaces: self._output_surfaces.remove(surface) def getOutputSurfaces(self) -> List[Any]: return list(self._output_surfaces) def setInputSurface(self, surface: Any) -> None: self._input_surface = surface def getInputSurface(self) -> Optional[Any]: return self._input_surface def setSessionParameter(self, key: str, value: Any) -> None: self._session_params[key] = value def getSessionParameter(self, key: str) -> Optional[Any]: return self._session_params.get(key) def toString(self) -> str: return (f"CaptureSessionConfig(outputs={len(self._output_surfaces)}, " f"input={'yes' if self._input_surface else 'no'})") class CaptureSessionOutput(Stub): """CaptureSessionOutput — 会话输出配置""" def __init__(self, surface: Any): super().__init__() self._surface = surface self._physical_camera_id: Optional[str] = None def getSurface(self) -> Any: return self._surface def setPhysicalCameraId(self, camera_id: str) -> None: self._physical_camera_id = camera_id def getPhysicalCameraId(self) -> Optional[str]: return self._physical_camera_id def toString(self) -> str: return (f"CaptureSessionOutput(surface={self._surface}, " f"physicalId={self._physical_camera_id})") class CaptureSessionInput(Stub): """CaptureSessionInput — 会话输入配置""" def __init__(self, surface: Any): super().__init__() self._surface = surface def getSurface(self) -> Any: return self._surface def toString(self) -> str: return f"CaptureSessionInput(surface={self._surface})" class CaptureSessionParams(Stub): """CaptureSessionParams — 会话参数配置""" def __init__(self): super().__init__() self._params: Dict[str, Any] = {} def set(self, key: str, value: Any) -> None: self._params[key] = value def get(self, key: str) -> Optional[Any]: return self._params.get(key) def getAll(self) -> Dict[str, Any]: return dict(self._params) def toString(self) -> str: return f"CaptureSessionParams(params={len(self._params)})"