Android前置摄像头视频预览和录制的比例不同

时间:2014-11-12 16:03:19

标签: android android-camera

我正在尝试在视频录制之前进行预览,然后开始录制视频。

BACK相机录制时:预览正常并且录制开始时比率无变化前置摄像头录制时:预览正常但录制开始时比率已更改(根据经验我可以说录制高度较小)

前置摄像头保存的视频格式也不正确。

我检索支持的录制尺寸以进行预览和录制。所选的配置文件具有相同的分辨率: 720x480

我使用自定义 SurfaceView (SimpleCameraPreview)作为视图添加到FrameLayout:

<FrameLayout
            android:id="@+id/camera_preview"
            android:layout_width="240dp"
            android:layout_height="160dp"
            android:layout_weight="1" />

720/3 = 240,480 / 3 = 160 目标版本Android 4.0 +

完整代码:

activity_recording_simple.xml

  

<FrameLayout
    android:id="@+id/camera_preview"
    android:layout_width="240dp"
    android:layout_height="160dp"
    android:background="#CC000000"
    android:layout_weight="1" />

<LinearLayout
    android:id="@+id/linearLayout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/camera_preview"
    android:layout_alignParentTop="true"
    android:layout_toRightOf="@id/camera_preview"
    android:gravity="center"
    android:layout_marginLeft="@dimen/activity_horizontal_margin"
    android:layout_marginRight="@dimen/activity_horizontal_margin"
    android:orientation="vertical">
    <Button
        android:id="@+id/start_recording_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:text="Start" />

    <Button
        android:id="@+id/stop_recording_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:text="Stop"
        android:visibility="gone" />
</LinearLayout> </RelativeLayout>

SimpleRecordingActivity.java

import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;

import cz.dynabit.voxpopuli.R;
import cz.dynabit.voxpopuli.SimpleCameraPreview;

public class SimpleRecordingActivity extends BaseAddRecipientActivity {
    private SimpleCameraPreview mPreview;
    private int currentCameraId;
    private boolean isRecording;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_recording_simple);
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        super.onCreate(savedInstanceState);
        final Button startButton = (Button) findViewById(R.id.start_recording_button);
        final Button stopButton = (Button) findViewById(R.id.stop_recording_button);

        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isRecording) {
                    return;
                }
                startButton.setVisibility(View.GONE);
                stopButton.setVisibility(View.VISIBLE);
                isRecording = true;
                mPreview.prepareVideoRecorder();
            }
        });
        stopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            if (isRecording) {
                    mPreview.stopRecording();
                    isRecording = false;
                    Intent i = new Intent(SimpleRecordingActivity.this, ReplayActivity.class);
                    startActivityForResult(i, 1);
                }
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        mPreview = new SimpleCameraPreview(this);
        mPreview.setCamera(getDefaultCamera());
        mPreview.setVisibility(View.VISIBLE);
        final FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.removeAllViews();
        preview.addView(mPreview);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mPreview != null) {
            mPreview.stop();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        MenuInflater mi = getMenuInflater();
        mi.inflate(R.menu.recording, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.camera_switch:
                mPreview.releaseMediaRecorder();
                mPreview.releaseCamera();
                Camera nextCamera = openNextCamera(currentCameraId + 1);
                if (nextCamera != null) {
                    mPreview.setCamera(nextCamera);
                }
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private int getCameraCount() {
        return Camera.getNumberOfCameras();
    }

    private Camera openNextCamera(int cameraId) {
        int cameraCount = getCameraCount();
        if (cameraId >= cameraCount) {
            cameraId = 0;
        }
        if (cameraCount > 0) {
            try {
                Camera cam = Camera.open(cameraId);
                currentCameraId = cameraId;
                return cam;
            } catch (RuntimeException e) {
                Log.e("app", "Camera failed to open: " + e.getLocalizedMessage());
            }
        }

        return null;
    }

    private Camera getDefaultCamera() {
        return openFrontFacingCameraGingerbread();
    }

    private Camera openFrontFacingCameraGingerbread() {
        int cameraCount = getCameraCount();
        Camera cam = null;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                try {
                    cam = Camera.open(camIdx);
                    currentCameraId = camIdx;
                    break;
                } catch (RuntimeException e) {
                    Log.e("app", "Camera failed to open: " + e.getLocalizedMessage());
                }
            }
        }
        if (cam == null && cameraCount > 0) {
            try {
                cam = Camera.open(0);
                currentCameraId = 0;

            } catch (RuntimeException e) {
                Log.e("app", "Camera failed to open: " + e.getLocalizedMessage());
            }
        }
        return cam;
    }
}

SimpleCameraPreview.java

import android.app.Activity;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class SimpleCameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private static String TAG = "app";
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private MediaRecorder mMediaRecorder;
    private String lastFilePath = null;
    private CamcorderProfile camProfile;

    private Camera.Size optimalPreviewSize;
    private Camera.Size optimalVideoSize;

    public SimpleCameraPreview(Activity context) {
        super(context);
        mHolder = getHolder();
        mHolder.addCallback(this);
        camProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
    }

    public void setCamera(Camera camera) {
        mCamera = camera;
        refreshSurface();
    }

    public boolean prepareVideoRecorder() {
        mMediaRecorder = new MediaRecorder();

        // Step 1: Unlock and set camera to MediaRecorder
        if (mCamera == null) {
            return false;
        }
        mCamera.unlock();
        mMediaRecorder.setCamera(mCamera);
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setProfile(camProfile);
        lastFilePath = String.format("/storage/emulated/0/Podcasts/app/VID_%s.mp4", new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()));
        mMediaRecorder.setOutputFile(lastFilePath);
        mMediaRecorder.setPreviewDisplay(mHolder.getSurface());
        mMediaRecorder.setVideoSize(optimalVideoSize.width, optimalVideoSize.height);
        mMediaRecorder.setVideoSize(720, 480);
        try {
            mMediaRecorder.prepare();
            mMediaRecorder.start();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();
            return false;
        } catch (Exception e) {
            releaseMediaRecorder();
            return false;
        }
        return true;
    }
    public void refreshSurface() {
        surfaceCreated(getHolder());
    }
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            if (mCamera == null) {
                return;
            }
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            //Desired ratio is 640/480
            int desiredWidth = 640, desiredHeight = 480;

            List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
            List<Camera.Size> recordingSizes = parameters.getSupportedVideoSizes();
            //Selected profiles are both 720x480!

            //calculates optimal preview and recording sizes
            optimalPreviewSize = getOptimalPreviewSize(previewSizes, desiredWidth, desiredHeight);
            optimalVideoSize = getOptimalPreviewSize(recordingSizes, desiredWidth, desiredHeight);

            parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mCamera.setParameters(parameters);
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }
    //NOT IMPORTANT STUFF!
    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.2;
        double targetRatio = (double) w / h;
        if (sizes == null)
            return null;
        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;
        int targetHeight = h;
        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
        return optimalSize;
    }

    public void releaseMediaRecorder() {
        try {
            if (mMediaRecorder != null) {
                mMediaRecorder.stop();
                mMediaRecorder.reset();   // clear recorder configuration
                mMediaRecorder.release(); // release the recorder object
                mMediaRecorder = null;
                mCamera.lock();           // lock camera for later use
            }
        } catch (Exception ex) {
            Log.e(TAG, "Error during releaseMediaRecorder");
        }
    }

    public void releaseCamera() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.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

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

        } catch (Exception e) {
            Log.d("vox", "Error starting camera preview: " + e.getMessage());
        }
    }
    public void stop() {

        stopRecording();
        releaseCamera();              // release the camera immediately on pause event
    }
    public void stopRecording() {
        releaseMediaRecorder();       // if you are using MediaRecorder, release it first
    }
}

更新

显然这只是某些设备上的问题(例如三星galaxy s4)。有些手机运行正常。

0 个答案:

没有答案