Rozszerzenia do aparatu

Producenci urządzeń mogą udostępniać rozszerzenia, takie jak bokeh, tryb nocny i HDR, deweloperom zewnętrznym za pomocą interfejsu rozszerzeń aparatu udostępnianego przez bibliotekę OEM. Deweloperzy mogą używać interfejsu Camera2 Extensions APIinterfejsu CameraX Extensions API, aby uzyskać dostęp do rozszerzeń zaimplementowanych w bibliotece OEM.

Listę obsługiwanych rozszerzeń, która jest taka sama w przypadku interfejsów Camera2 i CameraX, znajdziesz w interfejsie CameraX Extensions API. Jeśli chcesz dodać rozszerzenie, zgłoś błąd za pomocą śledzika błędów.

Na tej stronie dowiesz się, jak zaimplementować i włączyć bibliotekę OEM na urządzeniach.

Architektura

Na poniższym diagramie przedstawiono architekturę interfejsu rozszerzeń aparatu (extensions-interface):Architektura

Rysunek 1. Schemat architektury rozszerzeń aparatu

Jak widać na diagramie, aby obsługiwać rozszerzenia aparatu, musisz zaimplementować extensions-interface udostępniony przez bibliotekę OEM. Biblioteka OEM umożliwia korzystanie z 2 interfejsów API: CameraX Extensions APICamera2 Extensions API, które są używane odpowiednio przez aplikacje CameraX i Camera2 do uzyskiwania dostępu do rozszerzeń dostawcy.

Implementowanie biblioteki dostawcy OEM

Aby zaimplementować bibliotekę OEM, skopiuj pliki camera-extensions-stub do projektu biblioteki systemowej. Te pliki definiują interfejs rozszerzeń kamery.

Pliki camera-extensions-stub są podzielone na te kategorie:

Niezbędne pliki interfejsu (nie modyfikuj)

  • PreviewExtenderImpl.java
  • ImageCaptureExtenderImpl.java
  • ExtenderStateListener.java
  • ProcessorImpl.java
  • PreviewImageProcessorImpl.java
  • CaptureProcessorImpl.java
  • CaptureStageImpl.java
  • RequestUpdateProcessorImpl.java
  • ProcessResultImpl.java
  • advanced/AdvancedExtenderImpl.java
  • advanced/Camera2OutputConfigImpl.java
  • advanced/Camera2SessionConfigImpl.java
  • advanced/ImageProcessorImpl.java
  • advanced/ImageReaderOutputConfigImpl.java
  • advanced/ImageReferenceImpl.java
  • advanced/MultiResolutionImageReaderOutputConfigImpl.java
  • advanced/OutputSurfaceImpl.java
  • advanced/RequestProcessorImpl.java
  • advanced/SessionProcessorImpl.java
  • advanced/SurfaceOutputConfigImpl.java

Wymagania dotyczące implementacji (dodanie implementacji)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Klasy rozszerzeń Bokeh (wdróż je, jeśli rozszerzenie Bokeh jest obsługiwane)

  • BokehImageCaptureExtenderImpl.java
  • BokehPreviewExtenderImpl.java
  • advanced/BokehAdvancedExtenderImpl.java

Klasy rozszerzające nocne (wdrożyć, jeśli rozszerzenie nocne jest obsługiwane)

  • NightImageCaptureExtenderImpl.java
  • NightPreviewExtenderImpl.java
  • advanced/NightAdvancedExtenderImpl.java

Klasy rozszerzaczy automatycznych (wdróż je, jeśli rozszerzanie automatyczne jest obsługiwane)

  • AutoImageCaptureExtenderImpl.java
  • AutoPreviewExtenderImpl.java
  • advanced/AutoAdvancedExtenderImpl.java

Klasy rozszerzeń HDR (wdrożyć, jeśli rozszerzenie HDR jest obsługiwane)

  • HdrImageCaptureExtenderImpl.java
  • HdrPreviewExtenderImpl.java
  • advanced/HdrAdvancedExtenderImpl.java

Klasy rozszerzeń retuszu twarzy (wdróż je, jeśli rozszerzenie retuszu twarzy jest obsługiwane)

  • BeautyImageCaptureExtenderImpl.java
  • BeautyPreviewExtenderImpl.java
  • advanced/BeautyAdvancedExtenderImpl.java

Programy narzędziowe (opcjonalnie, można je usunąć)

  • advanced/Camera2OutputConfigImplBuilder.java
  • advanced/Camera2SessionConfigImplBuilder.java

Nie musisz udostępniać implementacji dla każdego rozszerzenia. Jeśli nie chcesz stosować rozszerzenia, ustaw isExtensionAvailable() na false lub usuń odpowiednie klasy Extender. Interfejsy API rozszerzeń Camera2 i CameraX informują aplikację, że rozszerzenie jest niedostępne.

Zobaczmy, jak interfejsy API rozszerzeń Camera2 i CameraX współpracują z biblioteką dostawcy, aby włączyć rozszerzenie. Poniższy diagram przedstawia kompleksowy proces, w którym przykładowo użyto rozszerzenia Night:

Mainflow

Rysunek 2. Wdrożenie rozszerzenia nocnego

  1. Weryfikacja wersji:

    wywołania Camera2/X ExtensionVersionImpl.checkApiVersion(), aby zapewnić zgodność wersji extensions-interface implementowanej przez OEM-a z wersjami obsługiwanymi przez Camera2/X.

  2. Inicjowanie biblioteki dostawcy:

    InitializerImpl ma metodę init(), która inicjuje bibliotekę dostawcy. Camera2/X kończy inicjalizację przed dostępem do klas Extender.

  3. Tworzenie instancji klas Extender:

    Tworzy instancje klas Extendera dla rozszerzenia. Istnieją 2 typy rozszerzeń: podstawowe i zaawansowane. Musisz zaimplementować jeden typ rozszerzenia dla wszystkich rozszerzeń. Więcej informacji znajdziesz w artykule Urządzenie rozszerzające podstawowe i zaawansowane.

    Camera2/X tworzy instancje klas Extender i współdziała z nimi, aby pobierać informacje i włączać rozszerzenia. W przypadku danego rozszerzenia Camera2/X może tworzyć instancje klas Extendera wielokrotnie. Dlatego nie wykonuj skomplikowanych operacji inicjalizacji w konstruktorze ani w wywołaniu init(). Wykonuj ciężkie zadania tylko wtedy, gdy sesja aparatu ma się rozpocząć, na przykład gdy wywołana jest funkcja onInit() w rozszerzeniu podstawowym lub funkcja initSession() w rozszerzeniu zaawansowanym.

    W przypadku rozszerzenia Night instancjonowane są te klasy Extendera dla typu Basic Extender:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    W przypadku typu rozszerzenia Zaawansowany:

    • NightAdvancedExtenderImpl.java
  4. Sprawdzanie dostępności rozszerzenia:

    Przed włączeniem rozszerzenia isExtensionAvailable() sprawdza, czy rozszerzenie jest dostępne na określonym identyfikatorze kamery za pomocą instancji Extendera.

  5. Inicjowanie rozszerzacza za pomocą informacji o kamerze:

    Aplikacja Camera2/X wywołuje funkcję init() w instancji Extendera, przekazując jej identyfikator aparatu i wartość CameraCharacteristics.

  6. Informacje o zapytaniu:

    Wywołuje klasę Extender, aby pobrać informacje, takie jak obsługiwane rozdzielczości, nadal rejestrować szacowaną latencję i pobierać klucze żądań z rozszerzenia w ramach przygotowań do włączenia rozszerzenia.

  7. Włącz rozszerzenie na urządzeniu rozszerzającym:

    Klasa Extender udostępnia wszystkie interfejsy potrzebne do włączenia klasy. Oferuje on mechanizm, który umożliwia OEM-om implementację w systemie Camera2, np. wstrzykiwanie parametrów żądania rejestrowania lub włączanie procesora postprodukcyjnego.

    W przypadku typu rozszerzacza zaawansowanego aplikacja Camera2/X współpracuje z urządzeniem SessionProcessorImpl, aby umożliwić rozszerzenie. Camera2/X pobiera instancję SessionProcessorImpl, wywołując funkcję createSessionProcessor() w Extender.

W następnych sekcjach opisujemy proces tworzenia rozszerzenia.

Weryfikacja wersji

Podczas wczytywania biblioteki dostawcy OEM z urządzenia w czasie wykonywania Camera2/X sprawdza, czy biblioteka jest zgodna z wersją extensions-interface. extensions-interface używa wersji semantycznej, czyli GŁÓWNA.PODRZĘDNA.POPRAWKA, na przykład 1.1.0 lub 1.2.0. Podczas weryfikacji wersji używane są jednak tylko główne i podrzędne wersje.

Aby sprawdzić wersję, Camera2/X wywołuje ExtensionVersionImpl.checkApiVersion() z obsługiwaną wersją extensions-interface. Następnie Camera2/X używa wersji zgłoszonej przez bibliotekę OEM, aby określić, czy rozszerzenie może być włączone i jakie funkcje powinno wywoływać.

Zgodność z wersją główną

Jeśli główne wersje interfejsu rozszerzenia różnią się między Camera2/X a biblioteką dostawcy, rozszerzenie jest uważane za niezgodne i jest wyłączane.

Zgodność wsteczna

Dopóki wersja główna jest identyczna, Camera2/X zapewnia wsteczną zgodność z bibliotekami dostawców OEM utworzonymi w poprzednich wersjach extensions-interface. Jeśli na przykład Camera2/X obsługuje extensions-interface 1.3.0, biblioteki OEM, które implementowały wersje 1.0.0, 1.1.0 i 1.2.0, nadal są zgodne. Oznacza to też, że po zaimplementowaniu konkretnej wersji biblioteki dostawcy Camera2/X zadba o to, aby była ona zgodna wstecznie z przyszłymi wersjami extension-interface.

Zgodność wsteczna

Kompatybilność wsteczna z bibliotekami dostawców nowszych wersji extensions-interface zależy od Ciebie, jako producenta OEM. Jeśli do wdrożenia rozszerzeń potrzebujesz pewnych funkcji, możesz włączyć rozszerzenia, rozpoczynając od określonej wersji. W takim przypadku możesz zwrócić obsługiwaną wersję extensions-interface, jeśli wersja biblioteki Camera2/X spełnia wymagania. Jeśli wersje Camera2/X nie są obsługiwane, możesz zwrócić niezgodną wersję, na przykład 99.0.0, aby wyłączyć rozszerzenia.

Inicjowanie biblioteki dostawcy

Po zweryfikowaniu wersji extensions-interface zaimplementowanej przez bibliotekę OEM Camera2/X rozpoczyna proces inicjalizacji. Metoda InitializerImpl.init() sygnalizuje bibliotece OEM, że aplikacja próbuje używać rozszerzeń.

Aplikacja Camera2/X nie wykonuje żadnych innych wywołań biblioteki OEM (oprócz sprawdzania wersji) do momentu, gdy biblioteka OEM OnExtensionsInitializedCallback.onSuccess() powiadomi o zakończeniu inicjalizacji.

Musisz wdrożyć InitializerImpl w wersji extensions-interface 1.1.0. Camera2/X pomija krok inicjowania biblioteki, jeśli biblioteka dostawcy OEM implementuje wersję extensions-interface 1.0.0.

Podstawowy a zaawansowany przedłużacz

Istnieją 2 typy implementacji extensions-interface: rozszerzenie podstawowe i zaawansowane. Rozszerzenie zaawansowane jest obsługiwane od wersji extensions-interface 1.2.0.

W przypadku rozszerzeń, które przetwarzają obrazy w interfejsie HAL aparatu, zastosuj podstawowe rozszerzenie lub użyj procesora do dalszego przetwarzania, który potrafi przetwarzać strumienie YUV.

W przypadku rozszerzeń, które wymagają dostosowania konfiguracji strumienia Camera2, wdróż rozszerzenie zaawansowane i w razie potrzeby wysyłaj żądania przechwytywania.

Porównanie znajdziesz w tabeli poniżej:

Podstawowy przedłużacz Rozszerzenie zaawansowane
Konfiguracje transmisji Rozwiązano
Podgląd: PRIVATE lub YUV_420_888 (jeśli procesor istnieje)
Nagrywanie statyczne: JPEG lub YUV_420_888 (jeśli procesor istnieje)
Możliwość dostosowania przez producenta OEM.
Wysyłanie żądania przechwycenia Tylko Camera2/X może wysyłać żądania wykonania zdjęcia. Możesz ustawić parametry tych żądań. Gdy procesor jest udostępniany do przechwytywania obrazu, Camera2/X może wysyłać liczne żądania przechwytywania i przekazywać wszystkie obrazy oraz wyniki przechwytywania procesorowi. Do wykonania żądania przechwycenia RequestProcessorImpl i uzyskania wyników oraz obrazu udostępniamy instancję RequestProcessorImpl.

Aplikacja Camera2/X wywołuje startRepeatingstartCapture na urządzeniu SessionProcessorImpl, aby zasygnalizować OEM, że należy rozpocząć powtarzanie żądania podglądu i uruchomić sekwencję wykonywania zdjęć.

Przyciski w potoku przetwarzania zdjęć
  • onPresetSession zawiera parametry sesji.
  • onEnableSession wysyła pojedyncze żądanie zaraz po skonfigurowaniu CameraCaptureSession.
  • onDisableSession wysyła jedną prośbę przed zamknięciem CameraCaptureSession.
  • initSession inicjalizuje i zwraca spersonalizowaną konfigurację sesji camera2 do tworzenia sesji przechwytywania.
  • onCaptureSessionStart jest wywoływany zaraz po skonfigurowaniu CameraCaptureSession.
  • Funkcja onCaptureSessionEnd jest wywoływana, zanim funkcja CameraCaptureSession zostanie zamknięta.
Dostępne dla Rozszerzenia zaimplementowane w interfejsie HAL aparatu lub w procesorze, który przetwarza obrazy YUV.
  • W przypadku rozszerzeń ma implementacje oparte na Camera2.
  • Wymaga niestandardowej konfiguracji strumienia, np. strumienia RAW.
  • Wymaga sekwencji interakcji.
Obsługiwana wersja interfejsu API Rozszerzenia Camera2: Android 13 lub nowszy
Rozszerzenia CameraX: camera-extensions1.1.0 lub nowsze
Rozszerzenia Camera2: Android 12L lub nowszy
Rozszerzenia CameraX: camera-extensions 1.2.0-alpha03 lub nowsze

Sekwencje w aplikacji

W tabeli poniżej przedstawiono 3 typy procesów w aplikacji i odpowiadające im wywołania interfejsu API rozszerzeń aparatu. Aplikacje Camera2/X udostępniają te interfejsy API, ale aby obsługiwać te przepływy danych, musisz prawidłowo zaimplementować bibliotekę dostawcy. Opisujemy to bardziej szczegółowo w następnej sekcji.

Rozszerzenia Camera2 Rozszerzenia CameraX
Dostępność rozszerzeń zapytań CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
Informacje o zapytaniu CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

CameraX zajmuje się pozostałymi informacjami w bibliotece.

Podgląd i robienie zdjęć przy włączonej rozszerzonej rzeczywistości CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...)

Podstawowy przedłużacz

Interfejs podstawowego rozszerzenia zapewnia punkty podłączenia w kilku miejscach w przepływie danych z kamery. Każdy typ rozszerzenia ma odpowiadające mu klasy rozszerzeń, które muszą być zaimplementowane przez producentów OEM.

W tabeli poniżej podano klasy rozszerzeń, które muszą być zaimplementowane przez OEM-ów w przypadku każdego rozszerzenia:

Klasy rozszerzeń do wdrożenia
Noc NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Auto AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

Retusz twarzy BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

W tym przykładzie używamy obiektów zastępczych PreviewExtenderImplImageCaptureExtenderImpl. Zastąp je nazwami rzeczywistych plików, które implementujesz.

Podstawowy rozszerzacz ma te możliwości:

  • Wstrzyknij parametry sesji podczas konfigurowania CameraCaptureSession ( onPresetSession).
  • Informować o rozpoczęciu i zamknięciu sesji rejestrowania oraz wysyłać pojedyncze żądanie, aby powiadomić HAL o zwróconych parametrach (onEnableSession, onDisableSession).
  • Wstrzyknij parametry rejestracji do zapytania (PreviewExtenderImpl.getCaptureStage, ImageCaptureExtenderImpl.getCaptureStages).
  • Dodaj procesory do podglądu i przechwytywania zdjęć, które mogą przetwarzać strumień YUV_420_888.

Zobaczmy, jak Camera2/X wywołuje extensions-interface, aby uzyskać 3 wymienione powyżej przepływy aplikacji.

Proces w aplikacji 1. Sprawdzanie dostępności rozszerzenia

BasicExtenderAppFlow1

Rysunek 3. Schemat działania aplikacji 1 w przypadku rozszerzenia podstawowego

W tym procesie Camera2/X bezpośrednio wywołuje metodę isExtensionAvailable() zarówno w przypadku PreviewExtenderImpl, jak i ImageCaptureExtenderImpl bez wywoływania init(). Aby włączyć rozszerzenia, obie klasy Extender muszą zwracać true.

Często jest to pierwszy krok, który aplikacje wykonują, aby sprawdzić, czy dany typ rozszerzenia jest obsługiwany przez dany identyfikator kamery przed włączeniem rozszerzenia. Dzieje się tak, ponieważ niektóre rozszerzenia są obsługiwane tylko w przypadku niektórych identyfikatorów kamery.

Proces w aplikacji 2. Informacje o zapytaniach

BasicExtenderAppFlow2

Rysunek 4. Proces w aplikacji 2 w przypadku podstawowego rozszerzenia

Po ustaleniu, czy rozszerzenie jest dostępne, aplikacje powinny zapytać o te informacje, zanim włączą rozszerzenie.

  • Zakres opóźnienia rejestrowania zdjęć: ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange zwraca zakres opóźnienia rejestrowania w aplikacji, aby umożliwić jej ocenę, czy w danym scenariuszu warto włączyć rozszerzenie.

  • Obsługiwane rozmiary podglądu i powierzchni do rejestrowania: ImageCaptureExtenderImpl.getSupportedResolutionsPreviewExtenderImpl.getSupportedResolutions zwracają listę formatów i rozmiarów obrazów obsługiwanych przez format i rozmiar powierzchni.

  • Obsługiwane klucze żądania i wyniku: Camera2/X wywołuje te metody, aby pobrać obsługiwane klucze żądania i wyniku z Twojej implementacji:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Przed wysłaniem zapytania o dodatkowe informacje Camera2/X zawsze wywołuje funkcję init() w tych klasach Extendera.

Proces w aplikacji 3: podgląd/przechwytywanie obrazu z włączonym rozszerzeniem (implementacja HAL)

BasicExtenderAppFlow3

Rysunek 5. Proces w aplikacji 3 w przypadku podstawowego rozszerzenia

Powyższy diagram przedstawia główny proces włączania podglądu i robienia zdjęć za pomocą rozszerzenia bez procesora. Oznacza to, że rozszerzenie jest przetwarzane przez HAL aparatu.

W tym procesie Camera2/X najpierw wywołuje init(), a potem onInit, co powoduje wyświetlenie powiadomienia o tym, że za chwilę rozpocznie się sesja aparatu ze wskazanymi rozszerzeniami. W funkcji onInit() możesz przeprowadzić skomplikowaną inicjalizację.

Podczas konfigurowania CameraCaptureSession Camera2/X wywołuje onPresetSession, aby uzyskać parametry sesji. Po skonfigurowaniu sesji rejestrowania Camera2/X wywołuje funkcję onEnableSession, zwracając wystąpienie CaptureStageImpl zawierające parametry rejestrowania. Aplikacja Camera2/X natychmiast wysyła pojedyncze żądanie z tymi parametrami, aby powiadomić HAL. Podobnie przed zamknięciem sesji rejestrowania Camera2/X wywołuje funkcję onDisableSession, a potem wysyła pojedyncze żądanie z zwróconymi parametrami rejestrowania.

Powtarzające się żądanie wywołane przez Camera2/X zawiera parametry żądania zwracane przez PreviewExtenderImpl.getCaptureStage(). Ponadto żądanie przechwycenia obrazu zawiera parametry zwrócone przez funkcję ImageCaptureExtenderImpl.getCaptureStages().

Na koniec Camera2/X wywołuje onDeInit() po zakończeniu sesji aparatu. Zasoby możesz zwolnić w onDeinit().

Procesor podglądu

Oprócz HAL aparatu możesz też wdrażać rozszerzenia w procesorze.

Aby określić typ procesora, użyj elementu PreviewExtenderImpl.getProcessorType w ten sposób:

  • PROCESSOR_TYPE_NONE: brak procesora. Obrazy są przetwarzane w aparacie HAL.

  • PROCESSOR_TYPE_REQUEST_UPDATE_ONLY: typ procesora umożliwia aktualizowanie powtarzających się żądań za pomocą nowych parametrów żądania przechwytywania na podstawie najnowszego TotalCaptureResult.

    Funkcja PreviewExtenderImpl.getProcessor musi zwracać instancję RequestUpdateProcessorImpl, która przetwarza instancję TotalCaptureResult i zwraca instancję CaptureStageImpl, aby zaktualizować powtarzającą się prośbę. Wartość PreviewExtenderImpl.getCaptureStage() powinna również odzwierciedlać wynik przetwarzania i zwracać najnowszą wartość CaptureStageImpl.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR: ten typ umożliwia implementację procesora do przetwarzania obrazów YUV_420_888 i zapisywania danych na powierzchni PRIVATE.

    W funkcji PreviewExtenderImpl.getProcessor musisz zaimplementować i zwrócić instancję PreviewImageProcessorImpl. Procesor jest odpowiedzialny za przetwarzanie obrazów wejściowych YUV_420_888. Powinien zapisać dane wyjściowe w formacie podglądu PRIVATE. Aplikacja Camera2/X używa powierzchni YUV_420_888 zamiast PRIVATE do konfigurowania CameraCaptureSession na potrzeby podglądu.

    Poniżej znajdziesz ilustrację przedstawiającą ten proces:

PreviewProcessor

Rysunek 6. Podgląd procesu z użyciem PreviewImageProcessorImpl

Interfejs PreviewImageProcessorImpl rozszerza ProcessImpl i zawiera 3 ważne metody:

  • onOutputSurface(Surface surface, int imageFormat) określa powierzchnię wyjściową dla procesora. W przypadku PreviewImageProcessorImpl wartość imageFormat to liczba pikseli, na przykład PixelFormat.RGBA_8888.

  • onResolutionUpdate(Size size) ustawia rozmiar obrazu wejściowego.

  • onImageFormatUpdate(int imageFormat) ustawia format obrazu wejściowego. Obecnie można ustawić tylko YUV_420_888.

Procesor do przechwytywania obrazu

W przypadku przechwytywania statycznych obrazów możesz zaimplementować procesor, zwracając instancję CaptureProcessorImpl za pomocą ImageCaptureExtenderImpl.getCaptureProcessor. Procesor jest odpowiedzialny za przetworzenie listy zarejestrowanych obrazów YUV_420_888 i wystąpieni TotalCaptureResult oraz zapisanie danych wyjściowych na powierzchni YUV_420_888.

Zanim wyślesz prośbę o przechwycenie obrazu, możesz założyć, że podgląd jest włączony i działa.

Proces ten przedstawia diagram poniżej:

CaptureProcessor

Rysunek 7. Nadal rejestrowanie ścieżki za pomocą CaptureProcessorImpl

  1. Camera2/X używa powierzchni w formacie YUV_420_888 do konfigurowania sesji rejestrowania zdjęć. Aparat2/X przygotowuje CaptureProcessorImpl, wywołując:

    • CaptureProcessorImpl.onImageFormatUpdate() z YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() z rozmiarem obrazu wejściowego.
    • CaptureProcessorImpl.onOutputSurface() z wyjściem na powierzchnię YUV_420_888.
  2. ImageCaptureExtenderImpl.getCaptureStages zwraca listę CaptureStageImpl, w której każdy element jest powiązany z instancją CaptureRequest z parametrami przechwytywania, które są wysyłane przez Camera2/X. Jeśli na przykład zwraca listę 3 instancji CaptureStageImpl, Camera2/X wysyła 3 żądania rejestrowania z odpowiednimi parametrami rejestrowania za pomocą interfejsu captureBurstAPI.

  3. Otrzymane obrazy i instancje TotalCaptureResult są grupowane i przesyłane do usługi CaptureProcessorImpl w celu przetworzenia.

  4. CaptureProcessorImpl zapisuje wynikowy obraz (w formacie YUV_420_888) na wyjściowej powierzchni określonej przez wywołanie onOutputSurface(). W razie potrzeby aplikacja Camera2/X konwertuje je na obrazy JPEG.

Obsługa kluczy i wyników żądań rejestrowania

Oprócz podglądu i przechwytywania aparatu aplikacje mogą ustawiać zoom, parametry lampy błyskowej lub aktywować funkcję „dotknij, aby wyostrzyć”. Te parametry mogą być niezgodne z implementacją rozszerzenia.

Aby umożliwić Ci udostępnianie parametrów obsługiwanych przez Twoją implementację, do wersji extensions-interface 1.3.0 dodano te metody:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() zwraca klucze żądań rejestrowania obsługiwane przez Twoją implementację.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() zwraca klucze efektów przechwycenia zawarte w efekcie przechwycenia.

Jeśli HAL kamery przetwarza rozszerzenie, Camera2/X pobiera wyniki przechwytywania w CameraCaptureSession.CaptureCallback. Jeśli jednak procesor jest zaimplementowany, Camera2/X pobiera wyniki przechwytywania w ProcessResultImpl, które są przekazywane do metody process()PreviewImageProcessorImplCaptureProcessorImpl. Ponosisz odpowiedzialność za zgłoszenie wyniku przechwycenia za pomocą ProcessResultImpl do Camera2/X.

Poniżej znajdziesz definicję interfejsu CaptureProcessorImpl. W wersji extensions-interface 1.3.0 lub nowszej wywoływana jest druga funkcja process():

Interface CaptureProcessorImpl extends ProcessorImpl {
    // invoked when extensions-interface version < 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
    // invoked when extensions-interface version >= 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
            ProcessResultImpl resultCallback, Executor executor);
}

W przypadku typowych operacji na aparacie, takich jak zoom, naciskanie, aby ustawić ostrość, lampa błyskowa i kompensacja ekspozycji, zalecamy obsługę tych kluczy zarówno w ramach żądania rejestrowania, jak i w ramach wyniku rejestrowania:

  • Powiększenie:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Focus-by-touch:
    • CaptureRequest#CONTROL_AF_MODE
    • CaptureRequest#CONTROL_AF_TRIGGER
    • CaptureRequest#CONTROL_AF_REGIONS
    • CaptureRequest#CONTROL_AE_REGIONS
    • CaptureRequest#CONTROL_AWB_REGIONS
  • Flash:
    • CaptureRequest#CONTROL_AE_MODE
    • CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
    • CaptureRequest#FLASH_MODE
  • Kompensacja ekspozycji:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

W przypadku rozszerzeń podstawowych, które implementują interfejs CameraX Extensions w wersji 1.2.0 lub starszej, interfejs CameraX Extensions obsługuje wszystkie wymienione powyżej klucze. W wersji extensions-interface 1.3.0 zarówno CameraX, jak i Camera2 uwzględniają zwracaną listę i obsługują tylko klucze na niej zawarte. Jeśli na przykład w wersji 1.3.0 zdecydujesz się zwrócić tylko CaptureRequest#CONTROL_ZOOM_RATIOCaptureRequest#SCALER_CROP_REGION, oznacza to, że aplikacja obsługuje tylko zoom, a dostępne nie są funkcje dotykania, aby ustawić ostrość, lampy błyskowej i kompensacji ekspozycji.

Rozszerzenie zaawansowane

Rozszerzenie zaawansowane to rodzaj implementacji przez dostawcę na podstawie interfejsu Camera2 API. Ten typ rozszerzenia został dodany w wersji extensions-interface 1.2.0. W zależności od producenta urządzenia rozszerzenia mogą być wdrażane na poziomie aplikacji. To zależy od tych czynników:

  • Konfiguracja niestandardowego strumienia: skonfiguruj niestandardowe strumienie, takie jak strumień RAW, lub skonfiguruj kilka strumieni dla różnych identyfikatorów fizycznych kamer.

  • Możliwość wysyłania żądań Camera2: obsługa skomplikowanej logiki interakcji, która może wysyłać żądania przechwytywania z parametrami na podstawie wyników poprzednich żądań.

Rozszerzenie zaawansowane udostępnia oprogramowanie opakowujące, czyli pośrednią warstwę, dzięki której możesz dostosowywać konfigurację strumienia i wysyłać żądania nagrywania na żądanie.

Pliki do wdrożenia

Aby przełączyć się na implementację rozszerzacza zaawansowanego, metoda isAdvancedExtenderImplemented()ExtensionVersionImpl musi zwracać true. W przypadku każdego typu rozszerzenia OEM musi zaimplementować odpowiednie klasy rozszerzeń. Pliki implementacji rozszerzenia zaawansowanego znajdują się w pakiecie advanced.

Klasy rozszerzeń do implementacji
Noc advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Auto advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Retusz twarzy advanced/BeautyAdvancedExtenderImpl.java

W tym przykładzie używamy zastępczego tekstu AdvancedExtenderImpl. Zastąp go nazwą pliku Extendera rozszerzenia, które wdrażasz.

Zobaczmy, jak Camera2/X wywołuje extensions-interface, aby uzyskać 3 przebiegi aplikacji.

Proces w aplikacji 1: sprawdzanie dostępności rozszerzeń

AdvancedAppFlow1

Rysunek 8. Proces instalacji aplikacji 1 w rozszerzeniu zaawansowanym

Najpierw aplikacja sprawdza, czy dane rozszerzenie jest obsługiwane.

Proces w aplikacji 2. Informacje o zapytaniach

AdvancedAppFlow2

Rysunek 9. Proces instalacji aplikacji 2 w przypadku rozszerzenia zaawansowanego

Po wywołaniu AdvancedExtenderImpl.init() aplikacja może wysłać zapytanie o te informacje z AdvancedExtenderImpl:

  • Szacowany czas oczekiwania na zrobienie zdjęcia: AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() zwraca zakres czasu oczekiwania na zrobienie zdjęcia w aplikacji, aby umożliwić ocenę, czy w danym scenariuszu warto włączyć rozszerzenie.

  • Obsługiwane rozdzielczości podglądu i fotografii:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() zwraca mapę formatu obrazu na listę rozmiarów obsługiwanych w przypadku formatu i rozmiaru powierzchni podglądu. Producenci OEM muszą obsługiwać co najmniej format PRIVATE.

    • AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() zwraca obsługiwane formaty i rozmiary powierzchni do przechwytywania zdjęć. Producenci OEM muszą obsługiwać formaty JPEGYUV_420_888.

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() zwraca obsługiwane rozmiary dodatkowego strumienia YUV_420_888 do analizy obrazu. Jeśli analiza obrazu nie obsługuje powierzchni YUV, funkcja getSupportedYuvAnalysisResolutions() powinna zwrócić null lub pustą listę.

  • Dostępne klucze żądań i wyników rejestrowania (dodane w extensions-interface 1.3.0): Camera2/X wywołuje te metody, aby pobrać obsługiwane klucze żądań i klucze wyników z Twojej implementacji:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Więcej informacji znajdziesz w artykule Klucze i wyniki żądań do zespołu pomocy.

Proces w aplikacji 3: podgląd/zapisywanie obrazu z włączonym rozszerzeniem

AdvancedAppFlow3

Rysunek 10. Proces instalacji aplikacji 3 w rozszerzeniu zaawansowanym

Powyższy diagram przedstawia główny proces uruchamiania podglądu i robienia zdjęć w przypadku typu rozszerzacza zaawansowanego. Omówmy wszystkie kroki.

  1. SessionProcessorImpl

    Podstawowa implementacja rozszerzenia zaawansowanego znajduje się w SessionProcessorImpl, która odpowiada za dostarczanie niestandardowej konfiguracji sesji i wysyłanie żądań przechwytywania, aby zainicjować podgląd i przechwytywanie. Funkcja AdvancedExtenderImpl.createSessionProcessor() jest wywoływana, aby zwrócić instancję SessionProcessorImpl.

  2. initSession

    SessionProcessorImpl.initSession() inicjuje sesję rozszerzenia. Tutaj przydzielasz zasoby i zwracasz konfigurację sesji na potrzeby przygotowywania CameraCaptureSession.

    W przypadku parametrów wejściowych Camera2/X określa konfiguracje powierzchni wyjściowej na potrzeby podglądu, przechwytywania obrazu i opcjonalnej analizy obrazu YUV. Ten parametr wyjściowy konfiguracja powierzchni (OutputSurfaceImpl) zawiera powierzchnię, rozmiar i format obrazu, które są pobierane za pomocą tych metod w AdvancedExtenderImpl:

    • getSupportedPreviewOutputResolutions()
    • getSupportedCaptureOutputResolutions()
    • getSupportedYuvAnalysisResolutions()

    Musisz zwrócić instancję Camera2SessionConfigImpl, która składa się z listy instancji Camera2OutputConfigImpl i parametrów sesji użytych do skonfigurowania CameraCaptureSession. Użytkownik jest odpowiedzialny za wyświetlanie prawidłowych obrazów z kamery na wyjściowych powierzchniach przekazanych przez Camera2/X. Oto kilka opcji włączania danych wyjściowych:

    • Przetwarzanie w interfejsie aparatu HAL: możesz bezpośrednio dodawać powierzchnie wyjściowe do CameraCaptureSession za pomocą implementacji SurfaceOutputConfigImpl. Skonfiguruje to podawaną powierzchnię wyjściową dla potoku przetwarzania aparatu i umożliwi procesowi HAL aparatu przetworzenie obrazu.
    • Przetwarzanie pośredniej powierzchni ImageReader (RAW, YUV itp.): dodaj pośrednie powierzchnie ImageReader do CameraCaptureSession za pomocą instancji ImageReaderOutputConfigImpl.

      Musisz przetworzyć obrazy pośrednie i zapisać wynikowy obraz na powierzchni wyjściowej.

    • Używanie udostępniania powierzchni w aplikacji Camera2: udostępnianie powierzchni innej aplikacji, dodając dowolny element Camera2OutputConfigImpl do metody getSurfaceSharingOutputConfigs() innej instancji Camera2OutputConfigImpl. Format i rozmiar powierzchni muszą być identyczne.

    Wszystkie elementy Camera2OutputConfigImpl, w tym SurfaceOutputConfigImplImageReaderOutputConfigImpl, muszą mieć unikalny identyfikator (getId()), który służy do określania docelowej powierzchni i pobierania obrazu z elementu ImageReaderOutputConfigImpl.

  3. onCaptureSessionStartRequestProcessorImpl

    Gdy CameraCaptureSession uruchamia się i wywołuje interfejs Camera framework, Camera2/X wywołuje SessionProcessorImpl.onCaptureSessionStart() za pomocą pakietu zadań Camera2 (Camera2 API) z opakowaniem RequestProcessImpl.onConfigured() Aplikacja Camera2/X implementuje interfejs RequestProcessImpl, który umożliwia wykonanie żądań wykonaniapobieranie zdjęć, jeśli używany jest interfejs ImageReaderOutputConfigImpl.

    Interfejsy API RequestProcessImpl są podobne do interfejsów API Camera2 CameraCaptureSession pod względem wykonywania żądań. Różnice:

    • Docelowa powierzchnia jest określana przez identyfikator instancji Camera2OutputConfigImpl.
    • Możliwość pobrania obrazu ImageReader.

    Aby zarejestrować instancję ImageProcessorImpl do odbierania obrazów, możesz wywołać funkcję RequestProcessorImpl.setImageProcessor() z określonym identyfikatorem Camera2OutputConfigImpl.

    Instancja RequestProcessImpl staje się nieprawidłowa po wywołaniu Camera2/XSessionProcessorImpl.onCaptureSessionEnd().

  4. Rozpocznij podgląd i zrób zdjęcie

    W ramach implementacji rozszerzenia zaawansowanego możesz wysyłać żądania przechwytywania za pomocą interfejsu RequestProcessorImpl. Aplikacja Camera2/X powiadomi Cię o tym, aby rozpocząć powtarzające się żądanie podglądu lub sekwencję zdjęć, odpowiednio wywołując SessionProcessorImpl#startRepeating lub SessionProcessorImpl#startCapture. Aby spełnić te żądania podglądu i zapisu, wyślij żądania przechwytywania.

    Aplikacja Camera2/X ustawia też parametry żądania przechwycenia za pomocą interfejsu SessionProcessorImpl#setParameters. Te parametry żądania (jeśli są obsługiwane) musisz ustawić zarówno w przypadku żądań powtarzających się, jak i pojedynczych.

    Musisz obsługiwać co najmniej CaptureRequest.JPEG_ORIENTATIONCaptureRequest.JPEG_QUALITY. extensions-interface 1.3.0 obsługuje klucze żądania i wyniku, które są dostępne za pomocą tych metod:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys()

    Gdy deweloperzy ustawiają klucze na liście getAvailableCaptureRequestKeys, musisz włączyć parametry i zadbać o to, aby wynik przechwytywania zawierał klucze z listy getAvailableCaptureResultKeys.

  5. startTrigger

    SessionProcessorImpl.startTrigger() jest wywoływany, aby uruchomić regułę, taką jak CaptureRequest.CONTROL_AF_TRIGGERCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Możesz zignorować klucze żądań przechwytywania, które nie były reklamowane w AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    Typ startTrigger() jest obsługiwany od wersji extensions-interface 1.3.0. Umożliwia aplikacjom implementowanie funkcji „dotknij, aby wyostrzyć” i migania za pomocą rozszerzeń.

  6. Czyszczenie danych

    Po zakończeniu sesji przechwytywania przed zamknięciem CameraCaptureSession wywoływana jest funkcja SessionProcessorImpl.onCaptureSessionEnd(). Po zamknięciu sesji przechwytywania deInitSession() wykonuje czyszczenie.

obsługa podglądu, przechwytywania obrazu i analizy obrazu;

Rozszerzenie należy zastosować zarówno do podglądu, jak i do przypadków użycia dotyczących nadal wykonywanych zdjęć. Jeśli jednak opóźnienie jest zbyt duże, aby można było płynnie wyświetlić podgląd, możesz zastosować rozszerzenie tylko do przechwytywania zdjęć.

W przypadku typu podstawowego rozszerzenia, niezależnie od włączenia rozszerzenia do podglądu, musisz zaimplementować zarówno ImageCaptureExtenderImpl, jak i PreviewExtenderImpl dla danego rozszerzenia. Aplikacja często używa też strumienia YUV do analizowania treści obrazu, np. do znajdowania kodów QR lub tekstu. Aby lepiej obsługiwać ten przypadek użycia, należy obsługiwać kombinację strumienia podglądu, strumienia obrazu stałego i strumienia YUV_420_888 w celu konfigurowania CameraCaptureSession. Oznacza to, że jeśli wdrożes przetwarzania, musisz obsługiwać kombinację 3 strumieni YUV_420_888.

W przypadku rozszerzenia zaawansowanego Camera2/X przekazuje 3 interfejsy wyjściowe do połączenia SessionProcessorImpl.initSession(). Te wyjścia są przeznaczone odpowiednio do podglądu, przechwytywania obrazu i analizy obrazu. Musisz się upewnić, że podgląd i wyjściowe powierzchnie podglądu wyświetlają prawidłowe dane wyjściowe. W przypadku powierzchni wyjściowej analizy obrazu upewnij się jednak, że działa ona tylko wtedy, gdy nie jest pusta. Jeśli Twoja implementacja nie obsługuje strumienia analizy obrazu, możesz zwrócić pustą listę w AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). Dzięki temu powierzchnia wyjściowa analizy obrazu jest zawsze pusta w elementach SessionProcessorImpl.initSession().

Obsługa rejestrowania filmów

Obecna architektura rozszerzenia aparatu obsługuje tylko przypadki użycia polegające na podglądzie i robieniu zdjęć. Nie obsługujemy włączania rozszerzenia na powierzchniach MediaCodec ani MediaRecorder do nagrywania filmów. Aplikacje mogą jednak nagrywać podgląd.

Trwają prace nad obsługą platform MediaCodecMediaRecorder.

Metadane dotyczące rozszerzenia

W Androidzie 14 i nowszych metadane dotyczące rozszerzeń umożliwiają klientom rozszerzeń aparatu ustawianie i odbieranie ustawień żądania rejestrowania i wyników dotyczących rozszerzenia. W szczególności klienci rozszerzenia kamery mogą używać parametru EXTENSION_STRENGTH żądania przechwycenia do kontrolowania siły rozszerzenia, a parametru EXTENSION_CURRENT_TYPE wyniku przechwycenia do wskazania włączonego typu rozszerzenia.

Przechwytywanie żądań

Parametr żądania EXTENSION_STRENGTH w żądaniu rejestrowania określa siłę efektu przetwarzania wtyczki. Odpowiednie wyniki przechwytywania zawierają domyślną wartość siły, jeśli parametr nie jest jawnie ustawiany przez klienta. Ten parametr można stosować w ten sposób w przypadku tych typów rozszerzeń:

  • BOKEH: określa stopień rozmycia.
  • HDRNIGHT: określają liczbę połączonych obrazów oraz jasność obrazu końcowego.
  • FACE_RETOUCH: określa stopień ulepszenia kosmetycznego i wygładzania skóry.

Obsługiwany zakres parametru EXTENSION_STRENGTH to 0100, gdzie 0 oznacza brak przetwarzania rozszerzenia lub proste przepuszczanie, a 100 – maksymalną moc rozszerzenia efektu przetwarzania.

Aby dodać obsługę EXTENSION_STRENGTH, użyj interfejsów API parametrów dostawcy wprowadzonych w wersji 1.3.0 interfejsu biblioteki rozszerzeń. Więcej informacji znajdziesz w sekcji getAvailableCaptureRequestKeys().

Wyniki rejestrowania

Wynik EXTENSION_CURRENT_TYPE pozwala implementacjom rozszerzeń informować klientów o aktywności typu rozszerzenia.

Rozszerzenia korzystające z typu AUTO dynamicznie przełączają się między typami rozszerzeń, takimi jak HDRNIGHT, w zależności od warunków w scenie. Aplikacje z rozszerzeniami aparatu mogą używać EXTENSION_CURRENT_TYPE do wyświetlania informacji o bieżącym rozszerzeniu wybranym przez rozszerzenie AUTO.

Przewidywana wartość opóźnienia w przypadku przechwytywania obrazu w czasie rzeczywistym

W Androidzie 14 i nowszych klienci rozszerzenia aparatu mogą wysyłać zapytania o szacowane opóźnienia w robieniu zdjęć w czasie rzeczywistym na podstawie warunków sceny i otoczenia za pomocą getRealtimeStillCaptureLatency(). Ta metoda zapewnia dokładniejsze szacunki niż metoda statyczna getEstimatedCaptureLatencyRangeMillis(). Na podstawie szacowanego opóźnienia aplikacje mogą pominąć przetwarzanie rozszerzenia lub wyświetlić komunikat informujący użytkowników o długotrwałej operacji.

CameraExtensionSession.StillCaptureLatency latency;

latency = extensionSession.getRealtimeStillCaptureLatency();

// The capture latency from ExtensionCaptureCallback#onCaptureStarted() until ExtensionCaptureCallback#onCaptureProcessStarted().

latency.getCaptureLatency();

// The processing latency from  ExtensionCaptureCallback#onCaptureProcessStarted() until  the processed frame returns to the client.

latency.getProcessingLatency();

Aby umożliwić szacowanie opóźnienia w przypadku ujęć statycznych w czasie rzeczywistym, wprowadź te rozwiązania:

Przechwytywanie wywołań zwrotnych dotyczących postępu przetwarzania

W Androidzie 14 i wyższych klienci rozszerzenia aparatu mogą otrzymywać wywołania zwrotne dotyczące postępu operacji przetwarzania zdjęć trwających długo. Aplikacje mogą wyświetlać użytkownikom bieżący postęp, aby poprawić ogólną wygodę użytkowników.

Aplikacje mogą używać tego kodu do zintegrowania tej funkcji:

import android.hardware.camera2.CameraExtensionSession.
ExtensionCaptureCallback;

{
…
  class AppCallbackImpl extends ExtensionCaptureCallback {
…
    @Override
    public void onCaptureProcessProgressed(
      @NonNull CameraExtensionSession session,
      @NonNull CaptureRequest request,
      @IntRange(from = 0, to = 100) int progress) {
      // Update app UI with current progress
    }
  }
…
}

Aby obsługiwać wywołania zwrotne dotyczące postępu przetwarzania obrazu, implementacja dostawcy rozszerzenia musi wywoływać te wywołania zwrotne z bieżącą wartością postępu:

Zapisanie widoku po obejrzeniu

W Androidzie 14 i nowszych rozszerzenia aparatu mogą dostarczać widok po zrobieniu zdjęcia (podgląd) za pomocą setPostviewOutputConfiguration. Aby zwiększyć wygodę użytkowników, aplikacje mogą wyświetlać obraz postview jako element zastępczy, gdy rozszerzenie ma wydłużony czas przetwarzania, a następnie zastąpić go obrazem końcowym, gdy będzie on dostępny. Aplikacje mogą konfigurować i wysyłać żądania przechwytywania po wyświetleniu za pomocą tego kodu referencyjnego:

{
…
if (!CameraExtensionCharacteristics.isPostviewAvailable()) {
    continue;
}
…
ExtensionSessionConfiguration extensionConfiguration = new
        ExtensionSessionConfiguration(
                CameraExtensionCharacteristics.EXTENSION_NIGHT,
                outputConfig,
                backgroundExecutor,
                extensionSessionStateCallback
    );

extensionConfiguration.setPostviewOutputConfiguration(
    postviewImageOutput);
…
CaptureRequest.Builder captureRequestBuilder =
    cameraDevice.createCaptureRequest(
        CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(stillImageReader.getSurface());
captureRequestBuilder.addTarget(postviewImageSurface);

CaptureRequest captureRequest = captureRequestBuilder.build();
…
}

Aby obsługiwać przechwytywanie obrazu po wyświetleniu, implementacja Twojego dostawcy musi uwzględniać te elementy:

Obsługa danych wyjściowych SurfaceView

W Androidzie 14 i nowszych klienci rozszerzenia aparatu mogą korzystać z ścieżek renderowania pod kątem mocy i wydajności, rejestrując instancjęSurfaceView do wyjścia podglądu w przypadku powtarzających się żądań.

Aby obsługiwać dane wyjściowe SurfaceView, implementacja rozszerzenia dostawcy musi umożliwiać przesyłanie strumieniowe i wyprowadzanie podglądu do instancji SurfaceView. Aby sprawdzić, czy jest to obsługiwane, uruchom moduł CTS SurfaceViewExtensionPreviewTest.java.

Typy sesji związanych z dostawcą

Ta funkcja umożliwia implementacjom rozszerzeń dostawcy wybranie typu sesji konkretnego dostawcy, który zostanie ustawiony w sesji wewnętrznego przechwytywania obrazu z kamery zamiast wartości domyślnej.

Funkcja działa wyłącznie w ramach frameworku i poziomu dostawcy oraz nie ma wpływu na interfejs API widoczny dla klienta/publiczny.

Aby wybrać typ sesji konkretnego dostawcy, w bibliotekach rozszerzeń zastosuj: * ExtenderStateListener.onSessionType() – w przypadku rozszerzeń podstawowych; * Camera2SessionConfigImpl.getSessionType() – w przypadku rozszerzeń zaawansowanych.

Historia wersji interfejsu rozszerzeń

W tabeli poniżej znajdziesz historię wersji interfejsu Rozszerzenia aparatu. Zawsze implementuj najnowszą wersję biblioteki dostawcy.

Wersja Dodane funkcje
1.0.0
  • Weryfikacja wersji
    • ExtensionVersionImpl
  • Podstawowy przedłużacz
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • Inicjowanie biblioteki
    • InitializerImpl
  • Wyświetlanie obsługiwanych rozdzielczości
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Uzyskaj szacowane opóźnienie rejestrowania
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Wyświetlanie obsługiwanych kluczy żądania przechwytywania/kluczy wyników
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeysgetAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeysgetAvailableCaptureResultKeys
    • Nowe połączenie process(), które zdobywa ProcessResultImplPreviewImageProcessorImplCaptureProcessorImpl
    • Prośba o pomoc dotycząca typu reguły
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Metadane dotyczące rozszerzenia
  • Przewidywania opóźnień w przypadku dynamicznego uchwycenia obrazu
  • Przechwytywanie wywołań zwrotnych dotyczących postępu przetwarzania
  • Zapisanie widoku po obejrzeniu
  • Obsługa danych wyjściowych SurfaceView
  • Typy sesji związanych z dostawcą

Implementacja referencyjna

frameworks/ex dostępne są te referencyjne implementacje biblioteki OEM:

  • advancedSample: podstawowa implementacja rozszerzenia zaawansowanego.

  • sample: podstawowa implementacja rozszerzenia podstawowego.

  • service_based_sample: implementacja pokazująca, jak hostować rozszerzenia aparatu w Service. Ta implementacja zawiera te komponenty:

    • oem_library: biblioteka OEM-owa rozszerzeń aparatu dla interfejsów API Camera2 i CameraX Extensions, która implementuje Extensions-Interface. Działa on jako przekaźnik, który przekierowuje wywołania z Extensions-Interface do usługi. Biblioteka ta zawiera też pliki AIDL i klasy opakowujące do komunikacji z usługą.

      Rozszerzenie zaawansowane jest domyślnie włączone. Aby włączyć rozszerzenie podstawowe, zmień wartość ExtensionsVersionImpl#isAdvancedExtenderImplemented na false.

    • extensions_service: przykładowa implementacja usługi rozszerzeń. Tutaj możesz dodać implementację. Interfejs do wdrożenia w usłudze jest podobny do Extensions-Interface. Na przykład implementacja funkcji IAdvancedExtenderImpl.Stub wykonuje te same operacje co AdvancedExtenderImpl. Aby można było dzielić na części obiekty ImageTotalCaptureResult, wymagane są obiekty ImageWrapperTotalCaptureResultWrapper.

Konfigurowanie biblioteki dostawcy na urządzeniu

Biblioteka OEM nie jest wbudowana w aplikację. Jest wczytywana z urządzenia w czasie działania przez Camera2/X. W CameraX tag <uses-library> deklaruje, że biblioteka androidx.camera.extensions.impl zdefiniowana w pliku AndroidManifest.xml biblioteki camera-extensions jest zależna od CameraX i musi być wczytana w czasie wykonywania. W ramach Camera2 framework wczytuje usługę rozszerzeń, która deklaruje, że <uses-library>wczytuje tę samą bibliotekę androidx.camera.extensions.impl w czasie wykonywania.

Dzięki temu aplikacje innych firm korzystające z rozszerzeń mogą automatycznie wczytywać bibliotekę dostawcy OEM. Biblioteka OEM jest oznaczona jako opcjonalna, aby aplikacje mogły działać na urządzeniach, na których nie ma tej biblioteki. Aplikacja Camera2/X obsługuje to zachowanie automatycznie, gdy próbuje użyć rozszerzenia aparatu, o ile producent urządzenia umieścił bibliotekę OEM na urządzeniu, aby aplikacja mogła ją wykryć.

Aby skonfigurować bibliotekę OEM na urządzeniu, wykonaj te czynności:

  1. Dodaj plik uprawnień, który jest wymagany przez tag <uses-library>, w tym formacie: /etc/permissions/ANY_FILENAME.xml. Na przykład: /etc/permissions/camera_extensions.xml. Pliki w tym katalogu zapewniają mapowanie biblioteki o nazwie podanej w pliku <uses-library> na rzeczywistą ścieżkę pliku na urządzeniu.
  2. Aby dodać wymagane informacje do pliku, skorzystaj z przykładu poniżej.

    • Wartość name musi być androidx.camera.extensions.impl, ponieważ jest to biblioteka wyszukiwana przez CameraX.
    • file to ścieżka bezwzględna do pliku zawierającego implementację rozszerzeń (na przykład /system/framework/androidx.camera.extensions.impl.jar).
    <?xml version="1.0" encoding="utf-8"?>
    <permissions>
        <library name="androidx.camera.extensions.impl"
                 file="OEM_IMPLEMENTED_JAR" />
    </permissions>
    

W Androidzie 12 lub nowszym właściwości ro.camerax.extensions.enabled na urządzeniach obsługujących rozszerzenia CameraX muszą mieć wartość true, co umożliwia sprawdzanie, czy urządzenie obsługuje rozszerzenia. Aby to zrobić, dodaj ten wiersz w pliku producenta urządzenia:

PRODUCT_VENDOR_PROPERTIES += \
    ro.camerax.extensions.enabled=true \

Weryfikacja

Aby przetestować implementację biblioteki OEM na etapie rozwoju, użyj przykładowej aplikacji androidx-main/camera/integration-tests/extensionstestapp/, która obsługuje różne rozszerzenia dostawców.

Po zakończeniu implementacji użyj narzędzia do sprawdzania rozszerzeń aparatu, aby uruchomić testy automatyczne i ręczne, które pozwolą sprawdzić, czy biblioteka dostawcy została prawidłowo zaimplementowana.

Tryb rozszerzonego sceny a rozszerzenia aparatu

W przypadku rozszerzenia bokeh oprócz ustawienia ekspozycji za pomocą rozszerzeń aparatu możesz ustawić ekspozycję za pomocą rozszerzonego trybu sceny, który jest włączany za pomocą klawisza CONTROL_EXTENDED_SCENE_MODE. Więcej informacji o wdrożeniu znajdziesz w artykule Bokeh w aparacie.

Rozszerzony tryb sceny ma mniej ograniczeń niż rozszerzenia aparatu w aplikacjach obsługujących API camera2. Możesz na przykład włączyć rozszerzony tryb sceny w zwykłej instancji CameraCaptureSession, która obsługuje elastyczne kombinacje strumieni i parametry żądania przechwytywania. Rozszerzenia kamery obsługują tylko określony zestaw typów strumieni i mają ograniczone możliwości obsługi parametrów żądania rejestrowania.

Wadą rozszerzonego trybu sceny jest to, że można go zaimplementować tylko w interfejsie HAL aparatu, co oznacza, że musi on zostać zweryfikowany pod kątem działania we wszystkich elementach sterujących dostępnych dla deweloperów aplikacji.

Zalecamy stosowanie efektu bokeh przy użyciu zarówno rozszerzonego trybu sceny, jak i rozszerzeń aparatu, ponieważ aplikacje mogą preferować używanie określonego interfejsu API do włączenia bokeh. Zalecamy najpierw użycie rozszerzonego trybu sceny, ponieważ jest to najbardziej elastyczny sposób włączenia rozszerzenia bokeh w aplikacjach. Następnie możesz zaimplementować interfejs rozszerzeń aparatu na podstawie rozszerzonego trybu sceny. Jeśli wdrożenie bokeh w interfejsie HAL aparatu jest trudne, np. dlatego, że wymaga użycia procesora podrzędnego działającego na poziomie aplikacji do przetwarzania obrazów, zalecamy wdrożenie rozszerzenia bokeh za pomocą interfejsu Camera Extensions.

Najczęstsze pytania

Czy istnieją jakieś ograniczenia dotyczące poziomów interfejsu API?

Tak. To zależy od zestawu funkcji interfejsu API Androida wymaganego przez implementację biblioteki dostawcy OEM. Na przykład tag ExtenderStateListener.onPresetSession() używa wywołania SessionConfiguration.setSessionParameters() do ustawienia podstawowego zestawu tagów. To wywołanie jest dostępne tylko w interfejsie API na poziomie 28 lub nowszym. Szczegółowe informacje o poszczególnych metodach interfejsu znajdziesz w dokumentacji interfejsu API.