Я искал Google и StackOverflow исчерпывающе и не могу найти это. Может быть, мне не хватает чего-то очевидного. Спасибо!
(Это связано с тем, что реализация Java в режиме предварительного просмотра [даже с буфером] слишком неэффективна.)
Я искал Google и StackOverflow исчерпывающе и не могу найти это. Может быть, мне не хватает чего-то очевидного. Спасибо!
(Это связано с тем, что реализация Java в режиме предварительного просмотра [даже с буфером] слишком неэффективна.)
Я провел небольшое исследование по теме. Это презентация (от стр .277, китайский) очень помогло.
Как уже упоминалось, вы можете получить буфер с помощью метода Camera.setPreviewCallback
.
Вот как это происходит (подробная версия):
Camera.startPreview()
, который является нативной функцией.android_hardware_Camera_startPreview
вызывает метод startPreview
класса С++ Camera
.Camera
вызывает метод startPreview
интерфейса ICamera
ICamera
вызывает вызов IPC
для удаленного клиента.setCameraMode
класса CameraService
.CameraService
устанавливает окно для отображения предварительного просмотра и вызывает метод startPreview
класса CameraHardwareInterface
.start_preview
на конкретном устройстве camera_device_t
. Я больше не искал, но он должен выполнить вызов драйвера.dataCallback
of CameraService
.handlePreviewData
клиента.ICameraClient
.ICameraClient
отправляет его через IPC
в Camera
.Camera
вызывает зарегистрированный прослушиватель и передает буфер на JNI
.Camera.addCallbackBuffer
, он сначала копирует его в буфер.Camera
обрабатывает сообщение и вызывает метод onPreviewFrame
Camera.PreviewCallback
.Как вы можете видеть, вызовы 2 IPC
были вызваны, и буфер был скопирован по меньшей мере дважды на шагах 10, 11. Первый экземпляр необработанного буфера, который возвращается camera_device_t
, размещен в другом процессе, и вы не можете получить доступ к нему из-за для проверок безопасности в CameraService
.
Однако, когда вы устанавливаете поверхность предварительного просмотра, используя либо Camera.setPreviewTexture
, либо Camera.setPreviewDisplay
, он передается непосредственно на устройство камеры и обновляется в реальном времени без участия всей вышеперечисленной цепи. Как говорится в документации:
Обработайте необработанный буфер, который управляется компоновщиком экрана.
Java class Surface
имеет способ извлечения содержимого:
public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
Но этот API скрыт. См., Например, этот вопрос, чтобы использовать его.
Нет никакого общедоступного API, чтобы делать то, что вы хотите; единственным официальным (то есть гарантированным для работы) методом является обратный вызов предварительного просмотра на уровне Java, настроенный посредством вызова Camera.setPreviewCallback(). В Android > 3.0 вы также можете использовать Camera.setPreviewTexture() для маршрутизации данных предварительного просмотра на графический процессор и обрабатывать его там, используя GLES (или считывать его обратно в CPU). Путь GPU - это то, что использует приложение камеры ICS AOSP для своих видеоэффектов.
Предположительно, OpenCV и другие просмотрели собственный код платформы Android и обошли API Java Camera API, напрямую связавшись с услугами ниже.
Это довольно опасно, потому что нет абсолютно никакой гарантии, что эти интерфейсы не изменятся между версиями Android, поскольку они не являются частью публичного API. Теперь их использование может быть прекрасным, а затем, когда пользователь обновит свое устройство, ваше приложение перестанет работать.
Вы взглянули на OpenCV для Android. Их расширенные учебные пособия показывают, как использовать JNI, и в своем пакете камеры есть объект NativeProcessor.