반응형

카메라 애플리케이션은 카메라를 제어할 때, 기본적으로 카메라 서비스로 제어를 요청한 후 대기한다. 카메라 서비스로 제어를 요청한 후 메소드의 리턴값만으로 수행 결과를 처리할 경우, 처리가 오래 걸려 애플리케이션이 응답하지 않아 시스템 감시에 의해 ANR(Application Not Responding)로 인식되는 문제가 발생한다. 또한 카메라 서비스가 제어를 수행하는 동안 애플리케이션이 대기하므로 사용자의 요청을 처리할 수 없게 된다. 이와 같은 문제를 해결하기 위하여 다양한 콜백 메서드를 사용한다.


콜백메서드는 카메라 시스템의 주요 기능인데, 크게 두가지로 나뉘어진다.

데이터를 받아오기 위한 dataCallback 메서드

동작에 대한 상태나 결과를 받아오기 위한 notifyCallback 메서드가 그것이다.


dataCallback 메서드는 카메라의 영상을 프레임이나 이미지 형태로 가져오기 위하여 사용하며, 데이터 포맷은 카메라 설정에 따라 다르나 프레임의 경우 NV21(yuv420sp)를 기본이고, 이미지의 경우에는 JPEG을 기본으로 한다.


notifyCallback 메서드는 요청한 기능에 대하여 수행상태나 수행 완료등의 제어 결과나 제어 상태 정보를 얻기 위하여 사용한다.





1) PreviewCallback


카메라 영상 데이터는 네이티브 프레임워크에서 처리되므로, 애플리케이션은 카메라 영상 데이터를 얻기 위하여 카메라 서비스에 요청해야 한다. 이때 콜백 메서드로 카메라 영상 데이터를 얻어오는데, PreviewCallback 메서드는 startPreview() 메서드를 이용해 카메라에서 입력받아 화면에 출력되는 영상을 프레임 단위로 받아올 수 있다. 카메라 영상을 직접 처리해야하는 애플리케이션의 경우 PreviewCallback 메서드를 사용한다.

PreviewCallback 메서드는 setPreviewCallbck()메서드나 setOneshot PreviewCallback()메서드로 카메라 서비스에 콜백 메서드를 등록하거나 해제할 수 있다.

setOneShot PreviewCallback() 메서드는 프레임 데이터를 한번만 받아오고, setPreviewCallback()메서드는 해제 전까지 지속적으로 프레임 데이터를 받아온다. 이 경우 데이터 복사등에 따른 데이터 처리량이 많아져 시스템에 부하가 걸릴수 있으므로, 원하는 용도에 맞게 사용을 해야한다.



2) PictureCallback


PictureCallback 메서드는 사진 촬영 시 촬영된 결과물을 얻기 위한 인터페이스로,

애플리케이션에서 인터페이스를 구현하여 목적에 맞게 사용한다.

이렇게 구현된 콜백 메서드는 RawPictureCallback, PostViewPictureCallback, JpegPictureCallback 이 있다




3) RawPictureCallback


RawPictureCallback 메서드는 사진 촬영 시, 촬영된 원본 데이터를 받아온다.

카메라의 기본 애플리케이션은 카메라 서비스를 이용해 카메라 촬영 요청 후 촬영을 완료하여 이미지를 생성 완료하는 과정에서 카메라가 촬영을 완료한 시점의 시간 정보를 획득하는 데 RawPictureCallback 메서드를 사용한다.





4) PostViewPictureCallback


PostViewPictureCallback 메서드는 촬영된 이미지를 화면에 출력할 목적으로 사용한다. 카메라 기본 애플리케이션은 PostViewPictureCallback 메서드 역시 촬영 기능에 대한 시간을 측정하기 위한 용도로 사용한다.




5) JpegPictureCallback


JpegPictureCallback 메서드는 RawPictureCallback 메서드와 마찬가지로 takePicture()메서드를 통해 카메라 서비스에 등록한다. 전달받는 데이터는 JPEG 이미지 데이터에 EXIF정보가 포함된 전체 데이터로, 저장소에 저장한다.




6) ShutterCallback


사진 촬영 시 카메라 장치에서 사진 촬영을 완료한 후 데이터를 받아오기 전에 ShutterCallback 메서드가 등록되어 있으면 이를 통해 사진이 촬영되었음을 알려준다. ShutterCallback메서드를 통해 카메라 서비스에서 카메라 촬영음을 낸다. 카메라 기본 애플리케이션은 ShutterCallback 메서드를 통해 카메라 동작에 대한 시간을 측정한다.




7)ErrorCallback


카메라 서비스가 동작 중 에러가 발생하는 경우, 이를 애플리케이션이 알기 위한 콜백 메서드로, 카메라 서비스가 잘못 동작해 카메라 서비스나 미디어 서버가 죽는 경우에 호출된다.


반응형
반응형

해당 부분은 개발자가 직접 개발할 수 있는 어플들에 관한 계층입니다.

시중에 나와있는 각종 안드로이드 책에서도 쉽게 볼 수 있는 부분입니다.

실제적으로 코딩을 해야되는 부분이므로, 천천히 읽어나가셨으면 합니다.

이 부분도 '안드로이드의 모든것 분석과 포팅'과 카메라 개발문서를 보면서 제 개인적으로 정리한 부분을 적어놓은것임을 미리 밝혀 드립니다.


카메라 애플리케이션을 만들기 위해서는 기본적으로 카메라영상을 사용자가 볼 수 있게 출력을 하는 Preview 부분이 먼저 구현이 되어야 한다.

그래서 카메라를 구동해서

영상을 입력받기 위한 카메라서비스 관련 기능과

영상을 화면에 출력하기 위한 SurfaceFlinger 서비스 관련 기능이 구현되어야 한다.



(카메라 예제 애플리케이션의 구조도)



애플리케이션을 코딩하기전에 androidManifest부터 설정을 해야한다.


   <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>



그다음 영상을 위한 출력을 해보자.

먼저 출력할 영역을 설정을 해야하는데, 이부분은 xml로도 가능하고 바로 코딩으로도 가능하다. 출력은 SurfaceView에서하는데 Surface를 생성하도록 SurfaceFlinger서비스에 요청을 해야한다. 그런데 SurfaceView를 관리하기 위한 SurfaceHolder가 존재하고 이를 통해 SurfaceView영역에 대한 처리를 SurfaceFlinger에 요청을 한다.



public class CameraPreview extends Activity{

private Preview mPreview;

protected void onCreate(Bundle savedInstanceState){

mPreview = new Preview(this);

setContentView(mPreview);

}

}


Preview 클래스는 ViewGroup 클래스를 확장하고, SurfaceHolder.Callback 인터페이스를 구현하였다. Preview 클래스는 인스턴스 생성 시 SurfaceVIew와 관련된 처리를 수행한다.

ViewGroup은 android.view.ViewGroup으로 View클래스를 확장한것이다. 그런데 이는 다른뷰를 포함할 수 있는 특별한 뷰이다. 

SurfaceHolder.Callback 인터페이스는 SurfaceFlinger서비스에서 요청된 Surface를 생성하거나 소멸시킬 때를 알기 위한 것으로, 애플리케이션이 Surface에 직접 접근할 권한이 없기 때문에 SurfaceHolder.Callback 인터페이스를 통해 콜백 메서드를 구현하여 Surface를 처리하여야 한다.




class Preview extends ViewGroup implements surfaceholder.callback{

Surfaceview mSurfaceView;

SurfaceHolder mHolder;

Preview(Context context){

mSurfaceView = new SurfaceView(context);

addView(mSurfaceView);

//Install a SurfaceHolder. Callback so we get notified when the

//underlying surface is created and destroyed.

mHolder = mSurfaceView.getHolder();

mHolder.addCallback(this);

mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

}


SufaceView 와 SurfaceHolder를 연결을 시켜야 하는데, 이 역할을 addCallback()메서드로 하게 된다. 이후 Surface가 생성되거나 소멸될 때, 속성이 변경될 때 콜백 메서드를 통해 Preview 인스턴스의 메서드를 호출한다.


이렇게 출력할 화면이 준비가 되면, 그 다음으로 카메라 장치와 이를 연결을 해주면 된다. 위의 CameraPreview애플리케이션이 구동이 되면

onResume()메서드가 호출이 되고, 이때 카메라 서비스를 이용해 카메라를 구동한다.

android.hardware.Camera의 open()메서드로 카메라 서비스를 이용해 카메라 장치를 활성화 하고, Camera 인스턴스를 얻어 온다.

그 후 Preview의 setCamera() 메서드를 호출하여 카메라 정보를 기반으로 레이아웃을 설정한다.


protected void onResume(){

mCamera = Camera.open();

mPreview.setCamera(mCamera);

}



public void setCamera(Camera camera){

mCamera = camera;

if(mCamera !=null){

mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();

}

}



애플리케이션에서 카메라 서비스의 현재 설정값을 얻고자 할때는

android.hardware.Camera에서 제공하는 getParameters()메서드를 사용한다.

카메라의 매개변수 중에서 카메라가 지원하는 프리뷰 크기 정보를 기반으로 하여,

Preview의 onMeasure()메서드에서 적절한 프리뷰 크기를 찾고,

Preview의 onLayout()메서드에서 선택된 프리뷰 크기 정보를 기반으로 뷰를 생성하고 크기 및 위치를 조정한다.




카메라 영상이 출력될 Surface가 생성되면 surfaceCreate()메서드가 호출되고,

카메라 서비스에 프리뷰 영역으로 생성된 Surface에 카메라 프리뷰가 출력되도록 설정한다.


public void surfaceCreated(SurfaceHolder holder){

try{

if(mCamera != null){

mCamera.setPreviewDisplay(holder);

}

}

}





이후 Surface가 변경되어 프리뷰 인스턴스의 surfaceChanged()메서드가 호출되면,

카메라의 현재 매개변수 값을 다시 가져와 선택된 프리뷰 크기로 변경하고,

setParameters()메서드로 프리뷰 카메라에 설정한다.

이후 startPreview()메서드로 카메라 서비스에서 영상을 가져와 화면에 출력한다.



public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){

//Now that the size is known, set up the camera parameters and begin the //preview.

Camera.Parameters parameters = mCamera.getParameters();

parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

requestLayout();


mCamera.setParameters(parameters);

mCamera.startPreview();

}

반응형

'CS > 안드로이드' 카테고리의 다른 글

[안드로이드] 카메라 #3_Callback  (0) 2016.10.24
[안드로이드] 카메라 #1_매커니즘  (0) 2016.10.24
반응형

1) 안드로이드 카메라 출력 매커니즘


안드로이드에서 카메라에 입력되는 영상을 처리하는 것은 다음과 같은 방식을 따릅니다. 애플리케이션에서 surfaceView를 통해 surface를 생성하여 화면에 영상을 출력할 영역을 설정합니다. 그리고 카메라 서비스에서 카메라로부터 영상 프레임 데이터를 받아와 SurfaceFlinger를 통해 화면에 출력을 합니다. 이때 하드웨어에서 Overlay 기능을 지원하면 해당 영역에 Overlay를 통해 화면에 직접 출력이 됩니다.




-애플리케이션 계층

사용자가 직접 해당 어플을 만드는 계층입니다. 흔히들 많이 쓰는 캔디카메라나 스노우와 같은것들이 작동하는 계층입니다.

해당 계층의 CameraView는 안드로이드에서 제공하는 예제 애플리케이션으로, 카메라 영상을 화면에 출력한다. com.android.camera(Camera.apk)는 기본으로 제공되는 카메라 애플리케이션으로, 카메라와 관련된 여러 기능이 구현되어 있다.


- 애플리케이션 프레임워크 계층

해당 계층의 android.hardware.Camera는 Java로 구현된 서비스와 C++로 구현된 JNI가 존재하며 애플리케이션과 Native Service 간의 중간 계층으로 애플리케이션이 Native Service에 접근하기 위한 징검다리 역할을 수행한다. JNI의 경우 Java와 C++간의 연결통로로, 주로 Java와 C++간의 데이터 변환을 처리한다.


-라이브러리 계층

해당계층의 libcamera_client는 카메라 서비스의 클라이언트의 역할을 하며 Binder를 통해 카메라 서비스와 연결되어 상위 응용 계층에서 내려오는 제어요청을 카메라 서비스에 전달하고 결과를 받아 상위 계층으로 전달한다. 카메라 서비스는 카메라에 대한 전반적인 제어를 담당하며 libcamera_client를 통해 내려오는 요청에 대한 처리 및 카메라 장치를 관리한다.


-HAL 계층

해당 계층의 libcamera는 카메라 장치에 대한 인터페이스이다.

이 인터페이스는 두가지로 구분이 되는데,

카메라 관련 정보를 제공하고 카메라 관련 설정 및 카메라 장치를 관리하는 인터페이스 영역과 각 카메라 장치별로 카메라 드라이버를 통해 제어를 수행하는 HAL로 구분된다.


-커널

사용자 영역에서 카메라에 접근하기 위하여 사용하는 API인 V4L2를 제공하고,

V4L2는 각 SoC의 카메라 인터페이스와 연결된다. 이후 카메라 인터페이스 드라이버에서 카메라 장치 드라이버를 제어하여 카메라 서비스를 제공한다.


반응형

+ Recent posts