10cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams/*
20cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * Copyright (C) 2012 The Android Open Source Project
30cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams *
40cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
50cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * you may not use this file except in compliance with the License.
60cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * You may obtain a copy of the License at
70cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams *
80cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
90cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams *
100cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * Unless required by applicable law or agreed to in writing, software
110cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
120cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * See the License for the specific language governing permissions and
140cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * limitations under the License.
150cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams */
160cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samspackage com.android.rs.livepreview;
170cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
180cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams//import com.android.cts.verifier.PassFailButtons;
190cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams//import com.android.cts.verifier.R;
200cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
210cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.app.Activity;
220cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.app.AlertDialog;
230cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.graphics.Bitmap;
240cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.graphics.Color;
250cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.graphics.ColorMatrix;
260cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.graphics.ColorMatrixColorFilter;
270cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.graphics.ImageFormat;
280cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.graphics.Matrix;
290cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.graphics.SurfaceTexture;
300cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.hardware.Camera;
310cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.os.AsyncTask;
320cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.os.Bundle;
330cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.os.Handler;
340cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.util.Log;
350cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.util.SparseArray;
360cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.view.View;
370cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.view.TextureView;
380cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.widget.AdapterView;
390cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.widget.ArrayAdapter;
400cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.widget.ImageView;
410cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.widget.Spinner;
420cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
430cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.io.IOException;
440cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.lang.InterruptedException;
450cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.lang.Math;
460cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.lang.Thread;
470cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.util.ArrayList;
480cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.util.Comparator;
490cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.util.List;
500cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport java.util.TreeSet;
510cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
520cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samsimport android.renderscript.*;
530cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
540cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams/**
550cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * Tests for manual verification of the CDD-required camera output formats
560cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams * for preview callbacks
570cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams */
580cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Samspublic class CameraPreviewActivity extends Activity
590cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        implements TextureView.SurfaceTextureListener, Camera.PreviewCallback {
600cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
610cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private static final String TAG = "CameraFormats";
620cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
630cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private TextureView mPreviewView;
640cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private SurfaceTexture mPreviewTexture;
650cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private int mPreviewTexWidth;
660cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private int mPreviewTexHeight;
670cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
680cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private ImageView mFormatView;
690cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
700cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private Spinner mCameraSpinner;
710cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private Spinner mResolutionSpinner;
720cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
730cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private int mCurrentCameraId = -1;
740cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private Camera mCamera;
750cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
760cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private List<Camera.Size> mPreviewSizes;
770cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private Camera.Size mNextPreviewSize;
780cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private Camera.Size mPreviewSize;
790cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
800cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private Bitmap mCallbackBitmap;
810cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
820cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private static final int STATE_OFF = 0;
830cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private static final int STATE_PREVIEW = 1;
840cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private static final int STATE_NO_CALLBACKS = 2;
850cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private int mState = STATE_OFF;
860cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private boolean mProcessInProgress = false;
870cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private boolean mProcessingFirstFrame = false;
880cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
890cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
900cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private RenderScript mRS;
910cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private RsYuv mFilterYuv;
920cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
930cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    @Override
940cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public void onCreate(Bundle savedInstanceState) {
950cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        super.onCreate(savedInstanceState);
960cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
970cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        setContentView(R.layout.cf_main);
980cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
990cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewView = (TextureView) findViewById(R.id.preview_view);
1000cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mFormatView = (ImageView) findViewById(R.id.format_view);
1010cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1020cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewView.setSurfaceTextureListener(this);
1030cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1040cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        int numCameras = Camera.getNumberOfCameras();
1050cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        String[] cameraNames = new String[numCameras];
1060cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        for (int i = 0; i < numCameras; i++) {
1070cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            cameraNames[i] = "Camera " + i;
1080cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
1090cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCameraSpinner = (Spinner) findViewById(R.id.cameras_selection);
1100cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCameraSpinner.setAdapter(
1110cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            new ArrayAdapter<String>(
1120cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                this, R.layout.cf_format_list_item, cameraNames));
1130cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
1140cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1150cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mResolutionSpinner = (Spinner) findViewById(R.id.resolution_selection);
1160cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mResolutionSpinner.setOnItemSelectedListener(mResolutionSelectedListener);
1170cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1180cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1190cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mRS = RenderScript.create(this);
1200cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
1210cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1220cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    @Override
1230cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public void onResume() {
1240cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        super.onResume();
1250cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1260cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        setUpCamera(mCameraSpinner.getSelectedItemPosition());
1270cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
1280cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1290cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    @Override
1300cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public void onPause() {
1310cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        super.onPause();
1320cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1330cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        shutdownCamera();
1340cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
1350cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1360cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public void onSurfaceTextureAvailable(SurfaceTexture surface,
1370cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            int width, int height) {
1380cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewTexture = surface;
1390cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewTexWidth = width;
1400cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewTexHeight = height;
1410cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        if (mCamera != null) {
1420cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            startPreview();
1430cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
1440cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
1450cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1460cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
1470cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        // Ignored, Camera does all the work for us
1480cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
1490cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1500cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
1510cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        return true;
1520cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
1530cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1540cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
1550cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        // Invoked every time there's a new Camera preview frame
1560cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
1570cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1580cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private AdapterView.OnItemSelectedListener mCameraSpinnerListener =
1590cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            new AdapterView.OnItemSelectedListener() {
1600cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                public void onItemSelected(AdapterView<?> parent,
1610cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                        View view, int pos, long id) {
1620cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    if (mCurrentCameraId != pos) {
1630cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                        setUpCamera(pos);
1640cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    }
1650cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                }
1660cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1670cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                public void onNothingSelected(AdapterView parent) {
1680cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1690cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                }
1700cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1710cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            };
1720cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1730cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private AdapterView.OnItemSelectedListener mResolutionSelectedListener =
1740cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            new AdapterView.OnItemSelectedListener() {
1750cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                public void onItemSelected(AdapterView<?> parent,
1760cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                        View view, int position, long id) {
1770cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    if (mPreviewSizes.get(position) != mPreviewSize) {
1780cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                        mNextPreviewSize = mPreviewSizes.get(position);
1790cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                        startPreview();
1800cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    }
1810cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                }
1820cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1830cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                public void onNothingSelected(AdapterView parent) {
1840cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1850cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                }
1860cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1870cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            };
1880cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1890cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1900cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private void setUpCamera(int id) {
1910cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        shutdownCamera();
1920cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1930cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCurrentCameraId = id;
1940cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCamera = Camera.open(id);
1950cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        Camera.Parameters p = mCamera.getParameters();
1960cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1970cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        // Get preview resolutions
1980cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
1990cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        List<Camera.Size> unsortedSizes = p.getSupportedPreviewSizes();
2000cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2010cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        class SizeCompare implements Comparator<Camera.Size> {
2020cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            public int compare(Camera.Size lhs, Camera.Size rhs) {
2030cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                if (lhs.width < rhs.width) return -1;
2040cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                if (lhs.width > rhs.width) return 1;
2050cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                if (lhs.height < rhs.height) return -1;
2060cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                if (lhs.height > rhs.height) return 1;
2070cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                return 0;
2080cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            }
2090cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        };
2100cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2110cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        SizeCompare s = new SizeCompare();
2120cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        TreeSet<Camera.Size> sortedResolutions = new TreeSet<Camera.Size>(s);
2130cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        sortedResolutions.addAll(unsortedSizes);
2140cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2150cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewSizes = new ArrayList<Camera.Size>(sortedResolutions);
2160cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2170cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        String[] availableSizeNames = new String[mPreviewSizes.size()];
2180cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        for (int i = 0; i < mPreviewSizes.size(); i++) {
2190cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            availableSizeNames[i] =
2200cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    Integer.toString(mPreviewSizes.get(i).width) + " x " +
2210cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    Integer.toString(mPreviewSizes.get(i).height);
2220cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
2230cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mResolutionSpinner.setAdapter(
2240cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            new ArrayAdapter<String>(
2250cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                this, R.layout.cf_format_list_item, availableSizeNames));
2260cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2270cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2280cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        // Set initial values
2290cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2300cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mNextPreviewSize = mPreviewSizes.get(0);
2310cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mResolutionSpinner.setSelection(0);
2320cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2330cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        if (mPreviewTexture != null) {
2340cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            startPreview();
2350cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
2360cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
2370cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2380cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private void shutdownCamera() {
2390cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        if (mCamera != null) {
2400cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.setPreviewCallbackWithBuffer(null);
2410cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.stopPreview();
2420cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.release();
2430cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera = null;
2440cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mState = STATE_OFF;
2450cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
2460cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
2470cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2480cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private void startPreview() {
2490cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        if (mState != STATE_OFF) {
2500cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            // Stop for a while to drain callbacks
2510cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.setPreviewCallbackWithBuffer(null);
2520cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.stopPreview();
2530cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mState = STATE_OFF;
2540cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            Handler h = new Handler();
2550cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            Runnable mDelayedPreview = new Runnable() {
2560cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                public void run() {
2570cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    startPreview();
2580cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                }
2590cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            };
2600cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            h.postDelayed(mDelayedPreview, 300);
2610cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            return;
2620cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
2630cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mState = STATE_PREVIEW;
2640cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2650cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        Matrix transform = new Matrix();
2660cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        float widthRatio = mNextPreviewSize.width / (float)mPreviewTexWidth;
2670cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        float heightRatio = mNextPreviewSize.height / (float)mPreviewTexHeight;
2680cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2690cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        transform.setScale(1, heightRatio/widthRatio);
2700cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        transform.postTranslate(0,
2710cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                mPreviewTexHeight * (1 - heightRatio/widthRatio)/2);
2720cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2730cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewView.setTransform(transform);
2740cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2750cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mPreviewSize   = mNextPreviewSize;
2760cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2770cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        Camera.Parameters p = mCamera.getParameters();
2780cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        p.setPreviewFormat(ImageFormat.NV21);
2790cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
2800cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCamera.setParameters(p);
2810cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2820cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCamera.setPreviewCallbackWithBuffer(this);
2830cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
2840cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
2850cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        for (int i=0; i < 4; i++) {
2860cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.addCallbackBuffer(new byte[expectedBytes]);
2870cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
2880cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        //mFormatView.setColorFilter(mYuv2RgbFilter);
2890cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2900cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mProcessingFirstFrame = true;
2910cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        try {
2920cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.setPreviewTexture(mPreviewTexture);
2930cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.startPreview();
2940cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        } catch (IOException ioe) {
2950cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            // Something bad happened
2960cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            Log.e(TAG, "Unable to start up preview");
2970cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
2980cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
2990cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
3000cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3010cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
302702fb2c502ee6bab5cced1835005e0e225533751Jason Sams    private class ProcessPreviewDataTask extends AsyncTask<byte[], Void, Boolean> {
303702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        protected Boolean doInBackground(byte[]... datas) {
304702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            byte[] data = datas[0];
305702fb2c502ee6bab5cced1835005e0e225533751Jason Sams
306702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            long t1 = java.lang.System.currentTimeMillis();
307702fb2c502ee6bab5cced1835005e0e225533751Jason Sams
3081ebb7202b68d18025de8755d4f1df0c6544397e3Jason Sams            mFilterYuv.execute(data, mCallbackBitmap);
309702fb2c502ee6bab5cced1835005e0e225533751Jason Sams
310702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            long t2 = java.lang.System.currentTimeMillis();
311702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            mTiming[mTimingSlot++] = t2 - t1;
312702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            if (mTimingSlot >= mTiming.length) {
313702fb2c502ee6bab5cced1835005e0e225533751Jason Sams                float total = 0;
314702fb2c502ee6bab5cced1835005e0e225533751Jason Sams                for (int i=0; i<mTiming.length; i++) {
315702fb2c502ee6bab5cced1835005e0e225533751Jason Sams                    total += (float)mTiming[i];
316702fb2c502ee6bab5cced1835005e0e225533751Jason Sams                }
317702fb2c502ee6bab5cced1835005e0e225533751Jason Sams                total /= mTiming.length;
318702fb2c502ee6bab5cced1835005e0e225533751Jason Sams                Log.e(TAG, "time + " + total);
319702fb2c502ee6bab5cced1835005e0e225533751Jason Sams                mTimingSlot = 0;
320702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            }
321702fb2c502ee6bab5cced1835005e0e225533751Jason Sams
322702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            mCamera.addCallbackBuffer(data);
323702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            mProcessInProgress = false;
324702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            return true;
325702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        }
326702fb2c502ee6bab5cced1835005e0e225533751Jason Sams
327702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        protected void onPostExecute(Boolean result) {
328702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            mFormatView.invalidate();
329702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        }
330702fb2c502ee6bab5cced1835005e0e225533751Jason Sams
331702fb2c502ee6bab5cced1835005e0e225533751Jason Sams    }
332702fb2c502ee6bab5cced1835005e0e225533751Jason Sams
3330cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private long mTiming[] = new long[50];
3340cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    private int mTimingSlot = 0;
3350cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3360cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    public void onPreviewFrame(byte[] data, Camera camera) {
3370cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        if (mProcessInProgress || mState != STATE_PREVIEW) {
3380cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.addCallbackBuffer(data);
3390cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            return;
3400cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
341702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        if (data == null) {
342702fb2c502ee6bab5cced1835005e0e225533751Jason Sams            return;
343702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        }
3440cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3450cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        int expectedBytes = mPreviewSize.width * mPreviewSize.height *
3460cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
3470cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3480cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        if (expectedBytes != data.length) {
3490cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            Log.e(TAG, "Mismatched size of buffer! Expected ");
3500cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3510cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mState = STATE_NO_CALLBACKS;
3520cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCamera.setPreviewCallbackWithBuffer(null);
3530cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            return;
3540cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
3550cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3560cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mProcessInProgress = true;
3570cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3580cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        if (mCallbackBitmap == null ||
3590cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                mPreviewSize.width != mCallbackBitmap.getWidth() ||
3600cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                mPreviewSize.height != mCallbackBitmap.getHeight() ) {
3610cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mCallbackBitmap =
3620cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                    Bitmap.createBitmap(
3630cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                        mPreviewSize.width, mPreviewSize.height,
3640cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams                        Bitmap.Config.ARGB_8888);
3650cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mFilterYuv = new RsYuv(mRS, getResources(), mPreviewSize.width, mPreviewSize.height);
3660cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams            mFormatView.setImageBitmap(mCallbackBitmap);
3670cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        }
3680cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3690cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3700cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mFormatView.invalidate();
3710cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3720cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams        mCamera.addCallbackBuffer(data);
373702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        mProcessInProgress = true;
374702fb2c502ee6bab5cced1835005e0e225533751Jason Sams        new ProcessPreviewDataTask().execute(data);
3750cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams    }
3760cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3770cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3780cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams
3790cb555ffcc30b79ae04a4dc6089863da4bb54852Jason Sams}