Android 에서 카메라 분석

http://android.yesky.com/thread-14399-1-1.html
1. Camera 구조 분석
안 드 로 이 드 의 카 메 라 는 프 리 뷰 (preview) 와 사진 촬영 (take picture) 기능 을 포함한다.현재 안 드 로 이 드 가 발표 한 Camera 프로그램 은 기능 이 비교적 간단 하지만 그 프로그램의 구 조 는 클 라 이언 트 와 서버 두 부분 으로 나 뉘 어 안 드 로 이 드 프로 세 스 간 통신 Binder 의 구조 에 세 워 졌 다.Android 에서 Camera 모듈 역시 Andorid 의 프레임 워 크 를 따 릅 니 다. 아래 그림 과 같 습 니 다.
Camera Architecture Camera 모듈 에는 주로 libandroid 가 포함 되 어 있 습 니 다.runtime. so, libui. so 와 libcameraservice. so 등 몇 개의 라 이브 러 리 파일 은 다음 과 같이 호출 됩 니 다.
Camera 모듈 의 각 라 이브 러 리 에서 libui. so 는 핵심 위치 에 있 으 며, 상부 에 제공 하 는 인 터 페 이 스 는 주로 Camera 류 입 니 다.
    libcameraservice. so 는 Camera 의 server 프로그램 으로 libui. so 의 클래스 를 계승 하여 server 의 기능 을 실현 하고 libui. so 의 다른 부분 과 프로 세 스 간 통신 (즉 Binder 체제) 을 통 해 통신 합 니 다.
libandroid_runtime. so 와 libui. so 두 라 이브 러 리 는 공용 으로 카메라 외 에 도 다른 기능 이 있 습 니 다.전체 카메라 가 실 행 될 때 대체적으로 Client 와 Server 두 부분 으로 나 눌 수 있 습 니 다. 각각 두 프로 세 스 에서 실 행 됩 니 다. 이들 은 Binder 체 제 를 사용 하여 프로 세 스 간 통신 을 실현 합 니 다.이렇게 하면 client 호출 인터페이스 에서 기능 은 server 에서 이 루어 지지 만 client 에서 호출 하면 server 의 기능 을 직접 호출 하 는 것 과 같 습 니 다. 프로 세 스 간 통신 부분 은 상부 프로그램 에 보이 지 않 습 니 다.
    프레임 구 조 를 보면 소스 코드 에서 ICamera Service. h, ICamera Client. h 와 ICamera. h 세 가지 유형 은 MeidaPlayer 의 인터페이스 와 구 조 를 정 의 했 고 ICamera Service. cpp 와 Camera. cpp 두 파일 은 Camera 구조의 실현 에 사용 되 었 으 며 Camera 의 구체 적 인 기능 은 하부 에서 하드웨어 와 관련 된 인 터 페 이 스 를 호출 하여 실현 되 었 다.
Camera 의 전체적인 구조 에서 클래스 Camera 는 전체 시스템 의 핵심 이 고 ICamera 류 는 Camera 의 주요 기능 인 터 페 이 스 를 제공 하여 클 라 이언 트 에서 호출 합 니 다.CameraService 는 Camera 서비스 로 실제 Camera 하드웨어 인 터 페 이 스 를 호출 하여 기능 을 실현 합 니 다.사실 그림 에서 빨간색 점선 상자 의 부분 은 모두 Camera 프로그램의 프레임 부분 으로 주로 안 드 로 이 드 시스템 의 Binder 체 제 를 이용 하여 통신 을 완성 했다.파란색 부분 은 Camera 하드웨어 와 관련 된 인 터 페 이 스 를 호출 하여 구체 적 인 Camera 서비스 기능 을 완성 하고 다른 부분 은 상층 의 JAVA 프로그램 에 JNI 인 터 페 이 스 를 제공 합 니 다.전체적인 구조 상 왼쪽 은 하나의 클 라 이언 트 로 볼 수 있 고 오른쪽 은 서버 로 볼 수 있 으 며 두 사람 은 Android 의 Bimder 를 통 해 프로 세 스 간 의 통신 을 실현 할 수 있 습 니 다.
2. Camera 작업 절차 개술
1. 카메라 서비스의 시작
①.App_main process: 프로 세 스 가 AndroidRuntime 을 통 해 register 를 호출 합 니 다.jni_procs 는 JNI 등록 모듈 의 native 함수 에 JVM 호출 을 제공 합 니 다.
AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",
camMethods, NELEM(camMethods));
        그 중에서 camMethods 는 다음 과 같이 정의 합 니 다. 
   
   
   
   
  1. static JNINativeMethod camMethods[] = { 
  2.  
  3.   { "native_setup"
  4.  
  5.     "(Ljava/lang/Object;)V"
  6.  
  7.     (void*)android_hardware_Camera_native_setup }, 
  8.  
  9.   { "native_release"
  10.  
  11.     "()V"
  12.  
  13.     (void*)android_hardware_Camera_release }, 
  14.  
  15.   { "setPreviewDisplay"
  16.  
  17.     "(Landroid/view/Surface;)V"
  18.  
  19.     (void *)android_hardware_Camera_setPreviewDisplay }, 
  20.  
  21.   { "startPreview"
  22.  
  23.     "()V"
  24.  
  25.     (void *)android_hardware_Camera_startPreview }, 
  26.  
  27.   { "stopPreview"
  28.  
  29.     "()V"
  30.  
  31.     (void *)android_hardware_Camera_stopPreview }, 
  32.  
  33.   { "previewEnabled"
  34.  
  35.     "()Z"
  36.  
  37.     (void *)android_hardware_Camera_previewEnabled }, 
  38.  
  39.   { "setHasPreviewCallback"
  40.  
  41.     "(ZZ)V"
  42.  
  43.     (void *)android_hardware_Camera_setHasPreviewCallback }, 
  44.  
  45.   { "native_autoFocus"
  46.  
  47.     "()V"
  48.  
  49.     (void *)android_hardware_Camera_autoFocus }, 
  50.  
  51.   { "native_takePicture"
  52.  
  53.     "()V"
  54.  
  55.     (void *)android_hardware_Camera_takePicture }, 
  56.  
  57.   { "native_setParameters"
  58.  
  59.     "(Ljava/lang/String;)V"
  60.  
  61.     (void *)android_hardware_Camera_setParameters }, 
  62.  
  63.   { "native_getParameters"
  64.  
  65.     "()Ljava/lang/String;"
  66.  
  67.     (void *)android_hardware_Camera_getParameters }, 
  68.  
  69.   { "reconnect"
  70.  
  71.     "()V"
  72.  
  73.     (void*)android_hardware_Camera_reconnect }, 
  74.  
  75.   { "lock"
  76.  
  77.     "()I"
  78.  
  79.     (void*)android_hardware_Camera_lock }, 
  80.  
  81.   { "unlock"
  82.  
  83.     "()I"
  84.  
  85.     (void*)android_hardware_Camera_unlock }, 
  86.  
  87. }; 

JNINativeMethod 의 첫 번 째 구성원 은 문자열 로 JAVA 로 컬 호출 방법의 이름 을 표시 합 니 다. 이 이름 은 JAVA 프로그램 에서 호출 된 이름 입 니 다.두 번 째 멤버 도 JAVA 로 컬 호출 방법의 인자 와 반환 값 을 나타 내 는 문자열 입 니 다.세 번 째 멤버 는 JAVA 로 컬 호출 방법 에 대응 하 는 C 언어 함수 입 니 다.
②. Mediaserver proces: 프로 세 스 는 다음 과 같은 서버 를 등 록 했 습 니 다: AudioFlinger, MediaPlayer Server, Camera Service. 
   
   
   
   
  1. int main(int argc, char** argv) 
  2.  
  3.  
  4.     sp proc(ProcessState::self()); 
  5.  
  6.     sp sm = defaultServiceManager(); 
  7.  
  8.     LOGI("ServiceManager: %p", sm.get()); 
  9.  
  10.     AudioFlinger::instantiate(); 
  11.  
  12.     MediaPlayerService::instantiate(); 
  13.  
  14.     CameraService::instantiate(); 
  15.  
  16.     ProcessState::self()->startThreadPool(); 
  17.  
  18.     IPCThreadState::self()->joinThreadPool(); 
  19.  

 ServiceManager 에 CameraService 서 비 스 를 등록 하면 client 의 요청 에 응답 할 수 있 습 니 다.
2. client 단 에서 service 에 요청 보 내기
①. 자바 응용 층 에서 onCreate () 함 수 를 호출 하여 상부 의 카메라 대상 을 얻는다. 
   
   
   
   
  1. public void onCreate(Bundle icicle) { 
  2.  
  3. super.onCreate(icicle); 
  4.  
  5. Thread openCameraThread = new Thread( 
  6.  
  7. new Runnable() { 
  8.  
  9. public void run() { 
  10.  
  11.                 mCameraDevice = android.hardware.Camera.open(); 
  12.  
  13.  
  14.  
  15. ); 
  16.  
  17. ……………………… 
  18.  
  19. }     

②. Camera 대상 을 통 해 구성원 함 수 를 호출 하고, 이 구성원 함 수 는 JNI 에 등 록 된 native 함 수 를 호출 하여 ICamera 인터페이스의 구성원 함 수 를 Binder Kernel Driver 에 서비스 요청 을 보 냅 니 다.
③. Binder Kernel Driver 는 client 의 요청 을 받 은 후 service 를 깨 우 는 프로 세 스 를 통 해 client 의 요청 을 처리 하고 처리 후 리 셋 함수 로 데 이 터 를 전송 하 며 상부 처리 가 완료 되 었 음 을 알 립 니 다.
3. Camera 라 이브 러 리 파일 분석
    위 에서 언급 한 Camera 모듈 은 주로 libandroid 를 포함 합 니 다.runtime. so, libui. so, libcameraservice. so 와 Camera 하드웨어 와 관련 된 바 텀 라 이브 러 리 입 니 다.그 중 libandroidruntime. so, libui. so 는 안 드 로 이 드 시스템 구조 와 관련 된 것 으로 수정 할 필요 가 없습니다. libcameraservice. so 와 Camera 하드웨어 와 관련 된 바 텀 라 이브 러 리 는 하드웨어 장치 와 관련 된 것 이 고 Canera 하드웨어 와 관련 된 바 텀 라 이브 러 리 는 실제 적 으로 장치 의 Linux 구동 입 니 다.그래서 Camera 장치 의 시스템 통합 은 주로 Camera Linux 드라이브 를 이식 하고 libcameraservice. so 라 이브 러 리 를 수정 하여 이 루어 집 니 다.
    libcameraservice. so 라 이브 러 리 는 다음 규칙 을 통 해 구축 합 니 다. 
   
   
   
   
  1. LOCAL_PATH:= $(call my-dir) 
  2.  
  3.  
  4. Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want 
  5.  
  6. # the camera service to use the fake camera.  For emulator or simulator builds, 
  7.  
  8. # we always use the fake camera. 
  9.  
  10. ifeq ($(USE_CAMERA_STUB),) 
  11.  
  12. USE_CAMERA_STUB:=false 
  13.  
  14. ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),) 
  15.  
  16. USE_CAMERA_STUB:=true 
  17.  
  18. endif #libcamerastub 
  19.  
  20. endif ifeq ($(USE_CAMERA_STUB),true
  21.  
  22.  
  23. # libcamerastub 
  24.  
  25.  
  26. include $(CLEAR_VARS) 
  27.  
  28. LOCAL_SRC_FILES:=               \ 
  29.  
  30.     CameraHardwareStub.cpp      \ 
  31.  
  32.     FakeCamera.cpp 
  33.  
  34. LOCAL_MODULE:= libcamerastub 
  35.  
  36. LOCAL_SHARED_LIBRARIES:= libui 
  37.  
  38. include $(BUILD_STATIC_LIBRARY) 
  39.  
  40. endif # USE_CAMERA_STUB 
  41.  
  42.  
  43. # libcameraservice 
  44.  
  45.  
  46. include $(CLEAR_VARS) 
  47.  
  48. LOCAL_SRC_FILES:=               \ 
  49.  
  50.     CameraService.cpp 
  51.  
  52. LOCAL_SHARED_LIBRARIES:= \ 
  53.  
  54.     libui \ 
  55.  
  56.     libutils \ 
  57.  
  58.     libcutils \ 
  59.  
  60.     libmedia 
  61.  
  62. LOCAL_MODULE:= libcameraservice 
  63.  
  64. LOCAL_CFLAGS+=-DLOG_TAG=\"CameraService\" 
  65.  
  66. ifeq ($(USE_CAMERA_STUB), true
  67.  
  68. LOCAL_STATIC_LIBRARIES += libcamerastub 
  69.  
  70. LOCAL_CFLAGS += -include CameraHardwareStub.h 
  71.  
  72. else 
  73.  
  74. LOCAL_SHARED_LIBRARIES += libcamera 
  75.  
  76. endif 
  77.  
  78. include $(BUILD_SHARED_LIBRARY) 

     위의 구축 규칙 에서 매크로 USE 를 사용 한 것 을 볼 수 있 습 니 다.CAMERA_STUB 는 진짜 카 메 라 를 사용 할 지 여 부 를 결정 하고 매크로 가 사실 이 라면 CameraHardware Stub. cpp 와 FakeCamera. cpp 를 사용 하여 가짜 카 메 라 를 만 들 고, 가짜 라면 libcamera 를 사용 하여 실제 카메라 서 비 스 를 만 듭 니 다.
    CameraHardware Stub. cpp 에서 CameraHardware Stub 류 를 정 의 했 습 니 다. 추상 적 인 카메라 Hardware 인터페이스 에서 정 의 된 Camera 장 치 를 진정 으로 조작 하 는 모든 순 허 함 수 를 계승 하고 실현 합 니 다.openCameraHardware () 를 통 해 CameraHardware Interface 류 의 대상 을 되 돌려 줍 니 다. 그러나 CameraHardware Interface 류 는 추상 류 이기 때문에 대상 을 만 들 수 없습니다. 파생 류 CameraHardware Stub 는 부모 류 의 순 허 함 수 를 완전히 실현 하기 때문에 openCameraHardware () 는 파생 류 대상 을 가리 키 는 기본 지침 을 바 텀 장치 작업 에 사용 합 니 다.Camera Hardware Stub 클래스 가 정의 하 는 함 수 는 가짜 Camera 를 조작 하 는 것 이기 때문에 openCamera Hardware 를 통 해 돌아 오 는 지침 은 주로 환경 이 Camera 에 대한 시 뮬 레이 션 작업 에 사 용 됩 니 다. openCamera Hardware 를 통 해 돌아 오 는 지침 을 통 해 실제 하드웨어 장 치 를 조작 하려 면 다음 단계 가 필요 합 니 다.
1.    CameraHardware 인터페이스 클래스 의 모든 순 허 함수 성명 을 허 함수 성명 으로 변경 합 니 다 (즉, 허 함수 성명 을 제거 한 후의 "= 0"). 
   
   
   
   
  1. class CameraHardwareInterface : public virtual RefBase { 
  2.  
  3. public
  4.  
  5.     virtual ~CameraHardwareInterface() { } 
  6.  
  7.     virtual sp         getPreviewHeap() const
  8.  
  9.     virtual sp         getRawHeap() const
  10.  
  11.     virtual status_t    startPreview(preview_callback cb, void* user); 
  12.  
  13.     virtual bool useOverlay() {return false;} 
  14.  
  15.     virtual status_t setOverlay(const sp &overlay) {return BAD_VALUE;} 
  16.  
  17.     virtual void        stopPreview(); 
  18.  
  19.     virtual bool        previewEnabled(); 
  20.  
  21.     virtual status_t    startRecording(recording_callback cb, void* user); 
  22.  
  23.     virtual void        stopRecording(); 
  24.  
  25.     virtual bool        recordingEnabled(); 
  26.  
  27.     virtual void        releaseRecordingFrame(const sp& mem); 
  28.  
  29.     virtual status_t    autoFocus(autofocus_callback, 
  30.  
  31.                                   void* user); 
  32.  
  33.   
  34.  
  35.     virtual status_t    takePicture(shutter_callback, 
  36.  
  37.                                     raw_callback, 
  38.  
  39.                                     jpeg_callback, 
  40.  
  41.                                     void* user); 
  42.  
  43.     virtual status_t    cancelPicture(bool cancel_shutter, 
  44.  
  45.                                       bool cancel_raw, 
  46.  
  47.                                       bool cancel_jpeg); 
  48.  
  49.     virtual status_t    setParameters(const CameraParameters& params); 
  50.  
  51.     virtual CameraParameters  getParameters() const
  52.  
  53.     virtual void release(); 
  54.  
  55.     virtual status_t dump(int fd, const Vector& args) const ; 
  56.  
  57. }; 

2.    CameraHardware 인터페이스 클래스 에서 설명 한 모든 가상 함 수 를 정의 하기 위해 원본 파일 을 만 들 고 openCameraHardware () 함 수 를 실현 하여 이 함 수 를 CameraHardware 인터페이스 클래스 대상 의 지침 으로 되 돌려 줍 니 다.예 를 들 면: 
   
   
   
   
  1. extern "C" sp openCameraHardware() 
  2.  
  3.  
  4.     CameraHardwareInterface realCamera; 
  5.  
  6.     return &realCamera; 
  7.  

3.    다른. mk 파일 을 본 떠 서 Android. mk 파일 을 작성 하여 2 단계 로 작 성 된 원본 파일 과 다른 관련 파일 을 포함 하 는 libcamera. so 파일 을 만 드 는 데 사용 합 니 다.예컨대 
   
   
   
   
  1. LOCAL_PATH := $(call my-dir) 
  2.  
  3. include $(CLEAR_VARS) 
  4.  
  5. LOCAL_MODULE := libcamera 
  6.  
  7. LOCAL_SHARED_LIBRARIES := \ 
  8.  
  9.     libutils \ 
  10.  
  11.     librpc \ 
  12.  
  13.     liblog 
  14.  
  15. LOCAL_SRC_FILES += MyCameraHardware.cpp 
  16.  
  17. LOCAL_CFLAGS += 
  18.  
  19. LOCAL_C_INCLUDES += 
  20.  
  21. LOCAL_STATIC_LIBRARIES += \ 
  22.  
  23.     libcamera-common \ 
  24.  
  25.     libclock-rpc \ 
  26.  
  27.     libcommondefs-rpc 
  28.  
  29. include $(BUILD_SHARED_LIBRARY) 

4.    장 홍 USECAMERA_STUB 를 false 로 변경 하면 libcameraservice. so 를 생 성 할 때 libcamera. so 라 이브 러 리 가 포 함 됩 니 다.(비고: CameraHardware 인터페이스 류 의 구성원 함수 가 하드웨어 를 직접 조작 하지 않 고 Camera 의 Liux 드라이브 를 호출 하여 하드웨어 를 간접 적 으로 조작 한다 면 이러한 CameraHardware 인터페이스 류 를 포함 한 libcamera. so 라 이브 러 리 는 HAL 에 해당 합 니 다)
      위의 왼쪽 그림 에서 libcamera. so 라 이브 러 리 는 Camera 장 치 를 직접 조작 합 니 다. 이렇게 하면 오른쪽 그림 에 비해 libcamera. so 라 이브 러 리 는 Camera 구동 을 포함 하고 오른쪽 그림 은 구동 을 라 이브 러 리 에서 분리 하여 HAL 을 형성 하 는 것 이 좋 습 니 다. 서로 다른 모델 이나 서로 다른 업 체 의 같은 장 치 를 이식 할 때 HAL 의 코드 가 적 으 면 됩 니 다.

좋은 웹페이지 즐겨찾기