Camera HAL層代碼分析1

Camera HAL層的基類是CameraHardwareInterface,主要定義在CameraHardwareInterface.h中。OEM廠商可以根據需要實現CameraHardwareInterface,根據需要實現CameraHardwareInterface定義的接口。

目前查閱的android source code,沒有按照google定義的規範和標準,而是自定義了一個CameraHAL類,以此類作爲基類,代替CameraHardwareInterface。對於Cameraid=0的業務邏輯,主要實現是在CameraHardware中,此類實現CameraHAL中定義的函數。因此解析來首先分析CameraHardware類。

 

CameraHardware的構造函數中,一開始調用:

initDefaultParameters();       


此類的實現如下:

/**
 Init default parameters
 */
void CameraHardware::initDefaultParameters() {
	//#ifndef NEON_MFEALIG64
	const mmap_info_t * MmapPhyBuffInfo = NULL;
	//#endif

	CameraParameters &p = mParameters;

	mWidth = MIN_WIDTH;  //640
	mHeight = MIN_HEIGHT;  //480

	mPictureWidth = MIN_WIDTH;
	mPictureHeight = MIN_HEIGHT;

	p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT);
	p.setPreviewFrameRate(30);
	p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
	p.setPictureFormat("jpeg");
	p.setPictureSize(MIN_WIDTH, MIN_HEIGHT);
	p.setVideoSize(MIN_WIDTH, MIN_HEIGHT);

從此類中可以看到,camera預覽的默認寬高是640和480,分別定義在CameraHardware.h中。preview的默認格式爲YUV420SP,api可以設置preview的格式,不知道是否起作用,默認爲YUV420SP,看起來在這裏可以進行修改。preview的默認幀率爲30fps,圖像的默認格式爲jpeg。(不懂這裏jpeg是什麼意思,可能與java層定義對應,後續研究)

 

構造函數中,初始化默認參數後,會實例化:

if (!mCamera) {
    delete mCamera;
    mCamera = new V4L2Camera();
}

V4L2Camera是一個獨立的類,實現Camera部分功能。

 

total = scandir("/dev", &namelist, my_select, 0);


這一行是掃描camera device。

scandir將掃描/dev目錄,將掃描的結果存放在namelist中,掃描的filter是my_select,返回非0的值存放在namelist中。

static int my_select(const struct dirent *dp) {
     if (strstr(dp->d_name, "video"))
        return 1;
     return 0;
}

即/dev/video*的文件會放在namelist中。返回值total爲掃描到的條目。

 

if (total > 0) {
		for (int i = 0; i < 3; i++) {
			snprintf(video_dev, 7, "video%d", i);
			found = 0;
			for (int j = 0; j < total; j++) {
				if (strcmp(video_dev, namelist[j]->d_name) == 0) {
					ALOGI("found camera dev = %s", namelist[j]->d_name);
					found = 1;
					break;
				}
			}

			if (found == 1)
				break;
		}

		while (total--)
			free(namelist[total]);

		free(namelist);
	}

	if (found == 1)
		snprintf(mCameraDev, 12, "/dev/%s", video_dev);
	else
		snprintf(mCameraDev, 12, "%s", VIDEO_DEVICE);

	fd = mCamera->Open(mCameraDev);

	if (fd == -1) {
		ALOGE("Camera device %s open failed.", mCameraDev);
		//return UNKNOWN_ERROR;
		mCameraOpened = false;
	}

以上代碼只會找vede0的目錄,找到即退出尋找。並且賦值mCameraDev爲/dev/video0,然後調用V4L2Camera的open函數,打開/dev/video0設備。

 

在java層調用Camera.open函數,抓取的log信息如下:

	Line 721: I/CameraClient( 1048): Opening camera 0
	Line 721: I/CameraClient( 1048): Opening camera 0
	Line 722: I/CameraHAL( 1048): camera_device open
	Line 722: I/CameraHAL( 1048): camera_device open
	Line 723: D/CameraHAL( 1048): create camerahardware ============
	Line 723: D/CameraHAL( 1048): create camerahardware ============
	Line 724: I/CameraHardware( 1048): found camera dev = video0
	Line 724: I/CameraHardware( 1048): found camera dev = video0
	Line 725: I/CameraHardware( 1048): Got m720pSupported !!!!!
	Line 726: I/CameraHardware( 1048): KEY_PREVIEW_FPS_RANGE 1000 ~ 45000
	Line 727: E/V4L2Camera( 1048): GetPixelFormat
	Line 728: E/V4L2Camera( 1048):     Came[ 1060.109414] Mstar-xhci-1 Mstar-xhci-1.0: WARN: transfer error on endpoint
	Line 730: E/V4L2Camera( 1048):     Camera Supported Format : YUYV
	Line 730: E/V4L2Camera( 1048):     Camera Supported Format : YUYV
	Line 731: E/V4L2Camera( 1048):     Selected Camera Format : YUYV
	Line 731: E/V4L2Camera( 1048):     Selected Camera Format : YUYV
	Line 732: E/V4L2Camera( 1048): Camera supported picture resolution : 1280x720,352x288,320x240,176x144,160x120,640x480
	Line 732: E/V4L2Camera( 1048): Camera supported picture resolution : 1280x720,352x288,320x240,176x144,160x120,640x480

即在java層調用open函數,會走到CameraHardware的構造函數。

 

#if YUV_DATA_ONLY
	if (mCamera->tryParameters(WIDTH_720P, HEIGHT_720P, V4L2_PIX_FMT_YUYV))
#else
	if (mCamera->tryParameters(WIDTH_720P, HEIGHT_720P, V4L2_PIX_FMT_MJPEG))
#endif
			{
		m720pSupported = false;
		mImageFormat = V4L2_PIX_FMT_YUYV;

		ret = mCamera->setParameters(mWidth, mHeight, mImageFormat);
		if (ret) {
			ALOGE("Camera setParameters failed: %s", strerror(errno));
			//return UNKNOWN_ERROR;
			mCameraOpened = false;
		}
	} else {
		m720pSupported = true;
#if YUV_DATA_ONLY
		mImageFormat = V4L2_PIX_FMT_YUYV;
#else
		mImageFormat = V4L2_PIX_FMT_MJPEG;
#endif
		mWidth = WIDTH_720P;
		mHeight = HEIGHT_720P;

		if (mbAIT8431) {
			if (mAitXuHandle) {
				SkypeXU_Release(&mAitXuHandle);
			}
			mAitXuHandle = SkypeXU_Init(fd);
			SkypeXU_SetMode(mAitXuHandle, 2);
			ret = SkypeXU_SetEncRes(mAitXuHandle, SKYPE_H264_1280X720);
			if (ret < 0) {
				ALOGE("Failed to select resolution \r\n");
			}
		}

		ret = mCamera->setParameters(mWidth, mHeight, mImageFormat);

		if (ret) {
			ALOGE("Camera setParameters failed: %s", strerror(errno));
			//return UNKNOWN_ERROR;
			mCameraOpened = false;
		}
	}

這段代碼主要是判定camera是否支持720P,如果不支持,看起來格式否是YUYV。如果支持720P,可以是MJPEG或YUYV。

/**
 Set supported parameters
 */
void CameraHardware::insertSupportedParams() {
	CameraParameters &p = mParameters;
	String8 previewColorString;

	previewColorString = CameraParameters::PIXEL_FORMAT_YUV420SP;
	previewColorString.append(",");
	previewColorString.append(CameraParameters::PIXEL_FORMAT_YUV420P);
	previewColorString.append(",");
	previewColorString.append(CameraParameters::PIXEL_FORMAT_YUV422I);

	if (m720pSupported) {
		ALOGI("Got m720pSupported !!!!!");
		if (mbAIT8431) {
			p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
					"352x288,384x216,320x240,176x144");
			p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
					"352x288,384x216,320x240,176x144");
			p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
					"1280x720,640x480,352x288,384x216,320x240,176x144,160x120");
			p.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
					"384x216");
			p.setVideoSize(WIDTH_720P, HEIGHT_720P);
			p.setPreviewSize(384, 216);
			p.setPictureSize(384, 216);
			// update video format to avc
			p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
					CameraParameters::PIXEL_FORMAT_AVC);
		} else {
			if (mJpegDecoder.is1080pSupport()) {
				p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
						"1920x1080,1280x720,640x480,352x288,384x216,320x240,176x144");
				p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
						"1920x1080,1280x720,640x480,352x288,384x216,320x240,176x144");
				p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
						"1920x1080,1280x720,640x480,352x288,384x216,320x240,176x144,160x120");
			} else {
				p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
						"1280x720,640x480,352x288,384x216,320x240,176x144");
				p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
						"1280x720,640x480,352x288,384x216,320x240,176x144");
				p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
						"1280x720,640x480,352x288,384x216,320x240,176x144,160x120");
			}

			p.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
					"1280x720");
			p.setVideoSize(WIDTH_720P, HEIGHT_720P);
			p.setPreviewSize(WIDTH_720P, HEIGHT_720P);
			p.setPictureSize(WIDTH_720P, HEIGHT_720P);
		}
	} else {
		p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
				"640x480,352x288,384x216,320x240,176x144");
		p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
				"640x480,352x288,384x216,320x240,176x144");
		p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
				"640x480,352x288,384x216,320x240,176x144,160x120");
		p.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
				"640x480");
	}

	p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, "auto");
	p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
			previewColorString.string());
	p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, "jpeg");
	p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "auto");
	//p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "30");
	p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, "160x120,0x0");
	p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, "auto");
	p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, "none");
	p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, "auto");
	p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(1000,45000)"); //(1000,33000)
	p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "1000,45000"); //"1000,33000"
	p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "51.2");
	p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "39.4");

	// set preview frame rate according to KEY_PREVIEW_FPS_RANGE
	int min_fps = 0, max_fps = 0;
	char supportedFrameRates[256], fps_value[10];

	p.getPreviewFpsRange(&min_fps, &max_fps);
	ALOGI("KEY_PREVIEW_FPS_RANGE %d ~ %d\n", min_fps, max_fps);
	if ((min_fps >= max_fps) || (min_fps <= 0) || (max_fps <= 0)) {
		// default 1~30fps
		min_fps = 1000;
		max_fps = 30000;
	}
	min_fps /= 1000;
	max_fps /= 1000;
	memset(supportedFrameRates, 0, sizeof(supportedFrameRates));
	for (int i = min_fps; i <= max_fps; i++) {
		sprintf(fps_value, "%d", i);
		strcat(supportedFrameRates, fps_value);
		if (i != max_fps)
			strcat(supportedFrameRates, ",");
	}
	p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
			supportedFrameRates);

	/*p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING, "auto");
	 p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "");
	 p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "");
	 p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "");
	 p.set(CameraParameters::KEY_ZOOM_RATIOS, "");
	 p.set(CameraParameters::KEY_MAX_ZOOM, "");
	 p.set(CameraParameters::KEY_ZOOM_SUPPORTED, "");
	 p.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, "");
	 p.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED, "");
	 p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "");
	 p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, "");
	 p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, "");
	 p.set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, "");*/
}

這個函數主要是講我們支持那些顏色格式,camera的分辨率。

 

int V4L2Camera::Open (const char *device)
{
    int ret;

    if ((fd = open(device, O_RDWR)) == -1) {
        ALOGE("ERROR opening V4L interface: %s", strerror(errno));
        return -1;
    }

    ret = ioctl (fd, VIDIOC_QUERYCAP, &videoIn->cap);
    if (ret < 0) {
        ALOGE("Error opening device: unable to query device.");
        return -1;
    }

    if ((videoIn->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
        ALOGE("Error opening device: video capture not supported.");
        return -1;
    }

    if (!(videoIn->cap.capabilities & V4L2_CAP_STREAMING)) {
        ALOGE("Capture device does not support streaming i/o");
        return -1;
    }

    return fd;
}

java層open主要調用到V4L2Camra的open函數,這個函數首先會打開/dev/video0,然後下命令給kernel,查詢device是否真的存在。最後查詢camera是否支持V4L2_CAP_VIDEO_CAPTURE和V4L2_CAP_STREAMING。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章