bug fix
This commit is contained in:
parent
c4a6e42446
commit
58ff822a9d
46
README.md
46
README.md
@ -1,46 +0,0 @@
|
||||
# eplayer demo - FB+视频共存问题
|
||||
|
||||
## 问题与根因
|
||||
|
||||
FB 和视频无法共存:`compress(TRUE)` 下 render 阻塞,`compress(FALSE)` 下视频返回 VO_BUSY。
|
||||
|
||||
根因: `rootfs_overlay/qua/ko/loadko.sh` 中 `insmod fhfb.ko fbc=0` 禁用了 FB 压缩,且 `fhfb.ko` 是旧版不支持 fbc。
|
||||
|
||||
## 修改点
|
||||
|
||||
### 内核层
|
||||
|
||||
1. 替换 fhfb.ko — 用 SDK 新版替换 `rootfs_overlay/qua/ko/fhfb.ko`(旧版 md5:`96d321` → 新版 md5:`58050d`)
|
||||
2. loadko.sh 启用 fbc — `fbc=0` → `fbc=3000`,`vram0_size=4000`,`fhfb0_fbc=1`
|
||||
|
||||
### 应用层
|
||||
|
||||
3. e_logger.c — 修复 `log_print` 死锁(持有 mutex 后调用 `log_init` 再次加锁)
|
||||
4. fbdev_10xd.c — `compress(TRUE)` 前加载 `bk.rgba` 全屏铺底 + `tag.rgba` 底部 alpha 叠加
|
||||
5. fbdev.c — 跳过 LVGL memcpy,仅做挖洞 + render
|
||||
6. main.c — 视频区域改为顶部,LVGL root 设为透明
|
||||
|
||||
## 关键时序
|
||||
|
||||
mmap → 写入图片 → compress(TRUE) → VO enable → show(TRUE) → render → 挖洞 → 播视频
|
||||
|
||||
> 图片必须在 `compress(TRUE)` 之前写入 FB buffer。
|
||||
|
||||
## 素材
|
||||
|
||||
素材需预转换(PNG/JPG → raw BGRA):
|
||||
|
||||
python3 -c "
|
||||
from PIL import Image
|
||||
import struct
|
||||
img = Image.open('/path/to/bk1.jpg').convert('RGBA')
|
||||
print(f'Size: {img.size}')
|
||||
with open('/path/to/bk1.rgba', 'wb') as f:
|
||||
for y in range(img.height):
|
||||
for x in range(img.width):
|
||||
r, g, b, a = img.getpixel((x, y))
|
||||
f.write(struct.pack('BBBB', b, g, r, a))
|
||||
print('Done')
|
||||
"
|
||||
|
||||
> 设备上 crc32 与 zlib 冲突,无法用 libpng,需预转换 raw 格式。
|
||||
BIN
bin/e_player
BIN
bin/e_player
Binary file not shown.
@ -91,7 +91,7 @@
|
||||
#endif
|
||||
#endif /*LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN*/
|
||||
|
||||
#define LV_DEF_REFR_PERIOD 33 /**< [ms] 33ms (30fps),优化后支持 tag.gif + 02.gif + 03.gif + 视频长时间稳定运行 */
|
||||
#define LV_DEF_REFR_PERIOD 150 /**< [ms] 33ms (30fps),优化后支持 tag.gif + 02.gif + 03.gif + 视频长时间稳定运行 */
|
||||
|
||||
#define LV_DPI_DEF 130 /**< [px/inch] */
|
||||
|
||||
|
||||
Binary file not shown.
@ -1 +1 @@
|
||||
d7d8bda7fec96e0cb0b071e56df40841 /home/hyx/work/0212/demo/release/e_player-single-00-70-1.0.84.tar
|
||||
1191545f9e16f1a3cb238f5c529dc0a7 /home/hyx/work/MC3302_push/0212/demo/release/e_player-single-00-70-1.0.84.tar
|
||||
|
||||
@ -504,7 +504,11 @@ static int play_video(VideoPlayer *video_player, const MediaPath *media_path)
|
||||
{
|
||||
qua_mm_player_set_parameter(player, KEY_PARAMETER_VO_DISPLAY_ID, (QUA_VOID_PTR)video_player->display);
|
||||
qua_mm_player_set_parameter(player, KEY_PARAMETER_VO_ROTATE, (QUA_VOID_PTR)&g_screen_rotation);
|
||||
xos_player_set_volume(player, 0);
|
||||
// 设置音频轨道类型为音乐
|
||||
qua_audio_track_type_t track_type = QUA_AUDIO_TRACK_TYPE_MUSIC;
|
||||
qua_mm_player_set_parameter(player, KEY_PARAMETER_AO_TRACK_TYPE, (QUA_VOID_PTR)&track_type);
|
||||
|
||||
xos_player_set_volume(player, 80); // 设置音量为80 (范围通常是0-100)
|
||||
qua_mm_player_set_loop(player, QUA_FALSE);
|
||||
video_player->player = player;
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ static disp_handle_t front_disp;
|
||||
static disp_handle_t back_disp;
|
||||
|
||||
// 屏幕旋转
|
||||
int g_screen_rotation = 2;
|
||||
int g_screen_rotation = 0;
|
||||
|
||||
qua_mm_system_ops_t *g_sys_ops = NULL;
|
||||
qua_mm_tde_device_t *g_tde_device_for_hole = NULL;
|
||||
|
||||
118
src/main.c
118
src/main.c
@ -7,6 +7,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
@ -101,56 +102,72 @@ int main(int argc, char **argv)
|
||||
|
||||
disp_handle_t disp = get_front_display();
|
||||
|
||||
/* 创建 tag.gif 全屏背景动画 */
|
||||
lv_obj_t *tag_gif = lv_gif_create(disp.root_obj);
|
||||
lv_gif_set_src(tag_gif, "A:usrdata/pic/tag.gif");
|
||||
lv_obj_set_pos(tag_gif, 0, 0); /* 全屏 */
|
||||
lv_obj_set_size(tag_gif, 800, 1280);
|
||||
lv_obj_clear_flag(tag_gif, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_gif_restart(tag_gif);
|
||||
|
||||
/* 创建 02.gif 小动画 - 根据旋转调整位置 */
|
||||
lv_obj_t *small_gif = lv_gif_create(disp.root_obj);
|
||||
lv_gif_set_src(small_gif, "A:usrdata/pic/02.gif");
|
||||
|
||||
// 根据屏幕旋转调整小动画位置
|
||||
extern int g_screen_rotation;
|
||||
int small_x, small_y;
|
||||
|
||||
if (g_screen_rotation == 2) {
|
||||
// 180度旋转:显示系统已旋转,逻辑坐标需要反向
|
||||
// 要显示在左上角,逻辑坐标应该是右下角
|
||||
small_x = 800 - 280; // 520,为280宽度留出空间
|
||||
small_y = 1280 - 280; // 1000,为280高度留出空间
|
||||
printf("[DEBUG] Rotation 2: position (%d, %d) will display at top-left\n", small_x, small_y);
|
||||
} else {
|
||||
// 不旋转:右下角位置
|
||||
small_x = 800 - 280 - 20; // 500,右下角留20像素边距
|
||||
small_y = 1280 - 280 - 20; // 980,右下角留20像素边距
|
||||
printf("[DEBUG] No rotation: position (%d, %d) at bottom-right\n", small_x, small_y);
|
||||
}
|
||||
|
||||
lv_obj_set_pos(small_gif, small_x, small_y);
|
||||
lv_obj_set_size(small_gif, 280, 280); // 增加尺寸到280x280
|
||||
lv_obj_clear_flag(small_gif, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_gif_restart(small_gif);
|
||||
|
||||
printf("[DEBUG] GIF position: (%d, %d), size: 280x280\n", small_x, small_y);
|
||||
/* 创建 bk.jpg 背景图片 */
|
||||
lv_obj_t *bk_img = lv_image_create(disp.root_obj);
|
||||
lv_image_set_src(bk_img, "A:data/pic/bk.jpeg");
|
||||
lv_obj_set_pos(bk_img, 0, 0);
|
||||
lv_obj_set_size(bk_img, 800, 1280);
|
||||
lv_obj_clear_flag(bk_img, LV_OBJ_FLAG_HIDDEN);
|
||||
printf("[INFO] bk.jpg loaded at (0, 0), size: 800x1280\n");
|
||||
|
||||
/* 创建 03.gif 在 02.gif 正上方 */
|
||||
lv_obj_t *third_gif = lv_gif_create(disp.root_obj);
|
||||
lv_gif_set_src(third_gif, "A:usrdata/pic/03.gif");
|
||||
|
||||
// 计算 03.gif 位置:在 02.gif 正上方
|
||||
int third_x = small_x; // X 坐标相同
|
||||
int third_y = small_y - 280 - 20; // Y 坐标在 02.gif 上方,间距20像素
|
||||
|
||||
printf("[DEBUG] 03.gif position: (%d, %d), size: 280x280\n", third_x, third_y);
|
||||
|
||||
lv_obj_set_pos(third_gif, third_x, third_y);
|
||||
lv_obj_set_size(third_gif, 280, 280);
|
||||
lv_obj_clear_flag(third_gif, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_gif_restart(third_gif);
|
||||
/* 创建 tag.png 图片 */
|
||||
lv_obj_t *tag_img = lv_image_create(disp.root_obj);
|
||||
lv_image_set_src(tag_img, "A:data/pic/tag.png");
|
||||
lv_obj_set_pos(tag_img, 0, 0);
|
||||
lv_obj_set_size(tag_img, 800, 1280);
|
||||
lv_obj_clear_flag(tag_img, LV_OBJ_FLAG_HIDDEN);
|
||||
printf("[INFO] tag.png loaded at (0, 0), size: 800x1280\n");
|
||||
|
||||
/* 创建底部细条状态栏 */
|
||||
lv_obj_t *status_bar = lv_obj_create(disp.root_obj);
|
||||
lv_obj_set_pos(status_bar, 320, 1240);
|
||||
lv_obj_set_size(status_bar, 160, 24);
|
||||
lv_obj_set_style_bg_color(status_bar, lv_color_make(0, 0, 0), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_opa(status_bar, 100, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(status_bar, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(status_bar, 12, LV_PART_MAIN);
|
||||
lv_obj_clear_flag(status_bar, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
/* 在线状态绿点 */
|
||||
lv_obj_t *online_dot = lv_obj_create(status_bar);
|
||||
lv_obj_set_pos(online_dot, 10, 4);
|
||||
lv_obj_set_size(online_dot, 16, 16);
|
||||
lv_obj_set_style_bg_color(online_dot, lv_color_make(0, 255, 0), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_opa(online_dot, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(online_dot, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(online_dot, 8, LV_PART_MAIN);
|
||||
lv_obj_clear_flag(online_dot, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
/* 时间显示标签 */
|
||||
lv_obj_t *time_label = lv_label_create(status_bar);
|
||||
lv_obj_set_pos(time_label, 32, 2);
|
||||
lv_obj_set_size(time_label, 80, 20);
|
||||
lv_obj_set_style_text_color(time_label, lv_color_make(255, 255, 255), LV_PART_MAIN);
|
||||
lv_obj_set_style_text_font(time_label, &lv_font_montserrat_22, LV_PART_MAIN);
|
||||
lv_label_set_text(time_label, "00:00");
|
||||
lv_obj_clear_flag(time_label, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
/* 更新时间线程 */
|
||||
pthread_t time_tid;
|
||||
static volatile bool time_running = true;
|
||||
void *time_update_thread(void *arg) {
|
||||
(void)arg;
|
||||
while (time_running) {
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm_info = localtime(&now);
|
||||
char time_str[16];
|
||||
strftime(time_str, sizeof(time_str), "%H:%M", tm_info);
|
||||
lv_label_set_text(time_label, time_str);
|
||||
sleep(60);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
pthread_create(&time_tid, NULL, time_update_thread, NULL);
|
||||
pthread_detach(time_tid);
|
||||
|
||||
printf("[INFO] status bar created at bottom\n");
|
||||
|
||||
//创建视频播放器
|
||||
VideoPlayer *video_player=video_player_init(0);
|
||||
@ -162,8 +179,7 @@ int main(int argc, char **argv)
|
||||
|
||||
// 根据屏幕旋转调整视频区域
|
||||
if (g_screen_rotation == 2) {
|
||||
// 180度旋转:视频应该显示在上半部分
|
||||
area.y = 640; // 设置到下半部分,旋转后会显示在上半部分
|
||||
area.y = 640;
|
||||
}
|
||||
|
||||
video_player_set_size(video_player,area);
|
||||
@ -176,12 +192,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
memset(media_path, 0, sizeof(MediaPath));
|
||||
|
||||
safe_strcpy(media_path->path, "/usrdata/downloads/lemon.MOV", MAX_URL_LEN);
|
||||
safe_strcpy(media_path->path, "/data/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/lemon.MOV", MAX_NAME_LEN);
|
||||
safe_strcpy(media_path->file_name, "/data/downloads/lemon.MOV", MAX_NAME_LEN);
|
||||
|
||||
media_path->type = 1; // 视频
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user