web-dev-qa-db-ja.com

JNIを使​​用してCで生のAndroidカメラバッファを取得するにはどうすればよいですか?

GoogleとStackOverflowを徹底的に検索してきましたが、見つかりません。多分私は明白な何かを逃しています。ありがとう!

(これは、Javaプレビューコールバックの実装[バッファがある場合でも]が非効率的すぎるためです。)

25
Nick

トピックについて少し調査しました。この プレゼンテーション (p.277、中国語から)は大いに役立ちました。

カメラプレビューコールチェーン

他の人が述べたように、_Camera.setPreviewCallback_メソッドを使用してバッファを取得できます。
そこで発生する方法は次のとおりです(詳細バージョン):

  1. ユーザーは、ネイティブ関数であるCamera.startPreview()を呼び出します。
  2. _Android_hardware_Camera_startPreview_は、C++ startPreviewクラスのCameraメソッドを呼び出します。
  3. CamerastartPreviewインターフェースのICameraメソッドを呼び出します
  4. ICameraはリモートクライアントにIPC呼び出しを行います。
  5. setCameraModeクラスのCameraServiceメソッドを呼び出します。
  6. CameraServiceは、プレビューを表示するウィンドウを設定し、startPreviewクラスのCameraHardwareInterfaceメソッドを呼び出します。
  7. 後者は、特定の_start_preview_デバイスで_camera_device_t_メソッドを呼び出そうとします。
    これ以上調べませんでしたが、ドライバーへの呼び出しを実行する必要があります。
  8. 画像が到着すると、dataCallbackCameraServiceが呼び出されます。
  9. クライアントのhandlePreviewDataメソッドにデータを渡します。
  10. クライアントはバッファをコピーするか、ICameraClientに直接送信します。
  11. ICameraClientはそれをIPC経由でCameraに送信します。
  12. Cameraは登録済みのリスナーを呼び出し、バッファをJNIに渡します。
  13. Javaクラスでコールバックを呼び出します。ユーザーが_Camera.addCallbackBuffer_でバッファーを提供した場合、最初にバッファーにコピーします。
  14. 最後に、Java class Cameraはメッセージを処理し、_Camera.PreviewCallback_のonPreviewFrameメソッドを呼び出します。

ご覧のとおり、手順10、11で2つのIPC呼び出しが呼び出され、バッファが少なくとも2回コピーされました。_camera_device_t_によって返されるrawバッファの最初のインスタンスは別のプロセスでホストされており、アクセスできません。 CameraServiceのセキュリティチェックが原因です。

プレビュー面

ただし、_Camera.setPreviewTexture_または_Camera.setPreviewDisplay_のいずれかを使用してプレビューサーフェスを設定すると、プレビューサーフェスはカメラデバイスに直接渡され、上記のすべてのチェーンに参加することなくリアルタイムで更新されます。ドキュメントにあるように:

スクリーンコンポジターによって管理されているrawバッファーを処理します。

JavaクラスSurfaceには、その内容を取得するメソッドがあります。

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

しかし、このAPIは隠されています。使用方法については、 この質問 を参照してください。

25
Andrey Ermakov

やりたいことをするためのパブリックAPIはありません。唯一の公式の(つまり、動作が保証されている)メソッドは、 Camera.setPreviewCallback() を呼び出すことによって設定されるJavaレベルのプレビューコールバックです。 Android> 3.0では、 Camera.setPreviewTexture() を使用してプレビューデータをGPUにルーティングし、GLESを使用してそこで処理する(または読み戻す)こともできます。 GPUパスは、ICS AOSPカメラアプリケーションがビデオエフェクトに使用するものです。

おそらく、OpenCVなどはAndroidフレームワークのネイティブコードを調べ、Java Camera APIをバイパスして、以下のサービスと直接通信しました。

これらのインターフェースはパブリックAPIの一部ではないため、Androidバージョン間で変更されないという保証はまったくないため、これはかなり危険です。それらを使用することは、時々問題ないかもしれません。ユーザーがデバイスをアップグレードすると、アプリは機能しなくなります。

5
Eddy Talvala

OpenCV for Android をご覧になりましたか。彼らの 高度なチュートリアル はJNIの使用方法を示しており、カメラパッケージにはNativeProcessorオブジェクトが含まれています。

1
Jeff