camera1 实时预览取帧

来源:互联网 发布:javascript reduce 编辑:程序博客网 时间:2024/06/06 09:28

安卓相机5.0以后加入了camera2类,但低版本还是用之前的camera1,所以直接选择camera1来开发!
直奔主题,在开发中遇到的坑!
1,安卓提供了camera.setPreviewCallbac这个回调写出这个回调后,在onPreviewFrame这里拿到摄像头获取的视频帧!
//cameraInst 相机对象

cameraInst.setPreviewCallback(new Camera.PreviewCallback() {        @Override        public void onPreviewFrame(byte[] bytes, Camera camera) { //这里的bytes即摄像头获取的视频帧        }    });

这里有个坑,在此获取的数据格式是有问题的,如果直接转bitmap是转不了的!这里找到一个方法转成bitmap,但是这里直接转的话拿到的图片角度是不正确的,具体还要看预览时官方的一个方法中获取的角度,
https://developer.android.com/reference/android/hardware/Camera.html

//这个方法就是官方给的解决办法拿到这里的角度,在转换时,旋转即可获取正确的位图!
//此方法为camera1设置正确预览使用

public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}

 int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {     result = (info.orientation + degrees) % 360;     result = (360 - result) % 360;  // compensate the mirror } else {  // back-facing     result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result);

}

//视频帧转位图     YuvImage也可用于转换,但此类并不兼容低版本设备!public Bitmap cameraByte2Bitmap(byte[] data, int width, int height) {    int frameSize = width * height;    int[] rgba = new int[frameSize];    for (int i = 0; i < height; i++)        for (int j = 0; j < width; j++) {            int y = (0xff & ((int) data[i * width + j]));            int u = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 0]));            int v = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 1]));            y = y < 16 ? 16 : y;            int r = Math.round(1.164f * (y - 16) + 1.596f * (v - 128));            int g = Math.round(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));            int b = Math.round(1.164f * (y - 16) + 2.018f * (u - 128));            r = r < 0 ? 0 : (r > 255 ? 255 : r);            g = g < 0 ? 0 : (g > 255 ? 255 : g);            b = b < 0 ? 0 : (b > 255 ? 255 : b);            rgba[i * width + j] = 0xff000000 + (b << 16) + (g << 8) + r;        }    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);    bmp.setPixels(rgba, 0, width, 0, 0, width, height);    return bmp;}

2,这里说第二个坑,写完以上以为已经解决了,运行,发现内存一直飙升直至内存溢出!查资料发现问题出现在setPreviewCallback 这个回调上,官方的api还给出一个setPreviewCallbackWithBuffer 这个回调,英文意思大体是说设置一个缓冲区!看文档,测试,以下这样解决!、

cameraInst.addCallbackBuffer(new byte[((cameraInst.getParameters().getPreviewSize().width * cameraInst.getParameters().getPreviewSize().height) * ImageFormat.getBitsPerPixel(ImageFormat.NV21)) / 8]);

   cameraInst.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {        @Override        public void onPreviewFrame(byte[] bytes, Camera camera) {            camera.addCallbackBuffer(bytes);  //这里加这一句        }    });}

程序运行,正常!

原创粉丝点击