Android -- Camera2(Android5.0)
Camera2
Camera2是Android5.0中的其中一个新的特性,新的API。与原来的camera API相比,不同之处在于:
原生支持RAW照片输出突发拍摄模式制约拍照速度的不再是软件而是硬件。以Nexus 5为例,分辨率全开下Andorid L的连拍速度可达到30fps。
全手动控制快门、感光度、对焦、测光、硬件视频防抖等多种参数都被整合到了新的API内。新的API中添加的手动控制功能列表:
感光度手动对焦/AF开关AE/AF/AWB模式AE/AWB锁硬件视频防抖连续帧干货
Camera2 程序逻辑与原Camera有很大不同。
CameraManager,系统服务,通过 CameraManager去获得camera设备对象。CameraDevices提供描述相机硬件设备支持可用的和输出的参数,这些信息通过 CameraCharacteristics获得,CameraCharacteristics又是从 getCameraCharacteristics(cameraId)获得,通过freamwork中的源码发现,其实这里就是直接调用的Camera API接口。
通过camera拍照,应用首先要创建由相机设备的输出surface组成的拍照会话,createCaptureSession(List, CameraCaptureSession.StateCallback, Handler)。每个surface必须预先设置适当的大小和格式去匹配相机设备的可支持的大小和格式。一个目标surface可以从不同的类中获取,包括SurfaceView,SurfaceTexture via Surface(SurfaceTexture), MediaCodec, MediaRecorder, Allocation, and ImageReader.
一旦请求被建立,他可以交给活动的拍照会话:一次拍照(one-shot )或者无止境连续拍照或预览(Repeating)。两种方法都有一个其他的方式:接受一系列的请求作为burst拍照/重复burst。
1
|
public
void
openCamera (String cameraId, CameraDevice.StateCallback callback, Handler handler)
|
使用getCameraIdList()来获得可用摄像设备的列表。一旦成功打开相机,CameraDevice.StateCallback中的onOpened(CameraDevice)将被调用。相机设备可以通过调用createCaptureSession()和createCaptureRequest()去设置操作。如果打开相机设备失败,那么设备回调的onError方法将被调用,和后续调用相机设备将抛出一个CameraAccessException。
1
|
public
abstract
CaptureRequest.Builder createCaptureRequest (
int
templateType)
|
为请求拍照创建一个CaptureRequest.Builder,初始化目标用例的模板。选择最好的设置为特定的相机设备,所以不建议为不同的相机设备重用相同的请求,创建一个builder为具体的设备和模板和根据需要覆盖的设置。
1
|
public
abstract
void
createCaptureSession (List<surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)</surface>
|
活动着的会话决定了相机的output Surfaces 为每个拍照的要求。给定请求可以使用全部或只有部分的output Surfaces。一旦CameraCaptureSession创建,可以提交capture请求、captureBurst请求,setRepeatingRequest请求或setRepeatingBurst请求。
权限
1
|
<uses-permission android:name=
"android.permission.CAMERA/"
></uses-permission>
|
布局
1
2
3
4
5
6
|
<!--?xml version=
1.0
encoding=utf-
8
?-->
<linearlayout android:layout_height=
"match_parent"
android:layout_width=
"match_parent"
android:orientation=
"vertical"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<textureview android:id=
"@+id/textureview"
android:layout_height=
"fill_parent/"
android:layout_width=
"fill_parent"
>
</textureview></linearlayout>
|
核心代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
public
class
CameraFragment
extends
Fragment
implements
TextureView.SurfaceTextureListener {
private
TextureView mPreviewView;
private
Handler mHandler;
private
HandlerThread mThreadHandler;
private
Size mPreviewSize;
private
CaptureRequest.Builder mPreviewBuilder;
public
static
CameraFragment newInstance() {
return
new
CameraFragment();
}
@SuppressWarnings
(ResourceType)
@Override
public
View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.camera_frag,
null
);
initLooper();
initUIAndListener(v);
return
v;
}
//很多过程都变成了异步的了,所以这里需要一个子线程的looper
private
void
initLooper() {
mThreadHandler =
new
HandlerThread(CAMERA2);
mThreadHandler.start();
mHandler =
new
Handler(mThreadHandler.getLooper());
}
//可以通过TextureView或者SurfaceView
private
void
initUIAndListener(View v) {
mPreviewView = (TextureView) v.findViewById(R.id.textureview);
mPreviewView.setSurfaceTextureListener(
this
);
}
@SuppressWarnings
(ResourceType)
@Override
public
void
onSurfaceTextureAvailable(SurfaceTexture surface,
int
width,
int
height) {
try
{
//获得CameraManager
CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
//获得属性
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(
0
);
//支持的STREAM CONFIGURATION
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//显示的size
mPreviewSize = map.getOutputSizes(SurfaceTexture.
class
)[
0
];
//打开相机
cameraManager.openCamera(
0
, mCameraDeviceStateCallback, mHandler);
}
catch
(CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public
void
onSurfaceTextureSizeChanged(SurfaceTexture surface,
int
width,
int
height) {
}
@Override
public
boolean
onSurfaceTextureDestroyed(SurfaceTexture surface) {
return
false
;
}
//TextureView.SurfaceTextureListener
@Override
public
void
onSurfaceTextureUpdated(SurfaceTexture surface) {
}
private
CameraDevice.StateCallback mCameraDeviceStateCallback =
new
CameraDevice.StateCallback() {
@Override
public
void
onOpened(CameraDevice camera) {
try
{
startPreview(camera);
}
catch
(CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public
void
onDisconnected(CameraDevice camera) {
}
@Override
public
void
onError(CameraDevice camera,
int
error) {
}
};
//开始预览,主要是camera.createCaptureSession这段代码很重要,创建会话
private
void
startPreview(CameraDevice camera)
throws
CameraAccessException {
SurfaceTexture texture = mPreviewView.getSurfaceTexture();
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface surface =
new
Surface(texture);
try
{
mPreviewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
}
catch
(CameraAccessException e) {
e.printStackTrace();
}
mPreviewBuilder.addTarget(surface);
camera.createCaptureSession(Arrays.asList(surface), mSessionStateCallback, mHandler);
}
private
CameraCaptureSession.StateCallback mSessionStateCallback =
new
CameraCaptureSession.StateCallback() {
@Override
public
void
onConfigured(CameraCaptureSession session) {
try
{
updatePreview(session);
}
catch
(CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public
void
onConfigureFailed(CameraCaptureSession session) {
}
};
private
void
updatePreview(CameraCaptureSession session)
throws
CameraAccessException {
session.setRepeatingRequest(mPreviewBuilder.build(),
null
, mHandler);
}
}
|
原文链接
http://www.2cto.com/kf/201501/367226.html