Android 에서 카메라 분석
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 는 다음 과 같이 정의 합 니 다.
- static JNINativeMethod camMethods[] = {
-
- { "native_setup",
-
- "(Ljava/lang/Object;)V",
-
- (void*)android_hardware_Camera_native_setup },
-
- { "native_release",
-
- "()V",
-
- (void*)android_hardware_Camera_release },
-
- { "setPreviewDisplay",
-
- "(Landroid/view/Surface;)V",
-
- (void *)android_hardware_Camera_setPreviewDisplay },
-
- { "startPreview",
-
- "()V",
-
- (void *)android_hardware_Camera_startPreview },
-
- { "stopPreview",
-
- "()V",
-
- (void *)android_hardware_Camera_stopPreview },
-
- { "previewEnabled",
-
- "()Z",
-
- (void *)android_hardware_Camera_previewEnabled },
-
- { "setHasPreviewCallback",
-
- "(ZZ)V",
-
- (void *)android_hardware_Camera_setHasPreviewCallback },
-
- { "native_autoFocus",
-
- "()V",
-
- (void *)android_hardware_Camera_autoFocus },
-
- { "native_takePicture",
-
- "()V",
-
- (void *)android_hardware_Camera_takePicture },
-
- { "native_setParameters",
-
- "(Ljava/lang/String;)V",
-
- (void *)android_hardware_Camera_setParameters },
-
- { "native_getParameters",
-
- "()Ljava/lang/String;",
-
- (void *)android_hardware_Camera_getParameters },
-
- { "reconnect",
-
- "()V",
-
- (void*)android_hardware_Camera_reconnect },
-
- { "lock",
-
- "()I",
-
- (void*)android_hardware_Camera_lock },
-
- { "unlock",
-
- "()I",
-
- (void*)android_hardware_Camera_unlock },
-
- };
JNINativeMethod 의 첫 번 째 구성원 은 문자열 로 JAVA 로 컬 호출 방법의 이름 을 표시 합 니 다. 이 이름 은 JAVA 프로그램 에서 호출 된 이름 입 니 다.두 번 째 멤버 도 JAVA 로 컬 호출 방법의 인자 와 반환 값 을 나타 내 는 문자열 입 니 다.세 번 째 멤버 는 JAVA 로 컬 호출 방법 에 대응 하 는 C 언어 함수 입 니 다.
②. Mediaserver proces: 프로 세 스 는 다음 과 같은 서버 를 등 록 했 습 니 다: AudioFlinger, MediaPlayer Server, Camera Service.
- int main(int argc, char** argv)
-
- {
-
- sp
proc(ProcessState::self());
-
- sp
sm = defaultServiceManager();
-
- LOGI("ServiceManager: %p", sm.get());
-
- AudioFlinger::instantiate();
-
- MediaPlayerService::instantiate();
-
- CameraService::instantiate();
-
- ProcessState::self()->startThreadPool();
-
- IPCThreadState::self()->joinThreadPool();
-
- }
ServiceManager 에 CameraService 서 비 스 를 등록 하면 client 의 요청 에 응답 할 수 있 습 니 다.
2. client 단 에서 service 에 요청 보 내기
①. 자바 응용 층 에서 onCreate () 함 수 를 호출 하여 상부 의 카메라 대상 을 얻는다.
- public void onCreate(Bundle icicle) {
-
- super.onCreate(icicle);
-
- Thread openCameraThread = new Thread(
-
- new Runnable() {
-
- public void run() {
-
- mCameraDevice = android.hardware.Camera.open();
-
- }
-
- }
-
- );
-
- ………………………
-
- }
②. 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 라 이브 러 리 는 다음 규칙 을 통 해 구축 합 니 다.
- LOCAL_PATH:= $(call my-dir)
-
- #
-
- # Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want
-
- # the camera service to use the fake camera. For emulator or simulator builds,
-
- # we always use the fake camera.
-
- ifeq ($(USE_CAMERA_STUB),)
-
- USE_CAMERA_STUB:=false
-
- ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
-
- USE_CAMERA_STUB:=true
-
- endif #libcamerastub
-
- endif ifeq ($(USE_CAMERA_STUB),true)
-
- #
-
- # libcamerastub
-
- #
-
- include $(CLEAR_VARS)
-
- LOCAL_SRC_FILES:= \
-
- CameraHardwareStub.cpp \
-
- FakeCamera.cpp
-
- LOCAL_MODULE:= libcamerastub
-
- LOCAL_SHARED_LIBRARIES:= libui
-
- include $(BUILD_STATIC_LIBRARY)
-
- endif # USE_CAMERA_STUB
-
- #
-
- # libcameraservice
-
- #
-
- include $(CLEAR_VARS)
-
- LOCAL_SRC_FILES:= \
-
- CameraService.cpp
-
- LOCAL_SHARED_LIBRARIES:= \
-
- libui \
-
- libutils \
-
- libcutils \
-
- libmedia
-
- LOCAL_MODULE:= libcameraservice
-
- LOCAL_CFLAGS+=-DLOG_TAG=\"CameraService\"
-
- ifeq ($(USE_CAMERA_STUB), true)
-
- LOCAL_STATIC_LIBRARIES += libcamerastub
-
- LOCAL_CFLAGS += -include CameraHardwareStub.h
-
- else
-
- LOCAL_SHARED_LIBRARIES += libcamera
-
- endif
-
- 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").
- class CameraHardwareInterface : public virtual RefBase {
-
- public:
-
- virtual ~CameraHardwareInterface() { }
-
- virtual sp
getPreviewHeap() const;
-
- virtual sp
getRawHeap() const;
-
- virtual status_t startPreview(preview_callback cb, void* user);
-
- virtual bool useOverlay() {return false;}
-
- virtual status_t setOverlay(const sp
&overlay) { return BAD_VALUE;}
-
- virtual void stopPreview();
-
- virtual bool previewEnabled();
-
- virtual status_t startRecording(recording_callback cb, void* user);
-
- virtual void stopRecording();
-
- virtual bool recordingEnabled();
-
- virtual void releaseRecordingFrame(const sp
& mem);
-
- virtual status_t autoFocus(autofocus_callback,
-
- void* user);
-
-
-
- virtual status_t takePicture(shutter_callback,
-
- raw_callback,
-
- jpeg_callback,
-
- void* user);
-
- virtual status_t cancelPicture(bool cancel_shutter,
-
- bool cancel_raw,
-
- bool cancel_jpeg);
-
- virtual status_t setParameters(const CameraParameters& params);
-
- virtual CameraParameters getParameters() const;
-
- virtual void release();
-
- virtual status_t dump(int fd, const Vector
& args) const ;
-
- };
2. CameraHardware 인터페이스 클래스 에서 설명 한 모든 가상 함 수 를 정의 하기 위해 원본 파일 을 만 들 고 openCameraHardware () 함 수 를 실현 하여 이 함 수 를 CameraHardware 인터페이스 클래스 대상 의 지침 으로 되 돌려 줍 니 다.예 를 들 면:
- extern "C" sp
openCameraHardware()
-
- {
-
- CameraHardwareInterface realCamera;
-
- return &realCamera;
-
- }
3. 다른. mk 파일 을 본 떠 서 Android. mk 파일 을 작성 하여 2 단계 로 작 성 된 원본 파일 과 다른 관련 파일 을 포함 하 는 libcamera. so 파일 을 만 드 는 데 사용 합 니 다.예컨대
- LOCAL_PATH := $(call my-dir)
-
- include $(CLEAR_VARS)
-
- LOCAL_MODULE := libcamera
-
- LOCAL_SHARED_LIBRARIES := \
-
- libutils \
-
- librpc \
-
- liblog
-
- LOCAL_SRC_FILES += MyCameraHardware.cpp
-
- LOCAL_CFLAGS +=
-
- LOCAL_C_INCLUDES +=
-
- LOCAL_STATIC_LIBRARIES += \
-
- libcamera-common \
-
- libclock-rpc \
-
- libcommondefs-rpc
-
- 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 의 코드 가 적 으 면 됩 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
양식 제출 후 제출 버튼 비활성화텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.