1 package com.android.testingcamera; 2 3 import android.content.res.Resources; 4 import android.graphics.ImageFormat; 5 import android.graphics.PixelFormat; 6 import android.os.AsyncTask; 7 import android.os.SystemClock; 8 import android.renderscript.Allocation; 9 import android.renderscript.Element; 10 import android.renderscript.Matrix4f; 11 import android.renderscript.RenderScript; 12 import android.renderscript.Script; 13 import android.renderscript.ScriptGroup; 14 import android.renderscript.ScriptIntrinsicColorMatrix; 15 import android.renderscript.Type; 16 import android.util.Log; 17 import android.view.Surface; 18 import android.view.SurfaceView; 19 20 /** 21 * Process preview callback data for display. 22 * This is done by constructing a two-step Renderscript group, 23 * the first of which converts from various YUV formats to 8bpp YUV, and 24 * the second of which converts from YUV to RGB. 25 * 26 * The processing is done in a background thread, and the result is produced 27 * into an Allocation that's backed by a SurfaceView 28 */ 29 class CallbackProcessor { 30 private SurfaceView mCallbackView; 31 private Surface mCallbackSurface; 32 33 private Object mTaskLock = new Object(); 34 35 private RenderScript mRS; 36 private Allocation mAllocationIn; 37 private Allocation mAllocationOut; 38 private ScriptGroup mConverter; 39 40 private int mWidth; 41 private int mHeight; 42 private int mFormat; 43 44 private boolean mDone = false; 45 private boolean mTaskInProgress = false; 46 47 static final private int kStopTimeout = 2000; // ms 48 49 private static final String TAG = "CallbackProcessor"; 50 CallbackProcessor(int width, int height, int format, Resources res, SurfaceView callbackView, int viewWidth, int viewHeight, RenderScript rs)51 public CallbackProcessor(int width, int height, int format, 52 Resources res, SurfaceView callbackView, 53 int viewWidth, int viewHeight, 54 RenderScript rs) { 55 mWidth = width; 56 mHeight = height; 57 mFormat = format; 58 mRS = rs; 59 mCallbackView = callbackView; 60 61 int inputSize = TestingCamera.getCallbackBufferSize(mWidth, mHeight, 62 mFormat); 63 mAllocationIn = Allocation.createSized(mRS, Element.U8(mRS), inputSize); 64 65 Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS)); 66 tb.setX(viewWidth); 67 tb.setY(viewHeight); 68 Type outType = tb.create(); 69 70 mAllocationOut = Allocation.createTyped(mRS, outType, 71 Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT); 72 73 ScriptC_callback swizzleScript = new ScriptC_callback(mRS); 74 swizzleScript.bind_yuv_in(mAllocationIn); 75 swizzleScript.invoke_init_convert(mWidth, mHeight, 76 mFormat, viewWidth, viewHeight); 77 Script.KernelID swizzleId; 78 79 switch (mFormat) { 80 case ImageFormat.NV21: 81 swizzleId = swizzleScript.getKernelID_convert_semiplanar(); 82 break; 83 case ImageFormat.YV12: 84 swizzleId = swizzleScript.getKernelID_convert_planar(); 85 break; 86 case ImageFormat.YUY2: 87 swizzleId = swizzleScript.getKernelID_convert_interleaved(); 88 break; 89 case ImageFormat.UNKNOWN: 90 default: 91 swizzleId = swizzleScript.getKernelID_convert_unknown(); 92 } 93 94 ScriptGroup.Builder b = new ScriptGroup.Builder(rs); 95 b.addKernel(swizzleId); 96 mConverter = b.create(); 97 98 mConverter.setOutput(swizzleId, mAllocationOut); 99 } 100 stop()101 public boolean stop() { 102 synchronized(mTaskLock) { 103 mDone = true; 104 long startTime = SystemClock.elapsedRealtime(); 105 while (mTaskInProgress) { 106 try { 107 mTaskLock.wait(kStopTimeout); 108 } catch (InterruptedException e) { 109 // ignored, keep waiting 110 } 111 long endTime = SystemClock.elapsedRealtime(); 112 if (endTime - startTime > kStopTimeout) { 113 return false; 114 } 115 } 116 } 117 mAllocationOut.setSurface(null); 118 return true; 119 } 120 displayCallback(byte[] data)121 public void displayCallback(byte[] data) { 122 synchronized(mTaskLock) { 123 if (mTaskInProgress || mDone) return; 124 mTaskInProgress = true; 125 } 126 if (mCallbackSurface == null) { 127 mCallbackView.getHolder().setFormat(PixelFormat.RGBA_8888); 128 mCallbackSurface = mCallbackView.getHolder().getSurface(); 129 if (mCallbackSurface == null) return; 130 mAllocationOut.setSurface(mCallbackSurface); 131 } 132 new ProcessCallbackTask().execute(data); 133 } 134 135 private class ProcessCallbackTask extends AsyncTask<byte[], Void, Boolean> { 136 137 @Override doInBackground(byte[]... datas)138 protected Boolean doInBackground(byte[]... datas) { 139 byte[] data = datas[0]; 140 141 mAllocationIn.copyFrom(data); 142 mConverter.execute(); 143 mAllocationOut.ioSend(); 144 145 synchronized(mTaskLock) { 146 mTaskInProgress = false; 147 mTaskLock.notify(); 148 } 149 return true; 150 } 151 152 @Override onPostExecute(Boolean result)153 protected void onPostExecute(Boolean result) { 154 } 155 } 156 157 } 158