SurfaceTexture

SurfaceTexture to połączenie powierzchni i tekstury OpenGL ES (GLES). Instancje SurfaceTexture służą do udostępniania platform, które generują dane wyjściowe w postaci tekstur GLES.

SurfaceTexture zawiera instancję BufferQueue, w której aplikacje są konsumentem. Wywołanie zwrotne onFrameAvailable() powiadamia aplikacje, gdy producent umieszcza w kolejce nowy bufor. Następnie aplikacje wywołują funkcję updateTexImage(), która zwalnia wcześniej używany bufor, pobiera nowy bufor z kolejki i wykonuje wywołania EGL, aby udostępnić bufor GLES jako teksturę zewnętrzną.

Zewnętrzne tekstury GLES

Zewnętrzne tekstury GLES (GL_TEXTURE_EXTERNAL_OES) różnią się od standardowych tekstur GLES (GL_TEXTURE_2D) w następujący sposób:

  • Tekstury zewnętrzne renderują teksturowane wielokąty bezpośrednio na podstawie danych otrzymanych z BufferQueue.
  • Zewnętrzne renderery tekstur są konfigurowane inaczej niż standardowe renderery tekstur GLES.
  • Tekstury zewnętrzne nie mogą wykonywać wszystkich standardowych działań związanych z teksturami GLES.

Główną zaletą tekstur zewnętrznych jest możliwość renderowania bezpośrednio z danych BufferQueue. Instancje SurfaceTexture ustawiają flagi użycia przez konsumenta na GRALLOC_USAGE_HW_TEXTURE, gdy tworzą instancje BufferQueue dla tekstur zewnętrznych, aby sprawdzić, czy dane w buforze są rozpoznawane przez GLES.

Ponieważ instancje SurfaceTexture wchodzą w interakcję z kontekstem EGL, aplikacja może wywoływać ich metody tylko wtedy, gdy kontekst EGL, do którego należy tekstura, jest bieżący w wątku wywołującym. Więcej informacji znajdziesz w dokumentacji klasy SurfaceTexture.

Sygnatury czasowe i przekształcenia

Instancje SurfaceTexture obejmują metodę getTimeStamp(), która pobiera sygnaturę czasową, oraz metodę getTransformMatrix(), która pobiera macierz przekształcenia. Wywołanie funkcji updateTexImage() ustawia zarówno sygnaturę czasową, jak i macierz przekształcenia. Każdy przekazywany bufor BufferQueue zawiera parametry przekształcenia i sygnaturę czasową.

Parametry przekształcania są przydatne ze względu na wydajność. W niektórych przypadkach dane źródłowe mogą być wyświetlane w nieprawidłowej orientacji. Zamiast obracać dane przed wysłaniem ich do konsumenta, wyślij je w ich orientacji z transformacją, która je poprawi. Macierz przekształceń można połączyć z innymi przekształceniami, gdy dane są używane, co minimalizuje obciążenie.

Sygnatura czasowa jest przydatna w przypadku źródeł buforowania, które są zależne od czasu. Na przykład gdy setPreviewTexture() połączy interfejs producenta z wyjściem kamery, klatki z kamery mogą być używane do tworzenia filmu. Każda klatka musi mieć znacznik czasu prezentacji z momentu jej zarejestrowania, a nie z momentu, w którym aplikacja ją otrzymała. Kod kamery ustawia sygnaturę czasową dostarczaną z buforem, co zapewnia bardziej spójną serię sygnatur czasowych.

Studium przypadku: ciągłe rejestrowanie obrazów przez Grafika

Ciągłe przechwytywanie w Grafice polega na nagrywaniu klatek z kamery urządzenia i wyświetlaniu ich na ekranie. Aby nagrywać klatki, utwórz powierzchnię za pomocą metody createInputSurface() klasy MediaCodec i przekaż ją do kamery. Aby wyświetlić klatki, utwórz instancję SurfaceView i przekaż powierzchnię do setPreviewDisplay(). Pamiętaj, że nagrywanie klatek i wyświetlanie ich w tym samym czasie to bardziej złożony proces.

Aktywność ciągłe nagrywanie wyświetla obraz z kamery podczas nagrywania filmu. W tym przypadku zakodowane wideo jest zapisywane w buforze cyklicznym w pamięci, który można w dowolnym momencie zapisać na dysku.

Ten proces obejmuje 3 kolejki buforowe:

  • App – Aplikacja używa instancji SurfaceTexture do odbierania klatek z kamery i przekształcania ich w zewnętrzną teksturę GLES.
  • SurfaceFlinger – aplikacja deklaruje instancję SurfaceView do wyświetlania klatek.
  • MediaServer – skonfiguruj MediaCodec koder z powierzchnią wejściową, aby utworzyć film.

Na rysunku poniżej strzałki wskazują propagację danych z kamery. Wyświetlane są BufferQueue instancje z wizualnymi wskaźnikami odróżniającymi producentów (turkusowy) od konsumentów (zielony).

Grafika continuous
capture activity

Rysunek 1. Ciągłe rejestrowanie aktywności przez Grafika

Zakodowany film H.264 trafia do bufora cyklicznego w pamięci RAM w procesie aplikacji. Gdy użytkownik naciśnie przycisk nagrywania, klasa MediaMuxer zapisze zakodowany film w pliku MP4 na dysku.

Wszystkie instancje BufferQueue są obsługiwane w aplikacji za pomocą jednego kontekstu EGL, a operacje GLES są wykonywane w wątku interfejsu. Obsługa zakodowanych danych (zarządzanie buforem cyklicznym i zapisywanie go na dysku) odbywa się w osobnym wątku.

Gdy używasz klasy SurfaceView, wywołanie zwrotne surfaceCreated() tworzy instancje EGLContextEGLSurface dla wyświetlacza i enkodera wideo. Gdy pojawi się nowa klatka,SurfaceTexture wykonuje 4 działania:

  1. Pobiera ramkę.
  2. Udostępnia ramkę jako teksturę GLES.
  3. Renderuje ramkę za pomocą poleceń GLES.
  4. Przekazuje przekształcenie i sygnaturę czasową dla każdego wystąpienia elementu EGLSurface.

Wątek kodera pobiera zakodowane dane wyjściowe z MediaCodec i zapisuje je w pamięci.

Bezpieczne odtwarzanie filmów z teksturami

Android obsługuje przetwarzanie końcowe chronionych treści wideo na GPU. Dzięki temu aplikacje mogą używać GPU do złożonych, nieliniowych efektów wideo (np. zniekształceń), mapowania chronionych treści wideo na tekstury do wykorzystania w ogólnych scenach graficznych (np. przy użyciu GLES) oraz w rzeczywistości wirtualnej (VR).

Bezpieczne odtwarzanie filmów z teksturami

Rysunek 2. Bezpieczne odtwarzanie filmów z teksturami

Obsługa jest włączana za pomocą tych 2 rozszerzeń:

  • Rozszerzenie EGL – (EGL_EXT_protected_content) umożliwia tworzenie chronionych kontekstów i powierzchni GL, które mogą działać na chronionych treściach.
  • Rozszerzenie GLES – (GL_EXT_protected_textures) umożliwia oznaczanie tekstur jako chronionych, aby można było ich używać jako załączników tekstur bufora ramki.

Android umożliwia wysyłanie chronionych treści przez SurfaceTexture i ACodec(libstagefright.so), nawet jeśli powierzchnia okna nie jest w kolejce do SurfaceFlinger i zapewnia chronioną powierzchnię wideo do użycia w chronionym kontekście. W tym celu ustawiamy bit ochrony konsumenta (GRALLOC_USAGE_PROTECTED) w usługach utworzonych w chronionym kontekście (zweryfikowanym przez ACodec).

Bezpieczne odtwarzanie filmów z teksturami stanowi podstawę solidnego wdrożenia zarządzania prawami cyfrowymi (DRM) w środowisku OpenGL ES. Bez solidnego wdrożenia DRM, takiego jak Widevine Level 1, wielu dostawców treści nie zezwala na renderowanie swoich wartościowych treści w środowisku OpenGL ES, co uniemożliwia ważne zastosowania VR, takie jak oglądanie w VR treści chronionych DRM.

Projekt Android Open Source (AOSP) zawiera kod platformy do bezpiecznego odtwarzania filmów z teksturami. Obsługa sterowników zależy od producentów OEM. Producenci urządzeń muszą zaimplementować rozszerzenia EGL_EXT_protected_contentGL_EXT_protected_textures. Jeśli używasz własnej biblioteki kodeków (zamiast libstagefright), zwróć uwagę na zmiany w /frameworks/av/media/libstagefright/SurfaceUtils.cpp, które umożliwiają wysyłanie buforów oznaczonych jako GRALLOC_USAGE_PROTECTED do ANativeWindow (nawet jeśli ANativeWindow nie kolejkuje bezpośrednio do kompozytora okien), o ile bity użycia konsumenta zawierają GRALLOC_USAGE_PROTECTED. Szczegółową dokumentację dotyczącą wdrażania rozszerzeń znajdziesz w rejestrach Khronos ( EGL_EXT_protected_content) i ( GL_EXT_protected_textures).