2017-06-19 80 views
0

我在OnPreviewFrame()中捕获帧,然后在线程中处理它们以检查它们是否有效。OutOfMemory从onPreviewFrame处理帧时出错

public void onPreviewFrame(byte[] data, Camera camera) { 
    if (imageFormat == ImageFormat.NV21) { 
     //We only accept the NV21(YUV420) format. 
     frameCount++; 
     if (frameCount > 19 && frameCount % 2 == 0) { 
      Camera.Parameters parameters = camera.getParameters(); 
      FrameModel fModel = new FrameModel(data); 
      fModel.setPreviewWidth(parameters.getPreviewSize().width); 
      fModel.setPreviewHeight(parameters.getPreviewSize().height); 
      fModel.setPicFormat(parameters.getPreviewFormat()); 
      fModel.setFrameCount(frameCount); 
      validateFrame(fModel); 
      } 
     }  
    } 

在validateFrame()中,i提交ValidatorThread可运行实例一的ThreadPoolExecutor与4个芯和最大线程数,以并行处理所述帧。

public class ValidatorThread implements Runnable { 

private FrameModel frame; 

public ValidatorThread(FrameModel fModel) { 
    frame = fModel; 
} 

@Override 
public void run() { 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    processNV21Data(); 
} 

private void processNV21Data() { 

    YuvImage yuv = new YuvImage(frame.getData(), frame.getPicFormat(), 
      frame.getPreviewWidth(), frame.getPreviewHeight(), null); 
    frame.releaseData(); 

    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    yuv.compressToJpeg(new Rect(0, 0, frame.getPreviewWidth(), frame.getPreviewHeight()), 100, out); 

    byte[] bytes = out.toByteArray(); 
    yuv = null; 

    try { 
     if (out != null) 
      out.close(); 
     out = null; 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    Bitmap baseBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 
    bytes = null; 

    // rotate bitmap 
    baseBitmap = rotateImage(baseBitmap, frame.getRotation()); 

    //create copy of original bitmap to use later 
    Bitmap mCheckedBitmap = baseBitmap.copy(Bitmap.Config.ARGB_8888, true); 

    // convert base bitmap to greyscale for validation 
    baseBitmap = toGrayscale(baseBitmap); 

    boolean isBitmapValid = Util.isBitmapValid(baseBitmap); 

    if (isBitmapValid) { 
     baseBitmap.recycle(); 
     mCheckedBitmap.recycle(); 
     frame = null; 
    } else { 
     baseBitmap.recycle(); 
     mCheckedBitmap.recycle(); 
     frame = null; 
    } 
} 

public Bitmap toGrayscale(Bitmap bmpOriginal) { 
    int width, height; 
    height = bmpOriginal.getHeight(); 
    width = bmpOriginal.getWidth(); 
    Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 
    Canvas c = new Canvas(bmpGrayscale); 
    Paint paint = new Paint(); 
    bmpOriginal.recycle(); 
    return bmpGrayscale; 
} 
private Bitmap rotateImage(final Bitmap source, float angle) { 
    Matrix matrix = new Matrix(); 
    matrix.postRotate(angle); 
    Bitmap rotatedBitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); 
    source.recycle(); 
    return rotatedBitmap; 
} 

}

的FrameModel类有这样的声明:

public class FrameModel { 

private byte[] data; 
private int previewWidth; 
private int previewHeight; 
private int picFormat; 
private int frameCount; 

public void releaseData() { 
    data = null; 
} 

// getters and setters 
} 

我得到OutOf内存错误,同时处理多个帧。

任何人都可以帮助代码需要什么内存优化吗?

+0

可能拍摄的帧有很大的分辨率。尝试在处理它之前调整YuvImage和位图的大小 – MatPag

+0

堆没有被取消分配..代码中是否有任何内存泄漏? –

+0

您是否尝试将方法末尾的位图设置为空? – MatPag

回答

0

如果您在不通过Jpeg的情况下从YUV数据生成灰度位图,则可以减少内存使用量。这也将显着加快。

public Bitmap yuv2grayscale(byte[] yuv, int width, int height) { 
    int[] pixels = new int[width * height]; 

    for (int i = 0; i < height*width; i++) { 
     int y = yuv[i] & 0xff; 
     pixels[i] = 0xFF000000 | y << 16 | y << 16 | y; 
    } 
    return Bitmap.createBitmap(pixels, width, height, Bitmap.Config.RGB_565); 
} 

或者,也可以不通过int[width*height]像素阵列会创建一个RGB_565位图,并使用NDK操纵位图像素到位。

+0

这是返回int [] ..我可以得到greyscaled数据在字节[] ..因为我想使用Bitmap.decodeByteArray()而不是createbitmap().. –

+0

decodeByteArray()工作在压缩流(请参阅* [格式支持BitmapFactory.decodeByteArray(...)](https://stackoverflow.com/questions/24333450/formats-supported-by-bitmapfactory-decodebytearray)*),但相机产生YUV。要将其压缩为JPEG并解压缩回位图,您既浪费时间又浪费内存。 –