From 263432ae8c0f6f6dc5cc214772f1863389184add Mon Sep 17 00:00:00 2001 From: whycxzp <glperry@163.com> Date: 星期五, 26 七月 2024 14:36:22 +0800 Subject: [PATCH] 优化线程和释放资源 --- app/src/main/java/com/whyc/widget/Camera2TextureView2.java | 244 ++++++++++++++++++++++++++++++++---------------- 1 files changed, 161 insertions(+), 83 deletions(-) diff --git a/app/src/main/java/com/whyc/widget/Camera2TextureView2.java b/app/src/main/java/com/whyc/widget/Camera2TextureView2.java index bd959f9..80f2920 100644 --- a/app/src/main/java/com/whyc/widget/Camera2TextureView2.java +++ b/app/src/main/java/com/whyc/widget/Camera2TextureView2.java @@ -3,6 +3,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; +import android.graphics.Bitmap; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; @@ -11,7 +12,6 @@ import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CaptureRequest; -import android.hardware.camera2.params.StreamConfigurationMap; import android.media.Image; import android.media.ImageReader; import android.media.MediaRecorder; @@ -27,16 +27,19 @@ import android.util.Size; import android.view.Surface; import android.view.TextureView; -import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; + +import com.whyc.util.BitmapUtil; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -68,21 +71,35 @@ private ImageReader mImageReader; private Surface surfaceForStream; - private Handler mHandler; + /**绾跨▼澶勭悊鍣� 鍒嗗埆澶勭悊 褰曞儚,棰勮,鎷嶇収*/ private Handler mainHandler = new Handler(Looper.getMainLooper()); - private HandlerThread mThreadHandler; + + private HandlerThread videoThread; + private HandlerThread previewThread; + private HandlerThread captureThread; + private HandlerThread imageThread; + + private Handler videoThreadHandler; + private Handler previewThreadHandler; + private Handler captureThreadHandler; + private Handler imageThreadHandler; + + ScheduledExecutorService scheduledExecutorService; //涓婚〉闈㈢殑瑙嗗浘 private LinearLayout llUpText; private TextView tvDevice; - private int weight = 3840; + private int wight = 3840; private int height = 2160; +// private int wight = 1920; +// private int height = 1080; private int videoWidth = 1920; private int videoHeight = 1080; - Size outputSizes; + Size outputSizes = new Size(wight,height); + public Camera2TextureView2(Context context) { super(context,null); @@ -99,14 +116,6 @@ });*/ mContext = context; - mThreadHandler = new HandlerThread("camera2"); - mThreadHandler.start(); - mHandler = new Handler(mThreadHandler.getLooper()); - - startBackgroundThread(); - - - } public void init(LinearLayout llUpText, TextView tvDevice) { @@ -120,8 +129,10 @@ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { //棰勮surface SurfaceTexture surfaceTexture = getSurfaceTexture(); - surfaceTexture.setDefaultBufferSize(videoWidth, videoHeight); + surfaceTexture.setDefaultBufferSize(outputSizes.getWidth(), outputSizes.getHeight()); previewSurface = new Surface(surfaceTexture); + //椤甸潰鍔犺浇鍚庡垵濮嬪寲绾跨▼澶勭悊鍣� + initPreviewThreadHandler(); initCamera2(); } @Override @@ -152,15 +163,9 @@ 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(); } @@ -187,23 +192,10 @@ @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(); - - }*/ + //鎷嶇収鐨勬帴鏀跺櫒 + mImageReader = ImageReader.newInstance(outputSizes.getWidth(), outputSizes.getHeight(), ImageFormat.YUV_420_888, 2); + // mImageReader = ImageReader.newInstance(outputSizes.getWidth(), outputSizes.getHeight(), ImageFormat.JPEG, 4); //鍒涘缓涓绘憚鍍忓ご浼氳瘽骞堕瑙� createPreviewSession(); } @@ -222,7 +214,7 @@ private void createPreviewSession() { try { - mainCameraDevice.createCaptureSession(Arrays.asList(previewSurface,surfaceForStream), new CameraCaptureSession.StateCallback() { + mainCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { mainCaptureSession = session; @@ -247,13 +239,12 @@ private void startPreview() { //鍚姩棰勮 try { - mainCaptureSession.setRepeatingRequest(previewCaptureBuilder.build(), null, mHandler); + mainCaptureSession.setRepeatingRequest(previewCaptureBuilder.build(), null, previewThreadHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } - private Surface recorderSurface; private File recorderFile; private String recorderPath; private boolean isRecording = false; @@ -280,31 +271,14 @@ mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); } - 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(){ if(mMediaRecorder!=null) { mMediaRecorder.reset(); } initRecorder(); + //绾跨▼寮�鍚� + initThreadHandlerForRecording(); + mImageReader.setOnImageAvailableListener(mImageReaderListener, imageThreadHandler); try{ mMediaRecorder.prepare(); mMediaRecorder.start(); @@ -323,7 +297,7 @@ videoCaptureBuilder.addTarget(mMediaRecorder.getSurface()); // 寮�濮嬪綍鍒惰棰� - subCaptureSession.setRepeatingRequest(videoCaptureBuilder.build(), null, backgroundHandler); + subCaptureSession.setRepeatingRequest(videoCaptureBuilder.build(), null, videoThreadHandler); } catch (Exception e) { e.printStackTrace(); } @@ -342,7 +316,7 @@ public void run() { takePhoto(); } - }, 2, 2, TimeUnit.SECONDS); + }, 5, 2, TimeUnit.SECONDS); // focus(); } catch (CameraAccessException e) { e.printStackTrace(); @@ -358,11 +332,13 @@ // 璁剧疆瀵圭劍妯″紡 // 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", "鎷嶇収鎴愬姛"); + if(captureCaptureBuilder == null) { + captureCaptureBuilder = mainCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); + captureCaptureBuilder.addTarget(mImageReader.getSurface()); + captureCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); + } + mainCaptureSession.capture(captureCaptureBuilder.build(),null, captureThreadHandler); + Log.d("Camera2", "鎷嶇収鎴愬姛:"); } catch (CameraAccessException e) { e.printStackTrace(); } @@ -371,18 +347,65 @@ } } - - private ImageReader.OnImageAvailableListener mImageReaderListener = reader -> { + Image image = reader.acquireNextImage(); + Log.d("Camera2", "鑾峰彇鍒板浘鍍忔暟鎹�:"); + try { // 鑾峰彇鍒版媿鐓х殑鍥惧儚鏁版嵁 - Image image = reader.acquireNextImage(); //杩欓噷鍙槸婕旂ずtest - llUpText.setVisibility(View.VISIBLE); - tvDevice.setText("杩欐槸娴嬭瘯鐨勫姩鎬佽祴鍊�"); - // 淇濆瓨鍥剧墖鍒扮浉鍐� - saveImageToGallery(image); + // llUpText.setVisibility(View.VISIBLE); + // tvDevice.setText("杩欐槸娴嬭瘯鐨勫姩鎬佽祴鍊�"); + // 淇濆瓨鍥剧墖鍒扮浉鍐�-杩欑鏂瑰紡鏄疛EPG鏍煎紡 + // saveImageToGallery(image); + //YUV420 + // int I420size = image.getWidth()*image.getHeight()*3/2; + // byte[] nv21 = new byte[I420size]; + // YUVUtil.YUVToNV21_NV12(image,nv21,outputSizes.getWidth(),outputSizes.getHeight(),"NV21"); + List<byte[]> planetBytes = getPlanetBytes(image); + byte[] nv21 = byteMergerAll(planetBytes.get(0), planetBytes.get(1)); + Bitmap bitmap = BitmapUtil.nv21ToBitmap(nv21, outputSizes.getWidth(), outputSizes.getHeight()); + BitmapUtil.saveBitmapToFile(bitmap); + }catch (Exception e){ + e.printStackTrace(); + }finally { + image.close(); + } }; + + private List<byte[]> getPlanetBytes(Image image) { + Image.Plane[] planes = image.getPlanes(); + int remaining0 = planes[0].getBuffer().remaining(); +// int remaining1 = planes[1].getBuffer().remaining(); + int remaining2 = planes[2].getBuffer().remaining(); + //鍒嗗埆鍑嗗涓変釜鏁扮粍鎺ユ敹YUV鍒嗛噺銆� + byte[] yRawSrcBytes = new byte[remaining0]; +// byte[] uRawSrcBytes = new byte[remaining1]; + byte[] vRawSrcBytes = new byte[remaining2]; + planes[0].getBuffer().get(yRawSrcBytes); +// planes[1].getBuffer().get(uRawSrcBytes); + planes[2].getBuffer().get(vRawSrcBytes); + + List<byte[]> yuvBytes = new ArrayList<>(); + yuvBytes.add(yRawSrcBytes); + yuvBytes.add(vRawSrcBytes); + return yuvBytes; + } + + private static byte[] byteMergerAll(byte[]... values) { + int length_byte = 0; + for (int i = 0; i < values.length; i++) { + length_byte += values[i].length; + } + byte[] all_byte = new byte[length_byte]; + int countLength = 0; + for (int i = 0; i < values.length; i++) { + byte[] b = values[i]; + System.arraycopy(b, 0, all_byte, countLength, b.length); + countLength += b.length; + } + return all_byte; + } private void saveImageToGallery(Image image) { // 瀹氫箟鍥剧墖鐨勪繚瀛樿矾寰勫拰鏂囦欢鍚� @@ -415,22 +438,20 @@ } public void stopRecording() { - stopBackgroundThread(); try { // 鍋滄褰曞埗瑙嗛,鍏抽棴褰曞儚璇锋眰 mMediaRecorder.stop(); //鍏抽棴褰曞埗瑙嗛浼氳瘽 - subCaptureSession.close(); - + subCaptureSession.stopRepeating(); //鍏抽棴鎷嶇収浼氳瘽 - scheduledExecutorService.shutdown(); - mainCaptureSession.close(); + scheduledExecutorService.shutdownNow(); //鍋滄鐢婚潰鍥剧墖鐩戝惉 - mImageReader.close(); + mImageReader.setOnImageAvailableListener(null, null); + //缁堟绾跨▼ + stopThreadHandlerForRecording(); + //杩欓噷鍙槸婕旂ずtest - llUpText.setVisibility(View.GONE); - //鍚姩棰勮 - createPreviewSession(); +// llUpText.setVisibility(View.GONE); } catch (Exception e) { e.printStackTrace(); } finally { @@ -452,4 +473,61 @@ Toast.makeText(mContext, "瑙嗛宸蹭繚瀛樿嚦鐩稿唽", Toast.LENGTH_SHORT).show(); }); } + + private void initPreviewThreadHandler(){ + //棰勮鐨勫鐞嗙嚎绋� + previewThread = new HandlerThread("camera2Preview"); + previewThread.start(); + previewThreadHandler = new Handler(previewThread.getLooper()); + + //鍥惧儚鐩戞祴鐨勫鐞嗙嚎绋� + imageThread = new HandlerThread("camera2Image"); + imageThread.start(); + imageThreadHandler = new Handler(imageThread.getLooper()); + } + + /** + * 褰曞儚 涓�涓嚎绋嬪鐞嗗櫒 + * 鎷嶇収 涓�涓嚎绋嬪鐞嗗櫒 + * 鍥惧儚鐩戞祴 涓�涓嚎绋嬪鐞嗗櫒 + */ + private void initThreadHandlerForRecording() { + //褰曞儚鐨勫鐞嗙嚎绋� + videoThread = new HandlerThread("Camera2Video"); + videoThread.start(); + videoThreadHandler = new Handler(videoThread.getLooper()); + + //鎷嶇収鐨勫鐞嗙嚎绋� + captureThread = new HandlerThread("camera2Capture"); + captureThread.start(); + captureThreadHandler = new Handler(captureThread.getLooper()); + + //鍥惧儚鐩戞祴鐨勫鐞嗙嚎绋� + if(imageThreadHandler == null) { + imageThread = new HandlerThread("camera2Image"); + imageThread.start(); + imageThreadHandler = new Handler(imageThread.getLooper()); + } + } + + private void stopThreadHandlerForRecording() { + try { + videoThread.quitSafely(); + videoThread.join(); + videoThread = null; + videoThreadHandler = null; + + captureThread.quitSafely(); + captureThread.join(); + captureThread = null; + captureThreadHandler = null; + + imageThread.quitSafely(); + imageThread.join(); + imageThread = null; + imageThreadHandler = null; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } -- Gitblit v1.9.1