package com.basic.security.widget; import android.content.Context; import android.content.ContextWrapper; import android.content.res.Configuration; import android.graphics.Bitmap; import android.hardware.Camera; import android.hardware.SensorManager; import android.util.AttributeSet; import android.view.OrientationEventListener; import android.view.SurfaceHolder; import android.view.ViewGroup; import com.basic.security.base.BaseApplication; import com.basic.security.utils.BgrUtils; import com.basic.security.utils.Constants; import com.basic.security.utils.DetectListener; import com.basic.security.utils.FaceId; import com.basic.security.utils.ProcessImageAndDrawResults; import com.basic.security.utils.RenderScriptHelper; import com.basic.security.utils.RotateUtil; import com.basic.security.utils.socket.RelaySocketServer; import com.basic.security.utils.socket.outdoor.OutdoorGuestSocketServer; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.util.List; public class Preview extends PreviewBase { Preview.MyThread rgbThread = new Preview.MyThread(); Preview.MyThread grayThread = new Preview.MyThread(); public Preview(Context context, AttributeSet attrs) { super(context, attrs); } public void setMeasuredDimension1(int measuredWidth, int measuredHeight) { setMeasuredDimension(measuredWidth, measuredHeight); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // ViewAttributeManager.onMeasure(this, widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } public void reset() { if (mCamera != null) { try { mCamera.release(); } catch (Exception e) { e.printStackTrace(); } } surfaceCreated(mHolder); surfaceChanged(mHolder, 0, 0, 0); } public void surfaceCreated(final SurfaceHolder holder) { // System1.out.println("Preview.surfaceCreated rgb_gray_camera="+rgb_gray_camera); // if (1 == 1) { // return; // } mFinished = false; try { mCamera = Camera.open(rgb_gray_camera); Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(640, 480); mCamera.setParameters(parameters); mCamera.setPreviewDisplay(holder); resetCamera = true; mCamera.setPreviewCallback((data, camera) -> { lastTimeOnPreviewFrame = System.currentTimeMillis(); if (Constants.indoorOutdoorInOne) { if (rgb_gray_camera == Constants.RGB_CAMERA) { if (secondDisplayRunnable.isNotRunning()) { if (data == null) { return; } secondDisplayRunnable.isRunning = true; secondDisplayRunnable.setFrame(data, mDraw); BaseApplication.getApplication().executorService.execute(secondDisplayRunnable); } } } try { if (rgb_gray_camera == Constants.RGB_CAMERA) { OutdoorGuestSocketServer.setCameraData(data); if (BaseApplication.getApplication().activity != null && BaseApplication.getApplication().activity.shouldDetectFace()) { if (!rgbThread.isRunning) { if (Constants.USE_GRAY_CAMERA) { byte[] grayBgrData = getMostMatchGrayBgrData(); if (grayBgrData != null) { try { System1.out.println("Preview.surfaceCreated grayThread"); grayThread.onPreviewFrame(grayBgrData, camera, Constants.GRAY_CAMERA); grayExecutorService.execute(grayThread); } catch (Exception e) { grayThread.isRunning = false; e.printStackTrace(); } } } rgbThread.isRunning = true; rgbThread.onPreviewFrame(data, camera, Constants.RGB_CAMERA); rgbExecutorService.execute(rgbThread); } } } else { updateGrayBgrData(data); } } catch (Exception e) { rgbThread.isRunning = false; e.printStackTrace(); } }); mCamera.startPreview(); OrientationEventListener mOrientationListener = new OrientationEventListener(FaceId.activity, SensorManager.SENSOR_DELAY_NORMAL) { public void onOrientationChanged(int orientation) { if (orientation == ORIENTATION_UNKNOWN) return; Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(0, info); orientation = (orientation + 45) / 90 * 90; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { Preview.rotation = (info.orientation - orientation + 360) % 360; } else { Preview.rotation = (info.orientation + orientation) % 360; } orientation1 = orientation; } }; if (mOrientationListener.canDetectOrientation()) { mOrientationListener.enable(); } else { mOrientationListener.disable(); } } catch (Exception exception) { System1.out.println("Preview.surfaceCreated " + exception.getMessage()); if (mCamera != null) { mCamera.release(); mCamera = null; } mFinished = true; } } public void updateGrayBgrData(byte[] data) { // System1.out.println("Preview.updateGrayBgrData " + data); grayCameraData = data; grayCameraDataLastTimeUpdate = System.currentTimeMillis(); } public byte[] getMostMatchGrayBgrData() { long internal = (System.currentTimeMillis() - grayCameraDataLastTimeUpdate); if (internal < 1000 && grayCameraData != null) { return grayCameraData; } return null; } public void surfaceDestroyed(SurfaceHolder holder) { // if (1 == 1) { // return; // } mFinished = true; if (mCamera != null) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (mFinished) { return; } // if (1 == 1) { // return; // } if (mCamera == null) return; Camera.Parameters parameters = mCamera.getParameters(); if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) { parameters.set("orientation", "portrait"); mCamera.setDisplayOrientation(90); mDraw.rotated = true; } else { parameters.set("orientation", "landscape"); mCamera.setDisplayOrientation(0); } List supportedSizes = parameters.getSupportedPreviewSizes(); int width = 0; int height = 0; for (Camera.Size s : supportedSizes) { if ((width - 640) * (width - 640) + (height - 480) * (height - 480) > (s.width - 640) * (s.width - 640) + (s.height - 480) * (s.height - 480)) { width = s.width; height = s.height; } } try { if (width * height > 0) { parameters.setPreviewSize(width, height); } parameters.setSceneMode(Camera.Parameters.SCENE_MODE_LANDSCAPE); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); mCamera.setParameters(parameters); } catch (Exception ex) { // System1.out.println("Preview.surfaceChanged " + ex.getMessage()); } parameters = mCamera.getParameters(); Camera.Size previewSize = parameters.getPreviewSize(); makeResizeForCameraAspect(1.0f / ((1.0f * previewSize.width) / previewSize.height)); } private void makeResizeForCameraAspect(float cameraAspectRatio) { ViewGroup.LayoutParams layoutParams = this.getLayoutParams(); int matchParentWidth = this.getWidth(); int newHeight = (int) (matchParentWidth / cameraAspectRatio); if (newHeight != layoutParams.height) { layoutParams.height = newHeight; layoutParams.width = matchParentWidth; this.setLayoutParams(layoutParams); this.invalidate(); } } public void init(Context context, int rgb_gray_camera, DetectListener detectListener) { if (rgb_gray_camera == Constants.RGB_CAMERA && Constants.indoorOutdoorInOne) { init1(context, rgb_gray_camera, detectListener); return; } // System1.out.println("Preview.init " + rgb_gray_camera); if (rgb_gray_camera == Constants.RGB_CAMERA) { Preview.rgbPreview = this; RelaySocketServer.startSocketServer(); } if (rgb_gray_camera == Constants.GRAY_CAMERA) { Preview.grayPreview = this; } this.detectListener = detectListener; mContext = context; mDraw = new ProcessImageAndDrawResults(rgb_gray_camera); this.rgb_gray_camera = rgb_gray_camera; mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void init1(Context context, int rgb_gray_camera, DetectListener detectListener) { if (rgb_gray_camera == Constants.RGB_CAMERA) { Preview.rgbPreview = this; RelaySocketServer.startSocketServer(); } if (rgb_gray_camera == Constants.GRAY_CAMERA) { Preview.grayPreview = this; } this.detectListener = detectListener; mContext = context; mDraw = new ProcessImageAndDrawResults(rgb_gray_camera); this.rgb_gray_camera = rgb_gray_camera; mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public static class SecondDisplayRunnable implements Runnable { public boolean isRunning = false; public long lastRunningTime = System.currentTimeMillis(); public byte[] data; public ProcessImageAndDrawResults mDraw; RenderScriptHelper renderScriptHelper = new RenderScriptHelper(); public void setFrame(byte[] data, ProcessImageAndDrawResults mDraw) { if (this.data == null || this.data.length != data.length) { this.data = new byte[data.length]; } System.arraycopy(data, 0, this.data, 0, data.length); this.mDraw = mDraw; } ///** Convert I420 (YYYYYYYY:UU:VV) to NV21 (YYYYYYYYY:VUVU) */ @Override public void run() { secondDisplayRunnable.lastRunningTime = System.currentTimeMillis(); if (data != null && mDraw != null) { try { if (Constants.indoorOutdoorInOne) { // RotateUtil.mirror(data, mDraw.mImageWidth, mDraw.mImageHeight); } // System1.out.println("SecondDisplayRunnable.run 0 "); // int yuvStrides[] = {mDraw.mImageWidth, mDraw.mImageWidth/2, mDraw.mImageWidth/2}; // VideoRenderer.I420Frame i420Frame = new VideoRenderer.I420Frame(mDraw.mImageWidth, mDraw.mImageHeight, yuvStrides, // RotateUtil.nv21ToI420(data, mDraw.mImageWidth, mDraw.mImageHeight)); // if ( BaseApplication.getApplication().activity.secondaryDisplay != null) { //// System1.out.println("SecondDisplayRunnable.run 1 " + BaseApplication.getApplication().activity.secondaryDisplay); // if(BaseApplication.getApplication().activity.secondaryDisplay.yuvImageRenderer != null) { //// System1.out.println("SecondDisplayRunnable.run 2 " + BaseApplication.getApplication().activity.secondaryDisplay.yuvImageRenderer); // BaseApplication.getApplication().activity.secondaryDisplay.yuvImageRenderer.setSize(mDraw.mImageWidth, mDraw.mImageHeight); // BaseApplication.getApplication().activity.secondaryDisplay.yuvImageRenderer.renderFrame(i420Frame); // } // } Bitmap frameBitmap = null; frameBitmap = renderScriptHelper.getBitmapFromFrameData(data, mDraw.mImageWidth, mDraw.mImageHeight); //// Matrix mtx = new Matrix(); //// mtx.preScale(-1.0f, 1.0f); //// Bitmap newImage = Bitmap.createBitmap(frameBitmap, 0, 0, frameBitmap.getWidth(), frameBitmap.getHeight(), mtx, true); BaseApplication.getApplication().activity.updateCameraImagesInSecondDisplay(frameBitmap); } catch (Exception e) { e.printStackTrace(); } } } public boolean isNotRunning() { if (System.currentTimeMillis() - lastRunningTime < 1000.0 / 18) { return false; } return System.currentTimeMillis() - lastRunningTime > 1 * 1000 || !isRunning; } } class MyThread implements Runnable { public boolean isRunning = false; RotateUtil rotateUtil = new RotateUtil(); BgrUtils bgrUtils = new BgrUtils(); ByteArrayOutputStream jpgBaos = new ByteArrayOutputStream(); byte[] data; Camera camera; int rgb_gray_camera; RenderScriptHelper renderScriptHelper = new RenderScriptHelper(); Camera.Parameters params; public void onPreviewFrame(byte[] data, Camera camera, int rgb_gray_camera) { this.rgb_gray_camera = rgb_gray_camera; if (this.data == null) { this.data = new byte[data.length]; } if (BaseApplication.getApplication().activity.needCopyCameraData()) { System.arraycopy(data, 0, this.data, 0, data.length); } else { this.data = data; } this.data = data; this.camera = camera; } public void run() { ProcessImageAndDrawResults mDraw; if (rgb_gray_camera == Constants.GRAY_CAMERA) { mDraw = grayPreview.mDraw; } else { mDraw = rgbPreview.mDraw; } mDraw.originalCameraData = this.data; isRunning = true; mDraw.setRgb_gray_camera(rgb_gray_camera); if (params == null) { params = camera.getParameters(); } int rotation = Constants.rotation; if (rotation == 360 || rotation == 0) { mDraw.mImageWidth = params.getPreviewSize().width; mDraw.mImageHeight = params.getPreviewSize().height; } if (rotation == 270) { data = rotateUtil.rotateYUV420Degree270(data, params.getPreviewSize().width, params.getPreviewSize().height); mDraw.mImageWidth = params.getPreviewSize().height; mDraw.mImageHeight = params.getPreviewSize().width; } if (rotation == 180) { data = rotateUtil.rotateYUV420Degree180(data, params.getPreviewSize().width, params.getPreviewSize().height); mDraw.mImageWidth = params.getPreviewSize().width; mDraw.mImageHeight = params.getPreviewSize().height; } if (rotation == 90) { data = rotateUtil.rotateYUV420Degree90(data, params.getPreviewSize().width, params.getPreviewSize().height); mDraw.mImageWidth = params.getPreviewSize().height; mDraw.mImageHeight = params.getPreviewSize().width; } Preview.this.rotationToSend = rotation; if (!Constants.useNv21ToBgr) { long begin = System.currentTimeMillis(); // byte[] dataBGR = new byte[640*480*3]; // dataBGR = FaceId.instance.yuv420p2rgb24(data, dataBGR,480, 640); // System1.out.println("MyThread.run " + (System.currentTimeMillis() - begin)); // YuvImage im = new YuvImage(data, ImageFormat.NV21, mDraw.mImageWidth, // mDraw.mImageHeight, null); // Rect r = new Rect(0, 0, mDraw.mImageWidth, mDraw.mImageHeight); // jpgBaos.reset(); // im.compressToJpeg(r, params.getJpegQuality(), jpgBaos); String outputFileName = ""; Bitmap frameBitmap = renderScriptHelper.getBitmapFromFrameData(data, mDraw.mImageWidth, mDraw.mImageHeight);// Bitmap.createBitmap(640, 480, Bitmap.Config.RGB_565); byte[] bgrArray = null; try { String name = ""; String filesPath = new ContextWrapper(FaceId.activity).getFilesDir().getAbsolutePath(); byte[] jpgByteArray = null; if (rgb_gray_camera == Constants.RGB_CAMERA) { name = "image_rgb.jpg"; outputFileName = "rgb.jpg"; File targetFile = new File(filesPath, outputFileName); // jpgByteArray = jpgBaos.toByteArray(); // frameBitmap = BitmapFactory.decodeByteArray(jpgByteArray, 0, jpgBaos.size()); jpgBaos.reset(); frameBitmap.compress(Bitmap.CompressFormat.JPEG, 100, jpgBaos); mDraw.frameJpgByteArray = jpgBaos.toByteArray(); jpgByteArray = mDraw.frameJpgByteArray; mDraw.frameBitmap = frameBitmap; bgrArray = bgrUtils.getPixelsBGR(frameBitmap); if (!Constants.useBgrArray) { FileOutputStream outputStream = new FileOutputStream(targetFile); outputStream.write(bgrArray); outputStream.close(); } } else { outputFileName = "gray.jpg"; name = "image_gray.jpg"; jpgBaos.reset(); frameBitmap.compress(Bitmap.CompressFormat.JPEG, 100, jpgBaos); mDraw.frameJpgByteArray = jpgBaos.toByteArray(); jpgByteArray = mDraw.frameJpgByteArray; mDraw.frameBitmap = frameBitmap; bgrArray = bgrUtils.getPixelsBGR(frameBitmap); // Bitmap bitmap = BitmapFactory.decodeByteArray(jpgBaos.toByteArray(), 0, jpgBaos.size()); // bitmapHolder.storeBitmap(bitmap); // bitmapHolder.flipBitmapHorizontal(); // bitmap = bitmapHolder.getBitmapAndFree(); // jpgBaos.reset(); // if (bitmap == null) { // System1.out.println("MyThread.run bitmap=" + bitmap); // isRunning = false; // return; // } // bitmap.compress(Bitmap.CompressFormat.JPEG, 100, jpgBaos); // jpgByteArray = jpgBaos.toByteArray(); File targetFile = new File(filesPath, outputFileName); FileOutputStream outputStream = new FileOutputStream(targetFile); // bgrArray = bgrUtils.getPixelsBGR(BitmapFactory.decodeByteArray(jpgByteArray, 0, jpgBaos.size())); outputStream.write(bgrArray); outputStream.close(); } FileOutputStream output = new FileOutputStream(new File(new ContextWrapper(getContext()).getFilesDir().getAbsolutePath(), name)); output.write(jpgByteArray); output.flush(); output.close(); } catch (Exception e) { e.printStackTrace(); } if (mFinished) return; if (mDraw.mYUVData == null) { mDraw.mRGBData = new byte[3 * mDraw.mImageWidth * mDraw.mImageHeight]; mDraw.mYUVData = new byte[data.length]; } mDraw.start(frameBitmap, bgrArray, data); } else { mDraw.start1(data); } isRunning = false; } } }