简介
- [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还有很多可以控制的细节,需要 日后不断完善。