@houxiaoni 全志对gstreamer做了适配支持,怎么tina的开发文档里都没有提及?还是我漏看了什么重要内容?我看到的文档,多媒体开发只有tplayer工具这一种,楼主能否澄清一下?
laocai 发布的最佳帖子
-
回复: 【FAQ】全志D1芯片 如何解决Gstreamer:fb UI旋转(直接修改内核参数)后,sunxifbsink显示异常问题?
-
sunxi图层之间的显示切换
现在有两个图层,它们由其他app生成,我希望通过编程的方法,简单的进行切换:显示图层1-->显示图层2-->再显示图层1-- >以此类推。如果通过DISP_LAYER_SET_CONFIG调用的话,似乎要把图层所有的参数,包括缓冲区地址等统统设置一遍,而我只想简单的切换两个图层,并不知道也不关心这些图层的详细参数。请问我该怎么做?
# cat /sys/class/disp/disp/attr/sys | more screen 0: de_rate 300000000 hz, ref_fps:62 mgr0: 480x480 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[0] force_ sync[0] unblank direct_show[false] iommu[1] dmabuf: cache[0] cache max[0] umap skip[0] umap skip max[18] lcd output backlight(229) fps:62.1 480x 480 err:11428 skip:90 irq:14361 vsync:0 vsync_skip:0 BUF enable ch[0] lyr[0] z[0] prem[N] a[globl 255] fmt[ 11] fb[ 480, 480; 0, 0; 0, 0] crop[ 0, 0, 0, 0] frame[ 0, 0, 480, 480] addr[ 2 80000, 0, 0] flags[0x 0] trd[0,0] depth[ 0] BUF enable ch[1] lyr[0] z[16] prem[N] a[pixel 255] fmt[ 0] fb[ 480, 480; 480, 480; 480, 480] crop[ 0, 0, 480, 480] frame[ 0, 0, 480, 48 0] addr[ 0, 0, 0] flags[0x 0] trd[0,0] depth[ 0]
laocai 发布的最新帖子
-
sunxi图层之间的显示切换
现在有两个图层,它们由其他app生成,我希望通过编程的方法,简单的进行切换:显示图层1-->显示图层2-->再显示图层1-- >以此类推。如果通过DISP_LAYER_SET_CONFIG调用的话,似乎要把图层所有的参数,包括缓冲区地址等统统设置一遍,而我只想简单的切换两个图层,并不知道也不关心这些图层的详细参数。请问我该怎么做?
# cat /sys/class/disp/disp/attr/sys | more screen 0: de_rate 300000000 hz, ref_fps:62 mgr0: 480x480 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[0] force_ sync[0] unblank direct_show[false] iommu[1] dmabuf: cache[0] cache max[0] umap skip[0] umap skip max[18] lcd output backlight(229) fps:62.1 480x 480 err:11428 skip:90 irq:14361 vsync:0 vsync_skip:0 BUF enable ch[0] lyr[0] z[0] prem[N] a[globl 255] fmt[ 11] fb[ 480, 480; 0, 0; 0, 0] crop[ 0, 0, 0, 0] frame[ 0, 0, 480, 480] addr[ 2 80000, 0, 0] flags[0x 0] trd[0,0] depth[ 0] BUF enable ch[1] lyr[0] z[16] prem[N] a[pixel 255] fmt[ 0] fb[ 480, 480; 480, 480; 480, 480] crop[ 0, 0, 480, 480] frame[ 0, 0, 480, 48 0] addr[ 0, 0, 0] flags[0x 0] trd[0,0] depth[ 0]
-
回复: V853显示屏无法直接显示图片
@ddrddr 可能你的framebuffer支持alpha通道,但是填充图像数据的时候没有填写相应alpha数值。检查一下framebuffer格式即可。
-
回复: 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题
@laocai 官方文档里也到处都是错误。
红线处正确的代码应该是这样的:
memset(&config, 0, sizeof(struct disp_layer_config)); config.channel = 0;//blending channel config.layer_id = 0;//layer index in the blending channel config.enable = 1; config.info.mode = LAYER_MODE_BUFFER;
-
回复: 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题
@zheng1 在 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题 中说:
@laocai tina的sdk有一个libuapi库是对这部分接口的封装,我在v851s上用DISP_LAYER_SET_CONFIG2会导致内核内存泄漏,你可以试试有没有同样的问题
我猜你遇到的问题可能和这段代码有关:
#if defined(CONF_KERNEL_IOMMU) ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REL, 0); if (ret) logv("ENGINE_REL failed\n"); struct user_iommu_param iommu_param; memset(&iommu_param, 0, sizeof(iommu_param)); iommu_param.fd = tmp->fd_data.aw_fd; ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_FREE_IOMMU_ADDR, &iommu_param); if (ret) logv("FREE_IOMMU_ADDR err, ret %d\n", ret); #endif /*close dma buffer fd*/ close(tmp->fd_data.aw_fd); /* free buffer */ handle_data.handle = tmp->fd_data.handle; ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_FREE, &handle_data); if (ret) logv("TON_IOC_FREE failed\n"); aw_mem_list_del(&tmp->i_list); free(tmp); flag = 1;
handle_data.handle = tmp->fd_data.handle;
内核版本为高版本(5.4)的时候,libuapi库在申请内存时根本没有初始化这个handle。然后释放内存的时候,却又用这个空的handle去调用释放的系统调用,内存根本不可能真正释放。换句话说,这个libuapi库只有在低版本内核上才有可能正常工作;高版本内核上,内存只能申请,无法释放。
-
回复: 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题
@laocai 另外关于sunxi_display2.h文件,我在tina sdk的package中发现了七个路径下有这个文件,前面三个文件的内容各不相同,和内核使用的sunxi_display2.h文件也不同。
allwinner/libAWIspApi/src/isp522/libisp/include/device/sunxi_display2.h
allwinner/tina_multimedia/libcedarx/demo/xplayerdemo/sunxi_display2.h
allwinner/tina_multimedia/libcedarx/demo/recoderdemo/sunxi_display2.h
allwinner/libuapi/src/sunxi_display_v2.h
testtools/tinatest/testcase/base/production/displaytester/common/sunxi_display_v2.h
allwinner/tinacvr/src/middle_ware/sunxi_display_v2.h
gui/minigui/multimedia-test/src/middle_ware/sunxi_display_v2.h比较了一下,和内核头文件最接近的是allwinner/libAWIspApi/src/isp522/libisp/include/device/sunxi_display2.h
allwinner/tinacvr/src/middle_ware/sunxi_display_v2.h和allwinner/libuapi/src/sunxi_display_v2.h比较接近,后者像是在前者基础上修改而来。
-
回复: 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题
@laocai 如果要获得framebuffer的物理地址,就采用这个方法
void* sunxifb_mem_get_phyaddr(void *data) { if (data != NULL) return SunxiMemGetPhysicAddressCpu(memops, data); else return NULL; }
-
回复: 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题
@laocai 我找到了一个简单使用libuapi库的例子,在tina-package/blob/main/gui/littlevgl-8/lv_drivers/display/sunximem.c
/** * @file sunximem.c * */ /********************* * INCLUDES *********************/ #include "sunximem.h" #if USE_SUNXIFB_G2D #include <stdio.h> #include <ion_mem_alloc.h> /********************* * DEFINES *********************/ /********************** * TYPEDEFS **********************/ /********************** * STRUCTURES **********************/ /********************** * STATIC PROTOTYPES **********************/ static struct SunxiMemOpsS *memops; /********************** * STATIC VARIABLES **********************/ /********************** * MACROS **********************/ /********************** * GLOBAL FUNCTIONS **********************/ bool sunxifb_mem_init() { if (memops) return true; memops = GetMemAdapterOpsS(); if (SunxiMemOpen(memops) < 0) { perror("Error: cannot open ion device"); return false; } return true; } void sunxifb_mem_deinit() { if (memops) { SunxiMemClose(memops); memops = NULL; } } void* sunxifb_mem_alloc(size_t size, char *label) { if (size == 0) { printf("size illegal."); return NULL; } void *alloc = SunxiMemPalloc(memops, size); if (alloc == NULL) { printf("couldn't allocate memory (%lu bytes).", (unsigned long) size); return NULL; } #ifdef LV_USE_SUNXIFB_DEBUG printf("%s: sunxifb_mem_alloc=%p size=%lu bytes\n", label, alloc, (unsigned long) size); #endif /* LV_USE_SUNXIFB_DEBUG */ return alloc; } void sunxifb_mem_free(void **data, char *label) { if (*data != NULL) { #ifdef LV_USE_SUNXIFB_DEBUG printf("%s: sunxifb_mem_free=%p\n", label, *data); #endif /* LV_USE_SUNXIFB_DEBUG */ SunxiMemPfree(memops, *data); *data = NULL; } else { printf("couldn't free memory.\n"); } } void* sunxifb_mem_get_phyaddr(void *data) { if (data != NULL) return SunxiMemGetPhysicAddressCpu(memops, data); else return NULL; } void sunxifb_mem_flush_cache(void *data, size_t size) { SunxiMemFlushCache(memops, data, size); } /********************** * STATIC FUNCTIONS **********************/ #endif
-
回复: 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题
@laocai 而选择ion设备还是cedar设备,是由编译选项决定的。如果要采用DISP_LAYER_SET_CONFIG2,必须编译的时候选择SUNXI_ALLOC_IOMMU,不知道我的理解是否正确?我找到的关于全志disp的讨论
choice prompt "Choose alloc method" default SUNXI_ALLOC_CMA help Select how to apply for memory. config SUNXI_ALLOC_CMA bool "sunxi_alloc_cma" config SUNXI_ALLOC_IOMMU bool "sunxi_alloc_iommu" endchoice choice prompt "Choose layer alloc method" default LUAPI_LAYER_ALLOC_CHN help Select how to apply for layer. config LUAPI_LAYER_ALLOC_CHN bool "luapi_layer_alloc_chn" config LUAPI_LAYER_ALLOC_LAY bool "luapi_layer_alloc_lay" endchoice choice prompt "Choose display rendering mode" default SUNXI_DISPLAY_DE help Choose display rendering mode, DE or GPU. config SUNXI_DISPLAY_DE bool "DE" config SUNXI_DISPLAY_GPU bool "GPU" help Define the macro SUNXI_DISPLAY_GPU, use GPU rendering, send the RGBA data after rendering to fb1 display, execute export FRAMEBUFFER=/dev/fb1 before executing the program, no longer support DispSetEnable, DispSetSrcRect, DispSetZorder and DispSetIoctl functions. Define the macro SUNXI_DISPLAY_GPU and SUNXI_DISPLAY_GPU_BUF, use GPU rendering, send the RGBA data after rendering to layer. No longer support DispSetSrcRect functions. Default use. endchoice endif endef define Build/Prepare $(INSTALL_DIR) $(PKG_BUILD_DIR)/ $(CP) ./src $(PKG_BUILD_DIR)/ endef define Build/Configure endef ifeq ($(CONFIG_SUNXI_DISPLAY_TWO),y) TARGET_CFLAGS+=-D__SUNXI_DISPLAY2__ TARGET_CFLAGS+=-D$(KERNEL_VERSION) endif ifeq ($(CONFIG_SUNXI_DISPLAY_ONE),y) TARGET_CFLAGS+=-D__SUNXI_DISPLAY__ TARGET_CFLAGS+=-D$(KERNEL_VERSION) endif ifeq ($(CONFIG_SUNXI_ALLOC_CMA),y) TARGET_CFLAGS+=-DCONF_KERNEL_CMA endif ifeq ($(CONFIG_SUNXI_ALLOC_IOMMU),y) TARGET_CFLAGS+=-DCONF_KERNEL_IOMMU endif
另外我还发现,linux 内核5.4版本的时候,libuapi库无法使用ion设备来分配framebuffer,原因就是代码里面根本没有实现alloc_data的赋值。
#if CONF_KERNEL_VERSION_OLD ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_ALLOC, &alloc_data); if (ret) { loge("ION_IOC_ALLOC error\n"); goto ALLOC_OUT; } /* get dmabuf fd */ fd_data.handle = alloc_data.handle; ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_MAP, &fd_data); if (ret) { loge("ION_IOC_MAP err, ret %d, dmabuf fd 0x%08x\n", ret, (unsigned int)fd_data.aw_fd); goto ALLOC_OUT; } #else struct aw_ion_new_alloc_data data = { .len = alloc_data.aw_len, .heap_id_mask = alloc_data.aw_heap_id_mask, .flags = alloc_data.flags, }; ret = ioctl(g_ion_alloc_context->fd, AW_ION_IOC_NEW_ALLOC, &data); if (ret < 0) { loge("AW_ION_IOC_NEW_ALLOC error\n"); goto ALLOC_OUT; } fd_data.aw_fd = data.fd; #endif
/* get phy address */ #if defined(CONF_KERNEL_IOMMU) memset(&iommu_param, 0, sizeof(iommu_param)); iommu_param.fd = fd_data.aw_fd; ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REQ, 0); if (ret) { loge("ENGINE_REQ err, ret %d\n", ret); addr_phy = 0; addr_vir = 0; goto ALLOC_OUT; } ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_GET_IOMMU_ADDR, &iommu_param); if (ret) { loge("GET_IOMMU_ADDR err, ret %d\n", ret); addr_phy = 0; addr_vir = 0; goto ALLOC_OUT; } addr_phy = iommu_param.iommu_addr; #else memset(&phys_data, 0, sizeof(phys_data)); phys_data.handle = alloc_data.handle; phys_data.size = size; custom_data.aw_cmd = ION_IOC_SUNXI_PHYS_ADDR; custom_data.aw_arg = (unsigned long)&phys_data; ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_CUSTOM, &custom_data); if (ret) { loge("ION_IOC_CUSTOM err, ret %d\n", ret); addr_phy = 0; addr_vir = 0; goto ALLOC_OUT; } addr_phy = phys_data.phys_addr; #endif