Самая низкая потолочная камера к процессору с GPU на Android

Моему приложению необходимо выполнить некоторую обработку кадров видео в реальном времени на процессоре, прежде чем отображать их на графическом процессоре. Есть также некоторые другие вещи, визуализируемые на GPU, которые зависят от результатов обработки CPU; поэтому важно поддерживать синхронизацию всего, чтобы мы не отображали сам кадр на графическом процессоре до тех пор, пока не будут доступны результаты обработки ЦП для этого кадра.

Вопрос в том, каков самый низкий уровень накладных расходов для этого на Android?

Для обработки ЦП в моем случае просто требуется изображение в градациях серого, поэтому формат YUV, в котором упакована плоскость Y, идеален (и, как правило, также хорошо подходит к собственному формату устройств камеры). NV12, NV21 или полностью плоский YUV обеспечат идеальный доступ с низким уровнем издержек к оттенкам серого, так что это будет предпочтительным на стороне процессора.

В исходном API камеры функция setPreviewCallbackWithBuffer () была единственным разумным способом передачи данных в ЦП для обработки. Эта плоскость Y была отдельной, поэтому была идеальной для обработки процессора. Получение этого фрейма в OpenGL для рендеринга с минимальными издержками было более сложным аспектом. В конце я написал подпрограмму преобразования цвета NEON для вывода RGB565 и просто использовал glTexSubImage2d, чтобы получить ее в графическом процессоре. Впервые это было реализовано на таймфрейме Nexus 1, где даже вызов glTexSubImage2d 320x240 занимал 50 мс процессорного времени (я полагаю, плохие драйверы, пытавшиеся извергать текстуры, значительно улучшились при обновлении системы позже).

В свое время я изучал такие вещи, как расширения eglImage, но они, похоже, не доступны или недостаточно документированы для пользовательских приложений. Я немного ознакомился с внутренними классами GraphicsBuffer для Android, но в идеале хочу остаться в мире поддерживаемых общедоступных API.

API android.hardware.camera2 обещал возможность подключать ImageReader и SurfaceTexture к сеансу захвата. К сожалению, я не вижу здесь никакого способа обеспечить правильный последовательный конвейер - откладывание вызова updateTexImage () до тех пор, пока процессор не обработает, достаточно просто, но если во время этой обработки прибыл другой кадр, то updateTexImage () пропустит сразу до последней Рамка. Также кажется, что с несколькими выходами будут независимые копии кадров в каждой из очередей, которых в идеале я бы хотел избежать.

В идеале это то, что я хотел бы:

Драйвер камеры заполняет память последним кадромCPU получает указатель на данные в памяти, может читать Y-данные без копированияCPU обрабатывает данные и устанавливает флаг в моем коде, когда кадр готовВ начале рендеринга кадра проверьте, готов ли новый кадрВызовите некоторый API, чтобы связать ту же память, что и текстура GLКогда новый кадр будет готов, освободите буфер, удерживающий предыдущий кадр, обратно в пул

Я не вижу способа сделать именно этот стиль с нулевым копированием с помощью публичного API на Android, но какой из них ближе всего?

Одна сумасшедшая вещь, которую я попробовал, похоже, работает, но не документирована: ANativeWindow NDK API может принимать данные формата NV12, даже если соответствующая константа формата не является одной из тех, что указаны в общедоступных заголовках. Это позволяет заполнить SurfaceTexture данными NV12 с помощью memcpy (), чтобы избежать преобразования цвета на стороне процессора и любых отклонений, происходящих на стороне драйвера в glTexImage2d. Это все еще дополнительная копия данных, хотя такое ощущение, что она должна быть ненужной, и опять же, поскольку она недокументирована, она может работать не на всех устройствах. Поддерживаемая последовательная нулевая копия Camera -> ImageReader -> SurfaceTexture или эквивалентная будет идеальной.

Ответы на вопрос(1)

Ваш ответ на вопрос