問(wèn)題描述
我一直在徹底搜索 Google 和 StackOverflow,但找不到這個(gè).也許我錯(cuò)過(guò)了一些明顯的東西.謝謝!
I've been searching Google and StackOverflow exhaustively and cannot find this. Maybe I'm missing something obvious. Thanks!
(這是因?yàn)轭A(yù)覽回調(diào)的Java實(shí)現(xiàn)[即使有緩沖區(qū)]效率太低.)
(This is because the Java implementation of the preview callback [even with buffer] is too inefficient.)
推薦答案
我對(duì)主題做了一點(diǎn)調(diào)查.這個(gè)介紹(來(lái)自p.277,中文)幫助很大.
I made a little investigation on topic. This presentation (from p.277, Chinese) helped a lot.
正如其他人提到的,您可以使用 Camera.setPreviewCallback
方法獲取緩沖區(qū).
以下是它的發(fā)生方式(詳細(xì)版本):
As others mentioned, you can get a buffer using a Camera.setPreviewCallback
method.
Here's how it happens there (a verbose version):
- 用戶調(diào)用
Camera.startPreview()
這是一個(gè)原生函數(shù). android_hardware_Camera_startPreview
調(diào)用C++Camera
類的startPreview
方法.Camera
調(diào)用ICamera
接口的startPreview
方法ICamera
對(duì)遠(yuǎn)程客戶端進(jìn)行IPC
調(diào)用.- 調(diào)用
CameraService
類的setCameraMode
方法. CameraService
設(shè)置一個(gè)窗口顯示預(yù)覽并調(diào)用CameraHardwareInterface
類的startPreview
方法.- 后者嘗試在特定
camera_device_t
設(shè)備上調(diào)用start_preview
方法.
我沒(méi)有進(jìn)一步查找,但它應(yīng)該會(huì)調(diào)用驅(qū)動(dòng)程序. - 當(dāng)圖片到達(dá)時(shí),調(diào)用
CameraService
的dataCallback
. - 將數(shù)據(jù)傳遞給客戶端的
handlePreviewData
方法. - 客戶端要么復(fù)制緩沖區(qū),要么直接將其發(fā)送到
ICameraClient
. ICameraClient
通過(guò)IPC
將其發(fā)送到Camera
.Camera
調(diào)用已注冊(cè)的監(jiān)聽(tīng)器并將緩沖區(qū)傳遞給JNI
.- 它調(diào)用 Java 類中的回調(diào).如果用戶使用
Camera.addCallbackBuffer
提供了一個(gè)緩沖區(qū),則它首先復(fù)制到緩沖區(qū). - 最后,Java 類
Camera
處理消息并調(diào)用Camera.PreviewCallback
的onPreviewFrame
方法.
- User calls
Camera.startPreview()
which is a native function. android_hardware_Camera_startPreview
callsstartPreview
method of C++Camera
class.Camera
calls astartPreview
method ofICamera
interfaceICamera
makes anIPC
call to remote client.- It calls a
setCameraMode
method ofCameraService
class. CameraService
sets a window to display a preview and calls astartPreview
method ofCameraHardwareInterface
class.- The latter tries to call a
start_preview
method on particularcamera_device_t
device.
I didn't looked up further but it should perform a call to the driver. - When image arrives,
dataCallback
ofCameraService
is invoked. - It passes data to
handlePreviewData
method of client. - Client either copies the buffer or sends it directly to the
ICameraClient
. ICameraClient
sends it overIPC
to theCamera
.Camera
calls a registered listener and passes buffer toJNI
.- It invokes a callback in Java class. If user provided a buffer with
Camera.addCallbackBuffer
then it copies to the buffer first. - Finally Java class
Camera
handles the message and invokes aonPreviewFrame
method ofCamera.PreviewCallback
.
如您所見(jiàn),調(diào)用了 2 個(gè) IPC
調(diào)用,并且在步驟 10、11 中至少?gòu)?fù)制了兩次緩沖區(qū).camera_device_t
返回的原始緩沖區(qū)的第一個(gè)實(shí)例是托管在另一個(gè)進(jìn)程中,由于 CameraService
中的安全檢查,您無(wú)法訪問(wèn)它.
As you can see 2 IPC
calls were invoked and buffer was copied at least twice on steps 10, 11. First instance of raw buffer which is returned by camera_device_t
is hosted in another process and you cannot access it due to security checks in CameraService
.
但是,當(dāng)您使用 Camera.setPreviewTexture
或 Camera.setPreviewDisplay
設(shè)置預(yù)覽表面時(shí),它會(huì)直接傳遞給相機(jī)設(shè)備并實(shí)時(shí)刷新,而無(wú)需上面的所有鏈條.正如它的文檔所說(shuō):
However, when you set a preview surface using either Camera.setPreviewTexture
or Camera.setPreviewDisplay
it is be passed directly to the camera device and refreshed in realtime without participation of all the chain above. As it's documentation says:
處理一個(gè)由屏幕合成器管理的原始緩沖區(qū).
Handle onto a raw buffer that is being managed by the screen compositor.
Java 類 Surface
有一個(gè)方法來(lái)檢索它的內(nèi)容:
Java class Surface
has a method to retrieve it's contents:
public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
但是這個(gè) API 是隱藏的.參見(jiàn) 這個(gè)問(wèn)題 了解使用方法.
But this API is hidden. See i.e. this question for a way to use it.
這篇關(guān)于如何使用 JNI 在 C 中獲取原始 Android 相機(jī)緩沖區(qū)?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!