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。