关于SurfaceView和MediaRecorder实现录像功能

来源:互联网 发布:腾讯足球数据统计 编辑:程序博客网 时间:2024/05/29 19:15

近期的需求写一个录像功能

我使用的是surfaceview和mediarecorder,但是录像出来特别模糊,所以加了camera来进行自动聚焦来录像,而且发现由于是横屏所以也得设置camera的orientation来旋转角度。

以下是设置camera的代码,因为模式是横屏 所以加了

mCamera.setDisplayOrientation(90);

来使其旋转为竖屏。

private void initCamera() throws IOException {    if (mCamera != null) {        freeCameraResource();    }    try {        mCamera = Camera.open();    } catch (Exception e) {        e.printStackTrace();    }    setCameraParams();    mCamera.setDisplayOrientation(90);    mCamera.setPreviewDisplay(mSurfaceHolder);    mCamera.startPreview();    if (isFocus) {        mCamera.autoFocus(null);    }    mCamera.unlock();}

这里是配置CameraParam的代码,用来设置自动对焦功能
public void setCameraParams() {    if (mCamera != null) {        Camera.Parameters params = mCamera.getParameters();        List<String> list = params.getSupportedFocusModes();        if (list.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {            isFocus = true;            params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);        }        params.set("orientation", "portrait");        mCamera.setParameters(params);    }}

然后录像出来特别模糊,查阅了相关资料发现设置好VideoSize和VideoEncodingBitRate之后会清楚很多。
mMediaRecorder.setVideoSize(640, 480);mMediaRecorder.setVideoEncodingBitRate(5*1024*1024);

然后录像录制出来是横屏,使用MediaRecorder.setOrientationHint(90);来让录制出来的也是竖屏。
以下是demo代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener{    private Button mRecord, mStop, mPress;    private SurfaceView mSurfaceView;    private SurfaceHolder mSurfaceHolder;    private Camera mCamera;    private MediaRecorder mMediaRecorder;    private boolean isCard, isFocus, isRecord;    private String sdCard, recordPath, recordFormat = ".mp4";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        getWindow().setFormat(PixelFormat.TRANSLUCENT);        setContentView(R.layout.activity_main);        init();        setListener();    }    private void init() {        mRecord = (Button) findViewById(R.id.record);        mStop = (Button) findViewById(R.id.stop);        mPress = (Button) findViewById(R.id.press);        mSurfaceView = (SurfaceView) findViewById(R.id.video_surface);        mSurfaceHolder = mSurfaceView.getHolder();        mSurfaceHolder.setType(mSurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        mSurfaceHolder.addCallback(new CustomCallBack());        mStop.setEnabled(false);        isCard = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);        isFocus = false;        isRecord = false;        if (isCard) {            sdCard = Environment.getExternalStorageDirectory().getAbsolutePath();        }    }    private void setListener() {        mRecord.setOnClickListener(this);        mStop.setOnClickListener(this);        mPress.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View view, MotionEvent motionEvent) {                switch (motionEvent.getAction()){                    case MotionEvent.ACTION_DOWN: {                        record();                        break;                    }                    case MotionEvent.ACTION_UP: {                        stop();                        break;                    }                    default:                        break;                }                return false;            }        });    }    @Override    public void onClick(View v) {        if (!isCard) {            toast("SDCard is Invalid");            return;        }        switch (v.getId()) {            case record:                record();                break;            case stop:                stop();                break;        }    }    private void record() {        isRecord = true;        try {            initCamera();            initRecord();        } catch (IOException e) {            e.printStackTrace();        }        referenceView();    }    private void stop() {        isRecord = false;        freeRecordResource();        freeCameraResource();        referenceView();    }    private void referenceView() {        if (isRecord) {            mRecord.setEnabled(false);            mStop.setEnabled(true);        } else {            mRecord.setEnabled(true);            mStop.setEnabled(false);            recordPath = null;        }    }    private void initCamera() throws IOException {        if (mCamera != null) {            freeCameraResource();        }        try {            mCamera = Camera.open();        } catch (Exception e) {            e.printStackTrace();        }        setCameraParams();        mCamera.setDisplayOrientation(90);        mCamera.setPreviewDisplay(mSurfaceHolder);        mCamera.startPreview();        if (isFocus) {            mCamera.autoFocus(null);        }        mCamera.unlock();    }    private void initRecord() throws IOException {        if (mMediaRecorder != null) {            freeRecordResource();        }        File file = createFile();        mMediaRecorder = new MediaRecorder();        mMediaRecorder.setCamera(mCamera);        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);        mMediaRecorder.setVideoSize(640, 480);        mMediaRecorder.setVideoEncodingBitRate(5*1024*1024);        mMediaRecorder.setOrientationHint(90);        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);        mMediaRecorder.setOutputFile(file.getAbsolutePath());        mMediaRecorder.prepare();        mMediaRecorder.start();    }    private File createFile() throws IOException {        if (recordPath == null) {            recordPath = sdCard + File.separator + System.currentTimeMillis() + recordFormat;        }        File file = new File(recordPath);        if (!file.exists()) {            File parent = file.getParentFile();            if (!parent.exists()) {                parent.mkdirs();            }            file.createNewFile();        }        return file;    }    private void freeCameraResource() {        if (mCamera != null) {            mCamera.setPreviewCallback(null);            mCamera.stopPreview();            mCamera.lock();            mCamera.release();            mCamera = null;        }    }    private void freeRecordResource() {        if (mMediaRecorder != null) {            mMediaRecorder.stop();            mMediaRecorder.reset();            mMediaRecorder.release();            mMediaRecorder = null;        }    }    public void setCameraParams() {        if (mCamera != null) {            Camera.Parameters params = mCamera.getParameters();            List<String> list = params.getSupportedFocusModes();            if (list.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {                isFocus = true;                params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);            }            params.set("orientation", "portrait");            mCamera.setParameters(params);        }    }    @Override    protected void onStop() {        stop();        super.onStop();    }    @Override    protected void onDestroy() {        stop();        super.onDestroy();    }    private void toast(String text) {        Toast.makeText(this, text, Toast.LENGTH_LONG).show();    }    public class CustomCallBack implements SurfaceHolder.Callback {        @Override        public void surfaceCreated(SurfaceHolder holder) {            if (mCamera == null) {                try {                    mCamera = Camera.open();                    mCamera.setDisplayOrientation(90);                    mCamera.setPreviewDisplay(holder);                    //                    camera.startPreview();                } catch (IOException e) {                    freeCameraResource();                    e.printStackTrace();                }            }        }        @Override        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {            if (mCamera != null) {                setCameraParams();                mCamera.startPreview();                if (isFocus) {                    mCamera.autoFocus(null);                }                mCamera.unlock();            }        }        @Override        public void surfaceDestroyed(SurfaceHolder holder) {            if (mCamera != null) {                freeCameraResource();            }        }    }}


xml的配置
<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <SurfaceView        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:id="@+id/video_surface"/>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">        <Button            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="record"            android:id="@+id/record"/>        <Button            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="stop"            android:id="@+id/stop"/>        <Button            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="press"            android:id="@+id/press"/>    </LinearLayout></LinearLayout>


AndroidMainfest的配置
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"          package="com.headline.myapplication">    <uses-permission android:name="android.permission.CAMERA" />    <uses-permission android:name="android.permission.RECORD_AUDIO" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-feature android:name="android.hardware.camera" />    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>            </intent-filter>        </activity>    </application></manifest>

运行即可实现简单的视频录制