PUPANVR-UI main interface video preview development

PUPANVR-UI main interface video preview development

UI choice

I originally considered using MINIGUI, but seeing the ancient control style, I thought it would be too annoying to make the textures more modern, and its open source method is not very user-friendly!

Then I looked at various UI libraries and looked at the examples of the LVGL library. Although I have never understood it well, I fell in love with it instantly!

Well, let’s use LVGL!

transplant

There is no need to talk about value shifting. The framebuffer is simple enough. On the HiSilicon platform, you can see the introduction to using it on Hi3536C in the previous article.

Single process or multi-threaded

I'm wondering if I need to make the UI an independent process. I'm a bit confused. If I write it as an independent process, there will be more interactions with the background recording management process on the UI. I think of the need for server and client modes, calling Notifications and protocol format decoding require a large amount of code! I feel that tools like gdbus are not easy to use, and the workload is not small! If the single-process method is used, in previous products, there are often coincidental calls to each code module. When there are more people maintaining it, things often get messed up later! But in multi-process mode, if there is customer customization in the front and back ends, it will also be a headache!
Considering the subsequent interactions and the amount of code, let’s use the single-process method first! Limit all UI code to a View directory. Communication and interaction between the UI and the external interface are converted through a layer, so that subsequent multi-process methods can be quickly modified!

View basic instructions

I put all the UI code in the project directory of the view, and only provide a view_main.h initialization and some calling interfaces to the outside world!

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

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

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

Specifically, you can see the call in main.cpp, which is relatively simple. After initialization, the main thread is blocked in view_process! Standard UI usage!

An interface view_lvgl.h is defined in the view. Here we will define some lvgl-related definitions and reference them in the header file! And some related operations of lvgl!

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

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

TView_App.h defines an entry for UI APP initialization. lvgl is also officially initialized from here. Later, the initial initialization related to UI can be placed here, such as a drawing display at startup. Create a UI in TView_App::
process The main interface, and call view_lvgl_process to officially enter the UI processing flow!

		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 is an abstraction of the UI window object

Looking at the lvgl documentation, there is no formal window concept in lvgl. It feels like the window design in various previous UI libraries has been intentionally weakened! In modern UI interactions, such as our mobile phones, the mouse is rarely used to interact with various screens, and the window style is inappropriate! Personally, I also abstract this as a base class and use it as a window of a base class!

		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

I redefined a ViewHandle in View, just redefining the typedef lv_obj_t* ViewHandle. There is no way, I am used to the concept of object handle!!! Since it is an LVGL object, there must be a definition of lv_obj_t!

lv_style_t m_style

A lv_style_t m_style is defined in the TViewObject object. Mainly when using lvgl to create each window object, I found that I need to set a different style. It feels very troublesome. Every window that comes out of the TViewObject needs it, so It should be placed directly in the base class.

virtual void event_process(lv_event_t * event);

In terms of event processing, we found that many windows need to process events. When processing events, they need to define an event processing callback. The C++ used here needs to be transferred to the corresponding window object for processing every time, so that is Directly implement a static method _event_process in the base class, and then call the virtual method event_process! In this class window, if you want to handle events, you only need to override this method! However, it seems that the default processing response of LVGL does not work. I just used LVGL to see how to solve this problem!

Construct and handle TViewObject::TViewObject(ViewHandle parentHandle)

In the constructor, the lv object is created directly, the style is initialized, and event processing is set!

	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);
	}

Build video preview in NVR UI

Several objects are abstracted in the UI, TViewMultiVideoManage: one is a multi-window manager, which manages the division and display mode of videos; TViewPlayer: a video player on the UI level;

TViewMultiVideoManage

Responsible for the creation of TViewPlayer and the display of modes. Several common rule display modes are defined in the system!

	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 currently does the following:

  • In TViewMultiVideoManage, the TViewPlayer that creates each channel is initialized and placed in a map structure, indexed with the video channel number as the Key!;
  • When setting the video display mode, TViewMultiVideoManage will be responsible for displaying the TViewPlayer of those channels and not displaying them there;
  • Set the style of the selected channel;
  • Responsible for video tour display;

TViewPlayer

TViewPlayer is responsible for the display style, interactive business processing of the channel UI, etc.! If the user clicks, it means that this channel is selected, the selected style is changed and related interactions are called!

Insert image description here

Insert image description here

LVGL usage experience

Through the above few codes, a video preview screen of NVR UI is basically realized. It feels like LVGL is very easy to use!!!

Simple, few layers, and modern, this is the feeling that LVGL gives me! I have only used it for two days, read a day of documents, and spent a day trying various controls and effects to create the main UI interface of the NVR above, with many details. If you don’t understand it, you may be misusing it! Let’s improve based on experience in the future!

code address

PUPANVR code address

Guess you like

Origin blog.csdn.net/jhting/article/details/122572476