4

だから私はカメラアプリに似たものに取り組んでいます。ネイティブの OpenGL テクスチャにライブ カメラ プレビューを描画します。ボタンを押すと、静止画像が生の形式でキャプチャされます (ライブ プレビューよりも高い解像度である可能性があります)。

これが私のコードの一般的な概要です。わかりやすくするために、関連性の低い部分は表示していません。これは、プレビューと静止画の解像度が同じである単純化された状況です。

void Setup(Activity a) {

  // .. snip ..

  mSurfaceView = new SurfaceView(a);
  mSurfaceView.getHolder().addCallback(this);
  //put the surface off-screen
  AbsoluteLayout.LayoutParams alp = new AbsoluteLayout.LayoutParams(8, 8, -8, -8); 
  a.addContentView(mSurfaceView, alp); //need this, otherwise surface is not created

  mCamera = Camera.open(miCameraId);
  mCamera.setPreviewCallbackWithBuffer(this);

  ConfigureCameraDefaults(640,480);
}

// -------------------------------------------------------------------- //

void ConfigureCameraDefaults(int iX, int iY) {
  Camera.Parameters oParameters=mCamera.getParameters();

  oParameters.setPreviewFormat(ImageFormat.NV21);
  oParameters.setPictureFormat(ImageFormat.NV21);
  oParameters.setPreviewSize(iX, iY); // for live preview
  oParameters.setPictureSize(iX, iY); // for still capture

  int bpp = ImageFormat.getBitsPerPixel(ImageFormat.NV21);
  int iBufSize = (int) (iX*iY*((float)bpp/8));
  mBuffer = new byte[iBufSize];
  mCamera.addCallbackBuffer(mBuffer);

  try {
      mCamera.setParameters(oParameters);
  } catch (Exception e) {
      // .. snip ..
  }
}

void startPreview() {
  mCamera.startPreview();
}

void stopPreview() {
  mCamera.stopPreview();
}

void takePicture() {
  mCamera.takePicture(null, this, null, null); //2nd is the raw callback
}

// -------------------------------------------------------------------- //

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
  // -- at this point the buffer is in a safe state, until it is added again
  onPreviewFrame_native(data);

  // -- make buffer writable again
  mCamera.addCallbackBuffer(mBuffer);
}

@Override
public void onPictureTaken(byte[] data, Camera camera) {
  onStillCapture_native(data);
  mCamera.startPreview(); //otherwise preview will stop
}

では、質問です。が呼び出されない場合takePicture()、すべてが計画どおりに機能します。プレビュー フレームが到着し、処理され、バッファが再キューイングされます。ただし、startPreview()その後にするtakePicture()と、ピクチャ コールバックは null データ配列を取得します。毎回。Googleドキュメントには、これについて次のように書かれていtakePicture()ます:

The raw callback occurs when the raw image data is available (NOTE: the data will be null if there is no raw image callback buffer available or the raw image callback buffer is not large enough to hold the raw image).

次のように、これは私には完全には明らかではありません。

  1. 静止キャプチャ用のバッファを設定する機能はありません。前のフレームのみです。
  2. 静止画とプレビュー フレームの両方に同じバッファーが使用されている場合でも、バッファーがキューに入れられます。
  3. 静止画用に 2 番目のバッファー (プレビュー バッファーと同じ) を追加しても、まったく効果がありません
  4. takePicture()を有効な呼び出しにするためには、プレビューを開始する必要があります。

明らかな何かが欠けていますか?それとも、ビデオから生のフレームを取得することは許可されていませんか? これに関するドキュメントには何もありません。カメラのソースも見ましたが、役に立ちませんでした。

どんな助けでも大歓迎です。

PS。写真を撮る前にプレビュー コールバックを設定解除し、2 番目のバッファーを追加し、2 番目のバッファーを再度キューに入れ、サーフェス ホルダーをプッシュ タイプに設定し、その他いくつかのことを試してみましたが、一瞬。どれも違いはありませんでした。

4

1 に答える 1

0

生の画像を取得する方法はないようです。このメソッドaddCallbackBufferは、プレビュー コールバックでのみ使用されます。addRawImageCallbackBufferあなたが望むことをするはずの別の方法があります。公開されていますが、エクスポートされていないため、直接呼び出すことはできません。次のように呼び出すことができます。

    try {
        final Method addRawImageCallbackBuffer =
                camera0.getClass()
                       .getDeclaredMethod("addRawImageCallbackBuffer",
                                          byte[].class);
        addRawImageCallbackBuffer.invoke(camera0, new byte[100000000]);
    } catch (Exception e) {
        Log.e("RNG", "Error", e);
    }

しかし、私のNexus 5ではまだnullコールバックで返されるので、単にサポートされていないと思います.

于 2014-03-10T08:09:46.683 に答える