我的应用程序目前有预览屏幕,我希望它每秒捕获许多帧 用于处理。目前,我的预览只是每秒存储一个图像,但是我需要更大的fps捕获率。任何帮助将不胜感激。
另一个问题(如果可以的话)是我的图像在我的SD卡上显示时会旋转90度。到目前为止,还没有互联网解决方案帮助我解决这些问题:(
谢谢:)
public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
public MyCameraSurfaceView(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int weight,
int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
mCamera.setDisplayOrientation(90);
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// make any resize, rotate or reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> size = parameters.getSupportedPreviewSizes();
parameters.setPreviewSize(size.get(0).width, size.get(0).height);
mCamera.setParameters(parameters);
mCamera.startPreview();
} catch (Exception e){}
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
int format = parameters.getPreviewFormat();
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w, h);
ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 10, output_stream);
byte[] byt = output_stream.toByteArray();
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format(
"/sdcard/bb%d.jpg", System.currentTimeMillis() / 1000));
outStream.write(byt);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
});
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
答案 0 :(得分:0)
首先,请注意Camera.Parameters允许您使用setPreviewFrameRate
设置帧速率。该值必须在getPreviewFpsRange
描述的范围内。
其次,处理byte[]
中的预览帧会严重限制帧速率,因为必须复制的数据量很大。如果您想将未修改的全帧YUV数据写入磁盘,那么您目前无法选择。如果您可以处理压缩工件,并且您拥有Android 4.3或更高版本,则可以将数据保存为MPEG视频并稍后再读取帧。有关代码示例,请参阅this page上的CameraToMpegTest.java示例。
将图像旋转90度或180度可以直接进行编码。如果您不想自己编写,Bitmap
类可以执行此操作。
答案 1 :(得分:0)
setPreviewCallback()
是一种简单但效率较低的请求预览框架的方法。主要问题是框架可能非常繁忙地分配byte[]
块来填充,垃圾收集器可能需要付出沉重的代价。首选方法是使用setPreviewCallbackWithBuffer()
,但即使这样也无法保证所需的帧速率,如 How to get raw preview data from Camera object at least 15 frames per second in Android?