From 06327334203607e2e77d43407fbbdbcfd5a700a3 Mon Sep 17 00:00:00 2001
From: whycxzp <glperry@163.com>
Date: 星期三, 24 七月 2024 15:23:38 +0800
Subject: [PATCH] 双摄-主摄预览拍照,副摄录像

---
 app/src/main/java/com/whyc/widget/Camera2TextureView2.java |  296 +++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 165 insertions(+), 131 deletions(-)

diff --git a/app/src/main/java/com/whyc/widget/Camera2TextureView2.java b/app/src/main/java/com/whyc/widget/Camera2TextureView2.java
index e7baeb8..d3b405c 100644
--- a/app/src/main/java/com/whyc/widget/Camera2TextureView2.java
+++ b/app/src/main/java/com/whyc/widget/Camera2TextureView2.java
@@ -4,14 +4,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.ImageFormat;
-import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.media.Image;
@@ -26,7 +24,7 @@
 import android.support.annotation.NonNull;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Range;
+import android.util.Size;
 import android.view.Surface;
 import android.view.TextureView;
 import android.view.View;
@@ -46,19 +44,29 @@
 import static android.content.ContentValues.TAG;
 import static android.os.Environment.DIRECTORY_DOCUMENTS;
 
-/**杩欎釜閲囩敤TEMPLATE_RECORD鍜孴EMPLATE_VIDEO_SNAPSHOT妯℃澘锛孴EMPLATE_RECORD妯℃澘鏄綍鍒惰棰�*/
+/**
+ * 杩欎釜閲囩敤TEMPLATE_RECORD鍜孴EMPLATE_VIDEO_SNAPSHOT妯℃澘锛孴EMPLATE_RECORD妯℃澘鏄綍鍒惰棰�
+ * 鏀逛负:
+ * 鍓憚 ->褰曞儚
+ * 涓绘憚-> 鎷嶇収
+ * */
 public class Camera2TextureView2 extends TextureView {
 
     private Context mContext;
-    private CameraDevice mCameraDevice;
-    private CaptureRequest.Builder captureBuilder = null;
-    private CameraCaptureSession mCaptureSession;
+    //涓绘憚,鍚庢憚
+    private CameraDevice mainCameraDevice;
+    //鍓憚,鍓嶆憚
+    private CameraDevice subCameraDevice;
+
+    private CaptureRequest.Builder captureCaptureBuilder = null;
+    private CaptureRequest.Builder videoCaptureBuilder = null;
+    private CaptureRequest.Builder previewCaptureBuilder = null;
+    private CameraCaptureSession mainCaptureSession;
+    private CameraCaptureSession subCaptureSession;
     private MediaRecorder mMediaRecorder;
     private Surface previewSurface;
     private ImageReader mImageReader;
     private Surface surfaceForStream;
-
-    CaptureRequest.Builder recordRequest;
 
     private Handler mHandler;
     private Handler mainHandler = new Handler(Looper.getMainLooper());
@@ -70,12 +78,12 @@
     private LinearLayout llUpText;
     private TextView tvDevice;
 
-    private int weight = 128;
-    private int height = 72;
+    private int weight = 3840;
+    private int height = 2160;
 
-    private int imageWeight = 1920;
-    private int imageHeight = 1080;
-    Range<Integer> rangeMin;
+    private int videoWidth = 1920;
+    private int videoHeight = 1080;
+    Size outputSizes;
 
     public Camera2TextureView2(Context context) {
         super(context,null);
@@ -83,7 +91,7 @@
 
     public Camera2TextureView2(Context context, AttributeSet attrs) {
         super(context, attrs);
-        executorService = Executors.newScheduledThreadPool(4);
+//        executorService = Executors.newScheduledThreadPool(4);
         /*String url = "http://192.168.10.79:8919/fg/server/timestamp";
         executorService.execute(()-> {
                 HttpReqData httpReqData = new HttpReqData(url);
@@ -95,6 +103,11 @@
         mThreadHandler = new HandlerThread("camera2");
         mThreadHandler.start();
         mHandler = new Handler(mThreadHandler.getLooper());
+
+        startBackgroundThread();
+
+
+
     }
 
     public void init(LinearLayout llUpText, TextView tvDevice) {
@@ -106,6 +119,10 @@
     private SurfaceTextureListener mSurfaceTextureListener = new SurfaceTextureListener() {
         @Override
         public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+            //棰勮surface
+            SurfaceTexture surfaceTexture = getSurfaceTexture();
+            surfaceTexture.setDefaultBufferSize(videoWidth, videoHeight);
+            previewSurface = new Surface(surfaceTexture);
             initCamera2();
         }
         @Override
@@ -128,30 +145,32 @@
 //        ActivityCompat.requestPermissions(Camera2TextureViewActivity.this, permissionArray, 1);
         CameraManager cm = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
         try {
-            String cameraId = cm.getCameraIdList()[0];
-            CameraCharacteristics cameraCharacteristics = cm.getCameraCharacteristics(cameraId);
-            StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
-            Range<Integer>[] availableFpsRanges = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
-            rangeMin = availableFpsRanges[0];
-            cm.openCamera(cameraId,mDeviceStateCallback,null);
+            //鑾峰彇鍓嶆憚鍍忓ご
+            String[] cameraIds = cm.getCameraIdList();
+            for (int i = 0; i < cameraIds.length; i++) {
+                String cameraId = cameraIds[i];
+                CameraCharacteristics cameraCharacteristics = cm.getCameraCharacteristics(cameraId);
+                if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT){
+                    cm.openCamera(cameraId,subDeviceStateCallback,null);
+                }else if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK){
+                    StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+                    outputSizes = new Size(weight,height);
+                    cm.openCamera(cameraId,mainDeviceStateCallback,null);
+                }
+            }
+            //鎷嶇収鐨勬帴鏀跺櫒
+            mImageReader = ImageReader.newInstance(outputSizes.getWidth(), outputSizes.getHeight(), ImageFormat.JPEG, 1);
+            mImageReader.setOnImageAvailableListener(mImageReaderListener, null);
+            surfaceForStream = mImageReader.getSurface();
         }catch (Exception e){
             e.printStackTrace();
         }
     }
 
-    private CameraDevice.StateCallback mDeviceStateCallback = new CameraDevice.StateCallback() {
+    private CameraDevice.StateCallback subDeviceStateCallback = new CameraDevice.StateCallback() {
             @Override
             public void onOpened(CameraDevice cameraDevice) {
-                mCameraDevice = cameraDevice;
-                SurfaceTexture surfaceTexture = getSurfaceTexture();
-                surfaceTexture.setDefaultBufferSize(weight, height);
-                previewSurface = new Surface(surfaceTexture);
-
-                try {
-                    createPreviewSession();
-                }catch (Exception e){
-                    e.printStackTrace();
-                }
+                subCameraDevice = cameraDevice;
             }
 
             @Override
@@ -165,13 +184,54 @@
             }
     };
 
+    private CameraDevice.StateCallback mainDeviceStateCallback = new CameraDevice.StateCallback() {
+        @Override
+        public void onOpened(CameraDevice cameraDevice) {
+            mainCameraDevice = cameraDevice;
+            //鍒濆鍖栦富鎽勫儚澶寸殑浼氳瘽
+            try {
+                mainCameraDevice.createCaptureSession(Arrays.asList(previewSurface, surfaceForStream), new CameraCaptureSession.StateCallback() {
+                    @Override
+                    public void onConfigured(@NonNull CameraCaptureSession session) {
+                        mainCaptureSession = session;
+                    }
+
+                    @Override
+                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
+
+                    }
+                }, null);
+            } catch (Exception e) {
+                e.printStackTrace();
+
+            }
+        }
+
+        @Override
+        public void onDisconnected(@NonNull CameraDevice camera) {
+
+        }
+
+        @Override
+        public void onError(@NonNull CameraDevice camera, int error) {
+
+        }
+    };
+
     private void createPreviewSession() {
         try {
-            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), new CameraCaptureSession.StateCallback() {
+
+            mainCameraDevice.createCaptureSession(Arrays.asList(previewSurface,surfaceForStream), new CameraCaptureSession.StateCallback() {
                 @Override
                 public void onConfigured(@NonNull CameraCaptureSession session) {
-                    mCaptureSession = session;
-                    startPreview(mCameraDevice);
+                    mainCaptureSession = session;
+                    try {
+                        previewCaptureBuilder = mainCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                    } catch (CameraAccessException e) {
+                        e.printStackTrace();
+                    }
+                    previewCaptureBuilder.addTarget(previewSurface);
+                    startPreview();
                 }
 
                 @Override
@@ -183,36 +243,16 @@
             e.printStackTrace();
         }
     }
-    private void startPreview(CameraDevice cameraDevice) {
+    private void startPreview() {
         //鍚姩棰勮
         try {
-            captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
-            captureBuilder.addTarget(previewSurface);
-
-            /*璁剧疆棰勮鐨勭晫闈�*/
-            //璁剧疆甯х巼
-            captureBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
-                    rangeMin);
-            /*//璁剧疆鑷姩瀵圭劍妯″紡
-            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
-                    CaptureRequest.CONTROL_AF_MODE_AUTO);
-            // 璁剧疆鑷姩鏇濆厜妯″紡
-            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
-                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
-            // 寮�濮嬪鐒�
-            captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
-                    CameraMetadata.CONTROL_AF_TRIGGER_START);*/
-            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,  90);
-
-            mCaptureSession.setRepeatingRequest(captureBuilder.build(), null, mHandler);
+            mainCaptureSession.setRepeatingRequest(previewCaptureBuilder.build(), null, mHandler);
         } catch (CameraAccessException e) {
             e.printStackTrace();
         }
     }
 
     private Surface recorderSurface;
-    private int videoWidth = 1280;
-    private int videoHeight = 720;
     private File recorderFile;
     private String recorderPath;
     private boolean isRecording = false;
@@ -228,8 +268,6 @@
         recorderPath = recorderFile.getAbsolutePath()+File.separator + System.currentTimeMillis() + ".mp4";
         Log.e(TAG, "瑙嗛璺緞锛�" + recorderPath);
         mMediaRecorder = new MediaRecorder();
-//        recorderSurface = MediaCodec.createPersistentInputSurface();
-//        mMediaRecorder.setInputSurface(recorderSurface);
         mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
@@ -239,26 +277,29 @@
         mMediaRecorder.setVideoSize(videoWidth, videoHeight);
         mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
         mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+    }
 
-        // 寮�濮嬪綍鍒�
-        /*try {
-            mMediaRecorder.prepare();
-        } catch (IOException e) {
+    private Handler backgroundHandler;
+    private HandlerThread backgroundThread;
+
+    private void startBackgroundThread() {
+        backgroundThread = new HandlerThread("Camera Background");
+        backgroundThread.start();
+        backgroundHandler = new Handler(backgroundThread.getLooper());
+    }
+
+    private void stopBackgroundThread() {
+        backgroundThread.quitSafely();
+        try {
+            backgroundThread.join();
+            backgroundThread = null;
+            backgroundHandler = null;
+        } catch (InterruptedException e) {
             e.printStackTrace();
-        }*/
+        }
     }
 
     public void createRecorderSession(){
-        //鍏抽棴棰勮璇锋眰,鍚姩褰曞儚鐩稿叧
-        try {
-            mCaptureSession.stopRepeating();
-        }catch (Exception e){
-            e.printStackTrace();
-        }
-        mImageReader = ImageReader.newInstance(imageWeight, imageHeight, ImageFormat.JPEG, 1);
-        surfaceForStream = mImageReader.getSurface();
-        mImageReader.setOnImageAvailableListener(mImageReaderListener, mainHandler);
-
         if(mMediaRecorder!=null) {
             mMediaRecorder.reset();
         }
@@ -270,34 +311,20 @@
             e.printStackTrace();
         }
         try {
-            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,mMediaRecorder.getSurface(),surfaceForStream), new CameraCaptureSession.StateCallback() {
-//            mCameraDevice.createCaptureSession(Arrays.asList(mMediaRecorder.getSurface(),surfaceForStream), new CameraCaptureSession.StateCallback() {
+            subCameraDevice.createCaptureSession(Arrays.asList(mMediaRecorder.getSurface()), new CameraCaptureSession.StateCallback() {
                 @Override
                 public void onConfigured(@NonNull CameraCaptureSession session) {
-                    mCaptureSession = session;
+                    subCaptureSession = session;
                     try {
                         //camera2 瑙嗛褰曞埗妯″紡
-                        recordRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+                        videoCaptureBuilder = subCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
 
-                        recordRequest.addTarget(previewSurface);
-                        recordRequest.addTarget(mMediaRecorder.getSurface());
+                        videoCaptureBuilder.addTarget(mMediaRecorder.getSurface());
 
-                        mCaptureSession.setRepeatingRequest(recordRequest.build(), null, mHandler); // 寮�濮嬪綍鍒惰棰�
-                        //camera2 鎹曟崏瑙嗛蹇収,1绉掗挓1娆$殑瀹氭椂浠诲姟
-                        CaptureRequest.Builder snapshotBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
-                        snapshotBuilder.addTarget(surfaceForStream);
-
-                        scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
-                        scheduledExecutorService.scheduleAtFixedRate(() -> {
-                            try {
-                                session.capture(snapshotBuilder.build(), null, null);
-                            }catch (Exception e){
-                                e.printStackTrace();
-                            }
-                        }, 1, 3, TimeUnit.SECONDS);
-
-
-                    } catch (Exception e) {                        e.printStackTrace();
+                        // 寮�濮嬪綍鍒惰棰�
+                        subCaptureSession.setRepeatingRequest(videoCaptureBuilder.build(), null, backgroundHandler);
+                    } catch (Exception e) {
+                        e.printStackTrace();
                     }
                 }
 
@@ -306,51 +333,53 @@
 
                 }
             }, null);
-//            CaptureRequest.Builder recordRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
-
-
-
+            //camera2 3绉掗挓1娆$殑瀹氭椂浠诲姟
+            //瀵圭劍骞舵媿鐓�
+            scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
+            scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+                @Override
+                public void run() {
+                    takePhoto();
+                }
+            }, 2, 2, TimeUnit.SECONDS);
+//            focus();
         } catch (CameraAccessException e) {
             e.printStackTrace();
         }
     }
 
+    private void takePhoto() {
+        try {
+            // 瀵圭劍瀹屾垚锛屽紑濮嬫媿鐓�
+            /*==========鎽勫儚澶寸殑妯″紡璁剧疆==========*/
+            // 璁剧疆鑷姩鐧藉钩琛�
+            //            captureCaptureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO);
+            // 璁剧疆瀵圭劍妯″紡
+            //            captureCaptureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+            try {
+                CaptureRequest.Builder captureRequest = mainCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+                captureRequest.addTarget(surfaceForStream);
+                captureRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+                mainCaptureSession.capture(captureRequest.build(),null, mHandler);
+                Log.d("Camera2", "鎷嶇収鎴愬姛");
+            } catch (CameraAccessException e) {
+                e.printStackTrace();
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+
+
     private ImageReader.OnImageAvailableListener mImageReaderListener = reader -> {
-        /*long now = System.currentTimeMillis();
-        SharedPreferences camera2Time = mContext.getSharedPreferences("camera2Time", Context.MODE_PRIVATE);
-        long lastTime = camera2Time.getLong("time", 0);
-        if (lastTime == 0 || now-lastTime > 1000) {
-            //杩欓噷鍙槸婕旂ずtest
-            llUpText.setVisibility(View.VISIBLE);
-            tvDevice.setText("杩欐槸娴嬭瘯鐨勫姩鎬佽祴鍊�");
-            camera2Time.edit().putLong("time", now).apply();
-
-            // 鑾峰彇鍒版媿鐓х殑鍥惧儚鏁版嵁
-            Image image = reader.acquireNextImage();
-
-            // 鑾峰彇鍥剧墖鐨勫瓧鑺傛暟缁�
-            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
-            byte[] data = new byte[buffer.remaining()];
-            buffer.get(data);
-            // 閲婃斁鍥惧儚璧勬簮
-            image.close();
-
-            // 淇濆瓨鍥剧墖鍒扮浉鍐�
-            saveImageToGallery(data);
-        }else{
-            // 鑾峰彇鍒版媿鐓х殑鍥惧儚鏁版嵁
-            Image image = reader.acquireNextImage();
-            image.close();
-        }*/
             // 鑾峰彇鍒版媿鐓х殑鍥惧儚鏁版嵁
             Image image = reader.acquireNextImage();
             //杩欓噷鍙槸婕旂ずtest
             llUpText.setVisibility(View.VISIBLE);
             tvDevice.setText("杩欐槸娴嬭瘯鐨勫姩鎬佽祴鍊�");
             // 淇濆瓨鍥剧墖鍒扮浉鍐�
-            executorService.execute(() -> {
-                saveImageToGallery(image);
-            });
+            saveImageToGallery(image);
 
     };
 
@@ -385,18 +414,23 @@
     }
 
     public void stopRecording() {
+        stopBackgroundThread();
         try {
             // 鍋滄褰曞埗瑙嗛,鍏抽棴褰曞儚璇锋眰
             mMediaRecorder.stop();
             //鍏抽棴瀹氭椂瑙嗛蹇収
             scheduledExecutorService.shutdownNow();
-            mCaptureSession.stopRepeating();
+            //鍏抽棴褰曞埗瑙嗛浼氳瘽
+            subCaptureSession.close();
+
+            //鍏抽棴鎷嶇収浼氳瘽
+            mainCaptureSession.close();
             //鍋滄鐢婚潰鍥剧墖鐩戝惉
             mImageReader.close();
            //杩欓噷鍙槸婕旂ずtest
             llUpText.setVisibility(View.GONE);
             //鍚姩棰勮
-            createPreviewSession();
+//            createPreviewSession();
         } catch (Exception e) {
             e.printStackTrace();
         } finally {

--
Gitblit v1.9.1