本文是在 Camera 采集数据通过 textureview 预览,手动对焦、自动对焦 (一) 在熟悉Camera使用基础上,增加了录制和拍照的功能,仿照微信点击拍照、长按录制视频。
网上也有很多仿微信相机的应用,不过基本上是使用MediaRecord录制视频,相对比较简单。与他们不同的是,这里我更想学习整个MP4的录制流程,从采集、编码、封包成MP4到解析、解码、播放,这更能够加深对音视频的理解和后续的学习。
拍照流程:
1.利用 Camera.PreviewCallback 回调接口收集到 YUV数据
public void onPreviewFrame(byte[] bytes, Camera camera)
2.若是拍照,将NV21数据保存为文件,或者转化成bitmap显示到ImageView
你会发现图片会显示的旋转角度不对,需要根据是前置和后置摄像头,来对NV21数据进行旋转一定的角度
public static boolean saveNV21(byte[] data, int width, int height, String path) {
try {
FileOutputStream outputStream = new FileOutputStream(path);
// 后置摄像头旋转90度,后置旋转270度
if (CameraUtil.isBackCamera()) {
data = rotateYUV420Degree90(data, height, width);
} else {
data = rotateYUV420Degree270(data, height, width);
}
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, width, height, null);
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 70, outputStream);
outputStream.flush();
outputStream.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
录制流程:
拍照比较简单,而录制需要分成三个部分:采集编码视频数据、采集编码音频数据、混合编制成MP4,这里遇到的坑要比拍照多多了。
1.同样获取onPreviewFrame()回调的YUV数据,利用MediaCodec编码成H.264格式数据
2.使用AudioRecord采集PCM原始音频数据,利用MediaCodec编码成AAC格式数据
3.使用MediaMuxer将H.264视频数据和AAC音频数据混合
采集编码视频数据
1.开启一个VideoRecordThread处理NV21数据
// 开始录制
public void begin() {
dataQueue.clear();
isRecording = true;
generateIndex = 0;
start();
}
// dataQueue存储来自camera的数据
public void frame