Home | History | Annotate | Download | only in testingcamera
      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 
     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 
    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 
    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
    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
    153         protected void onPostExecute(Boolean result) {
    154         }
    155     }
    156 
    157 }
    158