PUPANVR-UI主界面视频预览开发

PUPANVR-UI主界面视频预览开发

UI的选择

本来原来考虑到用的MINIGUI的,但看到那种古老的控件风格,想做现代点可能贴图就搞得不胜其烦了,并且其开源的方式也不太友好!

再看了下各种UI库,看了下LVGL的库的例子,虽然一直没有怎么了解过,但瞬间就爱了!

好吧就用LVGL了!

移植

谈不上什么移值了,framebuffer已经足够简单了,在海思平台上,可以具体见上一往篇Hi3536C上使用的介绍.

单进程还是多线程

我在想是否需要把UI做成一个独立的进程,有点纠集,如果写成一个独立的进程吧,在UI上同后台录相管理进程交互又会比较多,想到需要服务端与客户端模式,调用及通知、协议格式解码都需要大量的代码量!感觉那种gdbus这些工具也并不好用,工作量不小啊! 如果用单进程方式,在以前的产品中又常常出现各代码模块偶合调用,维护的人一多,后面又经常不成样了!但多进程方式时,如果前后端存在客户定制进也让人头痛!
考虑到后续交互,及代码量还是先用单进程方式吧!把所有UI的代码限在一个View的目录中,UI与外界面通信,交互都通过一个层来转换,这样后续如果使用多进程方式也可以快速修改!

View基本说明

我把所有的UI的代码都放在view的工程目录中,对外只提供了一个 view_main.h初始化及一些调用接口!

		/*
		 * UI的初始化操作
		 * */
		int 	view_init();

		/*
		 * UI的退出操作
		 * */
		void 	view_exit();

		/*
		 * 进入UI处理过程
		 * */
		int		view_process();

具体可见main.cpp中的调用,比较简单,初始化后,主线程阻塞在view_process上了!标准的UI使用方式!

在view里定义了一个view_lvgl.h的接口,这里后续定义一些lvgl相关的定义,并头文件引用! 及lvgl的一些相关操作!

		/*
		 * lvgl相关的初始调用
		 * */
		int 	view_lvgl_init();
		/*
		 * 退出lvgl
		 * */
		void 	view_lvgl_exit();

		/*
		 * 进入lvgl的UI处理
		 * */
		void	view_lvgl_process();

TView_App.h定义了一个UI APP初始化的入口,lvgl也是从这里正式的初始化的,后续把UI相关最开始的初始化可以放在这里,如开机的一个画机展示.
TView_App::process里创建一个UI主界面,并调用view_lvgl_process正式进入UI的处理流程!

		int TView_App::process()
		{
			TViewMainWindow* appMainWnd = TViewMainWindow::getInstance();

			if(!appMainWnd->init())
			{
				LOG(ERROR) << "TViewMainWindow init failure!" << endl;
				return -1;
			}

			view_lvgl_process();

			return 0;
		}

TViewObject 对UI窗口对像的一个抽像

看lvgl的文档,在lvgl里并没有什么正式的窗口概念,感觉是有意的弱化了以前各种UI库里的这种窗口的设计!而在现代的UI交互里,如我们的手机,各种屏的交互,都比较少用鼠标这种方式了,窗口的样式反而不合式!个人习惯吧,我也是把这里抽像一个基类,当做一个基类的一个窗口来使用的方式!

		class TViewObject
		{
		public:
			TViewObject();
			TViewObject(ViewHandle parentHandle);
			virtual ~TViewObject();
			/**
			 * 获取窗口对像句柄
			 * */
			virtual ViewHandle 	getViewHandle();
			/**
			 * 设置显示位置
			 * */
			virtual bool		setpos(int x, int y);
			/**
			 * 设置显示大小
			 * */
			virtual bool		setViewSize(int width, int height);

			virtual int			getViewWidth();

			virtual int 		getViewHeight();

			virtual bool 		viewShow();
			virtual bool		viewHide();

			/*事件处理*/
			virtual void		event_process(lv_event_t * event);
		private:
			static void			_event_process(lv_event_t * event);
		protected:
			/*LVGL的一个对像句柄*/
			ViewHandle m_viewHandle;
			/*LVGL的一个对像的基本样式*/
			lv_style_t m_style;
		};

ViewHandle m_viewHandle

在View里重定义了一个ViewHandle,只是对 typedef lv_obj_t* ViewHandle 重定义,没办法,习惯了对像句柄的概念!!!即然是一个LVGL的对像那一定是有一个lv_obj_t的定义的!

lv_style_t m_style

在TViewObject对像里定义了一个lv_style_t m_style, 主要是在使用lvgl创建各个窗口对像时,发现都需要设置一下不同的一点样式,感觉很麻烦,每一个从TViewObject里出来的一个窗口都需要,所认直接放在基类了。

virtual void event_process(lv_event_t * event);

在事件处理上,发现很多窗口都需要处理事件,在处理事件时又都需要定义一个事件处理回调,这里用的C++,又需要每一次都转到对应的窗口对像中来处理,所以也即在基类里直接实现一个静态的方法_event_process,再调用到 event_process这个虚方法上去!这样子类窗口,如果要处理事件,只需要override这个方法即可!不过好像这样LVGL默认的处理响应就不起作用了,刚用LVGL看后续如何操作解决这个问题!

构造处理 TViewObject::TViewObject(ViewHandle parentHandle)

在构造函数里,直接创建好了,lv的对像,初始化style,及设置事件处理!

	TViewObject::TViewObject(ViewHandle parentHandle)
	{
		m_viewHandle = lv_obj_create(parentHandle);
		lv_obj_add_event_cb(m_viewHandle, _event_process, LV_EVENT_ALL, this);
		lv_style_init(&m_style);
		lv_obj_add_style(m_viewHandle, &m_style, 0);
	}

构建NVR UI中的视频预览

在UI中抽像出了几个对像,TViewMultiVideoManage:一个是多视窗管理器-,这个管理视频的分割,显示模式; TViewPlayer:UI层面上的一个视频播放器;

TViewMultiVideoManage

负责TViewPlayer的创建,及模式的显示在系统里定义了几种比较常见的规则的显示模式!

	typedef enum{
		View_Splite_Mode_UNKNOW = 0,
		View_Splite_mode_1 = 1,
		View_Splite_mode_4 = 4,
		View_Splite_mode_9 = 9,
		View_Splite_mode_16 = 16
	}ViewVideoPlayerSplitMode;

TViewMultiVideoManage当前做了如下的事:

  • TViewMultiVideoManage中初始化创建各个通道的TViewPlayer放在一个map结构中,以视频channel通道号为Key来索引!;
  • 在设置视频显示模式时,TViewMultiVideoManage会负责好,那些通道的TViewPlayer显示,那里不显示;
  • 设置选中通道的样式;
  • 负责视频的轮巡显示;

TViewPlayer

TViewPlayer负责显示的样式,及通道UI的交互业务处理等!如用户单击,表示选中这个通道,改变选择的样式并调用相关的交互!

在这里插入图片描述

在这里插入图片描述

LVGL使用感觉

通过上面的很少的代码基本实现了一个NVR UI的视频预览画面,感觉还是很好用的LVGL!!!

简单,层次少,现代,这是LVGL给我的感觉!不过才用二天,看了一天的文档,花了一天的时间试各种控件,效果,做出上面这个NVR的UI主界面,很多细节没有了解,可能还有误用的地方!后续根据经验改进吧!

代码地址

PUPANVR代码地址

猜你喜欢

转载自blog.csdn.net/jhting/article/details/122572476