EGL 上下文在这里并不真正相关。您的战斗是与 SurfaceFlinger 和视图系统进行的。
如果你跑adb shell dumpsys SurfaceFlinger
您可以看到系统合成器知道的所有层的完整列表。如果您正在播放 320x240 的视频SurfaceView
,它看起来像这样(为简洁起见,删除了几列和许多其他内容):
type | source crop | frame name
------------+-----------------------------------+--------------------------------
HWC | [ 0.0, 0.0, 320.0, 240.0] | [ 48, 411, 1032, 1149] SurfaceView
HWC | [ 0.0, 75.0, 1080.0, 1776.0] | [ 0, 75, 1080, 1776] com.android.grafika/com.android.grafika.PlayMovieSurfaceActivity
HWC | [ 0.0, 0.0, 1080.0, 75.0] | [ 0, 0, 1080, 75] StatusBar
HWC | [ 0.0, 0.0, 1080.0, 144.0] | [ 0, 1776, 1080, 1920] NavigationBar
FB TARGET | [ 0.0, 0.0, 1080.0, 1920.0] | [ 0, 0, 1080, 1920] HWC_FRAMEBUFFER_TARGET
这些层按 Z 顺序排列,从后到前。 SurfaceView 的表面层位于后面,应用程序 UI 层位于其之上,系统状态 + 导航栏位于所有内容之上。
应用程序视图层次结构中的所有内容都呈现在单个层上。包括TextureView
。您无法控制其相对于其他硬件合成层的 Z 顺序。
SurfaceView
很奇特的是,视图部分只是一个透明的占位符,而真正的操作发生在那个单独的层上,你可以控制它的 Z 顺序(一点点)。您可以将其分为三个不同的级别:
- “媒体”(默认)
- “媒体覆盖”
- (应用程序用户界面在这里)
- “面板”(ZOrderOnTop)
所以你想做的就是把你的MediaCodec
默认层的输出,以及“媒体覆盖”层的 GLES 输出。你需要用SurfaceView
.
从这里很难提供更好的建议,因为您描述了尝试解决方案时遇到的问题,而不是您试图解决的问题(即您正在构建什么?),但我可以提供一些建议。
首先你can缩放 SurfaceView。如果您查看上面的 dumpsys 输出,您会注意到“SurfaceView”行的源裁剪矩形为 320x240(视频的大小),目标矩形为 984x738。这是来自格拉菲卡的 https://github.com/google/grafika“播放视频 (SurfaceView)”,它调整 SurfaceView 的大小以保留视频的 4:3 宽高比。 SurfaceFlinger 负责缩放内容以匹配视图。
其次,如果您不显示受 DRM 保护的视频内容,您可以将其发送至SurfaceTexture
当您渲染其他所有内容时,只需使用 GLES 渲染它即可。 (这正是TextureView
确实如此,这就是为什么它需要硬件加速。)参见例如Grafika 中的“连续捕捉”。
Update:可以在以下位置找到更长的描述Android系统级图形文档 http://source.android.com/devices/graphics/architecture.html.