TextureView

TextureView sınıfı, bir görünümü SurfaceTexture ile birleştiren bir görünüm nesnesidir.

OpenGL ES ile oluşturma

TextureView nesnesi, SurfaceTexture'ı sarmalar, geri çağırmalara yanıt verir ve yeni arabellekler edinir. TextureView yeni arabellekler edindiğinde TextureView, görünümü geçersiz kılma isteği gönderir ve en yeni arabelleğin içeriğini veri kaynağı olarak kullanarak çizim yapar. Böylece, görünüm durumu ne zaman ve nasıl gösterilmesi gerektiğini belirtirse o şekilde oluşturulur.

OpenGL ES (GLES), SurfaceTexture'ı EGL oluşturma çağrısına ileterek TextureView'da oluşturulabilir ancak bu durum sorun yaratır. GLES, TextureView'da oluşturulduğunda BufferQueue üreticileri ve tüketicileri aynı iş parçacığında yer alır. Bu durum, arabellek değişimi çağrısının durmasına veya başarısız olmasına neden olabilir. Örneğin, bir üretici UI iş parçacığından hızlı bir şekilde art arda birkaç arabellek gönderirse EGL arabellek değişimi çağrısının BufferQueue'dan bir arabellek çıkarması gerekir. Ancak tüketici ve üretici aynı iş parçacığında olduğundan arabellek olmaz ve takas çağrısı askıda kalır veya başarısız olur.

Arabellek değişimi duraklamalarını önlemek için BufferQueue'da her zaman sıradan çıkarma için kullanılabilir bir arabellek olması gerekir. Bunu yapmak için BufferQueue, yeni bir arabellek sıraya alındığında daha önce alınan arabelleğin içeriğini atar. Ayrıca, tüketicilerin tüm arabellekleri aynı anda tüketmesini önlemek için minimum ve maksimum arabellek sayılarıyla ilgili kısıtlamalar da getirir.

SurfaceView veya TextureView'ı seçme

SurfaceView ve TextureView benzer rolleri üstlenir ve her ikisi de görünüm hiyerarşisinin bir parçasıdır. Ancak SurfaceView ve TextureView'ın farklı uygulamaları vardır. SurfaceView, diğer görünümlerle aynı parametreleri alır ancak SurfaceView içerikleri oluşturulduğunda şeffaftır.

TextureView, SurfaceView'a kıyasla alfa ve döndürme işlemlerini daha iyi yönetir ancak SurfaceView, videoların üzerine katmanlanmış kullanıcı arayüzü öğelerini birleştirirken performans avantajları sunar. Bir istemci SurfaceView ile oluşturma yaptığında SurfaceView, istemciye ayrı bir birleştirme katmanı sağlar. SurfaceFlinger, cihaz tarafından destekleniyorsa ayrı katmanı donanım yerleşimi olarak oluşturur. Bir istemci TextureView ile oluşturduğunda, kullanıcı arayüzü araç seti TextureView'ın içeriğini GPU ile görünüm hiyerarşisine birleştirir. İçerikte yapılan güncellemeler, diğer görünüm öğelerinin yeniden çizilmesine neden olabilir. Örneğin, diğer görünümler bir TextureView'in üstüne yerleştirilmişse. Görünüm oluşturma işlemi tamamlandıktan sonra SurfaceFlinger, uygulama kullanıcı arayüzü katmanını ve diğer tüm katmanları birleştirir. Böylece, görünür her piksel iki kez birleştirilir.

Örnek Olay: Grafika's Play Video

Grafika'nın Play Video'sunda biri TextureView, diğeri SurfaceView ile uygulanmış iki video oynatıcı bulunur. Etkinliğin video kod çözme kısmı, hem TextureView hem de SurfaceView için MediaCodec'ten bir yüzeye kare gönderir. Uygulamalar arasındaki en büyük fark, doğru en boy oranını sunmak için gereken adımlardır.

SurfaceView'in ölçeklendirilmesi için FrameLayout'un özel olarak uygulanması gerekir. WindowManager, SurfaceFlinger'a yeni pencere konumu ve yeni boyut değerleri göndermelidir. Bir TextureView'ın SurfaceTexture'ını ölçeklendirmek için TextureView#setTransform() ile bir dönüşüm matrisi yapılandırmak gerekir.

Doğru en boy oranı sunulduktan sonra her iki uygulama da aynı deseni izler. SurfaceView/TextureView yüzeyi oluşturduğunda uygulama kodu oynatmayı etkinleştirir. Kullanıcı oynat'a dokunduğunda, yüzeyin çıkış hedefi olarak kullanıldığı bir video kod çözme iş parçacığı başlatılır. Bundan sonra uygulama kodu herhangi bir işlem yapmaz. Bileştirme ve görüntüleme işlemleri SurfaceFlinger (SurfaceView için) veya TextureView tarafından gerçekleştirilir.

Örnek olay: Grafika'nın Çift Kod Çözme

Grafika'nın Double Decode örneğinde, TextureView içindeki SurfaceTexture'ın nasıl değiştirildiği gösterilmektedir.

Grafika'nın Double Decode'u, yan yana oynatılan iki videoyu göstermek için bir çift TextureView nesnesi kullanır ve video konferans uygulamasını simüle eder. Ekranın yönü değiştiğinde ve etkinlik yeniden başladığında MediaCodec kod çözücüleri durmaz ve gerçek zamanlı bir video akışının oynatılmasını simüle eder. Verimliliği artırmak için istemci, yüzeyi etkin tutmalıdır. Yüzey, SurfaceTexture'ın BufferQueue'sindeki üretici arayüzünün tutma yeridir. TextureView, SurfaceTexture'ı yönettiğinden istemcinin yüzeyin etkin kalması için SurfaceTexture'ı etkin tutması gerekir.

Grafika'nın Double Decode özelliği, SurfaceTexture'ı etkin tutmak için TextureView nesnelerinden SurfaceTexture referansları alır ve bunları statik bir alana kaydeder. Ardından, Grafika's Double Decode, SurfaceTexture'ın bozulmasını önlemek için false değerini TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed() olarak döndürür. TextureView daha sonra onSurfaceTextureDestroyed()'ya bir SurfaceTexture iletir. Bu SurfaceTexture, etkinlik yapılandırması değişikliği boyunca korunabilir. İstemci, setSurfaceTexture() aracılığıyla bunu yeni TextureView'a iletir.

Her video kod çözücüyü ayrı iş parçacıkları çalıştırır. Mediaserver, çözülmüş çıkış içeren arabellekleri BufferQueue tüketicileri olan SurfaceTexture'lara gönderir. TextureView nesneleri oluşturma işlemini gerçekleştirir ve kullanıcı arayüzü iş parçacığında yürütülür.

SurfaceView ile Grafika'nın Double Decode özelliğini uygulamak, TextureView ile uygulamaktan daha zordur. Bunun nedeni, SurfaceView nesnelerinin yön değişiklikleri sırasında yüzeyleri yok etmesidir. Ayrıca, SurfaceView nesnelerinin kullanılması iki katman ekler. Bu durum, donanımda kullanılabilen yer paylaşımlarının sayısıyla ilgili sınırlamalar nedeniyle ideal değildir.