安卓相机的AsyncTask用preVIEW回调 [英] Android: Camera Asynctask with Preview Callback

查看:202
本文介绍了安卓相机的AsyncTask用preVIEW回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经成功地得到相机preVIEW自定义过滤器(灰度,色调等)工作。这种定制过滤器是通过操纵RGB的数组,然后拉回来到画布上,然后在表面视图中显示它应用了preVIEW回调。

I've managed to get camera preview with custom filter (grayscale, hue, etc) working. This custom filter is applied with preview callback by manipulating the array of RGB and then drawing it back to a canvas then display it at the surface view.

这是这样做的缺点是我得到一个非常低的FPS。有了这个低FPS,它做太多的工作,在UI线程,如果我不使用的AsyncTask后台线程做到这一点。所以我试图用AsyncTask的相机操作(我的主要目的是让仍在工作,即使完全从相机preVIEW回调繁重的工作UI)。

The drawback from this is I get a very low FPS. With this low FPS, it's doing too much work in the UI thread if I don't do this in the background thread using Asynctask. So I tried to use Asynctask for the camera operation (my main purpose is to get the UI still working perfectly even with the heavy work from the camera preview callback).

但是,即使我用的AsyncTask,它并没有太大的帮助。所以,我想知道是不是我的实现是错的还是因为即使AsyncTask的UI线程仍然会受到影响?

But even after I used Asynctask, it didn't help much. So I am wondering is it my implementation is wrong or is it because even with asynctask the UI thread will still be affected?

我的code代码片段如下:

Snippet of my code is below:

CameraActivity.java

CameraActivity.java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("ACTIVITY_LIFECYCLE","CameraActivity: onCreate");
    setContentView(R.layout.camera_layout);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
protected void onResume() {
    Log.d("ACTIVITY_LIFECYCLE","CameraActivity: onResume");
    if(preview == null){
        preview = new CameraPreviewAsync(this,camera);
        preview.execute();
    }
    super.onResume();
}

@Override
protected void onPause() {
    Log.d("ACTIVITY_LIFECYCLE","CameraActivity: onPause");
    if(preview!=null){
        preview.cancel(true);
        camera = preview.getCamera();
        if(camera!=null){
            camera.stopPreview();
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
            preview.setCamera(camera);
        }
        preview = null;
    }
    super.onPause();
}

@Override
public void onDestroy(){
    Log.d("ACTIVITY_LIFECYCLE","CameraActivity: onDestroy");
    super.onDestroy();
} 

相机previewAsync.java:

CameraPreviewAsync.java:

private final String TAG = "CameraPreviewAsync";

private CameraActivity camAct;
private Camera mCamera;
private int cameraId;
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;

private boolean isPreviewRunning = false;
private int[] rgbints;
private int width;
private int height;
private Bitmap mBitmap;

public CameraPreviewAsync(CameraActivity act, Camera cam){
    this.camAct = act;
    this.mCamera = cam;
    this.mSurfaceView = (SurfaceView) act.findViewById(R.id.surfaceView);
}

public void resetSurface(){
    if(mCamera!=null){
        mCamera.stopPreview();
        mCamera.setPreviewCallback(null);
        mCamera.release();
        mCamera = null;
    }
    int tempId = R.id.surfaceView;
    RelativeLayout buttonBar = (RelativeLayout) camAct.findViewById(R.id.buttonBar);
    ((RelativeLayout) camAct.findViewById(R.id.preview)).removeAllViews();

    SurfaceView newSurface = new SurfaceView(camAct);
    newSurface.setId(tempId);
    RelativeLayout.LayoutParams layParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    layParams.alignWithParent = true;
    newSurface.setLayoutParams(layParams);
    ((RelativeLayout) camAct.findViewById(R.id.preview)).addView(newSurface);
    ((RelativeLayout) camAct.findViewById(R.id.preview)).addView(buttonBar);
}

@Override
protected void onPreExecute() {
    //Things to do before doInBackground executed
    Log.d(TAG,"onPreExecute");

    RelativeLayout.LayoutParams layParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    layParams.alignWithParent = true;
    mSurfaceView.setLayoutParams(layParams);

    //Check number of camera in the device, if less than 2 then remove swap button
    if (Camera.getNumberOfCameras() < 2) {
        ((RelativeLayout) camAct.findViewById(R.id.buttonBar)).removeViewAt(R.id.cameraSwap);
    }

    //Opening the camera
    cameraId = findBackFacingCamera();
    if (cameraId < 0) {
        cameraId = findFrontFacingCamera();
        if (cameraId < 0)
            Toast.makeText(camAct, "No camera found.", Toast.LENGTH_LONG).show();
        else
            mCamera = Camera.open(cameraId);
    } else {
        mCamera = Camera.open(cameraId);
    }

    //invalidate the menu bar and show menu appropriately
    camAct.invalidateOptionsMenu();

    // get Camera parameters and set it to Auto Focus
    if(mCamera!=null){
        Camera.Parameters params = mCamera.getParameters();
        List<String> focusModes = params.getSupportedFocusModes();
        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
            // set the focus mode
            params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            // set Camera parameters
            mCamera.setParameters(params);
        }
    }

    super.onPreExecute();
}

@Override
protected Void doInBackground(Void... params) {
    //Things to do in the background thread
    Log.d(TAG,"doInBackground");

    mHolder = mSurfaceView.getHolder();
    mHolder.addCallback(surfaceCallback);

    return null;
}      

@Override
protected void onPostExecute(Void values) {
    //Things to do after doInBackground
    Log.d(TAG,"onPostExecute");

}

@Override
protected void onCancelled(){
    super.onCancelled();
}

/*
 * ************************************************************************************
 * SURFACEHOLDER CALLBACK
 * ************************************************************************************
 */
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG,"surfaceCreated!!");
        if(CameraActivity.filterMode == CameraActivity.NORMAL_FILTER){
            try {
                if (mCamera != null) {
                    mCamera.startPreview();
                    mCamera.setPreviewDisplay(holder);
                }else{
                    Log.d(TAG,"CAMERA IS NULL in surfaceCreated!!");
                }
            } catch (IOException exception) {
                Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
            }   
        }else{
            synchronized(mSurfaceView){
                if(isPreviewRunning){
                    return;
                }else{                      

                    mSurfaceView.setWillNotDraw(false);
                    if(mCamera!=null){
                        isPreviewRunning = true;
                        Camera.Parameters p = mCamera.getParameters();
                        List<Size> sizes = p.getSupportedPreviewSizes();

                        Size size = p.getPreviewSize();
                        width = size.width;
                        height = size.height;

                        p.setPreviewFormat(ImageFormat.NV21);
                        showSupportedCameraFormats(p);
                        mCamera.setParameters(p);

                        rgbints = new int[width * height];

                        mCamera.startPreview();
                        mCamera.setPreviewCallback(previewCallback);
                    }
                }
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.d(TAG,"surfaceDestroyed!");

        if(CameraActivity.filterMode == CameraActivity.NORMAL_FILTER){
            if (mCamera != null) {
                mCamera.stopPreview();
                isPreviewRunning = false;
            }
        }else{
            synchronized(mSurfaceView){
                if(mCamera!=null){
                    mCamera.setPreviewCallback(null);
                    mCamera.stopPreview();
                    isPreviewRunning = false;
                }
            }
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        Log.d(TAG,"surfaceChanged!");
    }
};


/*
 * ************************************************************************************
 * CAMERA PREVIEW CALLBACK
 * ************************************************************************************
 */

Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        if (!isPreviewRunning)
            return;
        Canvas resCanvas = null;

        if (mHolder == null) {
            return;
        }

        try {
            synchronized (mHolder) {
                resCanvas = mHolder.lockCanvas(null);
                int resCanvasW = resCanvas.getWidth();
                int resCanvasH = resCanvas.getHeight();

                if(mBitmap == null){
                    mBitmap =  Bitmap.createBitmap (width, height, Bitmap.Config.ARGB_8888);
                }

                decodeYUV(rgbints, data, width, height);

                Canvas canvas = new Canvas(mBitmap);

                //Setting the filter
                if(camAct.getCustomFilter().equalsIgnoreCase("NORMAL")) ;//don't change the rgb value
                if(camAct.getCustomFilter().equalsIgnoreCase("GRAYSCALE")) rgbints = grayscale(rgbints);
                if(camAct.getCustomFilter().equalsIgnoreCase("INVERT")) rgbints = invert(rgbints);
                if(camAct.getCustomFilter().equalsIgnoreCase("BOOSTRED")) rgbints = boostColor(rgbints,1);
                if(camAct.getCustomFilter().equalsIgnoreCase("BOOSTGREEN")) rgbints = boostColor(rgbints,2);
                if(camAct.getCustomFilter().equalsIgnoreCase("BOOSTBLUE")) rgbints = boostColor(rgbints,3);
                if(camAct.getCustomFilter().equalsIgnoreCase("NOISE")) rgbints = noise(rgbints);
                if(camAct.getCustomFilter().equalsIgnoreCase("HUE")) rgbints = hue(rgbints);
                if(camAct.getCustomFilter().equalsIgnoreCase("SATURATION")) rgbints = saturation(rgbints);
                if(camAct.getCustomFilter().equalsIgnoreCase("ENGRAVE")) rgbints = engrave(rgbints);
                if(camAct.getCustomFilter().equalsIgnoreCase("EMBOSS")) rgbints = emboss(rgbints);

                // draw the decoded image, centered on canvas
                canvas.drawBitmap(rgbints, 0, width, 0,0, width, height, false, null);

                resCanvas.drawBitmap (mBitmap, resCanvasW-((width+resCanvasW)>>1), resCanvasH-((height+resCanvasH)>>1),null);
            }
        }  catch (Exception e){
            e.printStackTrace();
        } finally {
            // do this in a finally so that if an exception is thrown
            // during the above, we don't leave the Surface in an
            // inconsistent state
            if (resCanvas != null) {
                mHolder.unlockCanvasAndPost(resCanvas);
            }
        }
    }
};

任何帮助是非常AP preciated! :)在此先感谢你们!

Any help is much appreciated! :) Thanks in advance guys!

推荐答案

回调从其它方法被递送到线程的事件循环,要求打开()。如果该线程没有事件循环,然后回调被传递到主应用程序事件循环。如果没有主应用程序的事件循环,回调不传递。 <一href="https://developer.android.com/reference/android/hardware/Camera.$p$pviewCallback%E2%80%8C%E2%80%8B.html#on$p$pviewFrame(byte[],%20android.hardware.Camera)"相对=nofollow>来源

Callbacks from other methods are delivered to the event loop of the thread which called open(). If this thread has no event loop, then callbacks are delivered to the main application event loop. If there is no main application event loop, callbacks are not delivered. Source

这篇关于安卓相机的AsyncTask用preVIEW回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆