功能: FB+视频共存 - bk背景+tag叠加+视频挖洞
This commit is contained in:
parent
b4d8f49143
commit
65e29b91e4
@ -71,8 +71,15 @@ void fbdev_exit(void)
|
||||
|
||||
void *fbdev_req_mem(int size)
|
||||
{
|
||||
(void)size;
|
||||
return lvgl_surface.data;
|
||||
void *buf = NULL;
|
||||
int ret = posix_memalign(&buf, 64, size);
|
||||
if (ret != 0 || buf == NULL)
|
||||
{
|
||||
printf("fbdev_req_mem malloc failed: ret=%d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
memset(buf, 0, size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int fbdev_get_actual_height(void)
|
||||
@ -133,6 +140,8 @@ static void fbdev_draw_hole()
|
||||
|
||||
void fbdev_flush(lv_display_t *drv, const lv_area_t *area, uint8_t *color_p)
|
||||
{
|
||||
static int flush_cnt = 0;
|
||||
if (flush_cnt < 3) { printf("[fbdev_flush] #%d area=[%d,%d,%d,%d]\n", flush_cnt, area->x1, area->y1, area->x2, area->y2); fflush(stdout); flush_cnt++; }
|
||||
if (fbp == NULL || finfo.line_length == 0)
|
||||
{
|
||||
lv_display_flush_ready(drv);
|
||||
@ -148,38 +157,8 @@ void fbdev_flush(lv_display_t *drv, const lv_area_t *area, uint8_t *color_p)
|
||||
return;
|
||||
}
|
||||
|
||||
/* lvgl_surface == fb_surface (same mmap buffer), LVGL writes directly to it.
|
||||
* qua_gl_transform with same src/dst triggers hardware compress pipeline. */
|
||||
int32_t act_x1 = LV_MAX(area->x1, 0);
|
||||
int32_t act_y1 = LV_MAX(area->y1, 0);
|
||||
int32_t act_x2 = LV_MIN(area->x2, (int32_t)lvgl_surface.width - 1);
|
||||
int32_t act_y2 = LV_MIN(area->y2, (int32_t)lvgl_surface.height - 1);
|
||||
|
||||
int32_t w = act_x2 - act_x1 + 1;
|
||||
int32_t h = act_y2 - act_y1 + 1;
|
||||
|
||||
lvgl_surface.crop_x = act_x1;
|
||||
lvgl_surface.crop_y = act_y1;
|
||||
lvgl_surface.crop_w = w;
|
||||
lvgl_surface.crop_h = h;
|
||||
fb_surface.crop_x = act_x1;
|
||||
fb_surface.crop_y = act_y1;
|
||||
fb_surface.crop_w = w;
|
||||
fb_surface.crop_h = h;
|
||||
|
||||
qua_gl_transform_t trans = {};
|
||||
trans.conversion = 1;
|
||||
qua_gl_transform(&trans, &lvgl_surface, &fb_surface);
|
||||
|
||||
lvgl_surface.crop_x = 0;
|
||||
lvgl_surface.crop_y = 0;
|
||||
lvgl_surface.crop_w = lvgl_surface.width;
|
||||
lvgl_surface.crop_h = lvgl_surface.height;
|
||||
fb_surface.crop_x = 0;
|
||||
fb_surface.crop_y = 0;
|
||||
fb_surface.crop_w = fb_surface.width;
|
||||
fb_surface.crop_h = fb_surface.height;
|
||||
|
||||
/* Skip memcpy: FB buffer already has pre-loaded image (tag.rgba).
|
||||
* Only do hole drawing + render on last flush. */
|
||||
if (lv_display_flush_is_last(drv))
|
||||
{
|
||||
fbdev_draw_hole();
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
#include "bootanimation/qua_bootanimation.h"
|
||||
|
||||
#define DISPLAY_ID "id:display0"
|
||||
#define BK_IMAGE_PATH "/usrdata/pic/bk.rgba"
|
||||
#define TAG_IMAGE_PATH "/usrdata/pic/tag.rgba"
|
||||
#define TAG_Y_OFFSET 640
|
||||
|
||||
static QUA_CHAR *pShowScreen;
|
||||
static QUA_U32 u32PhyAddrScreen;
|
||||
@ -160,6 +163,56 @@ static QUA_S32 init_fyfb()
|
||||
goto map_failed;
|
||||
}
|
||||
memset(pShowScreen, 0x00, finfo.smem_len);
|
||||
/* Step 1: load bk.rgba as full-screen background */
|
||||
{
|
||||
int fb_stride = finfo.line_length;
|
||||
int row_bytes = vinfo.xres * 4;
|
||||
FILE *fp = fopen(BK_IMAGE_PATH, "rb");
|
||||
if (fp) {
|
||||
for (unsigned int y = 0; y < vinfo.yres; y++) {
|
||||
if (fread(pShowScreen + y * fb_stride, 1, row_bytes, fp) <= 0) break;
|
||||
}
|
||||
fclose(fp);
|
||||
printf("[init_fyfb] loaded %s full screen\n", BK_IMAGE_PATH);
|
||||
} else {
|
||||
printf("[init_fyfb] %s not found\n", BK_IMAGE_PATH);
|
||||
}
|
||||
|
||||
/* Step 2: overlay tag.rgba at bottom (y=TAG_Y_OFFSET ~ yres) with alpha blend */
|
||||
fp = fopen(TAG_IMAGE_PATH, "rb");
|
||||
if (fp) {
|
||||
unsigned int tag_h = vinfo.yres - TAG_Y_OFFSET;
|
||||
uint8_t *row_buf = (uint8_t *)malloc(row_bytes);
|
||||
if (row_buf) {
|
||||
/* skip top TAG_Y_OFFSET rows of tag image */
|
||||
for (unsigned int y = 0; y < (unsigned int)TAG_Y_OFFSET; y++)
|
||||
if (fread(row_buf, 1, row_bytes, fp) <= 0) break;
|
||||
/* blend bottom rows */
|
||||
for (unsigned int y = 0; y < tag_h; y++) {
|
||||
if (fread(row_buf, 1, row_bytes, fp) <= 0) break;
|
||||
uint8_t *dst = (uint8_t *)(pShowScreen + (TAG_Y_OFFSET + y) * fb_stride);
|
||||
uint8_t *src = row_buf;
|
||||
for (unsigned int x = 0; x < vinfo.xres; x++) {
|
||||
uint8_t sb = src[0], sg = src[1], sr = src[2], sa = src[3];
|
||||
if (sa == 255) {
|
||||
dst[0] = sb; dst[1] = sg; dst[2] = sr; dst[3] = 255;
|
||||
} else if (sa > 0) {
|
||||
dst[0] = (sb * sa + dst[0] * (255 - sa)) / 255;
|
||||
dst[1] = (sg * sa + dst[1] * (255 - sa)) / 255;
|
||||
dst[2] = (sr * sa + dst[2] * (255 - sa)) / 255;
|
||||
dst[3] = 255;
|
||||
}
|
||||
src += 4; dst += 4;
|
||||
}
|
||||
}
|
||||
free(row_buf);
|
||||
}
|
||||
fclose(fp);
|
||||
printf("[init_fyfb] overlaid %s at y=%d\n", TAG_IMAGE_PATH, TAG_Y_OFFSET);
|
||||
} else {
|
||||
printf("[init_fyfb] %s not found\n", TAG_IMAGE_PATH);
|
||||
}
|
||||
}
|
||||
fb_device->compress(fb_device, QUA_TRUE);
|
||||
return QUA_SUCCESS;
|
||||
map_failed:
|
||||
@ -230,6 +283,8 @@ int fbdev_pan_disp(void)
|
||||
{
|
||||
qua_mm_fb_device_t *fb_dev = (qua_mm_fb_device_t *)g_fb_device;
|
||||
static int is_first_frame = 1;
|
||||
static int pan_cnt = 0;
|
||||
if (pan_cnt < 3) { printf("[fbdev_pan_disp] called #%d first=%d fb_dev=%p\n", pan_cnt, is_first_frame, fb_dev); fflush(stdout); pan_cnt++; }
|
||||
|
||||
if (fb_dev == NULL)
|
||||
return -1;
|
||||
@ -280,8 +335,9 @@ int fbdev_pan_disp(void)
|
||||
|
||||
if (fb_dev->render == NULL)
|
||||
return -1;
|
||||
|
||||
return fb_dev->render(fb_dev, &vinfo);
|
||||
|
||||
QUA_S32 render_ret = fb_dev->render(fb_dev, &vinfo);
|
||||
return render_ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -160,10 +160,15 @@ void log_print(LogLevel level, const char *file, int line, const char *format, .
|
||||
{
|
||||
pthread_mutex_lock(&log_mutex);
|
||||
|
||||
// 初始化检查
|
||||
// 初始化检查 (inline to avoid deadlock with log_init)
|
||||
if (g_output == NULL)
|
||||
{
|
||||
log_init();
|
||||
ensure_log_dir_exists();
|
||||
snprintf(g_log_file_path, sizeof(g_log_file_path), "%s/%s", LOG_DIR, LOG_FILE_NAME);
|
||||
g_output = fopen(g_log_file_path, "a");
|
||||
if (!g_output)
|
||||
g_output = stdout;
|
||||
init_udp_socket();
|
||||
}
|
||||
|
||||
// 检查日志级别是否足够
|
||||
|
||||
22
src/main.c
22
src/main.c
@ -99,22 +99,15 @@ int main(int argc, char **argv)
|
||||
|
||||
disp_handle_t disp = get_front_display();
|
||||
|
||||
lv_obj_t *cont_col = lv_obj_create(disp.root_obj);
|
||||
lv_obj_set_size(cont_col, LV_PCT(90), 640);
|
||||
lv_obj_set_pos(cont_col, 0, 640);
|
||||
lv_obj_center(cont_col);
|
||||
// 设置方向为垂直排列
|
||||
lv_obj_set_flex_flow(cont_col, LV_FLEX_FLOW_COLUMN);
|
||||
// 对齐方式
|
||||
lv_obj_set_flex_align(cont_col, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_set_style_bg_color(cont_col, lv_color_hex(0xffffff), LV_PART_MAIN);
|
||||
/* make LVGL root transparent so FB image (tag.rgba) shows through */
|
||||
lv_obj_set_style_bg_opa(disp.root_obj, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
|
||||
|
||||
//创建视频播放器
|
||||
VideoPlayer *video_player=video_player_init(0);
|
||||
e_player_area area={0};
|
||||
area.x = 0;
|
||||
area.y = 640;
|
||||
area.y = 0;
|
||||
area.width = 800;
|
||||
area.height = 640;
|
||||
|
||||
@ -128,12 +121,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
memset(media_path, 0, sizeof(MediaPath));
|
||||
|
||||
safe_strcpy(media_path->path, "/usrdata/downloads/xxx.mp4", MAX_URL_LEN);
|
||||
safe_strcpy(media_path->path, "/usrdata/downloads/lemon.MOV", MAX_URL_LEN);
|
||||
safe_strcpy(media_path->item_id, "", MAX_ID_LEN);
|
||||
safe_strcpy(media_path->deviceId, "700000000010", MAX_DEVICE_ID);
|
||||
|
||||
safe_strcpy(media_path->downloadUrl, "", MAX_URL_LEN);
|
||||
safe_strcpy(media_path->file_name, "/usrdata/downloads/xxx.mp4", MAX_NAME_LEN);
|
||||
safe_strcpy(media_path->file_name, "/usrdata/downloads/lemon.MOV", MAX_NAME_LEN);
|
||||
|
||||
media_path->type = 1; // 视频
|
||||
|
||||
@ -141,13 +134,10 @@ int main(int argc, char **argv)
|
||||
|
||||
video_player_play(video_player);
|
||||
|
||||
|
||||
printf("启动主循环\n");
|
||||
printf("[MAIN] 启动主循环\n"); fflush(stdout);
|
||||
// /* 主循环 */
|
||||
while (running)
|
||||
{
|
||||
// LOGI("启动主循环---------》》》");
|
||||
// pthread_mutex_lock(&lvgl_mutex);
|
||||
uint32_t wait_ms = lv_timer_handler();
|
||||
// pthread_mutex_unlock(&lvgl_mutex);
|
||||
// LOGI("启动主循环---------<<<");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user