您的位置:首页 > 其它

使用安卓Camera类完成视频截图功能

2016-03-10 15:47 204 查看

最近公司在VOIP视频上传的功能里加视频截图的功能。下面我来介绍一下我的实现思路和实现过程。

首先,简单说一下视频录制功能是调用的相机的自带的Camera类,用SurfaceView当容器,绘出摄像头采集的数据。要实现截取当前正在拍摄视频的截图主要有两种思路:1 获取当前屏幕的view,然后把view转换成Bitmap。之后再对Bitmap压缩然后上传。2 利用Camera类自带的takePicture()方法调用系统相机拍照,实际上相当于模拟相机拍照。

第一种方法看似简单,而且之前用过,我先试了一下,但是结果不如人意,图片是弄出来了,但是却是一片漆黑。好吧,经过查阅资料发现这和SurfaceView实现机制有关系,感觉这条路走不通,好,走第二条。

第二种方法可以使用正在上传录制的Camera对象,调用takePictiure方法

Camera.takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)

这个方法有3个参数,需要实现一个callback,调用这个方法会回调这个callback,这里我用的是最常用的PictureCallback,自己新建一个类继承这个Callback,重载里面的onPictureTaken方法

onPictureTaken(byte[] data, Camera camera)

方法里有一个byte数组,这里面就是梦寐以求的照片数据了,之后对它怎么处理不就是很easy的了,还有一点要注意的,调用了takePicture方法以后在回调里要调用一下Camera.startPreview(); 因为照相以后会把视频预览卡住,这样要重新开启一下。以下是我的代码。

camera.takePicture(null, null, new MyPictureCallback());


private final class MyPictureCallback implements PictureCallback {
public void onPictureTaken(byte[] data, Camera camera) {
try {
TakePhotoThread takePhotoThread = new TakePhotoThread(data);//处理照片线程
new Thread(takePhotoThread).start();
camera.startPreview();//在这里设置重新开始预览
Toast.makeText(context, "截图成功", Toast.LENGTH_SHORT);

} catch (Exception e) {
e.printStackTrace();
}
}
}


我这里新建了一个线程来处理照片数据。具体如何处理照片就按照各自的需求了。

貌似一切都可以了,但是事与愿违,截图功能出来以后,在不同测试机下显示的效果不太一样,有的手机,好吧就是万恶的小米手机,照出的照片只有176*144,再加上我加了一些压缩的逻辑,出来的截图简直惨不忍睹,根本看不到是什么。研究了很久,才找到一些资料,发现这个拍照有默认值,不同的手机默认分辨率不同,而小米手机默认的是最小分辨率,好那么我们通过代码设置一个默认分辨率

parameters.setPictureSize(1024, 768);

然而还有问题,在有的手机上直接boom了,原来是这个手机硬件没有这个尺寸。后来我选择了照相机尺寸中的最中间的一个,暂时让照片不会那么小了。

//设置拍照大小,设置为支持拍照像素的一半大小
List<Size> list = parameters.getSupportedPictureSizes();
if(list.size() >2){
Size size = list.get(list.size()/2);
parameters.setPictureSize(size.width, size.height);
}else{
Size size = list.get(0);
parameters.setPictureSize(size.width, size.height);
}


好以上就是我的实现方法,暂时解决了这个问题,但是调用的系统照相功能还是会在预览时停顿一下的,这就有了我们的第三种方法。我试了一下也是可行的。我简单说一下,就是在Activity里继承PreviewCallback这个接口重载这个函数:

public void onPreviewFrame(byte[] data, Camera camera) {}

用这个方法获取SurfaceView的中帧数据,这个也可以得到视频数据。但是我没有深入去做,只是试了一下不知道这个有没有bug。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: