系统之家提供 Windows 系统、Ghost 系统、驱动与常用软件的安全下载及安装教程。 后台管理
📢 欢迎访问系统之家!所有资源均经过安全检测。

Surface中的BufferQueue

发布时间:2026-09-28 | 浏览:1
📥 下载地址(文章开头)
装机神器,可安装一切系统,纯净版,英文版,繁体版 ,精简版,原版等等等
1. BufferQueue 是什么 本质 :一个 环形缓冲队列 (slots + fences),承接" 生产者 Producer 写帧 → 消费者 Consumer 取帧"的流。 本质 :一个 环形缓冲队列 (slots + fences),承接" 生产者 Producer 写帧 → 消费者 Consumer 取帧"的流。 关键目标 : 零拷贝/少拷贝 传递图像帧,降低延迟与功耗。 关键目标 : 零拷贝/少拷贝 传递图像帧,降低延迟与功耗。 典型 Producer :MediaCodec(硬解)、MediaPlayer/ExoPlayer、OpenGL(EGL)、Canvas CPU 绘制。 典型 Producer :MediaCodec(硬解)、MediaPlayer/ExoPlayer、OpenGL(EGL)、Canvas CPU 绘制。 典型 Consumer : SurfaceView: SurfaceFlinger (系统合成器,独立图层) TextureView: SurfaceTexture (把帧变为 GPU 纹理参与应用内合成) SurfaceView: SurfaceFlinger (系统合成器,独立图层) SurfaceView: SurfaceFlinger (系统合成器,独立图层) TextureView: SurfaceTexture (把帧变为 GPU 纹理参与应用内合成) TextureView: SurfaceTexture (把帧变为 GPU 纹理参与应用内合成) 2. 内部构成(你需要知道的名词) Slots :固定数量的缓冲槽位(Android 源码里 NUM_BUFFER_SLOTS=64 的上限,实际使用远小于此,一般 2~4)。 GraphicBuffer :每个 slot 上的图像缓冲(显存/共享内存)。 Fence(栅栏) :同步原语,标记"GPU/硬件写入/读取完成"。Producer queue 时附 release fence ;Consumer acquire 时拿到 acquire fence 。 IGraphicBufferProducer / Consumer :BufferQueue 的 Binder 两端接口;Java Surface → native Surface.cpp → IGBP。 BufferQueueProducer/Consumer/Core :C++ 里三分体实现(队列核心 + 生产/消费端包装)。 3.1 Producer 侧(写帧) dequeueBuffer() :向队列申请一个空闲 slot 若没有可用 slot,会 阻塞/失败 。 dequeueBuffer() :向队列申请一个空闲 slot 若没有可用 slot,会 阻塞/失败 。 请求/复用缓冲 :如果大小/格式/usage 不匹配,触发 重新分配 (避免每帧分配!)。 请求/复用缓冲 :如果大小/格式/usage 不匹配,触发 重新分配 (避免每帧分配!)。 渲染写入 : CPU:ANativeWindow_lock() → 绘制 → unlockAndPost() GL:向 egl window surface 画 → eglSwapBuffers() MediaCodec:解码器把帧直接写入绑定的 Surface CPU:ANativeWindow_lock() → 绘制 → unlockAndPost() GL:向 egl window surface 画 → eglSwapBuffers() MediaCodec:解码器把帧直接写入绑定的 Surface queueBuffer() :把填好的帧入队,并附上 release fence 、时间戳、裁剪、变换等元数据。 若队列满,可能阻塞或丢帧(async 模式)。 queueBuffer() :把填好的帧入队,并附上 release fence 、时间戳、裁剪、变换等元数据。 若队列满,可能阻塞或丢帧(async 模式)。 3.2 Consumer 侧(读帧) acquireBuffer() :取队首可用帧;等待 acquire fence 完成再读(保证数据有效)。 acquireBuffer() :取队首可用帧;等待 acquire fence 完成再读(保证数据有效)。 消费 : SurfaceView:SurfaceFlinger 在下一次合成周期把这帧与其它图层进行 硬件合成/混合 。 TextureView:SurfaceTexture 把帧 更新到 GL 纹理 ,在应用进程的 ViewRoot 绘制时采样参与合成。 SurfaceView:SurfaceFlinger 在下一次合成周期把这帧与其它图层进行 硬件合成/混合 。 TextureView:SurfaceTexture 把帧 更新到 GL 纹理 ,在应用进程的 ViewRoot 绘制时采样参与合成。 releaseBuffer() :用完把 slot 归还队列(可再次被 Producer 复用)。 releaseBuffer() :用完把 slot 归还队列(可再次被 Producer 复用)。 关键点 : 双/三缓冲 常见。三缓冲可降低生产/消费不同步导致的阻塞,但会增加一帧延迟。 4. 容量/阻塞规则(为什么会"卡住/掉帧") 队列允许 Producer 同时"借出"的 buffer 数量受 maxDequeuedBufferCount 限制(默认根据 Consumer 能同时持有的数量决定)。 队列允许 Producer 同时"借出"的 buffer 数量受 maxDequeuedBufferCount 限制(默认根据 Consumer 能同时持有的数量决定)。 当 Producer 已借出过多 或 Consumer 持有未释放 ,再 dequeueBuffer() 可能 阻塞 。 当 Producer 已借出过多 或 Consumer 持有未释放 ,再 dequeueBuffer() 可能 阻塞 。
📥 下载地址(文章中间)
装机神器,可安装一切系统,纯净版,英文版,繁体版 ,精简版,原版等等等
当 Producer queueBuffer() 太快 (消费者来不及合成/采样): 同步模式 :可能在 queueBuffer() 阻塞等待。 异步模式 (setAsyncMode(true)):不阻塞, 丢弃旧帧保留最新帧 (视频预览常用)。 当 Producer queueBuffer() 太快 (消费者来不及合成/采样): 同步模式 :可能在 queueBuffer() 阻塞等待。 异步模式 (setAsyncMode(true)):不阻塞, 丢弃旧帧保留最新帧 (视频预览常用)。 尺寸/格式改变 会导致老缓冲失配并重分配, 频繁 reallocate = 抖动/卡顿 。 尺寸/格式改变 会导致老缓冲失配并重分配, 频繁 reallocate = 抖动/卡顿 。 经验:视频/相机建议 3 缓冲 (Producer 可 deque 2 个,Consumer 同时 hold 1 个),并开启 异步模式 以避免阻塞主渲染。 5. SurfaceView vs TextureView:BufferQueue 的去向不同 相同点 :两者 Producer 都是对一个 Surface 写帧;BufferQueue 机制一致,只是"另一端是谁"不同。 6. 关键参数与调优点(Producer 侧常用) 尺寸 :ANativeWindow_setBuffersGeometry() / MediaCodec format.setInteger(KEY_WIDTH/HEIGHT, ...) → 只在必要时改 ,否则频繁重分配。 尺寸 :ANativeWindow_setBuffersGeometry() / MediaCodec format.setInteger(KEY_WIDTH/HEIGHT, ...) → 只在必要时改 ,否则频繁重分配。 格式 :PIXEL_FORMAT_RGBA_8888 等;视频解码一般 NV12/NV21/YUV420(由 Codec & HWC 决定)。 格式 :PIXEL_FORMAT_RGBA_8888 等;视频解码一般 NV12/NV21/YUV420(由 Codec & HWC 决定)。 Usage :GRALLOC_USAGE_SW_READ/WRITE, HW_TEXTURE, HW_COMPOSER, PROTECTED(DRM)等;决定缓冲放在哪、能否被哪类硬件高效访问。 Usage :GRALLOC_USAGE_SW_READ/WRITE, HW_TEXTURE, HW_COMPOSER, PROTECTED(DRM)等;决定缓冲放在哪、能否被哪类硬件高效访问。 Dataspace/ColorSpace :BT.709/BT.2020/HDR;和 HWC/GL 管线匹配,否则会偏色/错 gamma。 Dataspace/ColorSpace :BT.709/BT.2020/HDR;和 HWC/GL 管线匹配,否则会偏色/错 gamma。 Scaling/Transform/Crop :通过 queueBuffer() 的元数据携带。SurfaceView 通常用 HWC 处理,TextureView 用 setTransform()。 Scaling/Transform/Crop :通过 queueBuffer() 的元数据携带。SurfaceView 通常用 HWC 处理,TextureView 用 setTransform()。 卡住在 dequeue/queue 增加缓冲数(setBufferCount / setMaxDequeuedBufferCount); 开启 async 模式(允许丢旧帧保最新); 检查 Consumer 是否长期不 releaseBuffer()(例如合成阻塞、GL 卡帧)。 卡住在 dequeue/queue 增加缓冲数(setBufferCount / setMaxDequeuedBufferCount); 开启 async 模式(允许丢旧帧保最新); 检查 Consumer 是否长期不 releaseBuffer()(例如合成阻塞、GL 卡帧)。 频繁重分配 (alloc churn) 避免每帧改分辨率/格式; 先 detach 再统一 setBuffersGeometry ,或在场景切换时一次性变更。 频繁重分配 (alloc churn) 避免每帧改分辨率/格式; 先 detach 再统一 setBuffersGeometry ,或在场景切换时一次性变更。 黑屏/花屏/绿屏 TextureView 某些机型/解码器组合不稳 → 验证改用 SurfaceView; 确认 setSurface(null) 的时序,销毁前解绑定; 检查颜色空间/stride 对齐问题(尤其自研 GL)。 TextureView 某些机型/解码器组合不稳 → 验证改用 SurfaceView; 确认 setSurface(null) 的时序,销毁前解绑定; 检查颜色空间/stride 对齐问题(尤其自研 GL)。 高延迟 三缓冲 + async;降低渲染分辨率;减少在应用进程的二次合成(TextureView->考虑 SurfaceView)。 三缓冲 + async;降低渲染分辨率;减少在应用进程的二次合成(TextureView->考虑 SurfaceView)。 截图/录屏差异 SurfaceView 不参与应用内 View.draw() 截屏;系统录屏一般可见;DRM 可 setSecure(true) 禁止截屏。 SurfaceView 不参与应用内 View.draw() 截屏;系统录屏一般可见;DRM 可 setSecure(true) 禁止截屏。 adb shell dumpsys SurfaceFlinger --list / --displays / --latency:看图层、刷新、合成信息。 Systrace/Perfetto :Graphics、View、Sched、Freq 轨道看 queue/dequeue、合成耗时与丢帧。 dumpsys gfxinfo:帧时间分布、Janky 统计。 开启 debug.sf.* 系列系统属性(开发版 ROM)可见更详细日志(谨慎)。 9. 最小落地骨架(Player → Surface) 若用 EGL/GL 自绘:以 holder.surface 或 Surface(st) 创建 EGL window surface,再 eglSwapBuffers()。 BufferQueue 是 Surface 的"帧中转站":Producer 通过 dequeue→渲染→queue 写帧;Consumer acquire→显示→release 读帧。 在 SurfaceView ,帧被 SurfaceFlinger 直接合成;在 TextureView ,帧先变成纹理参与应用内合成。理解这一点,基本就能把"卡顿/黑屏/延迟"问题对症下药。
📥 下载地址(文章结尾)
装机神器,可安装一切系统,纯净版,英文版,繁体版 ,精简版,原版等等等