首页 > 解决方案 > 使用媒体记录器android录制视频时无法缩放

问题描述

我想在android中录制视频时实现缩放功能。但是,我无法在主活动和表面类中访问相机参数或相机startSmoothZoom()方法。如果您在媒体记录器方法(prepareMediaRecorder())中访问相机参数,它将引发空指针异常。

此活动类 - 在prepareMediaRecorder() 方法中无法访问相机参数,也无法设置 startSmoothZoom()。这里相机对象给出空指针异常。

      public class CustomCameraPreview extends BaseActivity implements
                                OnClickListener, AlertPositiveListener, OrientationListener, 
                               ActivityCompat.OnRequestPermissionsResultCallback { 

                     RelativeLayout mLayout;
                    MediaRecorder mediaRecorder;
                      private PictureCallback mPictureCallback = new PictureCallback() {

                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    try {
                        cameraData = data;
                        captureAngle = getRotation();
                        mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    }
                    catch (OutOfMemoryError e){
                        System.gc();
                        mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    }
                    // int rotation=getRotation();

                    Matrix matrix = new Matrix();
                    matrix.postRotate(getRotation());
                    /*mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(),
                            mBitmap.getHeight(), matrix, true);*/

                    mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(),
                            mBitmap.getHeight(), matrix, false);
                    if (mBitmap != null) {
                        mButtonRetake.setEnabled(true);
                    } else {
                        Message.displayToast(CustomCameraPreview.this,
                                getString(R.string.picture_not_taken));
                    }
                    mCamera.release();
                    mButtonCapture.setEnabled(false);

                }


            };


              protected void onCreate(){
                  initiCameraForVideo();
               }

              private void initiCameraForVideo() {
          params = mCamera.getParameters();

                    mButtonCapture.setBackgroundResource(R.drawable.videostart);

                    mShowCamera = new CameraSurfaceHolder(CustomCameraPreview.this,
                            mCamera);
                    mLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
                    mLayout.removeAllViews();
                    mLayout.addView(mShowCamera);
                   List<Camera.Size> mSizeList_Video = null;// params.getSupportedPreviewSizes();

                    if (params.getSupportedVideoSizes() != null) {
                        mSizeList_Video = params.getSupportedVideoSizes();
                    } else {
                        // Video sizes may be null, which indicates that all the
                        // supported preview sizes are supported for video
                        // recording.
                        mSizeList_Video = mCamera.getParameters()
                                .getSupportedPreviewSizes();
                    }
              }

        @Override
        public void onClick(View v) {
            int viewId = v.getId();
            switch (viewId) {
                case R.id.button_Capture: 
                 releaseCamera();
                            if (!prepareMediaRecorder()) {
                                Message.displayToast(
                                        CustomCameraPreview.this,
                                        getString(R.string.somethign_went_wrong));
                            } else {
                                mediaRecorder.start();
                                recording = true;
                            }
         }

         private boolean prepareMediaRecorder() \*method to setup media player to record video
         {
        mCamera = isCameraAvailable();

        mediaRecorder = new MediaRecorder();

        mCamera.unlock();
        mediaRecorder.setCamera(mCamera);

        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        if(CamcorderProfile.hasProfile(findCameraID(), CamcorderProfile.QUALITY_480P)) {
            mediaRecorder.setProfile(CamcorderProfile
                    .get(CamcorderProfile.QUALITY_480P));
        }else{
            mediaRecorder.setProfile(CamcorderProfile
                    .get(CamcorderProfile.QUALITY_LOW));
        }

        mediaRecorder.setOutputFile(getOutputVideoFile());
        mediaRecorder.setMaxDuration(60000);
//        mediaRecorder.setMaxFileSize(100 * 1000 * 1000);

        mediaRecorder.setPreviewDisplay(mShowCamera.getHolder().getSurface());

        try {
            mediaRecorder.prepare();
        } 


        }

        @Override
    protected void onPause() {
        super.onPause();
        releaseMediaRecorder();
        releaseCamera();

    }
      private void releaseCamera() {
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }

    }

而这个表面预览类-

 public class CameraSurfaceHolder extends SurfaceView implements
    SurfaceHolder.Callback {

private static final String TAG = "CameraSurfaceHolder";
Context mContext;
private String errorMessage = "";
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;

public CameraSurfaceHolder(Context context, Camera camera) {
    super(context);
    mContext = context;
    mCamera = camera;
    mSurfaceHolder = getHolder();
    mSurfaceHolder.addCallback(this);

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
                           int height) {

    /*if (holder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here
        setCameraDisplayOrientation((Activity)mContext, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();

        } 
          */
}

@Override
public void surfaceCreated(SurfaceHolder holder) {

    try {
        mCamera.setPreviewDisplay(mSurfaceHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        Logger.ex(e);
    }
}

public void setCameraDisplayOrientation(Activity activity, int cameraId,
                                        Camera camera) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    /*Display mDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int rotation = mDisplay.getDisplayId();*/
    int rotation = activity.getWindowManager().getDefaultDisplay()
            .getRotation();
    int degrees = 0;
    switch (rotation) {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;
    }

    int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360; // compensate the mirror
    } else { // back-facing
        result = (info.orientation - degrees + 360) % 360;
    }
    Camera.Parameters mParameters = camera.getParameters();
    mParameters.setRotation(rotation);
    camera.setDisplayOrientation(result);
    camera.setParameters(mParameters);

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}

}

在上面的类中,我添加了一些类似下面的代码,当用户触摸相机预览时,它在 onTouchEvent() 访问相机参数时抛出空指针异常。还尝试像我在配置媒体记录器( prepareMediaRecorder() )后再次将相机对象设置为活动表面,但缩放功能有效但视频未录制

          @Override
public boolean onTouchEvent(MotionEvent event) {
    // Get the pointer ID
    Camera.Parameters params = mCamera.getParameters();
    int action = event.getAction();


    if (event.getPointerCount() > 1) {
        // handle multi-touch events
        if (action == MotionEvent.ACTION_POINTER_DOWN) {
            mDist = getFingerSpacing(event);
        } else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
            mCamera.cancelAutoFocus();
            handleZoom(event, params);
        }
    } else {
        // handle single touch events
        if (action == MotionEvent.ACTION_UP) {
            handleFocus(event, params);
        }
    }
    return true;
}

private void handleZoom(MotionEvent event, Camera.Parameters params) {
    int maxZoom = params.getMaxZoom();
    int zoom = params.getZoom();
    float newDist = getFingerSpacing(event);
    if (newDist > mDist) {
        //zoom in
        if (zoom < maxZoom)
            zoom++;
    } else if (newDist < mDist) {
        //zoom out
        if (zoom > 0)
            zoom--;
    }
    mDist = newDist;
    params.setZoom(zoom);
    mCamera.setParameters(params);
}

public void handleFocus(MotionEvent event, Camera.Parameters params) {
    int pointerId = event.getPointerId(0);
    int pointerIndex = event.findPointerIndex(pointerId);
    // Get the pointer's current position
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);

    List<String> supportedFocusModes = params.getSupportedFocusModes();
    if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
        mCamera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean b, Camera camera) {
                // currently set to auto-focus on single touch
            }
        });
    }
}

/** Determine the space between the first two fingers */
private float getFingerSpacing(MotionEvent event) {
    // ...
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return (float)Math.sqrt(x * x + y * y);
}

标签: javaandroidsurfaceviewmediarecorder

解决方案


推荐阅读