Android Multiple Surfaceviews

Android Multiple SurfaceViews

It looks like you are not supposed to create multiple SurfaceViews on one Layout.
According to this two posts written by Android framework engineer:

The way surface view is implemented is that a separate surface is created and Z-ordered behind its containing window, and transparent pixels drawn into the rectangle where the SurfaceView is so you can see the surface behind. We never intended to allow for multiple surface view.

and

you should effectively think of SurfaceView as an overlay you embed inside your window,
giving you an area in which you can directly draw independently of the normal view update system.

So, what you can do, is use one SurfaceView to draw all the graphics you want.

Android: Is it possible to have two surfaceview on top of each other?

Yes, this is possible. You can add both SurfaceViews as children of a FrameLayout. You will also want to call setZOrderMediaOverlay on one or both of your SufaceViews in order to specify how they are layered.

Furthermore, this could be a graphic intensive algorithm you are describing. Consider adding the AndroidManifest.xml application attribute android:hardwareAccelerated="true".

Finally, just set up a custom OnTouchListener to handle drag events. Use MotionEvent.getRawX() and MotionEvent.getRawY() to get the touch point, and use this to manipulate the canvases.

Handling two surfaceViews

I want to display both the views simultaneously on the screen z ordered.

AFAIK, that is not supported by Android. Android cannot composite multiple SurfaceViews. It can handle a regular View (e.g., Button) on top of a SurfaceView, but not two SurfaceViews Z ordered.

I recommend redesigning your application to have a single SurfaceView at a time.

Android multiple surface views - clipping issue

Bear in mind that a SurfaceView has two parts, the Surface and the View, and that the Android graphics system uses multiple layers.

All of your Views live on a single layer, usually referred to simply as "the View UI layer". Views can be placed on top of or below each other because they're all being rendered into the same buffer of pixels.

Surfaces appear on their own layers. By default, the SurfaceView's Surface is below (behind) the View UI layer. The SurfaceView's View part is just a transparent rectangle that the View system uses for layout. If you draw on that View (by subclassing SurfaceView and overriding a draw method), you're rendering pixels that overlap the Surface, making them opaque. This is an easy way to mask the Surface.

Your mini-player Surface uses setZOrderOnTop(), which sets the layer for that SurfaceView's Surface to be on top (in front) of the View UI. This is handy if your Surface is partially transparent, as it lets you see the Views behind it. However, anything you draw on the SurfaceView's View will also appear behind it, so it will no longer work as a mask.

The trouble with what you're trying to do is that you want to have the lower Surface visible through the upper Surface at the corners. You can't simply mask those pixels off with another layer -- you need to make them transparent on the video playback layer itself. This is a bit tricky, as you will need to feed the video into a GLES texture and then render it.

See also the graphics architecture doc.

Using Multiple Surfaces Views For Optimization?

  1. If you're using postInvalidate(), you should be using a custom View, not a SurfaceView. The whole point of using a SurfaceView is to have a separate layer that is independent of the View UI. If you're overriding onDraw(), you're drawing on the View part, not the Surface part, and just wasting the Surface.

  2. All Views occupy a single layer, no matter how many you have. Each SurfaceView has a separate layer, so having a lot of them will become problematic. In practice you can have no more than three, because of Z-ordering limitations. (See the "multi-surface test" activity in Grafika for an example of three partially transparent SurfaceViews blended with the View UI.)

  3. If you can't render fast enough to maintain 60 fps, you need to consider changing the way you render. Custom Views and OpenGL ES take advantage of hardware acceleration. Canvas rendering onto a SurfaceView Surface does not. On the plus side, you can down-size a SurfaceView's Surface and let the hardware scale it back up; this lets you limit the number of pixels you have to draw each frame, regardless of the display's resolution. (Blog, demo.) If you have a lot of static elements, the best approach may be to render to an off-screen Bitmap, and then just blit the Bitmap every frame.

One approach that will be very fast is to render all of the static elements onto the View part of the SurfaceView, taking care to keep the background transparent, and then render the animated parts on the Surface with GLES. You could use a second SurfaceView, but that adds an additional composition layer, which will degrade system performance if you exceed the number of overlay planes supported by the hardware.

For a deeper understanding of the way Android graphics work, take a look at the graphics architecture doc.

Support for multiple active overlapping surface views in Android

I found it out myself. Call setZOrderOnTop(true) on the SurfaceView I want to have on top seems solve the problem

How to add multiple surfaces of SurfaceView after camera2 session created

This is not possible with the camera2 directly, for different output resolutions. If you need to change the resolution of an output, you have to create a new capture session with the new outputs you want.

If you want multiple SurfaceViews of the same size, you can use the surface sharing APIs added in API level 26 and later in OutputConfiguration (https://developer.android.com/reference/android/hardware/camera2/params/OutputConfiguration).

If that's not sufficient, the other option is to connect the camera to a SurfaceTexture with the maximum SurfaceView resolution you might want, and then render lower resolution outputs from that via OpenGL, creating EGL windows for each new SurfaceView you want to draw to. That's a lot of code needed to set up the EGL context and rendering, but should be fairly efficient.

Multiple android Surface consumers - video playback to two surfaceviews

I've resolved my issue by having multiple instances of MediaPlayer with same video file source. When doing basic player operations like pause/play/seek, I'm just doing them on every player.

capturing image of multiple surfaceviews

You can't read data back from a SurfaceView Surface. See e.g. this answer.

The way that you "capture" it is by rendering it to something you can read the pixels from. In your case, you'd grab a frame from the camera, render that to an offscreen pbuffer, then render the square with OpenGL ES onto the same pbuffer, and then grab that with glReadPixels(). Essentially you perform the Surface composition yourself.

Multiple videos on one Surface

No, that's not possible. You'll need to use multiple SurfaceTextures instead, one per video decoder, and render all the textures into one view using Open GL.

See https://source.android.com/devices/graphics/architecture.html for more explanations on how this works; in particular, each Surface can only have one producer and one consumer.



Related Topics



Leave a reply



Submit