Rozszerzenia 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ę dostawcy OEM. Deweloperzy mogą używać interfejsu Camera2 Extensions APIinterfejsu CameraX Extensions API, aby uzyskać dostęp do rozszerzeń zaimplementowanych w bibliotece dostawcy OEM.

Listę obsługiwanych rozszerzeń, która jest taka sama w przypadku interfejsów Camera2 i CameraX, znajdziesz w artykule Interfejs API rozszerzeń CameraX. Jeśli chcesz dodać rozszerzenie, zgłoś błąd w narzędziu Issue Tracker.

Z tego artykułu dowiesz się, jak wdrożyć i włączyć bibliotekę dostawcy OEM na urządzeniach.

Architektura

Poniższy diagram przedstawia architekturę interfejsu Camera Extensions lub extensions-interface:Architektura

Rysunek 1. Schemat architektury rozszerzeń aparatu

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

Wdrażanie biblioteki dostawcy OEM

Aby wdrożyć bibliotekę dostawcy OEM, skopiuj pliki camera-extensions-stub do projektu biblioteki systemowej. Te pliki definiują interfejs Camera Extensions.

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

Obowiązkowe implementacje (dodaj swoją implementację)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

Klasy rozszerzające efekt bokeh (wdrażaj je, jeśli rozszerzenie Bokeh jest obsługiwane)

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

Klasy rozszerzające noc (wdrażaj je, jeśli rozszerzenie nocne jest obsługiwane)

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

Klasy automatycznego rozszerzania (wdrażaj je, jeśli obsługiwane jest automatyczne rozszerzanie)

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

Klasy rozszerzające HDR (wdrażaj je, jeśli rozszerzenie HDR jest obsługiwane)

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

Klasy rozszerzające retusz twarzy (wdrażaj je, jeśli rozszerzenie retuszu twarzy jest obsługiwane)

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

Narzędzia (opcjonalnie, można usunąć)

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

Nie musisz podawać implementacji dla każdego rozszerzenia. Jeśli nie wdrażasz rozszerzenia, ustaw isExtensionAvailable(), aby zwracać false, lub usuń odpowiednie klasy Extender. Interfejsy API Camera2 i CameraX Extensions informują aplikację, że rozszerzenie jest niedostępne.

Przyjrzyjmy się, jak interfejsy Camera2 i CameraX Extensions API współdziałają z biblioteką dostawcy, aby włączyć rozszerzenie. Poniższy diagram przedstawia cały proces na przykładzie rozszerzenia Night:

Mainflow

Rysunek 2. Wdrożenie rozszerzenia nocnego

  1. Weryfikacja wersji:

    Wywołania Camera2/X ExtensionVersionImpl.checkApiVersion() zapewniają, że wersja extensions-interface zaimplementowana przez producenta OEM jest zgodna z wersjami obsługiwanymi przez Camera2/X.

  2. Inicjowanie biblioteki dostawcy:

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

  3. Utwórz instancje klas Extender:

    Tworzy instancje klas Extender dla rozszerzenia. Istnieją 2 typy wzmacniaczy: podstawowy i zaawansowany. W przypadku wszystkich rozszerzeń musisz wdrożyć jeden typ Extender. Więcej informacji znajdziesz w artykule Podstawowy i zaawansowany wzmacniacz sygnału.

    Camera2/X tworzy instancje klas Extender i wchodzi z nimi w interakcje, aby pobierać informacje i włączać rozszerzenie. W przypadku danego rozszerzenia Camera2/X może wielokrotnie tworzyć instancje klas Extender. Dlatego nie wykonuj w konstruktorze ani w wywołaniu init() inicjowania wymagającego dużych zasobów. Wykonuj wymagające obliczenia tylko wtedy, gdy sesja aparatu ma się rozpocząć, np. gdy w przypadku podstawowego rozszerzenia wywoływana jest funkcja onInit() lub w przypadku zaawansowanego rozszerzenia wywoływana jest funkcja initSession().

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

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    W przypadku typu Advanced Extender:

    • NightAdvancedExtenderImpl.java
  4. Sprawdź dostępność rozszerzenia:

    Przed włączeniem rozszerzenia isExtensionAvailable() sprawdza, czy rozszerzenie jest dostępne w przypadku określonego identyfikatora aparatu za pomocą instancji Extender.

  5. Zainicjuj przedłużacz, podając informacje o kamerze:

    Wywołania Camera2/X init() w instancji Extender i przekazuje jej identyfikator aparatu oraz CameraCharacteristics.

  6. Informacje o zapytaniu:

    Wywołuje klasę Extender, aby pobrać informacje takie jak obsługiwane rozdzielczości, szacowane opóźnienie przechwytywania obrazu i klucze żądań z klasy Extender w ramach przygotowań do włączenia rozszerzenia.

  7. Włącz rozszerzenie na wzmacniaczu:

    Klasa Extender udostępnia wszystkie interfejsy potrzebne do włączenia klasy. Umożliwia on podłączenie implementacji OEM do potoku Camera2, np. wstrzykiwanie parametrów żądania przechwytywania lub włączanie postprocesora.

    W przypadku typu Advanced Extender Camera2/X wchodzi w interakcję z SessionProcessorImpl, aby włączyć rozszerzenie. Camera2/X pobiera instancję SessionProcessorImpl, wywołując createSessionProcessor() na Extenderze.

W kolejnych sekcjach znajdziesz bardziej szczegółowe informacje o procesie rozszerzania.

Weryfikacja wersji

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

Aby sprawdzić wersję, wywołaj Camera2/X z obsługiwaną wersją.ExtensionVersionImpl.checkApiVersion()extensions-interface Camera2/X używa następnie wersji podanej przez bibliotekę OEM, aby określić, czy rozszerzenie można włączyć 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, są one uznawane za niezgodne i rozszerzenie jest wyłączane.

Zgodność wsteczna

Dopóki wersja główna jest identyczna, Camera2/X zapewnia kompatybilność wsteczną z bibliotekami dostawców OEM utworzonymi w poprzednich wersjach extensions-interface. Jeśli na przykład Camera2/X obsługuje wersję 1.3.0, biblioteki dostawcy OEM, które implementują wersje 1.0.0, 1.1.0 i 1.2.0, nadal są zgodne.extensions-interface Oznacza to również, że po wdrożeniu określonej wersji biblioteki dostawcy interfejs Camera2/X zapewnia jej zgodność wsteczną z przyszłymi wersjami extension-interface.

Zgodność w przyszłości

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

Inicjowanie biblioteki dostawcy

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

Camera2/X nie wykonuje żadnych innych wywołań biblioteki OEM (poza sprawdzaniem wersji), dopóki biblioteka dostawcy OEM nie wywoła funkcji OnExtensionsInitializedCallback.onSuccess(), aby powiadomić o zakończeniu inicjowania.

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

Podstawowe i zaawansowane przedłużenie platformy

Istnieją 2 typy implementacji: extensions-interface podstawowy i zaawansowany. Wzmacniacz zaawansowany jest obsługiwany od wersji extensions-interface 1.2.0.

Zaimplementuj podstawowy moduł rozszerzający w przypadku rozszerzeń, które przetwarzają obrazy w warstwie HAL aparatu lub korzystają z procesora końcowego zdolnego do przetwarzania strumieni YUV.

Zaimplementuj zaawansowany moduł rozszerzający dla rozszerzeń, które muszą dostosowywać konfigurację strumienia Camera2 i w razie potrzeby wysyłać żądania przechwytywania.

Porównanie znajdziesz w tej tabeli:

Podstawowy przedłużacz Advanced Extender
Konfiguracje strumienia Stały
Podgląd: PRIVATE lub YUV_420_888 (jeśli jest procesor)
Zdjęcie: JPEG lub YUV_420_888 (jeśli jest procesor)
Możliwość dostosowania przez producenta OEM.
Wysyłam prośbę o zrzut Tylko Camera2/X może wysyłać żądania przechwytywania. Możesz ustawić parametry tych żądań. Gdy procesor jest dostępny do przechwytywania obrazów, interfejs Camera2/X może wysyłać wiele żądań przechwytywania i przesyłać wszystkie obrazy oraz wyniki przechwytywania do procesora. Otrzymasz instancję RequestProcessorImpl, która umożliwia wykonanie żądania przechwytywania camera2 i uzyskanie wyników oraz obrazu.

Camera2/X wywołuje funkcje startRepeatingstartCapture na interfejsie SessionProcessorImpl, aby poinformować producenta OEM o konieczności rozpoczęcia powtarzającego się żądania podglądu i sekwencji przechwytywania zdjęć.

Punkty zaczepienia w potoku kamery
  • onPresetSession udostępnia parametry sesji.
  • onEnableSession wysyła pojedyncze żądanie od razu po skonfigurowaniu CameraCaptureSession.
  • onDisableSession wysyła jedną prośbę przed zamknięciem CameraCaptureSession.
  • initSession inicjuje i zwraca dostosowaną konfigurację sesji camera2 do tworzenia sesji przechwytywania.
  • Funkcja onCaptureSessionStart jest wywoływana natychmiast po skonfigurowaniu funkcji CameraCaptureSession.
  • Funkcja onCaptureSessionEnd jest wywoływana przed zamknięciem funkcji CameraCaptureSession.
Odpowiednie dla Rozszerzenia zaimplementowane w warstwie HAL aparatu lub w procesorze, który przetwarza obrazy YUV.
  • Ma implementacje rozszerzeń oparte na Camera2.
  • Wymaga dostosowanej konfiguracji strumienia, np. strumienia RAW.
  • Wymaga sekwencji interaktywnego przechwytywania.
Obsługiwana wersja interfejsu API Rozszerzenia Camera2: Android 13 lub nowszy
Rozszerzenia CameraX: camera-extensions 1.1.0 lub nowszy
Rozszerzenia Camera2: Android 12L lub nowszy.
Rozszerzenia CameraX: camera-extensions 1.2.0-alpha03 lub nowsze.

Przepływy w aplikacji

W tabeli poniżej znajdziesz 3 typy przepływów aplikacji i odpowiadające im wywołania interfejsu Camera Extensions API. Interfejsy Camera2/X udostępniają te interfejsy API, ale aby obsługiwać te procesy, musisz prawidłowo wdrożyć bibliotekę dostawcy. Opisujemy to szczegółowo w dalszej części.

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

CameraX obsługuje pozostałe informacje w bibliotece.

Podgląd i robienie zdjęć z włączonym rozszerzeniem CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

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

Podstawowy przedłużacz

Interfejs Basic Extender udostępnia punkty zaczepienia w kilku miejscach potoku kamery. Każdy typ rozszerzenia ma odpowiednie klasy Extender, które producenci OEM muszą zaimplementować.

W tabeli poniżej znajdziesz klasy Extender, które producenci OEM muszą wdrożyć w przypadku każdego rozszerzenia:

Klasy rozszerzające 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 poniższym przykładzie używamy zmiennych PreviewExtenderImplImageCaptureExtenderImpl. Zastąp je nazwami rzeczywistych plików, które wdrażasz.

Podstawowy wzmacniacz ma te możliwości:

  • Podczas konfigurowania CameraCaptureSession ( onPresetSession) wstaw parametry sesji.
  • Powiadamiać Cię o zdarzeniach rozpoczęcia i zamknięcia sesji przechwytywania oraz wysyłać pojedyncze żądanie powiadomienia HAL ze zwróconymi parametrami (onEnableSession, onDisableSession).
  • Wstaw parametry przechwytywania do żądania (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 osiągnąć 3 wspomniane powyżej przepływy aplikacji.

Przepływ aplikacji 1. Sprawdzanie dostępności rozszerzenia

BasicExtenderAppFlow1

Rysunek 3. Przepływ aplikacji 1 na podstawowym wzmacniaczu

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ć wartość true.

Jest to często pierwszy krok, który aplikacje wykonują, aby sprawdzić, czy dany typ rozszerzenia jest obsługiwany w przypadku danego identyfikatora aparatu, zanim włączą rozszerzenie. Dzieje się tak, ponieważ niektóre rozszerzenia są obsługiwane tylko w przypadku określonych identyfikatorów aparatu.

Przepływ aplikacji 2. Informacje o zapytaniu

BasicExtenderAppFlow2

Rysunek 4. Przepływ aplikacji 2 na wzmacniaczu podstawowym

Po sprawdzeniu, czy rozszerzenie jest dostępne, aplikacje powinny przed jego włączeniem wysłać zapytanie o te informacje:

  • Still capture latency range:ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange zwraca zakres opóźnienia przechwytywania, aby aplikacja mogła ocenić, czy w bieżącej sytuacji warto włączyć rozszerzenie.

  • Obsługiwane rozmiary podglądu i obszaru przechwytywania: ImageCaptureExtenderImpl.getSupportedResolutionsPreviewExtenderImpl.getSupportedResolutions zwracają listę formatów obrazów i rozmiarów obsługiwanych w przypadku formatu i rozmiaru obszaru.

  • Obsługiwane klucze żądań i wyników: Camera2/X wywołuje te metody, aby pobrać z Twojej implementacji obsługiwane klucze żądań i wyników przechwytywania:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Camera2/X zawsze najpierw wywołuje init() w przypadku tych klas Extender, a potem wysyła zapytanie o więcej informacji.

Przebieg działania aplikacji 3. Podgląd/wykonywanie zdjęć z włączonym rozszerzeniem (implementacja HAL)

BasicExtenderAppFlow3

Rysunek 5. Przepływ aplikacji 3 na wzmacniaczu podstawowym

Powyższy diagram ilustruje 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 powiadamia Cię, że sesja aparatu ma się rozpocząć z określonymi rozszerzeniami. Inicjowanie wymagające dużego nakładu pracy możesz wykonać w onInit().

Podczas konfigurowania CameraCaptureSession interfejs Camera2/X wywołuje onPresetSession, aby uzyskać parametry sesji. Po prawidłowym skonfigurowaniu sesji przechwytywania interfejs Camera2/X wywołuje funkcję onEnableSession, która zwraca instancję CaptureStageImpl zawierającą parametry przechwytywania. Camera2/X natychmiast wysyła pojedyncze żądanie z tymi parametrami przechwytywania, aby powiadomić HAL. Podobnie przed zamknięciem sesji przechwytywania interfejs Camera2/X wywołuje funkcję onDisableSession, a następnie wysyła pojedyncze żądanie ze zwróconymi parametrami przechwytywania.

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

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

Procesor podglądu

Oprócz warstwy HAL aparatu możesz też zaimplementować rozszerzenia w procesorze.

Wdróż PreviewExtenderImpl.getProcessorType, aby określić typ procesora, jak opisano poniżej:

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

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

    PreviewExtenderImpl.getProcessor musi zwrócić instancję RequestUpdateProcessorImpl, która przetwarza instancję TotalCaptureResult i zwraca instancję CaptureStageImpl, aby zaktualizować powtarzające się żądanie. PreviewExtenderImpl.getCaptureStage() powinna też odzwierciedlać wynik przetwarzania i zwracać najnowszą wartość CaptureStageImpl.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR: ten typ umożliwia wdrożenie procesora do przetwarzania obrazów YUV_420_888 i zapisywania danych wyjściowych na powierzchni PRIVATE.

    Musisz zaimplementować i zwrócić instancję PreviewImageProcessorImplPreviewExtenderImpl.getProcessor. Procesor odpowiada za przetwarzanie YUV_420_888 obrazów wejściowych. Powinien zapisywać dane wyjściowe w formacie PRIVATE podglądu. Camera2/X używa YUV_420_888 zamiast PRIVATE do skonfigurowania CameraCaptureSession na potrzeby podglądu.

    Przepływ znajdziesz na poniższej ilustracji:

PreviewProcessor

Rysunek 6. Podgląd przepływu z PreviewImageProcessorImpl

Interfejs PreviewImageProcessorImpl rozszerza interfejs ProcessImpl i ma 3 ważne metody:

  • onOutputSurface(Surface surface, int imageFormat) określa powierzchnię wyjściową procesora. W przypadku PreviewImageProcessorImpl, imageFormat to format piksela, np. PixelFormat.RGBA_8888.

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

  • onImageFormatUpdate(int imageFormat) ustawia format obrazu wejściowego. Obecnie może to być tylko YUV_420_888.

Procesor rejestrowania obrazu

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

Przed wysłaniem prośby o zrobienie zdjęcia możesz założyć, że podgląd jest włączony i działa.

Zobacz schemat poniżej:

CaptureProcessor

Rysunek 7. Zrób zdjęcie w aplikacji CaptureProcessorImpl

  1. Camera2/X używa powierzchni w formacie YUV_420_888 do przechwytywania zdjęć, aby skonfigurować sesję przechwytywania. Camera2/X przygotowuje CaptureProcessorImpl, wywołując:

    • CaptureProcessorImpl.onImageFormatUpdate() z YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() z rozmiarem obrazu wejściowego.
    • CaptureProcessorImpl.onOutputSurface() z powierzchnią wyjściową.YUV_420_888
  2. ImageCaptureExtenderImpl.getCaptureStages zwraca listę CaptureStageImpl, gdzie każdy element jest mapowany na instancję CaptureRequest z parametrami przechwytywania wysyłanymi przez Camera2/X. Jeśli na przykład zwróci listę 3 instancjiCaptureStageImpl, Camera2/X wyśle 3 żądania przechwytywania z odpowiednimi parametrami przechwytywania za pomocą interfejsu APIcaptureBurst.

    CaptureStageImpl
  3. Otrzymane obrazy i instancje TotalCaptureResult są łączone w pakiety i wysyłane do CaptureProcessorImpl w celu przetworzenia.

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

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

Oprócz podglądu z aparatu i robienia zdjęć aplikacje mogą ustawiać zoom, parametry lampy błyskowej lub wywoływać ustawianie ostrości przez dotknięcie. Te parametry mogą być niezgodne z implementacją rozszerzenia.

Do wersji 1.3.0 interfejsu extensions-interface dodaliśmy te metody, aby umożliwić Ci udostępnianie parametrów obsługiwanych przez Twoją implementację:

  • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() zwraca klucze żądań przechwytywania obsługiwane przez Twoją implementację.
  • ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() zwraca klucze wyników przechwytywania zawarte w wyniku przechwytywania.

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. Odpowiadasz za zgłaszanie wyniku przechwytywania za pomocą ProcessResultImpl do Camera2/X.

Przykładem może być definicja interfejsu CaptureProcessorImpl poniżej. W wersji extensions-interface 1.3.0 lub nowszej wywoływane jest drugie wywołanie 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 funkcji aparatu, takich jak zoom, dotknij, aby ustawić ostrość, lampa błyskowa i kompensacja ekspozycji, zalecamy obsługę tych kluczy zarówno w przypadku żądania przechwytywania, jak i wyniku przechwytywania:

  • Powiększenie:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Dotknij, aby ustawić ostrość:
    • 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 podstawowych rozszerzeń, które implementują wersję 1.2.0 lub starszą, interfejs CameraX Extensions API wyraźnie obsługuje wszystkie powyższe klucze. W przypadku wersji extensions-interface 1.3.0 zarówno CameraX, jak i Camera2 uwzględniają zwróconą listę i obsługują tylko klucze, które się na niej znajdują. Jeśli na przykład w implementacji w wersji 1.3.0 zdecydujesz się zwracać tylko CaptureRequest#CONTROL_ZOOM_RATIOCaptureRequest#SCALER_CROP_REGION, oznacza to, że w aplikacji obsługiwane jest tylko powiększenie, a funkcje takie jak dotknij, aby ustawić ostrość, lampa błyskowa i kompensacja ekspozycji nie są dozwolone.

Advanced Extender

Zaawansowany moduł rozszerzający to typ implementacji dostawcy oparty na interfejsie Camera2 API. Ten typ Extender został dodany w wersji extensions-interface 1.2.0. W zależności od producenta urządzenia rozszerzenia mogą być zaimplementowane w warstwie aplikacji, co zależy od tych czynników:

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

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

Advanced Extender zapewnia otokę lub warstwę pośrednią, dzięki czemu możesz dostosowywać konfigurację strumienia i wysyłać żądania zapisu na żądanie.

Pliki do wdrożenia

Aby przełączyć się na implementację zaawansowanego rozszerzenia, metoda isAdvancedExtenderImplemented() w klasie ExtensionVersionImpl musi zwracać wartość true. W przypadku każdego typu rozszerzenia producenci OEM muszą wdrożyć odpowiednie klasy Extender. Pliki wdrożeniowe zaawansowanego rozszerzenia znajdują się w pakiecie advanced.

Klasy rozszerzające do wdrożenia
Noc advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Auto advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
Retusz twarzy advanced/BeautyAdvancedExtenderImpl.java

W poniższym przykładzie używamy symbolu AdvancedExtenderImpl jako obiektu zastępczego. Zastąp go nazwą pliku Extender dla wdrażanego rozszerzenia.

Zobaczmy, jak Camera2/X wywołuje extensions-interface, aby osiągnąć 3 ścieżki aplikacji.

Przepływ aplikacji 1. Sprawdzanie dostępności rozszerzeń

AdvancedAppFlow1

Rysunek 8. Przepływ 1 w aplikacji na urządzeniu Advanced Extender

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

Przepływ aplikacji 2. Informacje o zapytaniu

AdvancedAppFlow2

Rysunek 9. Przepływ aplikacji 2 na zaawansowanym wzmacniaczu

Po wywołaniu funkcji AdvancedExtenderImpl.init() aplikacja może wysyłać zapytania o te informacje na temat AdvancedExtenderImpl:

  • Szacowany czas oczekiwania na zrobienie zdjęcia: AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() zwraca zakres czasu oczekiwania na zrobienie zdjęcia, aby aplikacja mogła ocenić, czy w bieżącej sytuacji warto włączyć rozszerzenie.

  • Obsługiwane rozdzielczości podglądu i robienia zdjęć:

    • AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() zwraca mapę formatu obrazu do listy rozmiarów, które są obsługiwane 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ć dane wyjściowe w formatach JPEGYUV_420_888.

    • AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() zwraca obsługiwane rozmiary dodatkowego strumienia YUV_420_888 na potrzeby analizy obrazu. Jeśli powierzchnia YUV analizy obrazu nie jest obsługiwana, funkcja getSupportedYuvAnalysisResolutions() powinna zwrócić wartość null lub pustą listę.

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

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Więcej informacji znajdziesz w artykule Obsługa kluczy żądań przechwytywania i wyników.

Przepływ aplikacji 3: podgląd/zrzut z włączonym rozszerzeniem

AdvancedAppFlow3

Rysunek 10. Przepływ aplikacji 3 na zaawansowanym wzmacniaczu

Powyższy diagram przedstawia główny proces rozpoczynania podglądu i wykonywania zdjęć w przypadku zaawansowanego typu przedłużacza. Przeanalizujmy ten proces.

  1. instancja SessionProcessorImpl

    Główna implementacja zaawansowanego rozszerzenia znajduje się w SessionProcessorImpl, która odpowiada za dostarczanie niestandardowej konfiguracji sesji i wysyłanie żądań przechwytywania w celu zainicjowania podglądu i przechwytywania żądań. AdvancedExtenderImpl.createSessionProcessor() jest wywoływana w celu zwrócenia instancji SessionProcessorImpl.

  2. initSession

    SessionProcessorImpl.initSession() inicjuje sesję rozszerzenia. W tym miejscu przydzielasz zasoby i zwracasz konfigurację sesji na potrzeby przygotowania CameraCaptureSession.

    W przypadku parametrów wejściowych Camera2/X określa konfiguracje powierzchni wyjściowych na potrzeby podglądu, robienia zdjęć i opcjonalnej analizy obrazu YUV. Ta konfiguracja powierzchni wyjściowej (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. Odpowiadasz za przesyłanie prawidłowych obrazów z kamery do powierzchni wyjściowych przekazywanych przez Camera2/X. Oto kilka opcji włączenia wyjścia:

    • Przetwarzanie w warstwie HAL aparatu: możesz bezpośrednio dodać powierzchnie wyjściowe do CameraCaptureSession za pomocą implementacji SurfaceOutputConfigImpl. Konfiguruje dostarczoną powierzchnię wyjściową dla potoku kamery i umożliwia HAL kamery przetwarzanie obrazu.
    • Przetwarzanie powierzchni pośredniej ImageReader (RAW, YUV itp.): dodaj powierzchnie pośrednie ImageReader do CameraCaptureSession za pomocą instancji ImageReaderOutputConfigImpl.

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

    • Użyj udostępniania powierzchni Camera2: użyj udostępniania powierzchni z inną powierzchnią, dodając dowolną instancję Camera2OutputConfigImpl do metody getSurfaceSharingOutputConfigs() innej instancji Camera2OutputConfigImpl. Format i rozmiar powierzchni muszą być identyczne.

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

  3. onCaptureSessionStartRequestProcessorImpl

    Gdy CameraCaptureSession się uruchomi i framework aparatu wywoła onConfigured(), Camera2/X wywoła SessionProcessorImpl.onCaptureSessionStart() z opakowaniem żądania Camera2 RequestProcessImpl. Camera2/X implementuje RequestProcessImpl, co umożliwia wykonywanie żądań przechwytywaniapobieranie obrazów, jeśli używana jest funkcja ImageReaderOutputConfigImpl.

    Interfejsy API RequestProcessImpl są podobne do interfejsów API Camera2CameraCaptureSession pod względem wykonywania żądań. Różnice są następujące:

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

    Możesz wywołać funkcję RequestProcessorImpl.setImageProcessor() z określonym identyfikatorem Camera2OutputConfigImpl, aby zarejestrować instancję ImageProcessorImpl i otrzymywać obrazy.

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

  4. Włącz podgląd i zrób zdjęcie

    W przypadku implementacji zaawansowanego rozszerzenia możesz wysyłać żądania zapisu transakcji za pomocą interfejsu RequestProcessorImpl. Camera2/X powiadamia Cię o konieczności rozpoczęcia powtarzającego się żądania podglądu lub sekwencji przechwytywania zdjęć, wywołując odpowiednio funkcje SessionProcessorImpl#startRepeatingSessionProcessorImpl#startCapture. Aby spełnić te żądania podglądu i wykonania zdjęcia, należy wysyłać żądania przechwytywania.

    Interfejs Camera2/X ustawia też parametry żądania przechwytywania za pomocą funkcji 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 w wersji 1.3.0 obsługuje klucze żądań i wyników, które są udostępniane przez te metody:

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

    Gdy deweloperzy ustawią klucze na liście getAvailableCaptureRequestKeys, musisz włączyć parametry i upewnić się, że wynik przechwytywania zawiera klucze z listy getAvailableCaptureResultKeys.

  5. startTrigger

    SessionProcessorImpl.startTrigger() jest wywoływana w celu uruchomienia wyzwalacza, takiego jak CaptureRequest.CONTROL_AF_TRIGGERCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. Możesz zignorować wszystkie klucze żądań przechwytywania, które nie były reklamowane w AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    startTrigger() jest obsługiwany od wersji extensions-interface 1.3.0. Umożliwia aplikacjom korzystanie z funkcji dotknij, aby ustawić ostrość, i lampy błyskowej z rozszerzeniami.

  6. Czyszczenie danych

    Po zakończeniu sesji przechwytywania wywoływana jest funkcja SessionProcessorImpl.onCaptureSessionEnd() przed zamknięciem CameraCaptureSession. Po zamknięciu sesji przechwytywania usługa deInitSession() zwalnia miejsce.

obsługuje podgląd, robienie zdjęć i analizę obrazu;

Rozszerzenie należy stosować zarówno w przypadku podglądu, jak i w przypadku przechwytywania obrazu. Jeśli jednak opóźnienie jest zbyt duże, aby płynnie wyświetlać podgląd, możesz zastosować rozszerzenie tylko w przypadku przechwytywania obrazu statycznego.

W przypadku typu Basic Extender, niezależnie od tego, czy rozszerzenie jest włączone w podglądzie, musisz zaimplementować zarówno ImageCaptureExtenderImpl, jak i PreviewExtenderImpl w przypadku 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ę strumieni podglądu, przechwytywania obrazu i strumienia YUV_420_888 do konfigurowania CameraCaptureSession. Oznacza to, że jeśli zaimplementujesz procesor, musisz obsługiwać kombinację strumieni składającą się z 3 strumieni YUV_420_888.

W przypadku zaawansowanego przedłużacza Camera2/X przekazuje do wywołania SessionProcessorImpl.initSession() 3 powierzchnie wyjściowe. Te powierzchnie wyjściowe służą odpowiednio do podglądu, przechwytywania obrazów i analizy obrazów. Musisz się upewnić, że powierzchnie wyjściowe podglądu i zdjęć pokazują prawidłowe dane wyjściowe. W przypadku powierzchni wyjściowej analizy obrazu upewnij się jednak, że działa ona tylko wtedy, gdy nie ma wartości null. 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 SessionProcessorImpl.initSession().

Obsługa nagrywania filmów

Obecna architektura rozszerzenia aparatu obsługuje tylko podgląd i robienie zdjęć. Nie obsługujemy włączania rozszerzenia na platformach MediaCodec lub MediaRecorder w celu nagrywania filmu. Aplikacje mogą jednak nagrywać podgląd.

Obsługa platform MediaCodecMediaRecorder jest w trakcie sprawdzania.

Metadane specyficzne dla rozszerzenia

W przypadku Androida 14 i nowszych metadane specyficzne dla rozszerzenia umożliwiają klientom rozszerzeń aparatu ustawianie i otrzymywanie ustawień żądania przechwytywania specyficznych dla rozszerzenia oraz wyników. W szczególności klienci rozszerzenia kamery mogą używać parametru żądania przechwytywania EXTENSION_STRENGTH do kontrolowania siły rozszerzenia i parametru wyniku przechwytywania EXTENSION_CURRENT_TYPE do wskazywania włączonego typu rozszerzenia.

Żądania przechwytywania

Parametr żądania przechwytywania EXTENSION_STRENGTH określa siłę efektu przetwarzania końcowego rozszerzenia. Odpowiedni wynik przechwytywania zawiera domyślną wartość siły, jeśli ten parametr nie jest jawnie ustawiony przez klienta. W przypadku tych typów rozszerzeń ten parametr można zastosować w ten sposób:

  • BOKEH: określa stopień rozmycia.
  • HDRNIGHT: kontroluje liczbę połączonych obrazów i jasność obrazu końcowego.
  • FACE_RETOUCH: określa stopień poprawy wyglądu i wygładzania skóry.

Obsługiwany zakres parametru EXTENSION_STRENGTH to 0100. Wartość 0 oznacza brak przetwarzania rozszerzenia lub proste przekazywanie, a 100 – maksymalną siłę rozszerzenia efektu przetwarzania.

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

Wyniki przechwytywania

Wynik przechwytywania EXTENSION_CURRENT_TYPE umożliwia implementacjom rozszerzeń powiadamianie klientów o aktywnym typie 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 sceny. Aplikacje rozszerzeń aparatu mogą używać EXTENSION_CURRENT_TYPE do wyświetlania informacji o bieżącym rozszerzeniu wybranym przez rozszerzenie AUTO.

Szacowana latencja przechwytywania obrazu w czasie rzeczywistym

W przypadku Androida 14 i nowszych wersji klienci rozszerzeń aparatu mogą wysyłać zapytania o szacunki opóźnień w czasie rzeczywistym dotyczące przechwytywania zdjęć na podstawie sceny i warunków środowiskowych za pomocą funkcji getRealtimeStillCaptureLatency(). Ta metoda zapewnia dokładniejsze szacunki niż metoda statycznagetEstimatedCaptureLatencyRangeMillis(). Na podstawie szacowanego opóźnienia aplikacje mogą zdecydować, czy pominąć przetwarzanie rozszerzenia, czy wyświetlić informację 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 obsługiwać szacunki opóźnienia przechwytywania zdjęć w czasie rzeczywistym, zaimplementuj:

Wywołania zwrotne postępu przetwarzania przechwytywania

W przypadku Androida 14 i nowszych klienci rozszerzeń aparatu mogą otrzymywać wywołania zwrotne dotyczące postępu długotrwałych operacji przetwarzania przechwytywania zdjęć. Aplikacje mogą wyświetlać użytkownikom bieżące postępy, aby poprawić ogólną wygodę korzystania z nich.

Aby zintegrować tę funkcję, aplikacje mogą użyć tego kodu:

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 postępu przetwarzania przechwytywania, implementacja dostawcy rozszerzenia musi wywoływać te wywołania zwrotne z bieżącą wartością postępu:

Zapis po obejrzeniu

W przypadku Androida 14 i nowszych wersji rozszerzenia aparatu mogą dostarczać podgląd (obraz podglądu) za pomocą setPostviewOutputConfiguration. Aby zwiększyć komfort użytkowników, aplikacje mogą wyświetlać obraz po wyświetleniu jako element zastępczy, gdy rozszerzenie ma większe opóźnienie przetwarzania, i zastępować go, gdy dostępny jest obraz końcowy. 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 dostawcy musi zawierać te elementy:

Obsługa danych wyjściowych SurfaceView

W przypadku Androida 14 i nowszych wersji klienci rozszerzeń aparatu mogą używać ścieżek renderowania podglądu zoptymalizowanych pod kątem mocy i wydajności, rejestrując instancję SurfaceView na potrzeby danych wyjściowych 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 wyświetlanie podglądu w instancjach SurfaceView. Aby sprawdzić, czy jest to obsługiwane, uruchom moduł SurfaceViewExtensionPreviewTest.java CTS.

Typy sesji dotyczące konkretnego dostawcy

Ta funkcja umożliwia implementacjom rozszerzeń dostawcy wybór typu sesji specyficznego dla dostawcy, który zostanie ustawiony w wewnętrznej sesji przechwytywania obrazu z aparatu zamiast wartości domyślnej.

Ta funkcja działa w ramach platformy i stosu dostawcy i nie ma wpływu na interfejs API widoczny dla klienta lub publiczny.

Aby wybrać typ sesji specyficzny dla dostawcy, w przypadku bibliotek rozszerzeń zaimplementuj te elementy: * ExtenderStateListener.onSessionType() w przypadku rozszerzeń podstawowych, * Camera2SessionConfigImpl.getSessionType() w przypadku rozszerzeń zaawansowanych.

Historia zmian wersji interfejsu rozszerzeń

W tabeli poniżej znajdziesz historię zmian interfejsu Camera Extension. Bibliotekę dostawcy należy zawsze wdrażać w najnowszej wersji.

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
  • Udostępnianie obsługiwanych rozdzielczości
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • Uzyskiwanie szacowanego opóźnienia przechwytywania
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • Udostępnianie obsługiwanych kluczy żądań przechwytywania i kluczy wyników
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys i getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys i getAvailableCaptureResultKeys
    • Nowe połączenie process(), które odbędzie się ProcessResultImpl w PreviewImageProcessorImpl i CaptureProcessorImpl
    • Prośba o typ aktywatora pomocy
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • Metadane specyficzne dla rozszerzenia
  • Szacowanie opóźnienia dynamicznego przechwytywania zdjęć
  • Wywołania zwrotne postępu przetwarzania przechwytywania
  • Zapis po obejrzeniu
  • Obsługa wyjścia SurfaceView
  • Typy sesji dotyczące konkretnego dostawcy

Implementacja referencyjna

W usłudze frameworks/ex dostępne są te implementacje biblioteki dostawcy OEM:

  • advancedSample: podstawowa implementacja zaawansowanego przedłużenia platformy.

  • sample: podstawowa implementacja podstawowego przedłużenia platformy.

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

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

      Zaawansowany wzmacniacz jest domyślnie włączony. Aby włączyć podstawowy przedłużacz, zmień ExtensionsVersionImpl#isAdvancedExtenderImplemented na powrótfalse.

    • extensions_service: przykładowa implementacja usługi rozszerzeń. Dodaj tutaj swoją implementację. Interfejs do wdrożenia w usłudze jest podobny do interfejsu Extensions-Interface. Na przykład implementacja IAdvancedExtenderImpl.Stub wykonuje te same operacje co AdvancedExtenderImpl. Aby można było przekazywać obiekty ImageTotalCaptureResult, wymagane są pola ImageWrapperTotalCaptureResultWrapper.

Konfigurowanie biblioteki dostawcy na urządzeniu

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

Umożliwia to aplikacjom innych firm korzystającym z rozszerzeń automatyczne wczytywanie biblioteki dostawcy OEM. Biblioteka OEM jest oznaczona jako opcjonalna, dzięki czemu aplikacje mogą działać na urządzeniach, które nie mają jej zainstalowanej. Camera2/X automatycznie obsługuje to zachowanie, gdy aplikacja 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:

  1. Dodaj plik uprawnień 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 zawierają mapowanie biblioteki o nazwie <uses-library> na rzeczywistą ścieżkę pliku na urządzeniu.
  2. Aby dodać wymagane informacje do pliku, skorzystaj z poniższego przykładu.

    • name musi być androidx.camera.extensions.impl, ponieważ to tej biblioteki szuka CameraX.
    • file to ścieżka bezwzględna do pliku, który zawiera implementację rozszerzeń (np. /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>

Na urządzeniach z Androidem 12 lub nowszym, które obsługują rozszerzenia CameraX, właściwość ro.camerax.extensions.enabled musi mieć wartość true. Umożliwia to sprawdzanie, czy urządzenie obsługuje rozszerzenia. Aby to zrobić, dodaj ten wiersz do pliku kompilacji urządzenia:

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

Weryfikacja

Aby przetestować implementację biblioteki dostawcy OEM na etapie rozwoju, użyj przykładowej aplikacji dostępnej pod adresem androidx-main/camera/integration-tests/extensionstestapp/, która korzysta z różnych rozszerzeń dostawcy.

Po zakończeniu implementacji użyj narzędzia do weryfikacji rozszerzeń aparatu, aby przeprowadzić testy automatyczne i ręczne i sprawdzić, czy biblioteka dostawcy została prawidłowo zaimplementowana.

Rozszerzony tryb scenerii a rozszerzenia aparatu

W przypadku rozszerzenia bokeh oprócz udostępniania go za pomocą rozszerzeń aparatu możesz udostępniać je za pomocą rozszerzonego trybu scenerii, który jest włączany za pomocą klawisza CONTROL_EXTENDED_SCENE_MODE. Więcej informacji o implementacji znajdziesz w artykule Bokeh w aparacie.

Tryb rozszerzonej scenerii ma mniej ograniczeń w porównaniu z rozszerzeniami aparatu w aplikacjach Camera2. Możesz na przykład włączyć rozszerzony tryb scenerii w zwykłej instancji CameraCaptureSession, która obsługuje elastyczne kombinacje strumieni i parametry żądania przechwytywania. Rozszerzenia aparatu obsługują tylko stały zestaw typów strumieni i mają ograniczone możliwości obsługi parametrów żądania przechwytywania.

Wadą rozszerzonego trybu scenerii jest to, że można go wdrożyć tylko w warstwie HAL aparatu. Oznacza to, że musi on być zweryfikowany pod kątem działania we wszystkich ortogonalnych elementach sterujących dostępnych dla deweloperów aplikacji.

Zalecamy udostępnianie efektu bokeh zarówno w trybie scenerii rozszerzonej, jak i w interfejsie CameraExtensions, ponieważ aplikacje mogą preferować używanie określonego interfejsu API do włączania efektu bokeh. Zalecamy najpierw użycie trybu rozszerzonej scenerii, ponieważ jest to najbardziej elastyczny sposób włączania rozszerzenia bokeh w aplikacjach. Następnie możesz wdrożyć interfejs rozszerzeń aparatu na podstawie rozszerzonego trybu scenerii. Jeśli wdrożenie efektu bokeh w warstwie HAL aparatu jest trudne, np. dlatego, że wymaga postprocesora działającego w warstwie aplikacji do przetwarzania obrazów, zalecamy wdrożenie rozszerzenia bokeh za pomocą interfejsu rozszerzeń aparatu.

Najczęstsze pytania

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

Tak. Zależy to od zestawu funkcji interfejsu Android API, które są wymagane przez implementację biblioteki dostawcy OEM. Na przykład funkcja ExtenderStateListener.onPresetSession() używa wywołania SessionConfiguration.setSessionParameters() do ustawienia podstawowego zestawu tagów. To wywołanie jest dostępne tylko na interfejsie API na poziomie 28 i wyższym. Szczegółowe informacje o poszczególnych metodach interfejsu znajdziesz w dokumentacji API.