Interfejsy API zarządzania buforem HAL3 kamery

W systemie Android 10 wprowadzono opcjonalne interfejsy API do zarządzania buforem HAL3 kamery , które umożliwiają wdrożenie logiki zarządzania buforami w celu uzyskania różnych kompromisów w zakresie pamięci i opóźnień w przechwytywaniu w implementacjach HAL kamery.

Kamera HAL wymaga N żądań (gdzie N jest równa głębokości potoku ) umieszczonych w kolejce, ale często nie wymaga jednocześnie wszystkich N zestawów buforów wyjściowych.

Na przykład warstwa HAL może mieć w kolejce osiem żądań, ale wymaga buforów wyjściowych jedynie dla dwóch żądań na ostatnich etapach potoku. Na urządzeniach z systemem Android 9 i starszym struktura kamery przydziela bufory, gdy żądanie jest umieszczane w kolejce w warstwie HAL, więc w warstwie HAL może znajdować się sześć zestawów buforów, które nie są używane. W systemie Android 10 interfejsy API zarządzania buforem HAL3 kamery umożliwiają oddzielenie buforów wyjściowych w celu zwolnienia sześciu zestawów buforów. Może to prowadzić do zaoszczędzenia setek megabajtów pamięci na urządzeniach z najwyższej półki, ale może być również korzystne w przypadku urządzeń o małej ilości pamięci.

Rysunek 1 przedstawia schemat interfejsu HAL kamery dla urządzeń z systemem Android 9 i starszym. Rysunek 2 przedstawia interfejs HAL kamery w systemie Android 10 z zaimplementowanymi interfejsami API zarządzania buforem HAL3 kamery.

Zarządzanie buforami w wersji 9 lub niższej

Rysunek 1. Interfejs HAL kamery w systemie Android 9 i starszych wersjach

Zarządzanie buforami w Androidzie 10

Rysunek 2. Interfejs HAL kamery w systemie Android 10 wykorzystujący interfejsy API zarządzania buforem

Implementacja interfejsów API zarządzania buforami

Aby zaimplementować interfejsy API zarządzania buforami, warstwa HAL kamery musi:

Kamera HAL używa metod requestStreamBuffers i returnStreamBuffers w ICameraDeviceCallback.hal do żądania i zwracania buforów. HAL musi także implementować metodę signalStreamFlush w ICameraDeviceSession.hal , aby zasygnalizować HAL kamery, aby zwróciła bufory.

Bufory żądania strumienia

Użyj metody requestStreamBuffers , aby zażądać buforów ze struktury kamery. W przypadku korzystania z interfejsów API zarządzania buforem HAL3 kamery żądania przechwytywania ze struktury kamery nie zawierają buforów wyjściowych, co oznacza, że ​​pole bufferId w StreamBuffer ma 0 . Dlatego warstwa HAL kamery musi używać requestStreamBuffers w celu żądania buforów ze struktury kamery.

Metoda requestStreamBuffers umożliwia wywołującemu żądanie wielu buforów z wielu strumieni wyjściowych w jednym wywołaniu, co pozwala na mniejszą liczbę wywołań HIDL IPC. Jednakże wywołania zajmują więcej czasu, gdy jednocześnie żąda się większej liczby buforów, co może negatywnie wpłynąć na całkowite opóźnienie od żądania do wyniku. Ponadto, ponieważ wywołania requestStreamBuffers są serializowane w usłudze kamery, zaleca się, aby warstwa HAL kamery korzystała z dedykowanego wątku o wysokim priorytecie w celu żądania buforów.

Jeśli żądanie bufora nie powiedzie się, warstwa HAL kamery musi być w stanie prawidłowo obsłużyć błędy niekrytyczne. Na poniższej liście opisano typowe przyczyny niepowodzenia żądań bufora oraz sposób ich obsługi przez warstwę HAL kamery.

  • Aplikacja odłącza się od strumienia wyjściowego: jest to błąd niekrytyczny. Kamera HAL powinna wysłać ERROR_REQUEST w przypadku każdego żądania przechwytywania skierowanego do odłączonego strumienia i być gotowa do normalnego przetwarzania kolejnych żądań.
  • Limit czasu: może się to zdarzyć, gdy aplikacja jest zajęta intensywnym przetwarzaniem, trzymając niektóre bufory. Kamera HAL powinna wysłać ERROR_REQUEST w przypadku żądań przechwytywania, których nie można zrealizować ze względu na błąd przekroczenia limitu czasu, i powinna być gotowa do normalnego przetwarzania kolejnych żądań.
  • Struktura kamery przygotowuje nową konfigurację strumienia: warstwa HAL kamery powinna poczekać do zakończenia następnego wywołania configureStreams przed ponownym wywołaniem requestStreamBuffers .
  • HAL kamery osiągnął limit bufora (pole maxBuffers ): HAL kamery powinien poczekać, aż zwróci przynajmniej jeden bufor strumienia, zanim ponownie wywoła requestStreamBuffers .

returnBufory strumienia

Użyj metody returnStreamBuffers , aby zwrócić dodatkowe bufory do struktury kamery. HAL kamery zwykle zwraca bufory do struktury kamery za pomocą metody processCaptureResult , ale może uwzględniać tylko żądania przechwytywania wysłane do warstwy HAL kamery. Dzięki metodzie requestStreamBuffers implementacja warstwy HAL kamery może zachować więcej buforów, niż zażądała struktura kamery. W tym przypadku należy zastosować metodę returnStreamBuffers . Jeśli implementacja HAL nigdy nie przechowuje więcej buforów niż żądano, implementacja HAL kamery nie musi wywoływać metody returnStreamBuffers .

SignalStreamFlush

Metoda signalStreamFlush jest wywoływana przez platformę kamery w celu powiadomienia warstwy HAL kamery o konieczności zwrócenia wszystkich dostępnych buforów. Jest to zwykle wywoływane, gdy struktura kamery ma zamiar configureStreams i musi opróżnić potok przechwytywania kamery. Podobnie jak w przypadku metody returnStreamBuffers , jeśli implementacja HAL kamery nie przechowuje więcej buforów niż żądano, możliwa jest pusta implementacja tej metody.

Gdy struktura kamery wywoła funkcję signalStreamFlush , platforma przestaje wysyłać nowe żądania przechwytywania do warstwy HAL kamery, dopóki wszystkie bufory nie zostaną zwrócone do struktury kamery. Po zwróceniu wszystkich buforów wywołania metody requestStreamBuffers kończą się niepowodzeniem i struktura kamery może kontynuować pracę w czystym stanie. Następnie struktura kamery wywołuje configureStreams lub processCaptureRequest . Jeśli struktura kamery wywoła configureStreams , warstwa HAL kamery może ponownie rozpocząć żądanie buforów po pomyślnym powrocie wywołania configureStreams . Jeśli struktura kamery wywoła metodę processCaptureRequest , warstwa HAL kamery może rozpocząć żądanie buforów podczas wywołania processCaptureRequest .

Semantyka metody signalStreamFlush i metody flush jest inna. Po wywołaniu metody flush HAL może przerwać oczekujące żądania przechwytywania za pomocą ERROR_REQUEST w celu jak najszybszego opróżnienia potoku. Po wywołaniu metody signalStreamFlush warstwa HAL musi normalnie zakończyć wszystkie oczekujące żądania przechwytywania i zwrócić wszystkie bufory do struktury kamery.

Inną różnicą między metodą signalStreamFlush a innymi metodami jest to, że signalStreamFlush jest jednokierunkową metodą HIDL, co oznacza, że ​​struktura kamery może wywoływać inne blokujące interfejsy API, zanim warstwa HAL odbierze wywołanie signalStreamFlush . Oznacza to, że metoda signalStreamFlush i inne metody (w szczególności configureStreams ) mogą dotrzeć do warstwy HAL kamery w innej kolejności niż kolejność, w jakiej zostały wywołane w środowisku kamery. Aby rozwiązać ten problem z asynchronią, do StreamConfiguration dodano pole streamConfigCounter i dodano je jako argument metody signalStreamFlush . Implementacja warstwy HAL kamery powinna używać argumentu streamConfigCounter w celu ustalenia, czy wywołanie signalStreamFlush nadejdzie później niż odpowiadające mu wywołanie configureStreams . Zobacz rysunek 3 jako przykład.

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

Rysunek 3. Jak kamera HAL powinna wykrywać i obsługiwać spóźnione wywołania SignalStreamFlush

Zachowanie zmienia się podczas implementowania interfejsów API zarządzania buforami

Korzystając z interfejsów API zarządzania buforami do implementacji logiki zarządzania buforami, należy wziąć pod uwagę następujące możliwe zmiany zachowania kamery i implementacji warstwy HAL kamery:

  • Żądania przechwytywania docierają do warstwy HAL kamery szybciej i częściej: bez interfejsów API do zarządzania buforami struktura kamery żąda buforów wyjściowych dla każdego żądania przechwytywania przed wysłaniem żądania przechwytywania do warstwy HAL kamery. Podczas korzystania z interfejsów API zarządzania buforami struktura kamery nie musi już czekać na bufory i dlatego może wcześniej wysyłać żądania przechwytywania do warstwy HAL kamery.

    Ponadto bez interfejsów API do zarządzania buforami struktura kamery przestaje wysyłać żądania przechwytywania, jeśli jeden ze strumieni wyjściowych żądania przechwytywania osiągnął maksymalną liczbę buforów, jakie warstwa HAL może pomieścić jednocześnie (wartość ta jest wyznaczana przez warstwę HAL kamery w Pole HalStream::maxBuffers w wartości zwracanej przez wywołanie configureStreams ). W przypadku interfejsów API zarządzania buforami to zachowanie ograniczające już nie występuje, a implementacja warstwy HAL kamery nie może akceptować wywołań processCaptureRequest , gdy warstwa HAL ma w kolejce zbyt wiele żądań przechwytywania.

  • Opóźnienie wywołania requestStreamBuffers znacznie się różni: Istnieje wiele powodów, dla których wywołanie requestStreamBuffers może zająć więcej czasu niż przeciętnie. Na przykład:

    • W przypadku kilku pierwszych buforów nowo utworzonego strumienia wywołania mogą trwać dłużej, ponieważ urządzenie musi przydzielić pamięć.
    • Oczekiwane opóźnienie wzrasta proporcjonalnie do liczby buforów żądanych w każdym wywołaniu.
    • Aplikacja przechowuje bufory i jest zajęta przetwarzaniem. Może to spowodować spowolnienie żądań bufora lub przekroczenie limitu czasu z powodu braku buforów lub zajętego procesora.

Strategie zarządzania buforami

Interfejsy API zarządzania buforami umożliwiają wdrażanie różnych rodzajów strategii zarządzania buforami. Oto kilka przykładów:

  • Kompatybilny wstecz: warstwa HAL żąda buforów dla żądania przechwytywania podczas wywołania processCaptureRequest . Strategia ta nie zapewnia żadnych oszczędności pamięci, ale może służyć jako pierwsza implementacja interfejsów API zarządzania buforami, wymagająca bardzo niewielu zmian w kodzie w istniejącej warstwie HAL kamery.
  • Maksymalna oszczędność pamięci: kamera HAL żąda buforów wyjściowych tylko bezpośrednio przed koniecznością ich zapełnienia. Strategia ta umożliwia maksymalizację oszczędności pamięci. Potencjalną wadą jest większe zacinanie się potoku kamery, gdy żądania bufora trwają niezwykle długo.
  • Buforowana: kamera HAL buforuje kilka buforów, dzięki czemu jest mniej prawdopodobne, że sporadyczne żądania powolnego bufora będą miały na nią wpływ.

Kamera HAL może przyjąć różne strategie dla konkretnych przypadków użycia, na przykład stosując strategię maksymalnego oszczędzania pamięci dla przypadków użycia, które zużywają dużo pamięci i stosując strategię kompatybilności wstecznej dla innych przypadków użycia.

Przykładowa realizacja w kamerze zewnętrznej HAL

Kamera zewnętrzna HAL została wprowadzona w systemie Android 9 i można ją znaleźć w drzewie źródłowym pod hardware/interfaces/camera/device/3.5/ . W systemie Android 10 został zaktualizowany w celu dołączenia ExternalCameraDeviceSession.cpp , implementacji interfejsu API zarządzania buforami. Ta zewnętrzna kamera HAL implementuje strategię maksymalnego oszczędzania pamięci wspomnianą w Strategiach zarządzania buforami w kilkuset wierszach kodu C++.