Interfejsy API do zarządzania buforem HAL3 kamery

Android 10 wprowadza opcjonalne interfejsy API do zarządzania buforem HAL3 kamery, które pozwalają wdrożyć logikę zarządzania buforem w celu uzyskania różnych ilości pamięci i rejestrowania kompromisów związanych z opóźnieniami w implementacjach HAL aparatu.

Interfejs HAL aparatu wymaga N żądań (gdzie N jest równe głębi potoku) w kole, ale często nie wymaga wszystkich N zestawów buforów wyjściowych w tym samym czasie.

Na przykład HAL może mieć 8 żądań w kolejce w potoku, ale wymaga tylko buforów wyjściowych dla 2 żądań na ostatnich etapach potoku. Na urządzeniach z Androidem 9 lub starszym platforma aparatu przydziela bufory, gdy żądanie jest umieszczone w kolejce w HAL, więc w tej wersji może znajdować się 6 zestawów buforów, które nie są w użyciu. W Androidzie 10 interfejsy HAL3 do zarządzania buforem w aparacie umożliwiają odłączenie buforów wyjściowych w celu zwolnienia 6 zestawów buforów. Może to prowadzić do oszczędności setek megabajtów pamięci na urządzeniach wysokiej klasy, a także przynieść korzyści w przypadku urządzeń o małej ilości pamięci.

Rysunek 1 przedstawia diagram interfejsu HAL aparatu na urządzeniach z Androidem 9 lub starszym. Ilustracja 2. przedstawia interfejs HAL aparatu na Androidzie 10 z zaimplementowanymi interfejsami API do zarządzania buforem HAL3 aparatu.

Zarządzanie buforami w 9 lub niższych

Rysunek 1. Interfejs Camera HAL w Androidzie 9 i starszych

Zarządzanie buforami w Androidzie 10

Rysunek 2. Interfejs HAL aparatu w Androidzie 10 korzystający z interfejsów API do zarządzania buforem

Wdrażanie interfejsów API do zarządzania buforem

Aby zaimplementować interfejsy API zarządzania buforem, interfejs HAL aparatu musi:

HAL aparatu używa metod requestStreamBuffers i returnStreamBuffers w ICameraDeviceCallback.hal do żądania i zwracania buforów. Biblioteka HAL musi też implementować metodę signalStreamFlushICameraDeviceSession.hal, aby sygnalizować bibliotece HAL aparatu, że ma zwrócić bufory.

requestStreamBuffers

Aby poprosić o bufory z ramki aparatu, użyj metody requestStreamBuffers. Gdy używasz interfejsów API do zarządzania buforami w ramach aparatu HAL3, żądania rejestrowania z ramy pracy aparatu nie zawierają buforów wyjściowych, czyli pole bufferIdStreamBuffer ma wartość 0. Dlatego HAL aparatu musi używać funkcji requestStreamBuffers, aby żądać buforów z ramy aparatu.

Metoda requestStreamBuffers umożliwia wywołującemu żądanie wielu buforów z wielu strumieni wyjściowych w jednym wywołaniu, co pozwala na ograniczenie wywołań HIDL IPC. Jednak wywołania zajmują więcej czasu, gdy jednocześnie jest wymagana większa liczba buforów, co może negatywnie wpłynąć na łączny czas od żądania do wyniku. Ponadto, ponieważ wywołania do funkcji requestStreamBuffers są serializowane w usłudze aparatu, zalecamy, aby interfejs HAL aparatu używał dedykowanego wątku o wysokim priorytecie do żądania buforów.

Jeśli żądanie bufora nie powiedzie się, interfejs HAL aparatu musi być w stanie prawidłowo obsłużyć błędy niekrytyczne. Poniżej znajdziesz listę typowych przyczyn niepowodzeń żądań buforowania oraz informacje o tym, jak powinny być one obsługiwane przez interfejs HAL aparatu.

  • Aplikacja rozłącza się ze strumieniem wyjściowym: to błąd niekrytyczny. Interfejs HAL aparatu powinien wysyłać żądanie ERROR_REQUEST dotyczące każdego żądania rejestrowania, które kieruje do odłączonego strumienia, i być gotowy do przetwarzania kolejnych żądań w normalny sposób.
  • Limit czasu: może się to zdarzyć, gdy aplikacja jest zajęta intensywnym przetwarzaniem, a jednocześnie przechowuje niektóre bufory. Interfejs HAL aparatu powinien ERROR_REQUEST przesyłać żądania rejestrowania, które nie mogą zostać zrealizowane z powodu błędu limitu czasu, i być gotowy do przetwarzania kolejnych żądań w normalny sposób.
  • Platforma kamery przygotowuje nową konfigurację transmisji: interfejs HAL kamery powinien zaczekać na zakończenie następnego wywołania configureStreams, zanim ponownie wywoła funkcję requestStreamBuffers.
  • HAL kamery osiągnęło limit bufora (pole maxBuffers): HAL kamery powinna poczekać, aż zwróci co najmniej 1 bufor strumienia, zanim ponownie wywoła requestStreamBuffers.

ReturnStreamBuffers:

Aby zwrócić dodatkowe bufory do aparatu, użyj metody returnStreamBuffers. Interfejs HAL aparatu zazwyczaj zwraca do interfejsu frameworku aparatu bufory za pomocą metody processCaptureResult, ale może uwzględnić tylko żądania rejestrowania, które zostały wysłane do interfejsu HAL aparatu. Dzięki metodzie requestStreamBuffers implementacja interfejsu HAL aparatu może zachować więcej buforów niż te, o które poprosił interfejs aparatu. W takim przypadku należy użyć metody returnStreamBuffers. Jeśli implementacja HAL nigdy nie przechowuje więcej buforów niż wymagane, implementacja HAL aparatu nie musi wywoływać metody returnStreamBuffers.

SignalsStreamFlush

Metoda signalStreamFlush jest wywoływana przez platformę kamery w celu powiadomienia HAL kamery o konieczności zwrócenia wszystkich dostępnych buforów. Jest ona zwykle wywoływana, gdy struktura kamery ma wywołać funkcję configureStreams i musi opróżnić potok nagrywania. Podobnie jak w przypadku metody returnStreamBuffers, jeśli implementacja interfejsu HAL aparatu nie przechowuje więcej buforów niż jest to wymagane, można użyć pustej implementacji tej metody.

Po wywołaniu przez framework aparatu funkcji signalStreamFlush framework przestaje wysyłać nowe żądania rejestrowania do interfejsu HAL aparatu, dopóki wszystkie bufory nie zostaną zwrócone do frameworku aparatu. Gdy wszystkie bufory zostaną zwrócone, wywołania metody requestStreamBuffers zakończą się niepowodzeniem, a ramka aparatu może kontynuować pracę w czystym stanie. Platforma kamery wywołuje metodę configureStreams lub processCaptureRequest. Jeśli platforma kamery wywołuje metodę configureStreams, po zwróceniu wywołania configureStreams interfejs HAL kamery może ponownie rozpocząć żądanie buforów. Jeśli framework aparatu wywołuje metodę processCaptureRequest, HAL aparatu może zacząć żądać buforów podczas wywołania processCaptureRequest.

Metoda signalStreamFlush różni się semantycznie od metody flush. Gdy wywoływana jest metoda flush, HAL może przerwać oczekujące żądania przechwytywania, aby jak najszybciej opróżnić kanał.ERROR_REQUEST Po wywołaniu metody signalStreamFlush HAL musi w zwykły sposób realizować wszystkie oczekujące żądania przechwytywania i zwracać wszystkie bufory do platformy kamery.

Kolejną różnicą między metodą signalStreamFlush a innymi metodami jest to, że signalStreamFlush to jednokierunkowa metoda HIDL, co oznacza, że framework aparatu może wywoływać inne blokujące interfejsy API, zanim HAL otrzyma wywołanie signalStreamFlush. Oznacza to, że metoda signalStreamFlush i inne metody (w szczególności metoda configureStreams) mogą docierać do aparatu HAL w innej kolejności niż kolejność wywołania w ramach interfejsu aparatu. Aby rozwiązać ten problem asynchroniczny, pole streamConfigCounter zostało dodane do metody StreamConfiguration i dodane jako argument do metody signalStreamFlush. Implementacja HAL aparatu powinna używać argumentu streamConfigCounter, aby określić, czy wywołanie signalStreamFlush zostanie odebrane później niż odpowiadające mu wywołanie configureStreams. Przykład znajdziesz na rysunku 3.

Obsługa połączeń przychodzących z opóźnieniem

Rysunek 3. Jak HAL kamery powinna wykrywać i przetwarzać spóźnione wywołania SignalsStreamFlush

Zmiany w działaniu po wdrożeniu interfejsów API do zarządzania buforem

Podczas implementowania logiki zarządzania buforem za pomocą interfejsów API zarządzania buforem należy wziąć pod uwagę te możliwe zmiany zachowania aparatu i implementacji interfejsu HAL aparatu:

  • Żądania rejestrowania docierają do interfejsu HAL aparatu szybciej i częściej: bez interfejsów API do zarządzania buforami framework aparatu prosi o bufory wyjściowe dla każdego żądania rejestrowania przed wysłaniem żądania rejestrowania do interfejsu HAL aparatu. Gdy używasz interfejsów API do zarządzania buforami, framework aparatu nie musi już czekać na bufory, więc może wcześniej wysyłać żądania rejestrowania do interfejsu HAL aparatu.

    Ponadto bez interfejsów API do zarządzania buforami framework aparatu przestaje wysyłać żądania przechwytywania, jeśli jeden ze strumieni wyjściowych żądania przechwytywania osiągnie maksymalną liczbę buforów, jaką może pomieścić HAL (ta wartość jest wyznaczana przez HAL aparatu w polu HalStream::maxBuffers w wartości zwracanej wywołania configureStreams). Dzięki interfejsom API do zarządzania buforem nie ma już takiego ograniczania przepustowości, a implementacja interfejsu HAL aparatu nie może akceptować wywołań processCaptureRequest, gdy ma zbyt wiele oczekujących żądań rejestrowania.

  • Czas oczekiwania na połączenie requestStreamBuffers może się znacznie różnić: istnieje wiele powodów, dla których połączenie requestStreamBuffers może trwać dłużej niż przeciętnie. Na przykład:

    • W przypadku pierwszych kilku buforów nowo utworzonego strumienia wywołania mogą potrwać dłużej, ponieważ urządzenie musi przydzielić pamięć.
    • Oczekiwany czas oczekiwania zwiększa się proporcjonalnie do liczby buforów zażądanych w każdym wywołaniu.
    • Aplikacja przechowuje bufory i przetwarza dane. Może to spowodować spowolnienie żądań buforów lub przekroczenie limitu czasu z powodu braku buforów lub zajętego procesora.

Strategie zarządzania buforami

Interfejsy API do zarządzania buforem umożliwiają wdrażanie różnych strategii zarządzania buforem. Przykłady:

  • Wsteczna zgodność: HAL prosi o bufory dla żądania zapisu podczas wywołania processCaptureRequest. Ta strategia nie pozwala oszczędzać pamięci, ale może służyć jako pierwsza implementacja interfejsów API do zarządzania buforem, wymagająca bardzo niewielkich zmian w kodzie w istniejącym interfejsie HAL aparatu.
  • Maksymalizacja oszczędności pamięci: interfejs HAL aparatu prosi o bufory wyjściowe tylko tuż przed wypełnieniem jednego z nich. Ta strategia pozwala na zmaksymalizowanie oszczędzania pamięci. Potencjalną wadą jest większa liczba żądań dotyczących strumienia kamery, gdy żądania buforowania zajmują nienormalnie dużo czasu.
  • W pamięci podręcznej: interfejs HAL aparatu zapisuje w pamięci podręcznej kilka buforów, aby zmniejszyć prawdopodobieństwo wpływu na niego sporadycznie wolnego żądania bufora.

HAL aparatu może przyjąć różne strategie w różnych przypadkach użycia, np. w przypadku zastosowania strategii maksymalizacji oszczędzania pamięci w przypadkach, w których używa się dużo pamięci, a w innych zastosowaniach – strategii zgodności wstecznej.

Przykładowa implementacja w interfejsie zewnętrznego aparatu HAL

Interfejs HAL aparatu zewnętrznego został wprowadzony w Androidzie 9 i można go znaleźć w drzewie źródłowym na stronie hardware/interfaces/camera/device/3.5/. W Androidzie 10 interfejs ten został zaktualizowany, aby uwzględniał ExternalCameraDeviceSession.cpp, czyli implementację interfejsu API do zarządzania buforem. Ten interfejs HAL kamery zewnętrznej implementuje strategię maksymalizacji oszczędzania pamięci wymienioną w artykule Zarządzanie buforami – strategie za pomocą kilkuset linii kodu C++.