环境平台
基于lvgl实现的播放视频的同时叠加图标控件。
硬件平台:anyka37E
lvgl版本:v7.11
单fb节点 , 不具备多硬件图层叠加功能,仅有/dev/fb0
基本思路
采用img obj作为视频的载体,构建图标与视频的层级关系
//新建一个video frame img 实例 类型为LV_IMG_CF_TRUE_COLOR_ALPHA,data地址为frame data缓存地址
lv_img_dsc_t img_lv_dec_video = {
.header.always_zero = 0,
.header.w = 1024,
.header.h = 600,
.data_size = 614400 * LV_IMG_PX_SIZE_ALPHA_BYTE,
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
.data = (const uint8_t * ) video_frame_addr,
};
//新建一个img obj,以确定其和其他空间的层级位置关系,将video img结构图赋值给img obj
lv_obj_t * video_img = lv_img_create(lv_src_act(), NULL);
lv_img_set_src(video_img , &img_lv_dec_video );
lv_obj_align(video_img , NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
//刷新dec frame 地址,传入新的一帧地址并刷新
img_lv_dec_video.data = (const uint8_t * )new_video_frame_addr;
lv_img_set_src(video_img , &img_lv_dec_video );
//引发刷新操作
lv_obj_invalidate(video_img );
详细过程
在lvgl 底层拿到video frame 后要对其特殊对待,这样的话就需要对其进行识别我的做法是在 lv_img_dsc_t 的 lv_img_header_t结构体中新加入一个成员uint32_t imf:6 这个成员你可以自己enum一些特定类型出来填充。通过层层调用最终在map_normal 中对该img imf类型进行判定,如果是video frame就采用driver 里提供的draw_video_cb来画图。采用了lvgl真实双buffer的机制。
总体的流程:
后面我会上传效果图。
绘图的代码流程:
_lv_disp_refr_task //刷新起点
lv_refr_areas
lv_refr_area
lv_refr_area_part
lv_refr_obj_and_children //遍历绘图
lv_refr_obj
if(obj->design_cb) obj->design_cb(obj, &obj_ext_mask, LV_DESIGN_DRAW_MAIN);
lv_img_design
lv_draw_img
lv_img_draw_core
_lv_img_cache_open //这里会判定img的cf类型
lv_draw_map
_lv_blend_map
map_normal
driver->draw_video_cb
draw_video_cb得自己实现,这个可以是软件绘制也可以是加速硬件绘制。函数的调用流程如上,发起者是lv_obj_invalidate(video_img ); 所以判定video类型的过程应该在这个流程上有所体现,可以自己设计采用的识别方式,我采用的是参数识别。如果不加以区分那将会影响lvgl系统的img绘制。或者你也可以做成插件的形式进行兼容扩展。
效果图等将视频改为gif后上传。