Android多媒体系统:集成的细微差异
扫描二维码
随时随地手机看文章
基于与 Android 设备制造商的长期密切合作,ARM 经历了大量常见的集成挑战,尤其是在“零拷贝zero-copy”多媒体管线(media pipeline)方面。尽管面临的挑战非常多,但依然有一些潜在的解决方案可以应对。传统的零拷贝多媒体管线主要目的是消除复制开销,然而当两个或多个多媒体处理硬件设备在内存中共享同一缓冲区空间时,就会出现问题,并且也会以一些非常不同的方式进行通信。软件驱动程序需要选择数据在缓冲区中的存储方式,如像素格式,并确保在 GPU 完成写入之前,显示器不会读取缓冲区。与组件相互通信的潜在集成问题有关的关键领域包括内存分配协商、像素格式协商和同步。
● 内存分配协商对于系统集成设计商来说是一个关键的领域,它可以决定系统图形缓冲区的内存分配位置和方式。分配内存时需要考虑到访问内存的底层硬件具备的多项限制。有多个重要问题有待解决,例如,所有组件是否都带有系统 MMU(内存管理单元)?如果不是,那么执行某些分配时需要将部分内存分配为连续的物理内存,以确保所有组件均可以读取该内存。适用于所有目标组件的理想内存对齐方式是指什么?例如,不同的硬件对于它想要如何在内存中对齐该内存的像素有不同的限制。如果缺乏对系统中每个组件的这种了解,在处理图形缓冲区时则可能会出现部分内存访问非常低效。基础物理地址宽度是另一个问题,即系统集成设计商可能拥有传统的 32 位内部显示管线,不能处理较大的内存块(例如,可以通过 ARMv8 64 位架构处理的内存块)。
是否存在某些组件无法访问的特定内存区域?或者它们必须访问的特定区域?Gralloc 模块由 Android 的编译引擎用来分配和管理适用于 2D 和 3D 图形用途的内存。ARM 提供的 Gralloc 库可以理解 ARM 多媒体处理器的所有系统限制,并且能够与 Android 内核的 ION 分配程序(一个统一的共享内存系统)配合运行,确保可以针对系统中的每个处理器执行最合适且高效的内存分配。软件驱动程序由 ARM 多媒体处理器用于实施标准 Linux DMA 缓冲区内存共享功能。如果所有驱动程序使用同一接口,则同一分配可以由一个处理器写入并由另一个处理器读取,从而为平台上的所有图形和视频内容提供零拷贝路径,确保仍能够维持尽可能低的内存带宽开销。
● 像素格式协商是需要在系统集成期间关注的第二个领域。务必确保多媒体 IP 解决方案中的每个组件(不论是视频、GPU 还是显示)实际上均能够理解来自其他组件的图形输出格式,以及确保每个组件生成的内容均能够以某种格式被其他组件读取。例如,尽管视频处理器可能能够以五种不同的 YUV 格式写出视频帧,如果显示处理器不支持其中的任何格式,则只能使用 GPU 功能在显示器上合成视频。或者,如果显示处理器不理解带有预乘 Alpha 值(大多数 Android 用户界面所使用的)的像素格式,则显示处理器将成为美化过的帧缓冲区控制器。最后,即便组件能够完全理解 32 位 RGBA 像素格式,出于某些未知的原因,显示的应用程序仍将出现反转的颜色。这会导致在开发过程中浪费大量时间,因为不仅需要追踪哪个组件在排序方面(比如 32 位像素格式的红色和蓝色组分)与其他一切不一致,而且还需要研究如何对它们进行反转。
● 同步是第三个领域,此处旨在尽可能异步运行以减少排队和延迟。主要问题在于,当系统中存在零拷贝路径、并且两个或多个设备正在直接使用同一个内存时,这些组件之间的同步将变得极为重要。例如,如果显示处理器在 GPU 或视频处理器完成写入之前便开始从缓冲区中进行读取,则会导致屏幕出现奇怪的伪像。在较早的 Android 版本(Jellybean 之前)中,渲染流水线中的每个组件通过执行以下一系列步骤处理和控制 Android 用户空间的同步:处理软件驱动程序中的命令;在硬件中执行其任务;等待任务在驱动程序中完成;以及将责任传递给管线的下一阶段。尽管这会使组件之间的同步方法变得简单容易,但也会造成管线出现暂停间隙,从而使流畅视觉内容之间出现差异并且中断最终用户体验。但是,一种全新同步化方法 Android Fences 已添加至平台;只要软件驱动程序支持它们,则允许在管线的每个阶段针对其组件执行 CPU 端处理和排队工作,即便前一阶段尚未在硬件中完成。这将大幅缩短一个硬件完成与下一个硬件开始之间的间隔。然而,要充分利用 Android Fences 的优势,还需要渲染管线中的每个组件均支持它们。如果所有组件均支持 Android Fences,但其中一个组件出现漏洞,则会出现问题。如果三个或更多个不同供应商提供的软件驱动程序均支持 Android Fences,但其中一个出现漏洞,则很难进行追踪、并且需要与多个供应商一起执行三项单独的调查。同时还有可能出现此种情况:只有当某个供应商的组件使用标准接口与其他供应商的组件进行通信时,该漏洞才会显现出来。