TextureView.getBitmap () que muestra un rendimiento inconsistente

Estoy haciendo algunas pruebas de procesamiento de imágenes con imágenes de mapa de bits obtenidas de un TextureView, que está manejando mi entrada de video. En mi prueba he notado que el tiempo que TextureView.getBitmap (Bitmap) tarda en ejecutarse, a veces varía entre las ejecuciones.

Para demostrar el problema, modifiqué un ejemplo de la referencia de la API de TextureView. En el siguiente código, utilizo la cámara como entrada en el TextureView, tomo el mapa de bits y lo presento a un SurfaceView, midiendo cuánto tiempo toma. Lo he probado en un par de dispositivos Nexus 7 que ejecutan Android 4.2.2. Realmente he notado dos patrones, uno lento y uno rápido.

Cuando la ejecución es "lenta", getBitmap (Bitmap) tarda unos 20ms. Cuando la ejecución es "rápida", getBitmap (Bitmap) tarda unos 15ms.

La mayoría de las veces esta aplicación se ejecuta en modo "lento". Si rastreo el dispositivo o vuelvo a compilar / reinstalar la aplicación, a veces lo hago funcionar en modo "rápido". Pero después de eso volverá a funcionar lentamente. La velocidad sólo cambia después de reiniciar el programa, nunca durante la ejecución.

Por cierto, el dumping del mapa de bits para el SurfaceView sólo toma alrededor de 8ms: Me pregunto por qué obtener el mapa de bits de la TextureView toma más del doble de ese tiempo.

Las preguntas:

  1. ¿Por qué ocurre esta disparidad en el tiempo de ejecución?
  2. ¿Hay alguna manera de asegurar que getBitmap (Bitmap) se ejecute siempre lo más rápido posible?
  3. ¿Es razonable que escribir a SurfaceView sea dos veces más rápido que leer desde TextureView?

Gracias.

–Rafael

PS: Ya he publicado esto en Android Developers Grupo de Google, pero parece que está atascado en la moderación desde la semana pasada. Perdón por la publicación cruzada.

Editar:

He añadido un proyecto de ejemplo a GitHub para aquellos que deseen probarlo más fácilmente:

La actividad:

import java.io.IOException; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; public class LiveCameraActivity extends Activity implements TextureView.SurfaceTextureListener { private Camera mCamera; private TextureView mTextureView; private SurfaceView mSurfaceView; private final int imgW = 640; private final int imgH = 480; private Bitmap bmp = Bitmap.createBitmap(imgW, imgH, Bitmap.Config.ARGB_8888); private Canvas canvas = new Canvas(bmp); private Paint paint1 = new Paint(); private SurfaceHolder mSurfaceHolder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main2); mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview); mSurfaceHolder = mSurfaceView.getHolder(); mTextureView = (TextureView) findViewById(R.id.textureview); mTextureView.setSurfaceTextureListener(this); final int textSize = 24; paint1.setColor(0xff00ffff); paint1.setTextSize(textSize); } public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mCamera = Camera.open(Camera.getNumberOfCameras()-1); Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(imgW, imgH); mCamera.setParameters(parameters); try { mCamera.setPreviewTexture(surface); mCamera.startPreview(); } catch (IOException ioe) { // Something bad happened } } public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { // Ignored, Camera does all the work for us } public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { mCamera.stopPreview(); mCamera.release(); return true; } public void onSurfaceTextureUpdated(SurfaceTexture surface) { // Invoked every time there's a new Camera preview frame long time0 = System.currentTimeMillis(); mTextureView.getBitmap(bmp); long time1 = System.currentTimeMillis() - time0; final Canvas c = mSurfaceHolder.lockCanvas(); if ( c != null) { canvas.drawText("getBmp= " + time1, 10, 40, paint1); c.drawBitmap(bmp, 0, 0, null); mSurfaceHolder.unlockCanvasAndPost(c); } long total = System.currentTimeMillis() - time0; long time2 = total -time1; Log.i("onFrame", "timing: getBmp= " + time1 + " blit= " + time2 + " total= " + total); } } 

El diseño:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" > <SurfaceView android:id="@+id/surfaceview" android:layout_width="640px" android:layout_height="480px" /> <TextureView android:id="@+id/textureview" android:layout_width="640px" android:layout_height="480px" /> </LinearLayout> 

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.