I need to be able to rotate a video on screen, so I created a custom TextureView which provides a convenience layer over a MediaPlayer similar to how the current implementation of VideoView does. This Android blog post says the following about TextureView:
Because a SurfaceView’s content does not live in the application’s window, it cannot be transformed (moved, scaled, rotated) efficiently. This makes it difficult to use a SurfaceView inside a ListView or a ScrollView. SurfaceView also cannot interact properly with some features of the UI toolkit such as fading edges or View.setAlpha().
To solve these problems, Android 4.0 introduces a new widget called TextureView that relies on the hardware accelerated 2D rendering pipeline and SurfaceTexture. TextureView offers the same capabilities as SurfaceView but, unlike SurfaceView, behaves as a regular view. You can for instance use a TextureView to display an OpenGL scene or a video stream. The TextureView itself can be animated, scrolled, etc.
However, it looks like the TextureView is struggling to play the videos. The target device I'm testing it on has a 1.2Ghz Rockchip RK3066 Dual Core CPU, a Quad core Mali-400 GPU (ARM) and 1GB RAM. The same code using VideoViews on this device performs fine, but the TextureViews either "stutter" while playing or don't show up at all (black box with white squares in the top left), depending on the specific device. The TextureViews perform fine on the emulator using the Intel-provided x86 "device".
Is this performance hit expected, or should I be looking elsewhere to find the problem? Thanks
Yes, it is expected with TextureView
. TextureView causes the video to go through normal view-compositing for rendering, unlike SurfaceView which is composited directly in the GPU (the decoding pipeline is rendering directly to the area of the screen where you place the SurfaceView
). While the TextureView
rendering is hardware-accelerated, it still is going through more steps for the additional flexibility, and there is a definite performance hit. Additionally, any code running on the UI-thread may affect TextureView
unlike SurfaceView
.
Additional information:
You can see this article
SurfaceView and TextureView fill similar roles, but have very different implementations. To decide which is best requires an understanding of the trade-offs. Because TextureView is a proper citizen of the View hierarchy, it behaves like any other View, and can overlap or be overlapped by other elements. You can perform arbitrary transformations and retrieve the contents as a bitmap with simple API calls.
The main strike against TextureView is the performance of the composition step. With SurfaceView, the content is written to a separate layer that SurfaceFlinger composites, ideally with an overlay. With TextureView, the View composition is always performed with GLES, and updates to its contents may cause other View elements to redraw as well (e.g. if they're positioned on top of the TextureView). After the View rendering completes, the app UI layer must then be composited with other layers by SurfaceFlinger, so you're effectively compositing every visible pixel twice. For a full-screen video player, or any other application that is effectively just UI elements layered on top of video, SurfaceView offers much better performance.