相机2 api全屏不伸展

问题描述 投票:2回答:1
private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();
private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();
private static final long DELAY = 1000;
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
private long startTime = 0L;
int num = 1;
List<VideoModel> videoList;

private Handler customHandler = new Handler();
private static final String TAG = "RecordVideoActivity";
private String videoName;
static {
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_0, 90);
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_90, 0);
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_180, 270);
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_270, 180);
}

static {
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_0, 270);
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_90, 180);
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_180, 90);
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
}

private AutoFitTextureView mTextureView;
private ImageButton mRecordButton;
private ImageView mDots;
private ImageButton mCheckPoint;

private CameraDevice mCameraDevice;

private CameraCaptureSession mPreviewSession;

private TextureView.SurfaceTextureListener mSurfaceTextureListener
        = new TextureView.SurfaceTextureListener() {

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
                                          int width, int height) {
        openCamera(width, height);
    }

    @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
                                                int width, int height) {
        configureTransform(width, height);
    }

    @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
        }

    };


    private Size mPreviewSize;


    private Size mVideoSize;

    private MediaRecorder mMediaRecorder;

    private boolean mIsRecordingVideo;

    private HandlerThread mBackgroundThread;

    private Handler mBackgroundHandler;

    private Semaphore mCameraOpenCloseLock = new Semaphore(1);

    private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {

        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            mCameraDevice = cameraDevice;
            startPreview();
            mCameraOpenCloseLock.release();
            if (null != mTextureView) {
                configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            mCameraOpenCloseLock.release();
            cameraDevice.close();
            mCameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int error) {
            mCameraOpenCloseLock.release();
            cameraDevice.close();
            mCameraDevice = null;
            finish();
        }

    };
private Integer mSensorOrientation;
private String mNextVideoAbsolutePath;
private CaptureRequest.Builder mPreviewBuilder;
private CameraManager manager;
private String cameraId;
private boolean isFlashSupported;
private ImageButton flashButton;
private ImageButton switchCamera;
private ImageButton revertVideo;
public static final String CAMERA_BACK = "0";
private TextView mChronometer;
private String flashOpt;
private long lastSavedTime;
private String prepend;

private static Size chooseVideoSize(Size[] choices) {
    for (Size size : choices) {
        if (size.getWidth() == size.getHeight() * 4 / 3 && size.getWidth() <= 1080) {
            return size;
        }
    }
    Log.e(TAG, "Couldn't find any suitable video size");
    return choices[choices.length - 1];
}


private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
    // Collect the supported resolutions that are at least as big as the preview Surface
    List<Size> bigEnough = new ArrayList<>();
    int w = aspectRatio.getWidth();
    int h = aspectRatio.getHeight();
    for (Size option : choices) {
        if (option.getHeight() == option.getWidth() * h / w &&
                option.getWidth() >= width && option.getHeight() >= height) {
            bigEnough.add(option);
        }
    }

    // Pick the smallest of those, assuming we found any
    if (bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizesByArea());
    } else {
        Log.e(TAG, "Couldn't find any suitable preview size");
        return choices[0];
    }
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera2_video_image);
    File dir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_MOVIES) + File.separator + AppConstants.APPDIRRECORDING);
    if (dir.isDirectory()) {
        deleteDirectory(dir);
    }
    videoList = new ArrayList<>();
    mTextureView = findViewById(R.id.textureView);
    mRecordButton = findViewById(R.id.videoOnlineImageButton);
    mRecordButton.setImageResource(R.drawable.ic_video);
    mCheckPoint = findViewById(R.id.checkPoint);
    mCheckPoint.setVisibility(View.GONE);
    mDots = findViewById(R.id.dot);
    mRecordButton.setOnClickListener(this);
    flashButton = findViewById(R.id.flashVideo);
    switchCamera = findViewById(R.id.switchVideo);
    revertVideo = findViewById(R.id.revertVideo);
    revertVideo.setVisibility(View.GONE);
    mChronometer = findViewById(R.id.chronometer);
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    flashOpt = prefs.getString(getString(R.string.flash_option), getString(R.string.auto));
    if (flashOpt.equals(getString(R.string.flash_off)))
        flashButton.setImageResource(R.drawable.flash_auto);

    else if (flashOpt.equals(getString(R.string.flash_on)))
        flashButton.setImageResource(R.drawable.flash_on);

    else
        flashButton.setImageResource(R.drawable.flash_off);
        findViewById(R.id.checkPoint).setOnClickListener(this);
        findViewById(R.id.flashVideo).setOnClickListener(this);
        findViewById(R.id.switchVideo).setOnClickListener(this);
        findViewById(R.id.revertVideo).setOnClickListener(this);
    }


    @Override
    public void onResume() {
        super.onResume();
        startBackgroundThread();
        if (mTextureView.isAvailable()) {
            openCamera(mTextureView.getWidth(), mTextureView.getHeight());
        } else {
            mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
        }
        if(mIsRecordingVideo)
            mRecordButton.setImageResource(R.drawable.ic_video_stop);
         else
            mRecordButton.setImageResource(R.drawable.ic_video);

        mCheckPoint.setEnabled(true);
        startTime=SystemClock.uptimeMillis();
        customHandler.postDelayed(updateTimerThread, 0);

    }

    @Override
    public void onPause() {
        closeCamera();
        mCheckPoint.setEnabled(false);
        timeSwapBuff += timeInMilliseconds;
        customHandler.removeCallbacks(updateTimerThread);
        stopBackgroundThread();
        super.onPause();
    }

    private Runnable updateTimerThread = new Runnable() {

        public void run() {
            timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
            updatedTime = timeSwapBuff + timeInMilliseconds;
            int secs = (int) (updatedTime / 1000);
            int mins = secs / 60;
            secs = secs % 60;
            int hour = mins / 60;
            mChronometer.setText("" + hour + ":"
                    + String.format("%02d", mins) + ":"
                    + String.format("%02d", secs));
            customHandler.postDelayed(this, 0);
        }

    };

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.videoOnlineImageButton: {
                if (mIsRecordingVideo) {
                    mDots.setVisibility(View.GONE);
                    mChronometer.setVisibility(View.GONE);
                    switchCamera.setVisibility(View.VISIBLE);
                    mCheckPoint.setVisibility(View.GONE);
                    stopRecordingVideo();
                    Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    mediaStoreUpdateIntent.setData(Uri.fromFile(new File(mNextVideoAbsolutePath)));
                    sendBroadcast(mediaStoreUpdateIntent);


                } else {
                    mCheckPoint.setVisibility(View.VISIBLE);
                    switchCamera.setVisibility(View.GONE);
                    mChronometer.setVisibility(View.VISIBLE);
                    mDots.setVisibility(View.VISIBLE);
                    startRecordingVideo();
                }
                break;
            }
            case R.id.switchVideo: {
                facingCamera = !facingCamera;
                closeCamera();
                if (mTextureView.isAvailable()) {
                    openCamera(mTextureView.getWidth(), mTextureView.getHeight());

                } else {
                    mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
                }
                break;
            }

            case R.id.flashVideo: {
                if (onFlashCheck()) {
                    CameraCharacteristics cameraCharacteristics = null;
                    try {
                        cameraCharacteristics = manager.getCameraCharacteristics(cameraId);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                    Boolean available = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
                    isFlashSupported = available == null ? false : available;

                    switchFlash();

                }
                break;
            }

        }
    }

    private void startBackgroundThread() {
        mBackgroundThread = new HandlerThread("CameraBackground");
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
    }


    private void stopBackgroundThread() {
        mBackgroundThread.quitSafely();
        try {
            mBackgroundThread.join();
            mBackgroundThread = null;
            mBackgroundHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    @SuppressLint("MissingPermission")
    private void openCamera(int width, int height) {
        final Activity activity = this;
        if (null == activity || activity.isFinishing()) {
            return;
        }
        manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
        try {
            Log.d(TAG, "tryAcquire");
            if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
                throw new RuntimeException("Time out waiting to lock camera opening.");
            }
            cameraId = manager.getCameraIdList()[1];
            if (facingCamera) {
                cameraId = manager.getCameraIdList()[1];
                flashButton.setVisibility(View.GONE);
            } else {
                cameraId = manager.getCameraIdList()[0];
                flashButton.setVisibility(View.VISIBLE);
            }

            // Choose the sizes for camera preview and video recording
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = characteristics
                    .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            if (map == null) {
                throw new RuntimeException("Cannot get available preview/video sizes");
            }
            mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
            mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                    width, height, mVideoSize);

            int orientation = getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            } else {
                mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
            }
            configureTransform(width, height);
            mMediaRecorder = new MediaRecorder();
            manager.openCamera(cameraId, mStateCallback, null);
        } catch (CameraAccessException e) {
            Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
            activity.finish();
        } catch (NullPointerException e) {
        } catch (InterruptedException e) {
            throw new RuntimeException("Interrupted while trying to lock camera opening.");
        }
    }

    private void closeCamera() {
        try {
            mCameraOpenCloseLock.acquire();
            closePreviewSession();
            if (null != mCameraDevice) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
            if (null != mMediaRecorder) {
                mMediaRecorder.release();
                mMediaRecorder = null;
            }
        } catch (InterruptedException e) {
            throw new RuntimeException("Interrupted while trying to lock camera closing.");
        } finally {
            mCameraOpenCloseLock.release();
        }
    }

    private void startPreview() {
        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
            return;
        }
        try {
            closePreviewSession();
            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

            Surface previewSurface = new Surface(texture);
            mPreviewBuilder.addTarget(previewSurface);

            mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
                    new CameraCaptureSession.StateCallback() {

                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession session) {
                            mPreviewSession = session;
                            updatePreview();
                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                            Toast.makeText(RecordVideoActivity.this, "Failed", Toast.LENGTH_SHORT).show();

                        }
                    }, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void updatePreview() {
        if (null == mCameraDevice) {
            return;
        }
        try {
            setUpCaptureRequestBuilder(mPreviewBuilder);
            HandlerThread thread = new HandlerThread("CameraPreview");
            thread.start();
            mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void setUpCaptureRequestBuilder(CaptureRequest.Builder builder) {
        if (onFlashCheck()) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    flashButton.setVisibility(View.VISIBLE);
                }
            });

            if (flashOpt.equals(getString(R.string.auto)))
                builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            else if (flashOpt.equals(getString(R.string.flash_off)))
                builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
            else
                builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
        } else
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    flashButton.setVisibility(View.GONE);
                }
            });

    }


    private void configureTransform(int viewWidth, int viewHeight) {
        if (null == mTextureView || null == mPreviewSize) {
            return;
        }
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        Matrix matrix = new Matrix();
        RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
        RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
        float centerX = viewRect.centerX();
        float centerY = viewRect.centerY();
        if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
            bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
            matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
            float scale = Math.max(
                    (float) viewHeight / mPreviewSize.getHeight(),
                    (float) viewWidth / mPreviewSize.getWidth());
            matrix.postScale(scale, scale, centerX, centerY);
            matrix.postRotate(90 * (rotation - 2), centerX, centerY);
        }
        mTextureView.setTransform(matrix);
    }

    private void setUpMediaRecorder() throws IOException {
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        File file = getVideoFilePath(this);
        mNextVideoAbsolutePath = file.getAbsolutePath();
        videoName = file.getName();
        mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
        mMediaRecorder.setVideoEncodingBitRate(10000000);
        mMediaRecorder.setVideoFrameRate(30);
        mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        switch (mSensorOrientation) {
            case SENSOR_ORIENTATION_DEFAULT_DEGREES:
                mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
                break;
            case SENSOR_ORIENTATION_INVERSE_DEGREES:
                mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
                break;
        }
        mMediaRecorder.prepare();
    }

    private File getVideoFilePath(Context context) {
        File appDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_MOVIES) + File.separator + AppConstants.APPDIRRECORDING);
        if (!appDir.isDirectory()) {
            appDir.mkdirs();
        }
        String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String prepend = "VIDEO_" + timestamp + ".mp4";
        File videoFile = null;
        try {
            videoFile = File.createTempFile(prepend, ".mp4", appDir);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return videoFile;
    }

    private void startRecordingVideo() {
        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
            return;
        }
        try {
            closePreviewSession();

            setUpMediaRecorder();

            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            List<Surface> surfaces = new ArrayList<>();

            // Set up Surface for the camera preview
            Surface previewSurface = new Surface(texture);
            surfaces.add(previewSurface);
            mPreviewBuilder.addTarget(previewSurface);

            // Set up Surface for the MediaRecorder
            Surface recorderSurface = mMediaRecorder.getSurface();
            surfaces.add(recorderSurface);
            mPreviewBuilder.addTarget(recorderSurface);
            mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {

                @Override
                public void onConfigured(@NonNull final CameraCaptureSession cameraCaptureSession) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mPreviewSession = cameraCaptureSession;
                            updatePreview();
                            mIsRecordingVideo = true;

                            startTime = SystemClock.uptimeMillis();
                            mChronometer.setVisibility(View.VISIBLE);
                            customHandler.postDelayed(updateTimerThread, 0);
                            mRecordButton.setImageResource(R.drawable.ic_video_stop);
                            mMediaRecorder.start();
                            mCheckPoint.setEnabled(true);
                        }
                    });


                }


                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

                    Toast.makeText(RecordVideoActivity.this, "Failed", Toast.LENGTH_SHORT).show();

                }
            }, mBackgroundHandler);
        } catch (CameraAccessException | IOException e) {
            e.printStackTrace();
        }

    }

    private void closePreviewSession() {
        if (mPreviewSession != null) {
            mPreviewSession.close();
            mPreviewSession = null;
        }
    }

    @SuppressLint("ResourceType")
    private void stopRecordingVideo() {
        mIsRecordingVideo = false;
        customHandler.removeCallbacks(updateTimerThread);
        mRecordButton.setImageResource(R.drawable.ic_video);
        if(mMediaRecorder!=null) {
            try {
                mMediaRecorder.stop();

            } catch (RuntimeException e) {
                e.printStackTrace();

            }
            mMediaRecorder.reset();
        }


    }
    static class CompareSizesByArea implements Comparator<Size> {

        @Override
        public int compare(Size lhs, Size rhs) {
            return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
                    (long) rhs.getWidth() * rhs.getHeight());
        }

    }
    @Override
    protected void onDestroy() {
        customHandler.removeCallbacks(updateTimerThread);
    }

我已经在我的app.i中使用了相机2 api进行视频录制。我觉得视频流是拉伸的。主要是当我把相机切换到前面时。请帮助我解决这个问题

我已经在我的app.i中使用了相机2 api进行视频录制。我觉得视频流是拉伸的。主要是当我把相机切换到前面时。请帮助我解决这个问题

android-camera android-camera2 video-recording android-video-record
1个回答
1
投票

在AutoFitTextureView类中更改宽高比值或使用Textureview而不是AutoFitTextureview。

© www.soinside.com 2019 - 2024. All rights reserved.