LVGL视频播放界面实现方法

1.主题

LVGL视频播放界面实现方法

2.问题背景

使用LVGL开发且需要在UI下显示视频或者显示摄像头数据,但是不知道如何实现,要么是只显示UI,要么就只显示视频。

3.具体表现

可以看下视频播放的时候有哪些元素。

在这里插入图片描述

有播放按钮,进度条,设置等可交互的控件,这些都位于UI层。

UI的下方就是视频解码后的一帧数据,视频数据位于视频层。

4.问题分析

一般UI层位于视频层的上方,如果UI层没有设置透明度,那么会有一个背景色,覆盖了视频层,导致只能看到背景色和一些控制按钮。

5.根本原因

首先需要知道有图层的概念,下面的命令可以看到图层的信息:

root@TinaLinux:/# cat /sys/class/disp/disp/attr/sys
screen 0:
de_rate 300000000 hz, ref_fps:59
mgr0: 1280x800 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[1] force_sync[1] unblank direct_show[false] iommu[1]
dmabuf: cache[4] cache max[4] umap skip[0] umap skip max[18]
        lcd output      backlight( 50)  fps:60.0        1280x 800
        err:0   skip:67 irq:2300        vsync:0 vsync_skip:0
   BUF    enable ch[0] lyr[0] z[0] prem[N] a[pixel   0] fmt[ 77] fb[1280, 736; 640, 368; 640, 368] crop[   0,   0,1280, 720] frame[   0,   0,1280, 800] addr[fb200000,fb2e6000,fb359000] flags[0x       0] trd[0,0]
depth[ 0]    BUF    enable ch[1] lyr[0] z[16] prem[N] a[pixel 255] fmt[  0] fb[1280, 800;1280, 800;1280, 800] crop[   0,   0,1280, 800] frame[   0,   0,1280, 800] addr[ff800000,       0,       0] flags[0x
  0] trd[0,0]

在内核初始化过程中,显示驱动注册/dev/fb0,会申请UI层,可以看到ch[1] lyr[0],一般UI就一个地址addr[ff800000, 0, 0],并且也是最顶层的z[16],混合模式a[pixel 255]表示由应用控制UI层的透明度。

视频播放(使用TPlayer接口)的时候会通过中间件申请视频图层,可以看到ch[0] lyr[0],并且yuv三个地址一直在变化addr[fb200000,fb2e6000,fb359000],通常视频会放到最底层z[0]。

当应用没有透明时,因为UI层的zorder比视频层大,因此只能看到UI,看不到视频,所以应用需要“挖空”。

6.解决办法

下面代码里的屏幕,一般是指/dev/fb0,LVGL版本是8.3.2。

使用下面的代码前需要在lv_conf.h中设置参数:

#define LV_COLOR_SCREEN_TRANSP 1
/* 初始化屏幕风格 */
static lv_style_t style_scr_act;
if (style_scr_act.prop_cnt == 0) {
    lv_style_init(&style_scr_act);
    /* 默认不是透明的,后面按需要切换即可 */
    lv_style_set_bg_opa(&style_scr_act, LV_OPA_COVER);
    /* 一定要应用风格,不然也是没有效果的 */
    lv_obj_add_style(lv_scr_act(), &style_scr_act, 0);
}

/* 这里根据按钮状态,切换不同风格,一种是UI能够透明看到底下的视频,一种是UI覆盖视频,视频就看不到了 */
if (lv_obj_has_state(btn, LV_STATE_CHECKED)) {
    /* 这里切换为UI透明 */
    lv_label_set_text(label, "Stop");
    /* 这里设置屏幕是透明的 */
    lv_disp_get_default()->driver->screen_transp = 1;
    /* 这里设置屏幕背景是透明的 */
    lv_disp_set_bg_opa(lv_disp_get_default(), LV_OPA_TRANSP);
    /* 这里清空屏幕,不清空的话,可能不会生效 */
    lv_memset_00(lv_disp_get_default()->driver->draw_buf->buf_act,
            lv_disp_get_default()->driver->draw_buf->size
                    * sizeof(lv_color32_t));
    /* 这里屏幕风格切换为透明的 */
    lv_style_set_bg_opa(&style_scr_act, LV_OPA_TRANSP);
    /* 通知风格变化,需要更新 */
    lv_obj_report_style_change(&style_scr_act);
} else {
    /* 这里切换为UI不透明,也就是覆盖视频 */
    lv_label_set_text(label, "Play");
    /* 这里设置屏幕是不透明的 */
    lv_disp_get_default()->driver->screen_transp = 0;
    /* 这里设置屏幕背景是不透明的 */
    lv_disp_set_bg_opa(lv_disp_get_default(), LV_OPA_COVER);
    /* 这里屏幕风格切换为不透明的 */
    lv_style_set_bg_opa(&style_scr_act, LV_OPA_COVER);
    /* 通知风格变化,需要更新 */
    lv_obj_report_style_change(&style_scr_act);
}

原贴链接:https://bbs.aw-ol.com/topic/2820/
全志及开发者最新动态可以关注全志在线微信公众号

LVGL 是一个开源的嵌入式图形库,可以在嵌入式系统中实现各种 UI 界面。如果要在 LVGL播放摄像头视频,需要使用图像解码器和显示驱动器。 以下是一个简单的示例代码,演示了如何在 LVGL播放摄像头视频: ```c #include "lvgl/lvgl.h" #include "lv_examples/lv_apps/demo/demo.h" /* 定义 LVGL 的显示设备和输入设备 */ lv_disp_drv_t disp_drv; lv_indev_drv_t indev_drv; /* 定义图像解码器和显示驱动器 */ static lv_disp_draw_buf_t draw_buf; static lv_disp_draw_buf_t disp_buf; static lv_disp_drv_t disp_drv; static lv_obj_t * screen; /* 摄像头的视频帧数据 */ uint8_t *frame_buf; uint32_t frame_size; /* 初始化 LVGL */ void lvgl_init(void) { lv_init(); /* 创建屏幕 */ lv_disp_draw_buf_init(&draw_buf, LV_HOR_RES_MAX, 10); lv_disp_drv_init(&disp_drv); disp_drv.draw_buf = &draw_buf; disp_drv.flush_cb = demo_flush; lv_disp_t *disp; disp = lv_disp_drv_register(&disp_drv); screen = lv_obj_create(NULL, NULL); lv_scr_load(screen); /* 创建图像解码器 */ lv_img_decoder_init(); /* 创建显示驱动器 */ lv_disp_draw_buf_init(&disp_buf, LV_HOR_RES_MAX, LV_VER_RES_MAX); static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.draw_buf = &disp_buf; disp_drv.flush_cb = demo_flush; lv_disp_drv_register(&disp_drv); } /* 播放摄像头视频 */ void play_camera_video(void) { /* 初始化摄像头 */ /* 获取摄像头视频帧数据 */ while (true) { /* 解码摄像头视频帧 */ lv_img_dsc_t img_dsc; img_dsc.header.always_zero = 0; img_dsc.header.w = CAMERA_WIDTH; img_dsc.header.h = CAMERA_HEIGHT; img_dsc.data_size = frame_size; img_dsc.data = frame_buf; lv_img_set_src(lv_img_create(screen, NULL), &img_dsc); lv_task_handler(); } } int main(void) { lvgl_init(); play_camera_video(); return 0; } ``` 请注意,这只是一个简单的示例代码,并且需要根据实际情况进行修改和扩展。在实际应用中,还需要考虑图像解码器和显示驱动器的性能和资源占用情况,以及摄像头视频帧数据的采集和处理方式等问题。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值