Androidvideo录制时的预览处理

我正在使用Android开发(SDK 2.2),我想使用mediaRecorder进行video录制,同时在每个预览帧上执行一些操作。

我在一个项目中使用MediaRecorder录制video,另一个使用onPreviewFrame(byte[] dataCamera camera )(来自PreviewCallback )处理预览图片。

我试图创build一个相机,并与mediaRecordersetCamera函数)使用它,但它不起作用。

是否有可能在同一时间?

其实我不明白如何连结两件事?

我的代码:

 package ch.fraise; import java.io.IOException; import android.app.Activity; import android.hardware.Camera; import android.hardware.Camera.PreviewCallback; import android.media.MediaRecorder; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.SurfaceHolder; import android.view.SurfaceView; public class CameraActivity extends Activity implements SurfaceHolder.Callback, Camera.AutoFocusCallback { private SurfaceView preview; private SurfaceHolder previewHolder; private MediaRecorder mRecorder; private Camera mCamera; private boolean mPreviewRunning = false; private boolean mCaptureFrame = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e("", "Begin onCreate"); setContentView(R.layout.main); preview = (SurfaceView) findViewById(R.id.surfaceView1); previewHolder = preview.getHolder(); previewHolder.addCallback(this); previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mRecorder = new MediaRecorder(); } @Override public void onResume() { super.onResume(); } @Override public void onPause() { super.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.capture_menu, menu); return true; } public void startRecording() { Log.e("", "Begin StartRecording"); mCaptureFrame = true; mRecorder.start(); } public void stopRecording() { Log.e("", "Begin StopChange"); mRecorder.stop(); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.startRecording: startRecording(); return true; case R.id.stopRecording: stopRecording(); return true; default: return super.onOptionsItemSelected(item); } } @Override public void surfaceCreated(SurfaceHolder holder) { Log.e("", "Begin surfaceDestroy"); mCamera = Camera.open(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview(); mPreviewRunning = false; mCamera.release(); mRecorder.reset(); mRecorder.release(); } @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub } /* * PreviewCallback() * * this callback captures the preview at every frame and puts it in a byte * buffer. we will evaluate if this is a frame that we want to process, and * if so, we will send it to an asynchronous thread that will process it to * an ARGB Bitmap and POST it to the server */ PreviewCallback previewCallback = new PreviewCallback() { public void onPreviewFrame(byte[] data, Camera camera) { Log.e("", "onPreviewFrame pass"); if (mCaptureFrame) { mCaptureFrame = false; // new FrameHandler().execute(data); } } }; @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.e("", "Begin SurfaceChange"); mRecorder.reset(); mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); mRecorder.setOutputFile("/sdcard/videotest2.mp4"); mRecorder.setVideoFrameRate(30); mRecorder.setPreviewDisplay(previewHolder.getSurface()); try { mRecorder.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } if (mPreviewRunning) mCamera.stopPreview(); Camera.Parameters p = mCamera.getParameters(); // p.setPreviewSize(width, height); mCamera.setParameters(p); try { mCamera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } mCamera.setPreviewCallback(previewCallback); mCamera.startPreview(); mPreviewRunning = true; } } 

和XML文件中的权限:

 <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_VIDEO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Solutions Collecting From Web of "Androidvideo录制时的预览处理"

find了! 诀窍是将您的PreviewCallback附加到surfaceChanged(...) SurfaceHolder.Callback ! 完成此操作后,在MediaRecorder运行后,您将继续获取预览帧数据!

例如:

 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { mCamera.setPreviewCallback(new PreviewCallback() { public void onPreviewFrame(byte[] _data, Camera _camera) { Log.d("onPreviewFrame-surfaceChanged",String.format("Got %d bytes of camera data", _data.length)); } }); } 

录制时无法访问videostream,一旦开始录制,onPreviewFrame将不会被调用。 奇怪的是,在logging之后,onPreviewFrame似乎不会被调用…

您只需将标签添加到您的清单文件。这样它将工作。示例代码如下所示。

例如:-

  </application> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_VIDEO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ***<uses-feature android:name="android.hardware.camera" />*** </manifest> 

如果您使用os 2.2或更高版本,则使用此准备失败的方法,并删除其他exception

  public boolean startRecording() { try { camera.unlock(); mediaRecorder = new MediaRecorder(); mediaRecorder.setCamera(camera); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setProfile(CamcorderProfile .get(CamcorderProfile.QUALITY_HIGH)); File tempFile = new File(getOutputMediaFile(MEDIA_TYPE_VIDEO) .toString()); mediaRecorder.setOutputFile(tempFile.getPath()); mediaRecorder.setVideoFrameRate(videoFramesPerSecond); mediaRecorder.setVideoSize(surfaceView.getWidth(), surfaceView.getHeight()); mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); mediaRecorder.setMaxFileSize(maxFileSizeInBytes); mediaRecorder.prepare(); mediaRecorder.start(); return true; } catch (IllegalStateException e) { Log.e(TAG, e.getMessage()); e.printStackTrace(); return false; } catch (IOException e) { Log.e(TAG, e.getMessage()); e.printStackTrace(); return false; } }