#ifndef VMF_VIDEO_SOURCE_H #define VMF_VIDEO_SOURCE_H #include typedef struct VMF_VSRC_HANDLE_S VMF_VSRC_HANDLE_T; typedef void (*VMF_VSRC_CALLBACK_T)(void *arg, void *buf_info); /* Gyro daemon config — matches real SDK gyro_daemon.h (VMF_VSRC_GYRO_CONFIG_T) */ typedef struct { unsigned long ulDeviceNum; /* device number (default: 1) */ unsigned int dwSpeed; /* polling speed in fps (default: 30) */ unsigned int dwFrequency; /* iio sample frequency (default: 200) */ int sdwGyroFsr; /* gyro full-scale range; -1 = unchanged */ int sdwAccelFsr; /* accel full-scale range; -1 = unchanged */ unsigned int dwSampleCount; /* gyro buffer depth (default: 200) */ char *pszPinName; /* SCM output pin name */ } VMF_VSRC_GYRO_CONFIG_T; /* EIS init config — all fields accessed by set_eis() in kdp2_host_stream.c */ typedef struct { char *pszLensCurveNodesPath; char *pszLogPath; float fGyroDataGain; uint32_t dwGridSection; uint32_t dwMaxGridSection; float fCropRatio; uint32_t dwImageType; uint32_t dwProcessMode; uint32_t dwCoordinateTransform[3]; int64_t sqwTimeOffset; uint32_t bImageRotate180; int32_t sdwReadoutTimeOffset; float fReadoutTimeRatio; uint32_t bForceOriRs; VMF_VSRC_GYRO_CONFIG_T tGyroConfig; uint32_t _pad[8]; } VMF_EIS_INIT_T; /* FEC init config — the REAL VMF_VSRC_FEC_INIT_CONFIG_T layout, deduced from fec_api.c * field access patterns. VMF_VSRC_Init reads up to afLensCurveNodeY[63], so the * struct must cover at least 536 bytes to prevent stack overread → SIGSEGV. * * Confirmed field order from loadCalibrateConfig / loadFECConfig in fec_api.c: * offset 0: eFecMethod (uint32_t) — VMF_FEC_METHOD * offset 4: ptEisInit (ptr) — EIS init (NULL if EIS disabled) * offset 8: iFecCenterOffsetX (int32_t) * offset 12: iFecCenterOffsetY (int32_t) * offset 16: iFecRadiusOffset (int32_t) * offset 20: dwLensCurveNodeNum (uint32_t) — 0 = no lens correction * offset 24: afLensCurveNodeX[64] (float[64], 256 bytes) * offset 280: afLensCurveNodeY[64] (float[64], 256 bytes) * offset 536: _pad[64] extra safety */ typedef struct { uint32_t eFecMethod; /* offset 0 */ VMF_EIS_INIT_T *ptEisInit; /* offset 4 */ int32_t iFecCenterOffsetX; /* offset 8 */ int32_t iFecCenterOffsetY; /* offset 12 */ int32_t iFecRadiusOffset; /* offset 16 */ uint32_t dwLensCurveNodeNum; /* offset 20 — 0 = no correction */ float afLensCurveNodeX[64]; /* offset 24 (256 bytes) */ float afLensCurveNodeY[64]; /* offset 280 (256 bytes) */ uint32_t _pad[64]; /* offset 536 (256 bytes extra safety) */ } VMF_FEC_INIT_CONFIG_T; /* total: 792 bytes */ /* Alias used by the real fec_api.c */ typedef VMF_FEC_INIT_CONFIG_T VMF_VSRC_FEC_INIT_CONFIG_T; /* Frontend config — confirmed real layout from VSRC_Front_Init_Normal disasm (0x3ec08): * r8 = initopt[8] = ptFrontConfig * [r8, #0] = dwSensorConfigCount ← checked: if 0 → "sensor config should not be empty" * [r8, #4] = apszSensorConfig[0] ← loaded for sensor 0 * [r8, #8] = apszSensorConfig[1] ← loaded for sensor 1 (fusion) * [r8, #12] = apszSensorConfig[2] * [r8, #16] = apszSensorConfig[3] * [r8, #20] = tFecInitConfig (eFecMethod, ptEisInit, ...) */ typedef struct { uint32_t dwSensorConfigCount; /* offset 0 — MUST BE FIRST */ const char *apszSensorConfig[4]; /* offset 4 (16 bytes) */ VMF_FEC_INIT_CONFIG_T tFecInitConfig; /* offset 20 (792 bytes) */ uint32_t _pad[8]; /* offset 812, extra safety */ } VMF_VSRC_FRONTEND_CONFIG_T; /* * VMF_LAYOUT_T — layout descriptor used for FEC and video positioning. */ typedef struct { uint32_t dwCanvasWidth; uint32_t dwCanvasHeight; uint32_t dwVideoPosX; uint32_t dwVideoPosY; uint32_t dwVideoWidth; uint32_t dwVideoHeight; uint32_t _pad[58]; } VMF_LAYOUT_T; /* ISP option flag */ #define ISP_OPTION_PRIVACY_MASK_SETTINGS 1u typedef struct { uint32_t option_flag; uint32_t adwData[4]; uint32_t _pad[8]; } VMF_ISP_OPTION_T; typedef struct { uint32_t bEnable; uint8_t abyColorYUV[3]; uint8_t _reserved1; uint32_t dwMaskStride; uint32_t bMainMaskDisable; uint32_t bResizeMaskDisable; unsigned char *pMaskBuffer; uint32_t _pad[4]; } VMF_ISP_PM_CONFIG_T; /* ISP mode enum */ typedef enum { VMF_ISP_MODE_NORMAL = 0, VMF_ISP_MODE_FEC = 1, VMF_ISP_MODE_FEC_C = 2, VMF_ISP_MODE_EIS = 3, } VMF_ISP_MODE_E; /* Encoder spec bits (nested in VMF_VSRC_SPEC_CONFIG_T.tIspEncSpec) */ typedef struct { uint32_t bEncH265; uint32_t bEncH264; uint32_t bEncJPEG; uint32_t bOthers; } VMF_ISP_ENC_SPEC_T; /* Spec config — fields accessed by setup_spec() in kdp2_host_stream.c. * Real size = 24 bytes (no padding): bEnableSpec(4)+dwIspMode(4)+tIspEncSpec(16). * Confirmed: fp[36]=bEnableSpec→handle[992], fp[40-47]=vld1.32(dwIspMode+tIspEncSpec[0])→handle[1012]. */ typedef struct { uint32_t bEnableSpec; uint32_t dwIspMode; /* VMF_ISP_MODE_E */ VMF_ISP_ENC_SPEC_T tIspEncSpec; /* NO padding — struct is 24 bytes; placed at initopt[36] per disasm */ } VMF_VSRC_SPEC_CONFIG_T; /* App mode enum */ typedef enum { VMF_VSRC_APP_MODE_NORMAL = 0, VMF_VSRC_APP_MODE_FUSION = 1, } VMF_VSRC_APP_MODE_E; /* Init callback type */ typedef void (*VMF_VSRC_INIT_CALLBACK_T)(uint32_t width, uint32_t height); /* * VMF_VSRC_INITOPT_T — confirmed offsets from libvmf.so disassembly: * * [r4,#0] = eAppMode — jump table 0-8 in sub_30a80; NORMAL=0, FUSION=1 * [r4,#4] = dwFrontConfigCount — CHECKED: must be 1-2 (VMF_VSRC_Init@32080) * [r4,#8] = ptFrontConfig — CHECKED: must be non-NULL (VMF_VSRC_Init@3208c) * [r4,#12] = fnInitCallback — init-done callback (placed after ptFrontConfig) * [r4,#16] = _unk[5] — unknown fields (20 bytes) * [r4,#36] = tSpecConfig — bEnableSpec→handle[992], vld1.32[40-47]→handle[1012] * [r4,#60] = _unk2[5] — unknown (20 bytes, before pszAutoSceneConfig) * [r4,#80] = pszAutoSceneConfig — nullable string, conditional strdup→handle[204] * [r4,#84] = _unk3[11] — unknown (44 bytes) * [r4,#128] = bShared — CHECKED boolean→handle[212] (VMF_VSRC_Init sub_30a80@30ac4) * [r4,#132] = pszOutPinPrefix — CHECKED non-NULL; strncpy(9)→handle[188] (@30ae8) * [r4,#136] = _unk6 — unknown (4 bytes) * [r4,#140] = pszResourceDir — strdup→handle[200] (@30afc) * [r4,#144] = _unk7[10] — unknown tail fields */ typedef struct { VMF_VSRC_APP_MODE_E eAppMode; /* offset 0 */ uint32_t dwFrontConfigCount; /* offset 4 */ VMF_VSRC_FRONTEND_CONFIG_T *ptFrontConfig; /* offset 8 */ VMF_VSRC_INIT_CALLBACK_T fnInitCallback; /* offset 12 */ uint32_t _unk[5]; /* offset 16 (20 bytes) */ VMF_VSRC_SPEC_CONFIG_T tSpecConfig; /* offset 36 (24 bytes) */ uint32_t _unk2[5]; /* offset 60 (20 bytes) */ const char *pszAutoSceneConfig; /* offset 80 */ uint32_t _unk3[11]; /* offset 84 (44 bytes) */ uint32_t bShared; /* offset 128 */ const char *pszOutPinPrefix; /* offset 132 */ uint32_t _unk6; /* offset 136 */ const char *pszResourceDir; /* offset 140 */ uint32_t _unk7[10]; /* offset 144 (40 bytes) */ } VMF_VSRC_INITOPT_T; VMF_VSRC_HANDLE_T *VMF_VSRC_Init(VMF_VSRC_INITOPT_T *initopt); void VMF_VSRC_Release(VMF_VSRC_HANDLE_T *hVsrc); int VMF_VSRC_Open(VMF_VSRC_HANDLE_T **handle, const char *cfg_path); int VMF_VSRC_Close(VMF_VSRC_HANDLE_T *handle); int VMF_VSRC_Start(VMF_VSRC_HANDLE_T *handle, void *arg); int VMF_VSRC_Stop(VMF_VSRC_HANDLE_T *handle); int VMF_VSRC_Suspend(VMF_VSRC_HANDLE_T *handle); int VMF_VSRC_Resume(VMF_VSRC_HANDLE_T *handle); int VMF_VSRC_SetFrontendConfig(VMF_VSRC_HANDLE_T *handle, VMF_VSRC_FRONTEND_CONFIG_T *cfg); int VMF_VSRC_ConfigISP(VMF_VSRC_HANDLE_T *h, int stream, int layer, int isp, VMF_ISP_OPTION_T *opt); void *VMF_VSRC_GetInfo(VMF_VSRC_HANDLE_T *h, uint32_t idx, void *info); /* Pull in FEC method enum (VMF_FEC_METHOD_GTR etc.) — safe due to include guards */ #include #endif /* VMF_VIDEO_SOURCE_H */