#.Android中Camera1使用主要流程:
开启相机使用的关键步骤:0.获取相应权限1.检查相机可用性2.遍历相机列表,打开指定方向(前置/后置)相机,获取对应实例对象3.设置预览参数4.设置预览画面偏转方向5.设置预览画面输出方式6.开启预览结束相机使用的关键步骤:1.关闭对应相机预览2.释放对应相机资源
##.一些要点
1.摄像头相关回调执行的线程
Camera.open([index])会启动相应的摄像头,并返回其实例对象。该方法在哪个线程调用,意味着摄像头将被哪个线程占用和绑定,后继的回调都会在该线程中调用。
2.可以通过设置帧回调接口,获取相机传回的帧画面,来做自己的处理。
private final int PREVIEW_BUFFER_COUNT = 3;
private byte[][] mPreviewCallbackBuffer;
private void otherApiExplain(){
//方式1:设置回调接口,每当相机有新生成的帧画面,都会自动创建缓冲区,并将画面数据回调
// 但是会频繁的创建缓冲区和GC销毁,会有较高内存消耗,并不推荐该方式
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
//这里面的Bytes的数据就是NV21格式的数据,或者YUV_420_888的数据
}
});
//方式2:设置该接口,只会回调一次,可用于拍照。会自动创建缓冲区,并将画面数据回调
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
//这里面的Bytes的数据就是NV21格式的数据,或者YUV_420_888的数据
}
});
//方式3:设置带缓冲区的回调接口。推荐的方式
// 需要自己addCallbackBuffer()把缓冲区数组传入缓冲区队列,相机画面会存储在这些缓冲区中回调回来;
// 每次回调,都会从队列取出一个缓冲区数组;当缓冲区队列中没有数组时,就不再继续回调。
// 因此,可以在每次回调时,都把返回的数据缓冲区,重新放回缓冲区队列中。
// 这样可以有效复用这些缓冲区,降低内存消耗。
if (mPreviewCallbackBuffer == null) {
// nv21 一个像素点1.5byte
mPreviewCallbackBuffer = new byte[PREVIEW_BUFFER_COUNT][DESIRED_WIDTH * DESIRED_HEIGHT * 3 / 2];
}
// 加入预先生成的指定数量预览缓冲buffer,这里是3个
for (int i = 0; i < PREVIEW_BUFFER_COUNT; i++){
mCamera.addCallbackBuffer(mPreviewCallbackBuffer[i]);
}
mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
//如果这里做费时的操作的话,最好优先把缓冲区放回去,再进行处理
// 以免队列中缓冲区暂时耗尽,不再回调
}
});
}
3.设置预览画面输出的两种方式
//设置预览画面输出方式
// 也可以不设置,而是通过setPreviewCallbackWithBuffer()等方式来获取相机预览画面帧。
//方式1:输出到一个SurfaceView的Surface上,
// 这种方式新的画面帧一旦生成,就会被绘制到SurfaceView的Surface上显示出来
mCamera.setPreviewDisplay(surfaceView.getHolder());
//方式2:输出到SurfaceTexture的缓冲区上,会被转化为一个OpenGl纹理
// SurfaceTexture通过调用updateTexImage()可以用画面流中最新的画面来更新纹理的内容
// 然后开发者可以将这个纹理做自己需要的业务处理。
// 例如用OpenGl进一步处理后显示到GlSurfaceView上,或者编码到直播视频流中。
// 可通过SurfaceTexture的API:getTransformMatrix(矩阵),来获取纹理采样坐标的变换矩阵;
mCamera.setPreviewTexture(SurfaceTexture);
4.关于预览中途手机画面方向旋转后,摄像头预览画面旋转角度变化的处理
4.1 手机预览中途,也可以通过调用 mCamera .setDisplayOrientation(result) 来重新设置预览画面的偏转角度。这一步很简单,只需要重新获取当前画面的旋转角度,然后计算预览画面的应偏转角度并设置就可以了。
4.2 其实有些麻烦的是,动态监听手机画面方向发生了变化。一般容易想到的是下面方法1和方法2两种方法,但都有一定问题。自己想的方法是,添加一个每个1s执行1次的循环,每次都检查方向是够改变,再结合方法2,来监听方向改变,即下面的方法3。
###方法1,该方法不可取。