一直想自己写一个从HAL层到应用层的Camera例子,android4.0上usb camera用不了 所以决定自己写一个usb camera和coms原理都是一样的 基本v4l2 只不过源码数据格式不一样而已 下面我们就从HAL层开始
以下是我的代码,先上代码在 一步步说明
fimcgzsd.c
/*
* Android USB Camera zc3xx Library
*
* Copyright (c) 2014Store information technology guangzhou ltd<>
* Copyright (c) 2014hclydao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineLOG_TAG"FimcGzsd"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
struct fimc_buffer {
unsigned char *start;
size_tlength;
};
static int fd = -1;
struct fimc_buffer *buffers=NULL;
struct v4l2_buffer v4l2_buf;
static int bufnum = 1;
static int mwidth,mheight;
/*
*open usb camera device
*/
JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_open(JNIEnv * env, jclass obj, const jbyteArray devname)
{
jbyte *dev = (jbyte*)(*env)->GetByteArrayElements(env, devname, 0);
fd = open(dev, O_RDWR, 0);
if (fdReleaseByteArrayElements(env, devname, dev, 0);
return fd;
}
/*
* init device
*/
JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_init(JNIEnv * env, jclass obj, jint width, jint height,jint numbuf)
{
int ret;
int i;
bufnum = numbuf;
mwidth = width;
mheight = height;
struct v4l2_format fmt;
struct v4l2_capability cap;
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if (ret GetByteArrayElements(env, videodata, 0);
v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_DQBUF, &v4l2_buf);
if (ret ReleaseByteArrayElements(env, videodata, data, 0);
return v4l2_buf.index;
}
/*
*put in frame buffer to queue
*/
JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_qbuf(JNIEnv * env, jclass obj,jint index)
{
int ret;
v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_buf.memory = V4L2_MEMORY_MMAP;
v4l2_buf.index = index;
ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);
if (ret
首先是open这个就不作说明了
第二初始化init函数
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if (ret 获取设备相关信息,检查是否支持capture模式
memset( &fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) 设置格式,usb camera获取到的已经是jpeg格式 所以这里设置成RGB565格式
struct v4l2_requestbuffers req;
req.count = numbuf;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_REQBUFS, &req);
if (ret 申请缓冲区,这里申请numbuf个缓冲帧buffers = calloc(req.count, sizeof(*buffers));
if (!buffers) {
LOGE ("++++%d Out of memory\n",__LINE__);
return -1;
}
for(i = 0; i映射虚拟内存到物理地址,获取每个缓冲区的物理地址
streamon函数
将缓冲区放入队列并开启数据流
dqbuf函数
获取一帧数据 返回当前缓冲区的序列号
qbuf函数
将指定缓冲区放入队列,获取到某一缓冲区的数据后需要重新将这个缓冲区放入队列
后面两个我就不多说明了
Android.mk文件:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_SRC_FILES:= fimcgzsd.c
LOCAL_MODULE := libfimcgzsd
LOCAL_LDLIBS:= -llog
LOCAL_SHARED_LIBRARIES := libc libcutils
include $(BUILD_SHARED_LIBRARY)
参考博文:http://blog.csdn.net/eastmoon502136/article/details/8190262
============================================
作者:hclydao
http://blog.csdn.net/hclydao
版权没有,但是转载请保留此段声明
============================================