简介
- [x] 音视频基础0——目录
- [x] 音视频基础1——AudioTrack、AudioRecorder、MediaRecorder音频数据采集播放处理
- [ ] 音视频基础2——Android Camera API及Camera2 API的使用
- [ ] 音视频基础3——Android Camera API及Camera2 采集视频数据
- [ ] 音视频基础4——Android MediaCodec API学习
- [ ] 音视频基础5——Android 实现rtmp推流
- [x] 音视频基础6——交叉编译动态库
- [ ] 音视频基础7——MacOs下编译FFMpeg4.2.2
两种API的基本说明
Camera API
打开摄像机,开启预览
Camera API 拍照流程
拍摄照片的一般步骤及API调用顺序
- 通过 - Camera#open(int)来获取- Camera实例;
- 通过 - Camera#getParameters(),来获取- Camera默认设置;
- 如果需要修改 - Camera的设置,则修改- Camera#getParameters()返回的- Camera.Parameters对象,然后调用- Camera#setParameters()设置- Camera参数;
- 通过调用 - Camera#setDisplayOrientation(int)来获得正确的预览方向;
- 传递一个完全初始化好的 - SurfaceHolder(通过- SurfaceView#getHolder()方法获取)给- Camera的- setPreviewDisplay(SurfaceHolder)方法,建立- Camera与- SurfaceView的联系;
- 在开始调用 - Camera#takePicture()之前,一定要先调用- Camera#startPreview()来开启预览;
- 调用 - void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg)来进行拍照,注意,在相应的回调中处理获取的图片数据;
- 调用 - takePicture之后,火锅还想继续拍照,需要重新调用- startPreview方法;
- 调用 - stopPreview来停止更新- SurfaceView的预览;
- 在应用不使用相机时,需要调用 - release()方法来释放相机资源以供其他应用使用。在- Activity onPause时应该立即释放相机资源,在- Activity onResume时在重新打开相机;
Camera API 视频录制模式
获取相机实例听开启预览(同拍照)
| 1 | public void openCamera() { | 
注意:使用相机需要 申请权限:Manifest.permission.CAMERA,Android 6.0后需要动态申请。
获取预览尺寸代码
| 1 | 
 | 
视频数据编码
定义一个视频编码工具类,将采集到的二进制数据(setPreviewFormat中指定预览的数据格式为 ImageFormat.NV21)进行数据转换,这里的示例是将其转换测h264格式数据。这里的编码采用的是MediaCodec。由于 MediaCodec 不直接支持 NV21格式,这里需要先将采集到的数据转换成 NV12格式,然后在将 NV12格式转换成 h264格式,示例代码如下:
| 1 | public class NV21EncoderH264 { | 
处理预览回调的数据
在camera.setPreviewCallback中处理回调的每一帧数据,调用上面的 encoderH264方法,将预览数据转换成h264数据,代码如下:
| 1 | //设置监听获取视频流的每一帧 | 
在停止预览时,最终会调用 EncoderListener的 h264(byte[] data) 方法,之遥在这个方法中将 data保存成文件即可。
Camera2 API
Camera2 API 是Android 5.0 之后出现的相机操作API,主要用来替代原来的Camera API,Camera2 API提高了Android系统的拍照性能,支持RAW照片输出,还可以根据设备的支持情况,设置相机的对焦模式、曝光模式、快门等,相对于Camera API,对各个功能做了分层,使用起来更灵活。先对Camera2 API中几个常用的类进行说明,然后给出使用Camera2 API进行视频采集的一般流程。
- CameraManager,相机管理类,是一个系统服务,需要通过该类可以检测、打开摄像头,同时可以获取该设备相机支持的特性;
- CameraCharacteristics,设备相机属性描述类,具体描述了相机支持哪些功能特性;
- CameraDevice,代表的是Android设备上的一个相机;
- CameraCaptureSession,用于创建预览、拍照的Session类。通过它的- setRepeatingRequest()方法控制预览界面 , 通过它的- capture()方法控制拍照动作或者录像动作;
- CameraRequest,一次捕获的请求,可以设置一些列的参数,用于控制预览和拍照参数,例如:对焦模式,曝光模式,zoom参数等等;
CameraCharacteristics
CameraCharacteristics是一个包含相机参数的对象,可以通过一些key获取对应的values。常用的参数如下:
- LENS_FACING,获取摄像头的方向,- 其中 - LENS_FACING_FRONT表示前置摄像头,
- LENS_FACING_BACK表示后置摄像头,
- LENS_FACING_EXTERNAL,表示外界摄像头;
 
- SENSOR_ORIENTATION,获取摄像头拍照的方向;
- FLASH_INFO_AVAILABLE,设备是否支持闪光灯;
- SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,设备最大数码调焦值,即zoom的最大值;
- LENS_INFO_MINIMUM_FOCUS_DISTANCE,获取最小的调焦距离,某些手机上获取到的该values为null或者0.0。前摄像头大部分有固定焦距,无法调节。 
- INFO_SUPPORTED_HARDWARE_LEVEL,获取摄像头支持某些特性的程度,以下是关于返回值的一些说明:- INFO_SUPPORTED_HARDWARE_LEVEL_FULL,功能支持最全的模式;
- INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,限制模式,具体使用某个特性时,需要单独查询;
- INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,向后兼容模式,支持的特性有限;
 
图片采集流程
- 检查设备兼容性; 
- 打开星际并设置预览; 
- 配置ImageReader 
- 拍照处理; 
- 恢复预览; 
视频采集流程
- 检查设备兼容性,需要确保当前的设备是否支持Camera2 API的全部特性或部分特性; 
- 打开相机和设置预览; 
- 配置Media Recorder 
- 开始录制; 
- 停止录制; 
使用Camera API或Camera2 API的流程大体上相同,Camera API操作都在Camera这个类中,所以所有操作都离不开Camera类或类实例,Camera2 API 由于对Camera的操作做了一些分层,使用流程有所不同。
检查设备兼容性
在使用Camera2 API 之前,先要确认当前硬件设备是否支持Camera2的特性,可以通过CameraManager.getCameraCharacteristics(String cameraId)来获取相机特性,并检查CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL,代码如下:
| 1 | CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); | 
打开相机设置和设置预览
打开相机
| 1 | // 获取 CameraManager | 
mStateCallback为相机打开状态会调监听,相机有三个状态可以进行会调处理:
- onOpened,成功打开,之后可以开始预览了; 
- onDisconnected,断开链接,设备已不可在用了,需要进行 CameraDevice 关闭 
- onError,打开失败,同样要进行 CameraDevice 关闭操作; 
具体实现如下:
| 1 | private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { | 
开启预览
上面的starPreview() 方法进行的就是开启相机预览的具体操作,一般来说,开启相机预览要经历一下步骤:
- 关闭之前的预览对话,即 如果之前存在 - CameraCaptureSession对象实例,需要先调用其- close()方法;
- 通过 CaptureRequest.Builder 构造新的 CaptureRequest,核心是要调用 CaptureRequest.Builder的addTarget(Surface) 为预览指定Surface对象(通常从TexttureView、SurfaceView等获取),注意 CaptureRequest.Builder 通过调用CameraDevice的createCaptureRequest方法获取; 
- 建立新的 CameraCaptureSession,并在建立成功后,更新预览即可,建立成功与否通过 CameraCaptureSession.StateCallback会调来判断; 
- 不断的通过 CameraCaptureSession 发送 重复的 CaptureRequest,由于这里需要一直不断重复的发送,所以这里推荐采用单独的线程来进行操作; 
通过上面的操作,就完成了相机的打开即预览开启的工作,接下来就是重头戏,视频的录制操作。
配置MediaRecorder
由是采用 MediaRecorder 来作为视频数据的输出端的,在开始录制之前,需要对 MediaRecorder进行相应的设置。
| 1 | private void setUpMediaRecorder() throws IOException { | 
开始录制
开始录制的过程其实和开启预览的过程差不多,区别在于以下几点:
- 预览 mCameraDevice.createCaptureRequest采用的是 - TEMPLATE_PREVIEW,而录制采用的是- TEMPLATE_RECORD;
- 预览CaptureRequest.Builder只添加了一个 previewSurface,即TextureView的Surface,而录制在此基础之上还添加了一个 recorderSurface,即MediaRecorder.getSurface(); 
注意:
如果要在 CameraCaputureSession 的会调中进行UI更新相关的操作,则需要进行线程的切换操作。
停止录制
结束录制很简单,终止相应的 CameraCaputureSession,调用 MediaRecorder的stop,并重置,然后再重新 调用前面的startPreview方法,具体如下:
| 1 | private void stopRecordingVideo() { | 
注意事项
- 使用相机相关API时,需要请求 - android.permission.CAMERA,代码如下:- 1 
 2
 3- <manifest xmlns:android="http://schemas.android.com/apk/res/android"> 
 <uses-permission android:name="android.permission.CAMERA" />
 </manifest>- 注意6.0 之后,这个权限需要动态请求了。动态请求权限代码片段如下: 
| 1 | public class VideoCameraDemoActivity extends AppCompatActivity { | 
- AndroidManifest.xml 中声明使用相机权限时,提示 Permission exists without corresponding hardware <uses-feature android:name="android.hardware.camera" required="false">,原因如下:
在大多数情况下,硬件是可选的,因此最好在
声明中将 android:required 设置为 false,从而将 
硬件声明为可选项,并在应用中检查是否支持硬件。如果不添加这个声明,则 Android 会假定应用必须在有该硬件的情况下才能
运行。因此,系统会阻止某些设备安装应用
总结
本文主要对 Camera API 和 Camera2 API 进行了简单的介绍,并给出了两种API下进行视频采集的具体实现,资料一部分来源于网络,一部分来源于自己对官方文档的理解,其中Camera2 API实例是Google 官方的 Camera2 的实例,通过本文,了解到了 Camera2 API使用的具体流程,当然Camera2 API还有很多可以控制的细节,需要 日后不断完善。