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. Programiści mogą używać interfejsów Camera2 Extensions API i 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 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 wdrożyć na urządzeniach bibliotekę dostawcy OEM i ją włączyć.

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. Określają one interfejs rozszerzeń aparatu.

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

Podstawowe 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 rozszerzeń Bokeh (wdróż je, jeśli rozszerzenie Bokeh jest obsługiwane)

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

Zajęcia wydłużające noc (wprowadź je, jeśli obsługiwane jest rozszerzenie nocne)

  • 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 w przypadku 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 Camera2 i CameraX Extensions 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 uzyskaniem dostępu do klas Extender.

  3. Klasy instancji 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 instancję klasy Extender i współpracuje z nią, aby pobrać informacje i włączyć rozszerzenie. W przypadku danego rozszerzenia Camera2/X może tworzyć instancje klas Extendera wielokrotnie. W związku z tym nie przeprowadzaj intensywności inicjowania 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. Sprawdź dostępność rozszerzeń:

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

  5. Zainicjuj Extender, podając informacje o kamerze:

    Camera2/X wywołuje init() w instancji Extender i przekazuje do niej identyfikator kamery oraz CameraCharacteristics.

  6. Informacje o zapytaniu:

    Wywołuje klasę Extender, aby pobrać informacje, takie jak obsługiwane rozdzielczości, nadal szacować opóźnienie 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 zaawansowanego przedłużenia Aparat2/X współdziała z SessionProcessorImpl, aby włączyć rozszerzenie. Camera2/X pobiera instancję SessionProcessorImpl, wywołując funkcję createSessionProcessor() w Extender.

W kolejnych sekcjach szczegółowo opisano proces 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ść z wyprzedzeniem

W przyszłości zgodność z bibliotekami dostawcy nowszej wersji extensions-interface zależy od Ciebie, 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 przywrócić niezgodną wersję, np. 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 etap inicjowania biblioteki, jeśli biblioteka dostawcy OEM wdrożyła 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.

Wdrożyć podstawowy rozszerzacz dla rozszerzeń, które przetwarzają obrazy w interfejsie HAL aparatu, lub użyć procesora końcowego zdolnego do przetwarzania strumieni YUV.

Zaimplementuj rozszerzenie Advanced Extender na potrzeby rozszerzeń, które muszą dostosować konfigurację strumienia Camera2 i w razie potrzeby wysyłać żądania zapisu.

Porównanie znajdziesz w tabeli poniżej:

Przedłużacz podstawowy Rozszerzenie zaawansowane
Konfiguracje transmisji Rozwiązano
Podgląd: PRIVATE lub YUV_420_888 (jeśli procesor istnieje)
Nagrywanie zdjęć: JPEG lub YUV_420_888 (jeśli procesor istnieje)
Możliwość dostosowania przez OEM.
Wysyłanie żądania przechwycenia Żądania przechwytywania mogą wysyłać tylko aparaty Camera2/X. Możesz ustawić parametry tych żądań. Gdy procesor jest udostępniany do przechwytywania obrazu, Camera2/X może wysyłać wiele żądań przechwytywania i przesyłać wszystkie obrazy oraz wyniki przechwytywania do procesora. Do wykonania żądania rejestrowania obrazu przez aparat 2 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ęć.

Blokady w ruchu kamery
  • Parametr onPresetSession udostępnia parametry sesji.
  • onEnableSession wysyła pojedyncze żądanie zaraz po skonfigurowaniu CameraCaptureSession.
  • onDisableSession wysyła jedną prośbę przed zamknięciem CameraCaptureSession.
  • initSession inicjuje i zwraca niestandardową konfigurację sesji Camera2 w celu utworzenia sesji przechwytywania.
  • Funkcja onCaptureSessionStart jest wywoływana zaraz po skonfigurowaniu metody CameraCaptureSession.
  • Funkcja onCaptureSessionEnd jest wywoływana, zanim funkcja CameraCaptureSession zostanie zamknięta.
Odpowiednie 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

Przepływy aplikacji

W tabeli poniżej znajdziesz 3 typy przepływów w aplikacji i odpowiadające im wywołania interfejsu Camera Extensions API. Interfejsy Camera2/X udostępniają te interfejsy API, ale do obsługi tych przepływów należy prawidłowo wdrożyć bibliotekę dostawcy. Szczegółowo opisujemy to w dalszej 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.

Basic Extender 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 są w stanie 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 platformy podglądu i rejestrowania: ImageCaptureExtenderImpl.getSupportedResolutions i PreviewExtenderImpl.getSupportedResolutions zwracają listę formatów obrazów oraz rozmiary, które są obsługiwane w przypadku formatu i rozmiaru 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. Krok 3 w aplikacji na urządzeniu Basic Extender

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(). Poza tym żądanie przechwytywania nieruchomości zawiera parametry zwrócone przez 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.

Zaimplementuj PreviewExtenderImpl.getProcessorType, aby określić typ procesora, w sposób opisany poniżej:

  • 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ę. Funkcja PreviewExtenderImpl.getCaptureStage() powinna również odzwierciedlać wynik przetwarzania i zwrócić najnowszą wartość CaptureStageImpl.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR: ten typ umożliwia implementację procesora w celu przetwarzania obrazów YUV_420_888 i zapisywania danych wyjściowych 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. Aparat2/X używa platformy YUV_420_888 zamiast PRIVATE do skonfigurowania podglądu CameraCaptureSession.

    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że to być tylko YUV_420_888.

Procesor do przechwytywania obrazu

W przypadku przechwytywania statycznych obrazów możesz zaimplementować procesor, zwracając instancję CaptureProcessorImpl za pomocą funkcji 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 rejestruj przepływ dzięki aplikacji 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 mapowany na instancję CaptureRequest z parametrami przechwytywania, które są wysyłane przez Camera2/X. Jeśli na przykład wyświetli listę 3 instancji CaptureStageImpl, Camera2/X wyśle 3 żądania przechwytywania z odpowiednimi parametrami przechwytywania za pomocą interfejsu API captureBurst.

  3. Odbierane obrazy i instancje (TotalCaptureResult) są grupowane i wysyłane do 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 aparatu przetwarza rozszerzenie, Camera2/X pobierze wyniki przechwytywania w formacie CameraCaptureSession.CaptureCallback. Jeśli jednak procesor jest zaimplementowany, Camera2/X pobierze wyniki przechwytywania w ProcessResultImpl, które są przekazywane do metody process() w PreviewImageProcessorImpl i CaptureProcessorImpl. 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 działań związanych z aparatem, takich jak zoom, namierzanie ostrości, lampa błyskowa czy kompensacja ekspozycji, zalecamy obsługę tych klawiszy zarówno w przypadku żądania zapisu, jak i wyniku przechwytywania:

  • Powiększenie:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • Kliknij, 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 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 funkcja dotykania, aby ustawić ostrość, lampa błyskowa i kompensacja ekspozycji nie są dozwolone.

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ń.

Advanced Extender udostępnia kod lub warstwę pośrednią, które pozwalają dostosowywać konfigurację strumienia i na żądanie wysyłać żądania przechwytywania.

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 przykładzie poniżej używamy zmiennej AdvancedExtenderImpl jako zmiennej. 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. Krok 2 w aplikacji na urządzeniu Advanced Extender

Po wywołaniu AdvancedExtenderImpl.init() aplikacja może wysłać zapytanie do AdvancedExtenderImpl z tymi informacjami:

  • Szacowany czas oczekiwania na przechwytywanie obrazu: AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() zwraca zakres czasu oczekiwania na zapis, po którym aplikacja może ocenić, czy można włączyć rozszerzenie w obecnej sytuacji.

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

    • 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 ich wyniki (dodane w extensions-interface 1.3.0): Aby pobrać obsługiwane klucze żądań i klucze wyników z Twojej implementacji, Camera2/X wywołuje te metody:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

Więcej informacji znajdziesz w artykule Klucze i wyniki żądań do 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 przechwytywania obrazu w przypadku typu rozszerzacza zaawansowanego. Omówmy każdy krok po kroku.

  1. SessionProcessorImpl

    Główna 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 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 zawiera listę instancji Camera2OutputConfigImpl i parametry sesji użyte do skonfigurowania CameraCaptureSession. Odpowiadasz za wysyłanie prawidłowych obrazów z kamery na platformy wyjściowe przekazywane przez Aparat 2/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 podłączoną 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 platformy ImageReader do CameraCaptureSession z wystąpieniem 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 powierzchni docelowej i pobierania obrazu z elementu ImageReaderOutputConfigImpl.

  3. onCaptureSessionStart i RequestProcessorImpl

    Gdy CameraCaptureSession uruchamia się i wywołuje interfejs Camera framework, Camera2/X wywołuje SessionProcessorImpl.onCaptureSessionStart() za pomocą owijarki zapytań Camera2 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 Camera2CameraCaptureSession pod względem wykonywania żądań. Różnice to:

    • 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.

    Po wywołaniu danych SessionProcessorImpl.onCaptureSessionEnd() przez Aparat 2/X instancja RequestProcessImpl stanie się nieprawidłowa.

  4. Uruchamianie podglądu i zrobienie zdjęcia

    W implementacji Advanced Extender można 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. Należy wysyłać żądania przechwytywania, aby zrealizować żądania podglądu i rejestracji.

    Aplikacja Camera2/X ustawia też parametry żądania rejestrowania za pomocą interfejsu SessionProcessorImpl#setParameters. Musisz je ustawiać (jeśli są obsługiwane) zarówno w żądaniach cyklicznych, jak i pojedynczych.

    Musisz obsługiwać co najmniej CaptureRequest.JPEG_ORIENTATION i CaptureRequest.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 żądania przechwytywania, które nie były rozgłaszane w AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

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

  6. Czyszczenie danych

    Po zakończeniu sesji przechwytywania funkcja SessionProcessorImpl.onCaptureSessionEnd() jest wywoływana przed zamknięciem funkcji CameraCaptureSession. Po zakończeniu 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 związanych z przechwytywaniem. 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 zaawansowanego przedłużenia kamery Aparat2/X przekazuje 3 platformy wyjściowe do wywołania SessionProcessorImpl.initSession(). Te platformy wyjściowe służą odpowiednio do podglądu, przechwytywania obrazu i analizy obrazów. Musisz się upewnić, że podgląd i pliki wyjściowe z nagrania 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 nagrywania 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, aby kontrolować siłę rozszerzenia, oraz parametru EXTENSION_CURRENT_TYPE wyniku przechwycenia, aby wskazać włączony typ 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 został jawnie ustawiony 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: kontroluje stopień poprawy kosmetyki i wygładzenie skóry.

Obsługiwany zakres parametru EXTENSION_STRENGTH mieści się w zakresie od 0 do 100, gdzie 0 oznacza brak przetwarzania rozszerzenia lub proste przekazywanie, a 100 wskazuje maksymalną siłę 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 przechwytywania EXTENSION_CURRENT_TYPE pozwala implementom rozszerzeń powiadamiać klientów o aktywnym typie rozszerzenia.

Rozszerzenia korzystające z typu AUTO, takie jak HDR i NIGHT, dynamicznie przełączają się między typami rozszerzeń (np. HDR i NIGHT) w zależności od warunków scenerii, dlatego aplikacje rozszerzeń aparatu mogą używać EXTENSION_CURRENT_TYPE do wyświetlania informacji o rozszerzeniu wybranym aktualnie przez rozszerzenie AUTO.

Szacowany czas oczekiwania na przechwytywanie w czasie rzeczywistym

W Androidzie 14 i nowszych klienci rozszerzenia kamery mogą wysyłać zapytania o szacowane opóźnienia w chwytaniu 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 oszacowania 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 długotrwałych operacji przetwarzania zdjęć. Aplikacje mogą wyświetlać użytkownikom informacje o aktualnym postępie, aby polepszyć ogólną wygodę korzystania z usługi.

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 filmu 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 klienty rozszerzeń do aparatu mogą korzystać ze ścieżek renderowania podglądu zoptymalizowanych pod kątem zasilania 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 wyprowadzanie podglądu do instancji SurfaceView. Aby sprawdzić, czy ta funkcja jest obsługiwana, uruchom moduł SurfaceViewExtensionPreviewTest.javaCTS.

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 w całości w ramach platformy i stosu dostawców oraz nie ma wpływu na interfejs API widoczny publicznie ani dla klienta.

Aby wybrać typ sesji w przypadku konkretnego dostawcy, zaimplementuj te biblioteki w swoich bibliotekach rozszerzeń: * ExtenderStateListener.onSessionType() – rozszerzenia podstawowe; * Camera2SessionConfigImpl.getSessionType() w przypadku rozszerzeń zaawansowanych.

Historia wersji interfejsu rozszerzeń

W tabeli poniżej znajdziesz historię wersji interfejsu Rozszerzenia aparatu. Zawsze używaj najnowszej wersji 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 filmu 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 poziomu 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 funkcja 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żnością CameraX i musi zostać załadowana w czasie wykonywania. W Aparacie 2 platforma wczytuje usługę rozszerzeń, która deklaruje też, że <uses-library>wczytuje tę samą bibliotekę androidx.camera.extensions.impl w czasie działania.

Dzięki temu aplikacje innych firm korzystające z rozszerzeń mogą automatycznie wczytywać bibliotekę dostawcy OEM. Biblioteka OEM jest oznaczona jako opcjonalna, dzięki czemu aplikacje mogą działać na urządzeniach, które nie mają takiej 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. 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 sprawdzenie, 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 scenerii ma mniej ograniczeń niż rozszerzenia aparatu w aplikacjach aparat2. 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 wsparcie dla 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, by w pierwszej kolejności użyć trybu sceny rozszerzonej, bo jest to najbardziej elastyczny sposób na włączenie rozszerzenia bokeh. Następnie możesz zaimplementować interfejs rozszerzeń aparatu na podstawie rozszerzonego trybu sceny. Jeśli wdrożenie bokeh w interfejsie HAL aparatu jest trudne, na przykład dlatego, że wymaga przetworzenia zdjęć przez procesor działający na poziomie aplikacji, 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 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 referencyjnej interfejsu API.