From efa5fe48ebc866ec07a597ef551cf7e13c3b7aba Mon Sep 17 00:00:00 2001
From: whycxzp <glperry@163.com>
Date: 星期六, 27 七月 2024 17:27:02 +0800
Subject: [PATCH] 更新单摄像头的AR方案

---
 app/src/main/java/com/whyc/widget/Camera2TextureView4.java |  461 +++++++++++++++++++--------------------------------------
 1 files changed, 153 insertions(+), 308 deletions(-)

diff --git a/app/src/main/java/com/whyc/widget/Camera2TextureView4.java b/app/src/main/java/com/whyc/widget/Camera2TextureView4.java
index e6d2661..f7c46cc 100644
--- a/app/src/main/java/com/whyc/widget/Camera2TextureView4.java
+++ b/app/src/main/java/com/whyc/widget/Camera2TextureView4.java
@@ -2,19 +2,14 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.ImageFormat;
-import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
-import android.graphics.YuvImage;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureRequest;
 import android.media.Image;
 import android.media.ImageReader;
@@ -24,7 +19,6 @@
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
 import android.media.MediaScannerConnection;
-import android.net.Uri;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -32,16 +26,15 @@
 import android.util.AttributeSet;
 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 java.io.ByteArrayOutputStream;
+import com.whyc.util.BitmapUtil;
+import com.whyc.util.YUVUtil;
+
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 
@@ -49,23 +42,34 @@
 
 /**
  * 杩欎釜閲囩敤ImageReader瑙嗛甯ф潵鑾峰彇瑙嗛鍜屽鐞嗗浘鐗�
+ * TODO 鍏抽棴褰曞儚鍑虹幇mMediaMuxer 寮傚父
  * */
 public class Camera2TextureView4 extends TextureView {
 
     private Context mContext;
     private CameraDevice mCameraDevice;
-    private CaptureRequest.Builder captureBuilder = null;
+    private CaptureRequest.Builder previewCaptureBuilder = null;
+    private CaptureRequest.Builder videoCaptureBuilder = null;
     private CameraCaptureSession mCaptureSession;
     private ImageReader mImageReader;
     private Surface previewSurface;
 
     private MediaCodec mMediaCodec;
     private MediaMuxer mMediaMuxer;
-    private Handler mBackgroundHandler;
-    private HandlerThread mBackgroundThread;
+
     private int videoWidth = 1920;
     private int videoHeight = 1080;
 
+    /** 绾跨▼澶勭悊鍣�*/
+    private HandlerThread videoThread;
+    private HandlerThread previewThread;
+    private HandlerThread imageThread;
+    private HandlerThread cameraThread;
+
+    private Handler videoThreadHandler;
+    private Handler previewThreadHandler;
+    private Handler imageThreadHandler;
+    private Handler cameraThreadHandler;
     //瑙嗛鍜屽浘鐗囩殑鏂囦欢澶硅矾寰�
     File fileDir = new File(Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS).getAbsolutePath() + "/yc_test/");
     String recorderPath = fileDir.getAbsolutePath() + File.separator + System.currentTimeMillis() + ".mp4";
@@ -81,20 +85,6 @@
     public Camera2TextureView4(Context context, AttributeSet attrs) throws IOException {
         super(context, attrs);
         mContext = context;
-        mBackgroundThread = new HandlerThread("Camera2VideoRecorder");
-        mBackgroundThread.start();
-        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
-        mImageReader = ImageReader.newInstance(videoWidth, videoHeight, ImageFormat.YUV_420_888, 2);
-
-        mMediaCodec = createAndConfigureEncoder(videoWidth, videoHeight);
-//        mMediaCodec.start();
-//        String recorderPath = fileDir.getAbsolutePath()+File.separator + System.currentTimeMillis() + ".mp4";
-        /*try {
-            this.mMediaMuxer = new MediaMuxer(recorderPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
-            this.mMediaMuxer.setOrientationHint(90);
-        }catch (Exception e){
-            e.printStackTrace();
-        }*/
     }
 
     public void init(LinearLayout llUpText, TextView tvDevice) {
@@ -129,6 +119,13 @@
         CameraManager cm = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
         try {
             String cameraId = cm.getCameraIdList()[0];
+            //鍒濆鍖栭瑙堢嚎绋�
+            initPreviewThreadHandler();
+            cameraThread = new HandlerThread("Camera2Video");
+            cameraThread.start();
+            cameraThreadHandler = new Handler(cameraThread.getLooper());
+//            cm.openCamera(cameraId,mDeviceStateCallback,previewThreadHandler);
+//            cm.openCamera(cameraId,mDeviceStateCallback,cameraThreadHandler);
             cm.openCamera(cameraId,mDeviceStateCallback,null);
         }catch (Exception e){
             e.printStackTrace();
@@ -138,11 +135,13 @@
     private CameraDevice.StateCallback mDeviceStateCallback = new CameraDevice.StateCallback() {
             @Override
             public void onOpened(CameraDevice cameraDevice) {
+                //棰勮鍜屽浘鍍忕洃娴�
                 mCameraDevice = cameraDevice;
                 SurfaceTexture surfaceTexture = getSurfaceTexture();
                 surfaceTexture.setDefaultBufferSize(1920, 1080);
                 previewSurface = new Surface(surfaceTexture);
-
+                //鍥惧儚鐩戞祴
+                mImageReader = ImageReader.newInstance(videoWidth, videoHeight, ImageFormat.YUV_420_888, 2);
                 try {
                     createPreviewSession();
                 }catch (Exception e){
@@ -163,41 +162,39 @@
 
     private void createPreviewSession() {
         try {
-            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), new CameraCaptureSession.StateCallback() {
+            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                 @Override
                 public void onConfigured(@NonNull CameraCaptureSession session) {
-                    mCaptureSession = session;
-                    startPreview(mCameraDevice);
+                    try {
+                        mCaptureSession = session;
+                        previewCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                        previewCaptureBuilder.addTarget(previewSurface);
+
+                        /*璁剧疆棰勮鐨勭晫闈�*/
+                        //璁剧疆鑷姩瀵圭劍妯″紡
+                        previewCaptureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
+                        // 璁剧疆鑷姩鏇濆厜妯″紡
+                        previewCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+                        //            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,  90);
+                        startPreview();
+                    }catch (Exception e){
+                        e.printStackTrace();
+                    }
                 }
 
                 @Override
                 public void onConfigureFailed(@NonNull CameraCaptureSession session) {
 
                 }
-            }, null);
+            }, previewThreadHandler);
         }catch (Exception e){
             e.printStackTrace();
         }
     }
-    private void startPreview(CameraDevice cameraDevice) {
+    private void startPreview() {
         //鍚姩棰勮
         try {
-            captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
-            captureBuilder.addTarget(previewSurface);
-
-            /*璁剧疆棰勮鐨勭晫闈�*/
-            //璁剧疆鑷姩瀵圭劍妯″紡
-            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, mBackgroundHandler);
+            mCaptureSession.setRepeatingRequest(previewCaptureBuilder.build(), null, previewThreadHandler);
         } catch (CameraAccessException e) {
             e.printStackTrace();
         }
@@ -225,27 +222,41 @@
             e.printStackTrace();
         }
     }*/
+    /**瑙嗛褰曞埗*/
     public void createRecorderSession() throws IOException {
+        try {
+            //鍏抽棴棰勮
+            mCaptureSession.stopRepeating();
+        } catch (CameraAccessException e) {
+            e.printStackTrace();
+        }
+        //鍏抽棴棰勮绾跨▼
+        stopPreviewThreadHandler();
+        //鍒濆鍖栧綍鍒剁嚎绋�
+        initThreadHandlerForRecording();
+        mImageReader.setOnImageAvailableListener(mImageReaderListener, imageThreadHandler);
+
         String recorderPath = fileDir.getAbsolutePath()+File.separator + System.currentTimeMillis() + ".mp4";
         try {
-            this.mMediaMuxer = new MediaMuxer(recorderPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
-            this.mMediaMuxer.setOrientationHint(90);
+            mMediaCodec = createAndConfigureEncoder(videoWidth, videoHeight);
+            mMediaMuxer = new MediaMuxer(recorderPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+//            mMediaMuxer.setOrientationHint(90);
 
-            mImageReader.setOnImageAvailableListener(mImageReaderListener, null);
-            captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
-            captureBuilder.addTarget(previewSurface);
-            captureBuilder.addTarget(mImageReader.getSurface());
+            videoCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+            videoCaptureBuilder.addTarget(previewSurface);
+            videoCaptureBuilder.addTarget(mImageReader.getSurface());
+            mCaptureSession.setRepeatingRequest(videoCaptureBuilder.build(), null, videoThreadHandler);
         } catch (Exception e) {
             e.printStackTrace();
         }
-        try {
+        /*try {
             mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                 @Override
                 public void onConfigured(@NonNull CameraCaptureSession session) {
                     mCaptureSession = session;
                     try {
                         //camera2 瑙嗛褰曞埗妯″紡
-                        captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+//                        captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                         mCaptureSession.setRepeatingRequest(captureBuilder.build(), null, mBackgroundHandler);
 
                     } catch (Exception e) {
@@ -261,7 +272,7 @@
 
         } catch (Exception e) {
             e.printStackTrace();
-        }
+        }*/
     }
 
     private int mVideoTrackIndex = -1;
@@ -269,18 +280,23 @@
     private ImageReader.OnImageAvailableListener mImageReaderListener = reader -> {
         Image image = reader.acquireNextImage();
 
+        //        Image imageCopy = ImageReader.newInstance(videoWidth, videoHeight, ImageFormat.YUV_420_888, 1).acquireLatestImage();
         byte[] nv12 = new byte[I420size];
-        YUVToNV21_NV12(image,nv12,videoWidth,videoHeight,"NV12");
+        byte[] nv21 = new byte[I420size];
+
+        YUVUtil.YUVToNV21_NV12(image,nv12,videoWidth,videoHeight,"NV12");
         long now = image.getTimestamp();
         image.close();
         //鍥剧墖鎴浘
         SharedPreferences camera2Time = mContext.getSharedPreferences("camera2Time", Context.MODE_PRIVATE);
         long lastTime = camera2Time.getLong("time", 0);
-
-        if (lastTime == 0  || now-lastTime > 1000000000) {
+        long secondsGap = (now - lastTime) / 1000000000;
+        if (lastTime == 0  || secondsGap > 2) {
             camera2Time.edit().putLong("time", now).apply();
-            Bitmap bitmap = nv21ToBitmap(nv12, videoWidth, videoHeight);
-            saveBitmapToFile(bitmap);
+            //闇�瑕佸皢nv12杞寲涓簄v21鍚庤繘琛屽浘鐗囧瓨鍌�
+            nv21 = convertNV12toNV21(nv12);
+            Bitmap bitmap = BitmapUtil.nv21ToBitmap(nv21, videoWidth, videoHeight);
+            BitmapUtil.saveBitmapToFile(bitmap);
         }
 
         // 鎻愪氦鏁版嵁缁橫ediaCodec
@@ -314,259 +330,42 @@
             }
         }
 
-            /*ByteBuffer encodedData = mMediaCodec.getOutputBuffer(outputBufferIndex);
-            if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
-                // 濡傛灉MediaMuxer杩樻病鏈夊噯澶囧ソ锛屾坊鍔犺棰戣建閬�
-
-                // 鍐欏叆鏁版嵁鍒癕ediaMuxer
-                MediaFormat format = mMediaCodec.getOutputFormat();
-                int trackIndex = mMediaMuxer.addTrack(format);
-                if(trackIndex)
-                mMediaMuxer.start();
-
-                encodedData.position(bufferInfo.offset);
-                encodedData.limit(bufferInfo.offset + bufferInfo.size);
-                mMediaMuxer.writeSampleData(trackIndex, encodedData, bufferInfo);
-            }
-
-            mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);*/
-
     };
-
-    private static void YUVToNV21_NV12(Image image, byte[] nv21, int w, int h,String type) {
-        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);
-        int j = 0, k = 0;
-        boolean flag = type.equals("NV21");
-        for (int i = 0; i < nv21.length; i++) {
-            if (i < w * h) {
-                //棣栧厛濉厖w*h涓猋鍒嗛噺
-                nv21[i] = yRawSrcBytes[i];
-            } else {
-                if (flag) {
-                    //鑻V21绫诲瀷 鍒橸鍒嗛噺鍒嗛厤瀹屽悗绗竴涓皢鏄疺鍒嗛噺
-                    nv21[i] = vRawSrcBytes[j];
-                    //PixelStride鏈夌敤鏁版嵁姝ラ暱 = 1绱у噾鎸夐『搴忓~鍏咃紝=2姣忛棿闅斾竴涓~鍏呮暟鎹�
-                    j += planes[1].getPixelStride();
-                } else {
-                    //鑻V12绫诲瀷 鍒橸鍒嗛噺鍒嗛厤瀹屽悗绗竴涓皢鏄疷鍒嗛噺
-                    nv21[i] = uRawSrcBytes[k];
-                    //PixelStride鏈夌敤鏁版嵁姝ラ暱 = 1绱у噾鎸夐『搴忓~鍏咃紝=2姣忛棿闅斾竴涓~鍏呮暟鎹�
-                    k += planes[2].getPixelStride();
-                }
-                //绱ф帴鐫�鍙互浜ら敊UV鎴栬�匳U鎺掑垪涓嶅仠鐨勬敼鍙榝lag鏍囧織鍗冲彲浜ら敊鎺掑垪
-                flag = !flag;
-            }
+    public byte[] convertNV12toNV21(byte[] nv12) {
+        int length = nv12.length;
+        byte[] nv21 = new byte[length];
+        // Copy Y component
+        System.arraycopy(nv12, 0, nv21, 0, length - (length / 4));
+        // Copy and swap U/V components
+        for (int i = length - (length / 4), j = length - (length / 4); i < length; i += 2, j += 2) {
+            nv21[j] = nv12[i + 1];
+            nv21[j + 1] = nv12[i];
         }
-    }
-
-    public static byte[] imageToNV12(Image image) {
-        final int width = image.getWidth();
-        final int height = image.getHeight();
-
-        Image.Plane[] planes = image.getPlanes();
-        byte[] yuv = new byte[width * height *2];
-
-        // Y component
-        ByteBuffer yBuffer = planes[0].getBuffer();
-        int ySize = yBuffer.remaining();
-        yBuffer.get(yuv, 0, ySize);
-
-        // U and V components
-        ByteBuffer uBuffer = planes[1].getBuffer();
-        ByteBuffer vBuffer = planes[2].getBuffer();
-        int uSize = uBuffer.remaining();
-        int vSize = vBuffer.remaining();
-
-        uBuffer.get(yuv, ySize, uSize);
-        vBuffer.get(yuv, ySize + uSize, vSize);
-
-        // Swap U and V for NV21 format
-        byte[] swapped = new byte[yuv.length];
-        System.arraycopy(yuv, 0, swapped, 0, ySize);
-        System.arraycopy(yuv, ySize + uSize, swapped, ySize + uSize, vSize);
-        System.arraycopy(yuv, ySize, swapped, ySize, uSize);
-
-        return swapped;
-    }
-
-    /*private void encodeFrame(Image image) {
-        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
-        int inputBufferId = mMediaCodec.dequeueInputBuffer(100);
-        if (inputBufferId >= 0) {
-            ByteBuffer inputBuffer = mMediaCodec.getInputBuffers()[inputBufferId];
-            inputBuffer.clear();
-
-            //杩欓噷鏄噸鐐�!
-            Image.Plane[] planes = image.getPlanes();
-            ByteBuffer[] yuvPlanes = new ByteBuffer[planes.length];
-            int[] offsets = new int[planes.length];
-            int[] strides = new int[planes.length];
-
-            for (int i = 0; i < planes.length; i++) {
-                yuvPlanes[i] = planes[i].getBuffer();
-                offsets[i] = yuvPlanes[i].position();
-                strides[i] = planes[i].getRowStride();
-            }
-
-            int height = image.getHeight();
-            int ySize = calculateSize(strides[0], image.getHeight());
-            int uSize = calculateSize(strides[1], image.getHeight() / 2);
-            int vSize = calculateSize(strides[2], image.getHeight() / 2);
-
-            if (ySize + uSize + vSize > inputBuffer.capacity()) {
-                throw new BufferOverflowException();
-            }
-            // Copy Y plane
-            copyPlaneData(yuvPlanes[0], inputBuffer, ySize, strides[0],height);
-
-            // Copy U plane
-            copyPlaneData(yuvPlanes[1], inputBuffer, uSize, strides[1],height/2);
-
-            // Copy V plane
-            copyPlaneData(yuvPlanes[2], inputBuffer, vSize, strides[2],height/2);
-
-            mMediaCodec.queueInputBuffer(
-                    inputBufferId,
-                    0,
-                    ySize + uSize + vSize,
-                    image.getTimestamp(),
-                    0
-            );
-            *//*int ySize = planes[0].getBuffer().remaining();
-            int uvSize = planes[1].getBuffer().remaining();
-
-            // Copy Y plane
-            planes[0].getBuffer().rewind();
-            inputBuffer.put(planes[0].getBuffer());
-
-            // Copy U and V planes
-            planes[1].getBuffer().rewind();
-            inputBuffer.put(planes[1].getBuffer());
-            planes[2].getBuffer().rewind();
-            inputBuffer.put(planes[2].getBuffer());
-
-            mMediaCodec.queueInputBuffer(
-                    inputBufferId,
-                    0,
-                    ySize + 2 * uvSize, // Size of YUV data
-                    image.getTimestamp(),
-                    0
-            );*//*
-
-        }
-        int encoderStatus = mMediaCodec.dequeueOutputBuffer(bufferInfo, 1000);
-        MediaFormat format = mMediaCodec.getOutputFormat();
-        int track = mMediaMuxer.addTrack(format);
-        if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-            mMediaMuxer.start();
-        } else if (encoderStatus >= 0) {
-            ByteBuffer encodedData = mMediaCodec.getOutputBuffers()[encoderStatus];
-            if (encodedData != null && encodedData.position() < encodedData.limit()) {
-                mMediaMuxer.writeSampleData(track, encodedData, bufferInfo);
-            }
-            mMediaCodec.releaseOutputBuffer(encoderStatus, false);
-        }
-    }
-
-    private int calculateSize(int stride, int height) {
-        return stride * height;
-    }
-
-    private void copyPlaneData(ByteBuffer src, ByteBuffer dst, int size, int stride,int height) {
-        int rowPadding = stride - (size / height);
-        int shift = 0;
-        while (src.hasRemaining()) {
-            dst.put(src.get());
-            shift++;
-            if (shift == stride) {
-                shift = 0;
-                dst.position(dst.position() + rowPadding);
-            }
-        }
-    }*/
-
-    private static Bitmap nv21ToBitmap(byte[] nv21, int width, int height) {
-        Bitmap bitmap = null;
-        try {
-            YuvImage image = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
-            ByteArrayOutputStream stream = new ByteArrayOutputStream();
-            //杈撳嚭鍒板搴旀祦
-            image.compressToJpeg(new Rect(0, 0, width, height), 100, stream);
-            //瀵瑰簲瀛楄妭娴佺敓鎴恇itmap
-            bitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
-            stream.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return bitmap;
-    }
-
-    private void saveBitmapToFile(Bitmap bitmap) {
-        // 瀹氫箟鍥剧墖鐨勪繚瀛樿矾寰勫拰鏂囦欢鍚�
-        String fileName = "IMG_" + System.currentTimeMillis() + ".jpg";
-        String filePath = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS).getAbsolutePath()  + "/yc_test"+ File.separator + fileName;
-        try{
-            FileOutputStream fos = new FileOutputStream(filePath);
-            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
-            fos.flush();
-        }catch (Exception e){
-            e.printStackTrace();
-        }
-    }
-    private void saveImageToGallery(byte[] data) {
-        // 瀹氫箟鍥剧墖鐨勪繚瀛樿矾寰勫拰鏂囦欢鍚�
-        String fileName = "IMG_" + System.currentTimeMillis() + ".jpg";
-        String filePath = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS).getAbsolutePath()  + "/yc_test"+ File.separator + fileName;
-
-        // 鍒涘缓鏂囦欢杈撳嚭娴�
-        try {
-            FileOutputStream fos = new FileOutputStream(filePath);
-            fos.write(data);
-            fos.close();
-
-            // 閫氱煡鍥惧簱鏇存柊
-            MediaScannerConnection.scanFile(mContext, new String[]{filePath}, null, null);
-
-            // 鍦ㄦ煇浜涜澶囦笂锛屽彲鑳介渶瑕佸彂閫佸箍鎾�氱煡鎵嶈兘浣垮浘鐗囩珛鍗冲嚭鐜板湪鐩稿唽涓�
-            mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(filePath))));
-
-            // 鏄剧ず淇濆瓨鎴愬姛鐨勬彁绀�
-            //            Toast.makeText(this, "鍥剧墖淇濆瓨鎴愬姛", Toast.LENGTH_SHORT).show();
-        } catch (IOException e) {
-            e.printStackTrace();
-            // 鏄剧ず淇濆瓨澶辫触鐨勬彁绀�
-            //            Toast.makeText(this, "鍥剧墖淇濆瓨澶辫触", Toast.LENGTH_SHORT).show();
-        }
+        return nv21;
     }
 
     public void stopRecording() {
-       //杩欓噷鍙槸婕旂ずtest
-        llUpText.setVisibility(View.GONE);
-        //鍋滄鐢婚潰鍥剧墖鐩戝惉
-        mImageReader.close();
-        this.mMediaCodec.stop();
-        this.mMediaCodec.release();
-        this.mMediaMuxer.stop();
-        this.mMediaMuxer.release();
-        // 鍋滄褰曞埗瑙嗛
         try {
-//            createPreviewSession();
-        } catch (IllegalStateException e) {
+            //鍋滄褰曞埗瑙嗛,鍋滄鐢婚潰鍥剧墖鐩戝惉
+            mMediaMuxer.stop();
+            mMediaCodec.stop();
+
+            //鍋滄褰曞儚Repeating
+            mCaptureSession.stopRepeating();
+            //绾跨▼鐩戞帶鍋滄
+            mImageReader.setOnImageAvailableListener(null, null);
+            //鍋滄褰曞埗瑙嗛绾跨▼
+            stopThreadHandlerForRecording();
+       //杩欓噷鍙槸婕旂ずtest
+//        llUpText.setVisibility(View.GONE);
+
+
+            startPreview();
+        } catch (IllegalStateException | CameraAccessException e) {
             e.printStackTrace();
         } finally {
-//            mMediaRecorder.reset();
-//            mMediaRecorder.release();
-//            mMediaRecorder = null;
+            mMediaCodec.release();
+            mMediaMuxer.release();
         }
 
         // 鍏抽棴鐩告満棰勮浼氳瘽
@@ -623,4 +422,50 @@
         return null;
     }
 
+    private void initPreviewThreadHandler(){
+        //棰勮鐨勫鐞嗙嚎绋�
+        previewThread = new HandlerThread("camera2Preview");
+        previewThread.start();
+        previewThreadHandler = new Handler(previewThread.getLooper());
+    }
+
+    private void stopPreviewThreadHandler(){
+        //棰勮鐨勫鐞嗙嚎绋�
+        try {
+            previewThread.quitSafely();
+            previewThread.join();
+            previewThread = null;
+            previewThreadHandler = null;
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void initThreadHandlerForRecording() {
+        //褰曞儚鐨勫鐞嗙嚎绋�
+        videoThread = new HandlerThread("Camera2Video");
+        videoThread.start();
+        videoThreadHandler = new Handler(videoThread.getLooper());
+
+        //鍥惧儚鐩戞祴鐨勫鐞嗙嚎绋�
+        imageThread = new HandlerThread("camera2Image");
+        imageThread.start();
+        imageThreadHandler = new Handler(imageThread.getLooper());
+    }
+
+    private void stopThreadHandlerForRecording() {
+        try {
+            videoThread.quitSafely();
+            videoThread.join();
+            videoThread = null;
+            videoThreadHandler = null;
+
+            imageThread.quitSafely();
+            imageThread.join();
+            imageThread = null;
+            imageThreadHandler = null;
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
 }

--
Gitblit v1.9.1