安卓多媒体开发框架中,从音频采集,视频采集,到音视频处理,音视频播放显示分别有哪些常用的框架?分成六章,这里一次帮你总结完。
音视频的主要流程是录制、处理、编解码和播放显示。本文也遵循这个流程展开,多媒体框架有视频驱动框架V4L2/UVC,显示驱动框架DRM,音视频处理框架openMAX,播放框架EXoplayer,以及显示渲染框架VLC等。
在一些大厂,一般和多媒体工程师和影像工程师进行区分,影像负责音视频的采集和处理;多媒体负责音视频的编解码和显示渲染;驱动和底层系统工程师负责提供底层的系统支持,以及框架内部的适配。
因为本人上下层都有涉猎,所以更加系统的把从多媒体的底层到上层,更为全面的角度审视这些多媒体框架。
本文是开源方案第二章,流媒体框架GStreamer之后单独一张补充,主要原因是做流媒体这一块的核心业务和流程和本地多媒体有蛮多差异。
有博友已经催更到朋友圈,所以做个说明:
最近同时面对工作和出差,身体抵抗力有所下降,每次写文章都忙到12点以后,考虑到健康状况,所以更新频率降低,恢复之后就继续安排上。因为文章皆为原创,同时为了保证质量,计划优先稳定在两周一更的频率。
一、多媒体框架综述
个人觉得通过上层到应用侧,通过JAVA API可以串联整个音视频的流程,更容易进行理解。
Android的多媒体框架同样也遵循这些流程,音视频解析/解码/播放/录制相关核心服务架构和流程有:
MediaExtractor/MediaCodec/MediaRecorder/MediaPlayerService/libstagefright/OpenMAX 等,使用它们从而完成音视频的采集、处理、编码、封包、mp4输出到最终的播放。
再具体一点,安卓相机的业务实现流程是:在收集数据之前,对Camera设置一些参数;然后设置PreviewCallback;之后获取到Camera的原始NV21数据;再创建一个H264Encoder类,在里面进行编码操作,并将编码后的数据存储到文件;结束编码的时候将相关的资源释放掉。这部分内容之后以高通为例,单独展开来说。
本文是对上一章《库》的补充,库和框架侧重不同。
库是一组可以重复使用的代码,提供了一些特定的功能,程序员可以在自己的程序中调用这些功能。比如在音视频多媒体系统开发中,库可能只负责音视频的编解码(如 FFmpeg)、音视频处理(如OpenCV)或视频渲染(如 OpenGL ES)等某个特定的功能模块。
框架则是提供了一整套的架构和机制,通过提供了大量的预定义代码和可复用组件从而实现一个完整的解决方案,框架会负责从音视频数据的获取、解码、处理到最终的显示渲染等整个流程的管理和组织。程序员是在这个框架的基础上实现自己的应用逻辑。
二、OpenMAX多媒体框架
OpenMAX(OMX)一个多媒体应用程序的框架标准,Android系统默认已经集成。
框架的特点是提供标准化的音视频处理API接口,便于集成和扩展;
因为其跨平台和标准化特点,在需要优化视频处理性能的时候,最常应用于嵌入式系统和移动设备中的音视频处理中。
程序员通过调用OpenMAX API来管理编解码器、设置编解码参数、发送编解码命令等。也可以发送音视频数据到编解码器进行处理,并接收处理后的数据。这些API通常通过JNI在Java层和Native层之间进行调用。
2.1框架分层
OMX的三个主要层次是DL(开发层)、IL(集成层)和AL(应用层)。
IL层在Android中是最常用的,IL层满足了操作系统到硬件的差异和多媒体应用的差异,IL提供了与硬件编解码器交互的接口。
硬件多媒体编解码框架,定义标准化接口对接 DSP/GPU 加速组件,提升编解码效率,如 MediaCodec
底层实现依赖此标准。
IL层主要实现了各种组件,组件是IL层实现的核心内容,通过输入端口消耗buffer,通过输出端口填充buffer,由此多组件相连接可以构成流式处理。
IL层对上层给AL层等框架层调用,也可以给应用程序直接调用;对下层可以调用DL层的接口,也可也直接调用各种codec实现。
OpenMAX IL层接口示例:
(1)组件加载与卸载接口:OMX_GetHandle
、OMX_FreeHandle
(2)组件控制与配置接口:OMX_SetParameter
、OMX_GetParameter
、OMX_SendCommand
(3)组件间通信接口:OMX_SetupTunnel
、OMX_UseBuffer
2.2使用流程
使用OpenMAX框架音视频开发的流程,和整体安卓多媒体的开发流程一致,主要包括以下几点:
(1)创建OpenMAX组件,使用OpenMAX IL API创建编解码器、源、解复用器等组件的实例。
(2)配置组件,设置组件的参数,如输入输出格式、缓冲区大小等。
(3)连接组件将不同的组件通过隧道化方式连接起来,形成处理流。
(4)发送数据,将音视频数据发送到编解码器进行处理。
(5)接收和处理结果,接收编解码器处理后的数据,并进行后续处理(如渲染、存储等)。
(6)资源释放,在处理完成后,释放组件和相关资源。
2.3在安卓系统应用
openmaxIL可以以插件的形式加入到android系统中,从而可以再Android系统的编解码开发、播放器组件以及中间件开发中都发挥作用。作为安卓系统的多媒体开发人员,对此毫不陌生。
(1)编解码器开发和管理。
通过OpenMAX IL层,音视频和图像编解码器能够与多媒体框架进行交互,提供统一的接口来支持编解码功能。Android系统通过OpenMAX IL层封装了硬件编解码器的功能,使得上层应用能够透明地利用硬件加速能力进行音视频编解码,从而提高接口处理效率。
(2)构成播放器组件。
在Android中,如NuPlayer或AwesomePlayer等播放器框架就使用了OpenMAX来管理编解码器、源、输出、解复用器demux等组件。
使用OpenMAX的组件化设计,播放器可以灵活地组合不同的模块,灵活实现音视频数据的解码、渲染和输出。
(3)实现多媒体中间件接口。
OpenMAX AL层提供了应用程序和多媒体中间件之间的标准化接口。应用开发着只需关注标准化的功能实现,差异化交给下层。
在Android中这有助于多媒体中间件与上层应用之间的集成,不同的厂商都热衷于设计和完成自己的中间件,比如编解码器库、图形库或者平台库等。
三、音视频采集框架
V4L2(Video for Linux 2)在Android音视频开发中的应用主要集中在视频采集和处理方面。V4L2是Linux内核中用于视频设备的一个API框架,旨在提供对视频捕捉、输出和处理设备的支持。
V4L2和UVC的驱动基础我们在之前的文章中已经分享过,本文更加关注框架层应用。
https://mp.weixin.qq.com/s/puaNQrfn1KFNe0uSN9SmKQ
https://mp.weixin.qq.com/s/JG2XDjI1E2jEU6fDlQZCCw
3.1V4L2的使用
在linux中使用V4L2,使用open()
函数打开视频设备文件/dev/videoX
,使用ioctl()
函数进行设置和处理视频帧。
在Android中使用V4L2,只需要在内核配置菜单中选择Video capture adapters”,确保V4L2驱动被选中并编译进内核,之后按照V4L2提供的API来访问和控制视频设备,使用ioctl等系统调用设置和处理视频帧。使用v4l2-ctl等命令行工具来调试和测试V4L2设备信息。通过logcat等工具来查看调试信息。
在驱动开发中,V4L2可以作为摄像头、视频采集卡等设备的驱动框架。驱动工程师根据V4L2的规范来编写或修改驱动程序,使设备能够在Android系统上正常工作。
在系统开发中,通过V4L2以直接与Android设备上的摄像头硬件进行交互,实现视频帧的捕获。系统工程师可以使用V4L2接口来开发特定的视频采集应用,如安防监控软件、实时视频流传输软件等。
在应用开发中,比如视频编辑软件、实时视频特效软件时,可以通过V4L2与GPU或其他硬件加速技术结合使用,提高处理效率。
3.2UVC的使用
在Linux音视频开发中,UVC是USB视频类驱动框架,标准化USB摄像头在Linux内核中的协议实现,主要用在处理USB摄像头和视频输入设备时。在Linux系统中,UVC设备通常会被识别为/dev/videoX
(X为设备编号)的文件。
使用UVC简化了视频采集的流程,Linux系统能够直接识别和使用USB摄像头,而无需安装额外的驱动程序。同样UVC摄像头通常支持多种视频格式和分辨率,所以UVC更容易应用于快捷视频接入的场景。
在视频监控中,UVC摄像头可以通过Linux系统实现视频的捕获、编码和传输,满足远程监控和管理的需求。
在视频会议和实时通讯应用中,UVC摄像头能够提供清晰的视频画面,支持语音通话和视频通话。
3.3音频采集Oboe
Android SDK 提供了两套音频采集的 API 接口: MediaRecorder 和 AudioRecord。
而Android NDK则可以通过OpenSL ES 、AAudio和Oboe完成音频采集。
Oboe是Android 团队开发的 C++ 音频框架,封装 AAudio
和 OpenSL ES
,支持高性能、低延迟音频采集与播放,用于构建高性能的音频应用程序,比如实时音频分析工具Audio Analyze就是使用的该框架。
更多资料:
https://github.com/google/oboe/blob/main/docs/FullGuide.md
https://github.com/googlearchive/android-audio-high-performance/
四、显示驱动框架
DRM(Direct Rendering Manager)是Linux内核显示渲染框架,管理GPU资源分配与多屏合成调度。Linux DRM聚焦图形硬件的高效利用,而Android DRM侧重内容安全。
DRM的驱动基础我们在之前的文章中已经分享过,本文更加关注框架层应用。
4.1、Linux系统中的DRM框架
DRM是Linux内核中管理GPU的核心框架,其开发使用可分为:内核层和应用层开发。
最终的应用也比较广泛,在嵌入式系统,DRM驱动实现多屏显示(如HDMI+LVDS);图形服务器中,利用DRM直接访问GPU进行窗口合成,避免X Server的间接渲染开销。
(1)内核层开发,通过drm_driver
结构体注册GPU驱动,实现drm_crtc
(显示控制器)、drm_plane
(图层)、drm_framebuffer
(帧缓冲区)等核心对象的生命周期管理。
(2)内核层开发,使用KMS
(Kernel Mode Setting)API进行显示模式配置(如分辨率、刷新率),通过GEM
(Graphics Execution Manager)管理显存分配与跨进程共享。
(3)内核层开发,调试工具链包括:modetest
:测试显示模式与帧缓冲操作;drm_info
:查询GPU设备信息;apitrace
:跟踪OpenGL/Vulkan调用。
(4)用户层开发,则通过libdrm
库调用ioctl
接口,或者结合GBM(Generic Buffer Management)或EGL实现GPU加速渲染。
4.2Android系统中的DRM框架
Android的DRM框架主要用于数字版权保护,包括DRM引擎和播放器集成,比如ExoPlayer通过DefaultDrmSessionManager与DRM服务器通信。
最终的应用有流媒体保护和企业应用,比如Netflix使用Widevine L1级保护4K内容,密钥通过安全通道传输;Android for Work通过DRM限制企业数据访问权限,防止数据泄露。
五、多媒体播放框架
Android 媒体框架通过 MediaPlayer
类来控制音视频的播放,MediaPlayer
会将解码后的视频帧输出到指定的 Surface
上进行显示。而具体的显示渲染则依赖于 SurfaceView
或 TextureView
等视图组件。
综合来说,Stagefright作为早期框架已被取代,NuPlayer集成于系统但扩展性有限,ExoPlayer则是开发的推荐选择,尤其在需要流媒体支持和高度定制的场景。
5.1Stagefright和NuPlayer
Stagefright和NuPlayer是Android系统中用于多媒体编解码与播放的底层框架,主要处理音频、视频的解析、解码和渲染。它通过OpenMAX接口与硬件编解码器交互,支持H.264、MP3等主流格式,Stagefright应用在Android 2.0至5.1版本,Android 5.1后被NuPlayer取代。
关键组件中,AwesomePlayer是核心播放器模块,管理音视频同步与渲染。MediaExtractor负责解析媒体文件,分离音视频流。OMXCodec则基于OpenMAX的编解码器,支持硬件加速。
Android中的Stagefright框架,包括Video Playback流程、与OpenMAX的运作、选择Video Decoder、Video Buffer传输、Video Rendering以及Audio Playback流程。Stagefright使用OpenMAX进行编解码,并通过AudioPlayer处理audio部分,实现Video与Audio的同步。
Stagefright | NuPlayer | |
---|---|---|
API | 通过MediaPlayer 类调用, |
通过MediaPlayer 类调用 |
使用 | 直接使用MediaPlayer 或MediaCodec 等高级API,底层由Stagefright处理编解码与渲染 |
基于StagefrightPlayer 基础类开发 |
流媒体支持 | 仅本地播放 | 支持HTTP Live、RTSP等流媒体协议 |
5.2ExoPlayer
ExoPlayer是谷歌开源播放框架,支持自定义渲染逻辑、自适应流(DASH/HLS)及 DRM 加密播放,可扩展性强于 MediaPlayer
,ExoPlayer是构建在MediaPlayer之上的库,用于替代 Android 原生的 MediaPlayer
,提供了更强大的功能和性能,当然也更复杂。
六、显示渲染框架
在音视频多媒体系统开发中,显示和渲染框架通常是指那些提供了一整套架构和机制,这些框架通常会包含多个模块,负责从音视频数据的解码、处理到最终的显示,显示和渲染基本在一个框架中实现。
6.1VLC和SDL
VLC 是一个非常流行的开源多媒体播放器,它背后也有一个强大的多媒体处理框架。
VLC 框架内部有自己的一套机制来处理音视频的显示和渲染。它支持多种视频输出模块,可以根据不同的平台和需求选择合适的输出方式,例如在 Windows 上可以使用 Direct3D 进行视频渲染,在 Linux 上可以使用 X11 等。
FFmpeg +SDL 构成一个简单的显示和渲染框架。
FFmpeg 负责音视频的解码等工作,而 SDL (Simple DirectMedia Layer)则负责将解码后的视频帧渲染到屏幕上。SDL 提供了跨平台的多媒体处理功能,包括音频播放和视频显示。
这种组合比较轻量级,适合一些对性能要求不是特别高,但需要快速实现音视频播放和显示的场景。由于 FFmpeg 和 SDL 都是开源的,也具有很好的可定制性。
6.2渲染视图组件
组件的使用,通过使用 MediaPlayer
类加载音视频文件;通过 SurfaceView
或 TextureView
将视频帧渲染到屏幕上,ImageView
则用于显示静态图像;使用 MediaCodec
进行音视频的解码,然后通过 OpenGL ES 或其他图形库进行自定义渲染。ExoPlayer 更是支持自定义渲染器,可以通过实现 Renderer
接口来实现自定义的音视频渲染逻辑。GLSurfaceView
则用于实现复杂的 3D 图形渲染比如游戏、AR 等场景。
总结
看到这里还不帮忙点个赞和关注,十分感谢!VX :森哥谈成像技术,更新更及时哦。
本文根据博主工作经验,汇总了影像系统从上到下,程序员都会用到的哪些开源框架。
掌握这些,有助于更好的分析问题以及查漏补缺,成为多媒体领域的全栈工程师。
本文是开源方案第二章,流媒体框架GStreamer之后单独一张补充,主要原因是做流媒体这一块的核心业务和流程和本地多媒体有蛮多差异。
本文只做简单的梳理,如有学习需要可以参考其更多资料。