Tistory View

구버전의 카메라Api를 사용하여 Preview를 보이게 하는 과정에서, setPreviewCallback을 사용할 경우, 지속적으로 메모리를 할당하는 방식을 쓰기 때문에, 효율을 위해 setPreviewCallbackWithBuffer를 사용할 수 밖에 없다.


실제 setPreviewCallback만 사용할 경우 메모리할당이 지속적으로 일어나며, 메모리를 해제한다고 GC의 순간 멈춤 또한 지속적으로 발생한다.
GC때문에 Logcat에는 GC가 동작에 따른 로그로 가득차기 일 수 있다.


효율적인 Preview를 위해 setPreviewCallBackWithBuffer를 사용해야 하는 데, 역시 예상대로 android개발은 삽질의 연속이다.


같은 코드를 사용하여 테스트를 한다고 해도, 어떤 기기에서는 상당히 잘 돌아가는 방면, 어떤기기는 동작이 멈춰버리기 일쑤이다.

대표적으로 Buffer abandon이 제일 문제였는 데..

어떤 기기는 발생하지도 않고 잘 동작하며, 어떤기기는 무조건 [버리기(abandon)]가 발생해버린다.
(필자가 좀 더 효율적으로 동작하는 코드를 넣는 다고 삽질하는 경우가 많은 데.. 역시 이런 삽질이 또 다른 문제를 일으킨다.  )


이 CallbackWithBuffer를 사용하다보니, 기기마다 호환성을 맞춰야하는 상황이 발생할 수 있다. 
(솔직히 미쳐버리기 직전이다. 안드로이드를 개발하면서 이런 문제에 부딪힐 때마다 느끼는 거지만,, 진짜 암걸릴 거 같다..)



그럼 setPreviewCallbackWithBuffer를 사용하면 뭐가 좋을 까...


setPreviewCallbackWithBuffer는 메모리를 지속적으로 할당하지 않고 미리 할당된 메모리를 지속적으로 사용하므로 할당과 해제의 부하를 줄일 수 있다, 이 부하는 특히 JAVA에서는 상당히 크다, GC가 동작할 때는 뚝뚝 끊기는 일이 발생하기도 한다.

또한 camera에서 preview이미지를 받아오는 것은 카메라가 찍는 시간이 상대적으로 길어서 미리미리 찍은 사진을 받아올 공간을 제공해 줘야 좀 더 부드러운 움직임을 얻을 수 있다.


preview를 받아오기 위한 buffer는 여러개를 미리 넣어 둘 수가 있다. 한 개의 buffer만으로 동작시키면 다음 preview를 놓칠 수가 있어서, 다중 버퍼를 이용해야 부드러운 화면을 만들 수 있다.



setPreviewCallBackWithBuffer에 callback interface는 다음과 같이 생겼다.


public interface PreviewCallback
{
        void onPreviewFrame(byte[] data, Camera camera);
};


카메라가 preview화면을 찍을 때마다 data로 저장되어 넘어오게 된다. 같이 넘어온 camera 파라미터를 통해 어떤 형식으로 저장되어있는지, 어떤 크기인지 알아 낼 수 있다.

이 때 data는 미리 할당된 값이다( 어딘 선가 addCallbackBuffer를 통해 넣어 준 버퍼이다. )



중요한 것은 이 data를 사용 후에 다시 addCallbackBuffer를 통해 다시 넣어 줘야 한다.
필자의 경우 이 data는 가공용으로 쓰고 새버퍼를 할당해 넣어 줬더니, 어떤 기기는 잘 동작 했지만, 어떤기기는 [버리기(abandon)]이 발생하여 preview가 멈춰버리는 경우 가 있었다. 정확히 이 문제 인지는 모르겠으나, 이 황당한 사태를 벗어나기 위해 필자가 선택한 방법은 다음과 같다.





setPreviewCallbackWithBuffer를 실행하기 전에 3~4개의 버퍼를 넣어준다.
setPreviewCallbackWithBuffer를 실행하고 필요한 위치에 startPreview한다.


onPreviewFrame에서 넘어온 값을 넘어온 순서대로 다시 addCallbackBuffer한다.
(중간에 새로운 버퍼를 만들어 넣거나 하지 않는다 )


우선 이 방식으로 abandon되는 일을 해결할 수가 있었다..... 



정말 짜증나는 일이다.....















Replies
Reply Write