Как получить необработанный буфер камеры Android в C с помощью JNI?

Я искал Google и StackOverflow исчерпывающе и не могу найти это. Может быть, мне не хватает чего-то очевидного. Благодаря!

(Это связано с тем, что реализация Java в режиме предварительного просмотра [даже с буфером] слишком неэффективна.)

Я сделал небольшое исследование по теме. Эта презентация (от стр.277, китайский) очень помогла.

Цепочка вызова предварительного просмотра камеры

Как уже упоминалось, вы можете получить буфер, используя метод Camera.setPreviewCallback .
Вот как это происходит (расширенная версия):

  1. Пользователь вызывает Camera.startPreview() который является нативной функцией.
  2. android_hardware_Camera_startPreview вызывает метод startPreview класса C ++ Camera .
  3. Camera вызывает метод ICamera интерфейса ICamera
  4. ICamera делает IPC вызов удаленному клиенту.
  5. Он вызывает метод CameraService класса CameraService .
  6. CameraService устанавливает окно для отображения предварительного просмотра и вызывает метод CameraHardwareInterface класса CameraHardwareInterface .
  7. Последний пытается вызвать метод start_preview на конкретном устройстве camera_device_t .
    Я больше не искал, но он должен выполнить звонок к драйверу.
  8. Когда изображение прибывает, dataCallback CameraService .
  9. Он передает данные в метод handlePreviewData клиента.
  10. Клиент либо копирует буфер, либо отправляет его непосредственно в ICameraClient .
  11. ICameraClient отправляет его по IPC на Camera .
  12. Camera вызывает зарегистрированного слушателя и передает буфер в JNI .
  13. Он вызывает обратный вызов в Java-классе. Если пользователь предоставил буфер с Camera.addCallbackBuffer он сначала копирует его в буфер.
  14. Наконец, Java-класс Camera обрабатывает сообщение и вызывает метод Camera.PreviewCallback для Camera.PreviewCallback .

Как вы видите, были вызваны 2 вызова IPC и буфер был скопирован как минимум дважды на шагах 10, 11. Первый экземпляр необработанного буфера, который возвращается camera_device_t , размещен в другом процессе, и вы не можете получить к нему доступ из-за проверок безопасности в CameraService .

Предварительная поверхность

Однако, когда вы устанавливаете поверхность предварительного просмотра, используя либо Camera.setPreviewTexture либо Camera.setPreviewDisplay она передается непосредственно на устройство камеры и обновляется в реальном времени без участия всей вышеперечисленной цепи. Как говорится в документации:

Обработайте необработанный буфер, которым управляет экранный компоновщик.

Класс Java Surface имеет метод для извлечения его содержимого:

 public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer); 

Но этот API скрыт. Смотрите, например, этот вопрос , чтобы использовать его.

Нет публичного API, чтобы делать то, что вы хотите; Единственным официальным (то есть гарантированным для работы) методом является обратный вызов предварительного просмотра на уровне Java, настроенный посредством вызова Camera.setPreviewCallback () . В Android> 3.0 вы также можете использовать Camera.setPreviewTexture () для маршрутизации данных предварительного просмотра на GPU и обрабатывать его там, используя GLES (или считывать его обратно в CPU). Путь GPU – это то, что использует приложение камеры ICS AOSP для своих видеоэффектов.

Предположительно, OpenCV и другие просмотрели собственный код платформы Android и обошли API Java Camera API, напрямую связавшись с услугами ниже.

Это довольно опасно, потому что нет абсолютно никакой гарантии, что эти интерфейсы не изменятся между версиями Android, поскольку они не являются частью публичного API. Теперь их использование может быть прекрасным, а затем, когда пользователь обновит свое устройство, ваше приложение перестанет работать.

Вы взглянули на OpenCV для Android . Их расширенные руководства показывают, как использовать JNI, и в пакете камеры есть объект NativeProcessor.

Intereting Posts
Разрешение на запись на SD-карту Диалог Android отклоняется только при втором щелчке. Зачем? SSLHandshakeException на Android 4.4 и ниже Android: когда использовать onStart (), onStop ()? Как использовать внутренний динамик для воспроизведения звука при подключении 3,5-мм разъема для записи звука с помощью внешнего микрофона Как рассчитать точное количество шагов ноги с помощью акселерометра в android? Соединение было отказано при попытке подключиться к моему серверу REST с эмулятора Android Как я могу запустить это утверждение с помощью RxJava? Как создать пользовательскую кнопку в Android с помощью стилей XML Android, как установить непрозрачность в bitmap xml Как загрузить изображение из dataurl в образе просмотра Android? Как создать дамп Java Thread в Android? Альфа-фон на FAB нажал Android-Jenkins: не удалось найти версию Build Tools 17.0.0 На Jenkins Build Server Android: ViewPagerIndicator – создание разных макетов для разных страниц