android2.3.4----6.camera与上层的交互

对于android下的camera有如下文件
java层:
./frameworks/base/core/java/android/hardware/Sensor.java
./frameworks/base/core/java/android/hardware/SensorEvent.java
./frameworks/base/core/java/android/hardware/SensorEventListener.java
./frameworks/base/core/java/android/hardware/SensorListener.java
./frameworks/base/core/java/android/hardware/SensorManager.java
./frameworks/base/core/java/android/hardware/Camera.java

libandroid_runtime.so:
./frameworks/base/core/jni/android_hardware_Camera.cpp
./frameworks/base/core/jni/android_hardware_SensorManager.cpp

libcamera_client.so:
./frameworks/base/libs/camera/ICamera.cpp
./frameworks/base/libs/camera/ICameraClient.cpp
./frameworks/base/libs/camera/ICameraService.cpp
./frameworks/base/libs/camera/Camera.cpp
./frameworks/base/libs/camera/CameraParameters.cpp

libcameraservice.so:
./frameworks/base/services/camera/libcameraservice/CameraService.cpp

libcamera.so:
./hardware/forlinx/libcamera/Ov965xCamera.cpp
./hardware/forlinx/libcamera/S3C6410CameraHardware.cpp
./hardware/forlinx/libcamera/USBCamera.cpp

一. camera的打开过程分析
1. java层调用jni的native_setup
在./frameworks/base/core/java/android/hardware/Camera.java中
native_setup(new WeakReference(this), cameraId);
1.1 jni层的native_setup
java
–> jni >>>libandroid_runtime.so
在./frameworks/base/core/jni/android_hardware_Camera.cpp中
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId)
{
sp camera = Camera::connect(cameraId); //调用libcamera_client层的connect
jclass clazz = env->GetObjectClass(thiz);
sp context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong(thiz);
camera->setListener(context);
env->SetIntField(thiz, fields.context, (int)context.get());
}
1.2 camera_client
java
–> jni >>>libandroid_runtime.so
–> libcamera_client.so
在./frameworks/base/libs/camera/Camera.cpp中
sp Camera::connect(int cameraId)
{
sp c = new Camera();
const sp& cs = getCameraService();
c->mCamera = cs->connect(c, cameraId); //调用CameraService的connect
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
}
1.3 cameraService
java
–> jni >>>libandroid_runtime.so
–> libcamera_client.so
–> libcameraservice.so
这个connect相当于注册的过程,生成client结构体注册在成员变量中
在./frameworks/base/services/camera/libcameraservice/CameraService.cpp中
sp CameraService::connect(const sp& cameraClient, int cameraId)
{
int callingPid = getCallingPid();
Mutex::Autolock lock(mServiceLock);
sp hardware = HAL_openCameraHardware(cameraId); //调用libCamera层的打开函数
CameraInfo info;
HAL_getCameraInfo(cameraId, &info); //调用libCamera层获取cameraInfo
client = new Client(this, cameraClient, hardware, cameraId, info.facing, callingPid); //初始化client
mClient[cameraId] = client; //并把client端保存在成员mClient中
return client;
}
1.4 libcamera
java
–> jni >>>libandroid_runtime.so
–> libcamera_client.so
–> libcameraservice.so
–> libCamera.so
在./hardware/forlinx/libcamera/S3C6410CameraHardware.cpp中
extern “C” sp HAL_openCameraHardware(int cameraId)
{
return CameraHardware::createInstance();
}
HAL_openCameraHardware
–> createInstance
在./hardware/forlinx/libcamera/S3C6410CameraHardware.cpp中
sp CameraHardware::createInstance()
{
return new CameraHardware();
}
HAL_openCameraHardware
–> createInstance
–> CameraHardware
在./hardware/forlinx/libcamera/S3C6410CameraHardware.cpp中
CameraHardware::CameraHardware()
{
mOv965xCamera = 0;
mUSBCamera = 0;
mCamType = probe_camera(); //1.4.1 查看Camera的类型
initDefaultParameters(); //1.4.2 将参数保存在成员变量mParameter中,并初始化摄像头
}
1.4.1 查看Camera的类型
HAL_openCameraHardware
–> createInstance
–> CameraHardware
–> probe_camera
查看Camera的类型(USB or CMOS)
先打开usbCamera, 如果没有找到再打开cmos_camera,再没找到返回NONE
在./hardware/forlinx/libcamera/S3C6410CameraHardware.cpp中
static int probe_camera()
{
int fd ;
fd = open(“/dev/video2”, O_RDWR | O_SYNC);
if(fd <= 0)
{
fd = open(“/dev/video0”, O_RDWR | O_SYNC);
if (fd <=0)
return CAMTYPE_NONE;
else
return CAMTYPE_CMOS;
}
else
{
close(fd);
return CAMTYPE_USB;
}
}
1.4.2 将默认参数保存在成员变量mParameter中,并初始化摄像头
HAL_openCameraHardware
–> createInstance
–> CameraHardware
–> initDefaultParameters
void CameraHardware::initDefaultParameters()
{
//设置默认参数
CameraParameters p;
p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, “320x240”);
p.setPreviewSize(320, 240);
p.setPreviewFrameRate(15);
p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);
p.set(CameraParameters::KEY_ROTATION, 90);

p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
p.setPictureSize(320, 240);
p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
//1.4.2.1将默认参数保存在成员变量mParameter中
setParameters(p);

}
1.4.2.1 保存参数,并初始化摄像头
HAL_openCameraHardware
–> createInstance
–> CameraHardware
–> initDefaultParameters
–> setParameters
status_t CameraHardware::setParameters(const CameraParameters& params)
{
Mutex::Autolock lock(mLock);
//… 跳过检查参数部分
//将参数保存在成员变量mParameters中
mParameters = params;

initHeapLocked();   //1.4.2.2 初始化摄像头

}
1.4.2.2 分配内存并初始化摄像头
HAL_openCameraHardware
–> createInstance
–> CameraHardware
–> initDefaultParameters
–> setParameters
–> initHeapLocked
void CameraHardware::initHeapLocked()
{
//为rawHeap分配内存,大小为: w*h*2(对于yuv420的w*h*1.5就够了)
int picture_width, picture_height;
mParameters.getPictureSize(&picture_width, &picture_height);
mRawHeap = new MemoryHeapBase(picture_width * picture_height * 2);

int preview_width, preview_height;
mParameters.getPreviewSize(&preview_width, &preview_height);

int how_big = preview_width * preview_height*2;
//为previewHeap分配内存,共4块,大小为: w*h*2(对于yuv420的w*h*1.5就够了)
mPreviewFrameSize = how_big;
mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
for (int i = 0; i < kBufferCount; i++) {
    mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
}
//如果在probe中检测到的摄像头类型为usb,则进行usb摄像头的初始化
if(mUSBCamera != 0)
{
    delete mUSBCamera;
    mUSBCamera = 0;
}
else if(mCamType == CAMTYPE_USB)    
    mUSBCamera = new USBCamera(preview_width, preview_height);
//如果在probe中检测到的摄像头类型为cmos,则进行cmos摄像头的初始化    
if(mOv965xCamera != 0)
{
    delete mOv965xCamera;
    mOv965xCamera = 0;  
}  //这儿为cmos摄像头,对cmos摄像头初始化
else if(mCamType == CAMTYPE_CMOS)    
    mOv965xCamera = new Ov965xCamera(preview_width, preview_height); 

}
libcamera.so:
在./hardware/forlinx/libcamera/Ov965xCamera.cpp中
Ov965xCamera::Ov965xCamera(int width, int height)
{
struct v4l2_format fmt;
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_fd = open(“/dev/video0”, O_RDWR | O_SYNC); //1.5.1open过程与驱动交互
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt); //1.5.2 ioctl的VIDIOC_S_FMT与驱动交互
ioctl(v4l2_fd, VIDIOC_STREAMON, &type); //1.5.3 ioctl的VIDIOC_STREAMON与驱动交互
setSize(width, height);
}
1.5 libCamera与驱动的交互
1.5.1 open 过程与驱动的交互
上层调用open(‘/dev/video0”)
–> 即调用v4l2_open
在drivers/media/video/v4l2-dev.c中
static int v4l2_open(struct inode *inode, struct file *filp)
{
mutex_lock(&videodev_lock);
struct video_device *vdev = video_devdata(filp);
video_get(vdev); //获取video_device结构体
mutex_unlock(&videodev_lock);

if (vdev->fops->open)
    vdev->fops->open(filp);          //调用s3c_fimc层的open函数
video_put(vdev);
return ret;

}
上层调用open(‘/dev/video0”)
–> 即调用v4l2_open >>> vdev->fops->open
–> s3c_fimc_open
在drivers/media/video/samsung/fimc/s3c_fimc_core.c中
static int s3c_fimc_open(struct file *filp)
{
struct s3c_fimc_control *ctrl;
int id, ret;
id =0;
ctrl = &s3c_fimc.ctrl[id]; //获取s3c_fimc_control结构体
mutex_lock(&ctrl->lock);
atomic_read(&ctrl->in_use);
atomic_inc(&ctrl->in_use); //引用计数加1
s3c_fimc_reset(ctrl);
filp->private_data = ctrl;
mutex_unlock(&ctrl->lock);
return 0;
}

1.5.2 ioctl 过程与驱动的交互
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
在drivers/media/video/v4l2-dev.c中
static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct video_device *vdev = video_devdata(filp);
int ret;
//如果s3c_fimc层有unlocked_ioctl就优先调用
if (vdev->fops->unlocked_ioctl)
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); //exec 1.5.2.1
else if (vdev->fops->ioctl) {
lock_kernel();
ret = vdev->fops->ioctl(filp, cmd, arg);
unlock_kernel();
} else
ret = -ENOTTY;
return ret;
}
在drivers/media/video/samsung/fimc/s3c_fimc_core.c中
static const struct v4l2_file_operations s3c_fimc_fops = {
.unlocked_ioctl = video_ioctl2,
};
1.5.2.1 调用video_device的ioctl
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2
在drivers/media/video/v4l2_ioctl.c中
long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg)
{
//跳过将用户空间的参数arg拷贝到内核空间部分
if (is_ext_ctrl) {
//这儿不是 ext_ctrl跳过
}
__video_do_ioctl(file, cmd, parg); //这个函数其实就是一个封装
}
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> V4L2_BUF_TYPE_VIDEO_CAPTURE
–> __video_do_ioctl
static long __video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vfd = video_devdata(file);
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
void *fh = file->private_data;
case VIDIOC_S_FMT:
{
struct v4l2_format f = (struct v4l2_format )arg;
switch (f->type)
{
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
CLEAR_AFTER_FIELD(f, fmt.pix);
v4l_print_pix_fmt(vfd, &f->fmt.pix);
if (ops->vidioc_s_fmt_vid_cap)
ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); //1.5.2.2ioctl设置参数
break;
}
}
}
}
1.5.2.2 ioctl设置参数
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> V4L2_BUF_TYPE_VIDEO_CAPTURE
–> __video_do_ioctl >> ops->video_s_fmt_vid_cap
–> s3c_fimc_v4l2_s_fmt_vid_cap
在drivers/media/video/samsung/fimc/s3c_fimc_v4l2.c中
static int s3c_fimc_v4l2_s_fmt_vid_cap(struct file *filp, void *fh, struct v4l2_format *f)
{
struct s3c_fimc_control ctrl = (struct s3c_fimc_control ) fh;
ctrl->v4l2.frmbuf.fmt = f->fmt.pix;

if (f->fmt.pix.priv == V4L2_FMT_IN)
    s3c_fimc_set_input_frame(ctrl, &f->fmt.pix);
else
    s3c_fimc_set_output_frame(ctrl, &f->fmt.pix);  //exec设置frame
return 0;

}
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> V4L2_BUF_TYPE_VIDEO_CAPTURE
–> __video_do_ioctl >> ops->video_s_fmt_vid_cap
–> s3c_fimc_v4l2_s_fmt_vid_cap
–> s3c_fimc_set_output_frame
在drivers/media/video/samsung/fimc/s3c_fimc_cfg.c中
int s3c_fimc_set_output_frame(struct s3c_fimc_control *ctrl, struct v4l2_pix_format *fmt)
{
struct s3c_fimc_out_frame *frame = &ctrl->out_frame;
int depth = 0;
depth = s3c_fimc_set_output_format(ctrl, fmt); //1.5.2.2.1 设置输出格式为rgb565
if (ctrl->out_type == PATH_OUT_DMA && frame->addr[0].virt_y == NULL) {
if (s3c_fimc_alloc_output_memory(frame)) //1.5.2.2.2
err(“cannot allocate memory\n”);
}
return depth;
}
1.5.2.2.1 设置输出格式为rgb565
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> V4L2_BUF_TYPE_VIDEO_CAPTURE
–> __video_do_ioctl >> ops->video_s_fmt_vid_cap
–> s3c_fimc_v4l2_s_fmt_vid_cap
–> s3c_fimc_set_output_frame
–> s3c_fimc_set_output_format
在drivers/media/video/samsung/fimc/s3c_fimc_cfg.c中
static int s3c_fimc_set_output_format(struct s3c_fimc_control *ctrl, struct v4l2_pix_format *fmt)
{
struct s3c_fimc_out_frame *frame = &ctrl->out_frame;
int depth = 0;
frame->width = fmt->width;
frame->height = fmt->height;

switch (fmt->pixelformat)
case V4L2_PIX_FMT_RGB565:
    frame->format = FORMAT_RGB565;
    frame->planes = 1;
    depth = 16;
    break;
return depth;

}
1.5.2.2.1 设置输出格式为rgb565
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> V4L2_BUF_TYPE_VIDEO_CAPTURE
–> __video_do_ioctl >> ops->video_s_fmt_vid_cap
–> s3c_fimc_v4l2_s_fmt_vid_cap
–> s3c_fimc_set_output_frame
–> s3c_fimc_alloc_output_memory
在drivers/media/video/samsung/fimc/s3c_fimc_cfg.c中
int s3c_fimc_alloc_output_memory(struct s3c_fimc_out_frame *info)
{
//1.5.2.2.1.1 计算buf_size=w*h*2,4k对齐
info->buf_size = s3c_fimc_get_buffer_size(info->width, info->height, info->format);
if (info->format == FORMAT_YCBCR420 || info->format == FORMAT_YCBCR422)
ret = s3c_fimc_alloc_yuv_memory(info);
else
ret = s3c_fimc_alloc_rgb_memory(info); //1.5.2.2.1.2 设置buf_size=w*h*2,4k对齐
return ret;
}

1.5.2.2.1.1 计算buf_size
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> V4L2_BUF_TYPE_VIDEO_CAPTURE
–> __video_do_ioctl >> ops->video_s_fmt_vid_cap
–> s3c_fimc_v4l2_s_fmt_vid_cap
–> s3c_fimc_set_output_frame
–> s3c_fimc_alloc_output_memory
–> s3c_fimc_get_buffer_size
设置buff_size是w*h*2,然后4k对齐=align(320*240*2)=155648
在drivers/media/video/samsung/fimc/s3c_fimc_cfg.c中
static u32 s3c_fimc_get_buffer_size(int width, int height, enum s3c_fimc_format_t fmt)
{
u32 size = width * height; //w*h
switch (fmt) {
case FORMAT_RGB565:
size *= 2; //w*h*2
buf_size = &size;
break;
}
if (*buf_size % PAGE_SIZE != 0) //4k字节对齐
buf_size = (*buf_size / PAGE_SIZE + 1) PAGE_SIZE;
return *buf_size;
}
1.5.2.2.1.2 申请dma内存
上层调用ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> V4L2_BUF_TYPE_VIDEO_CAPTURE
–> __video_do_ioctl >> ops->video_s_fmt_vid_cap
–> s3c_fimc_v4l2_s_fmt_vid_cap
–> s3c_fimc_set_output_frame
–> s3c_fimc_alloc_output_memory
–> s3c_fimc_alloc_rgb_memory
在drivers/media/video/samsung/fimc/s3c_fimc_cfg.c中
static int s3c_fimc_alloc_rgb_memory(struct s3c_fimc_out_frame *info)
{
struct s3c_fimc_frame_addr *frame;
int i, ret, nr_frames = info->nr_frames;
//nr_frames=4. 申请4块dma内存每块大小是152K=4k对齐(w*h*2)
for (i = 0; i < nr_frames; i++) {
frame = &info->addr[i];
frame->phys_rgb = s3c_fimc_get_dma_region(info->buf_size);
frame->virt_rgb = phys_to_virt(frame->phys_rgb);
}

for (i = nr_frames; i < S3C_FIMC_MAX_FRAMES; i++) {
    frame = &info->addr[i];
    frame->phys_rgb = info->addr[i - nr_frames].phys_rgb;
    frame->virt_rgb = info->addr[i - nr_frames].virt_rgb;
}
return 0;

}
1.5.3 ioclt的VIDIOC_STREAMON与驱动的交互
上层调用 ioctl(v4l2_fd, VIDIOC_STREAMON, &type);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> ops->vidioc_streamon(file, fh, i);
–> s3c_fimc_v4l2_streamon
在drivers/media/video/samsung/fimc/s3c_fimc_v4l2.c中
static int s3c_fimc_v4l2_streamon(struct file *filp, void *fh, enum v4l2_buf_type i)
{
struct s3c_fimc_control ctrl = (struct s3c_fimc_control ) fh;
if (ctrl->in_type != PATH_IN_DMA)
s3c_fimc_init_camera(ctrl); //设置cam->initialized = 1;
ctrl->out_frame.skip_frames = 0;
FSET_CAPTURE(ctrl);
FSET_IRQ_NORMAL(ctrl);
s3c_fimc_start_dma(ctrl);
return 0;
}
1.5.3.1 配置寄存器
上层调用 ioctl(v4l2_fd, VIDIOC_STREAMON, &type);
–> 即调用v4l2_ioctl
–> video_ioctl2 >>> ops->vidioc_streamon(file, fh, i);
–> s3c_fimc_v4l2_streamon
–> s3c_fimc_start_dma
在drivers/media/video/samsung/fimc/s3c_fimc_cfg.c中
void s3c_fimc_start_dma(struct s3c_fimc_control *ctrl)
{
//S3C_MSCOCTRL=0x0
//Codec path input data selection=External camera input path
s3c_fimc_set_input_path(ctrl);

if (ctrl->in_type == PATH_IN_DMA) {
    s3c_fimc_set_input_address(ctrl); //not exec
    s3c_fimc_set_input_dma(ctrl);
} else {
    //S3C_CISRCFMT=0x828001e0
    //ITU-R BT.601 YCbCr 8-bit mode enable
    //480*640分辨率
    s3c_fimc_set_source_format(ctrl);
   //S3C_CIWDOFST=0x80000000 S3C_CIWDOFST2=0x0-->enable windows offset
    s3c_fimc_set_window_offset(ctrl);
   //S3C_CIGCTRL=0x22100000  --> inverse the polarity of VSYNC
    s3c_fimc_set_polarity(ctrl);
}
// S3C_CICOSCPRERATIO=0x80020002  
     //8->Shift factor for codec pre-scaler
     //2--> Horizontal ratio of codec pre-scaler
     //2--> Vertical ratio of codec pre-scaler 
// S3C_CICOSCPREDST=0x14000f0  
    //Destination width for codec pre-scaler = 320
    //Destination height for codec pre-scaler = 240
s3c_fimc_set_scaler_info(ctrl);
//S3C_CICOTRGFMT=0x614000f0  //RGB输出,target image for codec DMA=240*320
//S3C_CICOTAREA=0x12c00=240*320 //Target area for codec DMA
s3c_fimc_set_target_format(ctrl);
//S3C_CICOSCCTRL=0x19000100  Codec main-scaler control 
//太多了
s3c_fimc_set_output_path(ctrl);

if (ctrl->out_type == PATH_OUT_DMA) {
    //对4个frame的Y Cb Cr  分别设置其start_address
    //这些address都是在s3c_fimc_alloc_rgb_memory中分配的
    //从0x5f5f9000开始,每个frame增加0x26000
    s3c_fimc_set_output_address(ctrl);
    //S3C_CICOCTRL=0x842080
    //Y Cr/Cr frames burst length is 8
   //not use last IRQ
   //memory order--> YCbCr        
    s3c_fimc_set_output_dma(ctrl);
}

if (!ctrl->scaler.bypass)
    //S3C_CICOSCCTRL=0x19008100-->只是设置了启动scale位,其它的不变
    s3c_fimc_start_scaler(ctrl);  

//S3C_CIIMGCPT=0xc0000000 
//capture interface global capture enable
// capture enable for codec scaler 
s3c_fimc_enable_capture(ctrl); 

}
二. camera getParameters分析
1. java层调用jni的getParameters
在./frameworks/base/core/java/android/hardware/Camera.java中
public Parameters getParameters() {
Parameters p = new Parameters();
String s = native_getParameters();
p.unflatten(s);
return p;
}
1.1 jni层的getParameters
java
–> jni >>>libandroid_runtime.so
在./frameworks/base/core/jni/android_hardware_Camera.cpp中
static jstring android_hardware_Camera_getParameters(JNIEnv *env, jobject thiz)
{
sp camera = get_native_camera(env, thiz, NULL);
return env->NewStringUTF(camera->getParameters().string());
}
1.2 jni调用libcamera_client层的getParameters
java
–> jni >>>libandroid_runtime.so
–> libcamera_client层的getParameters
在./frameworks/base/libs/camera/Camera.cpp中
String8 Camera::getParameters() const
{
String8 params;
sp c = mCamera;
params = mCamera->getParameters();
return params;
}
1.3 camera_client间接调用cameraService层的getParameters
java
–> jni >>>libandroid_runtime.so
–> libcamera_client层的getParameters
–> libcameraservice.so层的getParameters
在./frameworks/base/services/camera/libcameraservice/CameraService.cpp中
String8 CameraService::Client::getParameters() const {
Mutex::Autolock lock(mLock);
if (checkPidAndHardware() != NO_ERROR)
return String8();

String8 params(mHardware->getParameters().flatten());
return params;

}
1.4 libcamera.so层返回己设好的parameters
java
–> jni >>>libandroid_runtime.so
–> libcamera_client层的getParameters
–> libcameraservice.so层的getParameters
–> libcamera.so层的getParameters
在./hardware/forlinx/libcamera/S3C6410CameraHardware.cpp中
CameraParameters CameraHardware::getParameters() const
{
Mutex::Autolock lock(mLock);
return mParameters; //直接返回原先设好的mParameters
}
结果是:
picture-format=jpeg;picture-size=320x240;picture-size-values=320x240;
preview-format=rgb565;preview-frame-rate=15;preview-size=320x240;preview-size-values=320x240;
rotation=90

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值