7. 카메라2가 할 수 있는 일들
- 수동조작 (ISO, 노출시간, 렌즈 촛점, 화이트 밸런스 등)
- RAW 포맷 지원
- Burst mode 지원
- 3개이상의 카메라에 접근
8. 카메라2 핵심 구동 모델
- Per-setting control
- Single Request, multiple surfaces(up to 3)
- Multiple Requests and results in queue
simultaneosly
- Metadata returned back to the application as
requested separately
13. SurfaceTexture 얻기
TextureView mTextureView = findViewById(R.id.texture);
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
private final TextureView.SurfaceTextureListener mSurfaceTextureListener
= new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { … }
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { … }
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { return true; }
@Override
public void onSurfaceTextureUpdated(SurfaceTexture texture) {…}
};
SurfaceTexture는
OpenGL ES 텍스쳐로써 이미지 스트림으로부터 프레임을 캡쳐합니다.
15. Camera2 용어
- CameraManager : 카메라 목록, 특성, 모니터링 등
- CameraDevice : 물리 카메라 표현, 캡쳐세션, 캡쳐리퀘스트 생성
- CameraCharacteristics : 카메라 특성 정보
- CameraCaptureSession : 카메라로부터 얻은 이미지를 Surface에 출력요청
- CaptureRequest : 카메라로부터 어떻게 이미지를 얻을지 결정
- CaptureResult : 카메라로부터 캡쳐한 결과
16. Camera2 Step By Step
CameraManager얻기 Camera 고르기 CameraDevice 얻기
Surface 얻기 캡쳐 세션 생성 캡쳐 리퀘스트 생성
18. Camera2 Step By Step
CameraManager얻기 Camera 고르기 CameraDevice 얻기
Surface 얻기 캡쳐 세션 생성 캡쳐 세션 생성
19. CameraCharacteristics
for (String cameraId : manager.getCameraIdList()){
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
// 전면 카메라인지 확인
}
Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
mFlashSupported = available == null ? false : available;
// 플래시를 지원하는지 체크
…
}
CameraCharacteristics는 CameraDevice에 대한 메타데이터를 제공합니다.
20. 카메라 등급(INFO_SUPPORTED_HARDWARE_LEVEL)
// 카메라가 특정레벨의 하드웨어 수준을 충족하면 true를 반환
boolean isHardwareLevelSupported(CameraCharacteristics c, int requiredLevel) {
final int[] sortedHwLevels = {
INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL,
INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED, INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
INFO_SUPPORTED_HARDWARE_LEVEL_3 };
int deviceLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (requiredLevel == deviceLevel) {
return true;
}
for (int sortedlevel : sortedHwLevels) {
if (sortedlevel == requiredLevel) { return true; }
else if (sortedlevel == deviceLevel) { return false; }
}
return false; // Should never reach here
}
하나의 필드로 카메라의 하드웨어 지원 수준이 어느정도인지 제공합니다.
(LEGACY < LIMITED < FULL < LEVEL_3)
21. 내가 원하는 카메라를 찾자!
StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
// 사진찍는 용으로 가장 큰 해상도를 사용
Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
new CompareSizesByArea());
…
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
maxPreviewHeight, largest);
StreamConfigurationMap은 다음과 같은 정보를 제공합니다
- 지원하는 이미지 사이즈 및 포맷
- 지원하는 비디오 사이즈와 FPS
- Minimum frame durations and stall durations
22. Camera2 Step By Step
CameraManager얻기 Camera 고르기 CameraDevice 얻기
Surface 얻기 캡쳐 세션 생성 캡쳐 리퀘스트 생성
23. 카메라를 열고 CameraDevice객체를 얻자!
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
카메라를 열기위해서는 Camera Id, StateCallback, Handler가 필요합니다
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
// StateCallback is called when CameraDevice changes its state
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
// This method is called when the camera is opened. We start camera preview here.
mCameraDevice = cameraDevice;
createCameraPreviewSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
//close the resources
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int error) {
//handle error and close resources
}
};
24. Camera2 Step By Step
CameraManager얻기 Camera 고르기 CameraDevice 얻기
Surface 얻기 캡쳐 세션 생성 캡쳐 리퀘스트 생성
25. 텍스쳐뷰로 부터 얻은 SurfaceTexture로 Surface 만들기
SurfaceTexture texture = mTextureView.getSurfaceTexture();
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
// 프리뷰를 위한 Surface를 만듭니다.
Surface surface = new Surface(texture);
캡쳐세션을 만들기 전에 프리뷰를 위한 Surface를 준비합니다.
26. ImageReader로부터 Surface 얻기
ImageReader mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, 2);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
Surface surface = mImageReader.getSurface();
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
…
// save a jpeg into the file here
image.close();
}
};
이 Surface는 나중에 사진을 찍기 위해 사용합니다.
27. Camera2 Step By Step
CameraManager얻기 Camera 고르기 CameraDevice 얻기
Surface 얻기 캡쳐 세션 생성하기 캡쳐 리퀘스트 생성
28. 카메라 캡쳐 세션 생성하기
카메라 캡쳐세션을 생성하기 위해 아래의 메소드를 호출 합니다.
CameraDevice.createCaptureSession(List<Surface>, StateCallback, Handler)
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {...}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {…}
}, null
);
29. Camera2 Step By Step
CameraManager얻기 Camera 고르기 CameraDevice 얻기
Surface 얻기 캡쳐 세션 생성하기 캡쳐 리퀘스트 생성하기
30. 프리뷰를 위한 캡쳐 리퀘스트 생성
CaptureRequest.Builder mPreviewRequestBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
…
mPreviewRequestBuilder.addTarget(surface);
CaptureRequest mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);
31. 사진을 찍기 위한 캡쳐 리퀘스트 생성
CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mImageReader.getSurface());
…
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
32. 실시간 이미지 프로세싱을 위한 프리뷰 버퍼 얻는 방법
ImageReader previewImageReader =
ImageReader.newInstance(width, hegith, ImageFormat.YUV_420_888, 1);
ImageReader.OnImageAvailableListener previewCallback = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
//image processing
image.close();
}
};
33. 어렵고 복잡한 카메라를 쉽게!
- 유즈 케이스 기반으로 설계됨
- Lifecycle-aware
- Support effects. (Like Bokeh, HDR, Night and Beauty)