I always wanted to write a Camera example from the HAL layer to the application layer, usb camera cannot be used on android4.0, so I decided to write a usb camera and coms on my own. The basic principle is the same. v4l2, but the source code data format is different. Now we will start from the HAL layer.
The following is my code. First, the code is explained step by step.
Fimcgzsd. c
/* * Android USB Camera zc3xx Library * * Copyright (c) 2014 Store information technology guangzhou ltd
* Copyright (c) 2014 hclydao
* * 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
#define LOG_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_t length;};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 (fd<0){LOGE("%s ++++ open error\n",dev);return -1;}(*env)->ReleaseByteArrayElements(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 < 0) { LOGE("%d :VIDIOC_QUERYCAP failed\n",__LINE__); return -1; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { LOGE("%d : no capture devices\n",__LINE__); return -1; }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) < 0){LOGE("++++%d : set format failed\n",__LINE__);return -1;} 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 < 0) { LOGE("++++%d : VIDIOC_REQBUFS failed\n",__LINE__); return -1; } buffers = calloc(req.count, sizeof(*buffers)); if (!buffers) { LOGE ("++++%d Out of memory\n",__LINE__);return -1; }for(i = 0; i< bufnum; ++i) {memset(&v4l2_buf, 0, sizeof(v4l2_buf));v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;v4l2_buf.memory = V4L2_MEMORY_MMAP;v4l2_buf.index = i;ret = ioctl(fd , VIDIOC_QUERYBUF, &v4l2_buf);if(ret < 0) { LOGE("+++%d : VIDIOC_QUERYBUF failed\n",__LINE__); return -1;}buffers[i].length = v4l2_buf.length;if ((buffers[i].start = (char *)mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, v4l2_buf.m.offset)) < 0) { LOGE("%d : mmap() failed",__LINE__); return -1;}}return 0;}/* *open usb camera device */JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_streamon(JNIEnv * env, jclass obj){int i;int ret;enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;for(i = 0; i< bufnum; ++i) {memset(&v4l2_buf, 0, sizeof(v4l2_buf));v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;v4l2_buf.memory = V4L2_MEMORY_MMAP;v4l2_buf.index = i;ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);if (ret < 0) { LOGE("%d : VIDIOC_QBUF failed\n",__LINE__); return ret;}} ret = ioctl(fd, VIDIOC_STREAMON, &type); if (ret < 0) { LOGE("%d : VIDIOC_STREAMON failed\n",__LINE__); return ret; }return 0;}/* *get one frame data */JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_dqbuf(JNIEnv * env, jclass obj,const jbyteArray videodata){ int ret;jbyte *data = (jbyte*)(*env)->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 < 0) { LOGE("%s : VIDIOC_DQBUF failed, dropped frame\n",__func__); return ret; }memcpy(data,buffers[v4l2_buf.index].start,buffers[v4l2_buf.index].length);(*env)->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 < 0) { LOGE("%s : VIDIOC_QBUF failed\n",__func__); return ret; } return 0;}/* *streamoff */JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_streamoff(JNIEnv * env, jclass obj,jint index){ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int ret; ret = ioctl(fd, VIDIOC_STREAMOFF, &type); if (ret < 0) { LOGE("%s : VIDIOC_STREAMOFF failed\n",__func__); return ret; } return 0;}/* *release */JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_release(JNIEnv * env, jclass obj){ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int ret;int i; ret = ioctl(fd, VIDIOC_STREAMOFF, &type); if (ret < 0) { LOGE("%s : VIDIOC_STREAMOFF failed\n",__func__); return ret; } for (i = 0; i < bufnum; i++) { ret = munmap(buffers[i].start, buffers[i].length);if (ret < 0) { LOGE("%s : munmap failed\n",__func__); return ret; }}free (buffers);close(fd);return 0;}
The first is open.
Second, initialize the init function.
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap); if (ret < 0) { LOGE("%d :VIDIOC_QUERYCAP failed\n",__LINE__); return -1; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { LOGE("%d : no capture devices\n",__LINE__); return -1; }
Obtain the device information and check whether the capture mode is supported.
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) < 0){LOGE("++++%d : set format failed\n",__LINE__);return -1;}
Set the format. usb camera has obtained the jpeg format. Therefore, set the format to 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 < 0) { LOGE("++++%d : VIDIOC_REQBUFS failed\n",__LINE__); return -1; }
Apply for a buffer. Here, apply for numbuf buffer frames.
buffers = calloc(req.count, sizeof(*buffers)); if (!buffers) { LOGE ("++++%d Out of memory\n",__LINE__);return -1; }for(i = 0; i< bufnum; ++i) {memset(&v4l2_buf, 0, sizeof(v4l2_buf));v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;v4l2_buf.memory = V4L2_MEMORY_MMAP;v4l2_buf.index = i;ret = ioctl(fd , VIDIOC_QUERYBUF, &v4l2_buf);if(ret < 0) { LOGE("+++%d : VIDIOC_QUERYBUF failed\n",__LINE__); return -1;}buffers[i].length = v4l2_buf.length;if ((buffers[i].start = (char *)mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, v4l2_buf.m.offset)) < 0) { LOGE("%d : mmap() failed",__LINE__); return -1;}}
Map virtual memory to physical address to obtain the physical address of each buffer zone
Streamon Functions
Put the buffer into the queue and enable the data stream
Dqbuf Function
Get a frame of data and return the serial number of the current buffer.
Qbuf Functions
Put the specified buffer into the queue. After obtaining the data in a buffer zone, you need to re-put the buffer into the queue.
I won't explain much about the next two.
Android. mk file:
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := engLOCAL_SRC_FILES:= fimcgzsd.cLOCAL_MODULE := libfimcgzsdLOCAL_LDLIBS := -llogLOCAL_SHARED_LIBRARIES := libc libcutilsinclude $(BUILD_SHARED_LIBRARY)
Reference blog: http://blog.csdn.net/eastmoon502136/article/details/8190262
========================================================== ====
Author: hclydao
Http://blog.csdn.net/hclydao
No copyright, but please keep this statement for reprinting
========================================================== ====