私はGLSurfaceView
でアンドロイドの電話カメラからプレビューをレンダリングし、利用可能になるとすぐにフレームを保存します。フレームをSDカードに保存するには、2つの呼び出しの間の時間よりもはるかに時間がかかるので、画面からピクセルを読み取った後、別のスレッドで処理しています。Javaはバッファ読み取りでスレッドを同期させます
public void onDrawFrame(GL10 gl) {
//Process the frame, display it on the screen and other stuff
//Read pixels from the screen into my buffer
glReadPixels(0, 0, offscreenSize_.x, offscreenSize_.y, GL_RGBA, GL_UNSIGNED_BYTE,
intBuffer.clear());
// At the moment this has a counter and happens every 150ms
if(saveImage)
{
Thread thread = new Thread() {
@Override
public void run() {
// Convert to an array for Bitmap.createBitmap().
final int[] pixels = new int[intBuffer.capacity()];
intBuffer.rewind();
intBuffer.get(pixels);
try {
// Create/access a pictures subdirectory.
File directory = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"TangoFrames");
if (!directory.mkdirs() && !directory.isDirectory()) {
Log.d("WRITE ERR", "Couldn't create directory");
return;
}
// Get the current capture index to construct a unique filename.
SharedPreferences prefs = activity_.getPreferences(Context.MODE_PRIVATE);
int index = prefs.getInt("index", 0);
SharedPreferences.Editor prefsEditor = prefs.edit();
prefsEditor.putInt("index", index + 1);
prefsEditor.apply();
// Create the capture file.
File file = new File(directory, String.format("tango%05d.png", index));
FileOutputStream fileOutputStream = new FileOutputStream(file);
// Bitmap conveniently provides file output.
Bitmap bitmap = Bitmap.createBitmap(pixels, offscreenSize_.x, offscreenSize_.y, Bitmap.Config.ARGB_8888);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fileOutputStream);
fileOutputStream.close();
numberOfFrames++;
}
catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
}
}
私の問題は、スレッドが遅れて開始したとき、時々フレームのための読み取りが開始されるということが起こるということです。
final int[] pixels = new int[intBuffer.capacity()];
intBuffer.rewind();
intBuffer.get(pixels);
は次のコールバックが発射されるとintBuffer.clear()
が実行されるので、残りは腐敗する。 スレッドを同期させると、バッファがいっぱいになるたびに実行され、スレッドの実行中にバッファがクリアされないように注意してください。