环境平台

基于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绘制。或者你也可以做成插件的形式进行兼容扩展。
当然如果你的平台是支持多图层(fb0,fb1,fb2,fb3… 或者支持DRM)的话就不需要使用该方法了,只需要在conf.h中将
#define LV_COLOR_DEPTH 32
#define LV_COLOR_SCREEN_TRANSP 1
背景色设置为透明就可以将底层的视频层透出来了。当然像素格式是ARGB8888
在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐