Android: Caméra Asynctask avec Aperçu de Rappel

J'ai réussi à obtenir l'aperçu de l'appareil photo avec filtre personnalisé (niveaux de gris, teinte, etc) de travail. Ce filtre personnalisé est appliqué avec de l'extrait de rappel par la manipulation de la matrice de RVB et puis de nouveau à une toile, puis de les afficher à la surface d'affichage.

L'inconvénient de cette est que je obtenir un très faible FPS. Avec ce FPS bas, c'est de faire trop de travail dans le thread de l'INTERFACE utilisateur, si je ne fais pas ça dans le thread d'arrière-plan à l'aide de Asynctask. J'ai donc essayé d'utiliser Asynctask pour le fonctionnement de la caméra (mon principal objectif est d'obtenir de l'INTERFACE utilisateur fonctionne toujours parfaitement, même avec les travaux lourds à partir de l'aperçu de la caméra de rappel).

Mais, même après que j'ai utilisé Asynctask, il n'a pas beaucoup d'aide. Alors je me demande est-ce que mon application est mal ou est-ce parce que même avec asynctask le thread d'INTERFACE utilisateur seront touchés?

Extrait de mon code est ci-dessous:

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();
} 

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);
}
}
}
};

Toute aide est très appréciée! 🙂 Merci d'avance les gars!

Avez-vous d'exécuter un test pour mesurer le temps passé dans l'aperçu de rappel? Je ne suis pas sûr que le problème est la charge de travail dans onPreviewFrame
nope, je n'ai pas. Je ne suis pas sûr de savoir comment faire, pouvez-vous me recommander un moyen de le tester? merci!

OriginalL'auteur CodingBird | 2013-10-07