Z-order issue with MediaCodec and TextureView

你。 提交于 2019-12-06 05:52:48

EGL contexts aren't really relevant here. Your fight is with SurfaceFlinger and the view system.

If you run adb shell dumpsys SurfaceFlinger you can see something a complete list of all the layers that the system compositor knows about. If you're playing a 320x240 video in a SurfaceView, it looks something like this (several columns and lots of other stuff removed for brevity):

    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

The layers are in Z-order, from back to front. The SurfaceView's surface layer is at the back, the app UI layer is on top of that, and the system status + nav bars are above everything.

Everything in the app's View hierarchy is rendered on a single layer. That includes TextureView. You can't control its Z-ordering relative to other hardware-composited layers.

SurfaceViewis fancy in that the View portion is just a transparent placeholder, while the real action happens on that separate layer, whose Z-ordering you can control (a little). You can put it on three different levels:

  • "media" (the default)
  • "media overlay"
  • (app UI is here)
  • "panel" (ZOrderOnTop)

So what you want to do is put your MediaCodec output at the default layer, and your GLES output at the "media overlay" layer. You need to do both of these with a SurfaceView.

It's hard to provide better advice from here because you described the problems you're having with your attempted solution, rather than the problem you're trying to solve (i.e. what are you building?), but I can offer a couple of suggestions.

First, you can scale a SurfaceView. If you look at the dumpsys output above, you'll notice that the "SurfaceView" line has a source crop rect of 320x240 (the size of the video), and a destination rect that's 984x738. This is coming from Grafika's "Play video (SurfaceView)", which sized the SurfaceView to preserve the 4:3 aspect ratio of the video. SurfaceFlinger takes care of scaling the content to match the view.

Second, if you're not showing DRM-protected video content, you can send it to a SurfaceTexture and just render it with GLES when you're rendering everything else. (This is exactly what TextureView does, which is why it requires hardware acceleration.) See e.g. "Continuous capture" in Grafika.

Update: a much longer description can be found in the Android System-Level Graphics doc.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!