// Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include "uvc_ipc.h" #include "uvc_log.h" #include "drm.h" #include "mpi_enc.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "uvc_ipc" namespace ShmControl { struct UVC_IPC_INFO uvc_ipc_info; // TODO: (lxh) add handle here for use instead global handle extern "C" struct UVC_IPC_INFO *uvc_ipc_get_uvc_info_hd() { return &uvc_ipc_info; } extern "C" void uvc_ipc_init() { if (uvc_ipc_info.shm_control == NULL) { uvc_ipc_info.shm_control = new ShmUVCController(); // uvc_ipc_info.shm_control->startRecvMessage(); uvc_ipc_info.start = true; LOG_INFO("uvc_ipc_init first ok\n"); } else LOG_INFO("uvc_ipc_init yet\n"); } extern "C" void uvc_ipc_reinit() { if (uvc_ipc_info.shm_control) delete uvc_ipc_info.shm_control; LOG_INFO("uvc_ipc_reinit ok\n"); } extern "C" void uvc_ipc_event(enum UVC_IPC_EVENT event, void *data) { // LOG_INFO("enter uvc_ipc_event event:%s\n", shm_meg_name[event - 1].c_str()); pthread_mutex_lock(&uvc_ipc_info.mutex); if (uvc_ipc_info.start == false) //now only start onece { uvc_ipc_init(); } switch (event) { case UVC_IPC_EVENT_START: if (uvc_ipc_info.stop) { uvc_ipc_info.stop = false; uvc_ipc_info.shm_control->clearRecvMessage(); // clear the last data uvc_ipc_info.shm_control->startRecvMessage(); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_START, data); if (uvc_ipc_info.history[0] == true) { LOG_INFO("history eptz:%d\n", uvc_ipc_info.enable_eptz); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_ENABLE_ETPTZ, (void *)&uvc_ipc_info.enable_eptz); uvc_ipc_info.history[0] = false; uvc_ipc_info.history[2] = false; uvc_ipc_info.history[3] = false; } else { if (uvc_ipc_info.history[2] == true) { LOG_INFO("history eptz_pan:%d\n", uvc_ipc_info.zoom); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_SET_ZOOM, (void *)&uvc_ipc_info.zoom); uvc_ipc_info.history[2] = false; } if (uvc_ipc_info.history[3] == true) { LOG_INFO("history eptz_tilt:%d\n", uvc_ipc_info.zoom); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_SET_ZOOM, (void *)&uvc_ipc_info.zoom); uvc_ipc_info.history[3] = false; } } if (uvc_ipc_info.history[1] == true) { LOG_INFO("history zoom:%d\n", uvc_ipc_info.zoom); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_SET_ZOOM, (void *)&uvc_ipc_info.zoom); uvc_ipc_info.history[1] = false; } } break; case UVC_IPC_EVENT_STOP: if (!uvc_ipc_info.stop) { uvc_ipc_info.shm_control->stopRecvMessage(); //clear the recv data uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_STOP, data); uvc_ipc_info.shm_control->ShmUVCDrmRelease(); uvc_ipc_info.stop = true; } else { LOG_INFO("UVC_IPC_EVENT_STOP yet!\n"); } // uvc_ipc_reinit(); break; case UVC_IPC_EVENT_ENABLE_ETPTZ: #if UVC_STREAM_OFF_NOT_SEND_SETTING if (uvc_ipc_info.stop) { int *val = (int *)data; uvc_ipc_info.enable_eptz = *val; uvc_ipc_info.history[0] = true; LOG_INFO("eptz can't set %d now, UVC_IPC_EVENT_STOP yet! wait for next start effect!\n", uvc_ipc_info.enable_eptz); } else #endif uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_ENABLE_ETPTZ, data); break; case UVC_IPC_EVENT_SET_ZOOM: #if UVC_STREAM_OFF_NOT_SEND_SETTING if (uvc_ipc_info.stop) { int *val = (int *)data; uvc_ipc_info.zoom = *val; uvc_ipc_info.history[1] = true; LOG_INFO("zoom can't set %d now, UVC_IPC_EVENT_STOP yet! wait for next start effect!\n", uvc_ipc_info.zoom); } else #endif uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_SET_ZOOM, data); break; case UVC_IPC_EVENT_RET_TRANSPORT_BUF: uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_TRANSPORT_BUF, data); break; case UVC_IPC_EVENT_CONFIG_CAMERA: if (uvc_ipc_info.stop) { if (uvc_ipc_info.shm_control != NULL) { uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_CONFIG_CAMERA, data); } } break; case MSG_UVC_SET_EPTZ_PAN: #if UVC_STREAM_OFF_NOT_SEND_SETTING if (uvc_ipc_info.stop) { int *val = (int *)data; uvc_ipc_info.eptz_pan = *val; uvc_ipc_info.history[0] = false; uvc_ipc_info.history[2] = true; LOG_INFO("eptz_pan can't set %d now, UVC_IPC_EVENT_STOP yet! wait for next start effect!\n", uvc_ipc_info.eptz_pan); } else #endif uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_SET_EPTZ_PAN, data); break; case MSG_UVC_SET_EPTZ_TILT: #if UVC_STREAM_OFF_NOT_SEND_SETTING if (uvc_ipc_info.stop) { int *val = (int *)data; uvc_ipc_info.eptz_tilt = *val; uvc_ipc_info.history[0] = false; uvc_ipc_info.history[3] = true; LOG_INFO("eptz_tilt can't set %d now, UVC_IPC_EVENT_STOP yet! wait for next start effect!\n", uvc_ipc_info.eptz_tilt); } else #endif uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_SET_EPTZ_TILT, data); break; case UVC_IPC_EVENT_ENABLE_BYPASS: LOG_INFO("switch get stream from bypass link\n"); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_ENABLE_BYPASS, data); break; default: LOG_INFO("no support such uvc_ipc_event event:%d\n", event); break; } pthread_mutex_unlock(&uvc_ipc_info.mutex); if (event != UVC_IPC_EVENT_RET_TRANSPORT_BUF) LOG_INFO("exit uvc_ipc_event event:%s\n", shm_meg_name[event - 1].c_str()); } extern "C" void uvc_ipc_reconnect(void)//(struct UVC_IPC_INFO *info) { if (uvc_ipc_info.shm_control && uvc_ipc_info.stop == false) { LOG_INFO("aiserver died, uvc reconnect to aiserver and send last info\n"); uvc_ipc_info.shm_control->stopRecvMessage(); //clear the recv data uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_STOP, NULL); uvc_ipc_info.shm_control->ShmUVCDrmRelease(); uvc_ipc_info.shm_control->startRecvMessage(); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_CONFIG_CAMERA, &uvc_ipc_info.camera); uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_START, NULL); } else { LOG_INFO("aiserver died, uvc status is stop,no need do anything\n"); } } void ProcessRecvUVCMessage(void *opaque) { prctl(PR_SET_NAME, "uvc_ipc_recv_msg_thread"); ShmUVCController *controller = (ShmUVCController *)opaque; controller->recvUVCMessageLoop(); } #if UVC_IPC_DYNAMIC_DEBUG_ON void ProcessDebug(void *opaque) { prctl(PR_SET_NAME, "uvc_ipc_debug_thread"); ShmUVCController *controller = (ShmUVCController *)opaque; controller->uvcIPCDebugLoop(); } #endif ShmUVCController::ShmUVCController() { memset(&uvc_ipc_info, 0, sizeof(uvc_ipc_info)); pthread_mutex_init(&uvc_ipc_info.mutex, NULL); uvc_ipc_info.stop = true; #if UVC_SENDBUFF_USE_INIT_ALLOC MediaBufferInfo *send_bufferinfo = new MediaBufferInfo; send_message.set_allocated_buffer_info(send_bufferinfo); #endif #if UVC_IPC_DYNAMIC_DEBUG_ON debugLooping = true; debugThread = new std::thread(ProcessDebug, this); #endif initialize(); } ShmUVCController::~ShmUVCController() { if (drmFd >= 0) { drm_close(drmFd); drmFd = -1; } #if UVC_IPC_DYNAMIC_DEBUG_ON debugLooping = false; if (debugThread) { debugThread->join(); delete debugThread; debugThread = nullptr; } #endif pthread_mutex_destroy(&uvc_ipc_info.mutex); uvc_ipc_reinit(); } void ShmUVCController::ShmUVCDrmRelease() { int free_count = 0; for (std::map::iterator iter = drm_info.begin(); iter != drm_info.end(); ++iter) { ++free_count; if (iter->second.buf) drm_unmap_buffer(iter->second.buf, iter->second.size); if (iter->second.buf_fd) close(iter->second.buf_fd); if (iter->second.handle) drm_free(drmFd, iter->second.handle); LOG_DEBUG("drm_free count:%d\n", free_count); } drm_info.clear(); } void ShmUVCController::initialize() { recvLooping = false; recvThread = NULL; #ifdef USE_RK_AISERVER shmc::SetLogHandler(shmc::kDebug, [](shmc::LogLevel lv, const char *s) { printf("[%d] %s\n", lv, s); }); shmWriteQueue.InitForWrite(kShmUVCWriteKey, kQueueBufSize); //assert(shmWriteReadQueue.InitForWrite(kShmUVCReadKey, kQueueBufSize)); shmWriteReadQueue.InitForWrite(kShmUVCReadKey, kQueueBufSize); shmReadQueue.InitForRead(kShmUVCReadKey); LOG_DEBUG("ShmUVCController init\n"); #endif drmFd = drm_open(); } void ShmUVCController::startRecvMessage() { LOG_DEBUG("start recv message in\n"); #if UVC_IPC_DYNAMIC_DEBUG_ON gettimeofday(&ipc_enter_time, NULL); gettimeofday(&isp_enter_time, NULL); #endif recvLooping = true; norecv_err_count = 0; norecv_count = 0; abandon_count = 0; send_count = 0; recv_count = 0; set_buf_count = 0; isp_buf_count = 0; recvThread = new std::thread(ProcessRecvUVCMessage, this); if (!access("tmp/uvc_ipc_state", 0)) system("rm /tmp/uvc_ipc_state"); if (!access("/tmp/uvc_ipc_buffer", 0)) system("rm /tmp/uvc_ipc_buffer"); LOG_DEBUG("start recv message ok\n"); } void ShmUVCController::clearRecvMessage() { int ret = 0; int length = 0; std::string msg; std::lock_guard lock(rQueueMtx); do { ret = shmReadQueue.Pop(&msg); length = msg.length(); LOG_INFO("clear recv message(ret=%d, length=%d)\n", ret, length); // if (ret) // handleUVCMessage(msg); //test msg.clear(); } while (ret && length > 0); //queue_r_.Reset(); } void ShmUVCController::stopRecvMessage() { LOG_DEBUG("stop recv message enter\n"); #if UVC_IPC_DYNAMIC_DEBUG_ON if (!access(UVC_IPC_DYNAMIC_DEBUG_ISP_STATE, 0)) system("rm /tmp/uvc_isp_state"); #endif recvLooping = false; if (recvThread) { recvThread->join(); delete recvThread; recvThread = nullptr; } LOG_INFO("stop recv message ok\n"); clearRecvMessage(); //queue_r_.Reset(); } #if UVC_IPC_DYNAMIC_DEBUG_ON void ShmUVCController::uvcIPCDebugLoop() { LOG_DEBUG("enter\n"); bool eptz = false; int set_eptz = 0; while (debugLooping) { sleep(1); #if UVC_IPC_DYNAMIC_DEBUG_ON if (!access(UVC_IPC_DYNAMIC_DEBUG_STATE, 0)) { LOG_INFO("send state:%d,recv state:%d\n", send_state, recv_state); LOG_INFO("send_seq:%d, recv_seq:%d send_count:%d, recv_count:%d\n", send_seq, recv_seq, send_count, recv_count); } if (!access(UVC_IPC_DYNAMIC_DEBUG_EPTZ, 0) && eptz == false) { LOG_INFO("oepn eptz\n"); eptz = true; set_eptz = 1; uvc_ipc_event(UVC_IPC_EVENT_ENABLE_ETPTZ, (void *)&set_eptz); } else if (access(UVC_IPC_DYNAMIC_DEBUG_EPTZ, 0) && eptz == true) { LOG_INFO("close eptz\n"); eptz = false; set_eptz = 0; uvc_ipc_event(UVC_IPC_EVENT_ENABLE_ETPTZ, (void *)&set_eptz); } if (!access(UVC_IPC_DYNAMIC_DEBUG_ISP_STATE, 0)) { int fd = -1, ret = -1, handle_fd = -1, size = 0; char *buffer; unsigned int handle = 0; int isp_state = 0, y, uv; struct MPP_ENC_INFO enc_info; struct timespec now_tm = {0, 0}; LOG_INFO("send fixed picture to uvc instead isp enter\n"); std::lock_guard lock(rQueueMtx); fd = drm_open(); if (fd < 0) { LOG_ERROR("drm open fail\n"); goto DRM_FAIL; } size = MPP_ALIGN(width, 16) * MPP_ALIGN(height, 16) * 3 / 2; ret = drm_alloc(fd, size, 16, &handle, 0); if (ret) { LOG_ERROR("drm alloc fail\n"); goto DRM_FAIL; } ret = drm_handle_to_fd(fd, handle, &handle_fd, 0); if (ret) { LOG_ERROR("drm_handle_to_fd fail\n"); goto DRM_FAIL; } buffer = (char *)drm_map_buffer(fd, handle, size); if (!buffer) { LOG_ERROR("drm map buffer fail.\n"); goto DRM_FAIL; } enc_info.fd = handle_fd; enc_info.size = size; while (!access(UVC_IPC_DYNAMIC_DEBUG_ISP_STATE, 0)) { enc_info.seq = isp_state; clock_gettime(CLOCK_MONOTONIC, &now_tm); enc_info.pts = now_tm.tv_sec * 1000000LL + now_tm.tv_nsec / 1000; isp_state ++; if (isp_state % 2) { y = width * height / 4; memset(buffer, 128, y); memset(buffer + y, 64, y); memset(buffer + y * 2, 128, y); memset(buffer + y * 3, 192, y); uv = width * height / 8; memset(buffer + y * 4, 0, uv); memset(buffer + y * 4 + uv, 64, uv); memset(buffer + y * 4 + uv * 2, 128, uv); memset(buffer + y * 4 + uv * 3, 192, uv); } else { y = width * height / 4; memset(buffer, 64, y); memset(buffer + y, 128, y); memset(buffer + y * 2, 192, y); memset(buffer + y * 3, 128, y); uv = width * height / 8; memset(buffer + y * 4, 192, uv); memset(buffer + y * 4 + uv, 128, uv); memset(buffer + y * 4 + uv * 2, 64, uv); memset(buffer + y * 4 + uv * 3, 0, uv); } uvc_read_camera_buffer(buffer, &enc_info, NULL, 0); usleep(100 * 1000); } DRM_FAIL: drm_unmap_buffer(buffer, size); if (handle_fd >= 0) close(handle_fd); if (fd >=0 && handle > 0) drm_free(fd, handle); if (fd >= 0) drm_close(fd); if (!access(UVC_IPC_DYNAMIC_DEBUG_ISP_STATE, 0)) system("rm /tmp/uvc_isp_state"); LOG_INFO("send fixed picture to uvc instead isp exit\n"); } #endif } LOG_DEBUG("exit \n"); } #endif void ShmUVCController::recvUVCMessageLoop() { int ret = 0; LOG_DEBUG("recv uvc message thread enter\n"); while (recvLooping) { std::string msg; std::lock_guard lock(rQueueMtx); ret = shmReadQueue.Pop(&msg); if (ret) { //LOG_INFO("recv uvc message = %s \n", msg.c_str()); handleUVCMessage(msg); msg.clear(); norecv_count = 0; } else { usleep(1 * 1000); ++ norecv_count; if (norecv_count >= 5000) // 5s not recv data have error { ++ norecv_err_count; LOG_ERROR("%d ms not recv data, count up to %d, maybe isp err(uvc not get raw). stat:%d,%d seq:%d,%d\n", norecv_count * 1, norecv_err_count, send_state, recv_state, send_seq, recv_seq); if (norecv_err_count == 1) { system("touch /tmp/uvc_ipc_buffer"); // for check uvc_ipc_buffer LOG_INFO("test: touch /tmp/uvc_ipc_buffer ok!\n"); system("touch /tmp/uvc_ipc_state"); // for check uvc_ipc_state LOG_INFO("test: touch /tmp/uvc_ipc_state ok!\n"); } norecv_count = 0; } } } LOG_DEBUG("recv uvc message thread end\n"); } void ShmUVCController::handleUVCMessage(std::string &msg) { int msgType = 0; UVCMessage message; message.ParseFromString(msg); msgType = message.msg_type(); if (msgType == MSG_UVC_TRANSPORT_BUF) // UVC Buffer { MediaBufferInfo bufferInfo = message.buffer_info(); recvUVCBuffer(&bufferInfo); //LOG_INFO("recv uvc buffer message\n"); } else { LOG_WARN("recv uvc unknown message\n"); } } void ShmUVCController::recvUVCBuffer(MediaBufferInfo *bufferInfo) { int ret = 0; int buf_fd; unsigned int handle; int drm_size; char *buf = NULL; int32_t name = bufferInfo->id(); int32_t buf_size = bufferInfo->size(); int64_t privData = bufferInfo->priv_data(); int64_t pts = bufferInfo->pts(); int32_t seq = bufferInfo->seq(); struct SendBufferInfo send_info; //std::map temp_map; struct DrmBuffMap drm_map; int map_count; bool has_map = false; send_info.id = name; send_info.size = bufferInfo->size(); send_info.fd = bufferInfo->fd(); send_info.handle = bufferInfo->handle(); send_info.data = bufferInfo->data(); send_info.priv_data = privData; send_info.seq = seq; recv_count ++; int count = 0; struct MPP_ENC_INFO enc_info; #if UVC_DYNAMIC_DEBUG_USE_TIME if (!access(UVC_DYNAMIC_DEBUG_USE_TIME_CHECK, 0)) { int64_t use_time_us, now_time_us; struct timespec now_tm = {0, 0}; clock_gettime(CLOCK_MONOTONIC, &now_tm); now_time_us = now_tm.tv_sec * 1000000LL + now_tm.tv_nsec / 1000; // us use_time_us = now_time_us - pts; //pts = now_time_us;//for test LOG_INFO("isp->aiserver->ipc seq: %d latency time:%lld us, %lld ms\n",seq, use_time_us, use_time_us / 1000); } #endif #if UVC_IPC_DYNAMIC_DEBUG_ON recv_state = UVC_IPC_STATE_RECV_ENTER; recv_seq = seq; #endif #if UVC_IPC_DYNAMIC_DEBUG_ON if (!access(UVC_IPC_DYNAMIC_DEBUG_FPS, 0)) { ++frm; if (frm == 100) { struct timeval now_time; gettimeofday(&now_time, NULL); int64_t use_timems = (now_time.tv_sec * 1000 + now_time.tv_usec / 1000) - (ipc_enter_time.tv_sec * 1000 + ipc_enter_time.tv_usec / 1000); ipc_enter_time.tv_sec = now_time.tv_sec; ipc_enter_time.tv_usec = now_time.tv_usec; fps = (1000.0 * frm) / use_timems; frm = 0; LOG_INFO("ipc recv fps:%0.1f\n", fps); } } #endif for (std::map::iterator iter = drm_info.begin(); iter != drm_info.end(); ++iter) { count ++; if (name == iter->second.id) { has_map = true; #if RK_MPP_DYNAMIC_DEBUG_ON if (!access(RK_MPP_DYNAMIC_DEBUG_IN_CHECK, 0) || (encode_type == UVC_IPC_ENC_YUV)) #else if (encode_type == UVC_IPC_ENC_YUV) #endif { if (!iter->second.buf) { iter->second.buf = (char *)drm_map_buffer(drmFd, iter->second.handle, iter->second.size); } } buf = iter->second.buf; buf_fd = iter->second.buf_fd; break; } } // LOG_INFO("count=%d drm_info.size()=%d\n",count, drm_info.size()); if (has_map == false) { drm_get_info_from_name(drmFd, name, &handle, &drm_size); ret = drm_handle_to_fd(drmFd, handle, &buf_fd, 0); if (ret) { LOG_ERROR("drm_handle_to_fd fail\n"); return; } #if RK_MPP_DYNAMIC_DEBUG_ON if (!access(RK_MPP_DYNAMIC_DEBUG_IN_CHECK, 0) || (encode_type == UVC_IPC_ENC_YUV)) #else if (encode_type == UVC_IPC_ENC_YUV) #endif { buf = (char *)drm_map_buffer(drmFd, handle, buf_size); } drm_map.buf = buf; drm_map.id = name; drm_map.size = buf_size; drm_map.handle = handle; drm_map.buf_fd = buf_fd; map_count = drm_info.size() + 1; isp_buf_count ++; drm_info.insert(std::map::value_type(map_count, drm_map)); LOG_INFO("new drm_map count=%d name=%d,buf_fd=%d buf_size=%d drm_size=%d priv=0x%llx\n", map_count, name, buf_fd, buf_size, drm_size, privData); } #if UVC_IPC_DYNAMIC_DEBUG_ON recv_state = UVC_IPC_STATE_RECV_ENC_ENTER; #endif enc_info.fd = buf_fd; enc_info.size = nv12_size; enc_info.pts = pts; enc_info.seq = seq; #if RK_MPP_DYNAMIC_DEBUG_ON if (!access(UVC_IPC_DYNAMIC_DEBUG_ISP_FPS, 0)) { ++isp_frm; if (isp_frm == 100) { struct timeval now_time; gettimeofday(&now_time, NULL); int64_t use_timems = (now_time.tv_sec * 1000 + now_time.tv_usec / 1000) - (isp_enter_time.tv_sec * 1000 + isp_enter_time.tv_usec / 1000); isp_enter_time.tv_sec = now_time.tv_sec; isp_enter_time.tv_usec = now_time.tv_usec; fps = (1000.0 * isp_frm) / use_timems; isp_frm = 0; LOG_INFO("isp recv fps:%0.1f\n", fps); } } else #endif { #if UVC_ABANDON_FRM_COUNT if (abandon_count < UVC_ABANDON_FRM_COUNT) { ++ abandon_count; LOG_INFO("abandon frm, count=%d\n", abandon_count); } else #endif { uvc_read_camera_buffer(buf, &enc_info, NULL, 0); } } #if UVC_IPC_DYNAMIC_DEBUG_ON recv_state = UVC_IPC_STATE_RECV_ENC_EXIT; #endif //uvc_ipc_event(UVC_IPC_EVENT_RET_TRANSPORT_BUF, (void *)&send_info); //not call uvc_ipc_event here,it will be dead lock if (!set_buf_count || (set_buf_count && isp_buf_count <= set_buf_count)) uvc_ipc_info.shm_control->sendUVCBuffer(MSG_UVC_TRANSPORT_BUF, (void *)&send_info); else { // for mjpeg_fps 4k solution isp_buf_count -= 1; LOG_INFO("save isp buf count:%d priv=0x%llx\n", drm_info.size() - isp_buf_count, privData); } #if UVC_IPC_DYNAMIC_DEBUG_ON recv_state = UVC_IPC_STATE_RECV_EXIT; #endif } void ShmUVCController::sendUVCBuffer(enum ShmUVCMessageType event, void *data) { std::string sendbuf; #if UVC_IPC_DYNAMIC_DEBUG_ON send_state = UVC_IPC_STATE_SEND_ENTER; #endif std::lock_guard lock(wQueueMtx); #if UVC_IPC_DYNAMIC_DEBUG_ON send_state = UVC_IPC_STATE_SEND_ENTER_UNLOCK; #endif switch (event) { case MSG_UVC_START: { UVCMessage message; message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); if (encode_type == UVC_IPC_ENC_MJPEG_LOW_LATENCY) { set_buf_count = 2; } } break; case MSG_UVC_STOP: { UVCMessage message; message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); } break; case MSG_UVC_ENABLE_ETPTZ: { UVCMessage message; MethodParams *method_param = new MethodParams; int *enable; if (data == NULL) *enable = 0; else enable = (int *)data; method_param->set_i32_p(*enable); message.set_allocated_method_params(method_param); message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); LOG_INFO("send uvc eptz:%d \n", *enable); uvc_ipc_info.enable_eptz = *enable; } break; case MSG_UVC_SET_ZOOM: { UVCMessage message; MethodParams *method_param = new MethodParams; int *int_zoom = (int *)data; float zoom = (float)(*int_zoom / 10.0); //MethodParams method_param = method_param->set_flo_p(zoom); message.set_allocated_method_params(method_param); message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); LOG_INFO("send uvc zoom:%f \n", zoom); uvc_ipc_info.zoom = *int_zoom; } break; case MSG_UVC_TRANSPORT_BUF: { #if UVC_SENDBUFF_USE_INIT_ALLOC MediaBufferInfo *bufferInfo = &const_cast(send_message.buffer_info()); struct SendBufferInfo *info = (struct SendBufferInfo *)data; bufferInfo->set_id(info->id); bufferInfo->set_size(info->size); bufferInfo->set_fd(info->fd); bufferInfo->set_handle(info->handle); bufferInfo->set_data(info->data); bufferInfo->set_priv_data(info->priv_data); bufferInfo->set_seq(info->seq); send_seq = info->seq; send_count ++; send_message.set_msg_type(event); send_message.set_msg_name("uvcbuffer"); send_message.SerializeToString(&sendbuf); send_message.ParseFromString(sendbuf); #else UVCMessage message; MediaBufferInfo *bufferInfo = new MediaBufferInfo; struct SendBufferInfo *info = (struct SendBufferInfo *)data; bufferInfo->set_id(info->id); bufferInfo->set_size(info->size); bufferInfo->set_fd(info->fd); bufferInfo->set_handle(info->handle); bufferInfo->set_data(info->data); bufferInfo->set_priv_data(info->priv_data); message.set_allocated_buffer_info(bufferInfo); message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); #endif } break; case MSG_UVC_CONFIG_CAMERA: { UVCMessage message; StreamInfo *streamInfo = new StreamInfo; struct CAMERA_INFO *info = (struct CAMERA_INFO *)data; width = info->width; height = info->height; nv12_size = width * height * 3 / 2; streamInfo->set_width(info->width); streamInfo->set_height(info->height); streamInfo->set_vir_width(info->vir_width); streamInfo->set_vir_height(info->vir_height); streamInfo->set_buf_size(info->buf_size); streamInfo->set_range(info->range); encode_type = info->encode_type; uvc_fps_set = info->uvc_fps_set; message.set_allocated_stream_info(streamInfo); message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); LOG_INFO("send uvc config camera. \ width:%d,height:%d,vir_width=%d,vir_height=%d,buf_size=%d,range=%d,enc=%d,fps=%d\n", info->width, info->height, info->vir_width, info->vir_height, info->buf_size, info->range, encode_type, uvc_fps_set); memcpy(&uvc_ipc_info.camera, info, sizeof(struct CAMERA_INFO)); } break; case MSG_UVC_SET_EPTZ_PAN: { UVCMessage message; MethodParams *method_param = new MethodParams; int *pan; if (data == NULL) *pan = 0; else pan = (int *)data; method_param->set_i32_p(*pan); message.set_allocated_method_params(method_param); message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); LOG_INFO("send uvc eptz pan:%d \n", *pan); uvc_ipc_info.eptz_pan = *pan; } break; case MSG_UVC_SET_EPTZ_TILT: { UVCMessage message; MethodParams *method_param = new MethodParams; int *tilt; if (data == NULL) *tilt = 0; else tilt = (int *)data; method_param->set_i32_p(*tilt); message.set_allocated_method_params(method_param); message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); LOG_INFO("send uvc eptz tilt:%d \n", *tilt); uvc_ipc_info.eptz_tilt = *tilt; } break; case MSG_UVC_ENABLE_BYPASS: { UVCMessage message; MethodParams *method_param = new MethodParams; int *enable; if (data == NULL) *enable = 0; else enable = (int *)data; method_param->set_i32_p(*enable); message.set_allocated_method_params(method_param); message.set_msg_type(event); message.set_msg_name("uvcbuffer"); message.SerializeToString(&sendbuf); message.ParseFromString(sendbuf); LOG_INFO("send uvc use bypass:%d \n", *enable); } break; default : break; } #if UVC_IPC_DYNAMIC_DEBUG_ON send_state = UVC_IPC_STATE_SEND_READY; #endif shmWriteQueue.Push(sendbuf); #if UVC_IPC_DYNAMIC_DEBUG_ON send_state = UVC_IPC_STATE_SEND_EXIT; #endif } } // namespace ShmControl