我正在尝试构建一个基本的摄像机,允许用户通过触摸屏幕快速拍摄视频,这似乎很简单,但是我遇到的主要问题是 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();
}