2026-04-12 17:47:54 +08:00

739 lines
20 KiB
C

/*
*******************************************************************************
* Copyright (c) 2010-2022 VATICS(KNERON) Inc. All rights reserved.
*
* +-----------------------------------------------------------------+
* | THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED |
* | AND COPIED IN ACCORDANCE WITH THE TERMS AND CONDITIONS OF SUCH |
* | A LICENSE AND WITH THE INCLUSION OF THE THIS COPY RIGHT NOTICE. |
* | THIS SOFTWARE OR ANY OTHER COPIES OF THIS SOFTWARE MAY NOT BE |
* | PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. THE |
* | OWNERSHIP AND TITLE OF THIS SOFTWARE IS NOT TRANSFERRED. |
* | |
* | THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT |
* | ANY PRIOR NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY |
* | VATICS(KNERON) INC. |
* +-----------------------------------------------------------------+
*
*******************************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdarg.h>
#include <pthread.h>
#include <stdbool.h>
#include "fec_api.h"
#include "lvgl_example.h"
#include "lvgl_example_msg_sender.h"
#include "MemBroker/mem_broker.h"
#include "MsgBroker/msg_broker.h"
#include "vmf/video_source.h"
#include "vmf/video_bind.h"
#include "vmf/video_encoder.h"
#include "vmf/video_display_mechanism.h"
#include "vmf/source_connect.h"
#include "vmf/sync_shared_memory.h"
#include "vmf/config_fec.h"
#include "vmf/vector_dma.h"
#include "comm/video_buf.h"
#include "comm/frame_info.h"
#include "iniparser/iniparser.h"
#include "lvgl/lvgl.h"
#include "lvgl/custom/lv_custom.h"
#include "lv_drivers/display/v4l2dev.h"
#define VENC_VSRC_PIN "vsrc_ssm"
#define VENC_RESOURCE_DIR "./Resource/"
#define release_string(X) do { if (X) free(X); } while (0)
typedef enum {
HIDE = 0,
SHOW
} TEXT_MODE;
VMF_LAYOUT_T g_tLayout;
VMF_VSRC_HANDLE_T* g_ptVsrcHandle = NULL;
static char *g_szConfig = NULL;
static char *g_szAutoSceneConfig = NULL;
static char *g_szSensorConfig = NULL;
static uint32_t g_dwWidth, g_dwHeight;
static uint32_t g_dwFontSize, g_dwSubIdx;
static VMF_VENC_CODEC_TYPE g_eCodecType = VMF_VENC_CODEC_TYPE_H265;
static int g_bTerminate = 0;
static char text_string[32];
/*gui setting */
static uint32_t pool_size;
static uint32_t gui_width;
static uint32_t gui_height;
static uint32_t gui_x;
static uint32_t gui_y;
static bool yuv_device;
/*Indev button data*/
static const char *btn_txt[2][4] = {
{ "page1", "show_def", "show_ghi", "show_jkl" },
{ "show_lmn", "show_opq", "show_rst", "return" }
};
static const char *ovl_txt[2][4] = {
{ "", "def", "ghi", "jkl" },
{"lmn", "opq", "rst", "" }
};
static lv_point_t positons[4];
static int btn_index = 0;
static bool btn_status = 0;
static int page_index = 0;
static VMF_BIND_CONTEXT_T* g_ptBind = NULL;
extern void dump_yuv(uint8_t *, uint8_t *, uint8_t *, uint32_t, const char *);
static void load_config(void);
static void sig_handler(int);
static void exit_handler(void);
static int init_video_source(void);
static int init_fec_mode(void);
static int init_dma_handle(VMF_DMA_DESCRIPTOR_T **, VMF_DMA_HANDLE_T **);
static int dma_upadate_mem(uint8_t *, uint8_t *, uint32_t, VMF_DMA_DESCRIPTOR_T *, VMF_DMA_HANDLE_T *);
static void vsrc_init_callback(unsigned int, unsigned int);
static void setup_fec(VMF_FEC_ORIG_CONFIG_T *);
static void setup_spec(VMF_VSRC_SPEC_CONFIG_T *, VMF_VENC_CODEC_TYPE);
static void release_video_source(void);
static int init_bind(void);
static int init_video_display(VMF_VDISP_HANDLE_T **);
static void *video_loop(void *);
static void *gui_loop(void *);
static void draw_screen(void);
static bool button_read(lv_indev_drv_t *, lv_indev_data_t *);
static int get_button_index(void);
static bool get_button_status(void);
static void reset_button_status(void);
static void button_event(lv_obj_t *, lv_event_t);
static void release_bind(void);
static void msg_callback(MsgContext *, void *);
static int init_text_overlay(void);
static int set_text_overlay(TEXT_MODE);
void dump_yuv(uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_size, const char *fmt)
{
FILE *out = fopen(fmt, "wb");
fwrite(y, 1, y_size, out);
fwrite(u, 1, y_size >> 2, out);
fwrite(v, 1, y_size >> 2, out);
fclose(out);
}
void load_config(void)
{
const char *tmp;
dictionary *ini;
if((ini = iniparser_load(g_szConfig)) == NULL) {
print_msg("Unable to parse file: %s\n", g_szConfig);
exit(EXIT_FAILURE);
}
tmp = iniparser_getstring(ini, "sensor:sensor_config", NULL);
g_szSensorConfig = strdup(tmp);
tmp = iniparser_getstring(ini, "sensor:autoscene_config", NULL);
g_szAutoSceneConfig = strdup(tmp);
g_dwWidth = iniparser_getint(ini, "stream:width", 1920);
g_dwHeight = iniparser_getint(ini, "stream:height", 1080);
pool_size = iniparser_getint(ini, "gui:pool_size", 0);
gui_width = iniparser_getint(ini, "gui:width", 480);
gui_height = iniparser_getint(ini, "gui:height", 320);
gui_x = iniparser_getint(ini, "gui:pos_x", 0);
gui_y = iniparser_getint(ini, "gui:pos_y", 0);
yuv_device = iniparser_getboolean(ini, "gui:yuv_device", 0);
g_dwFontSize = iniparser_getint(ini, "text_overlay:font_size", 5);
iniparser_freedict(ini);
}
void sig_handler(int sig)
{
print_msg("[%s] receive SIGNAL: %d\n",__func__, sig);
g_bTerminate = 1;
}
void exit_handler(void)
{
release_string(g_szConfig);
release_string(g_szSensorConfig);
release_string(g_szAutoSceneConfig);
}
int init_video_source(void)
{
VMF_VSRC_INITOPT_T tInitOpt;
VMF_VSRC_FRONTEND_CONFIG_T tFrontCfg;
VMF_FEC_ORIG_CONFIG_T tFecOrgCfg;
memset(&tInitOpt, 0, sizeof tInitOpt);
memset(&tFrontCfg, 0, sizeof tFrontCfg);
memset(&tFecOrgCfg, 0, sizeof tFecOrgCfg);
setup_fec(&tFecOrgCfg);
tFrontCfg.tFecInitConfig.ptFecConfig = &tFecOrgCfg;
tFrontCfg.tFecInitConfig.eCoeffMode = VMF_FEC_COEF_MODE_ORIG;
tFrontCfg.tFecInitConfig.eFecMethod = VMF_FEC_METHOD_GTR;
tFrontCfg.tFecInitConfig.eGridSize = VMF_FEC_GRID_8X8;
tFrontCfg.dwSensorConfigCount = 1;
tFrontCfg.apszSensorConfig[0] = g_szSensorConfig;
tInitOpt.dwFrontConfigCount = 1;
tInitOpt.ptFrontConfig = &tFrontCfg;
tInitOpt.pszAutoSceneConfig = g_szAutoSceneConfig;
tInitOpt.pszOutPinPrefix = VENC_VSRC_PIN;
tInitOpt.bShared = 1;
tInitOpt.fnInitCallback = vsrc_init_callback;
tInitOpt.pszResourceDir = VENC_RESOURCE_DIR;
setup_spec(&tInitOpt.tSpecConfig, g_eCodecType);
g_ptVsrcHandle = VMF_VSRC_Init(&tInitOpt);
if (!g_ptVsrcHandle) {
print_msg("[%s] VMF_VSRC_Init failed!\n", __func__);
return -1;
}
if (VMF_VSRC_Start(g_ptVsrcHandle, NULL)) {
print_msg("[%s] VMF_VSRC_Start failed!\n", __func__);
return -1;
}
return 0;
}
int init_fec_mode(void)
{
if (setup_fec_mode(0, FEC_MODE_1R, false, g_eCodecType)) {
print_msg("[%s] setup_fec_mode failed!\n", __func__);
return -1;
}
return 0;
}
int init_dma_handle(VMF_DMA_DESCRIPTOR_T **pptDmaDesc, VMF_DMA_HANDLE_T **pptDmaHandle)
{
VMF_DMA_1D_INIT_T tDmaInit;
memset(&tDmaInit, 0, sizeof tDmaInit);
tDmaInit.dwFormatFlag = 0;
*pptDmaDesc = VMF_DMA_Descriptor_Create(DMA_1D, &tDmaInit);
if (!*pptDmaDesc) {
print_msg("[%s] VMF_DMA_Descriptor_Create failed!\n", __func__);
return -1;
}
*pptDmaHandle = VMF_DMA_Init(1, 128);
if (!*pptDmaHandle) {
print_msg("[%s] VMF_DMA_Init failed!\n", __func__);
return -1;
}
return 0;
}
int dma_upadate_mem(uint8_t *pbyDst, uint8_t *pbySrc, uint32_t dwSize,
VMF_DMA_DESCRIPTOR_T *ptDmaDesc, VMF_DMA_HANDLE_T *ptDmaHandle)
{
VMF_DMA_ADDR_T tDmaAddr;
tDmaAddr.pbySrcYPhysAddr = pbySrc;
tDmaAddr.pbyDstYPhysAddr = pbyDst;
tDmaAddr.dwTransSize = dwSize;
if (VMF_DMA_Descriptor_Update_Addr(ptDmaDesc, &tDmaAddr)) {
print_msg("[%s] VMF_DMA_Descriptor_Update_Addr failed!\n", __func__);
return -1;
}
if (VMF_DMA_Setup(ptDmaHandle, &ptDmaDesc, 1)) {
print_msg("[%s] VMF_DMA_Setup failed!\n", __func__);
return -1;
}
if (VMF_DMA_Process(ptDmaHandle)) {
print_msg("[%s] VMF_DMA_Process failed!\n", __func__);
return -1;
}
return 0;
}
void vsrc_init_callback(unsigned int dwWidth, unsigned int dwHeight)
{
memset(&g_tLayout, 0, sizeof g_tLayout);
g_tLayout.dwCanvasWidth = dwWidth;
g_tLayout.dwCanvasHeight = dwHeight;
g_tLayout.dwVideoPosX = 0;
g_tLayout.dwVideoPosY = 0;
g_tLayout.dwVideoWidth = dwWidth;
g_tLayout.dwVideoHeight = dwHeight;
print_msg("[%s]: width:%u, height:%u\n", __func__, dwHeight, dwHeight);
}
void setup_spec(VMF_VSRC_SPEC_CONFIG_T *ptSpec, VMF_VENC_CODEC_TYPE eCodecType)
{
ptSpec->bEnableSpec = 1;
ptSpec->dwIspMode = VMF_ISP_MODE_FEC;
switch (eCodecType) {
case VMF_VENC_CODEC_TYPE_H264:
ptSpec->tIfpEncSpec.bEncH264 = 1;
ptSpec->tIspEncSpec.bEncH264 = 1;
break;
case VMF_VENC_CODEC_TYPE_H265:
ptSpec->tIfpEncSpec.bEncH265 = 1;
ptSpec->tIspEncSpec.bEncH265 = 1;
break;
case VMF_VENC_CODEC_TYPE_MJPG:
ptSpec->tIfpEncSpec.bEncJPEG = 1;
ptSpec->tIspEncSpec.bEncJPEG = 1;
break;
default:
exit(EXIT_FAILURE);
}
}
void setup_fec(VMF_FEC_ORIG_CONFIG_T *ptFecOrgCfg)
{
ptFecOrgCfg->eAppType = VMF_FEC_APP_TABL;
ptFecOrgCfg->fZoom = 1.0;
}
void release_video_source(void)
{
if (g_ptVsrcHandle) {
VMF_VSRC_Stop(g_ptVsrcHandle);
VMF_VSRC_Release(g_ptVsrcHandle);
}
}
int init_bind(void)
{
VMF_BIND_INITOPT_T tInitOpt;
memset(&tInitOpt, 0, sizeof tInitOpt);
tInitOpt.dwSrcOutputIndex = 0;
tInitOpt.ptSrcHandle = g_ptVsrcHandle;
tInitOpt.pfnQueryFunc = (VMF_BIND_QUERY_FUNC) VMF_VSRC_GetInfo;
tInitOpt.pfnIspFunc = (VMF_BIND_CONFIG_ISP_FUNC) VMF_VSRC_ConfigISP;
g_ptBind = VMF_BIND_Init(&tInitOpt);
if (!g_ptBind){
print_msg("[%s] VMF_BIND_Init failed!!\n", __func__);
return -1;
}
return 0;
}
void release_bind(void)
{
if (g_ptBind)
VMF_BIND_Release(g_ptBind);
}
int init_video_display(VMF_VDISP_HANDLE_T **pptDispHandle)
{
VMF_VDISP_INITOPT_T tDisplayOpt;
memset(&tDisplayOpt, 0, sizeof tDisplayOpt);
tDisplayOpt.dwInPixFormat = VMF_MAKEFOURCC('Y', 'M', '1', '2');;
tDisplayOpt.dwMaxInWidth = VMF_32_ALIGN(g_dwWidth);
tDisplayOpt.dwMaxInHeight = VMF_16_ALIGN(g_dwHeight);
if ((*pptDispHandle = VMF_VDISP_Init(&tDisplayOpt)) == NULL) {
printf("%s VMF_VDISP_Init failed!\n", __func__);
return -1;
}
return 0;
}
void *video_loop(void *data __attribute__((unused)))
{
VMF_SRC_CONNECT_INFO_T tSrcCntInfo;
SSM_HANDLE_T *ptSsmHandle = NULL;
SSM_BUFFER_T tSsmBuf;
VMF_FRAME_BUF_T atDispBuf[VMF_VIDEO_DISPLAY_MIN_QUEUE_SIZE];
uint8_t *atPhysAddr[VMF_VIDEO_DISPLAY_MIN_QUEUE_SIZE];
unsigned int dwDispQIdx = 0;
pthread_t thrd_g;
unsigned int dwYSize = VMF_32_ALIGN(g_dwWidth)*VMF_16_ALIGN(g_dwHeight), dwYUVSize = dwYSize * 3 >> 1;
VMF_DMA_DESCRIPTOR_T *ptDmaDesc = NULL;
VMF_DMA_HANDLE_T *ptDmaHandle = NULL;
VMF_VDISP_HANDLE_T *ptDispHandle = NULL;
if (init_video_display(&ptDispHandle)) {
print_msg("[%s] init_video_display failed!\n", __func__);
goto RELEASE;
}
if (init_dma_handle(&ptDmaDesc, &ptDmaHandle)) {
print_msg("[%s] init_dma_handle failed!\n", __func__);
goto RELEASE;
}
memset(&tSrcCntInfo, 0, sizeof tSrcCntInfo);
memset(&tSsmBuf, 0, sizeof tSsmBuf);
memset(atDispBuf, 0, sizeof atDispBuf);
for (int i = 0; i < VMF_VIDEO_DISPLAY_MIN_QUEUE_SIZE; i++) {
atDispBuf[i].apdwData[0] = MemBroker_GetMemory(dwYUVSize, VMF_ALIGN_TYPE_8_BYTE);
if (!atDispBuf[i].apdwData[0]) {
print_msg("[%s] allocate display buffer failed!\n", __func__);
goto RELEASE;
}
atDispBuf[i].apdwData[1] = atDispBuf[i].apdwData[0] + dwYSize;
atDispBuf[i].apdwData[2] = atDispBuf[i].apdwData[1] + (dwYSize >> 2);
atPhysAddr[i] = MemBroker_GetPhysAddr(atDispBuf[i].apdwData[0]);
}
tSrcCntInfo.dwCodecType = g_eCodecType;
if (VMF_BIND_Request(g_ptBind, g_dwWidth, g_dwHeight, 0, 0, &tSrcCntInfo)) {
print_msg("[%s] VMF_BIND_Request failed!\n", __func__);
exit(EXIT_FAILURE);
}
g_dwSubIdx = tSrcCntInfo.bUseResizedSrc ? 1 : 0;
ptSsmHandle = SSM_Reader_Init(tSrcCntInfo.szSrcPin, tSrcCntInfo.bIsSsmShared);
if (!ptSsmHandle) {
print_msg("[%s] SSM_Reader_Init failed!\n", __func__);
goto RELEASE;
}
if (init_text_overlay()) {
print_msg("[%s] init_text_overlay failed\n", __func__);
goto RELEASE;
}
pthread_create(&thrd_g, NULL, gui_loop, ptDispHandle);
pthread_setname_np(thrd_g, "gui_loop");
while(!g_bTerminate) {
uint8_t *pbySrc, *pbyDst;
SSM_Reader_ReturnReceiveBuff(ptSsmHandle, &tSsmBuf);
pbySrc = MemBroker_GetPhysAddr(tSsmBuf.buffer + VMF_MAX_SSM_HEADER_SIZE);
pbyDst = atPhysAddr[dwDispQIdx];
if (dma_upadate_mem(pbyDst, pbySrc, dwYUVSize, ptDmaDesc, ptDmaHandle)) {
print_msg("[%s] dma_upadate_mem failed!\n", __func__);
goto RELEASE;
}
VMF_VDISP_ProcessOneFrame(ptDispHandle, &atDispBuf[dwDispQIdx], &dwDispQIdx);
}
RELEASE:
if (thrd_g) {
VMF_VDISP_PIP_Stop(ptDispHandle);
pthread_join(thrd_g, NULL);
}
if (ptSsmHandle) {
SSM_Reader_ReturnBuff(ptSsmHandle, &tSsmBuf);
SSM_Release(ptSsmHandle);
}
if (ptDispHandle)
VMF_VDISP_Release(ptDispHandle);
for (int i = 0; i < VMF_VIDEO_DISPLAY_MIN_QUEUE_SIZE; i++) {
if (atDispBuf[i].apdwData[0])
MemBroker_FreeMemory(atDispBuf[i].apdwData[0]);
}
if (ptDmaDesc)
VMF_DMA_Descriptor_Destroy(ptDmaDesc);
if (ptDmaHandle)
VMF_DMA_Release(ptDmaHandle);
return NULL;
}
void *gui_loop(void *data)
{
VMF_VDISP_HANDLE_T *disp_handle = data;
unsigned int disp_buf_size;
lv_color_t *buf;
lv_disp_buf_t disp_buf;
lv_disp_drv_t disp_drv;
lv_indev_drv_t indev_drv;
lv_indev_t *my_indev;
/*LittlevGL init, allocate memory space as pool*/
lv_init(pool_size);
/*Setup screen parameters*/
lv_scr_setup(disp_handle, gui_width, gui_height, gui_x, gui_y, yuv_device);
/*Linux v4l2 dev init*/
v4l2dev_init();
/*Init display buffer, allocate buffer for screen-flushing*/
disp_buf_size = 10 * lv_scr_get_hor_res();
buf = malloc(disp_buf_size * sizeof *buf);
/*Initialize a descriptor for the buffer*/
lv_disp_buf_init(&disp_buf, buf, NULL, disp_buf_size);
/*Initialize and register a display driver*/
lv_disp_drv_init(&disp_drv);
disp_drv.buffer = &disp_buf;
disp_drv.flush_cb = v4l2dev_flush;
lv_disp_drv_register(&disp_drv);
/*Draw the menu on screen*/
draw_screen();
/*Initialize and register a input driver*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_BUTTON;
indev_drv.read_cb = button_read;
my_indev = lv_indev_drv_register(&indev_drv);
lv_indev_set_button_points(my_indev, positons);
/*Flush screen*/
while (!g_bTerminate) {
lv_task_handler();
usleep(5000);
}
/*Release display buffer*/
free(buf);
/*Linux v4l2 dev release*/
v4l2dev_release();
/*LittlevGL release*/
lv_release();
return NULL;
}
void draw_screen(void)
{
lv_obj_t *scr = NULL;
static lv_style_t button_style_rel;
static lv_style_t button_style_pre;
uint32_t btn_w = lv_scr_get_hor_res() / 2;
uint32_t btn_h = lv_scr_get_ver_res() / 8;
/*Init screen*/
scr = lv_disp_get_scr_act(NULL);
lv_obj_clean(scr);
lv_obj_set_style(scr, &lv_style_transp);
/*Init button styles*/
lv_style_copy(&button_style_rel, &lv_style_btn_rel);
lv_style_copy(&button_style_pre, &lv_style_btn_pr);
button_style_rel.body.opa = LV_OPA_TRANSP;
button_style_rel.body.border.opa = LV_OPA_TRANSP;
button_style_rel.text.color = LV_COLOR_WHITE;
button_style_pre.body.opa = LV_OPA_TRANSP;
button_style_pre.body.border.opa = LV_OPA_TRANSP;
button_style_pre.text.color = LV_COLOR_YELLOW;
// button_style_pre.text.font = &lv_font_roboto_16;
for (int i = 0; i < 4; i++) {
lv_obj_t *btn;
char name[32];
lv_obj_t *label;
uint32_t offset = btn_h * 2 + i * btn_h;
lv_area_t coords;
/*Init buttons*/
btn = lv_btn_create(scr, NULL);
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &button_style_rel);
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &button_style_pre);
lv_obj_set_size(btn, btn_w, btn_h);
lv_obj_set_event_cb(btn, button_event);
lv_obj_align(btn, NULL, LV_ALIGN_IN_TOP_MID, 0, offset);
lv_obj_get_coords(btn, &coords);
positons[i].x = (coords.x1 + coords.x2) >> 1;
positons[i].y = (coords.y1 + coords.y2) >> 1;
/*Init labels*/
strncpy(name, btn_txt[page_index][i], 32);
label = lv_label_create(btn, NULL);
lv_label_set_text(label, name);
}
}
bool button_read(lv_indev_drv_t *drv __attribute__((unused)), lv_indev_data_t *data)
{
static uint32_t last_btn = 0; /*Store the last indicated button*/
int curr_btn = get_button_index();
if (curr_btn >= 0) { /*Is there a button indicated? (-1 means no button was indicated)*/
last_btn = curr_btn;
data->state = LV_INDEV_STATE_PR;
} else {
data->state = LV_INDEV_STATE_REL;
}
data->btn_id = last_btn;
return false;
}
/* * This fuction reads external hardware button ID (0, 1, 2, ...)
* * msg_callback is used to simulate external buttons*/
int get_button_index(void)
{
return btn_index;
}
/* * This fuction reads external hardware button status (pressed/unpressed).
* * msg_callback is used to simulate external buttons*/
bool get_button_status(void)
{
return btn_status;
}
/* * This fuction resets external hardware button to unpressed. */
void reset_button_status(void)
{
btn_status = false;
}
void button_event(lv_obj_t *obj __attribute__((unused)), lv_event_t event)
{
if (get_button_status() && event == LV_EVENT_PRESSING){
int ret = 0;
int curr_idx = get_button_index();
int swap_idx = (page_index == 0) ? 0 : 3;
/*Do something*/
if (curr_idx == swap_idx) {
page_index = (page_index == 0) ? 1 : 0;
draw_screen();
ret |= set_text_overlay(HIDE);
// release_text_overlay();
} else {
strncpy(text_string, ovl_txt[page_index][curr_idx], 32);
ret |= set_text_overlay(SHOW);
}
print_msg("Button %d is selected and pressed.\n", curr_idx);
reset_button_status();
}
}
void msg_callback(MsgContext *msg_context, void *user_data __attribute__((unused)))
{
print_msg("msg_context->pszHost=%s, msg_context->pszCmd=%s \n",
msg_context->pszHost, msg_context->pszCmd);
if (!strcasecmp(msg_context->pszHost, MODULE_NAME)) {
if (!strcasecmp(msg_context->pszCmd, MSG_LVGL_BTN)) {
btn_index = *(int *) msg_context->pbyData;
btn_status = false;
} else if (!strcasecmp(msg_context->pszCmd, MSG_LVGL_ENT)) {
btn_status = true;
} else if (!strcasecmp(msg_context->pszCmd, MSG_LVGL_RST)) {
btn_index = -1;
}
}
if (msg_context->bHasResponse) {
msg_context->dwDataSize = 0;
}
}
int set_text_overlay(TEXT_MODE eMode)
{
VMF_OVERLAY_TEXT_CONFIG_T tTxtConfig;
VMF_OVERLAY_CONFIG_T tOvlConfig;
memset(&tTxtConfig, 0, sizeof tTxtConfig);
memset(&tOvlConfig, 0, sizeof tOvlConfig);
tTxtConfig.dwPosX = 0;
tTxtConfig.dwPosY = 0;
tTxtConfig.dwAlign = VMF_TEXT_ALIGN_TOP | VMF_TEXT_ALIGN_RIGHT;
tTxtConfig.pszText = text_string;
//tOvlConfig->eMode = VMF_OVERLAY_MONO;
tOvlConfig.eMode = VMF_OVERLAY_MONO;
tOvlConfig.pszDatetimeFormat = NULL;
tOvlConfig.dwDatetimePosX = 0;
tOvlConfig.dwDatetimePosY = 0;
tOvlConfig.dwDateTimeAlign = VMF_TEXT_ALIGN_TOP | VMF_TEXT_ALIGN_LEFT;
tOvlConfig.dwTextCount = eMode;
tOvlConfig.ptTextArray = &tTxtConfig;
return VMF_VSRC_ConfigOverlay(g_ptVsrcHandle, 0, g_dwSubIdx, &tOvlConfig);
}
int init_text_overlay(void)
{
FONT_INFO_T tInfo;
memset(&tInfo, 0, sizeof tInfo);
memset(text_string, 0, sizeof text_string);
tInfo.pszFontPath = "DejaVuSans-Bold.ttf";
tInfo.nFontSize = g_dwFontSize;
tInfo.fOutlineWidth = 2; // set 0, if outline is not needed
tInfo.tColorInfo.dwFontColor = 255 | (128<<8) | (128<<16);// Byte 0:y, 1:u, 2:v
tInfo.tColorInfo.dwBorderColor = 0 | (128<<8) | (128<<16); // Byte 0:y, 1:u, 2:v
tInfo.tColorInfo.dwBackColor = 0; // Byte 0:y, 1:u, 2:v, 3:alpha, set 0 as transparent background
return VMF_VSRC_SetFont(g_ptVsrcHandle, 0, g_dwSubIdx, &tInfo);
}
int main(int argc, char **argv)
{
int ch;
pthread_t thrd_v;
atexit(exit_handler);
signal(SIGTERM, sig_handler);
signal(SIGINT, sig_handler);
while ((ch = getopt(argc, argv, "c:h")) != -1) {
switch(ch) {
case 'c':
g_szConfig = strdup(optarg);
break;
case 'h':
default:
print_msg("Usage:%s [-c<config_file)][-h]\n", argv[0]);
return -1;
}
}
load_config();
if (init_video_source()) {
print_msg("[%s] init_video_source failed!\n", __func__);
goto RELEASE;
}
if (0 && init_fec_mode()) {
print_msg("[%s] init_fec_mode failed!\n", __func__);
goto RELEASE;
}
if (init_bind()) {
print_msg("[%s] init_bind failed!\n", __func__);
goto RELEASE;
}
pthread_create(&thrd_v, NULL, video_loop, NULL);
pthread_setname_np(thrd_v, "video_loop");
MsgBroker_RegisterMsg(LVGL_CMD_FIFO);
MsgBroker_Run(LVGL_CMD_FIFO, msg_callback, NULL, &g_bTerminate);
MsgBroker_UnRegisterMsg();
pthread_join(thrd_v, NULL);
RELEASE:
release_bind();
release_video_source();
return 0;
}