[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# TextureView\n\nThe [TextureView](https://developer.android.com/reference/android/view/TextureView?hl=en) class is a view object that combines a view\nwith a SurfaceTexture.\n\nRendering with OpenGL ES\n------------------------\n\nA TextureView object wraps a SurfaceTexture, responding to callbacks and\nacquiring new buffers. When a TextureView acquires new buffers, a TextureView\nissues a view invalidate request and draws using the contents of the newest\nbuffer as its data source, rendering wherever and however the view state\nindicates it should.\n\n[OpenGL ES (GLES)](https://www.khronos.org/opengles/) *can*\nrender on a TextureView by passing the\nSurfaceTexture to the EGL creation call, but this creates a problem. When GLES\nrenders on a TextureView, BufferQueue producers and consumers are in the same\nthread, which can cause the buffer swap call to stall or fail. For example, if\na producer submits several buffers in quick succession from the UI thread, the\nEGL buffer swap call needs to dequeue a buffer from the BufferQueue. However,\nbecause the consumer and producer are on the same thread, there won't be any\nbuffers available and the swap call hangs or fails.\n\nTo ensure that the buffer swap doesn't stall, BufferQueue always needs a\nbuffer available to be dequeued. To implement this, BufferQueue discards the\ncontents of the previously acquired buffer when a new buffer is queued and\nplaces restrictions on minimum and maximum buffer counts to prevent a consumer\nfrom consuming all buffers at once.\n\nChoosing SurfaceView or TextureView\n-----------------------------------\n\n| **Note:** In API 24 and higher, it's recommended to implement SurfaceView instead of TextureView.\n\nSurfaceView and TextureView fill similar roles and are both citizens of the\nview hierarchy. However, SurfaceView and TextureView have different\nimplementations. A SurfaceView takes the same parameters as other views, but\nSurfaceView contents are transparent when rendered.\n\nA TextureView has better alpha and rotation handling than a SurfaceView, but\na SurfaceView has performance advantages when compositing UI elements layered\nover videos. When a client renders with a SurfaceView, the SurfaceView provides\nthe client with a separate composition layer. SurfaceFlinger composes the\nseparate layer as a hardware overlay if supported by the device. When a client\nrenders with a TextureView, the UI toolkit composites the TextureView's content\ninto the view hierarchy with the GPU. Updates to the content may cause other\nview elements to redraw, for example, if the other views are positioned on top\nof a TextureView. After view rendering completes, SurfaceFlinger composites the\napp UI layer and all other layers, so that every visible pixel is composited\ntwice.\n| **Note:** DRM-protected video can be presented only on an overlay plane. Video players that support protected content must be implemented with SurfaceView.\n\nCase Study: Grafika's Play Video\n--------------------------------\n\n[Grafika's Play Video](https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/PlayMovieActivity.java) includes a pair of video players, one\nimplemented with TextureView and one implemented with SurfaceView. The video\ndecoding portion of the activity sends frames from MediaCodec to a surface for\nboth TextureView and SurfaceView. The biggest difference between the\nimplementations are the steps required to present the correct aspect ratio.\n\nScaling SurfaceView requires a custom implementation of FrameLayout.\nWindowManager needs to send a new window position and new size values to\nSurfaceFlinger. Scaling a TextureView's SurfaceTexture requires configuring a\ntransformation matrix with `TextureView#setTransform()`.\n\nAfter presenting the correct aspect ratio, both implementations follow the\nsame pattern. When SurfaceView/TextureView creates the surface, the app code\nenables playback. When a user taps **play**, it starts a video\ndecoding thread, with the surface as the output target. After that, the app\ncode doesn't do anything---composition and display are handled by\nSurfaceFlinger (for the SurfaceView) or by the TextureView.\n\nCase Study: Grafika's Double Decode\n-----------------------------------\n\n[Grafika's Double Decode](https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/DoubleDecodeActivity.java) demonstrates manipulation of the\nSurfaceTexture inside a TextureView.\n\nGrafika's Double Decode uses a pair of TextureView objects to show two videos\nplaying side by side, simulating a video conferencing app. When the orientation\nof the screen changes and the activity restarts, the MediaCodec decoders don't\nstop, simulating playback of a real-time video stream. To improve efficiency,\nthe client should keep the surface alive. The surface is a handle to the producer\ninterface in the SurfaceTexture's BufferQueue. Because the TextureView manages\nthe SurfaceTexture, the client needs to keep the SurfaceTexture alive to keep\nthe surface alive.\n\nTo keep the SurfaceTexture alive, Grafika's Double Decode obtains references\nto SurfaceTextures from the TextureView objects and saves them in a static field.\nThen, Grafika's Double Decode returns `false` from\n`TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed()` to\nprevent the destruction of the SurfaceTexture. TextureView then passes a\nSurfaceTexture to `onSurfaceTextureDestroyed()` that can be\nmaintained across the activity configuration change, which the client passes to\nthe new TextureView through `setSurfaceTexture()`.\n\nSeparate threads drive each video decoder. Mediaserver sends buffers with\ndecoded output to the SurfaceTextures, the BufferQueue consumers. The\nTextureView objects perform rendering and execute on the UI thread.\n\nImplementing Grafika's Double Decode with SurfaceView is harder than\nimplementing with TextureView because SurfaceView objects destroy surfaces\nduring orientation changes. Additionally, using SurfaceView objects adds two\nlayers, which isn't ideal because of the limitations on the number of overlays\navailable on the hardware."]]