twerd

Highspeed Preview

May 24th, 2016
2,621
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Copyright 2014 The Android Open Source Project
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *       http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16.  
  17. package com.example.android.camera2video;
  18.  
  19. import android.Manifest;
  20. import android.app.Activity;
  21. import android.app.AlertDialog;
  22. import android.app.Dialog;
  23. import android.app.DialogFragment;
  24. import android.app.Fragment;
  25. import android.content.Context;
  26. import android.content.DialogInterface;
  27. import android.content.pm.PackageManager;
  28. import android.content.res.Configuration;
  29. import android.graphics.Matrix;
  30. import android.graphics.RectF;
  31. import android.graphics.SurfaceTexture;
  32. import android.hardware.camera2.CameraAccessException;
  33. import android.hardware.camera2.CameraCaptureSession;
  34. import android.hardware.camera2.CameraCharacteristics;
  35. import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
  36. import android.hardware.camera2.CameraDevice;
  37. import android.hardware.camera2.CameraManager;
  38. import android.hardware.camera2.CameraMetadata;
  39. import android.hardware.camera2.CaptureRequest;
  40. import android.hardware.camera2.TotalCaptureResult;
  41. import android.hardware.camera2.params.StreamConfigurationMap;
  42. import android.media.MediaRecorder;
  43. import android.opengl.GLES20;
  44. import android.os.Bundle;
  45. import android.os.Handler;
  46. import android.os.HandlerThread;
  47. import android.support.annotation.NonNull;
  48. import android.support.v13.app.FragmentCompat;
  49. import android.support.v4.app.ActivityCompat;
  50. import android.util.Log;
  51. import android.util.Range;
  52. import android.util.Size;
  53. import android.util.SparseIntArray;
  54. import android.view.LayoutInflater;
  55. import android.view.Surface;
  56. import android.view.TextureView;
  57. import android.view.View;
  58. import android.view.ViewGroup;
  59. import android.widget.Button;
  60. import android.widget.Toast;
  61.  
  62. import java.io.IOException;
  63. import java.util.ArrayList;
  64. import java.util.Arrays;
  65. import java.util.Collections;
  66. import java.util.Comparator;
  67. import java.util.List;
  68. import java.util.concurrent.Semaphore;
  69. import java.util.concurrent.TimeUnit;
  70.  
  71. public class Camera2VideoFragment extends Fragment
  72.         implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
  73.  
  74.     private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
  75.     private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
  76.     private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();
  77.     private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();
  78.  
  79.     private static final String TAG = "Camera2VideoFragment";
  80.     private static final int REQUEST_VIDEO_PERMISSIONS = 1;
  81.     private static final String FRAGMENT_DIALOG = "dialog";
  82.  
  83.     private static final String[] VIDEO_PERMISSIONS = {
  84.             Manifest.permission.CAMERA,
  85.             Manifest.permission.RECORD_AUDIO,
  86.     };
  87.  
  88.     static {
  89.         DEFAULT_ORIENTATIONS.append(Surface.ROTATION_0, 90);
  90.         DEFAULT_ORIENTATIONS.append(Surface.ROTATION_90, 0);
  91.         DEFAULT_ORIENTATIONS.append(Surface.ROTATION_180, 270);
  92.         DEFAULT_ORIENTATIONS.append(Surface.ROTATION_270, 180);
  93.     }
  94.  
  95.     static {
  96.         INVERSE_ORIENTATIONS.append(Surface.ROTATION_0, 270);
  97.         INVERSE_ORIENTATIONS.append(Surface.ROTATION_90, 180);
  98.         INVERSE_ORIENTATIONS.append(Surface.ROTATION_180, 90);
  99.         INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
  100.     }
  101.  
  102.     /**
  103.      * An {@link AutoFitTextureView} for camera preview.
  104.      */
  105.     private AutoFitTextureView mTextureView;
  106.  
  107.     /**
  108.      * Button to record video
  109.      */
  110.     private Button mButtonVideo;
  111.  
  112.     /**
  113.      * A refernce to the opened {@link android.hardware.camera2.CameraDevice}.
  114.      */
  115.     private CameraDevice mCameraDevice;
  116.  
  117.     /**
  118.      * A reference to the current {@link android.hardware.camera2.CameraCaptureSession} for
  119.      * preview.
  120.      */
  121.     private CameraConstrainedHighSpeedCaptureSession mPreviewSession;
  122.  
  123.     /**
  124.      * {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
  125.      * {@link TextureView}.
  126.      */
  127.     private TextureView.SurfaceTextureListener mSurfaceTextureListener
  128.             = new TextureView.SurfaceTextureListener() {
  129.  
  130.         @Override
  131.         public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
  132.                                               int width, int height) {
  133.             openCamera(width, height);
  134.         }
  135.  
  136.         @Override
  137.         public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
  138.                                                 int width, int height) {
  139.             configureTransform(width, height);
  140.         }
  141.  
  142.         @Override
  143.         public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
  144.             return true;
  145.         }
  146.  
  147.         @Override
  148.         public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
  149.             //Should I try using GLES20 here?
  150.             Log.i("Surface Texture", "available");
  151.         }
  152.  
  153.     };
  154.  
  155.     /**
  156.      * The {@link android.util.Size} of camera preview.
  157.      */
  158.     private Size mPreviewSize;
  159.  
  160.     /**
  161.      * The {@link android.util.Size} of video recording.
  162.      */
  163.     private Size mVideoSize;
  164.  
  165.     /**
  166.      * MediaRecorder
  167.      */
  168.     private MediaRecorder mMediaRecorder;
  169.  
  170.     /**
  171.      * Whether the app is recording video now
  172.      */
  173.     private boolean mIsRecordingVideo;
  174.  
  175.     /**
  176.      * An additional thread for running tasks that shouldn't block the UI.
  177.      */
  178.     private HandlerThread mBackgroundThread;
  179.  
  180.     /**
  181.      * A {@link Handler} for running tasks in the background.
  182.      */
  183.     private Handler mBackgroundHandler;
  184.  
  185.     /**
  186.      * A {@link Semaphore} to prevent the app from exiting before closing the camera.
  187.      */
  188.     private Semaphore mCameraOpenCloseLock = new Semaphore(1);
  189.  
  190.     /**
  191.      * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its status.
  192.      */
  193.     private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
  194.  
  195.         @Override
  196.         public void onOpened(CameraDevice cameraDevice) {
  197.             mCameraDevice = cameraDevice;
  198.             startPreview();
  199.             mCameraOpenCloseLock.release();
  200.             if (null != mTextureView) {
  201.                 configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
  202.             }
  203.         }
  204.  
  205.         @Override
  206.         public void onDisconnected(CameraDevice cameraDevice) {
  207.             mCameraOpenCloseLock.release();
  208.             cameraDevice.close();
  209.             mCameraDevice = null;
  210.         }
  211.  
  212.         @Override
  213.         public void onError(CameraDevice cameraDevice, int error) {
  214.             mCameraOpenCloseLock.release();
  215.             cameraDevice.close();
  216.             mCameraDevice = null;
  217.             Activity activity = getActivity();
  218.             if (null != activity) {
  219.                 activity.finish();
  220.             }
  221.         }
  222.  
  223.     };
  224.     private Integer mSensorOrientation;
  225.     private String mNextVideoAbsolutePath;
  226.     private CaptureRequest.Builder mPreviewBuilder;
  227.     private Surface mRecorderSurface;
  228.  
  229.     public static Camera2VideoFragment newInstance() {
  230.         return new Camera2VideoFragment();
  231.     }
  232.  
  233.     /**
  234.      * In this sample, we choose a video size with 3x4 aspect ratio. Also, we don't use sizes
  235.      * larger than 1080p, since MediaRecorder cannot handle such a high-resolution video.
  236.      *
  237.      * @param choices The list of available sizes
  238.      * @return The video size
  239.      */
  240.     private static Size chooseVideoSize(Size[] choices) {
  241.         for (Size size : choices) {
  242.             if (size.getWidth() == size.getHeight() * 4 / 3 && size.getWidth() <= 1080) {
  243.                 return size;
  244.             }
  245.         }
  246.         Log.e(TAG, "Couldn't find any suitable video size");
  247.         return choices[choices.length - 1];
  248.     }
  249.  
  250.     /**
  251.      * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose
  252.      * width and height are at least as large as the respective requested values, and whose aspect
  253.      * ratio matches with the specified value.
  254.      *
  255.      * @param choices     The list of sizes that the camera supports for the intended output class
  256.      * @param width       The minimum desired width
  257.      * @param height      The minimum desired height
  258.      * @param aspectRatio The aspect ratio
  259.      * @return The optimal {@code Size}, or an arbitrary one if none were big enough
  260.      */
  261.     private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
  262.         // Collect the supported resolutions that are at least as big as the preview Surface
  263.         List<Size> bigEnough = new ArrayList<Size>();
  264.         int w = aspectRatio.getWidth();
  265.         int h = aspectRatio.getHeight();
  266.         for (Size option : choices) {
  267.             if (option.getHeight() == option.getWidth() * h / w &&
  268.                     option.getWidth() >= width && option.getHeight() >= height) {
  269.                 bigEnough.add(option);
  270.             }
  271.         }
  272.  
  273.         // Pick the smallest of those, assuming we found any
  274.         if (bigEnough.size() > 0) {
  275.             return Collections.min(bigEnough, new CompareSizesByArea());
  276.         } else {
  277.             Log.e(TAG, "Couldn't find any suitable preview size");
  278.             return choices[0];
  279.         }
  280.     }
  281.  
  282.     @Override
  283.     public View onCreateView(LayoutInflater inflater, ViewGroup container,
  284.                              Bundle savedInstanceState) {
  285.         return inflater.inflate(R.layout.fragment_camera2_video, container, false);
  286.     }
  287.  
  288.     @Override
  289.     public void onViewCreated(final View view, Bundle savedInstanceState) {
  290.         mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
  291.         mButtonVideo = (Button) view.findViewById(R.id.video);
  292.         mButtonVideo.setOnClickListener(this);
  293.         view.findViewById(R.id.info).setOnClickListener(this);
  294.     }
  295.  
  296.     @Override
  297.     public void onResume() {
  298.         super.onResume();
  299.         startBackgroundThread();
  300.         if (mTextureView.isAvailable()) {
  301.             openCamera(mTextureView.getWidth(), mTextureView.getHeight());
  302.         } else {
  303.             mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
  304.         }
  305.     }
  306.  
  307.     @Override
  308.     public void onPause() {
  309.         closeCamera();
  310.         stopBackgroundThread();
  311.         super.onPause();
  312.     }
  313.  
  314.     @Override
  315.     public void onClick(View view) {
  316.         switch (view.getId()) {
  317.             case R.id.info: {
  318.                 Activity activity = getActivity();
  319.                 if (null != activity) {
  320.                     new AlertDialog.Builder(activity)
  321.                             .setMessage(R.string.intro_message)
  322.                             .setPositiveButton(android.R.string.ok, null)
  323.                             .show();
  324.                 }
  325.                 break;
  326.             }
  327.         }
  328.     }
  329.  
  330.     /**
  331.      * Starts a background thread and its {@link Handler}.
  332.      */
  333.     private void startBackgroundThread() {
  334.         mBackgroundThread = new HandlerThread("CameraBackground");
  335.         mBackgroundThread.start();
  336.         mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
  337.     }
  338.  
  339.     /**
  340.      * Stops the background thread and its {@link Handler}.
  341.      */
  342.     private void stopBackgroundThread() {
  343.         mBackgroundThread.quitSafely();
  344.         try {
  345.             mBackgroundThread.join();
  346.             mBackgroundThread = null;
  347.             mBackgroundHandler = null;
  348.         } catch (InterruptedException e) {
  349.             e.printStackTrace();
  350.         }
  351.     }
  352.  
  353.     /**
  354.      * Gets whether you should show UI with rationale for requesting permissions.
  355.      *
  356.      * @param permissions The permissions your app wants to request.
  357.      * @return Whether you can show permission rationale UI.
  358.      */
  359.     private boolean shouldShowRequestPermissionRationale(String[] permissions) {
  360.         for (String permission : permissions) {
  361.             if (FragmentCompat.shouldShowRequestPermissionRationale(this, permission)) {
  362.                 return true;
  363.             }
  364.         }
  365.         return false;
  366.     }
  367.  
  368.     /**
  369.      * Requests permissions needed for recording video.
  370.      */
  371.     private void requestVideoPermissions() {
  372.         if (shouldShowRequestPermissionRationale(VIDEO_PERMISSIONS)) {
  373.             new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG);
  374.         } else {
  375.             FragmentCompat.requestPermissions(this, VIDEO_PERMISSIONS, REQUEST_VIDEO_PERMISSIONS);
  376.         }
  377.     }
  378.  
  379.     @Override
  380.     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
  381.                                            @NonNull int[] grantResults) {
  382.         Log.d(TAG, "onRequestPermissionsResult");
  383.         if (requestCode == REQUEST_VIDEO_PERMISSIONS) {
  384.             if (grantResults.length == VIDEO_PERMISSIONS.length) {
  385.                 for (int result : grantResults) {
  386.                     if (result != PackageManager.PERMISSION_GRANTED) {
  387.                         ErrorDialog.newInstance(getString(R.string.permission_request))
  388.                                 .show(getChildFragmentManager(), FRAGMENT_DIALOG);
  389.                         break;
  390.                     }
  391.                 }
  392.             } else {
  393.                 ErrorDialog.newInstance(getString(R.string.permission_request))
  394.                         .show(getChildFragmentManager(), FRAGMENT_DIALOG);
  395.             }
  396.         } else {
  397.             super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  398.         }
  399.     }
  400.  
  401.     private boolean hasPermissionsGranted(String[] permissions) {
  402.         for (String permission : permissions) {
  403.             if (ActivityCompat.checkSelfPermission(getActivity(), permission)
  404.                     != PackageManager.PERMISSION_GRANTED) {
  405.                 return false;
  406.             }
  407.         }
  408.         return true;
  409.     }
  410.  
  411.     /**
  412.      * Tries to open a {@link CameraDevice}. The result is listened by `mStateCallback`.
  413.      */
  414.     private void openCamera(int width, int height) {
  415.         if (!hasPermissionsGranted(VIDEO_PERMISSIONS)) {
  416.             requestVideoPermissions();
  417.             return;
  418.         }
  419.         final Activity activity = getActivity();
  420.         if (null == activity || activity.isFinishing()) {
  421.             return;
  422.         }
  423.         CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
  424.         try {
  425.             Log.d(TAG, "tryAcquire");
  426.             if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
  427.                 throw new RuntimeException("Time out waiting to lock camera opening.");
  428.             }
  429.             String cameraId = manager.getCameraIdList()[0];
  430.  
  431.             // Choose the sizes for camera preview and video recording
  432.             CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
  433.             StreamConfigurationMap map = characteristics
  434.                     .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
  435.  
  436.             mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
  437.             mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
  438.             mPreviewSize = new Size(1280, 720);//chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height, mVideoSize);
  439.  
  440.             int orientation = getResources().getConfiguration().orientation;
  441.             if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
  442.                 mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
  443.             } else {
  444.                 mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
  445.             }
  446.             configureTransform(width, height);
  447.             mMediaRecorder = new MediaRecorder();
  448.             manager.openCamera(cameraId, mStateCallback, null);
  449.         } catch (CameraAccessException e) {
  450.             Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
  451.             activity.finish();
  452.         } catch (NullPointerException e) {
  453.             // Currently an NPE is thrown when the Camera2API is used but not supported on the
  454.             // device this code runs.
  455.             ErrorDialog.newInstance(getString(R.string.camera_error))
  456.                     .show(getChildFragmentManager(), FRAGMENT_DIALOG);
  457.         } catch (InterruptedException e) {
  458.             throw new RuntimeException("Interrupted while trying to lock camera opening.");
  459.         }
  460.     }
  461.  
  462.     private void closeCamera() {
  463.         try {
  464.             mCameraOpenCloseLock.acquire();
  465.             closePreviewSession();
  466.             if (null != mCameraDevice) {
  467.                 mCameraDevice.close();
  468.                 mCameraDevice = null;
  469.             }
  470.             if (null != mMediaRecorder) {
  471.                 mMediaRecorder.release();
  472.                 mMediaRecorder = null;
  473.             }
  474.         } catch (InterruptedException e) {
  475.             throw new RuntimeException("Interrupted while trying to lock camera closing.");
  476.         } finally {
  477.             mCameraOpenCloseLock.release();
  478.         }
  479.     }
  480.  
  481.     /**
  482.      * Start the camera preview.
  483.      */
  484.     private void startPreview() {
  485.         if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
  486.             return;
  487.         }
  488.         try {
  489.             closePreviewSession();
  490.             SurfaceTexture texture = mTextureView.getSurfaceTexture();
  491.             assert texture != null;
  492.             texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
  493.             mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  494.  
  495.             Surface previewSurface = new Surface(texture);
  496.             mPreviewBuilder.addTarget(previewSurface);
  497.  
  498.             mCameraDevice.createConstrainedHighSpeedCaptureSession(Arrays.asList(previewSurface), new CameraCaptureSession.StateCallback() {
  499.  
  500.                 @Override
  501.                 public void onConfigured(CameraCaptureSession cameraCaptureSession) {
  502.                     mPreviewSession = (CameraConstrainedHighSpeedCaptureSession) cameraCaptureSession;
  503.                     updatePreview();
  504.                 }
  505.  
  506.                 @Override
  507.                 public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
  508.                     Activity activity = getActivity();
  509.                     if (null != activity) {
  510.                         Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
  511.                     }
  512.                 }
  513.             }, mBackgroundHandler);
  514.         } catch (CameraAccessException e) {
  515.             e.printStackTrace();
  516.         }
  517.     }
  518.  
  519.     /**
  520.      * Update the camera preview. {@link #startPreview()} needs to be called in advance.
  521.      */
  522.     private void updatePreview() {
  523.         if (null == mCameraDevice) {
  524.             return;
  525.         }
  526.         try {
  527.             setUpCaptureRequestBuilder(mPreviewBuilder);
  528.             HandlerThread thread = new HandlerThread("CameraPreview");
  529.             thread.start();
  530.             List<CaptureRequest> capList = mPreviewSession.createHighSpeedRequestList(mPreviewBuilder.build());
  531.             //final long tic = System.currentTimeMillis();
  532.             mPreviewSession.setRepeatingBurst(capList, new CameraCaptureSession.CaptureCallback() {
  533.                 @Override
  534.                 public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
  535.                     super.onCaptureCompleted(session, request, result);
  536.                     //long toc = System. currentTimeMillis();
  537.                     //float fps = (toc-tic)/result.getFrameNumber();
  538.                     Log.i("Completed", "fps:" + result.getFrameNumber());
  539.                 }
  540.             }, mBackgroundHandler);
  541.  
  542.         } catch (CameraAccessException e) {
  543.             e.printStackTrace();
  544.         }
  545.     }
  546.  
  547.     private void setUpCaptureRequestBuilder(CaptureRequest.Builder builder) {
  548.         builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_OFF_KEEP_STATE);
  549.         builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<Integer>(120, 120));
  550.     }
  551.  
  552.     /**
  553.      * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
  554.      * This method should not to be called until the camera preview size is determined in
  555.      * openCamera, or until the size of `mTextureView` is fixed.
  556.      *
  557.      * @param viewWidth  The width of `mTextureView`
  558.      * @param viewHeight The height of `mTextureView`
  559.      */
  560.     private void configureTransform(int viewWidth, int viewHeight) {
  561.         Activity activity = getActivity();
  562.         if (null == mTextureView || null == mPreviewSize || null == activity) {
  563.             return;
  564.         }
  565.         int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
  566.         Matrix matrix = new Matrix();
  567.         RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
  568.         RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
  569.         float centerX = viewRect.centerX();
  570.         float centerY = viewRect.centerY();
  571.         if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
  572.             bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
  573.             matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
  574.             float scale = Math.max(
  575.                     (float) viewHeight / mPreviewSize.getHeight(),
  576.                     (float) viewWidth / mPreviewSize.getWidth());
  577.             matrix.postScale(scale, scale, centerX, centerY);
  578.             matrix.postRotate(90 * (rotation - 2), centerX, centerY);
  579.         }
  580.         mTextureView.setTransform(matrix);
  581.     }
  582.  
  583.     private void setUpMediaRecorder() throws IOException {
  584.         final Activity activity = getActivity();
  585.         if (null == activity) {
  586.             return;
  587.         }
  588.         mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
  589.         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
  590.         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
  591.         if (mNextVideoAbsolutePath == null || mNextVideoAbsolutePath.isEmpty()) {
  592.             mNextVideoAbsolutePath = getVideoFilePath(getActivity());
  593.         }
  594.         mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
  595.         mMediaRecorder.setVideoEncodingBitRate(10000000);
  596.         mMediaRecorder.setVideoFrameRate(30);
  597.         mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
  598.         mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
  599.         mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
  600.         int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
  601.         switch (mSensorOrientation) {
  602.             case SENSOR_ORIENTATION_DEFAULT_DEGREES:
  603.                 mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
  604.                 break;
  605.             case SENSOR_ORIENTATION_INVERSE_DEGREES:
  606.                 mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
  607.                 break;
  608.         }
  609.         mMediaRecorder.prepare();
  610.     }
  611.  
  612.     private String getVideoFilePath(Context context) {
  613.         return context.getExternalFilesDir(null).getAbsolutePath() + "/"
  614.                 + System.currentTimeMillis() + ".mp4";
  615.     }
  616.  
  617. //    private void startRecordingVideo() {
  618. //        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
  619. //            return;
  620. //        }
  621. //        try {
  622. //            closePreviewSession();
  623. //            setUpMediaRecorder();
  624. //            SurfaceTexture texture = mTextureView.getSurfaceTexture();
  625. //            assert texture != null;
  626. //            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
  627. //            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
  628. //            List<Surface> surfaces = new ArrayList<>();
  629. //
  630. //            // Set up Surface for the camera preview
  631. //            Surface previewSurface = new Surface(texture);
  632. //            surfaces.add(previewSurface);
  633. //            mPreviewBuilder.addTarget(previewSurface);
  634. //
  635. //            // Set up Surface for the MediaRecorder
  636. //            mRecorderSurface = mMediaRecorder.getSurface();
  637. //            surfaces.add(mRecorderSurface);
  638. //            mPreviewBuilder.addTarget(mRecorderSurface);
  639. //
  640. //            // Start a capture session
  641. //            // Once the session starts, we can update the UI and start recording
  642. //            mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
  643. //
  644. //                @Override
  645. //                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
  646. //                    mPreviewSession = cameraCaptureSession;
  647. //                    updatePreview();
  648. //                    getActivity().runOnUiThread(new Runnable() {
  649. //                        @Override
  650. //                        public void run() {
  651. //                            // UI
  652. //                            mButtonVideo.setText(R.string.stop);
  653. //                            mIsRecordingVideo = true;
  654. //
  655. //                            // Start recording
  656. //                            mMediaRecorder.start();
  657. //                        }
  658. //                    });
  659. //                }
  660. //
  661. //                @Override
  662. //                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
  663. //                    Activity activity = getActivity();
  664. //                    if (null != activity) {
  665. //                        Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
  666. //                    }
  667. //                }
  668. //            }, mBackgroundHandler);
  669. //        } catch (CameraAccessException e) {
  670. //            e.printStackTrace();
  671. //        } catch (IOException e) {
  672. //            e.printStackTrace();
  673. //        }
  674. //
  675. //    }
  676.  
  677.     private void closePreviewSession() {
  678.         if (mPreviewSession != null) {
  679.             mPreviewSession.close();
  680.             mPreviewSession = null;
  681.         }
  682.     }
  683.  
  684.     private void stopRecordingVideo() {
  685.         // UI
  686.         mIsRecordingVideo = false;
  687.         mButtonVideo.setText(R.string.record);
  688.         // Stop recording
  689.         mMediaRecorder.stop();
  690.         mMediaRecorder.reset();
  691.  
  692.         Activity activity = getActivity();
  693.         if (null != activity) {
  694.             Toast.makeText(activity, "Video saved: " + mNextVideoAbsolutePath,
  695.                     Toast.LENGTH_SHORT).show();
  696.             Log.d(TAG, "Video saved: " + mNextVideoAbsolutePath);
  697.         }
  698.         mNextVideoAbsolutePath = null;
  699.         startPreview();
  700.     }
  701.  
  702.     /**
  703.      * Compares two {@code Size}s based on their areas.
  704.      */
  705.     static class CompareSizesByArea implements Comparator<Size> {
  706.  
  707.         @Override
  708.         public int compare(Size lhs, Size rhs) {
  709.             // We cast here to ensure the multiplications won't overflow
  710.             return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
  711.                     (long) rhs.getWidth() * rhs.getHeight());
  712.         }
  713.  
  714.     }
  715.  
  716.     public static class ErrorDialog extends DialogFragment {
  717.  
  718.         private static final String ARG_MESSAGE = "message";
  719.  
  720.         public static ErrorDialog newInstance(String message) {
  721.             ErrorDialog dialog = new ErrorDialog();
  722.             Bundle args = new Bundle();
  723.             args.putString(ARG_MESSAGE, message);
  724.             dialog.setArguments(args);
  725.             return dialog;
  726.         }
  727.  
  728.         @Override
  729.         public Dialog onCreateDialog(Bundle savedInstanceState) {
  730.             final Activity activity = getActivity();
  731.             return new AlertDialog.Builder(activity)
  732.                     .setMessage(getArguments().getString(ARG_MESSAGE))
  733.                     .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  734.                         @Override
  735.                         public void onClick(DialogInterface dialogInterface, int i) {
  736.                             activity.finish();
  737.                         }
  738.                     })
  739.                     .create();
  740.         }
  741.  
  742.     }
  743.  
  744.     public static class ConfirmationDialog extends DialogFragment {
  745.  
  746.         @Override
  747.         public Dialog onCreateDialog(Bundle savedInstanceState) {
  748.             final Fragment parent = getParentFragment();
  749.             return new AlertDialog.Builder(getActivity())
  750.                     .setMessage(R.string.permission_request)
  751.                     .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  752.                         @Override
  753.                         public void onClick(DialogInterface dialog, int which) {
  754.                             FragmentCompat.requestPermissions(parent, VIDEO_PERMISSIONS,
  755.                                     REQUEST_VIDEO_PERMISSIONS);
  756.                         }
  757.                     })
  758.                     .setNegativeButton(android.R.string.cancel,
  759.                             new DialogInterface.OnClickListener() {
  760.                                 @Override
  761.                                 public void onClick(DialogInterface dialog, int which) {
  762.                                     parent.getActivity().finish();
  763.                                 }
  764.                             })
  765.                     .create();
  766.         }
  767.  
  768.     }
  769.  
  770. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×