我正在使用Android开发(SDK 2.2),我希望使用mediaRecorder
进行视频录制,同时在每个预览框架上执行一些处理。
我在项目中使用MediaRecorder
录制视频,在另一个中使用onPreviewFrame(byte[] data
,Camera camera
)(来自PreviewCallback
)处理预览图片。
我尝试创建一个相机,并将其与mediaRecorder
(setCamera
函数)一起使用,但它不起作用。
有可能同时做两件事吗?
其实我不明白如何联系两件事?
我的代码:
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"/>
答案 0 :(得分:6)
尤里卡!诀窍是将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));
}
});
}
答案 1 :(得分:4)
录制时无法访问视频流,一旦开始录制,onPreviewFrame将无法调用。奇怪的是,onPreviewFrame似乎在你录制后不会被调用...
答案 2 :(得分:0)
您只需将标记添加到清单文件中即可。它将起作用。示例代码如下所示。
例如: -
</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>
答案 3 :(得分:0)
如果您使用的是OS 2.2或更高版本,则使用此方法您的准备失败,其他异常将被删除
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;
}
}