如果调用太快,MediaRecorder start()会失败

时间:2013-06-10 13:59:08

标签: java android file-descriptor mediarecorder

我正在尝试构建一个基本的摄像机,允许用户通过触摸屏幕快速拍摄视频,这看起来很简单然而我遇到的主要问题是Android MediaRecorder不允许快速启动和重启崩溃,如果用户拍摄然后停止然后快速恢复再次拍摄它总是崩溃我不确定是否有办法直接解决这个问题所以我还设计了另一种方法来尝试录制单个视频但试图获得一些控制mediaRecorder实际写入文件的时间。但是我无法使用FileDescriptor完全运行,下面我将粘贴我的原始代码和我在第二次尝试控制写入时使用的方法,是否有任何方法可以调整任何代码以实现暂停后的功能?任何帮助都会有很长的路要走,谢谢

我的第一次尝试使用将文件设置为setOutPutFile()的常用方法:

public class MainActivity extends Activity implements SurfaceHolder.Callback {

public static final String LOGTAG = "VIDEOCAPTURE";

private MediaRecorder recorder;
private SurfaceHolder holder;
private CamcorderProfile camcorderProfile;
private Camera camera;

boolean recording = false;
boolean usecamera = true;
boolean previewRunning = false;

double timer = 0;
ProgressBar pb;
boolean neverEnd;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);

    setContentView(R.layout.activity_main);

    pb = (ProgressBar) findViewById(R.id.progressBar1);
    pb.setProgress(0);

    SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView);
    holder = cameraView.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    cameraView.setClickable(true);
    cameraView.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {

                recording = true;
                new recordVideo().execute();
                Log.v(LOGTAG, "Recording Started");

                return true;
            } else if (event.getAction() == MotionEvent.ACTION_UP) {

                recording = false;

                return true;
            }
            return false;
        }
    });
}

private void prepareRecorder() {
    recorder = new MediaRecorder();
    recorder.setPreviewDisplay(holder.getSurface());

    if (usecamera) {
        camera.unlock();
        recorder.setCamera(camera);
    }

    recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

    recorder.setProfile(camcorderProfile);


    Calendar calendarTime = Calendar.getInstance();

//initial attempt using a file path with setoutputfile 

    File file = new File(Environment.getExternalStorageDirectory(),
            String.valueOf(calendarTime.getTimeInMillis()) + ".mp4");

    if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.THREE_GPP) {

        recorder.setOutputFile(file.getAbsolutePath());
    } else if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.MPEG_4) {

        recorder.setOutputFile(file.getAbsolutePath());
    } else {

        recorder.setOutputFile(file.getAbsolutePath());

    }
    // recorder.setMaxDuration(50000); // 50 seconds
    // recorder.setMaxFileSize(5000000); // Approximately 5 megabytes

    boolean initialized = false;

    while (!initialized) {
        try {
            recorder.prepare();
            initialized = true;
        } catch (IllegalStateException e) {
            e.printStackTrace();
            // finish();
            initialized = false;
        } catch (IOException e) {
            e.printStackTrace();
            // finish();
            initialized = false;
        }
    }

}

public void surfaceCreated(SurfaceHolder holder) {
    Log.v(LOGTAG, "surfaceCreated");

    if (usecamera) {
        camera = Camera.open();

        try {
            camera.setPreviewDisplay(holder);
            camera.startPreview();
            previewRunning = true;
        } catch (IOException e) {
            Log.e(LOGTAG, e.getMessage());
            e.printStackTrace();
        }
    }

}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    Log.v(LOGTAG, "surfaceChanged");

    if (!recording && usecamera) {
        if (previewRunning) {
            camera.stopPreview();
        }

        try {
            Camera.Parameters p = camera.getParameters();

            p.setPreviewSize(camcorderProfile.videoFrameWidth,
                    camcorderProfile.videoFrameHeight);
            p.setPreviewFrameRate(camcorderProfile.videoFrameRate);

            camera.setParameters(p);

            camera.setPreviewDisplay(holder);
            camera.startPreview();
            previewRunning = true;
        } catch (IOException e) {
            Log.e(LOGTAG, e.getMessage());
            e.printStackTrace();
        }

        prepareRecorder();
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    Log.v(LOGTAG, "surfaceDestroyed");
    if (recording) {
        recorder.stop();
        recording = false;
    }
    recorder.release();
    if (usecamera) {
        previewRunning = false;
        // camera.lock();
        camera.release();
    }
    finish();
}

private class recordVideo extends AsyncTask<Void, Integer, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub

        try {

            recorder.start();
            while (recording) {

                Thread.sleep(100);

                publishProgress();
            }
            recorder.stop();
            recorder.release();
            recorder = null;

            // recorder.release();

            Log.v(LOGTAG, "Recording Stopped");
            // Let's prepareRecorder so we can record again
            prepareRecorder();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);

        if (recording) {
            timer += 0.1;
            pb.setProgress((int) (timer * 10));
        }

    }

}
}

这是我使用FileDescriptor的方法,这不起作用,只创建了一个文件,但没有写入它:

//Pass it into setOutputFile() like this
recorder.setOutputFile(getStreamFd());

    private FileDescriptor getStreamFd() {
    ParcelFileDescriptor pipe = null;
    try {

        Calendar calendarTime = Calendar.getInstance();

        File file = new File(Environment.getExternalStorageDirectory(),
                String.valueOf(calendarTime.getTimeInMillis()) + ".mp4");

        pipe = ParcelFileDescriptor.open(file,
                ParcelFileDescriptor.MODE_CREATE
                        | ParcelFileDescriptor.MODE_APPEND
                        | ParcelFileDescriptor.MODE_WORLD_WRITEABLE);

        byte[] buf = new byte[1024];
        int len;

        FileOutputStream out = new FileOutputStream(FileDescriptor.out);

        InputStream is = new FileInputStream(FileDescriptor.in);

        while (usecamera) {
                      if(recordng){
                        out.write(buf, 0, len);
                      }

        }

        is.close();
        out.close();

    } catch (IOException e) {
        Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
    }

    return pipe.getFileDescriptor();
}

1 个答案:

答案 0 :(得分:0)

在prepareRecorder()之后调用cameraView.setClickable(true)并在AsynkTask上调用prepareRecorder()之前调用cameraView.setClickable(false)