From a600f38767136ef6fc77d920c7121fd0568e0f07 Mon Sep 17 00:00:00 2001 From: miketsai Date: Mon, 8 Jun 2026 16:11:49 +0800 Subject: [PATCH] Fix error sync from v4 --- build_and_serve.py | 49 +++++++++++++++- src/host_stream/app_header_init.c | 22 +++++++- src/host_stream/bt_uart.c | 24 +++++++- src/host_stream/event_recorder.c | 25 ++++++++- src/host_stream/kdp2_host_stream.c | 90 ++++++++++++++++++++++++------ 5 files changed, 188 insertions(+), 22 deletions(-) diff --git a/build_and_serve.py b/build_and_serve.py index d2a7bd9..2c8d169 100644 --- a/build_and_serve.py +++ b/build_and_serve.py @@ -284,4 +284,51 @@ def main(): parser.add_argument("--no-copy",action="store_true", help="不要複製 binary 到網路資料夾") parser.add_argument("--no-serve", action="store_true", - \ No newline at end of file + help="只 build + check,不啟動 HTTP server") + parser.add_argument("--port", type=int, default=8080, + help="HTTP server port (default: 8080)") + parser.add_argument("--image", default=DOCKER_IMAGE, + help=f"Docker image name (default: {DOCKER_IMAGE})") + args = parser.parse_args() + + + DOCKER_IMAGE = args.image + + print(head("KL630 Build & Serve")) + print(f" Root : {SCRIPT_DIR}") + print(f" Binary : {BINARY_PATH}") + print(f" Port : {args.port}") + print(f" Copy : {args.copy_dst}") + + # ===== Clean only ===== + if args.clean: + step_clean() + sys.exit(0) + + # ===== Clean then build ===== + if args.clean_build: + step_clean() + + # ===== Step 1: Build ===== + if not args.no_build: + if not step_ensure_image(): + sys.exit(1) + if not step_build(): + sys.exit(1) + # ===== Step 2: Check ===== + if not args.no_check: + if not step_check(): + if args.no_build: + print(warn(" (使用 --no-build 時 binary 可能是舊的)")) + else: + sys.exit(1) + # ===== Step 3: Copy(重點)===== + if not args.no_copy: + if not step_copy_to_network(args.copy_dst): + sys.exit(1) + # ===== Step 4: Serve ===== + if not args.no_serve: + step_serve(args.port) + +if __name__ == "__main__": + main() diff --git a/src/host_stream/app_header_init.c b/src/host_stream/app_header_init.c index 8391083..55146da 100644 --- a/src/host_stream/app_header_init.c +++ b/src/host_stream/app_header_init.c @@ -601,4 +601,24 @@ int app_header_recv_inference(uint32_t buf_addr, bool *bl_run_next_inference) /* Collision emphasis: draw a second inner trapezoid when active. */ if (ana->collision_risk && x_tr > x_tl + 8u && x_br > x_bl + 16u && y_bottom > y_top + 8u) { stdc_add_trapezoid_outline(di, &cnt, - x_tl + 4u, x_tr - 4u, \ No newline at end of file + x_tl + 4u, x_tr - 4u, x_bl + 8u, x_br - 8u, + y_top + 4u, y_bottom - 4u); + } + + /* Side warning/class panels are intentionally disabled. + * Keep only central ROI overlays to avoid per-class side boxes. */ + + g_dwResultCounts = cnt; + } + + /* Drive violation event state machine */ + event_recorder_update(ana); + } + else { + printf("[%s] Error: Job ID %u\n", __FUNCTION__, header_stamp->job_id); + return KP_FW_ERROR_UNKNOWN_APP; + } + + return KP_SUCCESS; +} + diff --git a/src/host_stream/bt_uart.c b/src/host_stream/bt_uart.c index 91f5a95..d240868 100644 --- a/src/host_stream/bt_uart.c +++ b/src/host_stream/bt_uart.c @@ -507,4 +507,26 @@ void bt_uart_set_identity(const char *aresx_version, const char *bt_name) if (aresx_version && *aresx_version) snprintf(s_ares_version, sizeof(s_ares_version), "%s", aresx_version); if (bt_name && *bt_name) - snprintf(s_bt_name, siz \ No newline at end of file + snprintf(s_bt_name, sizeof(s_bt_name), "%s", bt_name); + printf("[BT] identity: version=%s name=%s\n", s_ares_version, s_bt_name); +} + +int bt_uart_get_rent_status(void) +{ + pthread_mutex_lock(&s_rent_mtx); + int st = s_rent_status; + pthread_mutex_unlock(&s_rent_mtx); + return st; +} + +void bt_uart_set_rent_status(int status) +{ + pthread_mutex_lock(&s_rent_mtx); + s_rent_status = status; + pthread_mutex_unlock(&s_rent_mtx); +} + +void bt_uart_set_intervention_cb(bt_intervention_fn fn) +{ + s_intervention_cb = fn; +} diff --git a/src/host_stream/event_recorder.c b/src/host_stream/event_recorder.c index f6fb0d6..c8f32ea 100644 --- a/src/host_stream/event_recorder.c +++ b/src/host_stream/event_recorder.c @@ -871,4 +871,27 @@ void event_recorder_provide_frame(void) if (snap_lazy_init() != 0) return; - uint8_t *jpeg = (uint8_t *)MemBroker_GetMemory(SNAP_BU \ No newline at end of file + uint8_t *jpeg = (uint8_t *)MemBroker_GetMemory(SNAP_BUF_SIZE, VMF_ALIGN_TYPE_DEFAULT); + if (!jpeg) { + printf("[EVT] snap: MemBroker_GetMemory failed\n"); + return; + } + + int jpeg_size = VMF_SNAP_ProcessOneFrame(s_snap, 1920, 1080, SNAP_BUF_SIZE, jpeg); + int snap_ok = (jpeg_size > 0); + if (snap_ok) { + char out_path[384]; + snprintf(out_path, sizeof(out_path), "%s/%s", req.work_dir, req.filename); + save_jpeg(out_path, jpeg, jpeg_size); + } else { + printf("[EVT] snap: ProcessOneFrame failed (%d) — upload will proceed without image\n", jpeg_size); + } + MemBroker_FreeMemory(jpeg); + + if (req.immediate_upload) { + const char imgs[4][64] = { "snapshot.jpg", "", "", "" }; + int image_count = snap_ok ? 1 : 0; + launch_upload(req.work_dir, req.event_id, req.event_type, + req.max_level, 0.0f, imgs, image_count, 0); + } +} diff --git a/src/host_stream/kdp2_host_stream.c b/src/host_stream/kdp2_host_stream.c index d375339..3b2984b 100644 --- a/src/host_stream/kdp2_host_stream.c +++ b/src/host_stream/kdp2_host_stream.c @@ -440,8 +440,8 @@ static int init_video_source(HOST_STREAM_INIT_OPT_T* pHostStreamInit) } } else { /* FEC passthrough (no lens correction). Load FEC config for gFecDefValue defaults only. - * Pass NULL for ptFrontConfig — skips lens curve node loading (not needed for passthrough). - * Do NOT set ptFecConfig here — SDK sets only eFecMethod=GTR (below) for this case. */ + * Pass NULL for ptFrontConfig ??skips lens curve node loading (not needed for passthrough). + * Do NOT set ptFecConfig here ??SDK sets only eFecMethod=GTR (below) for this case. */ if(loadFECConfig(pHostStreamInit, NULL) == -1){ printf("[%s] No fec config file, using defaults\n", __func__); } @@ -535,14 +535,14 @@ void set_data_to_yuv(unsigned char* pucYBuff, unsigned int dwWidth, unsigned int dwOffsetV = dwOffsetU + dwPlaneSize ; /* YCbCr colour table indexed by YOLO class number (BT.601 full-range). - * class=0 person → green (Y=149, Cb= 43, Cr= 21) - * class=1 (other) → white (Y=235, Cb=128, Cr=128) - * class=2 vehicle → red (Y= 76, Cb= 84, Cr=255) - * fallback → white */ + * class=0 person ??green (Y=149, Cb= 43, Cr= 21) + * class=1 (other) ??white (Y=235, Cb=128, Cr=128) + * class=2 vehicle ??red (Y= 76, Cb= 84, Cr=255) + * fallback ??white */ static const unsigned char CLASS_YUV[][3] = { - {149, 43, 21}, /* 0: person – green */ - {235, 128, 128}, /* 1: other – white */ - { 76, 84, 255}, /* 2: vehicle – red */ + {149, 43, 21}, /* 0: person ??green */ + {235, 128, 128}, /* 1: other ??white */ + { 76, 84, 255}, /* 2: vehicle ??red */ }; const unsigned char *yuv; if (iColor >= 0 && iColor < (int)(sizeof(CLASS_YUV)/sizeof(CLASS_YUV[0]))) @@ -669,7 +669,7 @@ void draw_rect(YUV_BUFF_INFO_T* yuvBuffInfo, DETECT_INFO *ptDetInfo, int iColor) * Per-class YCbCr colours for STDC segmentation overlay (BT.601 full-range). * Order matches STDC_CLASS_* indices: * 0=bunker 1=car 2=grass 3=greenery 4=person 5=pond 6=road 7=tree - * road (class 6) is left transparent — it occupies most of the frame and adds + * road (class 6) is left transparent ??it occupies most of the frame and adds * visual noise rather than information. */ static const uint8_t s_stdc_yuv[STDC_NUM_CLASSES][3] = { @@ -679,7 +679,7 @@ static const uint8_t s_stdc_yuv[STDC_NUM_CLASSES][3] = { {137, 104, 55}, /* greenery #22c55e */ {144, 59, 203}, /* person #f97316 */ {154, 182, 87}, /* pond #60a5fa */ - { 0, 0, 0}, /* road — transparent (unused) */ + { 0, 0, 0}, /* road ??transparent (unused) */ { 88, 113, 80}, /* tree #15803d */ }; @@ -710,7 +710,7 @@ static void stdc_paint_seg_overlay(unsigned char *base_buf, uint32_t y_stride = info->dwYStride; uint32_t uv_stride = info->dwYStride >> 1; - /* Pre-compute column mapping: output x → seg col index */ + /* Pre-compute column mapping: output x ??seg col index */ uint8_t col_lut[1920]; uint32_t fx_max = (frame_w < 1920) ? frame_w : 1920; for (uint32_t fx = 0; fx < fx_max; fx++) @@ -721,7 +721,7 @@ static void stdc_paint_seg_overlay(unsigned char *base_buf, const uint8_t *seg_row = local_map + seg_r * seg_w; uint8_t *y_row = y_buf + fy * y_stride; - /* Y plane — every pixel */ + /* Y plane ??every pixel */ for (uint32_t fx = 0; fx < fx_max; fx++) { uint8_t cls = seg_row[col_lut[fx]]; if (cls == STDC_CLASS_ROAD || cls >= STDC_NUM_CLASSES) continue; @@ -729,7 +729,7 @@ static void stdc_paint_seg_overlay(unsigned char *base_buf, y_row[fx] = (uint8_t)(((uint16_t)y_row[fx] + col[0]) >> 1); } - /* UV plane — every other row, every other column */ + /* UV plane ??every other row, every other column */ if ((fy & 1) == 0) { uint8_t *cb_row = cb_buf + (fy >> 1) * uv_stride; uint8_t *cr_row = cr_buf + (fy >> 1) * uv_stride; @@ -1543,8 +1543,8 @@ void *kdp2_host_voc_thread(void *arg) if (vsrc_ssm_info.dwOffset[0] != 0 && vsrc_ssm_info.dwOffset[1] != 0) { abuf[q_idx].apdwData[0] = ssm_buf[q_idx].buffer + vsrc_ssm_info.dwOffset[0]; abuf[q_idx].apdwData[1] = ssm_buf[q_idx].buffer + vsrc_ssm_info.dwOffset[1]; - /* NV12 (semi-planar): offset[2]==0 means no separate Cr plane → NULL. - * YM12 (planar): offset[2]!=0 → Cr plane pointer. */ + /* NV12 (semi-planar): offset[2]==0 means no separate Cr plane ??NULL. + * YM12 (planar): offset[2]!=0 ??Cr plane pointer. */ abuf[q_idx].apdwData[2] = vsrc_ssm_info.dwOffset[2] ? (ssm_buf[q_idx].buffer + vsrc_ssm_info.dwOffset[2]) : NULL; } else { @@ -1672,7 +1672,7 @@ void *kdp2_host_stream_image_thread(void *arg) * VOC thread unblocks on g_dwInitBind and immediately checks g_dwDrawBoxType * to decide which SSM pin to read from. If draw box is enabled on stream 0, * it must see g_dwDrawBoxType=1 so it reads from VENC_VSRC_B_PIN (overlay - * output) rather than the raw ISP SSM — fixes intermittent HDMI no-overlay. */ + * output) rather than the raw ISP SSM ??fixes intermittent HDMI no-overlay. */ if (pHostStreamInit->bDrawBoxEnable && pHostStreamInit->dwEncodeStreamCount > 0) g_dwDrawBoxType = 1; g_dwInitBind = 1; @@ -1879,4 +1879,58 @@ EXIT_MIPI_IMAGE_THREAD: return NULL; } -void *kdp2_host_updat \ No newline at end of file +void *kdp2_host_update_result_thread(void *arg) +{ + HOST_STREAM_INIT_OPT_T* pHostStreamInit = (HOST_STREAM_INIT_OPT_T*)arg; + uint32_t buf_addr = 0; + uint32_t phy_buf_addr = 0; + int buf_size = 0; + int sts = 0; + + dbg_log("[%s] starting ..\n", __FUNCTION__); + if (app_hdr_recv_inf_cb == NULL) { + printf("[%s] recv_inf_cb is NULL \n", __FUNCTION__); + goto EXIT_UPDATE_RESULT_THREAD; + } + + g_dwRoiX = pHostStreamInit->dwRoiX; + g_dwRoiY = pHostStreamInit->dwRoiY; + g_dwDrawBoxEnable = pHostStreamInit->bDrawBoxEnable; + g_dwOnlyPerson = pHostStreamInit->dwOnlyPerson; + + while (true == _blResultRunning) { + // get result data from queue blocking wait + int ret = VMF_NNM_Fifoq_Manager_Result_Dequeue(&buf_addr, &phy_buf_addr, &buf_size, -1); + + if (KP_FW_FIFOQ_ACCESS_FAILED_125 == ret) { + continue; + } else if (KP_SUCCESS != ret) { + printf("[%s] Error: FIFO queue error %d.\n", __FUNCTION__, sts); + goto EXIT_UPDATE_RESULT_THREAD; + } + + //dbg_log("[%s] buf 0x%x len %d -- usb --> host\n", __FUNCTION__, buf_addr, header_stamp->total_size); + sts = app_hdr_recv_inf_cb(buf_addr, &_blResultRunning); //printf result + if (KP_SUCCESS != sts) { + printf("[%s] Error: callback function error (%d)\n", __FUNCTION__, sts); + goto EXIT_UPDATE_RESULT_THREAD; + } + + // return free buf back to queue + ret = VMF_NNM_Fifoq_Manager_Result_Put_Free_Buffer(buf_addr, phy_buf_addr, buf_size, -1); + if (KP_FW_FIFOQ_ACCESS_FAILED_125 == ret) { + continue; + } else if (KP_SUCCESS != ret) { + goto EXIT_UPDATE_RESULT_THREAD; + } + } + +EXIT_UPDATE_RESULT_THREAD: + if (NULL != g_pm_buf) { + MemBroker_FreeMemory(g_pm_buf); + g_pm_buf = NULL; + } + + dbg_log("[%s] exit ..\n", __FUNCTION__); + return NULL; +}