blob: 3edd78f34381903b24226c0099bd8f4dfad07778 [file] [log] [blame]
package com.android.testingcamera;
import android.content.res.Resources;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.Matrix4f;
import android.renderscript.RenderScript;
import android.renderscript.Script;
import android.renderscript.ScriptGroup;
import android.renderscript.ScriptIntrinsicColorMatrix;
import android.renderscript.Type;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceView;
/**
* Process preview callback data for display.
* This is done by constructing a two-step Renderscript group,
* the first of which converts from various YUV formats to 8bpp YUV, and
* the second of which converts from YUV to RGB.
*
* The processing is done in a background thread, and the result is produced
* into an Allocation that's backed by a SurfaceView
*/
class CallbackProcessor {
private SurfaceView mCallbackView;
private Surface mCallbackSurface;
private Object mTaskLock = new Object();
private RenderScript mRS;
private Allocation mAllocationIn;
private Allocation mAllocationOut;
private ScriptGroup mConverter;
private int mWidth;
private int mHeight;
private int mFormat;
private boolean mDone = false;
private boolean mTaskInProgress = false;
static final private int kStopTimeout = 2000; // ms
private static final String TAG = "CallbackProcessor";
public CallbackProcessor(int width, int height, int format,
Resources res, SurfaceView callbackView,
int viewWidth, int viewHeight,
RenderScript rs) {
mWidth = width;
mHeight = height;
mFormat = format;
mRS = rs;
mCallbackView = callbackView;
int inputSize = TestingCamera.getCallbackBufferSize(mWidth, mHeight,
mFormat);
mAllocationIn = Allocation.createSized(mRS, Element.U8(mRS), inputSize);
Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
tb.setX(viewWidth);
tb.setY(viewHeight);
Type outType = tb.create();
mAllocationOut = Allocation.createTyped(mRS, outType,
Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);
ScriptC_callback swizzleScript =
new ScriptC_callback(mRS, res, R.raw.callback);
swizzleScript.bind_yuv_in(mAllocationIn);
swizzleScript.invoke_init_convert(mWidth, mHeight,
mFormat, viewWidth, viewHeight);
Script.KernelID swizzleId;
switch (mFormat) {
case ImageFormat.NV21:
swizzleId = swizzleScript.getKernelID_convert_semiplanar();
break;
case ImageFormat.YV12:
swizzleId = swizzleScript.getKernelID_convert_planar();
break;
case ImageFormat.YUY2:
swizzleId = swizzleScript.getKernelID_convert_interleaved();
break;
case ImageFormat.UNKNOWN:
default:
swizzleId = swizzleScript.getKernelID_convert_unknown();
}
ScriptGroup.Builder b = new ScriptGroup.Builder(rs);
b.addKernel(swizzleId);
mConverter = b.create();
mConverter.setOutput(swizzleId, mAllocationOut);
}
public boolean stop() {
synchronized(mTaskLock) {
mDone = true;
long startTime = SystemClock.elapsedRealtime();
while (mTaskInProgress) {
try {
mTaskLock.wait(kStopTimeout);
} catch (InterruptedException e) {
// ignored, keep waiting
}
long endTime = SystemClock.elapsedRealtime();
if (endTime - startTime > kStopTimeout) {
return false;
}
}
}
mAllocationOut.setSurface(null);
return true;
}
public void displayCallback(byte[] data) {
synchronized(mTaskLock) {
if (mTaskInProgress || mDone) return;
mTaskInProgress = true;
}
if (mCallbackSurface == null) {
mCallbackView.getHolder().setFormat(PixelFormat.RGBA_8888);
mCallbackSurface = mCallbackView.getHolder().getSurface();
if (mCallbackSurface == null) return;
mAllocationOut.setSurface(mCallbackSurface);
}
new ProcessCallbackTask().execute(data);
}
private class ProcessCallbackTask extends AsyncTask<byte[], Void, Boolean> {
@Override
protected Boolean doInBackground(byte[]... datas) {
byte[] data = datas[0];
mAllocationIn.copyFrom(data);
mConverter.execute();
mAllocationOut.ioSend();
synchronized(mTaskLock) {
mTaskInProgress = false;
mTaskLock.notify();
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
}
}
}