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